diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/modules | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/modules')
872 files changed, 24456 insertions, 12860 deletions
diff --git a/chromium/third_party/WebKit/Source/modules/BUILD.gn b/chromium/third_party/WebKit/Source/modules/BUILD.gn new file mode 100644 index 00000000000..b0870dfd05c --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/BUILD.gn @@ -0,0 +1,101 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/bindings.gni") +import("//third_party/WebKit/Source/bindings/modules/v8/generated.gni") +import("//third_party/WebKit/Source/build/make_file_arrays.gni") +import("//third_party/WebKit/Source/build/scripts/scripts.gni") +import("//third_party/WebKit/Source/modules/modules.gni") + +visibility = "//third_party/WebKit/Source/*" + +# GYP version: WebKit/Source/modules/modules.gyp:modules +source_set("modules") { + visibility = "//third_party/WebKit/*" + + sources = rebase_path(modules_files, ".", "//") + sources += rebase_path(bindings_modules_generated_aggregate_files, ".", "//") + + if (!is_win) { + sources -= [ + "webdatabase/sqlite/SQLiteFileSystemWin.cpp", + ] + } + if (!is_posix) { + sources -= [ + "webdatabase/sqlite/SQLiteFileSystemPosix.cpp", + ] + } + + configs += [ + "//third_party/WebKit/Source:config", + "//third_party/WebKit/Source:inside_blink", + ] + + deps = [ + ":make_modules_generated", + ":modules_fetch_polyfill", + ":modules_cache_polyfill", + ":modules_cache_storage_polyfill", + "//third_party/WebKit/Source/core", + "//third_party/sqlite", + "//third_party/zlib", + ] + + if (is_win) { + cflags = [ + "/wd4267", # Size to int truncations. + "/wd4334", # Result of 32-bit shift implicitly converted to 64 bits. + ] + } +} + +# GYP version: WebKit/Source/modules/modules.gyp:modules (FetchPolyfill action) +make_file_arrays("modules_fetch_polyfill") { + filename = "FetchPolyfill" + resources = [ + "serviceworkers/polyfills/fetchPolyfill.js", + ] + namespace = "WebCore" +} + +# GYP version: WebKit/Source/modules/modules.gyp:modules (CachePolyfill action) +make_file_arrays("modules_cache_polyfill") { + filename = "CachePolyfill" + resources = [ + "serviceworkers/polyfills/cachePolyfill.js", + ] + namespace = "WebCore" +} + +# GYP version: WebKit/Source/modules/modules.gyp:modules (CacheStoragePolyfill action) +make_file_arrays("modules_cache_storage_polyfill") { + filename = "CacheStoragePolyfill" + resources = [ + "serviceworkers/polyfills/cacheStoragePolyfill.js", + ] + namespace = "WebCore" +} + +# GYP version: WebKit/Source/modules/modules.gyp:modules_testing +source_set("modules_testing") { + sources = modules_testing_files + + configs += [ + "//third_party/WebKit/Source:config", + "//third_party/WebKit/Source:inside_blink", + ] + + deps = [ + "//third_party/WebKit/Source/core", + ] +} + +# GYP version: WebKit/Source/modules/modules.gyp:make_modules_generated +group("make_modules_generated") { + deps = [ + "//third_party/WebKit/Source/core:core_event_interfaces", + "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated", + ] +} diff --git a/chromium/third_party/WebKit/Source/modules/EventModules.h b/chromium/third_party/WebKit/Source/modules/EventModules.h new file mode 100644 index 00000000000..673cc17f162 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/EventModules.h @@ -0,0 +1,11 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EventModules_h +#define EventModules_h + +#include "EventModulesNames.h" +#include "core/events/Event.h" + +#endif // EventModules_h diff --git a/chromium/third_party/WebKit/Source/modules/EventModulesFactory.h b/chromium/third_party/WebKit/Source/modules/EventModulesFactory.h new file mode 100644 index 00000000000..b1b7d34850e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/EventModulesFactory.h @@ -0,0 +1,29 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EventModulesFactory_h +#define EventModulesFactory_h + +#include "core/events/EventFactory.h" +#include "platform/heap/Handle.h" +#include "wtf/PassRefPtr.h" +#include "wtf/text/AtomicString.h" + +namespace WebCore { + +class Event; + +class EventModulesFactory FINAL : public EventFactoryBase { +public: + static PassOwnPtr<EventModulesFactory> create() + { + return adoptPtr(new EventModulesFactory()); + } + + virtual PassRefPtrWillBeRawPtr<Event> create(const String& eventType) OVERRIDE; +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/modules/EventTargetModules.h b/chromium/third_party/WebKit/Source/modules/EventTargetModules.h new file mode 100644 index 00000000000..bc8103ca52e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/EventTargetModules.h @@ -0,0 +1,31 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EventTargetModules_h +#define EventTargetModules_h + +#include "EventModulesNames.h" +#include "EventTargetModulesInterfaces.h" +#include "EventTargetModulesNames.h" +#include "core/events/EventTarget.h" + +namespace WebCore { + +class AudioContext; +class FileWriter; +class IDBDatabase; +class IDBRequest; +class IDBTransaction; +class MIDIAccess; +class MIDIInput; +class MIDIPort; +class MediaStream; +class Notification; +class ExecutionContext; +class ScriptProcessorNode; +class WebSocket; + +} // namespace WebCore + +#endif // EventTargetModules_h diff --git a/chromium/third_party/WebKit/Source/modules/EventTargetModulesFactory.in b/chromium/third_party/WebKit/Source/modules/EventTargetModulesFactory.in new file mode 100644 index 00000000000..a0de14331ab --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/EventTargetModulesFactory.in @@ -0,0 +1,31 @@ +namespace="EventTarget" +suffix="Modules" + +modules/battery/BatteryManager +modules/encryptedmedia/MediaKeySession +modules/filesystem/FileWriter +modules/indexeddb/IDBDatabase +modules/indexeddb/IDBOpenDBRequest +modules/indexeddb/IDBRequest +modules/indexeddb/IDBTransaction +modules/mediasource/MediaSource +modules/mediasource/SourceBuffer +modules/mediasource/SourceBufferList +modules/mediastream/MediaStream +modules/mediastream/MediaStreamTrack +modules/mediastream/RTCDTMFSender +modules/mediastream/RTCDataChannel +modules/mediastream/RTCPeerConnection +modules/netinfo/NetworkInformation +modules/notifications/Notification +modules/serviceworkers/ServiceWorker +modules/serviceworkers/ServiceWorkerGlobalScope +modules/speech/SpeechRecognition +modules/speech/SpeechSynthesis +modules/speech/SpeechSynthesisUtterance +modules/webaudio/AudioContext Conditional=WEB_AUDIO +modules/webaudio/AudioNode Conditional=WEB_AUDIO +modules/webmidi/MIDIAccess +modules/webmidi/MIDIInput +modules/webmidi/MIDIPort +modules/websockets/WebSocket diff --git a/chromium/third_party/WebKit/Source/modules/InitModules.cpp b/chromium/third_party/WebKit/Source/modules/InitModules.cpp new file mode 100644 index 00000000000..d271534a38e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/InitModules.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "InitModules.h" + +#include "EventModulesFactory.h" +#include "EventModulesNames.h" +#include "EventTargetModulesNames.h" +#include "EventTypeNames.h" +#include "core/dom/Document.h" + +namespace WebCore { + +void ModulesInitializer::initEventNames() +{ + EventNames::init(); + EventNames::initModules(); +} + +void ModulesInitializer::initEventTargetNames() +{ + EventTargetNames::init(); + EventTargetNames::initModules(); +} + +void ModulesInitializer::registerEventFactory() +{ + CoreInitializer::registerEventFactory(); + Document::registerEventFactory(EventModulesFactory::create()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/InitModules.h b/chromium/third_party/WebKit/Source/modules/InitModules.h new file mode 100644 index 00000000000..eccc4a6874f --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/InitModules.h @@ -0,0 +1,27 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef InitModules_h +#define InitModules_h + +#include "core/Init.h" +#include "platform/heap/Handle.h" + +namespace WebCore { + +class Event; +class ExceptionState; + +class ModulesInitializer : public CoreInitializer { +public: + virtual void registerEventFactory() OVERRIDE; + virtual void initEventNames() OVERRIDE; + virtual void initEventTargetNames() OVERRIDE; +}; + +PassRefPtrWillBeRawPtr<Event> createEventModules(const String& eventType, ExceptionState&); + +} // namespace WebCore + +#endif // InitModules_h diff --git a/chromium/third_party/WebKit/Source/modules/OWNERS b/chromium/third_party/WebKit/Source/modules/OWNERS index 1382c2fc755..4c730ae82df 100644 --- a/chromium/third_party/WebKit/Source/modules/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/OWNERS @@ -2,13 +2,12 @@ abarth@chromium.org darin@chromium.org dglazkov@chromium.org eseidel@chromium.org +haraken@chromium.org jochen@chromium.org ojan@chromium.org tkent@chromium.org -# FIXME: Remove this when issue 235756 is fixed. -# Currently a top-level OWNERS file for *.idl doesn't cover IDL files -# in subdirectories like modules/. -haraken@chromium.org +# Reviewer for inspector-related code: +pfeldman@chromium.org per-file modules.gypi=* diff --git a/chromium/third_party/WebKit/Source/modules/battery/BatteryDispatcher.cpp b/chromium/third_party/WebKit/Source/modules/battery/BatteryDispatcher.cpp new file mode 100644 index 00000000000..707f27e1e73 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/BatteryDispatcher.cpp @@ -0,0 +1,50 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/battery/BatteryDispatcher.h" + +#include "modules/battery/BatteryStatus.h" +#include "platform/NotImplemented.h" +#include "public/platform/Platform.h" + +namespace WebCore { + +BatteryDispatcher& BatteryDispatcher::instance() +{ + DEFINE_STATIC_LOCAL(BatteryDispatcher, batteryDispatcher, ()); + return batteryDispatcher; +} + +BatteryDispatcher::BatteryDispatcher() +{ +} + +BatteryDispatcher::~BatteryDispatcher() +{ +} + +void BatteryDispatcher::updateBatteryStatus(const blink::WebBatteryStatus& batteryStatus) +{ + m_batteryStatus = BatteryStatus::create(batteryStatus.charging, batteryStatus.chargingTime, batteryStatus.dischargingTime, batteryStatus.level); + notifyControllers(); +} + +BatteryStatus* BatteryDispatcher::latestData() +{ + return m_batteryStatus.get(); +} + +void BatteryDispatcher::startListening() +{ + blink::Platform::current()->setBatteryStatusListener(this); +} + +void BatteryDispatcher::stopListening() +{ + blink::Platform::current()->setBatteryStatusListener(0); + m_batteryStatus.clear(); +} + +} diff --git a/chromium/third_party/WebKit/Source/modules/battery/BatteryDispatcher.h b/chromium/third_party/WebKit/Source/modules/battery/BatteryDispatcher.h new file mode 100644 index 00000000000..b27a7f51720 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/BatteryDispatcher.h @@ -0,0 +1,41 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BatteryDispatcher_h +#define BatteryDispatcher_h + +#include "core/frame/DeviceEventDispatcherBase.h" +#include "modules/battery/BatteryManager.h" +#include "modules/battery/BatteryStatus.h" +#include "public/platform/WebBatteryStatusListener.h" + +namespace blink { +class WebBatteryStatus; +} + +namespace WebCore { + +class BatteryDispatcher FINAL : public DeviceEventDispatcherBase, public blink::WebBatteryStatusListener { +public: + static BatteryDispatcher& instance(); + virtual ~BatteryDispatcher(); + + BatteryStatus* latestData(); + + // Inherited from blink::WebBatteryStatusListener. + virtual void updateBatteryStatus(const blink::WebBatteryStatus&) OVERRIDE; + +private: + BatteryDispatcher(); + + // Inherited from DeviceEventDispatcherBase. + virtual void startListening() OVERRIDE; + virtual void stopListening() OVERRIDE; + + RefPtrWillBePersistent<BatteryStatus> m_batteryStatus; +}; + +} + +#endif // BatteryDispatcher_h diff --git a/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.cpp b/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.cpp new file mode 100644 index 00000000000..7be6038a26e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.cpp @@ -0,0 +1,149 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/battery/BatteryManager.h" + +#include "modules/battery/BatteryDispatcher.h" +#include "modules/battery/BatteryStatus.h" +#include "platform/RuntimeEnabledFeatures.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<BatteryManager> BatteryManager::create(ExecutionContext* context) +{ + RefPtrWillBeRawPtr<BatteryManager> batteryManager(adoptRefWillBeRefCountedGarbageCollected(new BatteryManager(context))); + batteryManager->suspendIfNeeded(); + return batteryManager.release(); +} + +BatteryManager::~BatteryManager() +{ + stopUpdating(); +} + +BatteryManager::BatteryManager(ExecutionContext* context) + : ActiveDOMObject(context) + , DeviceEventControllerBase(toDocument(context)->page()) + , m_batteryStatus(BatteryStatus::create()) + , m_state(NotStarted) +{ +} + +ScriptPromise BatteryManager::startRequest(ScriptState* scriptState) +{ + if (m_state == Pending) + return m_resolver->promise(); + + m_resolver = ScriptPromiseResolverWithContext::create(scriptState); + ScriptPromise promise = m_resolver->promise(); + + if (m_state == Resolved) { + // FIXME: Consider returning the same promise in this case. See crbug.com/385025. + m_resolver->resolve(this); + } else if (m_state == NotStarted) { + m_state = Pending; + m_hasEventListener = true; + startUpdating(); + } + + return promise; +} + +bool BatteryManager::charging() +{ + return m_batteryStatus->charging(); +} + +double BatteryManager::chargingTime() +{ + return m_batteryStatus->chargingTime(); +} + +double BatteryManager::dischargingTime() +{ + return m_batteryStatus->dischargingTime(); +} + +double BatteryManager::level() +{ + return m_batteryStatus->level(); +} + +void BatteryManager::didUpdateData() +{ + ASSERT(RuntimeEnabledFeatures::batteryStatusEnabled()); + ASSERT(m_state != NotStarted); + + RefPtrWillBeRawPtr<BatteryStatus> oldStatus = m_batteryStatus; + m_batteryStatus = BatteryDispatcher::instance().latestData(); + +#if !ENABLE(OILPAN) + // BatteryDispatcher also holds a reference to m_batteryStatus. + ASSERT(m_batteryStatus->refCount() > 1); +#endif + + if (m_state == Pending) { + ASSERT(m_resolver); + m_state = Resolved; + m_resolver->resolve(this); + return; + } + + Document* document = toDocument(executionContext()); + if (document->activeDOMObjectsAreSuspended() || document->activeDOMObjectsAreStopped()) + return; + + ASSERT(oldStatus); + + if (m_batteryStatus->charging() != oldStatus->charging()) + dispatchEvent(Event::create(EventTypeNames::chargingchange)); + if (m_batteryStatus->chargingTime() != oldStatus->chargingTime()) + dispatchEvent(Event::create(EventTypeNames::chargingtimechange)); + if (m_batteryStatus->dischargingTime() != oldStatus->dischargingTime()) + dispatchEvent(Event::create(EventTypeNames::dischargingtimechange)); + if (m_batteryStatus->level() != oldStatus->level()) + dispatchEvent(Event::create(EventTypeNames::levelchange)); +} + +void BatteryManager::registerWithDispatcher() +{ + BatteryDispatcher::instance().addController(this); +} + +void BatteryManager::unregisterWithDispatcher() +{ + BatteryDispatcher::instance().removeController(this); +} + +bool BatteryManager::hasLastData() +{ + return BatteryDispatcher::instance().latestData(); +} + +void BatteryManager::suspend() +{ + m_hasEventListener = false; + stopUpdating(); +} + +void BatteryManager::resume() +{ + m_hasEventListener = true; + startUpdating(); +} + +void BatteryManager::stop() +{ + m_hasEventListener = false; + stopUpdating(); +} + +void BatteryManager::trace(Visitor* visitor) +{ + visitor->trace(m_batteryStatus); + EventTargetWithInlineData::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.h b/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.h new file mode 100644 index 00000000000..360095e9824 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.h @@ -0,0 +1,74 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BatteryManager_h +#define BatteryManager_h + +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "core/dom/ContextLifecycleObserver.h" +#include "core/dom/Document.h" +#include "core/frame/DeviceEventControllerBase.h" +#include "modules/EventTargetModules.h" +#include "platform/heap/Handle.h" + +namespace WebCore { + +class BatteryStatus; + +class BatteryManager FINAL : public RefCountedWillBeRefCountedGarbageCollected<BatteryManager>, public ActiveDOMObject, public DeviceEventControllerBase, public EventTargetWithInlineData { + REFCOUNTED_EVENT_TARGET(BatteryManager); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(BatteryManager); +public: + virtual ~BatteryManager(); + static PassRefPtrWillBeRawPtr<BatteryManager> create(ExecutionContext*); + + // Returns a promise object that will be resolved with this BatteryManager. + ScriptPromise startRequest(ScriptState*); + + // EventTarget implementation. + virtual const WTF::AtomicString& interfaceName() const OVERRIDE { return EventTargetNames::BatteryManager; } + virtual ExecutionContext* executionContext() const OVERRIDE { return ContextLifecycleObserver::executionContext(); } + + bool charging(); + double chargingTime(); + double dischargingTime(); + double level(); + + DEFINE_ATTRIBUTE_EVENT_LISTENER(chargingchange); + DEFINE_ATTRIBUTE_EVENT_LISTENER(chargingtimechange); + DEFINE_ATTRIBUTE_EVENT_LISTENER(dischargingtimechange); + DEFINE_ATTRIBUTE_EVENT_LISTENER(levelchange); + + // Inherited from DeviceEventControllerBase. + virtual void didUpdateData() OVERRIDE; + virtual void registerWithDispatcher() OVERRIDE; + virtual void unregisterWithDispatcher() OVERRIDE; + virtual bool hasLastData() OVERRIDE; + + // ActiveDOMObject implementation. + virtual bool canSuspend() const { return true; } + virtual void suspend() OVERRIDE; + virtual void resume() OVERRIDE; + virtual void stop() OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; + +private: + enum State { + NotStarted, + Pending, + Resolved, + }; + + explicit BatteryManager(ExecutionContext*); + + RefPtr<ScriptPromiseResolverWithContext> m_resolver; + RefPtrWillBeMember<BatteryStatus> m_batteryStatus; + State m_state; +}; + +} + +#endif // BatteryManager_h diff --git a/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.idl b/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.idl new file mode 100644 index 00000000000..01a6ce1d7ef --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/BatteryManager.idl @@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://dvcs.w3.org/hg/dap/raw-file/tip/battery/Overview.html#batterymanager-interface +[ + RuntimeEnabled=BatteryStatus, + TypeChecking=Unrestricted, +] interface BatteryManager : EventTarget { + readonly attribute boolean charging; + readonly attribute unrestricted double chargingTime; + readonly attribute unrestricted double dischargingTime; + readonly attribute double level; + + attribute EventHandler onchargingchange; + attribute EventHandler onchargingtimechange; + attribute EventHandler ondischargingtimechange; + attribute EventHandler onlevelchange; +}; diff --git a/chromium/third_party/WebKit/Source/modules/battery/BatteryStatus.cpp b/chromium/third_party/WebKit/Source/modules/battery/BatteryStatus.cpp new file mode 100644 index 00000000000..bed3805fd92 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/BatteryStatus.cpp @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/battery/BatteryStatus.h" + +#include <limits> + +namespace WebCore { + +PassRefPtrWillBeRawPtr<BatteryStatus> BatteryStatus::create() +{ + return adoptRefWillBeNoop(new BatteryStatus); +} + +PassRefPtrWillBeRawPtr<BatteryStatus> BatteryStatus::create(bool charging, double chargingTime, double dischargingTime, double level) +{ + return adoptRefWillBeNoop(new BatteryStatus(charging, chargingTime, dischargingTime, level)); +} + +BatteryStatus::BatteryStatus() + : m_charging(true) + , m_chargingTime(0) + , m_dischargingTime(std::numeric_limits<double>::infinity()) + , m_level(1) +{ +} + +BatteryStatus::BatteryStatus(bool charging, double chargingTime, double dischargingTime, double level) + : m_charging(charging) + , m_chargingTime(chargingTime) + , m_dischargingTime(dischargingTime) + , m_level(level) +{ +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/battery/BatteryStatus.h b/chromium/third_party/WebKit/Source/modules/battery/BatteryStatus.h new file mode 100644 index 00000000000..fdccb98f3a4 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/BatteryStatus.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BatteryStatus_h +#define BatteryStatus_h + +#include "platform/heap/Handle.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" + +namespace WebCore { + +class BatteryStatus FINAL : public RefCountedWillBeGarbageCollected<BatteryStatus> { +public: + static PassRefPtrWillBeRawPtr<BatteryStatus> create(); + static PassRefPtrWillBeRawPtr<BatteryStatus> create(bool charging, double chargingTime, double dischargingTime, double level); + + bool charging() const { return m_charging; } + double chargingTime() const { return m_chargingTime; } + double dischargingTime() const { return m_dischargingTime; } + double level() const { return m_level; } + + void trace(Visitor*) { } + +private: + BatteryStatus(); + BatteryStatus(bool charging, double chargingTime, double dischargingTime, double level); + + bool m_charging; + double m_chargingTime; + double m_dischargingTime; + double m_level; +}; + +} // namespace WebCore + +#endif // BatteryStatus_h diff --git a/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.cpp b/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.cpp new file mode 100644 index 00000000000..b72e98f728f --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.cpp @@ -0,0 +1,55 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/battery/NavigatorBattery.h" + +#include "core/frame/LocalFrame.h" +#include "modules/battery/BatteryManager.h" + +namespace WebCore { + +NavigatorBattery::NavigatorBattery() +{ +} + +NavigatorBattery::~NavigatorBattery() +{ +} + +ScriptPromise NavigatorBattery::getBattery(ScriptState* scriptState, Navigator& navigator) +{ + return NavigatorBattery::from(navigator).getBattery(scriptState); +} + +ScriptPromise NavigatorBattery::getBattery(ScriptState* scriptState) +{ + if (!m_batteryManager) + m_batteryManager = BatteryManager::create(scriptState->executionContext()); + + return m_batteryManager->startRequest(scriptState); +} + +const char* NavigatorBattery::supplementName() +{ + return "NavigatorBattery"; +} + +NavigatorBattery& NavigatorBattery::from(Navigator& navigator) +{ + NavigatorBattery* supplement = static_cast<NavigatorBattery*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); + if (!supplement) { + supplement = new NavigatorBattery(); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; +} + +void NavigatorBattery::trace(Visitor* visitor) +{ + visitor->trace(m_batteryManager); + WillBeHeapSupplement<Navigator>::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.h b/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.h new file mode 100644 index 00000000000..d5319e08cda --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.h @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NavigatorBattery_h +#define NavigatorBattery_h + +#include "bindings/v8/ScriptPromise.h" +#include "core/frame/Navigator.h" +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" + +namespace WebCore { + +class BatteryManager; +class Navigator; + +class NavigatorBattery FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorBattery>, public WillBeHeapSupplement<Navigator> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorBattery); +public: + virtual ~NavigatorBattery(); + + static NavigatorBattery& from(Navigator&); + + static ScriptPromise getBattery(ScriptState*, Navigator&); + ScriptPromise getBattery(ScriptState*); + + void trace(Visitor*); + +private: + NavigatorBattery(); + static const char* supplementName(); + + RefPtrWillBeMember<BatteryManager> m_batteryManager; +}; + +} // namespace WebCore + +#endif // NavigatorBattery_h diff --git a/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.idl b/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.idl new file mode 100644 index 00000000000..c5bff09da14 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/NavigatorBattery.idl @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=BatteryStatus, +] partial interface Navigator { + [CallWith=ScriptState] Promise getBattery(); +}; + diff --git a/chromium/third_party/WebKit/Source/modules/battery/OWNERS b/chromium/third_party/WebKit/Source/modules/battery/OWNERS new file mode 100644 index 00000000000..1fd89e0e2eb --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/battery/OWNERS @@ -0,0 +1 @@ +timvolodine@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp b/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp new file mode 100644 index 00000000000..f19380c6b16 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp @@ -0,0 +1,161 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/beacon/NavigatorBeacon.h" + +#include "bindings/v8/ExceptionState.h" +#include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" +#include "core/fileapi/Blob.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "core/html/DOMFormData.h" +#include "core/loader/BeaconLoader.h" +#include "wtf/ArrayBufferView.h" + +namespace WebCore { + +NavigatorBeacon::NavigatorBeacon(Navigator& navigator) + : m_transmittedBytes(0) + , m_navigator(navigator) +{ +} + +const char* NavigatorBeacon::supplementName() +{ + return "NavigatorBeacon"; +} + +NavigatorBeacon& NavigatorBeacon::from(Navigator& navigator) +{ + NavigatorBeacon* supplement = static_cast<NavigatorBeacon*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); + if (!supplement) { + supplement = new NavigatorBeacon(navigator); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; +} + +bool NavigatorBeacon::canSendBeacon(ExecutionContext* context, const KURL& url, ExceptionState& exceptionState) +{ + if (!url.isValid()) { + exceptionState.throwDOMException(SyntaxError, "The URL argument is ill-formed or unsupported."); + return false; + } + // For now, only support HTTP and related. + if (!url.protocolIsInHTTPFamily()) { + exceptionState.throwDOMException(SyntaxError, "Beacons are only supported over HTTP(S)."); + return false; + } + // FIXME: CSP is not enforced on redirects, crbug.com/372197 + if (!ContentSecurityPolicy::shouldBypassMainWorld(context) && !context->contentSecurityPolicy()->allowConnectToSource(url)) { + // We can safely expose the URL to JavaScript, as these checks happen synchronously before redirection. JavaScript receives no new information. + exceptionState.throwSecurityError("Refused to send beacon to '" + url.elidedString() + "' because it violates the document's Content Security Policy."); + return false; + } + + // Do not allow sending Beacons over a Navigator that is detached. + if (!m_navigator.frame()) + return false; + + return true; +} + +int NavigatorBeacon::maxAllowance() const +{ + const Settings* settings = m_navigator.frame()->settings(); + if (settings) { + int maxAllowed = settings->maxBeaconTransmission(); + if (maxAllowed < m_transmittedBytes) + return 0; + return maxAllowed - m_transmittedBytes; + } + return m_transmittedBytes; +} + +void NavigatorBeacon::updateTransmittedBytes(int length) +{ + ASSERT(length >= 0); + m_transmittedBytes += length; +} + +bool NavigatorBeacon::sendBeacon(ExecutionContext* context, Navigator& navigator, const String& urlstring, const String& data, ExceptionState& exceptionState) +{ + return NavigatorBeacon::from(navigator).sendBeacon(context, urlstring, data, exceptionState); +} + +bool NavigatorBeacon::sendBeacon(ExecutionContext* context, const String& urlstring, const String& data, ExceptionState& exceptionState) +{ + KURL url = context->completeURL(urlstring); + if (!canSendBeacon(context, url, exceptionState)) + return false; + + int bytes = 0; + bool result = BeaconLoader::sendBeacon(m_navigator.frame(), maxAllowance(), url, data, bytes); + if (result) + updateTransmittedBytes(bytes); + + return result; +} + +bool NavigatorBeacon::sendBeacon(ExecutionContext* context, Navigator& navigator, const String& urlstring, PassRefPtr<ArrayBufferView> data, ExceptionState& exceptionState) +{ + return NavigatorBeacon::from(navigator).sendBeacon(context, urlstring, data, exceptionState); +} + +bool NavigatorBeacon::sendBeacon(ExecutionContext* context, const String& urlstring, PassRefPtr<ArrayBufferView> data, ExceptionState& exceptionState) +{ + KURL url = context->completeURL(urlstring); + if (!canSendBeacon(context, url, exceptionState)) + return false; + + int bytes = 0; + bool result = BeaconLoader::sendBeacon(m_navigator.frame(), maxAllowance(), url, data, bytes); + if (result) + updateTransmittedBytes(bytes); + + return result; +} + +bool NavigatorBeacon::sendBeacon(ExecutionContext* context, Navigator& navigator, const String& urlstring, PassRefPtrWillBeRawPtr<Blob> data, ExceptionState& exceptionState) +{ + return NavigatorBeacon::from(navigator).sendBeacon(context, urlstring, data, exceptionState); +} + +bool NavigatorBeacon::sendBeacon(ExecutionContext* context, const String& urlstring, PassRefPtrWillBeRawPtr<Blob> data, ExceptionState& exceptionState) +{ + KURL url = context->completeURL(urlstring); + if (!canSendBeacon(context, url, exceptionState)) + return false; + + int bytes = 0; + bool result = BeaconLoader::sendBeacon(m_navigator.frame(), maxAllowance(), url, data, bytes); + if (result) + updateTransmittedBytes(bytes); + + return result; +} + +bool NavigatorBeacon::sendBeacon(ExecutionContext* context, Navigator& navigator, const String& urlstring, PassRefPtrWillBeRawPtr<DOMFormData> data, ExceptionState& exceptionState) +{ + return NavigatorBeacon::from(navigator).sendBeacon(context, urlstring, data, exceptionState); +} + +bool NavigatorBeacon::sendBeacon(ExecutionContext* context, const String& urlstring, PassRefPtrWillBeRawPtr<DOMFormData> data, ExceptionState& exceptionState) +{ + KURL url = context->completeURL(urlstring); + if (!canSendBeacon(context, url, exceptionState)) + return false; + + int bytes = 0; + bool result = BeaconLoader::sendBeacon(m_navigator.frame(), maxAllowance(), url, data, bytes); + if (result) + updateTransmittedBytes(bytes); + + return result; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.h b/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.h new file mode 100644 index 00000000000..c0c3f6d0e32 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.h @@ -0,0 +1,54 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NavigatorBeacon_h +#define NavigatorBeacon_h + +#include "core/frame/Navigator.h" +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" + +namespace WTF { +class ArrayBufferView; +} + +namespace WebCore { + +class Blob; +class DOMFormData; +class ExceptionState; +class ExecutionContext; +class KURL; + +class NavigatorBeacon FINAL : public NoBaseWillBeGarbageCollected<NavigatorBeacon>, public WillBeHeapSupplement<Navigator> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorBeacon); +public: + static NavigatorBeacon& from(Navigator&); + + static bool sendBeacon(ExecutionContext*, Navigator&, const String&, const String&, ExceptionState&); + static bool sendBeacon(ExecutionContext*, Navigator&, const String&, PassRefPtr<WTF::ArrayBufferView>, ExceptionState&); + static bool sendBeacon(ExecutionContext*, Navigator&, const String&, PassRefPtrWillBeRawPtr<Blob>, ExceptionState&); + static bool sendBeacon(ExecutionContext*, Navigator&, const String&, PassRefPtrWillBeRawPtr<DOMFormData>, ExceptionState&); + +private: + explicit NavigatorBeacon(Navigator&); + + static const char* supplementName(); + + bool sendBeacon(ExecutionContext*, const String&, const String&, ExceptionState&); + bool sendBeacon(ExecutionContext*, const String&, PassRefPtr<WTF::ArrayBufferView>, ExceptionState&); + bool sendBeacon(ExecutionContext*, const String&, PassRefPtrWillBeRawPtr<Blob>, ExceptionState&); + bool sendBeacon(ExecutionContext*, const String&, PassRefPtrWillBeRawPtr<DOMFormData>, ExceptionState&); + + bool canSendBeacon(ExecutionContext*, const KURL&, ExceptionState&); + int maxAllowance() const; + void updateTransmittedBytes(int); + + int m_transmittedBytes; + Navigator& m_navigator; +}; + +} // namespace WebCore + +#endif // NavigatorBeacon_h diff --git a/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.idl b/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.idl new file mode 100644 index 00000000000..465c2110593 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.idl @@ -0,0 +1,15 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/Beacon/Overview.html#Navigator + +[ + RuntimeEnabled=Beacon, +] partial interface Navigator { + // FIXME: should be union type http://crbug.com/240176 + [CallWith=ExecutionContext, RaisesException] boolean sendBeacon(DOMString url, ArrayBufferView data); + [CallWith=ExecutionContext, RaisesException] boolean sendBeacon(DOMString url, Blob data); + [CallWith=ExecutionContext, RaisesException] boolean sendBeacon(DOMString url, FormData data); + [CallWith=ExecutionContext, RaisesException] boolean sendBeacon(DOMString url, [Default=Undefined] optional DOMString data); +}; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesCbcParams.cpp b/chromium/third_party/WebKit/Source/modules/crypto/AesCbcParams.cpp deleted file mode 100644 index b16e3317e89..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesCbcParams.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/crypto/AesCbcParams.h" - -#include "public/platform/WebCryptoAlgorithmParams.h" - -namespace WebCore { - -Uint8Array* AesCbcParams::iv() -{ - if (!m_iv) { - const blink::WebVector<unsigned char>& iv = m_algorithm.aesCbcParams()->iv(); - m_iv = Uint8Array::create(iv.data(), iv.size()); - } - return m_iv.get(); -} - -AesCbcParams::AesCbcParams(const blink::WebCryptoAlgorithm& algorithm) - : Algorithm(algorithm) -{ - ASSERT(algorithm.aesCbcParams()); - ScriptWrappable::init(this); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyParams.cpp b/chromium/third_party/WebKit/Source/modules/crypto/AesKeyAlgorithm.cpp index 1db7e15e526..015ac986b7f 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyParams.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/AesKeyAlgorithm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,29 +29,32 @@ */ #include "config.h" -#include "modules/crypto/HmacKeyParams.h" +#include "modules/crypto/AesKeyAlgorithm.h" -#include "public/platform/WebCryptoAlgorithmParams.h" +#include "modules/crypto/NormalizeAlgorithm.h" +#include "wtf/text/WTFString.h" namespace WebCore { -Algorithm* HmacKeyParams::hash() +AesKeyAlgorithm* AesKeyAlgorithm::create(const blink::WebCryptoKeyAlgorithm& algorithm) { - if (!m_hash) - m_hash = Algorithm::create(m_algorithm.hmacKeyParams()->hash()); - return m_hash.get(); + return new AesKeyAlgorithm(algorithm); } -unsigned HmacKeyParams::length(bool& isNull) +unsigned short AesKeyAlgorithm::length() { - isNull = !m_algorithm.hmacKeyParams()->hasLengthBytes(); - return m_algorithm.hmacKeyParams()->optionalLengthBytes(); + return m_algorithm.aesParams()->lengthBits(); } -HmacKeyParams::HmacKeyParams(const blink::WebCryptoAlgorithm& algorithm) - : Algorithm(algorithm) +void AesKeyAlgorithm::trace(Visitor* visitor) { - ASSERT(algorithm.hmacKeyParams()); + KeyAlgorithm::trace(visitor); +} + +AesKeyAlgorithm::AesKeyAlgorithm(const blink::WebCryptoKeyAlgorithm& algorithm) + : KeyAlgorithm(algorithm) +{ + ASSERT(m_algorithm.aesParams()); ScriptWrappable::init(this); } diff --git a/chromium/third_party/WebKit/Source/modules/crypto/WorkerCrypto.h b/chromium/third_party/WebKit/Source/modules/crypto/AesKeyAlgorithm.h index 2b72aba570a..be51a8d22e3 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/WorkerCrypto.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/AesKeyAlgorithm.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,24 +28,31 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WorkerCrypto_h -#define WorkerCrypto_h +#ifndef AesKeyAlgorithm_h +#define AesKeyAlgorithm_h #include "bindings/v8/ScriptWrappable.h" +#include "modules/crypto/KeyAlgorithm.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" -#include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class WorkerCrypto : public ScriptWrappable, public RefCounted<WorkerCrypto> { +class AesKeyAlgorithm : public KeyAlgorithm { public: - static PassRefPtr<WorkerCrypto> create() { return adoptRef(new WorkerCrypto()); } + static AesKeyAlgorithm* create(const blink::WebCryptoKeyAlgorithm&); + + unsigned short length(); + + virtual void trace(Visitor*) OVERRIDE; private: - WorkerCrypto(); + explicit AesKeyAlgorithm(const blink::WebCryptoKeyAlgorithm&); }; -} +DEFINE_KEY_ALGORITHM_TYPE_CASTS(AesKeyAlgorithm); + +} // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/modules/crypto/WorkerCrypto.idl b/chromium/third_party/WebKit/Source/modules/crypto/AesKeyAlgorithm.idl index 4dd16cd8ba5..171650d215a 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/WorkerCrypto.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/AesKeyAlgorithm.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -30,6 +30,6 @@ [ NoInterfaceObject -] interface WorkerCrypto { - [Custom, RaisesException] ArrayBufferView getRandomValues(ArrayBufferView array); +] interface AesKeyAlgorithm : KeyAlgorithm { + readonly attribute unsigned short length; }; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesKeyGenParams.cpp b/chromium/third_party/WebKit/Source/modules/crypto/AesKeyGenParams.cpp deleted file mode 100644 index a363076c257..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesKeyGenParams.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/crypto/AesKeyGenParams.h" - -#include "public/platform/WebCryptoAlgorithmParams.h" - -namespace WebCore { - -unsigned short AesKeyGenParams::length() const -{ - return m_algorithm.aesKeyGenParams()->lengthBits(); -} - -AesKeyGenParams::AesKeyGenParams(const blink::WebCryptoAlgorithm& algorithm) - : Algorithm(algorithm) -{ - ASSERT(algorithm.aesKeyGenParams()); - ScriptWrappable::init(this); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesKeyGenParams.h b/chromium/third_party/WebKit/Source/modules/crypto/AesKeyGenParams.h deleted file mode 100644 index 655e8ce92ab..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesKeyGenParams.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AesKeyGenParams_h -#define AesKeyGenParams_h - -#include "modules/crypto/Algorithm.h" -#include "public/platform/WebCryptoAlgorithm.h" - -namespace WebCore { - -class AesKeyGenParams : public Algorithm { -public: - static PassRefPtr<AesKeyGenParams> create(const blink::WebCryptoAlgorithm& algorithm) { return adoptRef(new AesKeyGenParams(algorithm)); } - - unsigned short length() const; - -private: - explicit AesKeyGenParams(const blink::WebCryptoAlgorithm&); -}; - -} // namespace WebCore - -#endif diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Algorithm.cpp b/chromium/third_party/WebKit/Source/modules/crypto/Algorithm.cpp deleted file mode 100644 index 2bede54abd3..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/Algorithm.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/crypto/Algorithm.h" - -#include "modules/crypto/AesCbcParams.h" -#include "modules/crypto/AesCtrParams.h" -#include "modules/crypto/AesKeyGenParams.h" -#include "modules/crypto/HmacKeyParams.h" -#include "modules/crypto/HmacParams.h" -#include "modules/crypto/NormalizeAlgorithm.h" -#include "modules/crypto/RsaKeyGenParams.h" -#include "modules/crypto/RsaSsaParams.h" -#include "platform/NotImplemented.h" -#include "wtf/text/WTFString.h" - -namespace WebCore { - -PassRefPtr<Algorithm> Algorithm::create(const blink::WebCryptoAlgorithm& algorithm) -{ - switch (algorithm.paramsType()) { - case blink::WebCryptoAlgorithmParamsTypeNone: - return adoptRef(new Algorithm(algorithm)); - case blink::WebCryptoAlgorithmParamsTypeAesCbcParams: - return AesCbcParams::create(algorithm); - case blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams: - return AesKeyGenParams::create(algorithm); - case blink::WebCryptoAlgorithmParamsTypeHmacParams: - return HmacParams::create(algorithm); - case blink::WebCryptoAlgorithmParamsTypeHmacKeyParams: - return HmacKeyParams::create(algorithm); - case blink::WebCryptoAlgorithmParamsTypeRsaSsaParams: - return RsaSsaParams::create(algorithm); - case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams: - return RsaKeyGenParams::create(algorithm); - case blink::WebCryptoAlgorithmParamsTypeAesCtrParams: - return AesCtrParams::create(algorithm); - case blink::WebCryptoAlgorithmParamsTypeAesGcmParams: - case blink::WebCryptoAlgorithmParamsTypeRsaOaepParams: - // TODO - notImplemented(); - break; - } - ASSERT_NOT_REACHED(); - return 0; -} - -Algorithm::Algorithm(const blink::WebCryptoAlgorithm& algorithm) - : m_algorithm(algorithm) -{ - ScriptWrappable::init(this); -} - -String Algorithm::name() -{ - return algorithmIdToName(m_algorithm.id()); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Crypto.cpp b/chromium/third_party/WebKit/Source/modules/crypto/Crypto.cpp index 4a8a7f7e2bd..a5d40861a0a 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/Crypto.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/Crypto.cpp @@ -41,7 +41,7 @@ namespace { bool isIntegerArray(ArrayBufferView* array) { - ArrayBufferView::ViewType type = array->getType(); + ArrayBufferView::ViewType type = array->type(); return type == ArrayBufferView::TypeInt8 || type == ArrayBufferView::TypeUint8 || type == ArrayBufferView::TypeUint8Clamped @@ -58,7 +58,6 @@ Crypto::Crypto() ScriptWrappable::init(this); } -// Note: This implementation must be thread-safe, as it is used by workers. void Crypto::getRandomValues(ArrayBufferView* array, ExceptionState& exceptionState) { if (!array) { @@ -83,4 +82,9 @@ SubtleCrypto* Crypto::subtle() return m_subtleCrypto.get(); } +void Crypto::trace(Visitor* visitor) +{ + visitor->trace(m_subtleCrypto); +} + } diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Crypto.h b/chromium/third_party/WebKit/Source/modules/crypto/Crypto.h index 7ed5089d731..9aa9ea3a210 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/Crypto.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/Crypto.h @@ -31,6 +31,7 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/crypto/SubtleCrypto.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" @@ -39,18 +40,23 @@ namespace WebCore { class ExceptionState; -class Crypto : public ScriptWrappable, public RefCounted<Crypto> { +class Crypto : public GarbageCollectedFinalized<Crypto>, public ScriptWrappable { public: - static PassRefPtr<Crypto> create() { return adoptRef(new Crypto()); } + static Crypto* create() + { + return new Crypto(); + } - static void getRandomValues(ArrayBufferView*, ExceptionState&); + void getRandomValues(ArrayBufferView*, ExceptionState&); SubtleCrypto* subtle(); + void trace(Visitor*); + private: Crypto(); - RefPtr<SubtleCrypto> m_subtleCrypto; + Member<SubtleCrypto> m_subtleCrypto; }; } diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Crypto.idl b/chromium/third_party/WebKit/Source/modules/crypto/Crypto.idl index 52044ab6e05..2348d779845 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/Crypto.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/Crypto.idl @@ -27,6 +27,7 @@ */ [ + GarbageCollected, NoInterfaceObject ] interface Crypto { // Note that getRandomValues() is available even when the "Crypto" diff --git a/chromium/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp b/chromium/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp index 557562c2c68..c2cd20c9fdf 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp @@ -31,9 +31,13 @@ #include "config.h" #include "modules/crypto/CryptoResultImpl.h" -#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "bindings/v8/ScriptState.h" +#include "core/dom/ContextLifecycleObserver.h" +#include "core/dom/DOMError.h" +#include "core/dom/DOMException.h" +#include "core/dom/ExecutionContext.h" #include "modules/crypto/Key.h" -#include "modules/crypto/KeyPair.h" #include "modules/crypto/NormalizeAlgorithm.h" #include "public/platform/Platform.h" #include "public/platform/WebArrayBuffer.h" @@ -42,54 +46,151 @@ namespace WebCore { +class CryptoResultImpl::WeakResolver : public ScriptPromiseResolverWithContext { +public: + static WeakPtr<ScriptPromiseResolverWithContext> create(ScriptState* scriptState, CryptoResultImpl* result) + { + RefPtr<WeakResolver> p = adoptRef(new WeakResolver(scriptState, result)); + p->suspendIfNeeded(); + p->keepAliveWhilePending(); + return p->m_weakPtrFactory.createWeakPtr(); + } + + virtual ~WeakResolver() + { + m_result->cancel(); + } + +private: + WeakResolver(ScriptState* scriptState, CryptoResultImpl* result) + : ScriptPromiseResolverWithContext(scriptState) + , m_weakPtrFactory(this) + , m_result(result) { } + WeakPtrFactory<ScriptPromiseResolverWithContext> m_weakPtrFactory; + RefPtr<CryptoResultImpl> m_result; +}; + +ExceptionCode webCryptoErrorToExceptionCode(blink::WebCryptoErrorType errorType) +{ + switch (errorType) { + case blink::WebCryptoErrorTypeNotSupported: + return NotSupportedError; + case blink::WebCryptoErrorTypeSyntax: + return SyntaxError; + case blink::WebCryptoErrorTypeInvalidState: + return InvalidStateError; + case blink::WebCryptoErrorTypeInvalidAccess: + return InvalidAccessError; + case blink::WebCryptoErrorTypeUnknown: + return UnknownError; + case blink::WebCryptoErrorTypeData: + return DataError; + case blink::WebCryptoErrorTypeOperation: + return OperationError; + case blink::WebCryptoErrorTypeType: + // FIXME: This should construct a TypeError instead. For now do + // something to facilitate refactor, but this will need to be + // revisited. + return DataError; + } + + ASSERT_NOT_REACHED(); + return 0; +} + CryptoResultImpl::~CryptoResultImpl() { - ASSERT(m_finished); } -PassRefPtr<CryptoResultImpl> CryptoResultImpl::create(ScriptPromise promise) +PassRefPtr<CryptoResultImpl> CryptoResultImpl::create(ScriptState* scriptState) { - return adoptRef(new CryptoResultImpl(promise)); + return adoptRef(new CryptoResultImpl(scriptState)); } -void CryptoResultImpl::completeWithError() +void CryptoResultImpl::completeWithError(blink::WebCryptoErrorType errorType, const blink::WebString& errorDetails) { - m_promiseResolver->reject(ScriptValue::createNull()); - finish(); + if (m_resolver) + m_resolver->reject(DOMException::create(webCryptoErrorToExceptionCode(errorType), errorDetails)); } void CryptoResultImpl::completeWithBuffer(const blink::WebArrayBuffer& buffer) { - m_promiseResolver->resolve(PassRefPtr<ArrayBuffer>(buffer)); - finish(); + if (m_resolver) + m_resolver->resolve(PassRefPtr<ArrayBuffer>(buffer)); +} + +void CryptoResultImpl::completeWithJson(const char* utf8Data, unsigned length) +{ + if (m_resolver) { + ScriptPromiseResolverWithContext* resolver = m_resolver.get(); + ScriptState* scriptState = resolver->scriptState(); + ScriptState::Scope scope(scriptState); + + v8::Handle<v8::String> jsonString = v8::String::NewFromUtf8(scriptState->isolate(), utf8Data, v8::String::kInternalizedString, length); + + v8::TryCatch exceptionCatcher; + v8::Handle<v8::Value> jsonDictionary = v8::JSON::Parse(jsonString); + if (exceptionCatcher.HasCaught() || jsonDictionary.IsEmpty()) { + ASSERT_NOT_REACHED(); + resolver->reject(DOMException::create(OperationError, "Failed inflating JWK JSON to object")); + } else { + resolver->resolve(jsonDictionary); + } + } } void CryptoResultImpl::completeWithBoolean(bool b) { - m_promiseResolver->resolve(ScriptValue::createBoolean(b)); - finish(); + if (m_resolver) + m_resolver->resolve(b); } void CryptoResultImpl::completeWithKey(const blink::WebCryptoKey& key) { - m_promiseResolver->resolve(Key::create(key)); - finish(); + if (m_resolver) + m_resolver->resolve(Key::create(key)); } void CryptoResultImpl::completeWithKeyPair(const blink::WebCryptoKey& publicKey, const blink::WebCryptoKey& privateKey) { - m_promiseResolver->resolve(KeyPair::create(publicKey, privateKey)); - finish(); + if (m_resolver) { + ScriptState* scriptState = m_resolver->scriptState(); + ScriptState::Scope scope(scriptState); + + // FIXME: Use Dictionary instead, to limit amount of direct v8 access used from WebCore. + v8::Handle<v8::Object> keyPair = v8::Object::New(scriptState->isolate()); + + v8::Handle<v8::Value> publicKeyValue = toV8NoInline(Key::create(publicKey), scriptState->context()->Global(), scriptState->isolate()); + v8::Handle<v8::Value> privateKeyValue = toV8NoInline(Key::create(privateKey), scriptState->context()->Global(), scriptState->isolate()); + + keyPair->Set(v8::String::NewFromUtf8(scriptState->isolate(), "publicKey"), publicKeyValue); + keyPair->Set(v8::String::NewFromUtf8(scriptState->isolate(), "privateKey"), privateKeyValue); + + m_resolver->resolve(v8::Handle<v8::Value>(keyPair)); + } +} + +bool CryptoResultImpl::cancelled() const +{ + return acquireLoad(&m_cancelled); +} + +void CryptoResultImpl::cancel() +{ + releaseStore(&m_cancelled, 1); } -CryptoResultImpl::CryptoResultImpl(ScriptPromise promise) - : m_promiseResolver(ScriptPromiseResolver::create(promise)) - , m_finished(false) { } +CryptoResultImpl::CryptoResultImpl(ScriptState* scriptState) + : m_cancelled(0) +{ + // Creating the WeakResolver may return nullptr if active dom objects have + // been stopped. And in the process set m_cancelled to 1. + m_resolver = WeakResolver::create(scriptState, this); +} -void CryptoResultImpl::finish() +ScriptPromise CryptoResultImpl::promise() { - ASSERT(!m_finished); - m_finished = true; + return m_resolver ? m_resolver->promise() : ScriptPromise(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.h b/chromium/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.h index a0f39ed8f35..4060c49819a 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.h @@ -32,34 +32,53 @@ #define CryptoResultImpl_h #include "bindings/v8/ScriptPromise.h" -#include "core/platform/CryptoResult.h" +#include "core/dom/ExceptionCode.h" +#include "platform/CryptoResult.h" #include "public/platform/WebCrypto.h" #include "wtf/Forward.h" +#include "wtf/WeakPtr.h" namespace WebCore { -class ScriptPromiseResolver; +class ScriptPromiseResolverWithContext; +ExceptionCode webCryptoErrorToExceptionCode(blink::WebCryptoErrorType); // Wrapper around a Promise to notify completion of the crypto operation. -// Platform cannot know about Promises which are declared in bindings. -class CryptoResultImpl : public CryptoResult { +// +// The thread on which CryptoResultImpl was created on is referred to as the +// "origin thread". +// +// * At creation time there must be an active ExecutionContext. +// * The CryptoResult interface must only be called from the origin thread. +// * ref(), deref(), cancelled() and cancel() can be called from any thread. +// * One of the completeWith***() functions must be called, or the +// m_resolver will be leaked until the ExecutionContext is destroyed. +class CryptoResultImpl FINAL : public CryptoResult { public: ~CryptoResultImpl(); - static PassRefPtr<CryptoResultImpl> create(ScriptPromise); + static PassRefPtr<CryptoResultImpl> create(ScriptState*); - virtual void completeWithError() OVERRIDE; + virtual void completeWithError(blink::WebCryptoErrorType, const blink::WebString&) OVERRIDE; virtual void completeWithBuffer(const blink::WebArrayBuffer&) OVERRIDE; + virtual void completeWithJson(const char* utf8Data, unsigned length) OVERRIDE; virtual void completeWithBoolean(bool) OVERRIDE; virtual void completeWithKey(const blink::WebCryptoKey&) OVERRIDE; virtual void completeWithKeyPair(const blink::WebCryptoKey& publicKey, const blink::WebCryptoKey& privateKey) OVERRIDE; + virtual bool cancelled() const OVERRIDE; + + // If called after completion (including cancellation) will return an empty + // ScriptPromise. + ScriptPromise promise(); private: - explicit CryptoResultImpl(ScriptPromise); - void finish(); + class WeakResolver; + explicit CryptoResultImpl(ScriptState*); + + void cancel(); - RefPtr<ScriptPromiseResolver> m_promiseResolver; - bool m_finished; + WeakPtr<ScriptPromiseResolverWithContext> m_resolver; + volatile int m_cancelled; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/DOMWindowCrypto.cpp b/chromium/third_party/WebKit/Source/modules/crypto/DOMWindowCrypto.cpp index 5c4bbae2613..b3e4c3fe6c7 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/DOMWindowCrypto.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/DOMWindowCrypto.cpp @@ -31,13 +31,13 @@ #include "config.h" #include "modules/crypto/DOMWindowCrypto.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "modules/crypto/Crypto.h" namespace WebCore { -DOMWindowCrypto::DOMWindowCrypto(DOMWindow* window) - : DOMWindowProperty(window->frame()) +DOMWindowCrypto::DOMWindowCrypto(LocalDOMWindow& window) + : DOMWindowProperty(window.frame()) { } @@ -50,19 +50,19 @@ const char* DOMWindowCrypto::supplementName() return "DOMWindowCrypto"; } -DOMWindowCrypto* DOMWindowCrypto::from(DOMWindow* window) +DOMWindowCrypto& DOMWindowCrypto::from(LocalDOMWindow& window) { - DOMWindowCrypto* supplement = static_cast<DOMWindowCrypto*>(Supplement<DOMWindow>::from(window, supplementName())); + DOMWindowCrypto* supplement = static_cast<DOMWindowCrypto*>(WillBeHeapSupplement<LocalDOMWindow>::from(window, supplementName())); if (!supplement) { supplement = new DOMWindowCrypto(window); - provideTo(window, supplementName(), adoptPtr(supplement)); + provideTo(window, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -Crypto* DOMWindowCrypto::crypto(DOMWindow* window) +Crypto* DOMWindowCrypto::crypto(LocalDOMWindow& window) { - return DOMWindowCrypto::from(window)->crypto(); + return DOMWindowCrypto::from(window).crypto(); } Crypto* DOMWindowCrypto::crypto() const @@ -72,4 +72,10 @@ Crypto* DOMWindowCrypto::crypto() const return m_crypto.get(); } +void DOMWindowCrypto::trace(Visitor* visitor) +{ + visitor->trace(m_crypto); + WillBeHeapSupplement<LocalDOMWindow>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/DOMWindowCrypto.h b/chromium/third_party/WebKit/Source/modules/crypto/DOMWindowCrypto.h index 707918d6d01..fc155c92d98 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/DOMWindowCrypto.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/DOMWindowCrypto.h @@ -33,24 +33,28 @@ #include "core/frame/DOMWindowProperty.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { class Crypto; -class DOMWindow; +class LocalDOMWindow; -class DOMWindowCrypto : public Supplement<DOMWindow>, public DOMWindowProperty { +class DOMWindowCrypto FINAL : public NoBaseWillBeGarbageCollectedFinalized<DOMWindowCrypto>, public WillBeHeapSupplement<LocalDOMWindow>, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DOMWindowCrypto); public: virtual ~DOMWindowCrypto(); - static DOMWindowCrypto* from(DOMWindow*); - static Crypto* crypto(DOMWindow*); + static DOMWindowCrypto& from(LocalDOMWindow&); + static Crypto* crypto(LocalDOMWindow&); Crypto* crypto() const; + void trace(Visitor*); + private: - explicit DOMWindowCrypto(DOMWindow*); + explicit DOMWindowCrypto(LocalDOMWindow&); static const char* supplementName(); - mutable RefPtr<Crypto> m_crypto; + mutable PersistentWillBeMember<Crypto> m_crypto; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/RsaSsaParams.cpp b/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyAlgorithm.cpp index 214efc3abb2..1d750cb5dba 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/RsaSsaParams.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyAlgorithm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,23 +29,39 @@ */ #include "config.h" -#include "modules/crypto/RsaSsaParams.h" +#include "modules/crypto/HmacKeyAlgorithm.h" -#include "public/platform/WebCryptoAlgorithmParams.h" +#include "modules/crypto/NormalizeAlgorithm.h" +#include "wtf/text/WTFString.h" namespace WebCore { -Algorithm* RsaSsaParams::hash() +HmacKeyAlgorithm* HmacKeyAlgorithm::create(const blink::WebCryptoKeyAlgorithm& algorithm) +{ + return new HmacKeyAlgorithm(algorithm); +} + +KeyAlgorithm* HmacKeyAlgorithm::hash() { if (!m_hash) - m_hash = Algorithm::create(m_algorithm.rsaSsaParams()->hash()); + m_hash = KeyAlgorithm::createHash(m_algorithm.hmacParams()->hash()); return m_hash.get(); } -RsaSsaParams::RsaSsaParams(const blink::WebCryptoAlgorithm& algorithm) - : Algorithm(algorithm) +unsigned HmacKeyAlgorithm::length() +{ + return m_algorithm.hmacParams()->lengthBits(); +} + +void HmacKeyAlgorithm::trace(Visitor* visitor) +{ + visitor->trace(m_hash); + KeyAlgorithm::trace(visitor); +} + +HmacKeyAlgorithm::HmacKeyAlgorithm(const blink::WebCryptoKeyAlgorithm& algorithm) + : KeyAlgorithm(algorithm) { - ASSERT(algorithm.rsaSsaParams()); ScriptWrappable::init(this); } diff --git a/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyParams.h b/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyAlgorithm.h index 64b286ca7ae..ef500d68a55 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyParams.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyAlgorithm.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,28 +28,30 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef HmacKeyParams_h -#define HmacKeyParams_h +#ifndef HmacKeyAlgorithm_h +#define HmacKeyAlgorithm_h -#include "modules/crypto/Algorithm.h" -#include "wtf/RefPtr.h" +#include "modules/crypto/KeyAlgorithm.h" namespace WebCore { -class HmacKeyParams : public Algorithm { +class HmacKeyAlgorithm : public KeyAlgorithm { public: - static PassRefPtr<HmacKeyParams> create(const blink::WebCryptoAlgorithm& algorithm) { return adoptRef(new HmacKeyParams(algorithm)); } + static HmacKeyAlgorithm* create(const blink::WebCryptoKeyAlgorithm&); - Algorithm* hash(); + KeyAlgorithm* hash(); + unsigned length(); - unsigned length(bool& isNull); + virtual void trace(Visitor*) OVERRIDE; private: - explicit HmacKeyParams(const blink::WebCryptoAlgorithm&); + explicit HmacKeyAlgorithm(const blink::WebCryptoKeyAlgorithm&); - RefPtr<Algorithm> m_hash; + Member<KeyAlgorithm> m_hash; }; +DEFINE_KEY_ALGORITHM_TYPE_CASTS(HmacKeyAlgorithm); + } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesCbcParams.idl b/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyAlgorithm.idl index b068ec9586c..89cc8430ad3 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesCbcParams.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyAlgorithm.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,7 +29,8 @@ */ [ - NoInterfaceObject, -] interface AesCbcParams : Algorithm { - readonly attribute Uint8Array iv; + NoInterfaceObject +] interface HmacKeyAlgorithm : KeyAlgorithm { + readonly attribute KeyAlgorithm hash; + readonly attribute unsigned long length; }; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyParams.idl b/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyParams.idl deleted file mode 100644 index bb7ac7ea3be..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/HmacKeyParams.idl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - NoInterfaceObject, -] interface HmacKeyParams : Algorithm { - readonly attribute Algorithm hash; - readonly attribute unsigned long? length; -}; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/HmacParams.idl b/chromium/third_party/WebKit/Source/modules/crypto/HmacParams.idl deleted file mode 100644 index 2dae1c8f4f0..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/HmacParams.idl +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - NoInterfaceObject, -] interface HmacParams : Algorithm { - readonly attribute Algorithm hash; -}; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Key.cpp b/chromium/third_party/WebKit/Source/modules/crypto/Key.cpp index d6e5cc40f01..a559a00ecff 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/Key.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/Key.cpp @@ -33,8 +33,10 @@ #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "modules/crypto/Algorithm.h" +#include "modules/crypto/KeyAlgorithm.h" +#include "platform/CryptoResult.h" #include "public/platform/WebCryptoAlgorithmParams.h" +#include "public/platform/WebString.h" namespace WebCore { @@ -59,18 +61,20 @@ struct KeyUsageMapping { const char* const name; }; -// Keep this array sorted. +// The order of this array is the same order that will appear in Key.usages. It +// must be kept ordered as described by the Web Crypto spec. const KeyUsageMapping keyUsageMappings[] = { - { blink::WebCryptoKeyUsageDecrypt, "decrypt" }, - { blink::WebCryptoKeyUsageDeriveKey, "deriveKey" }, { blink::WebCryptoKeyUsageEncrypt, "encrypt" }, + { blink::WebCryptoKeyUsageDecrypt, "decrypt" }, { blink::WebCryptoKeyUsageSign, "sign" }, - { blink::WebCryptoKeyUsageUnwrapKey, "unwrapKey" }, { blink::WebCryptoKeyUsageVerify, "verify" }, + { blink::WebCryptoKeyUsageDeriveKey, "deriveKey" }, + { blink::WebCryptoKeyUsageDeriveBits, "deriveBits" }, { blink::WebCryptoKeyUsageWrapKey, "wrapKey" }, + { blink::WebCryptoKeyUsageUnwrapKey, "unwrapKey" }, }; -COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 6) + 1, update_keyUsageMappings); +COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, update_keyUsageMappings); const char* keyUsageToString(blink::WebCryptoKeyUsage usage) { @@ -91,26 +95,28 @@ blink::WebCryptoKeyUsageMask keyUsageStringToMask(const String& usageString) return 0; } -blink::WebCryptoKeyUsageMask toKeyUsage(AlgorithmOperation operation) +blink::WebCryptoKeyUsageMask toKeyUsage(blink::WebCryptoOperation operation) { switch (operation) { - case Encrypt: + case blink::WebCryptoOperationEncrypt: return blink::WebCryptoKeyUsageEncrypt; - case Decrypt: + case blink::WebCryptoOperationDecrypt: return blink::WebCryptoKeyUsageDecrypt; - case Sign: + case blink::WebCryptoOperationSign: return blink::WebCryptoKeyUsageSign; - case Verify: + case blink::WebCryptoOperationVerify: return blink::WebCryptoKeyUsageVerify; - case DeriveKey: + case blink::WebCryptoOperationDeriveKey: return blink::WebCryptoKeyUsageDeriveKey; - case WrapKey: + case blink::WebCryptoOperationDeriveBits: + return blink::WebCryptoKeyUsageDeriveBits; + case blink::WebCryptoOperationWrapKey: return blink::WebCryptoKeyUsageWrapKey; - case UnwrapKey: + case blink::WebCryptoOperationUnwrapKey: return blink::WebCryptoKeyUsageUnwrapKey; - case Digest: - case GenerateKey: - case ImportKey: + case blink::WebCryptoOperationDigest: + case blink::WebCryptoOperationGenerateKey: + case blink::WebCryptoOperationImportKey: break; } @@ -118,19 +124,6 @@ blink::WebCryptoKeyUsageMask toKeyUsage(AlgorithmOperation operation) return 0; } -bool getHmacHashId(const blink::WebCryptoAlgorithm& algorithm, blink::WebCryptoAlgorithmId& hashId) -{ - if (algorithm.hmacParams()) { - hashId = algorithm.hmacParams()->hash().id(); - return true; - } - if (algorithm.hmacKeyParams()) { - hashId = algorithm.hmacKeyParams()->hash().id(); - return true; - } - return false; -} - } // namespace Key::~Key() @@ -153,10 +146,10 @@ bool Key::extractable() const return m_key.extractable(); } -Algorithm* Key::algorithm() +KeyAlgorithm* Key::algorithm() { if (!m_algorithm) - m_algorithm = Algorithm::create(m_key.algorithm()); + m_algorithm = KeyAlgorithm::create(m_key.algorithm()); return m_algorithm.get(); } @@ -175,35 +168,22 @@ Vector<String> Key::usages() const return result; } -bool Key::canBeUsedForAlgorithm(const blink::WebCryptoAlgorithm& algorithm, AlgorithmOperation op, ExceptionState& exceptionState) const +bool Key::canBeUsedForAlgorithm(const blink::WebCryptoAlgorithm& algorithm, blink::WebCryptoOperation op, CryptoResult* result) const { if (!(m_key.usages() & toKeyUsage(op))) { - exceptionState.throwDOMException(NotSupportedError, "key.usages does not permit this operation"); + result->completeWithError(blink::WebCryptoErrorTypeInvalidAccess, "key.usages does not permit this operation"); return false; } if (m_key.algorithm().id() != algorithm.id()) { - exceptionState.throwDOMException(NotSupportedError, "key.algorithm does not match that of operation"); + result->completeWithError(blink::WebCryptoErrorTypeInvalidAccess, "key.algorithm does not match that of operation"); return false; } - // Verify that the algorithm-specific parameters for the key conform to the - // algorithm. - // FIXME: Verify that this is complete. - - if (m_key.algorithm().id() == blink::WebCryptoAlgorithmIdHmac) { - blink::WebCryptoAlgorithmId keyHash; - blink::WebCryptoAlgorithmId algorithmHash; - if (!getHmacHashId(m_key.algorithm(), keyHash) || !getHmacHashId(algorithm, algorithmHash) || keyHash != algorithmHash) { - exceptionState.throwDOMException(NotSupportedError, "key.algorithm does not match that of operation (HMAC's hash differs)"); - return false; - } - } - return true; } -bool Key::parseFormat(const String& formatString, blink::WebCryptoKeyFormat& format, ExceptionState& exceptionState) +bool Key::parseFormat(const String& formatString, blink::WebCryptoKeyFormat& format, CryptoResult* result) { // There are few enough values that testing serially is fast enough. if (formatString == "raw") { @@ -223,17 +203,17 @@ bool Key::parseFormat(const String& formatString, blink::WebCryptoKeyFormat& for return true; } - exceptionState.throwTypeError("Invalid keyFormat argument"); + result->completeWithError(blink::WebCryptoErrorTypeSyntax, "Invalid keyFormat argument"); return false; } -bool Key::parseUsageMask(const Vector<String>& usages, blink::WebCryptoKeyUsageMask& mask, ExceptionState& exceptionState) +bool Key::parseUsageMask(const Vector<String>& usages, blink::WebCryptoKeyUsageMask& mask, CryptoResult* result) { mask = 0; for (size_t i = 0; i < usages.size(); ++i) { blink::WebCryptoKeyUsageMask usage = keyUsageStringToMask(usages[i]); if (!usage) { - exceptionState.throwTypeError("Invalid keyUsages argument"); + result->completeWithError(blink::WebCryptoErrorTypeSyntax, "Invalid keyUsages argument"); return false; } mask |= usage; @@ -241,4 +221,9 @@ bool Key::parseUsageMask(const Vector<String>& usages, blink::WebCryptoKeyUsageM return true; } +void Key::trace(Visitor* visitor) +{ + visitor->trace(m_algorithm); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Key.h b/chromium/third_party/WebKit/Source/modules/crypto/Key.h index aa6bad09ffb..6a91841ef84 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/Key.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/Key.h @@ -33,40 +33,49 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/crypto/NormalizeAlgorithm.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebCryptoAlgorithm.h" #include "public/platform/WebCryptoKey.h" #include "wtf/Forward.h" -#include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace WebCore { -class Algorithm; -class ExceptionState; +class CryptoResult; +class KeyAlgorithm; -class Key : public ScriptWrappable, public RefCounted<Key> { +class Key : public GarbageCollectedFinalized<Key>, public ScriptWrappable { public: - static PassRefPtr<Key> create(const blink::WebCryptoKey& key) { return adoptRef(new Key(key)); } + static Key* create(const blink::WebCryptoKey& key) + { + return new Key(key); + } ~Key(); String type() const; bool extractable() const; - Algorithm* algorithm(); + KeyAlgorithm* algorithm(); Vector<String> usages() const; const blink::WebCryptoKey& key() const { return m_key; } - bool canBeUsedForAlgorithm(const blink::WebCryptoAlgorithm&, AlgorithmOperation, ExceptionState&) const; + // If the key cannot be used with the indicated algorithm, returns false + // and completes the CryptoResult with an error. + bool canBeUsedForAlgorithm(const blink::WebCryptoAlgorithm&, blink::WebCryptoOperation, CryptoResult*) const; - static bool parseFormat(const String&, blink::WebCryptoKeyFormat&, ExceptionState&); - static bool parseUsageMask(const Vector<String>&, blink::WebCryptoKeyUsageMask&, ExceptionState&); + // On failure, these return false and complete the CryptoResult with an error. + static bool parseFormat(const String&, blink::WebCryptoKeyFormat&, CryptoResult*); + static bool parseUsageMask(const Vector<String>&, blink::WebCryptoKeyUsageMask&, CryptoResult*); + + void trace(Visitor*); protected: explicit Key(const blink::WebCryptoKey&); const blink::WebCryptoKey m_key; - RefPtr<Algorithm> m_algorithm; + Member<KeyAlgorithm> m_algorithm; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Key.idl b/chromium/third_party/WebKit/Source/modules/crypto/Key.idl index 6124a2f5746..9bc03052298 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/Key.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/Key.idl @@ -29,10 +29,11 @@ */ [ - NoInterfaceObject, + GarbageCollected, + NoInterfaceObject ] interface Key { readonly attribute DOMString type; readonly attribute boolean extractable; - readonly attribute Algorithm algorithm; + readonly attribute KeyAlgorithm algorithm; readonly attribute DOMString[] usages; }; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/KeyAlgorithm.cpp b/chromium/third_party/WebKit/Source/modules/crypto/KeyAlgorithm.cpp new file mode 100644 index 00000000000..9ae965d5d1a --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/crypto/KeyAlgorithm.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/crypto/KeyAlgorithm.h" + +#include "modules/crypto/AesKeyAlgorithm.h" +#include "modules/crypto/HmacKeyAlgorithm.h" +#include "modules/crypto/NormalizeAlgorithm.h" +#include "modules/crypto/RsaHashedKeyAlgorithm.h" +#include "modules/crypto/RsaKeyAlgorithm.h" +#include "public/platform/WebCryptoAlgorithm.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +KeyAlgorithm::~KeyAlgorithm() +{ +} + +KeyAlgorithm* KeyAlgorithm::create(const blink::WebCryptoKeyAlgorithm& algorithm) +{ + switch (algorithm.paramsType()) { + case blink::WebCryptoKeyAlgorithmParamsTypeNone: + return new KeyAlgorithm(algorithm); + case blink::WebCryptoKeyAlgorithmParamsTypeAes: + return AesKeyAlgorithm::create(algorithm); + case blink::WebCryptoKeyAlgorithmParamsTypeHmac: + return HmacKeyAlgorithm::create(algorithm); + case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: + return RsaHashedKeyAlgorithm::create(algorithm); + } + ASSERT_NOT_REACHED(); + return 0; +} + +KeyAlgorithm* KeyAlgorithm::createHash(const blink::WebCryptoAlgorithm& hash) +{ + // Assume that none of the hash algorithms have any parameters. + ASSERT(hash.paramsType() == blink::WebCryptoAlgorithmParamsTypeNone); + return new KeyAlgorithm(blink::WebCryptoKeyAlgorithm(hash.id(), nullptr)); +} + +KeyAlgorithm::KeyAlgorithm(const blink::WebCryptoKeyAlgorithm& algorithm) + : m_algorithm(algorithm) +{ + ScriptWrappable::init(this); +} + +String KeyAlgorithm::name() +{ + const blink::WebCryptoAlgorithmInfo* info = blink::WebCryptoAlgorithm::lookupAlgorithmInfo(m_algorithm.id()); + return info->name; +} + +bool KeyAlgorithm::isAesKeyAlgorithm() const +{ + return m_algorithm.paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeAes; +} + +bool KeyAlgorithm::isHmacKeyAlgorithm() const +{ + return m_algorithm.paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeHmac; +} + +bool KeyAlgorithm::isRsaHashedKeyAlgorithm() const +{ + return m_algorithm.paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed; +} + +void KeyAlgorithm::trace(Visitor*) +{ +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Algorithm.h b/chromium/third_party/WebKit/Source/modules/crypto/KeyAlgorithm.h index 779bf28ea01..8d0e8dc2f1d 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/Algorithm.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/KeyAlgorithm.h @@ -28,31 +28,42 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Algorithm_h -#define Algorithm_h +#ifndef KeyAlgorithm_h +#define KeyAlgorithm_h #include "bindings/v8/ScriptWrappable.h" -#include "public/platform/WebCryptoAlgorithm.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebCryptoKeyAlgorithm.h" #include "wtf/Forward.h" -#include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class Algorithm : public ScriptWrappable, public RefCounted<Algorithm> { +class KeyAlgorithm : public GarbageCollectedFinalized<KeyAlgorithm>, public ScriptWrappable { public: - static PassRefPtr<Algorithm> create(const blink::WebCryptoAlgorithm&); + virtual ~KeyAlgorithm(); + + static KeyAlgorithm* create(const blink::WebCryptoKeyAlgorithm&); + static KeyAlgorithm* createHash(const blink::WebCryptoAlgorithm&); String name(); - blink::WebCryptoAlgorithmParamsType type() const { return m_algorithm.paramsType(); } + // Needed by SpecialWrapFor and for casting. + bool isAesKeyAlgorithm() const; + bool isHmacKeyAlgorithm() const; + bool isRsaHashedKeyAlgorithm() const; + + virtual void trace(Visitor*); protected: - explicit Algorithm(const blink::WebCryptoAlgorithm&); + explicit KeyAlgorithm(const blink::WebCryptoKeyAlgorithm&); - const blink::WebCryptoAlgorithm m_algorithm; + blink::WebCryptoKeyAlgorithm m_algorithm; }; +#define DEFINE_KEY_ALGORITHM_TYPE_CASTS(thisType) \ + DEFINE_TYPE_CASTS(thisType, KeyAlgorithm, value, value->is##thisType(), value.is##thisType()) + } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/modules/crypto/Algorithm.idl b/chromium/third_party/WebKit/Source/modules/crypto/KeyAlgorithm.idl index 6f1d20c97c1..d9e0ea0fb3b 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/Algorithm.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/KeyAlgorithm.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,8 +29,9 @@ */ [ - Custom=Wrap, + GarbageCollected, NoInterfaceObject, -] interface Algorithm { + SpecialWrapFor=AesKeyAlgorithm|HmacKeyAlgorithm|RsaHashedKeyAlgorithm +] interface KeyAlgorithm { readonly attribute DOMString name; }; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/KeyPair.idl b/chromium/third_party/WebKit/Source/modules/crypto/KeyPair.idl deleted file mode 100644 index 538f85a74b2..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/KeyPair.idl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - NoInterfaceObject, -] interface KeyPair { - readonly attribute Key publicKey; - readonly attribute Key privateKey; -}; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp b/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp index 2d4d62c47ef..ac51c7cbe10 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.cpp @@ -32,190 +32,190 @@ #include "modules/crypto/NormalizeAlgorithm.h" #include "bindings/v8/Dictionary.h" -#include "bindings/v8/ExceptionState.h" -#include "core/dom/ExceptionCode.h" #include "platform/NotImplemented.h" #include "public/platform/WebCryptoAlgorithmParams.h" +#include "public/platform/WebString.h" #include "wtf/ArrayBuffer.h" #include "wtf/ArrayBufferView.h" -#include "wtf/HashMap.h" #include "wtf/MathExtras.h" #include "wtf/Uint8Array.h" #include "wtf/Vector.h" #include "wtf/text/StringBuilder.h" -#include "wtf/text/StringHash.h" +#include <algorithm> namespace WebCore { namespace { struct AlgorithmNameMapping { + // Must be an upper case ASCII string. const char* const algorithmName; + // Must be strlen(algorithmName). + unsigned char algorithmNameLength; blink::WebCryptoAlgorithmId algorithmId; -}; - -// Indicates that the algorithm doesn't support the specified operation. -const int UnsupportedOp = -1; -// Either UnsupportedOp, or a value from blink::WebCryptoAlgorithmParamsType -typedef int AlgorithmParamsForOperation; - -struct OperationParamsMapping { - blink::WebCryptoAlgorithmId algorithmId; - AlgorithmOperation operation; - AlgorithmParamsForOperation params; +#if ASSERT_ENABLED + bool operator<(const AlgorithmNameMapping&) const; +#endif }; +// Must be sorted by length, and then by reverse string. +// Also all names must be upper case ASCII. const AlgorithmNameMapping algorithmNameMappings[] = { - {"AES-CBC", blink::WebCryptoAlgorithmIdAesCbc}, - {"AES-CTR", blink::WebCryptoAlgorithmIdAesCtr}, - {"HMAC", blink::WebCryptoAlgorithmIdHmac}, - {"RSASSA-PKCS1-v1_5", blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5}, - {"RSAES-PKCS1-v1_5", blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5}, - {"SHA-1", blink::WebCryptoAlgorithmIdSha1}, - {"SHA-224", blink::WebCryptoAlgorithmIdSha224}, - {"SHA-256", blink::WebCryptoAlgorithmIdSha256}, - {"SHA-384", blink::WebCryptoAlgorithmIdSha384}, - {"SHA-512", blink::WebCryptoAlgorithmIdSha512}, - {"AES-KW", blink::WebCryptoAlgorithmIdAesKw}, + {"HMAC", 4, blink::WebCryptoAlgorithmIdHmac}, + {"SHA-1", 5, blink::WebCryptoAlgorithmIdSha1}, + {"AES-KW", 6, blink::WebCryptoAlgorithmIdAesKw}, + {"SHA-512", 7, blink::WebCryptoAlgorithmIdSha512}, + {"SHA-384", 7, blink::WebCryptoAlgorithmIdSha384}, + {"SHA-256", 7, blink::WebCryptoAlgorithmIdSha256}, + {"AES-CBC", 7, blink::WebCryptoAlgorithmIdAesCbc}, + {"AES-GCM", 7, blink::WebCryptoAlgorithmIdAesGcm}, + {"AES-CTR", 7, blink::WebCryptoAlgorithmIdAesCtr}, + {"RSA-OAEP", 8, blink::WebCryptoAlgorithmIdRsaOaep}, + {"RSASSA-PKCS1-V1_5", 17, blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5}, }; -// What operations each algorithm supports, and what parameters it expects. -const OperationParamsMapping operationParamsMappings[] = { - // AES-CBC - {blink::WebCryptoAlgorithmIdAesCbc, Decrypt, blink::WebCryptoAlgorithmParamsTypeAesCbcParams}, - {blink::WebCryptoAlgorithmIdAesCbc, Encrypt, blink::WebCryptoAlgorithmParamsTypeAesCbcParams}, - {blink::WebCryptoAlgorithmIdAesCbc, GenerateKey, blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams}, - {blink::WebCryptoAlgorithmIdAesCbc, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdAesCbc, UnwrapKey, blink::WebCryptoAlgorithmParamsTypeAesCbcParams}, - {blink::WebCryptoAlgorithmIdAesCbc, WrapKey, blink::WebCryptoAlgorithmParamsTypeAesCbcParams}, - - // AES-CTR - {blink::WebCryptoAlgorithmIdAesCtr, Decrypt, blink::WebCryptoAlgorithmParamsTypeAesCtrParams}, - {blink::WebCryptoAlgorithmIdAesCtr, Encrypt, blink::WebCryptoAlgorithmParamsTypeAesCtrParams}, - {blink::WebCryptoAlgorithmIdAesCtr, GenerateKey, blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams}, - {blink::WebCryptoAlgorithmIdAesCtr, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdAesCtr, UnwrapKey, blink::WebCryptoAlgorithmParamsTypeAesCtrParams}, - {blink::WebCryptoAlgorithmIdAesCtr, WrapKey, blink::WebCryptoAlgorithmParamsTypeAesCtrParams}, - - // HMAC - {blink::WebCryptoAlgorithmIdHmac, Sign, blink::WebCryptoAlgorithmParamsTypeHmacParams}, - {blink::WebCryptoAlgorithmIdHmac, Verify, blink::WebCryptoAlgorithmParamsTypeHmacParams}, - {blink::WebCryptoAlgorithmIdHmac, GenerateKey, blink::WebCryptoAlgorithmParamsTypeHmacKeyParams}, - {blink::WebCryptoAlgorithmIdHmac, ImportKey, blink::WebCryptoAlgorithmParamsTypeHmacParams}, - - // RSASSA-PKCS1-v1_5 - {blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, Sign, blink::WebCryptoAlgorithmParamsTypeRsaSsaParams}, - {blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, Verify, blink::WebCryptoAlgorithmParamsTypeRsaSsaParams}, - {blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, GenerateKey, blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams}, - {blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone}, - - // RSAES-PKCS1-v1_5 - {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, Encrypt, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, Decrypt, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, GenerateKey, blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams}, - {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, WrapKey, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, UnwrapKey, blink::WebCryptoAlgorithmParamsTypeNone}, - - // SHA-* - {blink::WebCryptoAlgorithmIdSha1, Digest, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdSha224, Digest, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdSha256, Digest, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdSha384, Digest, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdSha512, Digest, blink::WebCryptoAlgorithmParamsTypeNone}, - - // AES-KW - {blink::WebCryptoAlgorithmIdAesKw, GenerateKey, blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams}, - {blink::WebCryptoAlgorithmIdAesKw, ImportKey, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdAesKw, UnwrapKey, blink::WebCryptoAlgorithmParamsTypeNone}, - {blink::WebCryptoAlgorithmIdAesKw, WrapKey, blink::WebCryptoAlgorithmParamsTypeNone}, -}; +#if ASSERT_ENABLED -// This structure describes an algorithm and its supported operations. -struct AlgorithmInfo { - AlgorithmInfo() - : algorithmName(0) - { - for (size_t i = 0; i < WTF_ARRAY_LENGTH(paramsForOperation); ++i) - paramsForOperation[i] = UnsupportedOp; +// Essentially std::is_sorted() (however that function is new to C++11). +template <typename Iterator> +bool isSorted(Iterator begin, Iterator end) +{ + if (begin == end) + return true; + + Iterator prev = begin; + Iterator cur = begin + 1; + + while (cur != end) { + if (*cur < *prev) + return false; + cur++; + prev++; } - blink::WebCryptoAlgorithmId algorithmId; - const char* algorithmName; - AlgorithmParamsForOperation paramsForOperation[LastAlgorithmOperation + 1]; -}; + return true; +} -// AlgorithmRegistry enumerates each of the different algorithms and its -// parameters. This describes the same information as the static tables above, -// but in a more convenient runtime form. -class AlgorithmRegistry { -public: - static AlgorithmRegistry& instance(); +bool AlgorithmNameMapping::operator<(const AlgorithmNameMapping& o) const +{ + if (algorithmNameLength < o.algorithmNameLength) + return true; + if (algorithmNameLength > o.algorithmNameLength) + return false; - const AlgorithmInfo* lookupAlgorithmByName(const String&) const; - const AlgorithmInfo* lookupAlgorithmById(blink::WebCryptoAlgorithmId) const; + for (size_t i = 0; i < algorithmNameLength; ++i) { + size_t reverseIndex = algorithmNameLength - i - 1; + char c1 = algorithmName[reverseIndex]; + char c2 = o.algorithmName[reverseIndex]; -private: - AlgorithmRegistry(); + if (c1 < c2) + return true; + if (c1 > c2) + return false; + } - // Algorithm name to ID. - typedef HashMap<String, blink::WebCryptoAlgorithmId, CaseFoldingHash> AlgorithmNameToIdMap; - AlgorithmNameToIdMap m_algorithmNameToId; + return false; +} - // Algorithm ID to information. - AlgorithmInfo m_algorithms[blink::NumberOfWebCryptoAlgorithmId]; -}; +bool verifyAlgorithmNameMappings(const AlgorithmNameMapping* begin, const AlgorithmNameMapping* end) +{ + for (const AlgorithmNameMapping* it = begin; it != end; ++it) { + if (it->algorithmNameLength != strlen(it->algorithmName)) + return false; + String str(it->algorithmName, it->algorithmNameLength); + if (!str.containsOnlyASCII()) + return false; + if (str.upper() != str) + return false; + } + + return isSorted(begin, end); +} +#endif -AlgorithmRegistry& AlgorithmRegistry::instance() +template <typename CharType> +bool algorithmNameComparator(const AlgorithmNameMapping& a, StringImpl* b) { - DEFINE_STATIC_LOCAL(AlgorithmRegistry, registry, ()); - return registry; + if (a.algorithmNameLength < b->length()) + return true; + if (a.algorithmNameLength > b->length()) + return false; + + // Because the algorithm names contain many common prefixes, it is better + // to compare starting at the end of the string. + for (size_t i = 0; i < a.algorithmNameLength; ++i) { + size_t reverseIndex = a.algorithmNameLength - i - 1; + CharType c1 = a.algorithmName[reverseIndex]; + CharType c2 = b->getCharacters<CharType>()[reverseIndex]; + if (!isASCII(c2)) + return false; + c2 = toASCIIUpper(c2); + + if (c1 < c2) + return true; + if (c1 > c2) + return false; + } + + return false; } -const AlgorithmInfo* AlgorithmRegistry::lookupAlgorithmByName(const String& algorithmName) const +bool lookupAlgorithmIdByName(const String& algorithmName, blink::WebCryptoAlgorithmId& id) { - AlgorithmNameToIdMap::const_iterator it = m_algorithmNameToId.find(algorithmName); - if (it == m_algorithmNameToId.end()) - return 0; - return lookupAlgorithmById(it->value); + const AlgorithmNameMapping* begin = algorithmNameMappings; + const AlgorithmNameMapping* end = algorithmNameMappings + WTF_ARRAY_LENGTH(algorithmNameMappings); + + ASSERT(verifyAlgorithmNameMappings(begin, end)); + + const AlgorithmNameMapping* it; + if (algorithmName.impl()->is8Bit()) + it = std::lower_bound(begin, end, algorithmName.impl(), &algorithmNameComparator<LChar>); + else + it = std::lower_bound(begin, end, algorithmName.impl(), &algorithmNameComparator<UChar>); + + if (it == end) + return false; + + if (it->algorithmNameLength != algorithmName.length() || !equalIgnoringCase(algorithmName, it->algorithmName)) + return false; + + id = it->algorithmId; + return true; } -const AlgorithmInfo* AlgorithmRegistry::lookupAlgorithmById(blink::WebCryptoAlgorithmId algorithmId) const +void setSyntaxError(const String& message, AlgorithmError* error) { - ASSERT(algorithmId >= 0 && algorithmId < WTF_ARRAY_LENGTH(m_algorithms)); - return &m_algorithms[algorithmId]; + error->errorType = blink::WebCryptoErrorTypeSyntax; + error->errorDetails = message; } -AlgorithmRegistry::AlgorithmRegistry() +void setNotSupportedError(const String& message, AlgorithmError* error) { - for (size_t i = 0; i < WTF_ARRAY_LENGTH(algorithmNameMappings); ++i) { - const AlgorithmNameMapping& mapping = algorithmNameMappings[i]; - m_algorithmNameToId.add(mapping.algorithmName, mapping.algorithmId); - m_algorithms[mapping.algorithmId].algorithmName = mapping.algorithmName; - m_algorithms[mapping.algorithmId].algorithmId = mapping.algorithmId; - } + error->errorType = blink::WebCryptoErrorTypeNotSupported; + error->errorDetails = message; +} - for (size_t i = 0; i < WTF_ARRAY_LENGTH(operationParamsMappings); ++i) { - const OperationParamsMapping& mapping = operationParamsMappings[i]; - m_algorithms[mapping.algorithmId].paramsForOperation[mapping.operation] = mapping.params; - } +void setDataError(const String& message, AlgorithmError* error) +{ + error->errorType = blink::WebCryptoErrorTypeData; + error->errorDetails = message; } -// ExceptionContext holds a stack of string literals which describe what was -// happening at the time the exception was thrown. This is helpful because +// ErrorContext holds a stack of string literals which describe what was +// happening at the time the error occurred. This is helpful because // parsing of the algorithm dictionary can be recursive and it is difficult to -// tell what went wrong from the exception type alone (TypeError). -class ExceptionContext { +// tell what went wrong from a failure alone. +class ErrorContext { public: - explicit ExceptionContext(AlgorithmOperation op) - : m_op(op) + void add(const char* message) { + m_messages.append(message); } - void add(const char* message) + void removeLast() { - m_messages.append(message); + m_messages.removeLast(); } // Join all of the string literals into a single String. @@ -243,47 +243,94 @@ public: String toString(const char* message) const { - ExceptionContext stack(*this); + ErrorContext stack(*this); stack.add(message); return stack.toString(); } String toString(const char* message1, const char* message2) const { - ExceptionContext stack(*this); + ErrorContext stack(*this); stack.add(message1); stack.add(message2); return stack.toString(); } private: - AlgorithmOperation m_op; - // This inline size is large enough to avoid having to grow the Vector in // the majority of cases (up to 1 nested algorithm identifier). Vector<const char*, 10> m_messages; }; -bool getArrayBufferView(const Dictionary& raw, const char* propertyName, RefPtr<ArrayBufferView>& buffer, const ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; +// +// FIXME: Currently only supports ArrayBufferView. +bool getOptionalCryptoOperationData(const Dictionary& raw, const char* propertyName, bool& hasProperty, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, AlgorithmError* error) { - if (!raw.get(propertyName, buffer) || !buffer) { - exceptionState.throwTypeError(context.toString(propertyName, "Missing or not a ArrayBufferView")); + if (!raw.get(propertyName, buffer)) { + hasProperty = false; + return true; + } + + hasProperty = true; + + if (!buffer) { + setSyntaxError(context.toString(propertyName, "Not an ArrayBufferView"), error); return false; } + return true; } -bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; +// +// FIXME: Currently only supports ArrayBufferView. +bool getCryptoOperationData(const Dictionary& raw, const char* propertyName, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, AlgorithmError* error) { + bool hasProperty; + bool ok = getOptionalCryptoOperationData(raw, propertyName, hasProperty, buffer, context, error); + if (!hasProperty) { + setSyntaxError(context.toString(propertyName, "Missing required property"), error); + return false; + } + return ok; +} + +bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, AlgorithmError* error) +{ + if (!raw.get(propertyName, array) || !array) { + setSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), error); + return false; + } + return true; +} + +// Defined by the WebCrypto spec as: +// +// typedef Uint8Array BigInteger; +bool getBigInteger(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, AlgorithmError* error) +{ + if (!getUint8Array(raw, propertyName, array, context, error)) + return false; + + if (!array->byteLength()) { + setSyntaxError(context.toString(propertyName, "BigInteger should not be empty"), error); + return false; + } + if (!raw.get(propertyName, array) || !array) { - exceptionState.throwTypeError(context.toString(propertyName, "Missing or not a Uint8Array")); + setSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), error); return false; } return true; } // Gets an integer according to WebIDL's [EnforceRange]. -bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& hasProperty, double& value, double minValue, double maxValue, const ExceptionContext& context, ExceptionState& exceptionState) +bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& hasProperty, double& value, double minValue, double maxValue, const ErrorContext& context, AlgorithmError* error) { double number; bool ok = raw.get(propertyName, number, hasProperty); @@ -292,14 +339,14 @@ bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& h return true; if (!ok || std::isnan(number)) { - exceptionState.throwTypeError(context.toString(propertyName, "Is not a number")); + setSyntaxError(context.toString(propertyName, "Is not a number"), error); return false; } number = trunc(number); if (std::isinf(number) || number < minValue || number > maxValue) { - exceptionState.throwTypeError(context.toString(propertyName, "Outside of numeric range")); + setSyntaxError(context.toString(propertyName, "Outside of numeric range"), error); return false; } @@ -307,65 +354,70 @@ bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& h return true; } -bool getInteger(const Dictionary& raw, const char* propertyName, double& value, double minValue, double maxValue, const ExceptionContext& context, ExceptionState& exceptionState) +bool getInteger(const Dictionary& raw, const char* propertyName, double& value, double minValue, double maxValue, const ErrorContext& context, AlgorithmError* error) { bool hasProperty; - if (!getOptionalInteger(raw, propertyName, hasProperty, value, minValue, maxValue, context, exceptionState)) + if (!getOptionalInteger(raw, propertyName, hasProperty, value, minValue, maxValue, context, error)) return false; if (!hasProperty) { - exceptionState.throwTypeError(context.toString(propertyName, "Missing required property")); + setSyntaxError(context.toString(propertyName, "Missing required property"), error); return false; } return true; } -bool getUint32(const Dictionary& raw, const char* propertyName, uint32_t& value, const ExceptionContext& context, ExceptionState& exceptionState) +bool getUint32(const Dictionary& raw, const char* propertyName, uint32_t& value, const ErrorContext& context, AlgorithmError* error) { double number; - if (!getInteger(raw, propertyName, number, 0, 0xFFFFFFFF, context, exceptionState)) + if (!getInteger(raw, propertyName, number, 0, 0xFFFFFFFF, context, error)) return false; value = number; return true; } -bool getUint16(const Dictionary& raw, const char* propertyName, uint16_t& value, const ExceptionContext& context, ExceptionState& exceptionState) +bool getUint16(const Dictionary& raw, const char* propertyName, uint16_t& value, const ErrorContext& context, AlgorithmError* error) { double number; - if (!getInteger(raw, propertyName, number, 0, 0xFFFF, context, exceptionState)) + if (!getInteger(raw, propertyName, number, 0, 0xFFFF, context, error)) return false; value = number; return true; } -bool getUint8(const Dictionary& raw, const char* propertyName, uint8_t& value, const ExceptionContext& context, ExceptionState& exceptionState) +bool getUint8(const Dictionary& raw, const char* propertyName, uint8_t& value, const ErrorContext& context, AlgorithmError* error) { double number; - if (!getInteger(raw, propertyName, number, 0, 0xFF, context, exceptionState)) + if (!getInteger(raw, propertyName, number, 0, 0xFF, context, error)) return false; value = number; return true; } -bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& hasValue, uint32_t& value, const ExceptionContext& context, ExceptionState& exceptionState) +bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& hasValue, uint32_t& value, const ErrorContext& context, AlgorithmError* error) { double number; - if (!getOptionalInteger(raw, propertyName, hasValue, number, 0, 0xFFFFFFFF, context, exceptionState)) + if (!getOptionalInteger(raw, propertyName, hasValue, number, 0, 0xFFFFFFFF, context, error)) return false; if (hasValue) value = number; return true; } -bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// dictionary AesCbcParams : Algorithm { +// CryptoOperationData iv; +// }; +bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) { RefPtr<ArrayBufferView> iv; - if (!getArrayBufferView(raw, "iv", iv, context, exceptionState)) + if (!getCryptoOperationData(raw, "iv", iv, context, error)) return false; if (iv->byteLength() != 16) { - exceptionState.throwTypeError(context.toString("iv", "Must be 16 bytes")); + setDataError(context.toString("iv", "Must be 16 bytes"), error); return false; } @@ -373,187 +425,305 @@ bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmPa return true; } -bool parseAesKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// dictionary AesKeyGenParams : Algorithm { +// [EnforceRange] unsigned short length; +// }; +bool parseAesKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) { uint16_t length; - if (!getUint16(raw, "length", length, context, exceptionState)) + if (!getUint16(raw, "length", length, context, error)) return false; params = adoptPtr(new blink::WebCryptoAesKeyGenParams(length)); return true; } -bool normalizeAlgorithm(const Dictionary&, AlgorithmOperation, blink::WebCryptoAlgorithm&, ExceptionContext, ExceptionState&); +bool parseAlgorithm(const Dictionary&, blink::WebCryptoOperation, blink::WebCryptoAlgorithm&, ErrorContext, AlgorithmError*); -bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ExceptionContext context, ExceptionState& exceptionState) +bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ErrorContext context, AlgorithmError* error) { Dictionary rawHash; if (!raw.get("hash", rawHash)) { - exceptionState.throwTypeError(context.toString("hash", "Missing or not a dictionary")); + setSyntaxError(context.toString("hash", "Missing or not a dictionary"), error); return false; } context.add("hash"); - return normalizeAlgorithm(rawHash, Digest, hash, context, exceptionState); + return parseAlgorithm(rawHash, blink::WebCryptoOperationDigest, hash, context, error); } -bool parseHmacParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// dictionary HmacImportParams : Algorithm { +// AlgorithmIdentifier hash; +// }; +bool parseHmacImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) { blink::WebCryptoAlgorithm hash; - if (!parseHash(raw, hash, context, exceptionState)) + if (!parseHash(raw, hash, context, error)) return false; - params = adoptPtr(new blink::WebCryptoHmacParams(hash)); + params = adoptPtr(new blink::WebCryptoHmacImportParams(hash)); return true; } -bool parseHmacKeyParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// dictionary HmacKeyGenParams : Algorithm { +// AlgorithmIdentifier hash; +// // The length (in bits) of the key to generate. If unspecified, the +// // recommended length will be used, which is the size of the associated hash function's block +// // size. +// unsigned long length; +// }; +bool parseHmacKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) { blink::WebCryptoAlgorithm hash; - if (!parseHash(raw, hash, context, exceptionState)) + if (!parseHash(raw, hash, context, error)) return false; bool hasLength; uint32_t length = 0; - if (!getOptionalUint32(raw, "length", hasLength, length, context, exceptionState)) + if (!getOptionalUint32(raw, "length", hasLength, length, context, error)) return false; - params = adoptPtr(new blink::WebCryptoHmacKeyParams(hash, hasLength, length)); + params = adoptPtr(new blink::WebCryptoHmacKeyGenParams(hash, hasLength, length)); return true; } -bool parseRsaSsaParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// dictionary RsaHashedImportParams { +// AlgorithmIdentifier hash; +// }; +bool parseRsaHashedImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) { blink::WebCryptoAlgorithm hash; - if (!parseHash(raw, hash, context, exceptionState)) + if (!parseHash(raw, hash, context, error)) return false; - params = adoptPtr(new blink::WebCryptoRsaSsaParams(hash)); + params = adoptPtr(new blink::WebCryptoRsaHashedImportParams(hash)); return true; } -bool parseRsaKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// dictionary RsaHashedKeyGenParams : RsaKeyGenParams { +// AlgorithmIdentifier hash; +// }; +// +// dictionary RsaKeyGenParams : Algorithm { +// unsigned long modulusLength; +// BigInteger publicExponent; +// }; +bool parseRsaHashedKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) { uint32_t modulusLength; - if (!getUint32(raw, "modulusLength", modulusLength, context, exceptionState)) + if (!getUint32(raw, "modulusLength", modulusLength, context, error)) return false; RefPtr<Uint8Array> publicExponent; - if (!getUint8Array(raw, "publicExponent", publicExponent, context, exceptionState)) + if (!getBigInteger(raw, "publicExponent", publicExponent, context, error)) return false; - params = adoptPtr(new blink::WebCryptoRsaKeyGenParams(modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength())); + blink::WebCryptoAlgorithm hash; + if (!parseHash(raw, hash, context, error)) + return false; + + params = adoptPtr(new blink::WebCryptoRsaHashedKeyGenParams(hash, modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength())); return true; } -bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ExceptionContext& context, ExceptionState& es) +// Defined by the WebCrypto spec as: +// +// dictionary AesCtrParams : Algorithm { +// CryptoOperationData counter; +// [EnforceRange] octet length; +// }; +bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) { - RefPtr<Uint8Array> counter; - if (!getUint8Array(raw, "counter", counter, context, es)) + RefPtr<ArrayBufferView> counter; + if (!getCryptoOperationData(raw, "counter", counter, context, error)) return false; uint8_t length; - if (!getUint8(raw, "length", length, context, es)) + if (!getUint8(raw, "length", length, context, error)) return false; params = adoptPtr(new blink::WebCryptoAesCtrParams(length, static_cast<const unsigned char*>(counter->baseAddress()), counter->byteLength())); return true; } -bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParamsType type, OwnPtr<blink::WebCryptoAlgorithmParams>& params, ExceptionContext& context, ExceptionState& exceptionState) +// Defined by the WebCrypto spec as: +// +// dictionary AesGcmParams : Algorithm { +// CryptoOperationData iv; +// CryptoOperationData? additionalData; +// [EnforceRange] octet? tagLength; // May be 0-128 +// } +bool parseAesGcmParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) +{ + RefPtr<ArrayBufferView> iv; + if (!getCryptoOperationData(raw, "iv", iv, context, error)) + return false; + + bool hasAdditionalData; + RefPtr<ArrayBufferView> additionalData; + if (!getOptionalCryptoOperationData(raw, "additionalData", hasAdditionalData, additionalData, context, error)) + return false; + + double tagLength; + bool hasTagLength; + if (!getOptionalInteger(raw, "tagLength", hasTagLength, tagLength, 0, 128, context, error)) + return false; + + const unsigned char* ivStart = static_cast<const unsigned char*>(iv->baseAddress()); + unsigned ivLength = iv->byteLength(); + + const unsigned char* additionalDataStart = hasAdditionalData ? static_cast<const unsigned char*>(additionalData->baseAddress()) : 0; + unsigned additionalDataLength = hasAdditionalData ? additionalData->byteLength() : 0; + + params = adoptPtr(new blink::WebCryptoAesGcmParams(ivStart, ivLength, hasAdditionalData, additionalDataStart, additionalDataLength, hasTagLength, tagLength)); + return true; +} + +// Defined by the WebCrypto spec as: +// +// dictionary RsaOaepParams : Algorithm { +// CryptoOperationData? label; +// }; +bool parseRsaOaepParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, AlgorithmError* error) +{ + bool hasLabel; + RefPtr<ArrayBufferView> label; + if (!getOptionalCryptoOperationData(raw, "label", hasLabel, label, context, error)) + return false; + + const unsigned char* labelStart = hasLabel ? static_cast<const unsigned char*>(label->baseAddress()) : 0; + unsigned labelLength = hasLabel ? label->byteLength() : 0; + + params = adoptPtr(new blink::WebCryptoRsaOaepParams(hasLabel, labelStart, labelLength)); + return true; +} + +bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParamsType type, OwnPtr<blink::WebCryptoAlgorithmParams>& params, ErrorContext& context, AlgorithmError* error) { switch (type) { case blink::WebCryptoAlgorithmParamsTypeNone: return true; case blink::WebCryptoAlgorithmParamsTypeAesCbcParams: context.add("AesCbcParams"); - return parseAesCbcParams(raw, params, context, exceptionState); + return parseAesCbcParams(raw, params, context, error); case blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams: context.add("AesKeyGenParams"); - return parseAesKeyGenParams(raw, params, context, exceptionState); - case blink::WebCryptoAlgorithmParamsTypeHmacParams: - context.add("HmacParams"); - return parseHmacParams(raw, params, context, exceptionState); - case blink::WebCryptoAlgorithmParamsTypeHmacKeyParams: - context.add("HmacKeyParams"); - return parseHmacKeyParams(raw, params, context, exceptionState); - case blink::WebCryptoAlgorithmParamsTypeRsaSsaParams: - context.add("RsaSSaParams"); - return parseRsaSsaParams(raw, params, context, exceptionState); - case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams: - context.add("RsaKeyGenParams"); - return parseRsaKeyGenParams(raw, params, context, exceptionState); + return parseAesKeyGenParams(raw, params, context, error); + case blink::WebCryptoAlgorithmParamsTypeHmacImportParams: + context.add("HmacImportParams"); + return parseHmacImportParams(raw, params, context, error); + case blink::WebCryptoAlgorithmParamsTypeHmacKeyGenParams: + context.add("HmacKeyGenParams"); + return parseHmacKeyGenParams(raw, params, context, error); + case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams: + context.add("RsaHashedKeyGenParams"); + return parseRsaHashedKeyGenParams(raw, params, context, error); + case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams: + context.add("RsaHashedImportParams"); + return parseRsaHashedImportParams(raw, params, context, error); case blink::WebCryptoAlgorithmParamsTypeAesCtrParams: context.add("AesCtrParams"); - return parseAesCtrParams(raw, params, context, exceptionState); + return parseAesCtrParams(raw, params, context, error); case blink::WebCryptoAlgorithmParamsTypeAesGcmParams: + context.add("AesGcmParams"); + return parseAesGcmParams(raw, params, context, error); case blink::WebCryptoAlgorithmParamsTypeRsaOaepParams: - // TODO - notImplemented(); + context.add("RsaOaepParams"); + return parseRsaOaepParams(raw, params, context, error); break; } ASSERT_NOT_REACHED(); return false; } -const AlgorithmInfo* algorithmInfo(const Dictionary& raw, const ExceptionContext& context, ExceptionState& exceptionState) +const char* operationToString(blink::WebCryptoOperation op) { + switch (op) { + case blink::WebCryptoOperationEncrypt: + return "encrypt"; + case blink::WebCryptoOperationDecrypt: + return "decrypt"; + case blink::WebCryptoOperationSign: + return "sign"; + case blink::WebCryptoOperationVerify: + return "verify"; + case blink::WebCryptoOperationDigest: + return "digest"; + case blink::WebCryptoOperationGenerateKey: + return "generateKey"; + case blink::WebCryptoOperationImportKey: + return "importKey"; + case blink::WebCryptoOperationDeriveKey: + return "deriveKey"; + case blink::WebCryptoOperationDeriveBits: + return "deriveBits"; + case blink::WebCryptoOperationWrapKey: + return "wrapKey"; + case blink::WebCryptoOperationUnwrapKey: + return "unwrapKey"; + } + return 0; +} + +bool parseAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, ErrorContext context, AlgorithmError* error) +{ + context.add("Algorithm"); + if (!raw.isObject()) { - exceptionState.throwTypeError(context.toString("Not an object")); - return 0; + setSyntaxError(context.toString("Not an object"), error); + return false; } String algorithmName; if (!raw.get("name", algorithmName)) { - exceptionState.throwTypeError(context.toString("name", "Missing or not a string")); - return 0; + setSyntaxError(context.toString("name", "Missing or not a string"), error); + return false; } - const AlgorithmInfo* info = AlgorithmRegistry::instance().lookupAlgorithmByName(algorithmName); - if (!info) { - exceptionState.throwDOMException(NotSupportedError, context.toString("Unrecognized algorithm name")); - return 0; + blink::WebCryptoAlgorithmId algorithmId; + if (!lookupAlgorithmIdByName(algorithmName, algorithmId)) { + // FIXME: The spec says to return a SyntaxError if the input contains + // any non-ASCII characters. + setNotSupportedError(context.toString("Unrecognized name"), error); + return false; } - return info; -} - -// This implementation corresponds with: -// http://www.w3.org/TR/WebCryptoAPI/#algorithm-normalizing-rules -bool normalizeAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, ExceptionContext context, ExceptionState& exceptionState) -{ - context.add("Algorithm"); - - const AlgorithmInfo* info = algorithmInfo(raw, context, exceptionState); - if (!info) - return false; + // Remove the "Algorithm:" prefix for all subsequent errors. + context.removeLast(); - context.add(info->algorithmName); + const blink::WebCryptoAlgorithmInfo* algorithmInfo = blink::WebCryptoAlgorithm::lookupAlgorithmInfo(algorithmId); - if (info->paramsForOperation[op] == UnsupportedOp) { - exceptionState.throwDOMException(NotSupportedError, context.toString("Unsupported operation")); + if (algorithmInfo->operationToParamsType[op] == blink::WebCryptoAlgorithmInfo::Undefined) { + context.add(algorithmInfo->name); + setNotSupportedError(context.toString("Unsupported operation", operationToString(op)), error); return false; } - blink::WebCryptoAlgorithmParamsType paramsType = static_cast<blink::WebCryptoAlgorithmParamsType>(info->paramsForOperation[op]); + blink::WebCryptoAlgorithmParamsType paramsType = static_cast<blink::WebCryptoAlgorithmParamsType>(algorithmInfo->operationToParamsType[op]); + OwnPtr<blink::WebCryptoAlgorithmParams> params; - if (!parseAlgorithmParams(raw, paramsType, params, context, exceptionState)) + if (!parseAlgorithmParams(raw, paramsType, params, context, error)) return false; - algorithm = blink::WebCryptoAlgorithm(info->algorithmId, params.release()); + algorithm = blink::WebCryptoAlgorithm(algorithmId, params.release()); return true; } } // namespace -bool normalizeAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, ExceptionState& exceptionState) -{ - return normalizeAlgorithm(raw, op, algorithm, ExceptionContext(op), exceptionState); -} - -const char* algorithmIdToName(blink::WebCryptoAlgorithmId id) +bool normalizeAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, AlgorithmError* error) { - return AlgorithmRegistry::instance().lookupAlgorithmById(id)->algorithmName; + return parseAlgorithm(raw, op, algorithm, ErrorContext(), error); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.h b/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.h index 9565eb72b34..14efbbb5ef7 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/NormalizeAlgorithm.h @@ -31,38 +31,33 @@ #ifndef NormalizeAlgorithm_h #define NormalizeAlgorithm_h +#include "public/platform/WebCrypto.h" #include "public/platform/WebCryptoAlgorithm.h" +#include "public/platform/WebString.h" #include "wtf/Assertions.h" - -namespace blink { class WebCryptoAlgorithm; } +#include "wtf/Forward.h" namespace WebCore { class Dictionary; -class ExceptionState; -enum AlgorithmOperation { - Encrypt, - Decrypt, - Sign, - Verify, - Digest, - GenerateKey, - ImportKey, - DeriveKey, - WrapKey, - UnwrapKey, - // <---- End of list (keep this up-to-date) - LastAlgorithmOperation = UnwrapKey, +struct AlgorithmError { + blink::WebCryptoErrorType errorType; + blink::WebString errorDetails; }; -// Normalizes an algorithm identifier (dictionary) into a WebCryptoAlgorithm. If -// normalization fails then returns false and sets the ExceptionState. -bool normalizeAlgorithm(const Dictionary&, AlgorithmOperation, blink::WebCryptoAlgorithm&, ExceptionState&) WARN_UNUSED_RETURN; - -// Returns a null-terminated C-string literal. Caller can assume the pointer -// will be valid for the program's entire runtime. -const char* algorithmIdToName(blink::WebCryptoAlgorithmId); +// Converts a javascript Dictionary to a WebCryptoAlgorithm object. +// +// This corresponds with "normalizing" [1] the algorithm, and then validating +// the expected parameters for the algorithm/operation combination. +// +// On success returns true and sets the WebCryptoAlgorithm. +// +// On failure normalizeAlgorithm returns false and sets the AlgorithmError with +// a error type and a (non-localized) debug string. +// +// [1] http://www.w3.org/TR/WebCryptoAPI/#algorithm-normalizing-rules +bool normalizeAlgorithm(const Dictionary&, blink::WebCryptoOperation, blink::WebCryptoAlgorithm&, AlgorithmError*) WARN_UNUSED_RETURN; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/HmacParams.cpp b/chromium/third_party/WebKit/Source/modules/crypto/RsaHashedKeyAlgorithm.cpp index eb82c20505a..a6dbdba7c3b 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/HmacParams.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/RsaHashedKeyAlgorithm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,23 +29,34 @@ */ #include "config.h" -#include "modules/crypto/HmacParams.h" +#include "modules/crypto/RsaHashedKeyAlgorithm.h" -#include "public/platform/WebCryptoAlgorithmParams.h" +#include "modules/crypto/NormalizeAlgorithm.h" +#include "wtf/text/WTFString.h" namespace WebCore { -Algorithm* HmacParams::hash() +RsaHashedKeyAlgorithm* RsaHashedKeyAlgorithm::create(const blink::WebCryptoKeyAlgorithm& algorithm) +{ + return new RsaHashedKeyAlgorithm(algorithm); +} + +KeyAlgorithm* RsaHashedKeyAlgorithm::hash() { if (!m_hash) - m_hash = Algorithm::create(m_algorithm.hmacParams()->hash()); + m_hash = KeyAlgorithm::createHash(m_algorithm.rsaHashedParams()->hash()); return m_hash.get(); } -HmacParams::HmacParams(const blink::WebCryptoAlgorithm& algorithm) - : Algorithm(algorithm) +void RsaHashedKeyAlgorithm::trace(Visitor* visitor) +{ + visitor->trace(m_hash); + RsaKeyAlgorithm::trace(visitor); +} + +RsaHashedKeyAlgorithm::RsaHashedKeyAlgorithm(const blink::WebCryptoKeyAlgorithm& algorithm) + : RsaKeyAlgorithm(algorithm) { - ASSERT(algorithm.hmacParams()); ScriptWrappable::init(this); } diff --git a/chromium/third_party/WebKit/Source/modules/crypto/HmacParams.h b/chromium/third_party/WebKit/Source/modules/crypto/RsaHashedKeyAlgorithm.h index eb85d091552..f537a923888 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/HmacParams.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/RsaHashedKeyAlgorithm.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,26 +28,29 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef HmacParams_h -#define HmacParams_h +#ifndef RsaHashedKeyAlgorithm_h +#define RsaHashedKeyAlgorithm_h -#include "modules/crypto/Algorithm.h" -#include "wtf/RefPtr.h" +#include "modules/crypto/RsaKeyAlgorithm.h" namespace WebCore { -class HmacParams : public Algorithm { +class RsaHashedKeyAlgorithm : public RsaKeyAlgorithm { public: - static PassRefPtr<HmacParams> create(const blink::WebCryptoAlgorithm& algorithm) { return adoptRef(new HmacParams(algorithm)); } + static RsaHashedKeyAlgorithm* create(const blink::WebCryptoKeyAlgorithm&); - Algorithm* hash(); + KeyAlgorithm* hash(); + + virtual void trace(Visitor*) OVERRIDE; private: - explicit HmacParams(const blink::WebCryptoAlgorithm&); + explicit RsaHashedKeyAlgorithm(const blink::WebCryptoKeyAlgorithm&); - RefPtr<Algorithm> m_hash; + Member<KeyAlgorithm> m_hash; }; +DEFINE_KEY_ALGORITHM_TYPE_CASTS(RsaHashedKeyAlgorithm); + } // namespace WebCore #endif diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesKeyGenParams.idl b/chromium/third_party/WebKit/Source/modules/crypto/RsaHashedKeyAlgorithm.idl index 2158208404c..28b765dc420 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesKeyGenParams.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/RsaHashedKeyAlgorithm.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,7 +29,7 @@ */ [ - NoInterfaceObject, -] interface AesKeyGenParams : Algorithm { - readonly attribute unsigned short length; + NoInterfaceObject +] interface RsaHashedKeyAlgorithm : RsaKeyAlgorithm { + readonly attribute KeyAlgorithm hash; }; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyGenParams.cpp b/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyAlgorithm.cpp index cdfc1e596da..301101a9502 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyGenParams.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyAlgorithm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,30 +29,47 @@ */ #include "config.h" -#include "modules/crypto/RsaKeyGenParams.h" +#include "modules/crypto/RsaKeyAlgorithm.h" -#include "public/platform/WebCryptoAlgorithmParams.h" +#include "modules/crypto/NormalizeAlgorithm.h" +#include "public/platform/WebVector.h" +#include "wtf/Uint8Array.h" +#include "wtf/text/WTFString.h" namespace WebCore { -unsigned RsaKeyGenParams::modulusLength() const +RsaKeyAlgorithm::~RsaKeyAlgorithm() { - return m_algorithm.rsaKeyGenParams()->modulusLengthBits(); } -Uint8Array* RsaKeyGenParams::publicExponent() +RsaKeyAlgorithm* RsaKeyAlgorithm::create(const blink::WebCryptoKeyAlgorithm& algorithm) { - if (!m_publicExponent) { - const blink::WebVector<unsigned char>& exponent = m_algorithm.rsaKeyGenParams()->publicExponent(); + return new RsaKeyAlgorithm(algorithm); +} + +unsigned RsaKeyAlgorithm::modulusLength() +{ + return m_algorithm.rsaHashedParams()->modulusLengthBits(); +} + +Uint8Array* RsaKeyAlgorithm::publicExponent() +{ + if (!m_publicExponent.get()) { + const blink::WebVector<unsigned char>& exponent = m_algorithm.rsaHashedParams()->publicExponent(); m_publicExponent = Uint8Array::create(exponent.data(), exponent.size()); } return m_publicExponent.get(); } -RsaKeyGenParams::RsaKeyGenParams(const blink::WebCryptoAlgorithm& algorithm) - : Algorithm(algorithm) +void RsaKeyAlgorithm::trace(Visitor* visitor) +{ + KeyAlgorithm::trace(visitor); +} + +RsaKeyAlgorithm::RsaKeyAlgorithm(const blink::WebCryptoKeyAlgorithm& algorithm) + : KeyAlgorithm(algorithm) { - ASSERT(algorithm.rsaKeyGenParams()); + ASSERT(algorithm.rsaHashedParams()); ScriptWrappable::init(this); } diff --git a/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyGenParams.h b/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyAlgorithm.h index 7a44705fc5b..aca0d83d071 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyGenParams.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyAlgorithm.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,25 +28,28 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RsaKeyGenParams_h -#define RsaKeyGenParams_h +#ifndef RsaKeyAlgorithm_h +#define RsaKeyAlgorithm_h -#include "modules/crypto/Algorithm.h" -#include "public/platform/WebCryptoAlgorithm.h" -#include "wtf/Uint8Array.h" +#include "modules/crypto/KeyAlgorithm.h" namespace WebCore { -class RsaKeyGenParams : public Algorithm { +class RsaKeyAlgorithm : public KeyAlgorithm { public: - static PassRefPtr<RsaKeyGenParams> create(const blink::WebCryptoAlgorithm& algorithm) { return adoptRef(new RsaKeyGenParams(algorithm)); } + ~RsaKeyAlgorithm(); - unsigned modulusLength() const; + static RsaKeyAlgorithm* create(const blink::WebCryptoKeyAlgorithm&); + + unsigned modulusLength(); Uint8Array* publicExponent(); -private: - explicit RsaKeyGenParams(const blink::WebCryptoAlgorithm&); + virtual void trace(Visitor*) OVERRIDE; +protected: + explicit RsaKeyAlgorithm(const blink::WebCryptoKeyAlgorithm&); + +private: RefPtr<Uint8Array> m_publicExponent; }; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyAlgorithm.idl b/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyAlgorithm.idl new file mode 100644 index 00000000000..8cf43edbfb9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyAlgorithm.idl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + NoInterfaceObject +] interface RsaKeyAlgorithm : KeyAlgorithm { + readonly attribute unsigned long modulusLength; + readonly attribute Uint8Array publicExponent; +}; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyGenParams.idl b/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyGenParams.idl deleted file mode 100644 index 0ec9d215ff6..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/RsaKeyGenParams.idl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - NoInterfaceObject, -] interface RsaKeyGenParams : Algorithm { - readonly attribute unsigned long modulusLength; - readonly attribute Uint8Array publicExponent; -}; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/RsaSsaParams.idl b/chromium/third_party/WebKit/Source/modules/crypto/RsaSsaParams.idl deleted file mode 100644 index f289529ff8b..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/RsaSsaParams.idl +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - NoInterfaceObject, -] interface RsaSsaParams : Algorithm { - readonly attribute Algorithm hash; -}; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp b/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp index e92c1dbf837..ca705a87c5f 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp @@ -32,11 +32,11 @@ #include "modules/crypto/SubtleCrypto.h" #include "bindings/v8/Dictionary.h" -#include "bindings/v8/ExceptionState.h" -#include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" #include "modules/crypto/CryptoResultImpl.h" #include "modules/crypto/Key.h" #include "modules/crypto/NormalizeAlgorithm.h" +#include "platform/JSONValues.h" #include "public/platform/Platform.h" #include "public/platform/WebCrypto.h" #include "public/platform/WebCryptoAlgorithm.h" @@ -44,57 +44,89 @@ namespace WebCore { -// FIXME: asynchronous completion of CryptoResult. Need to re-enter the -// v8::Context before trying to fulfill the promise, and enable test. +// Seems like the generated bindings should take care of these however it +// currently doesn't. See also http://crbug.com/264520 +static bool ensureNotNull(const ArrayPiece& x, const char* paramName, CryptoResult* result) +{ + if (x.isNull()) { + String message = String("Invalid ") + paramName + String(" argument"); + result->completeWithError(blink::WebCryptoErrorTypeType, blink::WebString(message)); + return false; + } + return true; +} -namespace { +static bool ensureNotNull(Key* key, const char* paramName, CryptoResult* result) +{ + if (!key) { + String message = String("Invalid ") + paramName + String(" argument"); + result->completeWithError(blink::WebCryptoErrorTypeType, blink::WebString(message)); + return false; + } + return true; +} -ScriptPromise startCryptoOperation(const Dictionary& rawAlgorithm, Key* key, AlgorithmOperation operationType, ArrayBufferView* signature, ArrayBufferView* dataBuffer, ExceptionState& exceptionState) +static bool parseAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, CryptoResult* result) { - bool requiresKey = operationType != Digest; + AlgorithmError error; + bool success = normalizeAlgorithm(raw, op, algorithm, &error); + if (!success) + result->completeWithError(error.errorType, error.errorDetails); + return success; +} - // Seems like the generated bindings should take care of these however it - // currently doesn't. See also http://crbugh.com/264520 - if (requiresKey && !key) { - exceptionState.throwTypeError("Invalid key argument"); - return ScriptPromise(); - } - if (operationType == Verify && !signature) { - exceptionState.throwTypeError("Invalid signature argument"); - return ScriptPromise(); - } - if (!dataBuffer) { - exceptionState.throwTypeError("Invalid dataBuffer argument"); - return ScriptPromise(); +static bool canAccessWebCrypto(ScriptState* scriptState, CryptoResult* result) +{ + const SecurityOrigin* origin = scriptState->executionContext()->securityOrigin(); + if (!origin->canAccessFeatureRequiringSecureOrigin()) { + result->completeWithError(blink::WebCryptoErrorTypeNotSupported, "WebCrypto is only supported over secure origins. See http://crbug.com/373032"); + return false; } - blink::WebCryptoAlgorithm algorithm; - if (!normalizeAlgorithm(rawAlgorithm, operationType, algorithm, exceptionState)) - return ScriptPromise(); + return true; +} - if (requiresKey && !key->canBeUsedForAlgorithm(algorithm, operationType, exceptionState)) - return ScriptPromise(); +static ScriptPromise startCryptoOperation(ScriptState* scriptState, const Dictionary& rawAlgorithm, Key* key, blink::WebCryptoOperation operationType, const ArrayPiece& signature, const ArrayPiece& dataBuffer) +{ + RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); + ScriptPromise promise = result->promise(); + + if (!canAccessWebCrypto(scriptState, result.get())) + return promise; - const unsigned char* data = static_cast<const unsigned char*>(dataBuffer->baseAddress()); - unsigned dataSize = dataBuffer->byteLength(); + bool requiresKey = operationType != blink::WebCryptoOperationDigest; - ScriptPromise promise = ScriptPromise::createPending(); - RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(promise); + if (requiresKey && !ensureNotNull(key, "key", result.get())) + return promise; + if (operationType == blink::WebCryptoOperationVerify && !ensureNotNull(signature, "signature", result.get())) + return promise; + if (!ensureNotNull(dataBuffer, "dataBuffer", result.get())) + return promise; + + blink::WebCryptoAlgorithm algorithm; + if (!parseAlgorithm(rawAlgorithm, operationType, algorithm, result.get())) + return promise; + + if (requiresKey && !key->canBeUsedForAlgorithm(algorithm, operationType, result.get())) + return promise; + + const unsigned char* data = dataBuffer.bytes(); + unsigned dataSize = dataBuffer.byteLength(); switch (operationType) { - case Encrypt: + case blink::WebCryptoOperationEncrypt: blink::Platform::current()->crypto()->encrypt(algorithm, key->key(), data, dataSize, result->result()); break; - case Decrypt: + case blink::WebCryptoOperationDecrypt: blink::Platform::current()->crypto()->decrypt(algorithm, key->key(), data, dataSize, result->result()); break; - case Sign: + case blink::WebCryptoOperationSign: blink::Platform::current()->crypto()->sign(algorithm, key->key(), data, dataSize, result->result()); break; - case Verify: - blink::Platform::current()->crypto()->verifySignature(algorithm, key->key(), reinterpret_cast<const unsigned char*>(signature->baseAddress()), signature->byteLength(), data, dataSize, result->result()); + case blink::WebCryptoOperationVerify: + blink::Platform::current()->crypto()->verifySignature(algorithm, key->key(), signature.bytes(), signature.byteLength(), data, dataSize, result->result()); break; - case Digest: + case blink::WebCryptoOperationDigest: blink::Platform::current()->crypto()->digest(algorithm, data, dataSize, result->result()); break; default: @@ -105,178 +137,264 @@ ScriptPromise startCryptoOperation(const Dictionary& rawAlgorithm, Key* key, Alg return promise; } -} // namespace +static bool copyStringProperty(const char* property, const Dictionary& source, JSONObject* destination) +{ + String value; + if (!source.get(property, value)) + return false; + destination->setString(property, value); + return true; +} + +static bool copySequenceOfStringProperty(const char* property, const Dictionary& source, JSONObject* destination) +{ + Vector<String> value; + if (!source.get(property, value)) + return false; + RefPtr<JSONArray> jsonArray = JSONArray::create(); + for (unsigned i = 0; i < value.size(); ++i) + jsonArray->pushString(value[i]); + destination->setArray(property, jsonArray.release()); + return true; +} + +// FIXME: At the time of writing this is not a part of the spec. It is based an +// an unpublished editor's draft for: +// https://www.w3.org/Bugs/Public/show_bug.cgi?id=24963 +// See http://crbug.com/373917. +static bool copyJwkDictionaryToJson(const Dictionary& dict, CString& jsonUtf8, CryptoResult* result) +{ + RefPtr<JSONObject> jsonObject = JSONObject::create(); + + if (!copyStringProperty("kty", dict, jsonObject.get())) { + result->completeWithError(blink::WebCryptoErrorTypeData, "The required JWK property \"kty\" was missing"); + return false; + } + + copyStringProperty("use", dict, jsonObject.get()); + copySequenceOfStringProperty("key_ops", dict, jsonObject.get()); + copyStringProperty("alg", dict, jsonObject.get()); + + bool ext; + if (dict.get("ext", ext)) + jsonObject->setBoolean("ext", ext); + + const char* const propertyNames[] = { "d", "n", "e", "p", "q", "dp", "dq", "qi", "k" }; + for (unsigned i = 0; i < WTF_ARRAY_LENGTH(propertyNames); ++i) + copyStringProperty(propertyNames[i], dict, jsonObject.get()); + + String json = jsonObject->toJSONString(); + jsonUtf8 = json.utf8(); + return true; +} SubtleCrypto::SubtleCrypto() { ScriptWrappable::init(this); } -ScriptPromise SubtleCrypto::encrypt(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* data, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::encrypt(ScriptState* scriptState, const Dictionary& rawAlgorithm, Key* key, const ArrayPiece& data) { - return startCryptoOperation(rawAlgorithm, key, Encrypt, 0, data, exceptionState); + return startCryptoOperation(scriptState, rawAlgorithm, key, blink::WebCryptoOperationEncrypt, ArrayPiece(), data); } -ScriptPromise SubtleCrypto::decrypt(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* data, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::decrypt(ScriptState* scriptState, const Dictionary& rawAlgorithm, Key* key, const ArrayPiece& data) { - return startCryptoOperation(rawAlgorithm, key, Decrypt, 0, data, exceptionState); + return startCryptoOperation(scriptState, rawAlgorithm, key, blink::WebCryptoOperationDecrypt, ArrayPiece(), data); } -ScriptPromise SubtleCrypto::sign(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* data, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::sign(ScriptState* scriptState, const Dictionary& rawAlgorithm, Key* key, const ArrayPiece& data) { - return startCryptoOperation(rawAlgorithm, key, Sign, 0, data, exceptionState); + return startCryptoOperation(scriptState, rawAlgorithm, key, blink::WebCryptoOperationSign, ArrayPiece(), data); } -ScriptPromise SubtleCrypto::verifySignature(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* signature, ArrayBufferView* data, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::verifySignature(ScriptState* scriptState, const Dictionary& rawAlgorithm, Key* key, const ArrayPiece& signature, const ArrayPiece& data) { - return startCryptoOperation(rawAlgorithm, key, Verify, signature, data, exceptionState); + return startCryptoOperation(scriptState, rawAlgorithm, key, blink::WebCryptoOperationVerify, signature, data); } -ScriptPromise SubtleCrypto::digest(const Dictionary& rawAlgorithm, ArrayBufferView* data, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::digest(ScriptState* scriptState, const Dictionary& rawAlgorithm, const ArrayPiece& data) { - return startCryptoOperation(rawAlgorithm, 0, Digest, 0, data, exceptionState); + return startCryptoOperation(scriptState, rawAlgorithm, 0, blink::WebCryptoOperationDigest, ArrayPiece(), data); } -ScriptPromise SubtleCrypto::generateKey(const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::generateKey(ScriptState* scriptState, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) { + RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); + ScriptPromise promise = result->promise(); + + if (!canAccessWebCrypto(scriptState, result.get())) + return promise; + blink::WebCryptoKeyUsageMask keyUsages; - if (!Key::parseUsageMask(rawKeyUsages, keyUsages, exceptionState)) - return ScriptPromise(); + if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get())) + return promise; blink::WebCryptoAlgorithm algorithm; - if (!normalizeAlgorithm(rawAlgorithm, GenerateKey, algorithm, exceptionState)) - return ScriptPromise(); + if (!parseAlgorithm(rawAlgorithm, blink::WebCryptoOperationGenerateKey, algorithm, result.get())) + return promise; - ScriptPromise promise = ScriptPromise::createPending(); - RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(promise); blink::Platform::current()->crypto()->generateKey(algorithm, extractable, keyUsages, result->result()); return promise; } -ScriptPromise SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* keyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& rawFormat, const ArrayPiece& keyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) { + RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); + ScriptPromise promise = result->promise(); + + if (!canAccessWebCrypto(scriptState, result.get())) + return promise; + + if (!ensureNotNull(keyData, "keyData", result.get())) + return promise; + blink::WebCryptoKeyFormat format; - if (!Key::parseFormat(rawFormat, format, exceptionState)) - return ScriptPromise(); + if (!Key::parseFormat(rawFormat, format, result.get())) + return promise; - if (!keyData) { - exceptionState.throwTypeError("Invalid keyData argument"); - return ScriptPromise(); + if (format == blink::WebCryptoKeyFormatJwk) { + result->completeWithError(blink::WebCryptoErrorTypeData, "Key data must be an object for JWK import"); + return promise; } blink::WebCryptoKeyUsageMask keyUsages; - if (!Key::parseUsageMask(rawKeyUsages, keyUsages, exceptionState)) - return ScriptPromise(); + if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get())) + return promise; - // The algorithm is optional. blink::WebCryptoAlgorithm algorithm; - if (!rawAlgorithm.isUndefinedOrNull() && !normalizeAlgorithm(rawAlgorithm, ImportKey, algorithm, exceptionState)) - return ScriptPromise(); - - const unsigned char* keyDataBytes = static_cast<unsigned char*>(keyData->baseAddress()); + if (!parseAlgorithm(rawAlgorithm, blink::WebCryptoOperationImportKey, algorithm, result.get())) + return promise; - ScriptPromise promise = ScriptPromise::createPending(); - RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(promise); - blink::Platform::current()->crypto()->importKey(format, keyDataBytes, keyData->byteLength(), algorithm, extractable, keyUsages, result->result()); + blink::Platform::current()->crypto()->importKey(format, keyData.bytes(), keyData.byteLength(), algorithm, extractable, keyUsages, result->result()); return promise; } -ScriptPromise SubtleCrypto::exportKey(const String& rawFormat, Key* key, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& rawFormat, const Dictionary& keyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) { + RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); + ScriptPromise promise = result->promise(); + + if (!canAccessWebCrypto(scriptState, result.get())) + return promise; + blink::WebCryptoKeyFormat format; - if (!Key::parseFormat(rawFormat, format, exceptionState)) - return ScriptPromise(); + if (!Key::parseFormat(rawFormat, format, result.get())) + return promise; - if (!key) { - exceptionState.throwTypeError("Invalid key argument"); - return ScriptPromise(); + blink::WebCryptoKeyUsageMask keyUsages; + if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get())) + return promise; + + if (format != blink::WebCryptoKeyFormatJwk) { + result->completeWithError(blink::WebCryptoErrorTypeData, "Key data must be a buffer for non-JWK formats"); + return promise; } + blink::WebCryptoAlgorithm algorithm; + if (!parseAlgorithm(rawAlgorithm, blink::WebCryptoOperationImportKey, algorithm, result.get())) + return promise; + + CString jsonUtf8; + if (!copyJwkDictionaryToJson(keyData, jsonUtf8, result.get())) + return promise; + + blink::Platform::current()->crypto()->importKey(format, reinterpret_cast<const unsigned char*>(jsonUtf8.data()), jsonUtf8.length(), algorithm, extractable, keyUsages, result->result()); + return promise; +} + +ScriptPromise SubtleCrypto::exportKey(ScriptState* scriptState, const String& rawFormat, Key* key) +{ + RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); + ScriptPromise promise = result->promise(); + + if (!canAccessWebCrypto(scriptState, result.get())) + return promise; + + if (!ensureNotNull(key, "key", result.get())) + return promise; + + blink::WebCryptoKeyFormat format; + if (!Key::parseFormat(rawFormat, format, result.get())) + return promise; + if (!key->extractable()) { - exceptionState.throwDOMException(NotSupportedError, "key is not extractable"); - return ScriptPromise(); + result->completeWithError(blink::WebCryptoErrorTypeInvalidAccess, "key is not extractable"); + return promise; } - ScriptPromise promise = ScriptPromise::createPending(); - RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(promise); blink::Platform::current()->crypto()->exportKey(format, key->key(), result->result()); return promise; } -ScriptPromise SubtleCrypto::wrapKey(const String& rawFormat, Key* key, Key* wrappingKey, const Dictionary& rawWrapAlgorithm, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::wrapKey(ScriptState* scriptState, const String& rawFormat, Key* key, Key* wrappingKey, const Dictionary& rawWrapAlgorithm) { - blink::WebCryptoKeyFormat format; - if (!Key::parseFormat(rawFormat, format, exceptionState)) - return ScriptPromise(); + RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); + ScriptPromise promise = result->promise(); - if (!key) { - exceptionState.throwTypeError("Invalid key argument"); - return ScriptPromise(); - } + if (!canAccessWebCrypto(scriptState, result.get())) + return promise; - if (!wrappingKey) { - exceptionState.throwTypeError("Invalid wrappingKey argument"); - return ScriptPromise(); - } + if (!ensureNotNull(key, "key", result.get())) + return promise; + + if (!ensureNotNull(wrappingKey, "wrappingKey", result.get())) + return promise; + + blink::WebCryptoKeyFormat format; + if (!Key::parseFormat(rawFormat, format, result.get())) + return promise; blink::WebCryptoAlgorithm wrapAlgorithm; - if (!normalizeAlgorithm(rawWrapAlgorithm, WrapKey, wrapAlgorithm, exceptionState)) - return ScriptPromise(); + if (!parseAlgorithm(rawWrapAlgorithm, blink::WebCryptoOperationWrapKey, wrapAlgorithm, result.get())) + return promise; if (!key->extractable()) { - exceptionState.throwDOMException(NotSupportedError, "key is not extractable"); - return ScriptPromise(); + result->completeWithError(blink::WebCryptoErrorTypeInvalidAccess, "key is not extractable"); + return promise; } - if (!wrappingKey->canBeUsedForAlgorithm(wrapAlgorithm, WrapKey, exceptionState)) - return ScriptPromise(); + if (!wrappingKey->canBeUsedForAlgorithm(wrapAlgorithm, blink::WebCryptoOperationWrapKey, result.get())) + return promise; - ScriptPromise promise = ScriptPromise::createPending(); - RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(promise); blink::Platform::current()->crypto()->wrapKey(format, key->key(), wrappingKey->key(), wrapAlgorithm, result->result()); return promise; } -ScriptPromise SubtleCrypto::unwrapKey(const String& rawFormat, ArrayBufferView* wrappedKey, Key* unwrappingKey, const Dictionary& rawUnwrapAlgorithm, const Dictionary& rawUnwrappedKeyAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionState& exceptionState) +ScriptPromise SubtleCrypto::unwrapKey(ScriptState* scriptState, const String& rawFormat, const ArrayPiece& wrappedKey, Key* unwrappingKey, const Dictionary& rawUnwrapAlgorithm, const Dictionary& rawUnwrappedKeyAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) { - blink::WebCryptoKeyFormat format; - if (!Key::parseFormat(rawFormat, format, exceptionState)) - return ScriptPromise(); + RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); + ScriptPromise promise = result->promise(); - if (!wrappedKey) { - exceptionState.throwTypeError("Invalid wrappedKey argument"); - return ScriptPromise(); - } + if (!canAccessWebCrypto(scriptState, result.get())) + return promise; - if (!unwrappingKey) { - exceptionState.throwTypeError("Invalid unwrappingKey argument"); - return ScriptPromise(); - } + if (!ensureNotNull(wrappedKey, "wrappedKey", result.get())) + return promise; + if (!ensureNotNull(unwrappingKey, "unwrappingKey", result.get())) + return promise; - blink::WebCryptoAlgorithm unwrapAlgorithm; - if (!normalizeAlgorithm(rawUnwrapAlgorithm, UnwrapKey, unwrapAlgorithm, exceptionState)) - return ScriptPromise(); - - // The unwrappedKeyAlgorithm is optional. - blink::WebCryptoAlgorithm unwrappedKeyAlgorithm; - if (!rawUnwrappedKeyAlgorithm.isUndefinedOrNull() && !normalizeAlgorithm(rawUnwrappedKeyAlgorithm, ImportKey, unwrappedKeyAlgorithm, exceptionState)) - return ScriptPromise(); + blink::WebCryptoKeyFormat format; + if (!Key::parseFormat(rawFormat, format, result.get())) + return promise; blink::WebCryptoKeyUsageMask keyUsages; - if (!Key::parseUsageMask(rawKeyUsages, keyUsages, exceptionState)) - return ScriptPromise(); + if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get())) + return promise; - if (!unwrappingKey->canBeUsedForAlgorithm(unwrapAlgorithm, UnwrapKey, exceptionState)) - return ScriptPromise(); + blink::WebCryptoAlgorithm unwrapAlgorithm; + if (!parseAlgorithm(rawUnwrapAlgorithm, blink::WebCryptoOperationUnwrapKey, unwrapAlgorithm, result.get())) + return promise; - const unsigned char* wrappedKeyData = static_cast<const unsigned char*>(wrappedKey->baseAddress()); - unsigned wrappedKeyDataSize = wrappedKey->byteLength(); + blink::WebCryptoAlgorithm unwrappedKeyAlgorithm; + if (!parseAlgorithm(rawUnwrappedKeyAlgorithm, blink::WebCryptoOperationImportKey, unwrappedKeyAlgorithm, result.get())) + return promise; + + if (!unwrappingKey->canBeUsedForAlgorithm(unwrapAlgorithm, blink::WebCryptoOperationUnwrapKey, result.get())) + return promise; - ScriptPromise promise = ScriptPromise::createPending(); - RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(promise); - blink::Platform::current()->crypto()->unwrapKey(format, wrappedKeyData, wrappedKeyDataSize, unwrappingKey->key(), unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages, result->result()); + blink::Platform::current()->crypto()->unwrapKey(format, wrappedKey.bytes(), wrappedKey.byteLength(), unwrappingKey->key(), unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages, result->result()); return promise; } - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.h b/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.h index 313d8ee304d..6b038406b1d 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.h @@ -33,33 +33,39 @@ #include "bindings/v8/ScriptPromise.h" #include "bindings/v8/ScriptWrappable.h" +#include "platform/heap/Handle.h" +#include "wtf/ArrayPiece.h" #include "wtf/Forward.h" -#include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { class Dictionary; -class ExceptionState; class Key; -class SubtleCrypto : public ScriptWrappable, public RefCounted<SubtleCrypto> { +class SubtleCrypto : public GarbageCollectedFinalized<SubtleCrypto>, public ScriptWrappable { public: - static PassRefPtr<SubtleCrypto> create() { return adoptRef(new SubtleCrypto()); } + static SubtleCrypto* create() + { + return new SubtleCrypto(); + } - ScriptPromise encrypt(const Dictionary&, Key*, ArrayBufferView* data, ExceptionState&); - ScriptPromise decrypt(const Dictionary&, Key*, ArrayBufferView* data, ExceptionState&); - ScriptPromise sign(const Dictionary&, Key*, ArrayBufferView* data, ExceptionState&); + ScriptPromise encrypt(ScriptState*, const Dictionary&, Key*, const ArrayPiece&); + ScriptPromise decrypt(ScriptState*, const Dictionary&, Key*, const ArrayPiece&); + ScriptPromise sign(ScriptState*, const Dictionary&, Key*, const ArrayPiece&); // Note that this is not named "verify" because when compiling on Mac that expands to a macro and breaks. - ScriptPromise verifySignature(const Dictionary&, Key*, ArrayBufferView* signature, ArrayBufferView* data, ExceptionState&); - ScriptPromise digest(const Dictionary&, ArrayBufferView* data, ExceptionState&); + ScriptPromise verifySignature(ScriptState*, const Dictionary&, Key*, const ArrayPiece& signature, const ArrayPiece& data); + ScriptPromise digest(ScriptState*, const Dictionary&, const ArrayPiece& data); - ScriptPromise generateKey(const Dictionary&, bool extractable, const Vector<String>& keyUsages, ExceptionState&); - ScriptPromise importKey(const String&, ArrayBufferView*, const Dictionary&, bool extractable, const Vector<String>& keyUsages, ExceptionState&); - ScriptPromise exportKey(const String&, Key*, ExceptionState&); + ScriptPromise generateKey(ScriptState*, const Dictionary&, bool extractable, const Vector<String>& keyUsages); + ScriptPromise importKey(ScriptState*, const String&, const ArrayPiece&, const Dictionary&, bool extractable, const Vector<String>& keyUsages); + ScriptPromise importKey(ScriptState*, const String&, const Dictionary&, const Dictionary&, bool extractable, const Vector<String>& keyUsages); + ScriptPromise exportKey(ScriptState*, const String&, Key*); - ScriptPromise wrapKey(const String&, Key*, Key*, const Dictionary&, ExceptionState&); - ScriptPromise unwrapKey(const String&, ArrayBufferView*, Key*, const Dictionary&, const Dictionary&, bool, const Vector<String>&, ExceptionState&); + ScriptPromise wrapKey(ScriptState*, const String&, Key*, Key*, const Dictionary&); + ScriptPromise unwrapKey(ScriptState*, const String&, const ArrayPiece&, Key*, const Dictionary&, const Dictionary&, bool, const Vector<String>&); + + void trace(Visitor*) { } private: SubtleCrypto(); diff --git a/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl b/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl index f11dc76dbdf..da23af3e960 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/SubtleCrypto.idl @@ -28,20 +28,43 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface + +typedef DOMString KeyFormat; +typedef DOMString KeyUsage; // from Key interface + +// FIXME: use below; needs support for union types http://crbug.com/240176 +typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; + [ + GarbageCollected, NoInterfaceObject, ] interface SubtleCrypto { - [RaisesException] Promise encrypt(Dictionary algorithm, Key key, ArrayBufferView data); - [RaisesException] Promise decrypt(Dictionary algorithm, Key key, ArrayBufferView data); - [RaisesException] Promise sign(Dictionary algorithm, Key key, ArrayBufferView data); - [RaisesException, ImplementedAs=verifySignature] Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBufferView data); - [RaisesException] Promise digest(Dictionary algorithm, ArrayBufferView data); - - [RaisesException] Promise generateKey(Dictionary algorithm, boolean extractable, DOMString[] keyUsages); - [RaisesException] Promise importKey(DOMString format, ArrayBufferView keyData, Dictionary? algorithm, boolean extractable, DOMString[] keyUsages); - [RaisesException] Promise exportKey(DOMString format, Key key); - - [RaisesException] Promise wrapKey(DOMString format, Key key, Key wrappingKey, Dictionary wrapAlgorithm); - [RaisesException] Promise unwrapKey(DOMString format, ArrayBufferView wrappedKey, Key unwrappingKey, Dictionary unwrapAlgorithm, Dictionary? unwrappedKeyAlgorithm, boolean extractable, DOMString[] keyUsages); -}; + [CallWith=ScriptState] Promise encrypt(Dictionary algorithm, Key key, ArrayBuffer data); + [CallWith=ScriptState] Promise encrypt(Dictionary algorithm, Key key, ArrayBufferView data); + + [CallWith=ScriptState] Promise decrypt(Dictionary algorithm, Key key, ArrayBuffer data); + [CallWith=ScriptState] Promise decrypt(Dictionary algorithm, Key key, ArrayBufferView data); + + [CallWith=ScriptState] Promise sign(Dictionary algorithm, Key key, ArrayBuffer data); + [CallWith=ScriptState] Promise sign(Dictionary algorithm, Key key, ArrayBufferView data); + + // FIXME: should be: Promise verify(Dictionary algorithm, Key key, CryptoOperationData signature, CryptoOperationData data); + [CallWith=ScriptState, Custom, ImplementedAs=verifySignature] Promise verify(Dictionary algorithm, Key key, object signature, object data); + [CallWith=ScriptState] Promise digest(Dictionary algorithm, ArrayBuffer data); + [CallWith=ScriptState] Promise digest(Dictionary algorithm, ArrayBufferView data); + + [CallWith=ScriptState] Promise generateKey(Dictionary algorithm, boolean extractable, DOMString[] keyUsages); + + [CallWith=ScriptState] Promise importKey(KeyFormat format, ArrayBuffer keyData, Dictionary algorithm, boolean extractable, KeyUsage[] keyUsages); + [CallWith=ScriptState] Promise importKey(KeyFormat format, ArrayBufferView keyData, Dictionary algorithm, boolean extractable, KeyUsage[] keyUsages); + [CallWith=ScriptState] Promise importKey(KeyFormat format, Dictionary keyData, Dictionary algorithm, boolean extractable, KeyUsage[] keyUsages); + + [CallWith=ScriptState] Promise exportKey(KeyFormat format, Key key); + + [CallWith=ScriptState] Promise wrapKey(KeyFormat format, Key key, Key wrappingKey, Dictionary wrapAlgorithm); + + [CallWith=ScriptState] Promise unwrapKey(KeyFormat format, ArrayBuffer wrappedKey, Key unwrappingKey, Dictionary unwrapAlgorithm, Dictionary unwrappedKeyAlgorithm, boolean extractable, KeyUsage[] keyUsages); + [CallWith=ScriptState] Promise unwrapKey(KeyFormat format, ArrayBufferView wrappedKey, Key unwrappingKey, Dictionary unwrapAlgorithm, Dictionary unwrappedKeyAlgorithm, boolean extractable, KeyUsage[] keyUsages); +}; diff --git a/chromium/third_party/WebKit/Source/modules/crypto/WindowCrypto.idl b/chromium/third_party/WebKit/Source/modules/crypto/WindowCrypto.idl index 46ef6c4b039..b80f1614c6d 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/WindowCrypto.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/WindowCrypto.idl @@ -29,8 +29,7 @@ */ [ - ImplementedAs=DOMWindowCrypto + ImplementedAs=DOMWindowCrypto, ] partial interface Window { readonly attribute Crypto crypto; }; - diff --git a/chromium/third_party/WebKit/Source/modules/crypto/WorkerCrypto.cpp b/chromium/third_party/WebKit/Source/modules/crypto/WorkerCrypto.cpp deleted file mode 100644 index d77d0978de7..00000000000 --- a/chromium/third_party/WebKit/Source/modules/crypto/WorkerCrypto.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/crypto/WorkerCrypto.h" - -namespace WebCore { - -WorkerCrypto::WorkerCrypto() -{ - ScriptWrappable::init(this); -} - -} diff --git a/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.cpp b/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.cpp index a2645149013..5209f63409a 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.cpp +++ b/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.cpp @@ -32,7 +32,7 @@ #include "modules/crypto/WorkerGlobalScopeCrypto.h" #include "core/dom/ExecutionContext.h" -#include "modules/crypto/WorkerCrypto.h" +#include "modules/crypto/Crypto.h" namespace WebCore { @@ -40,35 +40,37 @@ WorkerGlobalScopeCrypto::WorkerGlobalScopeCrypto() { } -WorkerGlobalScopeCrypto::~WorkerGlobalScopeCrypto() -{ -} - const char* WorkerGlobalScopeCrypto::supplementName() { return "WorkerGlobalScopeCrypto"; } -WorkerGlobalScopeCrypto* WorkerGlobalScopeCrypto::from(WorkerSupplementable* context) +WorkerGlobalScopeCrypto& WorkerGlobalScopeCrypto::from(WillBeHeapSupplementable<WorkerGlobalScope>& context) { - WorkerGlobalScopeCrypto* supplement = static_cast<WorkerGlobalScopeCrypto*>(WorkerSupplement::from(context, supplementName())); + WorkerGlobalScopeCrypto* supplement = static_cast<WorkerGlobalScopeCrypto*>(WillBeHeapSupplement<WorkerGlobalScope>::from(context, supplementName())); if (!supplement) { supplement = new WorkerGlobalScopeCrypto(); - provideTo(context, supplementName(), adoptPtr(supplement)); + provideTo(context, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -WorkerCrypto* WorkerGlobalScopeCrypto::crypto(WorkerSupplementable* context) +Crypto* WorkerGlobalScopeCrypto::crypto(WillBeHeapSupplementable<WorkerGlobalScope>& context) { - return WorkerGlobalScopeCrypto::from(context)->crypto(); + return WorkerGlobalScopeCrypto::from(context).crypto(); } -WorkerCrypto* WorkerGlobalScopeCrypto::crypto() const +Crypto* WorkerGlobalScopeCrypto::crypto() const { if (!m_crypto) - m_crypto = WorkerCrypto::create(); + m_crypto = Crypto::create(); return m_crypto.get(); } +void WorkerGlobalScopeCrypto::trace(Visitor* visitor) +{ + visitor->trace(m_crypto); + WillBeHeapSupplement<WorkerGlobalScope>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.h b/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.h index 3c5f4d80063..9dcb8b8b368 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.h +++ b/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.h @@ -31,25 +31,30 @@ #ifndef WorkerGlobalScopeCrypto_h #define WorkerGlobalScopeCrypto_h -#include "core/workers/WorkerSupplementable.h" +#include "core/workers/WorkerGlobalScope.h" +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { -class WorkerCrypto; +class Crypto; class ExecutionContext; +class WorkerGlobalScope; -class WorkerGlobalScopeCrypto : public WorkerSupplement { +class WorkerGlobalScopeCrypto FINAL : public NoBaseWillBeGarbageCollected<WorkerGlobalScopeCrypto>, public WillBeHeapSupplement<WorkerGlobalScope> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WorkerGlobalScopeCrypto); public: - virtual ~WorkerGlobalScopeCrypto(); - static WorkerGlobalScopeCrypto* from(WorkerSupplementable*); - static WorkerCrypto* crypto(WorkerSupplementable*); - WorkerCrypto* crypto() const; + static WorkerGlobalScopeCrypto& from(WillBeHeapSupplementable<WorkerGlobalScope>&); + static Crypto* crypto(WillBeHeapSupplementable<WorkerGlobalScope>&); + Crypto* crypto() const; + + virtual void trace(Visitor*); private: WorkerGlobalScopeCrypto(); static const char* supplementName(); - mutable RefPtr<WorkerCrypto> m_crypto; + mutable PersistentWillBeMember<Crypto> m_crypto; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.idl b/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.idl index 3044d427ba6..2def760c239 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.idl +++ b/chromium/third_party/WebKit/Source/modules/crypto/WorkerGlobalScopeCrypto.idl @@ -28,6 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -partial interface WorkerGlobalScope { - [RuntimeEnabled=Crypto] readonly attribute WorkerCrypto crypto; +[ + RuntimeEnabled=Crypto, +] partial interface WorkerGlobalScope { + readonly attribute Crypto crypto; }; diff --git a/chromium/third_party/WebKit/Source/modules/device_light/DOMWindowDeviceLight.h b/chromium/third_party/WebKit/Source/modules/device_light/DOMWindowDeviceLight.h new file mode 100644 index 00000000000..3e5caff325b --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/DOMWindowDeviceLight.h @@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DOMWindowDeviceLight_h +#define DOMWindowDeviceLight_h + +#include "modules/EventTargetModules.h" + +namespace WebCore { + +class DOMWindowDeviceLight { +public: + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(devicelight); +}; + +} // namespace WebCore + +#endif // DOMWindowDeviceLight_h diff --git a/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightController.cpp b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightController.cpp new file mode 100644 index 00000000000..3768be38631 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightController.cpp @@ -0,0 +1,74 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/device_light/DeviceLightController.h" + +#include "core/dom/Document.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/page/Page.h" +#include "modules/device_light/DeviceLightDispatcher.h" +#include "modules/device_light/DeviceLightEvent.h" +#include "platform/RuntimeEnabledFeatures.h" + +namespace WebCore { + +DeviceLightController::DeviceLightController(Document& document) + : DeviceSingleWindowEventController(document) +{ +} + +DeviceLightController::~DeviceLightController() +{ + stopUpdating(); +} + +const char* DeviceLightController::supplementName() +{ + return "DeviceLightController"; +} + +DeviceLightController& DeviceLightController::from(Document& document) +{ + DeviceLightController* controller = static_cast<DeviceLightController*>(DocumentSupplement::from(document, supplementName())); + if (!controller) { + controller = new DeviceLightController(document); + DocumentSupplement::provideTo(document, supplementName(), adoptPtrWillBeNoop(controller)); + } + return *controller; +} + +bool DeviceLightController::hasLastData() +{ + return DeviceLightDispatcher::instance().latestDeviceLightData() >= 0; +} + +void DeviceLightController::registerWithDispatcher() +{ + DeviceLightDispatcher::instance().addController(this); +} + +void DeviceLightController::unregisterWithDispatcher() +{ + DeviceLightDispatcher::instance().removeController(this); +} + +PassRefPtrWillBeRawPtr<Event> DeviceLightController::lastEvent() const +{ + return DeviceLightEvent::create(EventTypeNames::devicelight, + DeviceLightDispatcher::instance().latestDeviceLightData()); +} + +bool DeviceLightController::isNullEvent(Event* event) const +{ + DeviceLightEvent* lightEvent = toDeviceLightEvent(event); + return lightEvent->value() == std::numeric_limits<double>::infinity(); +} + +const AtomicString& DeviceLightController::eventTypeName() const +{ + return EventTypeNames::devicelight; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightController.h b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightController.h new file mode 100644 index 00000000000..cddb6f2044d --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightController.h @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DeviceLightController_h +#define DeviceLightController_h + +#include "core/dom/DocumentSupplementable.h" +#include "core/frame/DeviceSingleWindowEventController.h" + +namespace WebCore { + +class LocalDOMWindow; +class Event; + +class DeviceLightController FINAL : public NoBaseWillBeGarbageCollectedFinalized<DeviceLightController>, public DeviceSingleWindowEventController, public DocumentSupplement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DeviceLightController); +public: + virtual ~DeviceLightController(); + + static const char* supplementName(); + static DeviceLightController& from(Document&); + +private: + explicit DeviceLightController(Document&); + + // Inherited from DeviceEventControllerBase. + virtual void registerWithDispatcher() OVERRIDE; + virtual void unregisterWithDispatcher() OVERRIDE; + virtual bool hasLastData() OVERRIDE; + + // Inherited from DeviceSingleWindowEventController. + virtual PassRefPtrWillBeRawPtr<Event> lastEvent() const OVERRIDE; + virtual const AtomicString& eventTypeName() const OVERRIDE; + virtual bool isNullEvent(Event*) const OVERRIDE; +}; + +} // namespace WebCore + +#endif // DeviceLightController_h diff --git a/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.cpp b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.cpp new file mode 100644 index 00000000000..31128269c14 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.cpp @@ -0,0 +1,50 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/device_light/DeviceLightDispatcher.h" + +#include "modules/device_light/DeviceLightController.h" +#include "public/platform/Platform.h" + +namespace WebCore { + +DeviceLightDispatcher& DeviceLightDispatcher::instance() +{ + DEFINE_STATIC_LOCAL(DeviceLightDispatcher, deviceLightDispatcher, ()); + return deviceLightDispatcher; +} + +DeviceLightDispatcher::DeviceLightDispatcher() + : m_lastDeviceLightData(-1) +{ +} + +DeviceLightDispatcher::~DeviceLightDispatcher() +{ +} + +void DeviceLightDispatcher::startListening() +{ + blink::Platform::current()->setDeviceLightListener(this); +} + +void DeviceLightDispatcher::stopListening() +{ + blink::Platform::current()->setDeviceLightListener(0); + m_lastDeviceLightData = -1; +} + +void DeviceLightDispatcher::didChangeDeviceLight(double value) +{ + m_lastDeviceLightData = value; + notifyControllers(); +} + +double DeviceLightDispatcher::latestDeviceLightData() const +{ + return m_lastDeviceLightData; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.h b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.h new file mode 100644 index 00000000000..d886079f090 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.h @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DeviceLightDispatcher_h +#define DeviceLightDispatcher_h + +#include "core/frame/DeviceEventDispatcherBase.h" +#include "public/platform/WebDeviceLightListener.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +class DeviceLightController; + +// This class listens to device light data and notifies all registered controllers. +class DeviceLightDispatcher FINAL : public DeviceEventDispatcherBase, public blink::WebDeviceLightListener { +public: + static DeviceLightDispatcher& instance(); + + double latestDeviceLightData() const; + + // Inherited from WebDeviceLightListener. + virtual void didChangeDeviceLight(double) OVERRIDE; + +private: + DeviceLightDispatcher(); + virtual ~DeviceLightDispatcher(); + + // Inherited from DeviceEventDispatcherBase. + virtual void startListening() OVERRIDE; + virtual void stopListening() OVERRIDE; + + double m_lastDeviceLightData; +}; + +} // namespace WebCore + +#endif // DeviceLightDispatcher_h diff --git a/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.cpp b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.cpp new file mode 100644 index 00000000000..766b2add8d5 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.cpp @@ -0,0 +1,43 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/device_light/DeviceLightEvent.h" + +namespace WebCore { + +DeviceLightEvent::~DeviceLightEvent() +{ +} + +DeviceLightEvent::DeviceLightEvent() + : m_value(std::numeric_limits<double>::infinity()) +{ + ScriptWrappable::init(this); +} + +DeviceLightEvent::DeviceLightEvent(const AtomicString& eventType, double value) + : Event(eventType, true, false) // The DeviceLightEvent bubbles but is not cancelable. + , m_value(value) +{ + ScriptWrappable::init(this); +} + +DeviceLightEvent::DeviceLightEvent(const AtomicString& eventType, const DeviceLightEventInit& initializer) + : Event(eventType, initializer) + , m_value(initializer.value) +{ + ScriptWrappable::init(this); +} + +const AtomicString& DeviceLightEvent::interfaceName() const +{ + return EventNames::DeviceLightEvent; +} + +} // namespace WebCore + + + + diff --git a/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.h b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.h new file mode 100644 index 00000000000..5f97af5e4d8 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.h @@ -0,0 +1,56 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DeviceLightEvent_h +#define DeviceLightEvent_h + +#include "modules/EventModules.h" +#include "platform/heap/Handle.h" + +namespace WebCore { + +struct DeviceLightEventInit : public EventInit { + DeviceLightEventInit() + : value(std::numeric_limits<double>::infinity()) + { + bubbles = true; + }; + + double value; +}; + +class DeviceLightEvent FINAL : public Event { +public: + virtual ~DeviceLightEvent(); + + static PassRefPtrWillBeRawPtr<DeviceLightEvent> create() + { + return adoptRefWillBeNoop(new DeviceLightEvent); + } + static PassRefPtrWillBeRawPtr<DeviceLightEvent> create(const AtomicString& eventType, double value) + { + return adoptRefWillBeNoop(new DeviceLightEvent(eventType, value)); + } + static PassRefPtrWillBeRawPtr<DeviceLightEvent> create(const AtomicString& eventType, const DeviceLightEventInit& initializer) + { + return adoptRefWillBeNoop(new DeviceLightEvent(eventType, initializer)); + } + + double value() const { return m_value; } + + virtual const AtomicString& interfaceName() const OVERRIDE; + +private: + DeviceLightEvent(); + DeviceLightEvent(const AtomicString& eventType, double value); + DeviceLightEvent(const AtomicString& eventType, const DeviceLightEventInit& initializer); + + double m_value; +}; + +DEFINE_TYPE_CASTS(DeviceLightEvent, Event, event, event->interfaceName() == EventNames::DeviceLightEvent, event.interfaceName() == EventNames::DeviceLightEvent); + +} // namespace WebCore + +#endif // DeviceLightEvent_h diff --git a/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl new file mode 100644 index 00000000000..6d3d3b9ed44 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/DeviceLightEvent.idl @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=DeviceLight, + EventConstructor +] interface DeviceLightEvent : Event { + [InitializedByEventConstructor] readonly attribute unrestricted double value; +}; diff --git a/chromium/third_party/WebKit/Source/modules/device_light/WindowDeviceLight.idl b/chromium/third_party/WebKit/Source/modules/device_light/WindowDeviceLight.idl new file mode 100644 index 00000000000..1b8cd79f723 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_light/WindowDeviceLight.idl @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=DeviceLight, + ImplementedAs=DOMWindowDeviceLight +] partial interface Window { + attribute EventHandler ondevicelight; +}; diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DOMWindowDeviceMotion.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DOMWindowDeviceMotion.h new file mode 100644 index 00000000000..ed3718372ea --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DOMWindowDeviceMotion.h @@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DOMWindowDeviceMotion_h +#define DOMWindowDeviceMotion_h + +#include "modules/EventTargetModules.h" + +namespace WebCore { + +class DOMWindowDeviceMotion { +public: + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(devicemotion); +}; + +} // namespace WebCore + +#endif // DOMWindowDeviceMotion_h diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DOMWindowDeviceOrientation.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DOMWindowDeviceOrientation.h new file mode 100644 index 00000000000..b01fa4beb47 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DOMWindowDeviceOrientation.h @@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DOMWindowDeviceOrientation_h +#define DOMWindowDeviceOrientation_h + +#include "modules/EventTargetModules.h" + +namespace WebCore { + +class DOMWindowDeviceOrientation { +public: + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(deviceorientation); +}; + +} // namespace WebCore + +#endif // DOMWindowDeviceOrientation_h diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.cpp index f3f01c545e7..0c74e536971 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.cpp @@ -28,12 +28,17 @@ namespace WebCore { -DeviceAcceleration::DeviceAcceleration(PassRefPtr<DeviceMotionData::Acceleration> acceleration) +DeviceAcceleration::DeviceAcceleration(PassRefPtrWillBeRawPtr<DeviceMotionData::Acceleration> acceleration) : m_acceleration(acceleration) { ScriptWrappable::init(this); } +void DeviceAcceleration::trace(Visitor* visitor) +{ + visitor->trace(m_acceleration); +} + double DeviceAcceleration::x(bool& isNull) const { if (m_acceleration->canProvideX()) diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.h index 5465a43f83a..0b17446c48c 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.h @@ -28,25 +28,27 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/device_orientation/DeviceMotionData.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" namespace WebCore { -class DeviceAcceleration : public ScriptWrappable, public RefCounted<DeviceAcceleration> { +class DeviceAcceleration : public RefCountedWillBeGarbageCollectedFinalized<DeviceAcceleration>, public ScriptWrappable { public: - static PassRefPtr<DeviceAcceleration> create(PassRefPtr<DeviceMotionData::Acceleration> acceleration) + static PassRefPtrWillBeRawPtr<DeviceAcceleration> create(PassRefPtrWillBeRawPtr<DeviceMotionData::Acceleration> acceleration) { - return adoptRef(new DeviceAcceleration(acceleration)); + return adoptRefWillBeNoop(new DeviceAcceleration(acceleration)); } + void trace(Visitor*); double x(bool& isNull) const; double y(bool& isNull) const; double z(bool& isNull) const; private: - DeviceAcceleration(PassRefPtr<DeviceMotionData::Acceleration>); + DeviceAcceleration(PassRefPtrWillBeRawPtr<DeviceMotionData::Acceleration>); - RefPtr<DeviceMotionData::Acceleration> m_acceleration; + RefPtrWillBeMember<DeviceMotionData::Acceleration> m_acceleration; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.idl b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.idl index c4ff4a67e61..6ad701c2da8 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.idl +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceAcceleration.idl @@ -24,6 +24,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface DeviceAcceleration { readonly attribute double? x; diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp index 877fe372663..ed76d86d4db 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp @@ -1,45 +1,20 @@ -/* - * Copyright 2010 Apple Inc. All rights reserved. - * Copyright (C) 2012 Samsung Electronics. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #include "config.h" #include "modules/device_orientation/DeviceMotionController.h" -#include "RuntimeEnabledFeatures.h" #include "core/dom/Document.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/page/Page.h" +#include "modules/EventModules.h" #include "modules/device_orientation/DeviceMotionData.h" #include "modules/device_orientation/DeviceMotionDispatcher.h" #include "modules/device_orientation/DeviceMotionEvent.h" namespace WebCore { -DeviceMotionController::DeviceMotionController(Document* document) - : DeviceSensorEventController(document) - , DOMWindowLifecycleObserver(document->domWindow()) +DeviceMotionController::DeviceMotionController(Document& document) + : DeviceSingleWindowEventController(document) { } @@ -48,24 +23,19 @@ DeviceMotionController::~DeviceMotionController() stopUpdating(); } -void DeviceMotionController::didChangeDeviceMotion(DeviceMotionData* deviceMotionData) -{ - dispatchDeviceEvent(DeviceMotionEvent::create(EventTypeNames::devicemotion, deviceMotionData)); -} - const char* DeviceMotionController::supplementName() { return "DeviceMotionController"; } -DeviceMotionController* DeviceMotionController::from(Document* document) +DeviceMotionController& DeviceMotionController::from(Document& document) { DeviceMotionController* controller = static_cast<DeviceMotionController*>(DocumentSupplement::from(document, supplementName())); if (!controller) { controller = new DeviceMotionController(document); - DocumentSupplement::provideTo(document, supplementName(), adoptPtr(controller)); + DocumentSupplement::provideTo(document, supplementName(), adoptPtrWillBeNoop(controller)); } - return controller; + return *controller; } bool DeviceMotionController::hasLastData() @@ -73,48 +43,30 @@ bool DeviceMotionController::hasLastData() return DeviceMotionDispatcher::instance().latestDeviceMotionData(); } -PassRefPtr<Event> DeviceMotionController::getLastEvent() -{ - return DeviceMotionEvent::create(EventTypeNames::devicemotion, DeviceMotionDispatcher::instance().latestDeviceMotionData()); -} - void DeviceMotionController::registerWithDispatcher() { - DeviceMotionDispatcher::instance().addDeviceMotionController(this); + DeviceMotionDispatcher::instance().addController(this); } void DeviceMotionController::unregisterWithDispatcher() { - DeviceMotionDispatcher::instance().removeDeviceMotionController(this); -} - -bool DeviceMotionController::isNullEvent(Event* event) -{ - DeviceMotionEvent* motionEvent = toDeviceMotionEvent(event); - return !motionEvent->deviceMotionData()->canProvideEventData(); + DeviceMotionDispatcher::instance().removeController(this); } -void DeviceMotionController::didAddEventListener(DOMWindow*, const AtomicString& eventType) +PassRefPtrWillBeRawPtr<Event> DeviceMotionController::lastEvent() const { - if (eventType == EventTypeNames::devicemotion && RuntimeEnabledFeatures::deviceMotionEnabled()) { - if (page() && page()->visibilityState() == PageVisibilityStateVisible) - startUpdating(); - m_hasEventListener = true; - } + return DeviceMotionEvent::create(EventTypeNames::devicemotion, DeviceMotionDispatcher::instance().latestDeviceMotionData()); } -void DeviceMotionController::didRemoveEventListener(DOMWindow*, const AtomicString& eventType) +bool DeviceMotionController::isNullEvent(Event* event) const { - if (eventType == EventTypeNames::devicemotion) { - stopUpdating(); - m_hasEventListener = false; - } + DeviceMotionEvent* motionEvent = toDeviceMotionEvent(event); + return !motionEvent->deviceMotionData()->canProvideEventData(); } -void DeviceMotionController::didRemoveAllEventListeners(DOMWindow*) +const AtomicString& DeviceMotionController::eventTypeName() const { - stopUpdating(); - m_hasEventListener = false; + return EventTypeNames::devicemotion; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.h index d960201c07d..1ca07a008e7 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.h @@ -1,65 +1,38 @@ -/* - * Copyright 2010 Apple Inc. All rights reserved. - * Copyright (C) 2012 Samsung Electronics. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef DeviceMotionController_h #define DeviceMotionController_h #include "core/dom/DocumentSupplementable.h" -#include "core/events/Event.h" -#include "core/frame/DOMWindowLifecycleObserver.h" -#include "modules/device_orientation/DeviceSensorEventController.h" +#include "core/frame/DeviceSingleWindowEventController.h" namespace WebCore { class DeviceMotionData; -class DOMWindow; - -class DeviceMotionController : public DeviceSensorEventController, public DocumentSupplement, public DOMWindowLifecycleObserver { +class Event; +class DeviceMotionController FINAL : public NoBaseWillBeGarbageCollectedFinalized<DeviceMotionController>, public DeviceSingleWindowEventController, public DocumentSupplement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DeviceMotionController); public: virtual ~DeviceMotionController(); static const char* supplementName(); - static DeviceMotionController* from(Document*); - - void didChangeDeviceMotion(DeviceMotionData*); + static DeviceMotionController& from(Document&); private: - explicit DeviceMotionController(Document*); + explicit DeviceMotionController(Document&); + + // Inherited from DeviceEventControllerBase. virtual void registerWithDispatcher() OVERRIDE; virtual void unregisterWithDispatcher() OVERRIDE; - - // Inherited from DOMWindowLifecycleObserver. - virtual void didAddEventListener(DOMWindow*, const AtomicString&) OVERRIDE; - virtual void didRemoveEventListener(DOMWindow*, const AtomicString&) OVERRIDE; - virtual void didRemoveAllEventListeners(DOMWindow*) OVERRIDE; - virtual bool hasLastData() OVERRIDE; - virtual PassRefPtr<Event> getLastEvent() OVERRIDE; - virtual bool isNullEvent(Event*) OVERRIDE; + + // Inherited from DeviceSingleWindowEventController. + virtual PassRefPtrWillBeRawPtr<Event> lastEvent() const OVERRIDE; + virtual const AtomicString& eventTypeName() const OVERRIDE; + virtual bool isNullEvent(Event*) const OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionData.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionData.cpp index f0b92137d33..0c95aeeef14 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionData.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionData.cpp @@ -29,11 +29,10 @@ namespace WebCore { -PassRefPtr<DeviceMotionData::Acceleration> DeviceMotionData::Acceleration::create(bool canProvideX, double x, - bool canProvideY, double y, - bool canProvideZ, double z) +PassRefPtrWillBeRawPtr<DeviceMotionData::Acceleration> DeviceMotionData::Acceleration::create( + bool canProvideX, double x, bool canProvideY, double y, bool canProvideZ, double z) { - return adoptRef(new DeviceMotionData::Acceleration(canProvideX, x, canProvideY, y, canProvideZ, z)); + return adoptRefWillBeNoop(new DeviceMotionData::Acceleration(canProvideX, x, canProvideY, y, canProvideZ, z)); } DeviceMotionData::Acceleration::Acceleration(bool canProvideX, double x, bool canProvideY, double y, bool canProvideZ, double z) @@ -47,11 +46,10 @@ DeviceMotionData::Acceleration::Acceleration(bool canProvideX, double x, bool ca { } -PassRefPtr<DeviceMotionData::RotationRate> DeviceMotionData::RotationRate::create(bool canProvideAlpha, double alpha, - bool canProvideBeta, double beta, - bool canProvideGamma, double gamma) +PassRefPtrWillBeRawPtr<DeviceMotionData::RotationRate> DeviceMotionData::RotationRate::create( + bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma) { - return adoptRef(new DeviceMotionData::RotationRate(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma)); + return adoptRefWillBeNoop(new DeviceMotionData::RotationRate(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma)); } DeviceMotionData::RotationRate::RotationRate(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma) @@ -64,18 +62,22 @@ DeviceMotionData::RotationRate::RotationRate(bool canProvideAlpha, double alpha, { } -PassRefPtr<DeviceMotionData> DeviceMotionData::create() +PassRefPtrWillBeRawPtr<DeviceMotionData> DeviceMotionData::create() { - return adoptRef(new DeviceMotionData); + return adoptRefWillBeNoop(new DeviceMotionData); } -PassRefPtr<DeviceMotionData> DeviceMotionData::create(PassRefPtr<Acceleration> acceleration, PassRefPtr<Acceleration> accelerationIncludingGravity, - PassRefPtr<RotationRate> rotationRate, bool canProvideInterval, double interval) +PassRefPtrWillBeRawPtr<DeviceMotionData> DeviceMotionData::create( + PassRefPtrWillBeRawPtr<Acceleration> acceleration, + PassRefPtrWillBeRawPtr<Acceleration> accelerationIncludingGravity, + PassRefPtrWillBeRawPtr<RotationRate> rotationRate, + bool canProvideInterval, + double interval) { - return adoptRef(new DeviceMotionData(acceleration, accelerationIncludingGravity, rotationRate, canProvideInterval, interval)); + return adoptRefWillBeNoop(new DeviceMotionData(acceleration, accelerationIncludingGravity, rotationRate, canProvideInterval, interval)); } -PassRefPtr<DeviceMotionData> DeviceMotionData::create(const blink::WebDeviceMotionData& data) +PassRefPtrWillBeRawPtr<DeviceMotionData> DeviceMotionData::create(const blink::WebDeviceMotionData& data) { return DeviceMotionData::create( DeviceMotionData::Acceleration::create( @@ -99,8 +101,12 @@ DeviceMotionData::DeviceMotionData() { } -DeviceMotionData::DeviceMotionData(PassRefPtr<Acceleration> acceleration, PassRefPtr<Acceleration> accelerationIncludingGravity, - PassRefPtr<RotationRate> rotationRate, bool canProvideInterval, double interval) +DeviceMotionData::DeviceMotionData( + PassRefPtrWillBeRawPtr<Acceleration> acceleration, + PassRefPtrWillBeRawPtr<Acceleration> accelerationIncludingGravity, + PassRefPtrWillBeRawPtr<RotationRate> rotationRate, + bool canProvideInterval, + double interval) : m_acceleration(acceleration) , m_accelerationIncludingGravity(accelerationIncludingGravity) , m_rotationRate(rotationRate) @@ -109,6 +115,13 @@ DeviceMotionData::DeviceMotionData(PassRefPtr<Acceleration> acceleration, PassRe { } +void DeviceMotionData::trace(Visitor* visitor) +{ + visitor->trace(m_acceleration); + visitor->trace(m_accelerationIncludingGravity); + visitor->trace(m_rotationRate); +} + bool DeviceMotionData::canProvideEventData() const { const bool hasAcceleration = m_acceleration && (m_acceleration->canProvideX() || m_acceleration->canProvideY() || m_acceleration->canProvideZ()); diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionData.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionData.h index 980c8fc6e61..706e91f0988 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionData.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionData.h @@ -26,7 +26,7 @@ #ifndef DeviceMotionData_h #define DeviceMotionData_h -#include "wtf/PassRefPtr.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" @@ -36,11 +36,13 @@ class WebDeviceMotionData; namespace WebCore { -class DeviceMotionData : public RefCounted<DeviceMotionData> { +class DeviceMotionData : public RefCountedWillBeGarbageCollected<DeviceMotionData> { public: - class Acceleration : public RefCounted<DeviceMotionData::Acceleration> { + + class Acceleration : public RefCountedWillBeGarbageCollected<DeviceMotionData::Acceleration> { public: - static PassRefPtr<Acceleration> create(bool canProvideX, double x, bool canProvideY, double y, bool canProvideZ, double z); + static PassRefPtrWillBeRawPtr<Acceleration> create(bool canProvideX, double x, bool canProvideY, double y, bool canProvideZ, double z); + void trace(Visitor*) { } bool canProvideX() const { return m_canProvideX; } bool canProvideY() const { return m_canProvideY; } @@ -62,9 +64,10 @@ public: bool m_canProvideZ; }; - class RotationRate : public RefCounted<DeviceMotionData::RotationRate> { + class RotationRate : public RefCountedWillBeGarbageCollected<DeviceMotionData::RotationRate> { public: - static PassRefPtr<RotationRate> create(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma); + static PassRefPtrWillBeRawPtr<RotationRate> create(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma); + void trace(Visitor*) { } bool canProvideAlpha() const { return m_canProvideAlpha; } bool canProvideBeta() const { return m_canProvideBeta; } @@ -86,14 +89,19 @@ public: bool m_canProvideGamma; }; - static PassRefPtr<DeviceMotionData> create(); - static PassRefPtr<DeviceMotionData> create(PassRefPtr<Acceleration> acceleration, PassRefPtr<Acceleration> accelerationIncludingGravity, - PassRefPtr<RotationRate> rotationRate, bool canProvideInterval, double interval); - static PassRefPtr<DeviceMotionData> create(const blink::WebDeviceMotionData&); + static PassRefPtrWillBeRawPtr<DeviceMotionData> create(); + static PassRefPtrWillBeRawPtr<DeviceMotionData> create( + PassRefPtrWillBeRawPtr<Acceleration>, + PassRefPtrWillBeRawPtr<Acceleration> accelerationIncludingGravity, + PassRefPtrWillBeRawPtr<RotationRate>, + bool canProvideInterval, + double interval); + static PassRefPtrWillBeRawPtr<DeviceMotionData> create(const blink::WebDeviceMotionData&); + void trace(Visitor*); - PassRefPtr<Acceleration> acceleration() const { return m_acceleration; } - PassRefPtr<Acceleration> accelerationIncludingGravity() const { return m_accelerationIncludingGravity; } - PassRefPtr<RotationRate> rotationRate() const { return m_rotationRate; } + Acceleration* acceleration() const { return m_acceleration.get(); } + Acceleration* accelerationIncludingGravity() const { return m_accelerationIncludingGravity.get(); } + RotationRate* rotationRate() const { return m_rotationRate.get(); } bool canProvideInterval() const { return m_canProvideInterval; } double interval() const { return m_interval; } @@ -102,12 +110,11 @@ public: private: DeviceMotionData(); - DeviceMotionData(PassRefPtr<Acceleration> acceleration, PassRefPtr<Acceleration> accelerationIncludingGravity, - PassRefPtr<RotationRate> rotationRate, bool canProvideInterval, double interval); + DeviceMotionData(PassRefPtrWillBeRawPtr<Acceleration>, PassRefPtrWillBeRawPtr<Acceleration> accelerationIncludingGravity, PassRefPtrWillBeRawPtr<RotationRate>, bool canProvideInterval, double interval); - RefPtr<Acceleration> m_acceleration; - RefPtr<Acceleration> m_accelerationIncludingGravity; - RefPtr<RotationRate> m_rotationRate; + RefPtrWillBeMember<Acceleration> m_acceleration; + RefPtrWillBeMember<Acceleration> m_accelerationIncludingGravity; + RefPtrWillBeMember<RotationRate> m_rotationRate; bool m_canProvideInterval; double m_interval; }; diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionDispatcher.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionDispatcher.cpp index 00efc88d654..de89684be38 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionDispatcher.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionDispatcher.cpp @@ -34,7 +34,6 @@ #include "modules/device_orientation/DeviceMotionController.h" #include "modules/device_orientation/DeviceMotionData.h" #include "public/platform/Platform.h" -#include "wtf/TemporaryChange.h" namespace WebCore { @@ -52,16 +51,6 @@ DeviceMotionDispatcher::~DeviceMotionDispatcher() { } -void DeviceMotionDispatcher::addDeviceMotionController(DeviceMotionController* controller) -{ - addController(controller); -} - -void DeviceMotionDispatcher::removeDeviceMotionController(DeviceMotionController* controller) -{ - removeController(controller); -} - void DeviceMotionDispatcher::startListening() { blink::Platform::current()->setDeviceMotionListener(this); @@ -76,19 +65,7 @@ void DeviceMotionDispatcher::stopListening() void DeviceMotionDispatcher::didChangeDeviceMotion(const blink::WebDeviceMotionData& motion) { m_lastDeviceMotionData = DeviceMotionData::create(motion); - - { - TemporaryChange<bool> changeIsDispatching(m_isDispatching, true); - // Don't fire controllers removed or added during event dispatch. - size_t size = m_controllers.size(); - for (size_t i = 0; i < size; ++i) { - if (m_controllers[i]) - static_cast<DeviceMotionController*>(m_controllers[i])->didChangeDeviceMotion(m_lastDeviceMotionData.get()); - } - } - - if (m_needsPurge) - purgeControllers(); + notifyControllers(); } DeviceMotionData* DeviceMotionDispatcher::latestDeviceMotionData() diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionDispatcher.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionDispatcher.h index 03ced17fb87..227a5bb3742 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionDispatcher.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionDispatcher.h @@ -31,7 +31,8 @@ #ifndef DeviceMotionDispatcher_h #define DeviceMotionDispatcher_h -#include "modules/device_orientation/DeviceSensorEventDispatcher.h" +#include "core/frame/DeviceEventDispatcherBase.h" +#include "platform/heap/Handle.h" #include "public/platform/WebDeviceMotionListener.h" #include "wtf/RefPtr.h" @@ -44,9 +45,8 @@ namespace WebCore { class DeviceMotionController; class DeviceMotionData; -// This class listens to device motion data and dispatches it to all -// listening controllers. -class DeviceMotionDispatcher : public DeviceSensorEventDispatcher, public blink::WebDeviceMotionListener { +// This class listens to device motion data and notifies all registered controllers. +class DeviceMotionDispatcher FINAL : public DeviceEventDispatcherBase, public blink::WebDeviceMotionListener { public: static DeviceMotionDispatcher& instance(); @@ -54,19 +54,18 @@ public: // FIXME: make the return value const, see crbug.com/233174. DeviceMotionData* latestDeviceMotionData(); - // This method is called every time new device motion data is available. + // Inherited from WebDeviceMotionListener. virtual void didChangeDeviceMotion(const blink::WebDeviceMotionData&) OVERRIDE; - void addDeviceMotionController(DeviceMotionController*); - void removeDeviceMotionController(DeviceMotionController*); private: DeviceMotionDispatcher(); - ~DeviceMotionDispatcher(); + virtual ~DeviceMotionDispatcher(); + // Inherited from DeviceEventDispatcherBase. virtual void startListening() OVERRIDE; virtual void stopListening() OVERRIDE; - RefPtr<DeviceMotionData> m_lastDeviceMotionData; + RefPtrWillBePersistent<DeviceMotionData> m_lastDeviceMotionData; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.cpp index 08483234246..b8b1e6f6834 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "modules/device_orientation/DeviceMotionEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "modules/device_orientation/DeviceAcceleration.h" #include "modules/device_orientation/DeviceMotionData.h" #include "modules/device_orientation/DeviceRotationRate.h" @@ -110,4 +109,13 @@ const AtomicString& DeviceMotionEvent::interfaceName() const return EventNames::DeviceMotionEvent; } +void DeviceMotionEvent::trace(Visitor* visitor) +{ + visitor->trace(m_deviceMotionData); + visitor->trace(m_acceleration); + visitor->trace(m_accelerationIncludingGravity); + visitor->trace(m_rotationRate); + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.h index 6ee5dfb9df0..20ac08b4bb7 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.h @@ -26,7 +26,8 @@ #ifndef DeviceMotionEvent_h #define DeviceMotionEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -34,16 +35,16 @@ class DeviceAcceleration; class DeviceMotionData; class DeviceRotationRate; -class DeviceMotionEvent : public Event { +class DeviceMotionEvent FINAL : public Event { public: - ~DeviceMotionEvent(); - static PassRefPtr<DeviceMotionEvent> create() + virtual ~DeviceMotionEvent(); + static PassRefPtrWillBeRawPtr<DeviceMotionEvent> create() { - return adoptRef(new DeviceMotionEvent); + return adoptRefWillBeNoop(new DeviceMotionEvent); } - static PassRefPtr<DeviceMotionEvent> create(const AtomicString& eventType, DeviceMotionData* deviceMotionData) + static PassRefPtrWillBeRawPtr<DeviceMotionEvent> create(const AtomicString& eventType, DeviceMotionData* deviceMotionData) { - return adoptRef(new DeviceMotionEvent(eventType, deviceMotionData)); + return adoptRefWillBeNoop(new DeviceMotionEvent(eventType, deviceMotionData)); } void initDeviceMotionEvent(const AtomicString& type, bool bubbles, bool cancelable, DeviceMotionData*); @@ -55,24 +56,21 @@ public: DeviceRotationRate* rotationRate(); double interval(bool& isNull) const; - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: DeviceMotionEvent(); DeviceMotionEvent(const AtomicString& eventType, DeviceMotionData*); - RefPtr<DeviceMotionData> m_deviceMotionData; - - RefPtr<DeviceAcceleration> m_acceleration; - RefPtr<DeviceAcceleration> m_accelerationIncludingGravity; - RefPtr<DeviceRotationRate> m_rotationRate; + RefPtrWillBeMember<DeviceMotionData> m_deviceMotionData; + RefPtrWillBeMember<DeviceAcceleration> m_acceleration; + RefPtrWillBeMember<DeviceAcceleration> m_accelerationIncludingGravity; + RefPtrWillBeMember<DeviceRotationRate> m_rotationRate; }; -inline DeviceMotionEvent* toDeviceMotionEvent(Event* event) -{ - ASSERT_WITH_SECURITY_IMPLICATION(!event || event->interfaceName() == EventNames::DeviceMotionEvent); - return static_cast<DeviceMotionEvent*>(event); -} +DEFINE_TYPE_CASTS(DeviceMotionEvent, Event, event, event->interfaceName() == EventNames::DeviceMotionEvent, event.interfaceName() == EventNames::DeviceMotionEvent); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl index 8643b55c5f2..5e70a8376ab 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceMotionEvent.idl @@ -23,9 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -[ - RuntimeEnabled=DeviceMotion -] interface DeviceMotionEvent : Event { +interface DeviceMotionEvent : Event { readonly attribute DeviceAcceleration acceleration; readonly attribute DeviceAcceleration accelerationIncludingGravity; readonly attribute DeviceRotationRate rotationRate; @@ -33,8 +31,8 @@ [Custom] void initDeviceMotionEvent([Default=Undefined] optional DOMString type, [Default=Undefined] optional boolean bubbles, [Default=Undefined] optional boolean cancelable, - [Default=Undefined] optional Acceleration acceleration, - [Default=Undefined] optional Acceleration accelerationIncludingGravity, - [Default=Undefined] optional RotationRate rotationRate, + [Default=Undefined] optional DeviceAcceleration acceleration, + [Default=Undefined] optional DeviceAcceleration accelerationIncludingGravity, + [Default=Undefined] optional DeviceRotationRate rotationRate, [Default=Undefined] optional double interval); }; diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp index 579ea390d76..98e04dd6e55 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp @@ -1,45 +1,20 @@ -/* - * Copyright 2010 Apple Inc. All rights reserved. - * Copyright (C) 2012 Samsung Electronics. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #include "config.h" #include "modules/device_orientation/DeviceOrientationController.h" -#include "RuntimeEnabledFeatures.h" #include "core/dom/Document.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/page/Page.h" +#include "modules/EventModules.h" #include "modules/device_orientation/DeviceOrientationData.h" #include "modules/device_orientation/DeviceOrientationDispatcher.h" #include "modules/device_orientation/DeviceOrientationEvent.h" namespace WebCore { -DeviceOrientationController::DeviceOrientationController(Document* document) - : DeviceSensorEventController(document) - , DOMWindowLifecycleObserver(document->domWindow()) +DeviceOrientationController::DeviceOrientationController(Document& document) + : DeviceSingleWindowEventController(document) { } @@ -48,9 +23,11 @@ DeviceOrientationController::~DeviceOrientationController() stopUpdating(); } -void DeviceOrientationController::didChangeDeviceOrientation(DeviceOrientationData* deviceOrientationData) +void DeviceOrientationController::didUpdateData() { - dispatchDeviceEvent(DeviceOrientationEvent::create(EventTypeNames::deviceorientation, deviceOrientationData)); + if (m_overrideOrientationData) + return; + dispatchDeviceEvent(lastEvent()); } const char* DeviceOrientationController::supplementName() @@ -58,64 +35,72 @@ const char* DeviceOrientationController::supplementName() return "DeviceOrientationController"; } -DeviceOrientationController* DeviceOrientationController::from(Document* document) +DeviceOrientationController& DeviceOrientationController::from(Document& document) { DeviceOrientationController* controller = static_cast<DeviceOrientationController*>(DocumentSupplement::from(document, supplementName())); if (!controller) { controller = new DeviceOrientationController(document); - DocumentSupplement::provideTo(document, supplementName(), adoptPtr(controller)); + DocumentSupplement::provideTo(document, supplementName(), adoptPtrWillBeNoop(controller)); } - return controller; + return *controller; } -bool DeviceOrientationController::hasLastData() +DeviceOrientationData* DeviceOrientationController::lastData() const { - return DeviceOrientationDispatcher::instance().latestDeviceOrientationData(); + return m_overrideOrientationData ? m_overrideOrientationData.get() : DeviceOrientationDispatcher::instance().latestDeviceOrientationData(); } -PassRefPtr<Event> DeviceOrientationController::getLastEvent() +bool DeviceOrientationController::hasLastData() { - return DeviceOrientationEvent::create(EventTypeNames::deviceorientation, - DeviceOrientationDispatcher::instance().latestDeviceOrientationData()); + return lastData(); } void DeviceOrientationController::registerWithDispatcher() { - DeviceOrientationDispatcher::instance().addDeviceOrientationController(this); + DeviceOrientationDispatcher::instance().addController(this); } void DeviceOrientationController::unregisterWithDispatcher() { - DeviceOrientationDispatcher::instance().removeDeviceOrientationController(this); + DeviceOrientationDispatcher::instance().removeController(this); +} + +PassRefPtrWillBeRawPtr<Event> DeviceOrientationController::lastEvent() const +{ + return DeviceOrientationEvent::create(eventTypeName(), lastData()); } -bool DeviceOrientationController::isNullEvent(Event* event) +bool DeviceOrientationController::isNullEvent(Event* event) const { DeviceOrientationEvent* orientationEvent = toDeviceOrientationEvent(event); return !orientationEvent->orientation()->canProvideEventData(); } -void DeviceOrientationController::didAddEventListener(DOMWindow* window, const AtomicString& eventType) +const AtomicString& DeviceOrientationController::eventTypeName() const { - if (eventType == EventTypeNames::deviceorientation && RuntimeEnabledFeatures::deviceOrientationEnabled()) { - if (page() && page()->visibilityState() == PageVisibilityStateVisible) - startUpdating(); - m_hasEventListener = true; - } + return EventTypeNames::deviceorientation; } -void DeviceOrientationController::didRemoveEventListener(DOMWindow* window, const AtomicString& eventType) +void DeviceOrientationController::setOverride(DeviceOrientationData* deviceOrientationData) { - if (eventType == EventTypeNames::deviceorientation) { - stopUpdating(); - m_hasEventListener = false; - } + ASSERT(deviceOrientationData); + m_overrideOrientationData = deviceOrientationData; + dispatchDeviceEvent(lastEvent()); } -void DeviceOrientationController::didRemoveAllEventListeners(DOMWindow* window) +void DeviceOrientationController::clearOverride() { - stopUpdating(); - m_hasEventListener = false; + if (!m_overrideOrientationData) + return; + m_overrideOrientationData.clear(); + if (lastData()) + didUpdateData(); +} + +void DeviceOrientationController::trace(Visitor* visitor) +{ + visitor->trace(m_overrideOrientationData); + DocumentSupplement::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.h index 8e10883a7db..e578dc535cc 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.h @@ -1,64 +1,50 @@ -/* - * Copyright 2010 Apple Inc. All rights reserved. - * Copyright (C) 2012 Samsung Electronics. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef DeviceOrientationController_h #define DeviceOrientationController_h #include "core/dom/DocumentSupplementable.h" -#include "core/events/Event.h" -#include "core/frame/DOMWindowLifecycleObserver.h" -#include "modules/device_orientation/DeviceSensorEventController.h" +#include "core/frame/DeviceSingleWindowEventController.h" namespace WebCore { class DeviceOrientationData; +class Event; -class DeviceOrientationController : public DeviceSensorEventController, public DocumentSupplement, public DOMWindowLifecycleObserver { - +class DeviceOrientationController FINAL : public NoBaseWillBeGarbageCollectedFinalized<DeviceOrientationController>, public DeviceSingleWindowEventController, public DocumentSupplement { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DeviceOrientationController); public: virtual ~DeviceOrientationController(); static const char* supplementName(); - static DeviceOrientationController* from(Document*); + static DeviceOrientationController& from(Document&); + + // Inherited from DeviceSingleWindowEventController. + void didUpdateData() OVERRIDE; - void didChangeDeviceOrientation(WebCore::DeviceOrientationData*); + void setOverride(DeviceOrientationData*); + void clearOverride(); - // Inherited from DOMWindowLifecycleObserver - virtual void didAddEventListener(DOMWindow*, const AtomicString&) OVERRIDE; - virtual void didRemoveEventListener(DOMWindow*, const AtomicString&) OVERRIDE; - virtual void didRemoveAllEventListeners(DOMWindow*) OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; private: - explicit DeviceOrientationController(Document*); + explicit DeviceOrientationController(Document&); + + // Inherited from DeviceEventControllerBase. virtual void registerWithDispatcher() OVERRIDE; virtual void unregisterWithDispatcher() OVERRIDE; - virtual bool hasLastData() OVERRIDE; - virtual PassRefPtr<Event> getLastEvent() OVERRIDE; - virtual bool isNullEvent(Event*) OVERRIDE; + + // Inherited from DeviceSingleWindowEventController. + virtual PassRefPtrWillBeRawPtr<Event> lastEvent() const OVERRIDE; + virtual const AtomicString& eventTypeName() const OVERRIDE; + virtual bool isNullEvent(Event*) const OVERRIDE; + + DeviceOrientationData* lastData() const; + + RefPtrWillBeMember<DeviceOrientationData> m_overrideOrientationData; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationData.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationData.cpp index 8c6aeb2bf42..93c025f7c9c 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationData.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationData.cpp @@ -29,17 +29,17 @@ namespace WebCore { -PassRefPtr<DeviceOrientationData> DeviceOrientationData::create() +PassRefPtrWillBeRawPtr<DeviceOrientationData> DeviceOrientationData::create() { - return adoptRef(new DeviceOrientationData); + return adoptRefWillBeNoop(new DeviceOrientationData); } -PassRefPtr<DeviceOrientationData> DeviceOrientationData::create(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma, bool canProvideAbsolute, bool absolute) +PassRefPtrWillBeRawPtr<DeviceOrientationData> DeviceOrientationData::create(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma, bool canProvideAbsolute, bool absolute) { - return adoptRef(new DeviceOrientationData(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma, canProvideAbsolute, absolute)); + return adoptRefWillBeNoop(new DeviceOrientationData(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma, canProvideAbsolute, absolute)); } -PassRefPtr<DeviceOrientationData> DeviceOrientationData::create(const blink::WebDeviceOrientationData& data) +PassRefPtrWillBeRawPtr<DeviceOrientationData> DeviceOrientationData::create(const blink::WebDeviceOrientationData& data) { return DeviceOrientationData::create(data.hasAlpha, data.alpha, data.hasBeta, data.beta, data.hasGamma, data.gamma, data.hasAbsolute, data.absolute); } diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationData.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationData.h index 274ac81a47f..b968a23a3a0 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationData.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationData.h @@ -26,7 +26,7 @@ #ifndef DeviceOrientationData_h #define DeviceOrientationData_h -#include "wtf/PassRefPtr.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" namespace blink { @@ -35,11 +35,12 @@ class WebDeviceOrientationData; namespace WebCore { -class DeviceOrientationData : public RefCounted<DeviceOrientationData> { +class DeviceOrientationData : public RefCountedWillBeGarbageCollected<DeviceOrientationData> { public: - static PassRefPtr<DeviceOrientationData> create(); - static PassRefPtr<DeviceOrientationData> create(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma, bool canProvideAbsolute = false, bool absolute = false); - static PassRefPtr<DeviceOrientationData> create(const blink::WebDeviceOrientationData&); + static PassRefPtrWillBeRawPtr<DeviceOrientationData> create(); + static PassRefPtrWillBeRawPtr<DeviceOrientationData> create(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma, bool canProvideAbsolute = false, bool absolute = false); + static PassRefPtrWillBeRawPtr<DeviceOrientationData> create(const blink::WebDeviceOrientationData&); + void trace(Visitor*) { } double alpha() const; double beta() const; diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationDispatcher.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationDispatcher.cpp index ed73d039e8a..4c82b25aaa9 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationDispatcher.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationDispatcher.cpp @@ -34,7 +34,6 @@ #include "modules/device_orientation/DeviceOrientationController.h" #include "modules/device_orientation/DeviceOrientationData.h" #include "public/platform/Platform.h" -#include "wtf/TemporaryChange.h" namespace WebCore { @@ -52,16 +51,6 @@ DeviceOrientationDispatcher::~DeviceOrientationDispatcher() { } -void DeviceOrientationDispatcher::addDeviceOrientationController(DeviceOrientationController* controller) -{ - addController(controller); -} - -void DeviceOrientationDispatcher::removeDeviceOrientationController(DeviceOrientationController* controller) -{ - removeController(controller); -} - void DeviceOrientationDispatcher::startListening() { blink::Platform::current()->setDeviceOrientationListener(this); @@ -76,19 +65,7 @@ void DeviceOrientationDispatcher::stopListening() void DeviceOrientationDispatcher::didChangeDeviceOrientation(const blink::WebDeviceOrientationData& motion) { m_lastDeviceOrientationData = DeviceOrientationData::create(motion); - - { - TemporaryChange<bool> changeIsDispatching(m_isDispatching, true); - // Don't fire controllers removed or added during event dispatch. - size_t size = m_controllers.size(); - for (size_t i = 0; i < size; ++i) { - if (m_controllers[i]) - static_cast<DeviceOrientationController*>(m_controllers[i])->didChangeDeviceOrientation(m_lastDeviceOrientationData.get()); - } - } - - if (m_needsPurge) - purgeControllers(); + notifyControllers(); } DeviceOrientationData* DeviceOrientationDispatcher::latestDeviceOrientationData() diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationDispatcher.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationDispatcher.h index a3be9424bd2..42162230e81 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationDispatcher.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationDispatcher.h @@ -31,7 +31,8 @@ #ifndef DeviceOrientationDispatcher_h #define DeviceOrientationDispatcher_h -#include "modules/device_orientation/DeviceSensorEventDispatcher.h" +#include "core/frame/DeviceEventDispatcherBase.h" +#include "platform/heap/Handle.h" #include "public/platform/WebDeviceOrientationListener.h" #include "wtf/RefPtr.h" @@ -44,9 +45,8 @@ namespace WebCore { class DeviceOrientationController; class DeviceOrientationData; -// This class listens to device motion data and dispatches it to all -// listening controllers. -class DeviceOrientationDispatcher : public DeviceSensorEventDispatcher, public blink::WebDeviceOrientationListener { +// This class listens to device orientation data and notifies all registered controllers. +class DeviceOrientationDispatcher : public DeviceEventDispatcherBase, public blink::WebDeviceOrientationListener { public: static DeviceOrientationDispatcher& instance(); @@ -54,19 +54,18 @@ public: // FIXME: make the return value const, see crbug.com/233174. DeviceOrientationData* latestDeviceOrientationData(); - // This method is called every time new device motion data is available. + // Inherited from WebDeviceOrientationListener. virtual void didChangeDeviceOrientation(const blink::WebDeviceOrientationData&) OVERRIDE; - void addDeviceOrientationController(DeviceOrientationController*); - void removeDeviceOrientationController(DeviceOrientationController*); private: DeviceOrientationDispatcher(); ~DeviceOrientationDispatcher(); + // Inherited from DeviceEventDispatcherBase. virtual void startListening() OVERRIDE; virtual void stopListening() OVERRIDE; - RefPtr<DeviceOrientationData> m_lastDeviceOrientationData; + RefPtrWillBePersistent<DeviceOrientationData> m_lastDeviceOrientationData; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.cpp index dc899d285b2..715e3c655b9 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "modules/device_orientation/DeviceOrientationEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "modules/device_orientation/DeviceOrientationData.h" namespace WebCore { @@ -98,4 +97,10 @@ const AtomicString& DeviceOrientationEvent::interfaceName() const return EventNames::DeviceOrientationEvent; } +void DeviceOrientationEvent::trace(Visitor* visitor) +{ + visitor->trace(m_orientation); + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.h index 0acbbf9e1fd..ba19a762427 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationEvent.h @@ -26,22 +26,23 @@ #ifndef DeviceOrientationEvent_h #define DeviceOrientationEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" +#include "platform/heap/Handle.h" namespace WebCore { class DeviceOrientationData; -class DeviceOrientationEvent : public Event { +class DeviceOrientationEvent FINAL : public Event { public: - ~DeviceOrientationEvent(); - static PassRefPtr<DeviceOrientationEvent> create() + virtual ~DeviceOrientationEvent(); + static PassRefPtrWillBeRawPtr<DeviceOrientationEvent> create() { - return adoptRef(new DeviceOrientationEvent); + return adoptRefWillBeNoop(new DeviceOrientationEvent); } - static PassRefPtr<DeviceOrientationEvent> create(const AtomicString& eventType, DeviceOrientationData* orientation) + static PassRefPtrWillBeRawPtr<DeviceOrientationEvent> create(const AtomicString& eventType, DeviceOrientationData* orientation) { - return adoptRef(new DeviceOrientationEvent(eventType, orientation)); + return adoptRefWillBeNoop(new DeviceOrientationEvent(eventType, orientation)); } void initDeviceOrientationEvent(const AtomicString& type, bool bubbles, bool cancelable, DeviceOrientationData*); @@ -53,20 +54,18 @@ public: double gamma(bool& isNull) const; bool absolute(bool& isNull) const; - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: DeviceOrientationEvent(); DeviceOrientationEvent(const AtomicString& eventType, DeviceOrientationData*); - RefPtr<DeviceOrientationData> m_orientation; + RefPtrWillBeMember<DeviceOrientationData> m_orientation; }; -inline DeviceOrientationEvent* toDeviceOrientationEvent(Event* event) -{ - ASSERT_WITH_SECURITY_IMPLICATION(!event || event->interfaceName() == EventNames::DeviceOrientationEvent); - return static_cast<DeviceOrientationEvent*>(event); -} +DEFINE_TYPE_CASTS(DeviceOrientationEvent, Event, event, event->interfaceName() == EventNames::DeviceOrientationEvent, event.interfaceName() == EventNames::DeviceOrientationEvent); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.cpp new file mode 100644 index 00000000000..4e2e4518187 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.cpp @@ -0,0 +1,86 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/device_orientation/DeviceOrientationInspectorAgent.h" + +#include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" +#include "core/inspector/InspectorController.h" +#include "core/inspector/InspectorState.h" +#include "core/page/Page.h" + +#include "modules/device_orientation/DeviceOrientationController.h" +#include "modules/device_orientation/DeviceOrientationData.h" + +namespace WebCore { + +namespace DeviceOrientationInspectorAgentState { +static const char alpha[] = "alpha"; +static const char beta[] = "beta"; +static const char gamma[] = "gamma"; +static const char overrideEnabled[] = "overrideEnabled"; +} + +void DeviceOrientationInspectorAgent::provideTo(Page& page) +{ + OwnPtr<DeviceOrientationInspectorAgent> deviceOrientationAgent(adoptPtr(new DeviceOrientationInspectorAgent(page))); + page.inspectorController().registerModuleAgent(deviceOrientationAgent.release()); +} + +DeviceOrientationInspectorAgent::~DeviceOrientationInspectorAgent() +{ +} + +DeviceOrientationInspectorAgent::DeviceOrientationInspectorAgent(Page& page) + : InspectorBaseAgent<DeviceOrientationInspectorAgent>("DeviceOrientation") + , m_page(page) +{ +} + +DeviceOrientationController& DeviceOrientationInspectorAgent::controller() +{ + ASSERT(toLocalFrame(m_page.mainFrame())->document()); + return DeviceOrientationController::from(*m_page.deprecatedLocalMainFrame()->document()); +} + +void DeviceOrientationInspectorAgent::setDeviceOrientationOverride(ErrorString* error, double alpha, double beta, double gamma) +{ + m_state->setBoolean(DeviceOrientationInspectorAgentState::overrideEnabled, true); + m_state->setDouble(DeviceOrientationInspectorAgentState::alpha, alpha); + m_state->setDouble(DeviceOrientationInspectorAgentState::beta, beta); + m_state->setDouble(DeviceOrientationInspectorAgentState::gamma, gamma); + controller().setOverride(DeviceOrientationData::create(true, alpha, true, beta, true, gamma).get()); +} + +void DeviceOrientationInspectorAgent::clearDeviceOrientationOverride(ErrorString* error) +{ + m_state->setBoolean(DeviceOrientationInspectorAgentState::overrideEnabled, false); + controller().clearOverride(); +} + +void DeviceOrientationInspectorAgent::clearFrontend() +{ + m_state->setBoolean(DeviceOrientationInspectorAgentState::overrideEnabled, false); + controller().clearOverride(); +} + +void DeviceOrientationInspectorAgent::restore() +{ + if (m_state->getBoolean(DeviceOrientationInspectorAgentState::overrideEnabled)) { + double alpha = m_state->getDouble(DeviceOrientationInspectorAgentState::alpha); + double beta = m_state->getDouble(DeviceOrientationInspectorAgentState::beta); + double gamma = m_state->getDouble(DeviceOrientationInspectorAgentState::gamma); + controller().setOverride(DeviceOrientationData::create(true, alpha, true, beta, true, gamma).get()); + } +} + +void DeviceOrientationInspectorAgent::didCommitLoadForMainFrame() +{ + // New document in main frame - apply override there. + // No need to cleanup previous one, as it's already gone. + restore(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.h new file mode 100644 index 00000000000..a77363f055d --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationInspectorAgent.h @@ -0,0 +1,43 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DeviceOrientationInspectorAgent_h +#define DeviceOrientationInspectorAgent_h + +#include "core/inspector/InspectorBaseAgent.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class DeviceOrientationController; +class Page; + +typedef String ErrorString; + +class DeviceOrientationInspectorAgent FINAL : public InspectorBaseAgent<DeviceOrientationInspectorAgent>, public InspectorBackendDispatcher::DeviceOrientationCommandHandler { + WTF_MAKE_NONCOPYABLE(DeviceOrientationInspectorAgent); +public: + static void provideTo(Page&); + + virtual ~DeviceOrientationInspectorAgent(); + + // Protocol methods. + virtual void setDeviceOrientationOverride(ErrorString*, double, double, double) OVERRIDE; + virtual void clearDeviceOrientationOverride(ErrorString*) OVERRIDE; + + // Inspector Controller API. + virtual void clearFrontend() OVERRIDE; + virtual void restore() OVERRIDE; + virtual void didCommitLoadForMainFrame() OVERRIDE; + +private: + explicit DeviceOrientationInspectorAgent(Page&); + DeviceOrientationController& controller(); + Page& m_page; +}; + +} // namespace WebCore + + +#endif // !defined(DeviceOrientationInspectorAgent_h) diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.cpp index a08167e30bd..a2857520f96 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.cpp +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.cpp @@ -28,12 +28,17 @@ namespace WebCore { -DeviceRotationRate::DeviceRotationRate(PassRefPtr<DeviceMotionData::RotationRate> rotationRate) +DeviceRotationRate::DeviceRotationRate(PassRefPtrWillBeRawPtr<DeviceMotionData::RotationRate> rotationRate) : m_rotationRate(rotationRate) { ScriptWrappable::init(this); } +void DeviceRotationRate::trace(Visitor* visitor) +{ + visitor->trace(m_rotationRate); +} + double DeviceRotationRate::alpha(bool& isNull) const { if (m_rotationRate->canProvideAlpha()) diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.h index e33d1b60d76..12845f78ef4 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.h +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.h @@ -28,25 +28,27 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/device_orientation/DeviceMotionData.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" namespace WebCore { -class DeviceRotationRate : public ScriptWrappable, public RefCounted<DeviceRotationRate> { +class DeviceRotationRate : public RefCountedWillBeGarbageCollectedFinalized<DeviceRotationRate>, public ScriptWrappable { public: - static PassRefPtr<DeviceRotationRate> create(PassRefPtr<DeviceMotionData::RotationRate> rotationRate) + static PassRefPtrWillBeRawPtr<DeviceRotationRate> create(PassRefPtrWillBeRawPtr<DeviceMotionData::RotationRate> rotationRate) { - return adoptRef(new DeviceRotationRate(rotationRate)); + return adoptRefWillBeNoop(new DeviceRotationRate(rotationRate)); } + void trace(Visitor*); double alpha(bool& isNull) const; double beta(bool& isNull) const; double gamma(bool& isNull) const; private: - DeviceRotationRate(PassRefPtr<DeviceMotionData::RotationRate>); + DeviceRotationRate(PassRefPtrWillBeRawPtr<DeviceMotionData::RotationRate>); - RefPtr<DeviceMotionData::RotationRate> m_rotationRate; + RefPtrWillBeMember<DeviceMotionData::RotationRate> m_rotationRate; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.idl b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.idl index 2d7600aa86f..71d299f9bc9 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.idl +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceRotationRate.idl @@ -24,6 +24,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface DeviceRotationRate { readonly attribute double? alpha; diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventController.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventController.cpp deleted file mode 100644 index 19a205780fd..00000000000 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventController.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2010 Apple Inc. All rights reserved. - * Copyright (C) 2012 Samsung Electronics. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/device_orientation/DeviceSensorEventController.h" - -#include "core/dom/Document.h" -#include "core/frame/DOMWindow.h" -#include "core/page/Page.h" - -namespace WebCore { - -DeviceSensorEventController::DeviceSensorEventController(Document* document) - : PageLifecycleObserver(document->page()) - , m_hasEventListener(false) - , m_document(document) - , m_isActive(false) - , m_needsCheckingNullEvents(true) - , m_timer(this, &DeviceSensorEventController::fireDeviceEvent) -{ -} - -DeviceSensorEventController::~DeviceSensorEventController() -{ -} - -void DeviceSensorEventController::fireDeviceEvent(Timer<DeviceSensorEventController>* timer) -{ - ASSERT_UNUSED(timer, timer == &m_timer); - ASSERT(hasLastData()); - - m_timer.stop(); - dispatchDeviceEvent(getLastEvent()); -} - -void DeviceSensorEventController::dispatchDeviceEvent(PassRefPtr<Event> prpEvent) -{ - RefPtr<Event> event = prpEvent; - if (m_document && m_document->domWindow() - && !m_document->activeDOMObjectsAreSuspended() - && !m_document->activeDOMObjectsAreStopped()) - m_document->domWindow()->dispatchEvent(event); - - if (m_needsCheckingNullEvents) { - if (isNullEvent(event.get())) - stopUpdating(); - else - m_needsCheckingNullEvents = false; - } -} - -void DeviceSensorEventController::startUpdating() -{ - if (m_isActive) - return; - - if (hasLastData() && !m_timer.isActive()) { - // Make sure to fire the device motion data as soon as possible. - m_timer.startOneShot(0); - } - - registerWithDispatcher(); - m_isActive = true; -} - -void DeviceSensorEventController::stopUpdating() -{ - if (!m_isActive) - return; - - if (m_timer.isActive()) - m_timer.stop(); - - unregisterWithDispatcher(); - m_isActive = false; -} - -void DeviceSensorEventController::pageVisibilityChanged() -{ - if (!m_hasEventListener) - return; - - if (page()->visibilityState() == PageVisibilityStateVisible) - startUpdating(); - else - stopUpdating(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventController.h b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventController.h deleted file mode 100644 index 6129b4e0a34..00000000000 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventController.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DeviceSensorEventController_h -#define DeviceSensorEventController_h - -#include "core/events/Event.h" -#include "core/page/PageLifecycleObserver.h" -#include "platform/Timer.h" - -namespace WebCore { - -class Document; - -class DeviceSensorEventController : public PageLifecycleObserver { - -public: - void startUpdating(); - void stopUpdating(); - -protected: - explicit DeviceSensorEventController(Document*); - virtual ~DeviceSensorEventController(); - - void dispatchDeviceEvent(const PassRefPtr<Event>); - - virtual bool hasLastData() = 0; - virtual PassRefPtr<Event> getLastEvent() = 0; - virtual void registerWithDispatcher() = 0; - virtual void unregisterWithDispatcher() = 0; - virtual bool isNullEvent(Event*) = 0; - - bool m_hasEventListener; - -private: - // Inherited from PageLifecycleObserver. - virtual void pageVisibilityChanged() OVERRIDE; - - void fireDeviceEvent(Timer<DeviceSensorEventController>*); - - Document* m_document; - bool m_isActive; - bool m_needsCheckingNullEvents; - Timer<DeviceSensorEventController> m_timer; -}; - -} // namespace WebCore - -#endif // DeviceSensorEventController_h diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventDispatcher.cpp b/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventDispatcher.cpp deleted file mode 100644 index b5cd6ffaf0e..00000000000 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventDispatcher.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/device_orientation/DeviceSensorEventDispatcher.h" - -namespace WebCore { - -DeviceSensorEventDispatcher::DeviceSensorEventDispatcher() - : m_needsPurge(false) - , m_isDispatching(false) -{ -} - -DeviceSensorEventDispatcher::~DeviceSensorEventDispatcher() -{ -} - -void DeviceSensorEventDispatcher::addController(DeviceSensorEventController* controller) -{ - bool wasEmpty = m_controllers.isEmpty(); - if (!m_controllers.contains(controller)) - m_controllers.append(controller); - if (wasEmpty) - startListening(); -} - -void DeviceSensorEventDispatcher::removeController(DeviceSensorEventController* controller) -{ - // Do not actually remove the controller from the vector, instead zero them out. - // The zeros are removed in these two cases: - // 1. either immediately if we are not dispatching any events, - // 2. or after didChangeDeviceMotion/Orientation has dispatched all events. - // This is to correctly handle the re-entrancy case when a controller is destroyed - // while in the didChangeDeviceMotion/Orientation method. - size_t index = m_controllers.find(controller); - if (index == kNotFound) - return; - - m_controllers[index] = 0; - m_needsPurge = true; - - if (!m_isDispatching) - purgeControllers(); -} - -void DeviceSensorEventDispatcher::purgeControllers() -{ - ASSERT(m_needsPurge); - - size_t i = 0; - while (i < m_controllers.size()) { - if (!m_controllers[i]) { - m_controllers[i] = m_controllers.last(); - m_controllers.removeLast(); - } else { - ++i; - } - } - - m_needsPurge = false; - - if (m_controllers.isEmpty()) - stopListening(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/WindowDeviceMotion.idl b/chromium/third_party/WebKit/Source/modules/device_orientation/WindowDeviceMotion.idl new file mode 100644 index 00000000000..15130d84733 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/WindowDeviceMotion.idl @@ -0,0 +1,9 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + ImplementedAs=DOMWindowDeviceMotion +] partial interface Window { + attribute EventHandler ondevicemotion; +}; diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/WindowDeviceOrientation.idl b/chromium/third_party/WebKit/Source/modules/device_orientation/WindowDeviceOrientation.idl new file mode 100644 index 00000000000..8a7d18a9dfd --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/device_orientation/WindowDeviceOrientation.idl @@ -0,0 +1,9 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + ImplementedAs=DOMWindowDeviceOrientation +] partial interface Window { + attribute EventHandler ondeviceorientation; +}; diff --git a/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.cpp b/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.cpp index 5358b2c93a8..03fcebf5ac9 100644 --- a/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.cpp +++ b/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.cpp @@ -31,13 +31,13 @@ #include "config.h" #include "modules/donottrack/NavigatorDoNotTrack.h" -#include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" +#include "core/loader/FrameLoaderClient.h" namespace WebCore { -NavigatorDoNotTrack::NavigatorDoNotTrack(Frame* frame) +NavigatorDoNotTrack::NavigatorDoNotTrack(LocalFrame* frame) : DOMWindowProperty(frame) { } @@ -51,24 +51,26 @@ const char* NavigatorDoNotTrack::supplementName() return "NavigatorDoNotTrack"; } -NavigatorDoNotTrack* NavigatorDoNotTrack::from(Navigator* navigator) +NavigatorDoNotTrack& NavigatorDoNotTrack::from(Navigator& navigator) { - NavigatorDoNotTrack* supplement = static_cast<NavigatorDoNotTrack*>(Supplement<Navigator>::from(navigator, supplementName())); + NavigatorDoNotTrack* supplement = static_cast<NavigatorDoNotTrack*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); if (!supplement) { - supplement = new NavigatorDoNotTrack(navigator->frame()); - provideTo(navigator, supplementName(), adoptPtr(supplement)); + supplement = new NavigatorDoNotTrack(navigator.frame()); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -String NavigatorDoNotTrack::doNotTrack(Navigator* navigator) +String NavigatorDoNotTrack::doNotTrack(Navigator& navigator) { - return NavigatorDoNotTrack::from(navigator)->doNotTrack(); + return NavigatorDoNotTrack::from(navigator).doNotTrack(); } String NavigatorDoNotTrack::doNotTrack() { - return frame() ? frame()->loader().client()->doNotTrackValue() : String(); + if (!frame() || !frame()->loader().client()) + return String(); + return frame()->loader().client()->doNotTrackValue(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.h b/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.h index 3b260bd4960..eb1dc3b9387 100644 --- a/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.h +++ b/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.h @@ -33,24 +33,28 @@ #include "core/frame/DOMWindowProperty.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { -class Frame; +class LocalFrame; class Navigator; -class NavigatorDoNotTrack : public Supplement<Navigator>, public DOMWindowProperty { +class NavigatorDoNotTrack FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorDoNotTrack>, public WillBeHeapSupplement<Navigator>, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorDoNotTrack); public: virtual ~NavigatorDoNotTrack(); - static NavigatorDoNotTrack* from(Navigator*); + static NavigatorDoNotTrack& from(Navigator&); - static String doNotTrack(Navigator*); + static String doNotTrack(Navigator&); String doNotTrack(); + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Navigator>::trace(visitor); } + private: - explicit NavigatorDoNotTrack(Frame*); + explicit NavigatorDoNotTrack(LocalFrame*); static const char* supplementName(); }; diff --git a/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.idl b/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.idl index f1626bff129..1ecea7fecd8 100644 --- a/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.idl +++ b/chromium/third_party/WebKit/Source/modules/donottrack/NavigatorDoNotTrack.idl @@ -31,4 +31,3 @@ partial interface Navigator { [TreatReturnedNullStringAs=Null] readonly attribute DOMString doNotTrack; }; - diff --git a/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.cpp b/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.cpp index e463c08f725..59e5e2603d5 100644 --- a/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.cpp +++ b/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.cpp @@ -34,31 +34,38 @@ #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" +#include "wtf/StringExtras.h" #include "wtf/text/TextEncodingRegistry.h" namespace WebCore { -PassRefPtr<TextDecoder> TextDecoder::create(const String& label, const Dictionary& options, ExceptionState& exceptionState) +TextDecoder* TextDecoder::create(const String& label, const Dictionary& options, ExceptionState& exceptionState) { const String& encodingLabel = label.isNull() ? String("utf-8") : label; WTF::TextEncoding encoding(encodingLabel); - if (!encoding.isValid()) { - exceptionState.throwUninformativeAndGenericTypeError(); + // The replacement encoding is not valid, but the Encoding API also + // rejects aliases of the replacement encoding. + if (!encoding.isValid() || !strcasecmp(encoding.name(), "replacement")) { + exceptionState.throwTypeError("The encoding label provided ('" + encodingLabel + "') is invalid."); return 0; } bool fatal = false; options.get("fatal", fatal); - return adoptRef(new TextDecoder(encoding.name(), fatal)); + bool ignoreBOM = false; + options.get("ignoreBOM", ignoreBOM); + + return new TextDecoder(encoding, fatal, ignoreBOM); } -TextDecoder::TextDecoder(const String& encoding, bool fatal) +TextDecoder::TextDecoder(const WTF::TextEncoding& encoding, bool fatal, bool ignoreBOM) : m_encoding(encoding) - , m_codec(newTextCodec(m_encoding)) + , m_codec(newTextCodec(encoding)) , m_fatal(fatal) + , m_ignoreBOM(ignoreBOM) , m_bomSeen(false) { } @@ -85,10 +92,7 @@ String TextDecoder::decode(ArrayBufferView* input, const Dictionary& options, Ex const char* start = input ? static_cast<const char*>(input->baseAddress()) : 0; size_t length = input ? input->byteLength() : 0; - bool flush = !stream; - - // FIXME: Not all TextCodec implementations handle |flush| - notably TextCodecUTF16 - // ignores it and never flushes! + WTF::FlushBehavior flush = stream ? WTF::DoNotFlush : WTF::DataEOF; bool sawError = false; String s = m_codec->decode(start, length, flush, m_fatal, sawError); @@ -98,7 +102,7 @@ String TextDecoder::decode(ArrayBufferView* input, const Dictionary& options, Ex return String(); } - if (!m_bomSeen && !s.isEmpty()) { + if (!m_ignoreBOM && !m_bomSeen && !s.isEmpty()) { m_bomSeen = true; String name(m_encoding.name()); if ((name == "UTF-8" || name == "UTF-16LE" || name == "UTF-16BE") && s[0] == 0xFEFF) diff --git a/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.h b/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.h index 73a9c64d75d..9b9857ee1f4 100644 --- a/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.h +++ b/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.h @@ -32,6 +32,7 @@ #define TextDecoder_h #include "bindings/v8/Dictionary.h" +#include "platform/heap/Handle.h" #include "wtf/ArrayBufferView.h" #include "wtf/RefCounted.h" #include "wtf/text/TextCodec.h" @@ -42,25 +43,27 @@ namespace WebCore { class ExceptionState; -class TextDecoder : public RefCounted<TextDecoder> { +class TextDecoder FINAL : public GarbageCollectedFinalized<TextDecoder> { public: - static PassRefPtr<TextDecoder> create(const String& label, const Dictionary&, ExceptionState&); - virtual ~TextDecoder(); + static TextDecoder* create(const String& label, const Dictionary&, ExceptionState&); + ~TextDecoder(); // Implement the IDL String encoding() const; + bool fatal() const { return m_fatal; } + bool ignoreBOM() const { return m_ignoreBOM; } String decode(ArrayBufferView*, const Dictionary&, ExceptionState&); String decode(ExceptionState& exceptionState) { return decode(0, Dictionary(), exceptionState); } - using RefCounted<TextDecoder>::ref; - using RefCounted<TextDecoder>::deref; + void trace(Visitor*) { } private: - TextDecoder(const String& encoding, bool fatal); + TextDecoder(const WTF::TextEncoding&, bool fatal, bool ignoreBOM); WTF::TextEncoding m_encoding; OwnPtr<WTF::TextCodec> m_codec; bool m_fatal; + bool m_ignoreBOM; bool m_bomSeen; }; diff --git a/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.idl b/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.idl index 136b0ef204d..f71c7b89647 100644 --- a/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.idl +++ b/chromium/third_party/WebKit/Source/modules/encoding/TextDecoder.idl @@ -30,10 +30,14 @@ [ RuntimeEnabled=EncodingAPI, - GlobalContext=Window&WorkerGlobalScope, - Constructor([Default=NullString] optional DOMString label, optional Dictionary options), - RaisesException=Constructor + Exposed=Window&Worker, + Constructor(optional DOMString label = null, optional Dictionary options), + RaisesException=Constructor, + GarbageCollected, + MeasureAs=TextDecoderConstructor ] interface TextDecoder { readonly attribute DOMString encoding; - [RaisesException] DOMString decode(optional ArrayBufferView input, optional Dictionary options); + readonly attribute boolean fatal; + readonly attribute boolean ignoreBOM; + [RaisesException, MeasureAs=TextDecoderDecode] DOMString decode(optional ArrayBufferView input, optional Dictionary options); }; diff --git a/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.cpp b/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.cpp index 98b935497dc..a669e0272d1 100644 --- a/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.cpp +++ b/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.cpp @@ -39,28 +39,28 @@ namespace WebCore { -PassRefPtr<TextEncoder> TextEncoder::create(const String& utfLabel, ExceptionState& exceptionState) +TextEncoder* TextEncoder::create(const String& utfLabel, ExceptionState& exceptionState) { const String& encodingLabel = utfLabel.isNull() ? String("utf-8") : utfLabel; WTF::TextEncoding encoding(encodingLabel); if (!encoding.isValid()) { - exceptionState.throwUninformativeAndGenericTypeError(); + exceptionState.throwTypeError("The encoding label provided ('" + encodingLabel + "') is invalid."); return 0; } String name(encoding.name()); if (name != "UTF-8" && name != "UTF-16LE" && name != "UTF-16BE") { - exceptionState.throwUninformativeAndGenericTypeError(); + exceptionState.throwTypeError("The encoding provided ('" + encodingLabel + "') is not one of 'utf-8', 'utf-16', or 'utf-16be'."); return 0; } - return adoptRef(new TextEncoder(encoding.name())); + return new TextEncoder(encoding); } -TextEncoder::TextEncoder(const String& encoding) +TextEncoder::TextEncoder(const WTF::TextEncoding& encoding) : m_encoding(encoding) - , m_codec(newTextCodec(m_encoding)) + , m_codec(newTextCodec(encoding)) { } @@ -84,10 +84,12 @@ PassRefPtr<Uint8Array> TextEncoder::encode(const String& input, const Dictionary // handle split surrogates here. CString result; - if (input.is8Bit()) - result = m_codec->encode(input.characters8(), input.length(), WTF::QuestionMarksForUnencodables); - else - result = m_codec->encode(input.characters16(), input.length(), WTF::QuestionMarksForUnencodables); + if (!input.isNull()) { + if (input.is8Bit()) + result = m_codec->encode(input.characters8(), input.length(), WTF::QuestionMarksForUnencodables); + else + result = m_codec->encode(input.characters16(), input.length(), WTF::QuestionMarksForUnencodables); + } const char* buffer = result.data(); const unsigned char* unsignedBuffer = reinterpret_cast<const unsigned char*>(buffer); diff --git a/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.h b/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.h index 08199a8a28f..afd7f725981 100644 --- a/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.h +++ b/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.h @@ -31,6 +31,7 @@ #ifndef TextEncoder_h #define TextEncoder_h +#include "platform/heap/Handle.h" #include "wtf/ArrayBufferView.h" #include "wtf/RefCounted.h" #include "wtf/Uint8Array.h" @@ -43,20 +44,19 @@ namespace WebCore { class Dictionary; class ExceptionState; -class TextEncoder : public RefCounted<TextEncoder> { +class TextEncoder FINAL : public GarbageCollectedFinalized<TextEncoder> { public: - static PassRefPtr<TextEncoder> create(const String& utfLabel, ExceptionState&); - virtual ~TextEncoder(); + static TextEncoder* create(const String& utfLabel, ExceptionState&); + ~TextEncoder(); // Implement the IDL String encoding() const; PassRefPtr<Uint8Array> encode(const String&, const Dictionary&); - using RefCounted<TextEncoder>::ref; - using RefCounted<TextEncoder>::deref; + void trace(Visitor*) { } private: - TextEncoder(const String& encoding); + TextEncoder(const WTF::TextEncoding&); WTF::TextEncoding m_encoding; OwnPtr<WTF::TextCodec> m_codec; diff --git a/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.idl b/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.idl index 9258c0cf437..dc86fef21bf 100644 --- a/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.idl +++ b/chromium/third_party/WebKit/Source/modules/encoding/TextEncoder.idl @@ -30,10 +30,12 @@ [ RuntimeEnabled=EncodingAPI, - GlobalContext=Window&WorkerGlobalScope, - Constructor([Default=NullString] optional DOMString utfLabel), - RaisesException=Constructor + Exposed=Window&Worker, + Constructor(optional DOMString utfLabel = null), + RaisesException=Constructor, + GarbageCollected, + MeasureAs=TextEncoderConstructor ] interface TextEncoder { readonly attribute DOMString encoding; - Uint8Array encode([Default=NullString] optional DOMString input, optional Dictionary options); + [MeasureAs=TextEncoderEncode] Uint8Array encode(optional ScalarValueString input = null, optional Dictionary options); }; diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.cpp b/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.cpp new file mode 100644 index 00000000000..6bacb1da2ad --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.cpp @@ -0,0 +1,358 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h" + +#include "bindings/v8/ExceptionState.h" +#include "core/dom/ExceptionCode.h" +#include "core/html/HTMLMediaElement.h" +#include "core/html/MediaKeyError.h" +#include "core/html/MediaKeyEvent.h" +#include "modules/encryptedmedia/MediaKeyNeededEvent.h" +#include "modules/encryptedmedia/MediaKeys.h" +#include "platform/Logging.h" +#include "platform/RuntimeEnabledFeatures.h" + +namespace WebCore { + +static void throwExceptionIfMediaKeyExceptionOccurred(const String& keySystem, const String& sessionId, blink::WebMediaPlayer::MediaKeyException exception, ExceptionState& exceptionState) +{ + switch (exception) { + case blink::WebMediaPlayer::MediaKeyExceptionNoError: + return; + case blink::WebMediaPlayer::MediaKeyExceptionInvalidPlayerState: + exceptionState.throwDOMException(InvalidStateError, "The player is in an invalid state."); + return; + case blink::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported: + exceptionState.throwDOMException(NotSupportedError, "The key system provided ('" + keySystem +"') is not supported."); + return; + case blink::WebMediaPlayer::MediaKeyExceptionInvalidAccess: + exceptionState.throwDOMException(InvalidAccessError, "The session ID provided ('" + sessionId + "') is invalid."); + return; + } + + ASSERT_NOT_REACHED(); + return; +} + +HTMLMediaElementEncryptedMedia::HTMLMediaElementEncryptedMedia() + : m_emeMode(EmeModeNotSelected) +{ +} + +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(HTMLMediaElementEncryptedMedia) + +const char* HTMLMediaElementEncryptedMedia::supplementName() +{ + return "HTMLMediaElementEncryptedMedia"; +} + +HTMLMediaElementEncryptedMedia& HTMLMediaElementEncryptedMedia::from(HTMLMediaElement& element) +{ + HTMLMediaElementEncryptedMedia* supplement = static_cast<HTMLMediaElementEncryptedMedia*>(WillBeHeapSupplement<HTMLMediaElement>::from(element, supplementName())); + if (!supplement) { + supplement = new HTMLMediaElementEncryptedMedia(); + provideTo(element, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; +} + +bool HTMLMediaElementEncryptedMedia::setEmeMode(EmeMode emeMode, ExceptionState& exceptionState) +{ + if (m_emeMode != EmeModeNotSelected && m_emeMode != emeMode) { + exceptionState.throwDOMException(InvalidStateError, "Mixed use of EME prefixed and unprefixed API not allowed."); + return false; + } + m_emeMode = emeMode; + return true; +} + +blink::WebContentDecryptionModule* HTMLMediaElementEncryptedMedia::contentDecryptionModule() +{ + return m_mediaKeys ? m_mediaKeys->contentDecryptionModule() : 0; +} + +MediaKeys* HTMLMediaElementEncryptedMedia::mediaKeys(HTMLMediaElement& element) +{ + HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(element); + return thisElement.m_mediaKeys.get(); +} + +void HTMLMediaElementEncryptedMedia::setMediaKeysInternal(HTMLMediaElement& element, MediaKeys* mediaKeys) +{ + if (m_mediaKeys == mediaKeys) + return; + + ASSERT(m_emeMode == EmeModeUnprefixed); + m_mediaKeys = mediaKeys; + + // If a player is connected, tell it that the CDM has changed. + if (element.webMediaPlayer()) + element.webMediaPlayer()->setContentDecryptionModule(contentDecryptionModule()); +} + +void HTMLMediaElementEncryptedMedia::setMediaKeys(HTMLMediaElement& element, MediaKeys* mediaKeys, ExceptionState& exceptionState) +{ + WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::setMediaKeys"); + HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(element); + + if (!thisElement.setEmeMode(EmeModeUnprefixed, exceptionState)) + return; + + thisElement.setMediaKeysInternal(element, mediaKeys); +} + +// Create a MediaKeyNeededEvent for WD EME. +static PassRefPtrWillBeRawPtr<Event> createNeedKeyEvent(const String& contentType, const unsigned char* initData, unsigned initDataLength) +{ + MediaKeyNeededEventInit initializer; + initializer.contentType = contentType; + initializer.initData = Uint8Array::create(initData, initDataLength); + initializer.bubbles = false; + initializer.cancelable = false; + + return MediaKeyNeededEvent::create(EventTypeNames::needkey, initializer); +} + +// Create a 'needkey' MediaKeyEvent for v0.1b EME. +static PassRefPtrWillBeRawPtr<Event> createWebkitNeedKeyEvent(const String& contentType, const unsigned char* initData, unsigned initDataLength) +{ + MediaKeyEventInit webkitInitializer; + webkitInitializer.keySystem = String(); + webkitInitializer.sessionId = String(); + webkitInitializer.initData = Uint8Array::create(initData, initDataLength); + webkitInitializer.bubbles = false; + webkitInitializer.cancelable = false; + + return MediaKeyEvent::create(EventTypeNames::webkitneedkey, webkitInitializer); +} + +void HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest(HTMLMediaElement& element, const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState& exceptionState) +{ + HTMLMediaElementEncryptedMedia::from(element).generateKeyRequest(element.webMediaPlayer(), keySystem, initData, exceptionState); +} + +void HTMLMediaElementEncryptedMedia::generateKeyRequest(blink::WebMediaPlayer* webMediaPlayer, const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState& exceptionState) +{ + WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest"); + + if (!setEmeMode(EmeModePrefixed, exceptionState)) + return; + + if (keySystem.isEmpty()) { + exceptionState.throwDOMException(SyntaxError, "The key system provided is empty."); + return; + } + + if (!webMediaPlayer) { + exceptionState.throwDOMException(InvalidStateError, "No media has been loaded."); + return; + } + + const unsigned char* initDataPointer = 0; + unsigned initDataLength = 0; + if (initData) { + initDataPointer = initData->data(); + initDataLength = initData->length(); + } + + blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer->generateKeyRequest(keySystem, initDataPointer, initDataLength); + throwExceptionIfMediaKeyExceptionOccurred(keySystem, String(), result, exceptionState); +} + +void HTMLMediaElementEncryptedMedia::webkitGenerateKeyRequest(HTMLMediaElement& mediaElement, const String& keySystem, ExceptionState& exceptionState) +{ + webkitGenerateKeyRequest(mediaElement, keySystem, Uint8Array::create(0), exceptionState); +} + +void HTMLMediaElementEncryptedMedia::webkitAddKey(HTMLMediaElement& element, const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState& exceptionState) +{ + HTMLMediaElementEncryptedMedia::from(element).addKey(element.webMediaPlayer(), keySystem, key, initData, sessionId, exceptionState); +} + +void HTMLMediaElementEncryptedMedia::addKey(blink::WebMediaPlayer* webMediaPlayer, const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState& exceptionState) +{ + WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitAddKey"); + + if (!setEmeMode(EmeModePrefixed, exceptionState)) + return; + + if (keySystem.isEmpty()) { + exceptionState.throwDOMException(SyntaxError, "The key system provided is empty."); + return; + } + + if (!key) { + exceptionState.throwDOMException(SyntaxError, "The key provided is invalid."); + return; + } + + if (!key->length()) { + exceptionState.throwDOMException(TypeMismatchError, "The key provided is invalid."); + return; + } + + if (!webMediaPlayer) { + exceptionState.throwDOMException(InvalidStateError, "No media has been loaded."); + return; + } + + const unsigned char* initDataPointer = 0; + unsigned initDataLength = 0; + if (initData) { + initDataPointer = initData->data(); + initDataLength = initData->length(); + } + + blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer->addKey(keySystem, key->data(), key->length(), initDataPointer, initDataLength, sessionId); + throwExceptionIfMediaKeyExceptionOccurred(keySystem, sessionId, result, exceptionState); +} + +void HTMLMediaElementEncryptedMedia::webkitAddKey(HTMLMediaElement& mediaElement, const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState& exceptionState) +{ + webkitAddKey(mediaElement, keySystem, key, Uint8Array::create(0), String(), exceptionState); +} + +void HTMLMediaElementEncryptedMedia::webkitCancelKeyRequest(HTMLMediaElement& element, const String& keySystem, const String& sessionId, ExceptionState& exceptionState) +{ + HTMLMediaElementEncryptedMedia::from(element).cancelKeyRequest(element.webMediaPlayer(), keySystem, sessionId, exceptionState); +} + +void HTMLMediaElementEncryptedMedia::cancelKeyRequest(blink::WebMediaPlayer* webMediaPlayer, const String& keySystem, const String& sessionId, ExceptionState& exceptionState) +{ + WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::webkitCancelKeyRequest"); + + if (!setEmeMode(EmeModePrefixed, exceptionState)) + return; + + if (keySystem.isEmpty()) { + exceptionState.throwDOMException(SyntaxError, "The key system provided is empty."); + return; + } + + if (!webMediaPlayer) { + exceptionState.throwDOMException(InvalidStateError, "No media has been loaded."); + return; + } + + blink::WebMediaPlayer::MediaKeyException result = webMediaPlayer->cancelKeyRequest(keySystem, sessionId); + throwExceptionIfMediaKeyExceptionOccurred(keySystem, sessionId, result, exceptionState); +} + +void HTMLMediaElementEncryptedMedia::keyAdded(HTMLMediaElement& element, const String& keySystem, const String& sessionId) +{ + WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyAdded"); + + MediaKeyEventInit initializer; + initializer.keySystem = keySystem; + initializer.sessionId = sessionId; + initializer.bubbles = false; + initializer.cancelable = false; + + RefPtrWillBeRawPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyadded, initializer); + event->setTarget(&element); + element.scheduleEvent(event.release()); +} + +void HTMLMediaElementEncryptedMedia::keyError(HTMLMediaElement& element, const String& keySystem, const String& sessionId, blink::WebMediaPlayerClient::MediaKeyErrorCode errorCode, unsigned short systemCode) +{ + WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyError: sessionID=%s, errorCode=%d, systemCode=%d", sessionId.utf8().data(), errorCode, systemCode); + + MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; + switch (errorCode) { + case blink::WebMediaPlayerClient::MediaKeyErrorCodeUnknown: + mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; + break; + case blink::WebMediaPlayerClient::MediaKeyErrorCodeClient: + mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT; + break; + case blink::WebMediaPlayerClient::MediaKeyErrorCodeService: + mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_SERVICE; + break; + case blink::WebMediaPlayerClient::MediaKeyErrorCodeOutput: + mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_OUTPUT; + break; + case blink::WebMediaPlayerClient::MediaKeyErrorCodeHardwareChange: + mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_HARDWARECHANGE; + break; + case blink::WebMediaPlayerClient::MediaKeyErrorCodeDomain: + mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_DOMAIN; + break; + } + + MediaKeyEventInit initializer; + initializer.keySystem = keySystem; + initializer.sessionId = sessionId; + initializer.errorCode = MediaKeyError::create(mediaKeyErrorCode); + initializer.systemCode = systemCode; + initializer.bubbles = false; + initializer.cancelable = false; + + RefPtrWillBeRawPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeyerror, initializer); + event->setTarget(&element); + element.scheduleEvent(event.release()); +} + +void HTMLMediaElementEncryptedMedia::keyMessage(HTMLMediaElement& element, const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength, const blink::WebURL& defaultURL) +{ + WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyMessage: sessionID=%s", sessionId.utf8().data()); + + MediaKeyEventInit initializer; + initializer.keySystem = keySystem; + initializer.sessionId = sessionId; + initializer.message = Uint8Array::create(message, messageLength); + initializer.defaultURL = KURL(defaultURL); + initializer.bubbles = false; + initializer.cancelable = false; + + RefPtrWillBeRawPtr<Event> event = MediaKeyEvent::create(EventTypeNames::webkitkeymessage, initializer); + event->setTarget(&element); + element.scheduleEvent(event.release()); +} + +void HTMLMediaElementEncryptedMedia::keyNeeded(HTMLMediaElement& element, const String& contentType, const unsigned char* initData, unsigned initDataLength) +{ + WTF_LOG(Media, "HTMLMediaElementEncryptedMedia::mediaPlayerKeyNeeded: contentType=%s", contentType.utf8().data()); + + if (RuntimeEnabledFeatures::encryptedMediaEnabled()) { + // Send event for WD EME. + RefPtrWillBeRawPtr<Event> event = createNeedKeyEvent(contentType, initData, initDataLength); + event->setTarget(&element); + element.scheduleEvent(event.release()); + } + + if (RuntimeEnabledFeatures::prefixedEncryptedMediaEnabled()) { + // Send event for v0.1b EME. + RefPtrWillBeRawPtr<Event> event = createWebkitNeedKeyEvent(contentType, initData, initDataLength); + event->setTarget(&element); + element.scheduleEvent(event.release()); + } +} + +void HTMLMediaElementEncryptedMedia::playerDestroyed(HTMLMediaElement& element) +{ +#if ENABLE(OILPAN) + // FIXME: Oilpan: remove this once the media player is on the heap. crbug.com/378229 + if (element.isFinalizing()) + return; +#endif + + HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(element); + thisElement.setMediaKeysInternal(element, 0); +} + +blink::WebContentDecryptionModule* HTMLMediaElementEncryptedMedia::contentDecryptionModule(HTMLMediaElement& element) +{ + HTMLMediaElementEncryptedMedia& thisElement = HTMLMediaElementEncryptedMedia::from(element); + return thisElement.contentDecryptionModule(); +} + +void HTMLMediaElementEncryptedMedia::trace(Visitor* visitor) +{ + visitor->trace(m_mediaKeys); + WillBeHeapSupplement<HTMLMediaElement>::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h b/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h new file mode 100644 index 00000000000..7ba1d023fc2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.h @@ -0,0 +1,84 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HTMLMediaElementEncryptedMedia_h +#define HTMLMediaElementEncryptedMedia_h + +#include "modules/EventTargetModules.h" +#include "platform/Supplementable.h" +#include "platform/graphics/media/MediaPlayer.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebMediaPlayerClient.h" +#include "wtf/Forward.h" + +namespace WebCore { + +class ExceptionState; +class HTMLMediaElement; +class MediaKeys; + +class HTMLMediaElementEncryptedMedia FINAL : public NoBaseWillBeGarbageCollected<HTMLMediaElementEncryptedMedia>, public WillBeHeapSupplement<HTMLMediaElement> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLMediaElementEncryptedMedia); + DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(HTMLMediaElementEncryptedMedia); +public: + // encrypted media extensions (v0.1b) + static void webkitGenerateKeyRequest(HTMLMediaElement&, const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState&); + static void webkitGenerateKeyRequest(HTMLMediaElement&, const String& keySystem, ExceptionState&); + static void webkitAddKey(HTMLMediaElement&, const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState&); + static void webkitAddKey(HTMLMediaElement&, const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState&); + static void webkitCancelKeyRequest(HTMLMediaElement&, const String& keySystem, const String& sessionId, ExceptionState&); + + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(webkitkeyadded); + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(webkitkeyerror); + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(webkitkeymessage); + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(webkitneedkey); + + // encrypted media extensions (WD) + static MediaKeys* mediaKeys(HTMLMediaElement&); + static void setMediaKeys(HTMLMediaElement&, MediaKeys*, ExceptionState&); + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(needkey); + + static void keyAdded(HTMLMediaElement&, const String& keySystem, const String& sessionId); + static void keyError(HTMLMediaElement&, const String& keySystem, const String& sessionId, blink::WebMediaPlayerClient::MediaKeyErrorCode, unsigned short systemCode); + static void keyMessage(HTMLMediaElement&, const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength, const blink::WebURL& defaultURL); + static void keyNeeded(HTMLMediaElement&, const String& contentType, const unsigned char* initData, unsigned initDataLength); + static void playerDestroyed(HTMLMediaElement&); + static blink::WebContentDecryptionModule* contentDecryptionModule(HTMLMediaElement&); + + static HTMLMediaElementEncryptedMedia& from(HTMLMediaElement&); + static const char* supplementName(); + + virtual void trace(Visitor*) OVERRIDE; + +private: + HTMLMediaElementEncryptedMedia(); + void generateKeyRequest(blink::WebMediaPlayer*, const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState&); + void addKey(blink::WebMediaPlayer*, const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState&); + void cancelKeyRequest(blink::WebMediaPlayer*, const String& keySystem, const String& sessionId, ExceptionState&); + + // EventTarget + bool setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>); + EventListener* getAttributeEventListener(const AtomicString& eventType); + + // Currently we have both EME v0.1b and EME WD implemented in media element. + // But we do not want to support both at the same time. The one used first + // will be supported. Use |m_emeMode| to track this selection. + // FIXME: Remove EmeMode once EME v0.1b support is removed. See crbug.com/249976. + enum EmeMode { EmeModeNotSelected, EmeModePrefixed, EmeModeUnprefixed }; + + // check (and set if necessary) the encrypted media extensions (EME) mode + // (v0.1b or WD). Returns whether the mode is allowed and successfully set. + bool setEmeMode(EmeMode, ExceptionState&); + + blink::WebContentDecryptionModule* contentDecryptionModule(); + void setMediaKeysInternal(HTMLMediaElement&, MediaKeys*); + + EmeMode m_emeMode; + + PersistentWillBeMember<MediaKeys> m_mediaKeys; +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.idl b/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.idl new file mode 100644 index 00000000000..52cd222a5a3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/HTMLMediaElementEncryptedMedia.idl @@ -0,0 +1,18 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +partial interface HTMLMediaElement { + [RuntimeEnabled=PrefixedEncryptedMedia, RaisesException, MeasureAs=PrefixedMediaGenerateKeyRequest] void webkitGenerateKeyRequest([TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString keySystem, optional Uint8Array initData); + [RuntimeEnabled=PrefixedEncryptedMedia, RaisesException, MeasureAs=PrefixedMediaAddKey] void webkitAddKey([TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString keySystem, Uint8Array key, optional Uint8Array initData, optional DOMString sessionId = null); + [RuntimeEnabled=PrefixedEncryptedMedia, RaisesException, MeasureAs=PrefixedMediaCancelKeyRequest] void webkitCancelKeyRequest([TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString keySystem, optional DOMString sessionId = null); + + [RuntimeEnabled=PrefixedEncryptedMedia] attribute EventHandler onwebkitkeyadded; + [RuntimeEnabled=PrefixedEncryptedMedia] attribute EventHandler onwebkitkeyerror; + [RuntimeEnabled=PrefixedEncryptedMedia] attribute EventHandler onwebkitkeymessage; + [RuntimeEnabled=PrefixedEncryptedMedia] attribute EventHandler onwebkitneedkey; + + [RuntimeEnabled=EncryptedMedia] readonly attribute MediaKeys mediaKeys; + [RuntimeEnabled=EncryptedMedia, RaisesException, TypeChecking=Interface|Nullable] void setMediaKeys(MediaKeys? mediaKeys); + [RuntimeEnabled=EncryptedMedia] attribute EventHandler onneedkey; +}; diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.cpp b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.cpp index 86b0e57bedc..3874a818071 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "modules/encryptedmedia/MediaKeyMessageEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "wtf/Uint8Array.h" namespace WebCore { @@ -57,4 +56,9 @@ const AtomicString& MediaKeyMessageEvent::interfaceName() const return EventNames::MediaKeyMessageEvent; } +void MediaKeyMessageEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.h b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.h index bf3ef1e9ef8..a512101ba94 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.h +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.h @@ -27,8 +27,8 @@ #ifndef MediaKeyMessageEvent_h #define MediaKeyMessageEvent_h -#include "core/events/Event.h" #include "core/html/MediaKeyError.h" +#include "modules/EventModules.h" namespace WebCore { @@ -39,18 +39,18 @@ struct MediaKeyMessageEventInit : public EventInit { String destinationURL; }; -class MediaKeyMessageEvent : public Event { +class MediaKeyMessageEvent FINAL : public Event { public: virtual ~MediaKeyMessageEvent(); - static PassRefPtr<MediaKeyMessageEvent> create() + static PassRefPtrWillBeRawPtr<MediaKeyMessageEvent> create() { - return adoptRef(new MediaKeyMessageEvent); + return adoptRefWillBeNoop(new MediaKeyMessageEvent); } - static PassRefPtr<MediaKeyMessageEvent> create(const AtomicString& type, const MediaKeyMessageEventInit& initializer) + static PassRefPtrWillBeRawPtr<MediaKeyMessageEvent> create(const AtomicString& type, const MediaKeyMessageEventInit& initializer) { - return adoptRef(new MediaKeyMessageEvent(type, initializer)); + return adoptRefWillBeNoop(new MediaKeyMessageEvent(type, initializer)); } virtual const AtomicString& interfaceName() const OVERRIDE; @@ -58,6 +58,8 @@ public: Uint8Array* message() const { return m_message.get(); } String destinationURL() const { return m_destinationURL; } + virtual void trace(Visitor*) OVERRIDE; + private: MediaKeyMessageEvent(); MediaKeyMessageEvent(const AtomicString& type, const MediaKeyMessageEventInit& initializer); diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.idl b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.idl index a7eaf905e5d..67bc8f41e05 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.idl +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyMessageEvent.idl @@ -25,7 +25,7 @@ [ EventConstructor, - RuntimeEnabled=EncryptedMedia, + RuntimeEnabled=EncryptedMedia ] interface MediaKeyMessageEvent : Event { readonly attribute Uint8Array message; [InitializedByEventConstructor] readonly attribute DOMString destinationURL; diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.cpp b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.cpp index 10c264fdb08..2c4ee4851d8 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "modules/encryptedmedia/MediaKeyNeededEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "wtf/Uint8Array.h" namespace WebCore { @@ -42,6 +41,7 @@ MediaKeyNeededEvent::MediaKeyNeededEvent() MediaKeyNeededEvent::MediaKeyNeededEvent(const AtomicString& type, const MediaKeyNeededEventInit& initializer) : Event(type, initializer) + , m_contentType(initializer.contentType) , m_initData(initializer.initData) { ScriptWrappable::init(this); @@ -56,4 +56,9 @@ const AtomicString& MediaKeyNeededEvent::interfaceName() const return EventNames::MediaKeyNeededEvent; } +void MediaKeyNeededEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.h b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.h index 910a9d003c9..c74aa27097c 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.h +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.h @@ -26,39 +26,44 @@ #ifndef MediaKeyNeededEvent_h #define MediaKeyNeededEvent_h -#include "core/events/Event.h" #include "core/html/MediaKeyError.h" +#include "modules/EventModules.h" namespace WebCore { struct MediaKeyNeededEventInit : public EventInit { MediaKeyNeededEventInit(); + String contentType; RefPtr<Uint8Array> initData; }; -class MediaKeyNeededEvent : public Event { +class MediaKeyNeededEvent FINAL : public Event { public: virtual ~MediaKeyNeededEvent(); - static PassRefPtr<MediaKeyNeededEvent> create() + static PassRefPtrWillBeRawPtr<MediaKeyNeededEvent> create() { - return adoptRef(new MediaKeyNeededEvent); + return adoptRefWillBeNoop(new MediaKeyNeededEvent); } - static PassRefPtr<MediaKeyNeededEvent> create(const AtomicString& type, const MediaKeyNeededEventInit& initializer) + static PassRefPtrWillBeRawPtr<MediaKeyNeededEvent> create(const AtomicString& type, const MediaKeyNeededEventInit& initializer) { - return adoptRef(new MediaKeyNeededEvent(type, initializer)); + return adoptRefWillBeNoop(new MediaKeyNeededEvent(type, initializer)); } virtual const AtomicString& interfaceName() const OVERRIDE; + String contentType() const { return m_contentType; } Uint8Array* initData() const { return m_initData.get(); } + virtual void trace(Visitor*) OVERRIDE; + private: MediaKeyNeededEvent(); MediaKeyNeededEvent(const AtomicString& type, const MediaKeyNeededEventInit& initializer); + String m_contentType; RefPtr<Uint8Array> m_initData; }; diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.idl b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.idl index 878813f5302..c99a180b5e1 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.idl +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeyNeededEvent.idl @@ -25,8 +25,9 @@ [ EventConstructor, - RuntimeEnabled=EncryptedMedia, + RuntimeEnabled=EncryptedMedia ] interface MediaKeyNeededEvent : Event { + readonly attribute DOMString contentType; readonly attribute Uint8Array initData; }; diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp index 0760ee356b0..b7d37d6a1af 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.cpp @@ -27,55 +27,74 @@ #include "modules/encryptedmedia/MediaKeySession.h" #include "bindings/v8/ExceptionState.h" -#include "core/events/Event.h" #include "core/dom/ExceptionCode.h" #include "core/events/GenericEventQueue.h" #include "core/html/MediaKeyError.h" #include "modules/encryptedmedia/MediaKeyMessageEvent.h" #include "modules/encryptedmedia/MediaKeys.h" -#include "platform/drm/ContentDecryptionModule.h" +#include "platform/Logging.h" +#include "public/platform/WebContentDecryptionModule.h" +#include "public/platform/WebString.h" +#include "public/platform/WebURL.h" namespace WebCore { -PassRefPtr<MediaKeySession> MediaKeySession::create(ExecutionContext* context, ContentDecryptionModule* cdm, MediaKeys* keys) +PassOwnPtr<MediaKeySession::PendingAction> MediaKeySession::PendingAction::CreatePendingUpdate(PassRefPtr<Uint8Array> data) { - return adoptRef(new MediaKeySession(context, cdm, keys)); + ASSERT(data); + return adoptPtr(new PendingAction(Update, data)); } -MediaKeySession::MediaKeySession(ExecutionContext* context, ContentDecryptionModule* cdm, MediaKeys* keys) - : ContextLifecycleObserver(context) - , m_keySystem(keys->keySystem()) - , m_asyncEventQueue(GenericEventQueue::create(this)) - , m_session(cdm->createSession(this)) - , m_keys(keys) - , m_keyRequestTimer(this, &MediaKeySession::keyRequestTimerFired) - , m_addKeyTimer(this, &MediaKeySession::addKeyTimerFired) +PassOwnPtr<MediaKeySession::PendingAction> MediaKeySession::PendingAction::CreatePendingRelease() { - ScriptWrappable::init(this); + return adoptPtr(new PendingAction(Release, PassRefPtr<Uint8Array>())); } -MediaKeySession::~MediaKeySession() +MediaKeySession::PendingAction::PendingAction(Type type, PassRefPtr<Uint8Array> data) + : type(type) + , data(data) { - close(); } -void MediaKeySession::setError(MediaKeyError* error) +MediaKeySession::PendingAction::~PendingAction() { - m_error = error; } -void MediaKeySession::close() +MediaKeySession* MediaKeySession::create(ExecutionContext* context, blink::WebContentDecryptionModule* cdm, MediaKeys* keys) { - ASSERT(!m_keys == !m_session); + MediaKeySession* session = adoptRefCountedGarbageCollectedWillBeNoop(new MediaKeySession(context, cdm, keys)); + session->suspendIfNeeded(); + return session; +} - if (m_session) - m_session->close(); +MediaKeySession::MediaKeySession(ExecutionContext* context, blink::WebContentDecryptionModule* cdm, MediaKeys* keys) + : ActiveDOMObject(context) + , m_keySystem(keys->keySystem()) + , m_asyncEventQueue(GenericEventQueue::create(this)) + , m_session(adoptPtr(cdm->createSession(this))) + , m_keys(keys) + , m_isClosed(false) + , m_actionTimer(this, &MediaKeySession::actionTimerFired) +{ + WTF_LOG(Media, "MediaKeySession::MediaKeySession"); + ScriptWrappable::init(this); + ASSERT(m_session); +} + +MediaKeySession::~MediaKeySession() +{ m_session.clear(); +#if !ENABLE(OILPAN) + // MediaKeySession and m_asyncEventQueue always become unreachable + // together. So MediaKeySession and m_asyncEventQueue are destructed in the + // same GC. We don't need to call cancelAllEvents explicitly in Oilpan. m_asyncEventQueue->cancelAllEvents(); +#endif +} - // FIXME: Release ref that MediaKeys has by removing it from m_sessions. - // if (m_keys) m_keys->sessionClosed(this); - m_keys = 0; +void MediaKeySession::setError(MediaKeyError* error) +{ + m_error = error; } String MediaKeySession::sessionId() const @@ -83,84 +102,131 @@ String MediaKeySession::sessionId() const return m_session->sessionId(); } -void MediaKeySession::generateKeyRequest(const String& mimeType, Uint8Array* initData) +void MediaKeySession::initializeNewSession(const String& mimeType, const Uint8Array& initData) { - m_pendingKeyRequests.append(PendingKeyRequest(mimeType, initData)); - // FIXME: Eliminate timers. Asynchronicity will be handled in Chromium. - m_keyRequestTimer.startOneShot(0); + ASSERT(!m_isClosed); + m_session->initializeNewSession(mimeType, initData.data(), initData.length()); } -void MediaKeySession::keyRequestTimerFired(Timer<MediaKeySession>*) +void MediaKeySession::update(Uint8Array* response, ExceptionState& exceptionState) { - ASSERT(m_pendingKeyRequests.size()); - if (!m_session) - return; + WTF_LOG(Media, "MediaKeySession::update"); + ASSERT(!m_isClosed); - while (!m_pendingKeyRequests.isEmpty()) { - PendingKeyRequest request = m_pendingKeyRequests.takeFirst(); + // From <https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-update>: + // The update(response) method must run the following steps: + // 1. If response is an empty array, throw an INVALID_ACCESS_ERR + // exception and abort these steps. + if (!response->length()) { + exceptionState.throwDOMException(InvalidAccessError, String::format("The response argument provided is %s.", response ? "an empty array" : "invalid")); + return; + } - // NOTE: Continued from step 5 in MediaKeys::createSession(). - // The user agent will asynchronously execute the following steps in the task: + // 2. If the session is not in the PENDING state, throw an INVALID_STATE_ERR. + // FIXME: Implement states in MediaKeySession. - // 1. Let cdm be the cdm loaded in the MediaKeys constructor. - // 2. Let destinationURL be null. + // 3. Schedule a task to handle the call, providing response. + m_pendingActions.append(PendingAction::CreatePendingUpdate(response)); - // 3. Use cdm to generate a key request and follow the steps for the first matching condition from the following list: - m_session->generateKeyRequest(request.mimeType, *request.initData); - } + if (!m_actionTimer.isActive()) + m_actionTimer.startOneShot(0, FROM_HERE); } -void MediaKeySession::update(Uint8Array* key, ExceptionState& exceptionState) +void MediaKeySession::release(ExceptionState& exceptionState) { - // From <http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-addkey>: - // The addKey(key) method must run the following steps: - // 1. If the first or second argument [sic] is null or an empty array, throw an InvalidAccessError. - // NOTE: the reference to a "second argument" is a spec bug. - if (!key || !key->length()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } + WTF_LOG(Media, "MediaKeySession::release"); + ASSERT(!m_isClosed); - // 2. Schedule a task to handle the call, providing key. - m_pendingKeys.append(key); - m_addKeyTimer.startOneShot(0); + // From <https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-release>: + // The release() method must run the following steps: + // 1. If the state of the MediaKeySession is CLOSED then abort these steps. + // 2. If the state of the MediaKeySession is ERROR, throw an INVALID_STATE_ERR + // exception and abort these steps. + // FIXME: Implement states in MediaKeySession. + + // 3. Schedule a task to handle the call. + m_pendingActions.append(PendingAction::CreatePendingRelease()); + + if (!m_actionTimer.isActive()) + m_actionTimer.startOneShot(0, FROM_HERE); } -void MediaKeySession::addKeyTimerFired(Timer<MediaKeySession>*) +void MediaKeySession::actionTimerFired(Timer<MediaKeySession>*) { - ASSERT(m_pendingKeys.size()); - if (!m_session) - return; + ASSERT(m_pendingActions.size()); - while (!m_pendingKeys.isEmpty()) { - RefPtr<Uint8Array> pendingKey = m_pendingKeys.takeFirst(); + while (!m_pendingActions.isEmpty()) { + OwnPtr<PendingAction> pendingAction(m_pendingActions.takeFirst()); - // NOTE: Continued from step 2. of MediaKeySession::update() - // 2.1. Let cdm be the cdm loaded in the MediaKeys constructor. - // NOTE: This is m_session. - // 2.2. Let 'did store key' be false. - // 2.3. Let 'next message' be null. - // 2.4. Use cdm to handle key. - m_session->update(*pendingKey); + switch (pendingAction->type) { + case PendingAction::Update: + // NOTE: Continued from step 3. of MediaKeySession::update() + // 3.1. Let cdm be the cdm loaded in the MediaKeys constructor. + // 3.2. Let request be null. + // 3.3. Use cdm to execute the following steps: + // 3.3.1 Process response. + m_session->update(pendingAction->data->data(), pendingAction->data->length()); + break; + case PendingAction::Release: + // NOTE: Continued from step 3. of MediaKeySession::release(). + // 3.1 Let cdm be the cdm loaded in the MediaKeys constructor. + // 3.2 Use cdm to execute the following steps: + // 3.2.1 Process the release request. + m_session->release(); + break; + } } } -void MediaKeySession::keyAdded() +// Queue a task to fire a simple event named keymessage at the new object +void MediaKeySession::message(const unsigned char* message, size_t messageLength, const blink::WebURL& destinationURL) +{ + WTF_LOG(Media, "MediaKeySession::message"); + + MediaKeyMessageEventInit init; + init.bubbles = false; + init.cancelable = false; + init.message = Uint8Array::create(message, messageLength); + init.destinationURL = destinationURL.string(); + + RefPtrWillBeRawPtr<MediaKeyMessageEvent> event = MediaKeyMessageEvent::create(EventTypeNames::message, init); + event->setTarget(this); + m_asyncEventQueue->enqueueEvent(event.release()); +} + +void MediaKeySession::ready() { - RefPtr<Event> event = Event::create(EventTypeNames::webkitkeyadded); + WTF_LOG(Media, "MediaKeySession::ready"); + + RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::ready); event->setTarget(this); m_asyncEventQueue->enqueueEvent(event.release()); } +void MediaKeySession::close() +{ + WTF_LOG(Media, "MediaKeySession::close"); + + RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::close); + event->setTarget(this); + m_asyncEventQueue->enqueueEvent(event.release()); + + // Once closed, the session can no longer be the target of events from + // the CDM so this object can be garbage collected. + m_isClosed = true; +} + // Queue a task to fire a simple event named keyadded at the MediaKeySession object. -void MediaKeySession::keyError(MediaKeyErrorCode errorCode, unsigned long systemCode) +void MediaKeySession::error(MediaKeyErrorCode errorCode, unsigned long systemCode) { + WTF_LOG(Media, "MediaKeySession::error: errorCode=%d, systemCode=%lu", errorCode, systemCode); + MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; switch (errorCode) { - case UnknownError: + case MediaKeyErrorCodeUnknown: mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN; break; - case ClientError: + case MediaKeyErrorCodeClient: mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT; break; } @@ -172,23 +238,30 @@ void MediaKeySession::keyError(MediaKeyErrorCode errorCode, unsigned long system m_error = MediaKeyError::create(mediaKeyErrorCode, systemCode); // 3. queue a task to fire a simple event named keyerror at the MediaKeySession object. - RefPtr<Event> event = Event::create(EventTypeNames::webkitkeyerror); + RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::error); event->setTarget(this); m_asyncEventQueue->enqueueEvent(event.release()); } -// Queue a task to fire a simple event named keymessage at the new object -void MediaKeySession::keyMessage(const unsigned char* message, size_t messageLength, const KURL& destinationURL) +void MediaKeySession::error(blink::WebContentDecryptionModuleException exception, unsigned long systemCode, const blink::WebString& errorMessage) { - MediaKeyMessageEventInit init; - init.bubbles = false; - init.cancelable = false; - init.message = Uint8Array::create(message, messageLength); - init.destinationURL = destinationURL; + WTF_LOG(Media, "MediaKeySession::error: exception=%d, systemCode=%lu", exception, systemCode); - RefPtr<MediaKeyMessageEvent> event = MediaKeyMessageEvent::create(EventTypeNames::webkitkeymessage, init); - event->setTarget(this); - m_asyncEventQueue->enqueueEvent(event.release()); + // FIXME: EME-WD MediaKeyError now derives from DOMException. Figure out how + // to implement this without breaking prefixed EME, which has a totally + // different definition. The spec may also change to be just a DOMException. + // For now, simply generate an existing MediaKeyError. + MediaKeyErrorCode errorCode; + switch (exception) { + case blink::WebContentDecryptionModuleExceptionClientError: + errorCode = MediaKeyErrorCodeClient; + break; + default: + // All other exceptions get converted into Unknown. + errorCode = MediaKeyErrorCodeUnknown; + break; + } + error(errorCode, systemCode); } const AtomicString& MediaKeySession::interfaceName() const @@ -198,7 +271,36 @@ const AtomicString& MediaKeySession::interfaceName() const ExecutionContext* MediaKeySession::executionContext() const { - return ContextLifecycleObserver::executionContext(); + return ActiveDOMObject::executionContext(); +} + +bool MediaKeySession::hasPendingActivity() const +{ + // Remain around if there are pending events or MediaKeys is still around + // and we're not closed. + return ActiveDOMObject::hasPendingActivity() + || !m_pendingActions.isEmpty() + || m_asyncEventQueue->hasPendingEvents() + || (m_keys && !m_isClosed); +} + +void MediaKeySession::stop() +{ + // Stop the CDM from firing any more events for this session. + m_session.clear(); + m_isClosed = true; + + if (m_actionTimer.isActive()) + m_actionTimer.stop(); + m_pendingActions.clear(); + m_asyncEventQueue->close(); +} + +void MediaKeySession::trace(Visitor* visitor) +{ + visitor->trace(m_asyncEventQueue); + visitor->trace(m_keys); + EventTargetWithInlineData::trace(visitor); } } diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.h b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.h index 26ad01f7e48..903fa8bd000 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.h +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.h @@ -27,36 +27,50 @@ #define MediaKeySession_h #include "bindings/v8/ScriptWrappable.h" -#include "core/dom/ContextLifecycleObserver.h" -#include "core/events/EventTarget.h" +#include "core/dom/ActiveDOMObject.h" +#include "modules/EventTargetModules.h" #include "platform/Timer.h" -#include "platform/drm/ContentDecryptionModuleSession.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebContentDecryptionModuleSession.h" #include "wtf/Deque.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/Uint8Array.h" +#include "wtf/WeakPtr.h" #include "wtf/text/WTFString.h" +namespace blink { +class WebContentDecryptionModule; +} + namespace WebCore { -class ContentDecryptionModule; -class ContentDecryptionModuleSession; class ExceptionState; class GenericEventQueue; class MediaKeyError; class MediaKeys; -// References are held by JS and MediaKeys. -// Because this object controls the lifetime of the ContentDecryptionModuleSession, -// it may outlive any references to it as long as the MediaKeys object is alive. -// The ContentDecryptionModuleSession has the same lifetime as this object. -class MediaKeySession - : public RefCounted<MediaKeySession>, public ScriptWrappable, public EventTargetWithInlineData, public ContextLifecycleObserver - , private ContentDecryptionModuleSessionClient { - REFCOUNTED_EVENT_TARGET(MediaKeySession); +// References are held by JS only. However, even if all JS references are +// dropped, it won't be garbage collected until close event received or +// MediaKeys goes away (as determined by the validity of a WeakPtr). This allows +// the CDM to continue to fire events for this session, as long as the session +// is open. +// +// WeakPtr<MediaKeys> is used instead of having MediaKeys and MediaKeySession +// keep references to each other, and then having to inform the other object +// when it gets destroyed. +// +// Because this object controls the lifetime of the WebContentDecryptionModuleSession, +// it may outlive any JavaScript references as long as the MediaKeys object is alive. +// The WebContentDecryptionModuleSession has the same lifetime as this object. +class MediaKeySession FINAL + : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<MediaKeySession>, public ActiveDOMObject, public ScriptWrappable, public EventTargetWithInlineData + , private blink::WebContentDecryptionModuleSession::Client { + DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<MediaKeySession>); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaKeySession); public: - static PassRefPtr<MediaKeySession> create(ExecutionContext*, ContentDecryptionModule*, MediaKeys*); - ~MediaKeySession(); + static MediaKeySession* create(ExecutionContext*, blink::WebContentDecryptionModule*, MediaKeys*); + virtual ~MediaKeySession(); const String& keySystem() const { return m_keySystem; } String sessionId() const; @@ -64,46 +78,63 @@ public: void setError(MediaKeyError*); MediaKeyError* error() { return m_error.get(); } - void generateKeyRequest(const String& mimeType, Uint8Array* initData); - void update(Uint8Array* key, ExceptionState&); - void close(); - - void enqueueEvent(PassRefPtr<Event>); + void initializeNewSession(const String& mimeType, const Uint8Array& initData); + void update(Uint8Array* response, ExceptionState&); + void release(ExceptionState&); - DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeyadded); - DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeyerror); - DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeymessage); + void enqueueEvent(PassRefPtrWillBeRawPtr<Event>); + // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE; + // ActiveDOMObject + virtual bool hasPendingActivity() const OVERRIDE; + virtual void stop() OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; + private: - MediaKeySession(ExecutionContext*, ContentDecryptionModule*, MediaKeys*); - void keyRequestTimerFired(Timer<MediaKeySession>*); - void addKeyTimerFired(Timer<MediaKeySession>*); + // A struct holding the pending action. + struct PendingAction { + enum Type { + Update, + Release + }; + const Type type; + const RefPtr<Uint8Array> data; + + static PassOwnPtr<PendingAction> CreatePendingUpdate(PassRefPtr<Uint8Array> data); + static PassOwnPtr<PendingAction> CreatePendingRelease(); + ~PendingAction(); + + private: + PendingAction(Type, PassRefPtr<Uint8Array> data); + }; + + MediaKeySession(ExecutionContext*, blink::WebContentDecryptionModule*, MediaKeys*); + void actionTimerFired(Timer<MediaKeySession>*); - // ContentDecryptionModuleSessionClient - virtual void keyAdded() OVERRIDE; - virtual void keyError(MediaKeyErrorCode, unsigned long systemCode) OVERRIDE; - virtual void keyMessage(const unsigned char* message, size_t messageLength, const KURL& destinationURL) OVERRIDE; + // blink::WebContentDecryptionModuleSession::Client + virtual void message(const unsigned char* message, size_t messageLength, const blink::WebURL& destinationURL) OVERRIDE; + virtual void ready() OVERRIDE; + virtual void close() OVERRIDE; + virtual void error(MediaKeyErrorCode, unsigned long systemCode) OVERRIDE; + virtual void error(blink::WebContentDecryptionModuleException, unsigned long systemCode, const blink::WebString& errorMessage) OVERRIDE; String m_keySystem; RefPtr<MediaKeyError> m_error; - OwnPtr<GenericEventQueue> m_asyncEventQueue; - OwnPtr<ContentDecryptionModuleSession> m_session; - // Used to remove the reference from the parent MediaKeys when close()'d. - MediaKeys* m_keys; - - struct PendingKeyRequest { - PendingKeyRequest(const String& mimeType, Uint8Array* initData) : mimeType(mimeType), initData(initData) { } - String mimeType; - RefPtr<Uint8Array> initData; - }; - Deque<PendingKeyRequest> m_pendingKeyRequests; - Timer<MediaKeySession> m_keyRequestTimer; + OwnPtrWillBeMember<GenericEventQueue> m_asyncEventQueue; + OwnPtr<blink::WebContentDecryptionModuleSession> m_session; + + // Used to determine if MediaKeys is still active. + WeakMember<MediaKeys> m_keys; + + // Is the CDM finished with this session? + bool m_isClosed; - Deque<RefPtr<Uint8Array> > m_pendingKeys; - Timer<MediaKeySession> m_addKeyTimer; + Deque<OwnPtr<PendingAction> > m_pendingActions; + Timer<MediaKeySession> m_actionTimer; }; } diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.idl b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.idl index c0b7f8cf7a1..a5cf3338e91 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.idl +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeySession.idl @@ -21,10 +21,13 @@ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + */ [ - RuntimeEnabled=EncryptedMedia + ActiveDOMObject, + RuntimeEnabled=EncryptedMedia, + GarbageCollected, + TypeChecking=Interface|Nullable ] interface MediaKeySession : EventTarget { // error state readonly attribute MediaKeyError error; @@ -34,11 +37,6 @@ readonly attribute DOMString sessionId; // session operations - [RaisesException] void update(Uint8Array key); - void close(); - - // EventHandlers - [RuntimeEnabled=EncryptedMedia] attribute EventHandler onwebkitkeyadded; - [RuntimeEnabled=EncryptedMedia] attribute EventHandler onwebkitkeyerror; - [RuntimeEnabled=EncryptedMedia] attribute EventHandler onwebkitkeymessage; + [RaisesException] void update(Uint8Array response); + [RaisesException] void release(); }; diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.cpp b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.cpp index 285c58ac437..59e428313bb 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.cpp +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.cpp @@ -27,107 +27,176 @@ #include "modules/encryptedmedia/MediaKeys.h" #include "bindings/v8/ExceptionState.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/dom/ContextLifecycleObserver.h" +#include "core/dom/Document.h" +#include "core/dom/ExecutionContext.h" #include "core/html/HTMLMediaElement.h" #include "modules/encryptedmedia/MediaKeyMessageEvent.h" -#include "modules/encryptedmedia/MediaKeySession.h" +#include "modules/encryptedmedia/MediaKeysClient.h" +#include "modules/encryptedmedia/MediaKeysController.h" +#include "platform/ContentType.h" +#include "platform/Logging.h" +#include "platform/MIMETypeRegistry.h" #include "platform/UUID.h" -#include "platform/drm/ContentDecryptionModule.h" +#include "public/platform/Platform.h" +#include "public/platform/WebContentDecryptionModule.h" #include "wtf/HashSet.h" namespace WebCore { -PassRefPtr<MediaKeys> MediaKeys::create(const String& keySystem, ExceptionState& exceptionState) +static bool isKeySystemSupportedWithContentType(const String& keySystem, const String& contentType) +{ + ASSERT(!keySystem.isEmpty()); + + ContentType type(contentType); + String codecs = type.parameter("codecs"); + return MIMETypeRegistry::isSupportedEncryptedMediaMIMEType(keySystem, type.type(), codecs); +} + +MediaKeys* MediaKeys::create(ExecutionContext* context, const String& keySystem, ExceptionState& exceptionState) { // From <http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-media-keys-constructor>: // The MediaKeys(keySystem) constructor must run the following steps: - // 1. If keySystem is null or an empty string, throw an InvalidAccessError exception and abort these steps. + // 1. If keySystem is an empty string, throw an InvalidAccessError exception and abort these steps. if (keySystem.isEmpty()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, "The key system provided is invalid."); return 0; } // 2. If keySystem is not one of the user agent's supported Key Systems, throw a NotSupportedError and abort these steps. - if (!ContentDecryptionModule::supportsKeySystem(keySystem)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + if (!isKeySystemSupportedWithContentType(keySystem, "")) { + exceptionState.throwDOMException(NotSupportedError, "The '" + keySystem + "' key system is not supported."); return 0; } // 3. Let cdm be the content decryption module corresponding to keySystem. // 4. Load cdm if necessary. - OwnPtr<ContentDecryptionModule> cdm = ContentDecryptionModule::create(keySystem); + Document* document = toDocument(context); + MediaKeysController* controller = MediaKeysController::from(document->page()); + OwnPtr<blink::WebContentDecryptionModule> cdm = controller->createContentDecryptionModule(context, keySystem); if (!cdm) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + exceptionState.throwDOMException(NotSupportedError, "A content decryption module could not be loaded for the '" + keySystem + "' key system."); return 0; } // 5. Create a new MediaKeys object. // 5.1 Let the keySystem attribute be keySystem. // 6. Return the new object to the caller. - return adoptRef(new MediaKeys(keySystem, cdm.release())); + return new MediaKeys(context, keySystem, cdm.release()); } -MediaKeys::MediaKeys(const String& keySystem, PassOwnPtr<ContentDecryptionModule> cdm) - : m_mediaElement(0) +MediaKeys::MediaKeys(ExecutionContext* context, const String& keySystem, PassOwnPtr<blink::WebContentDecryptionModule> cdm) + : ContextLifecycleObserver(context) , m_keySystem(keySystem) , m_cdm(cdm) + , m_initializeNewSessionTimer(this, &MediaKeys::initializeNewSessionTimerFired) { + WTF_LOG(Media, "MediaKeys::MediaKeys"); ScriptWrappable::init(this); } MediaKeys::~MediaKeys() { - // From <http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-media-keys-constructor>: - // When destroying a MediaKeys object, follow the steps in close(). - for (size_t i = 0; i < m_sessions.size(); ++i) - m_sessions[i]->close(); } -PassRefPtr<MediaKeySession> MediaKeys::createSession(ExecutionContext* context, const String& type, Uint8Array* initData, ExceptionState& exceptionState) +MediaKeySession* MediaKeys::createSession(ExecutionContext* context, const String& contentType, Uint8Array* initData, ExceptionState& exceptionState) { + WTF_LOG(Media, "MediaKeys::createSession"); + // From <http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-createsession>: // The createSession(type, initData) method must run the following steps: // Note: The contents of initData are container-specific Initialization Data. - // 1. If type is null or an empty string and initData is not null or an empty string, throw an - // InvalidAccessError exception and abort these steps. - if ((type.isEmpty()) && (!initData || initData->length())) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + if (contentType.isEmpty()) { + exceptionState.throwDOMException(InvalidAccessError, "The contentType provided ('" + contentType + "') is empty."); + return 0; + } + + if (!initData->length()) { + exceptionState.throwDOMException(InvalidAccessError, "The initData provided is empty."); return 0; } - // 2. If type contains a MIME type that is not supported or is not supported by the keySystem, throw - // a NotSupportedError exception and abort these steps. - ASSERT(!type.isEmpty()); - if (type.isEmpty() || !m_cdm->supportsMIMEType(type)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + // 1. If type contains a MIME type that is not supported or is not supported by the keySystem, + // throw a NOT_SUPPORTED_ERR exception and abort these steps. + if (!isKeySystemSupportedWithContentType(m_keySystem, contentType)) { + exceptionState.throwDOMException(NotSupportedError, "The type provided ('" + contentType + "') is unsupported."); return 0; } - // 3. Create a new MediaKeySession object. - RefPtr<MediaKeySession> session = MediaKeySession::create(context, m_cdm.get(), this); - // 3.1 Let the keySystem attribute be keySystem. + // 2. Create a new MediaKeySession object. + MediaKeySession* session = MediaKeySession::create(context, m_cdm.get(), this); + // 2.1 Let the keySystem attribute be keySystem. ASSERT(!session->keySystem().isEmpty()); - // 3.2 Let the sessionId attribute be a unique Session ID string. It may be generated by cdm. - // This is handled by m_cdm and may happen asynchronously. + // FIXME: 2.2 Let the state of the session be CREATED. - // 4. Add the new object to an internal list of session objects. - m_sessions.append(session); + // 3. Add the new object to an internal list of session objects (not needed). - // 5. Schedule a task to generate a key request, providing type, initData, and the new object. - session->generateKeyRequest(type, initData); + // 4. Schedule a task to initialize the session, providing type, initData, and the new object. + m_pendingInitializeNewSessionData.append(InitializeNewSessionData(session, contentType, initData)); - // 6. Return the new object to the caller. + if (!m_initializeNewSessionTimer.isActive()) + m_initializeNewSessionTimer.startOneShot(0, FROM_HERE); + + // 5. Return the new object to the caller. return session; } -void MediaKeys::setMediaElement(HTMLMediaElement* element) +bool MediaKeys::isTypeSupported(const String& keySystem, const String& contentType) { - // FIXME: Cause HTMLMediaElement::setMediaKeys() to throw an exception if m_mediaElement is not 0. - // FIXME: Hook up the CDM to the WebMediaPlayer in Chromium. - ASSERT(!m_mediaElement); - m_mediaElement = element; + WTF_LOG(Media, "MediaKeys::isTypeSupported(%s, %s)", keySystem.ascii().data(), contentType.ascii().data()); + + // 1. If keySystem is an empty string, return false and abort these steps. + if (keySystem.isEmpty()) + return false; + + // 2. If keySystem contains an unrecognized or unsupported Key System, return false and abort + // these steps. Key system string comparison is case-sensitive. + if (!isKeySystemSupportedWithContentType(keySystem, "")) + return false; + + // 3. If contentType is an empty string, return true and abort these steps. + if (contentType.isEmpty()) + return true; + + // 4. If the Key System specified by keySystem does not support decrypting the container and/or + // codec specified by contentType, return false and abort these steps. + return isKeySystemSupportedWithContentType(keySystem, contentType); +} + +blink::WebContentDecryptionModule* MediaKeys::contentDecryptionModule() +{ + return m_cdm.get(); +} + +void MediaKeys::initializeNewSessionTimerFired(Timer<MediaKeys>*) +{ + ASSERT(m_pendingInitializeNewSessionData.size()); + + while (!m_pendingInitializeNewSessionData.isEmpty()) { + InitializeNewSessionData data = m_pendingInitializeNewSessionData.takeFirst(); + // FIXME: Refer to the spec to see what needs to be done in blink. + data.session->initializeNewSession(data.contentType, *data.initData); + } +} + +void MediaKeys::trace(Visitor* visitor) +{ + visitor->trace(m_pendingInitializeNewSessionData); +} + +void MediaKeys::InitializeNewSessionData::trace(Visitor* visitor) +{ + visitor->trace(session); +} + +void MediaKeys::contextDestroyed() +{ + ContextLifecycleObserver::contextDestroyed(); + + // We don't need the CDM anymore. + m_cdm.clear(); } } diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.h b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.h index bb2e0cd1921..9533b18ecd5 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.h +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.h @@ -27,44 +27,72 @@ #define MediaKeys_h #include "bindings/v8/ScriptWrappable.h" -#include "core/events/EventTarget.h" +#include "core/dom/ContextLifecycleObserver.h" +#include "core/dom/ExecutionContext.h" +#include "modules/EventTargetModules.h" +#include "modules/encryptedmedia/MediaKeySession.h" +#include "platform/Timer.h" +#include "platform/heap/Handle.h" +#include "wtf/Deque.h" #include "wtf/OwnPtr.h" -#include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/Uint8Array.h" #include "wtf/Vector.h" #include "wtf/text/WTFString.h" +namespace blink { +class WebContentDecryptionModule; +} + namespace WebCore { -class ContentDecryptionModule; -class MediaKeySession; class HTMLMediaElement; class ExceptionState; // References are held by JS and HTMLMediaElement. -// The ContentDecryptionModule has the same lifetime as this object. -// Maintains a reference to all MediaKeySessions created to ensure they live as -// long as this object unless explicitly close()'d. -class MediaKeys : public RefCounted<MediaKeys>, public ScriptWrappable { +// The WebContentDecryptionModule has the same lifetime as this object. +class MediaKeys : public GarbageCollectedFinalized<MediaKeys>, public ContextLifecycleObserver, public ScriptWrappable { public: - static PassRefPtr<MediaKeys> create(const String& keySystem, ExceptionState&); + static MediaKeys* create(ExecutionContext*, const String& keySystem, ExceptionState&); ~MediaKeys(); - PassRefPtr<MediaKeySession> createSession(ExecutionContext*, const String& mimeType, Uint8Array* initData, ExceptionState&); - const String& keySystem() const { return m_keySystem; } - void setMediaElement(HTMLMediaElement*); + MediaKeySession* createSession(ExecutionContext*, const String& contentType, Uint8Array* initData, ExceptionState&); -protected: - MediaKeys(const String& keySystem, PassOwnPtr<ContentDecryptionModule>); + static bool isTypeSupported(const String& keySystem, const String& contentType); + + blink::WebContentDecryptionModule* contentDecryptionModule(); + + void trace(Visitor*); - Vector<RefPtr<MediaKeySession> > m_sessions; + // ContextLifecycleObserver + virtual void contextDestroyed() OVERRIDE; + +protected: + MediaKeys(ExecutionContext*, const String& keySystem, PassOwnPtr<blink::WebContentDecryptionModule>); + void initializeNewSessionTimerFired(Timer<MediaKeys>*); - HTMLMediaElement* m_mediaElement; const String m_keySystem; - OwnPtr<ContentDecryptionModule> m_cdm; + OwnPtr<blink::WebContentDecryptionModule> m_cdm; + + // FIXME: Check whether |initData| can be changed by JS. Maybe we should not pass it as a pointer. + class InitializeNewSessionData { + ALLOW_ONLY_INLINE_ALLOCATION(); + public: + InitializeNewSessionData(MediaKeySession* session, const String& contentType, PassRefPtr<Uint8Array> initData) + : session(session) + , contentType(contentType) + , initData(initData) { } + + void trace(Visitor*); + + Member<MediaKeySession> session; + String contentType; + RefPtr<Uint8Array> initData; + }; + HeapDeque<InitializeNewSessionData> m_pendingInitializeNewSessionData; + Timer<MediaKeys> m_initializeNewSessionTimer; }; } diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.idl b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.idl index 9d99d435835..a17d8d903ca 100644 --- a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.idl +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.idl @@ -26,9 +26,14 @@ [ RuntimeEnabled=EncryptedMedia, Constructor(DOMString keySystem), - RaisesException=Constructor + ConstructorCallWith=ExecutionContext, + RaisesException=Constructor, + GarbageCollected, + TypeChecking=Interface|Nullable ] interface MediaKeys { - [CallWith=ExecutionContext, RaisesException] MediaKeySession createSession([Default=Undefined] optional DOMString type, [Default=Undefined] optional Uint8Array initData); - readonly attribute DOMString keySystem; + + [CallWith=ExecutionContext, RaisesException] MediaKeySession createSession(DOMString type, Uint8Array initData); + + static boolean isTypeSupported(DOMString keySystem, optional DOMString contentType = null); }; diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysClient.h b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysClient.h new file mode 100644 index 00000000000..2479156b86f --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysClient.h @@ -0,0 +1,33 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaKeysClient_h +#define MediaKeysClient_h + +#include "wtf/PassOwnPtr.h" +#include "wtf/text/WTFString.h" + +namespace blink { +class WebContentDecryptionModule; +} + +namespace WebCore { + +class ExecutionContext; +class Page; + +class MediaKeysClient { +public: + virtual PassOwnPtr<blink::WebContentDecryptionModule> createContentDecryptionModule(ExecutionContext*, const String& keySystem) = 0; + +protected: + virtual ~MediaKeysClient() { } +}; + +void provideMediaKeysTo(Page&, MediaKeysClient*); + +} // namespace WebCore + +#endif // MediaKeysClient_h + diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysController.cpp b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysController.cpp new file mode 100644 index 00000000000..6031c526fb9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysController.cpp @@ -0,0 +1,35 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/encryptedmedia/MediaKeysController.h" + +#include "modules/encryptedmedia/MediaKeysClient.h" +#include "public/platform/WebContentDecryptionModule.h" + +namespace WebCore { + +const char* MediaKeysController::supplementName() +{ + return "MediaKeysController"; +} + +MediaKeysController::MediaKeysController(MediaKeysClient* client) + : m_client(client) +{ +} + +PassOwnPtr<blink::WebContentDecryptionModule> MediaKeysController::createContentDecryptionModule(ExecutionContext* context, const String& keySystem) +{ + return m_client->createContentDecryptionModule(context, keySystem); +} + + +void MediaKeysController::provideMediaKeysTo(Page& page, MediaKeysClient* client) +{ + MediaKeysController::provideTo(page, supplementName(), adoptPtrWillBeNoop(new MediaKeysController(client))); +} + +} // namespace WebCore + diff --git a/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysController.h b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysController.h new file mode 100644 index 00000000000..ab0f2a18eee --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/encryptedmedia/MediaKeysController.h @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaKeysController_h +#define MediaKeysController_h + +#include "core/page/Page.h" +#include "wtf/PassOwnPtr.h" + +namespace blink { +class WebContentDecryptionModule; +} + +namespace WebCore { + +class ExecutionContext; +class MediaKeysClient; + +class MediaKeysController FINAL : public NoBaseWillBeGarbageCollected<MediaKeysController>, public WillBeHeapSupplement<Page> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaKeysController); +public: + PassOwnPtr<blink::WebContentDecryptionModule> createContentDecryptionModule(ExecutionContext*, const String& keySystem); + + static void provideMediaKeysTo(Page&, MediaKeysClient*); + static MediaKeysController* from(Page* page) { return static_cast<MediaKeysController*>(WillBeHeapSupplement<Page>::from(page, supplementName())); } + + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Page>::trace(visitor); } + +private: + explicit MediaKeysController(MediaKeysClient*); + static const char* supplementName(); + MediaKeysClient* m_client; +}; + +} // namespace WebCore + +#endif // MediaKeysController_h + diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFilePath.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFilePath.cpp index fd5b8077e2d..8016c927c6e 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFilePath.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFilePath.cpp @@ -33,6 +33,7 @@ #include "wtf/Vector.h" #include "wtf/text/CString.h" +#include "wtf/text/StringBuilder.h" namespace WebCore { @@ -46,11 +47,8 @@ String DOMFilePath::append(const String& base, const String& components) String DOMFilePath::ensureDirectoryPath(const String& path) { - if (!DOMFilePath::endsWithSeparator(path)) { - String newPath = path; - newPath.append(DOMFilePath::separator); - return newPath; - } + if (!DOMFilePath::endsWithSeparator(path)) + return path + DOMFilePath::separator; return path; } @@ -103,12 +101,12 @@ String DOMFilePath::removeExtraParentReferences(const String& path) } if (canonicalized.isEmpty()) return DOMFilePath::root; - String result; + StringBuilder result; for (size_t i = 0; i < canonicalized.size(); ++i) { result.append(DOMFilePath::separator); result.append(canonicalized[i]); } - return result; + return result.toString(); } bool DOMFilePath::isValidPath(const String& path) diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFilePath.h b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFilePath.h index bcfcdf6c811..8ce0cf64f97 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFilePath.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFilePath.h @@ -31,8 +31,6 @@ #ifndef DOMFilePath_h #define DOMFilePath_h -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.cpp index 7736ae85520..66ad0108025 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.cpp @@ -54,14 +54,14 @@ namespace WebCore { // static -PassRefPtr<DOMFileSystem> DOMFileSystem::create(ExecutionContext* context, const String& name, FileSystemType type, const KURL& rootURL) +DOMFileSystem* DOMFileSystem::create(ExecutionContext* context, const String& name, FileSystemType type, const KURL& rootURL) { - RefPtr<DOMFileSystem> fileSystem(adoptRef(new DOMFileSystem(context, name, type, rootURL))); + DOMFileSystem* fileSystem(new DOMFileSystem(context, name, type, rootURL)); fileSystem->suspendIfNeeded(); - return fileSystem.release(); + return fileSystem; } -PassRefPtr<DOMFileSystem> DOMFileSystem::createIsolatedFileSystem(ExecutionContext* context, const String& filesystemId) +DOMFileSystem* DOMFileSystem::createIsolatedFileSystem(ExecutionContext* context, const String& filesystemId) { if (filesystemId.isEmpty()) return 0; @@ -88,26 +88,34 @@ PassRefPtr<DOMFileSystem> DOMFileSystem::createIsolatedFileSystem(ExecutionConte DOMFileSystem::DOMFileSystem(ExecutionContext* context, const String& name, FileSystemType type, const KURL& rootURL) : DOMFileSystemBase(context, name, type, rootURL) , ActiveDOMObject(context) + , m_numberOfPendingCallbacks(0) { ScriptWrappable::init(this); } -PassRefPtr<DirectoryEntry> DOMFileSystem::root() +DirectoryEntry* DOMFileSystem::root() { return DirectoryEntry::create(this, DOMFilePath::root); } void DOMFileSystem::addPendingCallbacks() { - setPendingActivity(this); + ++m_numberOfPendingCallbacks; } void DOMFileSystem::removePendingCallbacks() { - unsetPendingActivity(this); + ASSERT(m_numberOfPendingCallbacks > 0); + --m_numberOfPendingCallbacks; } -void DOMFileSystem::reportError(PassOwnPtr<ErrorCallback> errorCallback, PassRefPtr<FileError> fileError) +bool DOMFileSystem::hasPendingActivity() const +{ + ASSERT(m_numberOfPendingCallbacks >= 0); + return m_numberOfPendingCallbacks; +} + +void DOMFileSystem::reportError(PassOwnPtr<ErrorCallback> errorCallback, PassRefPtrWillBeRawPtr<FileError> fileError) { scheduleCallback(errorCallback, fileError); } @@ -139,19 +147,19 @@ void DOMFileSystem::createWriter(const FileEntry* fileEntry, PassOwnPtr<FileWrit { ASSERT(fileEntry); - RefPtr<FileWriter> fileWriter = FileWriter::create(executionContext()); + FileWriter* fileWriter = FileWriter::create(executionContext()); OwnPtr<FileWriterBaseCallback> conversionCallback = ConvertToFileWriterCallback::create(successCallback); - OwnPtr<AsyncFileSystemCallbacks> callbacks = FileWriterBaseCallbacks::create(fileWriter, conversionCallback.release(), errorCallback); - fileSystem()->createFileWriter(createFileSystemURL(fileEntry), fileWriter.get(), callbacks.release()); + OwnPtr<AsyncFileSystemCallbacks> callbacks = FileWriterBaseCallbacks::create(fileWriter, conversionCallback.release(), errorCallback, m_context); + fileSystem()->createFileWriter(createFileSystemURL(fileEntry), fileWriter, callbacks.release()); } namespace { class SnapshotFileCallback : public FileSystemCallbacksBase { public: - static PassOwnPtr<AsyncFileSystemCallbacks> create(PassRefPtr<DOMFileSystem> filesystem, const String& name, const KURL& url, PassOwnPtr<FileCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) + static PassOwnPtr<AsyncFileSystemCallbacks> create(DOMFileSystem* filesystem, const String& name, const KURL& url, PassOwnPtr<FileCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context) { - return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new SnapshotFileCallback(filesystem, name, url, successCallback, errorCallback))); + return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new SnapshotFileCallback(filesystem, name, url, successCallback, errorCallback, context))); } virtual void didCreateSnapshotFile(const FileMetadata& metadata, PassRefPtr<BlobDataHandle> snapshot) @@ -182,8 +190,8 @@ public: } private: - SnapshotFileCallback(PassRefPtr<DOMFileSystem> filesystem, const String& name, const KURL& url, PassOwnPtr<FileCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) - : FileSystemCallbacksBase(errorCallback, filesystem.get()) + SnapshotFileCallback(DOMFileSystem* filesystem, const String& name, const KURL& url, PassOwnPtr<FileCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context) + : FileSystemCallbacksBase(errorCallback, filesystem, context) , m_name(name) , m_url(url) , m_successCallback(successCallback) @@ -200,7 +208,7 @@ private: void DOMFileSystem::createFile(const FileEntry* fileEntry, PassOwnPtr<FileCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) { KURL fileSystemURL = createFileSystemURL(fileEntry); - fileSystem()->createSnapshotFileAndReadMetadata(fileSystemURL, SnapshotFileCallback::create(this, fileEntry->name(), fileSystemURL, successCallback, errorCallback)); + fileSystem()->createSnapshotFileAndReadMetadata(fileSystemURL, SnapshotFileCallback::create(this, fileEntry->name(), fileSystemURL, successCallback, errorCallback, m_context)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.h b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.h index 1a4d059ed46..7f81372c9cb 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.h @@ -37,6 +37,7 @@ #include "core/dom/ExecutionContextTask.h" #include "modules/filesystem/DOMFileSystemBase.h" #include "modules/filesystem/EntriesCallback.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -46,19 +47,22 @@ class FileCallback; class FileEntry; class FileWriterCallback; -class DOMFileSystem : public DOMFileSystemBase, public ScriptWrappable, public ActiveDOMObject { +class DOMFileSystem FINAL : public DOMFileSystemBase, public ScriptWrappable, public ActiveDOMObject { public: - static PassRefPtr<DOMFileSystem> create(ExecutionContext*, const String& name, FileSystemType, const KURL& rootURL); + static DOMFileSystem* create(ExecutionContext*, const String& name, FileSystemType, const KURL& rootURL); // Creates a new isolated file system for the given filesystemId. - static PassRefPtr<DOMFileSystem> createIsolatedFileSystem(ExecutionContext*, const String& filesystemId); + static DOMFileSystem* createIsolatedFileSystem(ExecutionContext*, const String& filesystemId); - PassRefPtr<DirectoryEntry> root(); + DirectoryEntry* root(); // DOMFileSystemBase overrides. virtual void addPendingCallbacks() OVERRIDE; virtual void removePendingCallbacks() OVERRIDE; - virtual void reportError(PassOwnPtr<ErrorCallback>, PassRefPtr<FileError>) OVERRIDE; + virtual void reportError(PassOwnPtr<ErrorCallback>, PassRefPtrWillBeRawPtr<FileError>) OVERRIDE; + + // ActiveDOMObject overrides. + virtual bool hasPendingActivity() const OVERRIDE; void createWriter(const FileEntry*, PassOwnPtr<FileWriterCallback>, PassOwnPtr<ErrorCallback>); void createFile(const FileEntry*, PassOwnPtr<FileCallback>, PassOwnPtr<ErrorCallback>); @@ -66,19 +70,34 @@ public: // Schedule a callback. This should not cross threads (should be called on the same context thread). // FIXME: move this to a more generic place. template <typename CB, typename CBArg> - static void scheduleCallback(ExecutionContext*, PassOwnPtr<CB>, PassRefPtr<CBArg>); + static void scheduleCallback(ExecutionContext*, PassOwnPtr<CB>, PassRefPtrWillBeRawPtr<CBArg>); + + template <typename CB, typename CBArg> + static void scheduleCallback(ExecutionContext*, PassOwnPtr<CB>, CBArg*); + + template <typename CB, typename CBArg> + static void scheduleCallback(ExecutionContext*, PassOwnPtr<CB>, const HeapVector<CBArg>&); template <typename CB, typename CBArg> static void scheduleCallback(ExecutionContext*, PassOwnPtr<CB>, const CBArg&); + template <typename CB> + static void scheduleCallback(ExecutionContext*, PassOwnPtr<CB>); + + template <typename CB, typename CBArg> + void scheduleCallback(PassOwnPtr<CB> callback, PassRefPtrWillBeRawPtr<CBArg> callbackArg) + { + scheduleCallback(executionContext(), callback, callbackArg); + } + template <typename CB, typename CBArg> - void scheduleCallback(PassOwnPtr<CB> callback, PassRefPtr<CBArg> callbackArg) + void scheduleCallback(PassOwnPtr<CB> callback, CBArg* callbackArg) { scheduleCallback(executionContext(), callback, callbackArg); } template <typename CB, typename CBArg> - void scheduleCallback(PassOwnPtr<CB> callback, const CBArg& callbackArg) + void scheduleCallback(PassOwnPtr<CB> callback, const CBArg& callbackArg) { scheduleCallback(executionContext(), callback, callbackArg); } @@ -88,26 +107,45 @@ private: // A helper template to schedule a callback task. template <typename CB, typename CBArg> - class DispatchCallbacRefPtrArgTask : public ExecutionContextTask { + class DispatchCallbackRefPtrArgTask FINAL : public ExecutionContextTask { + public: + DispatchCallbackRefPtrArgTask(PassOwnPtr<CB> callback, PassRefPtrWillBeRawPtr<CBArg> arg) + : m_callback(callback) + , m_callbackArg(arg) + { + } + + virtual void performTask(ExecutionContext*) OVERRIDE + { + m_callback->handleEvent(m_callbackArg.get()); + } + + private: + OwnPtr<CB> m_callback; + RefPtrWillBePersistent<CBArg> m_callbackArg; + }; + + template <typename CB, typename CBArg> + class DispatchCallbackPtrArgTask FINAL : public ExecutionContextTask { public: - DispatchCallbacRefPtrArgTask(PassOwnPtr<CB> callback, PassRefPtr<CBArg> arg) + DispatchCallbackPtrArgTask(PassOwnPtr<CB> callback, CBArg* arg) : m_callback(callback) , m_callbackArg(arg) { } - virtual void performTask(ExecutionContext*) + virtual void performTask(ExecutionContext*) OVERRIDE { m_callback->handleEvent(m_callbackArg.get()); } private: OwnPtr<CB> m_callback; - RefPtr<CBArg> m_callbackArg; + Persistent<CBArg> m_callbackArg; }; template <typename CB, typename CBArg> - class DispatchCallbackNonPtrArgTask : public ExecutionContextTask { + class DispatchCallbackNonPtrArgTask FINAL : public ExecutionContextTask { public: DispatchCallbackNonPtrArgTask(PassOwnPtr<CB> callback, const CBArg& arg) : m_callback(callback) @@ -115,7 +153,7 @@ private: { } - virtual void performTask(ExecutionContext*) + virtual void performTask(ExecutionContext*) OVERRIDE { m_callback->handleEvent(m_callbackArg); } @@ -124,14 +162,49 @@ private: OwnPtr<CB> m_callback; CBArg m_callbackArg; }; + + template <typename CB> + class DispatchCallbackNoArgTask FINAL : public ExecutionContextTask { + public: + DispatchCallbackNoArgTask(PassOwnPtr<CB> callback) + : m_callback(callback) + { + } + + virtual void performTask(ExecutionContext*) OVERRIDE + { + m_callback->handleEvent(); + } + + private: + OwnPtr<CB> m_callback; + }; + + int m_numberOfPendingCallbacks; }; template <typename CB, typename CBArg> -void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, PassOwnPtr<CB> callback, PassRefPtr<CBArg> arg) +void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, PassOwnPtr<CB> callback, PassRefPtrWillBeRawPtr<CBArg> arg) +{ + ASSERT(executionContext->isContextThread()); + if (callback) + executionContext->postTask(adoptPtr(new DispatchCallbackRefPtrArgTask<CB, CBArg>(callback, arg))); +} + +template <typename CB, typename CBArg> +void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, PassOwnPtr<CB> callback, CBArg* arg) +{ + ASSERT(executionContext->isContextThread()); + if (callback) + executionContext->postTask(adoptPtr(new DispatchCallbackPtrArgTask<CB, CBArg>(callback, arg))); +} + +template <typename CB, typename CBArg> +void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, PassOwnPtr<CB> callback, const HeapVector<CBArg>& arg) { ASSERT(executionContext->isContextThread()); if (callback) - executionContext->postTask(adoptPtr(new DispatchCallbacRefPtrArgTask<CB, CBArg>(callback, arg))); + executionContext->postTask(adoptPtr(new DispatchCallbackNonPtrArgTask<CB, PersistentHeapVector<CBArg> >(callback, arg))); } template <typename CB, typename CBArg> @@ -142,6 +215,14 @@ void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, PassOwn executionContext->postTask(adoptPtr(new DispatchCallbackNonPtrArgTask<CB, CBArg>(callback, arg))); } +template <typename CB> +void DOMFileSystem::scheduleCallback(ExecutionContext* executionContext, PassOwnPtr<CB> callback) +{ + ASSERT(executionContext->isContextThread()); + if (callback) + executionContext->postTask(adoptPtr(new DispatchCallbackNoArgTask<CB>(callback))); +} + } // namespace #endif // DOMFileSystem_h diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.idl b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.idl index 6e8ab7fbce7..80f50321c43 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystem.idl @@ -31,7 +31,8 @@ [ NoInterfaceObject, - ActiveDOMObject + ActiveDOMObject, + GarbageCollected, ] interface DOMFileSystem { readonly attribute DOMString name; readonly attribute DirectoryEntry root; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp index f9f3b2ca188..7d490d34249 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp @@ -187,7 +187,7 @@ bool DOMFileSystemBase::pathPrefixToFileSystemType(const String& pathPrefix, Fil void DOMFileSystemBase::getMetadata(const EntryBase* entry, PassOwnPtr<MetadataCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, SynchronousType synchronousType) { - OwnPtr<AsyncFileSystemCallbacks> callbacks(MetadataCallbacks::create(successCallback, errorCallback, this)); + OwnPtr<AsyncFileSystemCallbacks> callbacks(MetadataCallbacks::create(successCallback, errorCallback, m_context, this)); callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous); fileSystem()->readMetadata(createFileSystemURL(entry), callbacks.release()); } @@ -229,7 +229,7 @@ void DOMFileSystemBase::move(const EntryBase* source, EntryBase* parent, const S return; } - OwnPtr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(successCallback, errorCallback, parent->filesystem(), destinationPath, source->isDirectory())); + OwnPtr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(successCallback, errorCallback, m_context, parent->filesystem(), destinationPath, source->isDirectory())); callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous); fileSystem()->move(createFileSystemURL(source), parent->filesystem()->createFileSystemURL(destinationPath), callbacks.release()); @@ -243,7 +243,7 @@ void DOMFileSystemBase::copy(const EntryBase* source, EntryBase* parent, const S return; } - OwnPtr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(successCallback, errorCallback, parent->filesystem(), destinationPath, source->isDirectory())); + OwnPtr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(successCallback, errorCallback, m_context, parent->filesystem(), destinationPath, source->isDirectory())); callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous); fileSystem()->copy(createFileSystemURL(source), parent->filesystem()->createFileSystemURL(destinationPath), callbacks.release()); @@ -258,7 +258,7 @@ void DOMFileSystemBase::remove(const EntryBase* entry, PassOwnPtr<VoidCallback> return; } - OwnPtr<AsyncFileSystemCallbacks> callbacks(VoidCallbacks::create(successCallback, errorCallback, this)); + OwnPtr<AsyncFileSystemCallbacks> callbacks(VoidCallbacks::create(successCallback, errorCallback, m_context, this)); callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous); fileSystem()->remove(createFileSystemURL(entry), callbacks.release()); @@ -273,7 +273,7 @@ void DOMFileSystemBase::removeRecursively(const EntryBase* entry, PassOwnPtr<Voi return; } - OwnPtr<AsyncFileSystemCallbacks> callbacks(VoidCallbacks::create(successCallback, errorCallback, this)); + OwnPtr<AsyncFileSystemCallbacks> callbacks(VoidCallbacks::create(successCallback, errorCallback, m_context, this)); callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous); fileSystem()->removeRecursively(createFileSystemURL(entry), callbacks.release()); @@ -283,7 +283,7 @@ void DOMFileSystemBase::getParent(const EntryBase* entry, PassOwnPtr<EntryCallba { ASSERT(entry); String path = DOMFilePath::getDirectory(entry->fullPath()); - fileSystem()->directoryExists(createFileSystemURL(path), EntryCallbacks::create(successCallback, errorCallback, this, path, true)); + fileSystem()->directoryExists(createFileSystemURL(path), EntryCallbacks::create(successCallback, errorCallback, m_context, this, path, true)); } void DOMFileSystemBase::getFile(const EntryBase* entry, const String& path, const FileSystemFlags& flags, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, SynchronousType synchronousType) @@ -294,7 +294,7 @@ void DOMFileSystemBase::getFile(const EntryBase* entry, const String& path, cons return; } - OwnPtr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(successCallback, errorCallback, this, absolutePath, false)); + OwnPtr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(successCallback, errorCallback, m_context, this, absolutePath, false)); callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous); if (flags.create) @@ -311,7 +311,7 @@ void DOMFileSystemBase::getDirectory(const EntryBase* entry, const String& path, return; } - OwnPtr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(successCallback, errorCallback, this, absolutePath, true)); + OwnPtr<AsyncFileSystemCallbacks> callbacks(EntryCallbacks::create(successCallback, errorCallback, m_context, this, absolutePath, true)); callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous); if (flags.create) @@ -320,15 +320,19 @@ void DOMFileSystemBase::getDirectory(const EntryBase* entry, const String& path, fileSystem()->directoryExists(createFileSystemURL(absolutePath), callbacks.release()); } -bool DOMFileSystemBase::readDirectory(PassRefPtr<DirectoryReaderBase> reader, const String& path, PassOwnPtr<EntriesCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, SynchronousType synchronousType) +int DOMFileSystemBase::readDirectory(DirectoryReaderBase* reader, const String& path, PassOwnPtr<EntriesCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, SynchronousType synchronousType) { ASSERT(DOMFilePath::isAbsolute(path)); - OwnPtr<AsyncFileSystemCallbacks> callbacks(EntriesCallbacks::create(successCallback, errorCallback, reader, path)); + OwnPtr<AsyncFileSystemCallbacks> callbacks(EntriesCallbacks::create(successCallback, errorCallback, m_context, reader, path)); callbacks->setShouldBlockUntilCompletion(synchronousType == Synchronous); - fileSystem()->readDirectory(createFileSystemURL(path), callbacks.release()); - return true; + return fileSystem()->readDirectory(createFileSystemURL(path), callbacks.release()); +} + +bool DOMFileSystemBase::waitForAdditionalResult(int callbacksId) +{ + return fileSystem()->waitForAdditionalResult(callbacksId); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.h b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.h index 7d5e40376b9..40fc6f26c19 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.h @@ -33,9 +33,8 @@ #include "modules/filesystem/FileSystemFlags.h" #include "platform/FileSystemType.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace blink { @@ -57,7 +56,7 @@ class SecurityOrigin; class VoidCallback; // A common base class for DOMFileSystem and DOMFileSystemSync. -class DOMFileSystemBase : public RefCounted<DOMFileSystemBase> { +class DOMFileSystemBase : public GarbageCollectedFinalized<DOMFileSystemBase> { public: enum SynchronousType { Synchronous, @@ -80,7 +79,7 @@ public: virtual void removePendingCallbacks() { } // Overridden by subclasses to handle sync vs async error-handling. - virtual void reportError(PassOwnPtr<ErrorCallback>, PassRefPtr<FileError>) = 0; + virtual void reportError(PassOwnPtr<ErrorCallback>, PassRefPtrWillBeRawPtr<FileError>) = 0; const String& name() const { return m_name; } FileSystemType type() const { return m_type; } @@ -112,7 +111,10 @@ public: void getParent(const EntryBase*, PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>); void getFile(const EntryBase*, const String& path, const FileSystemFlags&, PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>, SynchronousType = Asynchronous); void getDirectory(const EntryBase*, const String& path, const FileSystemFlags&, PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>, SynchronousType = Asynchronous); - bool readDirectory(PassRefPtr<DirectoryReaderBase>, const String& path, PassOwnPtr<EntriesCallback>, PassOwnPtr<ErrorCallback>, SynchronousType = Asynchronous); + int readDirectory(DirectoryReaderBase*, const String& path, PassOwnPtr<EntriesCallback>, PassOwnPtr<ErrorCallback>, SynchronousType = Asynchronous); + bool waitForAdditionalResult(int callbacksId); + + virtual void trace(Visitor*) { } protected: DOMFileSystemBase(ExecutionContext*, const String& name, FileSystemType, const KURL& rootURL); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.cpp index bb36cf12862..f1f3f5258cd 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.cpp @@ -50,9 +50,9 @@ namespace WebCore { class FileWriterBase; -PassRefPtr<DOMFileSystemSync> DOMFileSystemSync::create(DOMFileSystemBase* fileSystem) +DOMFileSystemSync* DOMFileSystemSync::create(DOMFileSystemBase* fileSystem) { - return adoptRef(new DOMFileSystemSync(fileSystem->m_context, fileSystem->name(), fileSystem->type(), fileSystem->rootURL())); + return new DOMFileSystemSync(fileSystem->m_context, fileSystem->name(), fileSystem->type(), fileSystem->rootURL()); } DOMFileSystemSync::DOMFileSystemSync(ExecutionContext* context, const String& name, FileSystemType type, const KURL& rootURL) @@ -65,30 +65,35 @@ DOMFileSystemSync::~DOMFileSystemSync() { } -void DOMFileSystemSync::reportError(PassOwnPtr<ErrorCallback> errorCallback, PassRefPtr<FileError> fileError) +void DOMFileSystemSync::reportError(PassOwnPtr<ErrorCallback> errorCallback, PassRefPtrWillBeRawPtr<FileError> fileError) { errorCallback->handleEvent(fileError.get()); } -PassRefPtr<DirectoryEntrySync> DOMFileSystemSync::root() +DirectoryEntrySync* DOMFileSystemSync::root() { return DirectoryEntrySync::create(this, DOMFilePath::root); } namespace { -class CreateFileHelper : public AsyncFileSystemCallbacks { +class CreateFileHelper FINAL : public AsyncFileSystemCallbacks { public: - class CreateFileResult : public RefCounted<CreateFileResult> { + class CreateFileResult : public RefCountedWillBeGarbageCollected<CreateFileResult> { public: - static PassRefPtr<CreateFileResult> create() + static PassRefPtrWillBeRawPtr<CreateFileResult> create() { - return adoptRef(new CreateFileResult()); + return adoptRefWillBeNoop(new CreateFileResult()); } bool m_failed; int m_code; - RefPtr<File> m_file; + RefPtrWillBeMember<File> m_file; + + void trace(Visitor* visitor) + { + visitor->trace(m_file); + } private: CreateFileResult() @@ -97,18 +102,21 @@ public: { } +#if !ENABLE(OILPAN) ~CreateFileResult() { } - friend class WTF::RefCounted<CreateFileResult>; +#endif + + friend class RefCountedWillBeGarbageCollected<CreateFileResult>; }; - static PassOwnPtr<AsyncFileSystemCallbacks> create(PassRefPtr<CreateFileResult> result, const String& name, const KURL& url, FileSystemType type) + static PassOwnPtr<AsyncFileSystemCallbacks> create(PassRefPtrWillBeRawPtr<CreateFileResult> result, const String& name, const KURL& url, FileSystemType type) { return adoptPtr(static_cast<AsyncFileSystemCallbacks*>(new CreateFileHelper(result, name, url, type))); } - virtual void didFail(int code) + virtual void didFail(int code) OVERRIDE { m_result->m_failed = true; m_result->m_code = code; @@ -118,7 +126,7 @@ public: { } - virtual void didCreateSnapshotFile(const FileMetadata& metadata, PassRefPtr<BlobDataHandle> snapshot) + virtual void didCreateSnapshotFile(const FileMetadata& metadata, PassRefPtr<BlobDataHandle> snapshot) OVERRIDE { // We can't directly use the snapshot blob data handle because the content type on it hasn't been set. // The |snapshot| param is here to provide a a chain of custody thru thread bridging that is held onto until @@ -147,7 +155,7 @@ public: } private: - CreateFileHelper(PassRefPtr<CreateFileResult> result, const String& name, const KURL& url, FileSystemType type) + CreateFileHelper(PassRefPtrWillBeRawPtr<CreateFileResult> result, const String& name, const KURL& url, FileSystemType type) : m_result(result) , m_name(name) , m_url(url) @@ -155,7 +163,7 @@ private: { } - RefPtr<CreateFileResult> m_result; + RefPtrWillBePersistent<CreateFileResult> m_result; String m_name; KURL m_url; FileSystemType m_type; @@ -163,28 +171,28 @@ private: } // namespace -PassRefPtr<File> DOMFileSystemSync::createFile(const FileEntrySync* fileEntry, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<File> DOMFileSystemSync::createFile(const FileEntrySync* fileEntry, ExceptionState& exceptionState) { KURL fileSystemURL = createFileSystemURL(fileEntry); - RefPtr<CreateFileHelper::CreateFileResult> result(CreateFileHelper::CreateFileResult::create()); + RefPtrWillBeRawPtr<CreateFileHelper::CreateFileResult> result(CreateFileHelper::CreateFileResult::create()); fileSystem()->createSnapshotFileAndReadMetadata(fileSystemURL, CreateFileHelper::create(result, fileEntry->name(), fileSystemURL, type())); if (result->m_failed) { - exceptionState.throwUninformativeAndGenericDOMException(result->m_code); - return 0; + exceptionState.throwDOMException(result->m_code, "Could not create '" + fileEntry->name() + "'."); + return nullptr; } - return result->m_file; + return result->m_file.get(); } namespace { -class ReceiveFileWriterCallback : public FileWriterBaseCallback { +class ReceiveFileWriterCallback FINAL : public FileWriterBaseCallback { public: static PassOwnPtr<ReceiveFileWriterCallback> create() { return adoptPtr(new ReceiveFileWriterCallback()); } - void handleEvent(FileWriterBase*) + virtual void handleEvent(FileWriterBase*) OVERRIDE { } @@ -194,14 +202,14 @@ private: } }; -class LocalErrorCallback : public ErrorCallback { +class LocalErrorCallback FINAL : public ErrorCallback { public: static PassOwnPtr<LocalErrorCallback> create(FileError::ErrorCode& errorCode) { return adoptPtr(new LocalErrorCallback(errorCode)); } - void handleEvent(FileError* error) + virtual void handleEvent(FileError* error) OVERRIDE { ASSERT(error->code() != FileError::OK); m_errorCode = error->code(); @@ -218,24 +226,24 @@ private: } -PassRefPtr<FileWriterSync> DOMFileSystemSync::createWriter(const FileEntrySync* fileEntry, ExceptionState& exceptionState) +FileWriterSync* DOMFileSystemSync::createWriter(const FileEntrySync* fileEntry, ExceptionState& exceptionState) { ASSERT(fileEntry); - RefPtr<FileWriterSync> fileWriter = FileWriterSync::create(); + FileWriterSync* fileWriter = FileWriterSync::create(); OwnPtr<ReceiveFileWriterCallback> successCallback = ReceiveFileWriterCallback::create(); FileError::ErrorCode errorCode = FileError::OK; OwnPtr<LocalErrorCallback> errorCallback = LocalErrorCallback::create(errorCode); - OwnPtr<AsyncFileSystemCallbacks> callbacks = FileWriterBaseCallbacks::create(fileWriter, successCallback.release(), errorCallback.release()); + OwnPtr<AsyncFileSystemCallbacks> callbacks = FileWriterBaseCallbacks::create(fileWriter, successCallback.release(), errorCallback.release(), m_context); callbacks->setShouldBlockUntilCompletion(true); - fileSystem()->createFileWriter(createFileSystemURL(fileEntry), fileWriter.get(), callbacks.release()); + fileSystem()->createFileWriter(createFileSystemURL(fileEntry), fileWriter, callbacks.release()); if (errorCode != FileError::OK) { FileError::throwDOMException(exceptionState, errorCode); return 0; } - return fileWriter.release(); + return fileWriter; } } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.h b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.h index 0a2212856a6..4507279e058 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.h @@ -33,6 +33,7 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/filesystem/DOMFileSystemBase.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -42,23 +43,23 @@ class FileEntrySync; class FileWriterSync; class ExceptionState; -class DOMFileSystemSync : public DOMFileSystemBase, public ScriptWrappable { +class DOMFileSystemSync FINAL : public DOMFileSystemBase, public ScriptWrappable { public: - static PassRefPtr<DOMFileSystemSync> create(ExecutionContext* context, const String& name, FileSystemType type, const KURL& rootURL) + static DOMFileSystemSync* create(ExecutionContext* context, const String& name, FileSystemType type, const KURL& rootURL) { - return adoptRef(new DOMFileSystemSync(context, name, type, rootURL)); + return new DOMFileSystemSync(context, name, type, rootURL); } - static PassRefPtr<DOMFileSystemSync> create(DOMFileSystemBase*); + static DOMFileSystemSync* create(DOMFileSystemBase*); virtual ~DOMFileSystemSync(); - virtual void reportError(PassOwnPtr<ErrorCallback>, PassRefPtr<FileError>) OVERRIDE; + virtual void reportError(PassOwnPtr<ErrorCallback>, PassRefPtrWillBeRawPtr<FileError>) OVERRIDE; - PassRefPtr<DirectoryEntrySync> root(); + DirectoryEntrySync* root(); - PassRefPtr<File> createFile(const FileEntrySync*, ExceptionState&); - PassRefPtr<FileWriterSync> createWriter(const FileEntrySync*, ExceptionState&); + PassRefPtrWillBeRawPtr<File> createFile(const FileEntrySync*, ExceptionState&); + FileWriterSync* createWriter(const FileEntrySync*, ExceptionState&); private: DOMFileSystemSync(ExecutionContext*, const String& name, FileSystemType, const KURL& rootURL); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.idl b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.idl index 5e67ada5449..55ce1d71459 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMFileSystemSync.idl @@ -29,7 +29,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + GarbageCollected, ] interface DOMFileSystemSync { readonly attribute DOMString name; readonly attribute DirectoryEntrySync root; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMWindowFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DOMWindowFileSystem.cpp index faa99c554ce..99e1e8579e4 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMWindowFileSystem.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMWindowFileSystem.cpp @@ -28,7 +28,7 @@ #include "core/dom/Document.h" #include "core/fileapi/FileError.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "modules/filesystem/DOMFileSystem.h" #include "modules/filesystem/EntryCallback.h" #include "modules/filesystem/ErrorCallback.h" @@ -48,12 +48,12 @@ DOMWindowFileSystem::~DOMWindowFileSystem() { } -void DOMWindowFileSystem::webkitRequestFileSystem(DOMWindow* window, int type, long long size, PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) +void DOMWindowFileSystem::webkitRequestFileSystem(LocalDOMWindow& window, int type, long long size, PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) { - if (!window->isCurrentlyDisplayedInFrame()) + if (!window.isCurrentlyDisplayedInFrame()) return; - Document* document = window->document(); + Document* document = window.document(); if (!document) return; @@ -68,15 +68,15 @@ void DOMWindowFileSystem::webkitRequestFileSystem(DOMWindow* window, int type, l return; } - LocalFileSystem::from(document)->requestFileSystem(document, fileSystemType, size, FileSystemCallbacks::create(successCallback, errorCallback, document, fileSystemType)); + LocalFileSystem::from(*document)->requestFileSystem(document, fileSystemType, size, FileSystemCallbacks::create(successCallback, errorCallback, document, fileSystemType)); } -void DOMWindowFileSystem::webkitResolveLocalFileSystemURL(DOMWindow* window, const String& url, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) +void DOMWindowFileSystem::webkitResolveLocalFileSystemURL(LocalDOMWindow& window, const String& url, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) { - if (!window->isCurrentlyDisplayedInFrame()) + if (!window.isCurrentlyDisplayedInFrame()) return; - Document* document = window->document(); + Document* document = window.document(); if (!document) return; @@ -92,7 +92,7 @@ void DOMWindowFileSystem::webkitResolveLocalFileSystemURL(DOMWindow* window, con return; } - LocalFileSystem::from(document)->resolveURL(document, completedURL, ResolveURICallbacks::create(successCallback, errorCallback, document)); + LocalFileSystem::from(*document)->resolveURL(document, completedURL, ResolveURICallbacks::create(successCallback, errorCallback, document)); } COMPILE_ASSERT(static_cast<int>(DOMWindowFileSystem::TEMPORARY) == static_cast<int>(FileSystemTypeTemporary), enum_mismatch); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DOMWindowFileSystem.h b/chromium/third_party/WebKit/Source/modules/filesystem/DOMWindowFileSystem.h index eb0a76068d6..d852426182b 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DOMWindowFileSystem.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DOMWindowFileSystem.h @@ -26,20 +26,19 @@ #ifndef DOMWindowFileSystem_h #define DOMWindowFileSystem_h -#include "wtf/PassRefPtr.h" #include "wtf/text/WTFString.h" namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class EntryCallback; class ErrorCallback; class FileSystemCallback; class DOMWindowFileSystem { public: - static void webkitRequestFileSystem(DOMWindow*, int type, long long size, PassOwnPtr<FileSystemCallback>, PassOwnPtr<ErrorCallback>); - static void webkitResolveLocalFileSystemURL(DOMWindow*, const String&, PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>); + static void webkitRequestFileSystem(LocalDOMWindow&, int type, long long size, PassOwnPtr<FileSystemCallback>, PassOwnPtr<ErrorCallback>); + static void webkitResolveLocalFileSystemURL(LocalDOMWindow&, const String&, PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>); // They are placed here and in all capital letters so they can be checked against the constants in the // IDL at compile time. diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.cpp index cbcd4127467..4aadb40dabb 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.cpp @@ -31,11 +31,11 @@ #include "config.h" #include "modules/filesystem/DataTransferItemFileSystem.h" -#include "core/dom/Clipboard.h" -#include "core/dom/DataTransferItem.h" +#include "core/clipboard/Clipboard.h" +#include "core/clipboard/DataObject.h" +#include "core/clipboard/DataTransferItem.h" #include "core/dom/ExecutionContext.h" #include "core/fileapi/File.h" -#include "core/platform/chromium/ChromiumDataObject.h" #include "modules/filesystem/DOMFilePath.h" #include "modules/filesystem/DOMFileSystem.h" #include "modules/filesystem/DirectoryEntry.h" @@ -48,27 +48,24 @@ namespace WebCore { // static -PassRefPtr<Entry> DataTransferItemFileSystem::webkitGetAsEntry(ExecutionContext* executionContext, DataTransferItem* item) +Entry* DataTransferItemFileSystem::webkitGetAsEntry(ExecutionContext* executionContext, DataTransferItem& item) { - if (!item->dataObjectItem()->isFilename()) + if (!item.dataObjectItem()->isFilename()) return 0; // For dragged files getAsFile must be pretty lightweight. - Blob* file = item->getAsFile().get(); + Blob* file = item.getAsFile().get(); // The clipboard may not be in a readable state. if (!file) return 0; ASSERT(file->isFile()); - DraggedIsolatedFileSystem* filesystem = DraggedIsolatedFileSystem::from(item->clipboard()->dataObject().get()); - DOMFileSystem* domFileSystem = filesystem ? filesystem->getDOMFileSystem(executionContext) : 0; - if (!filesystem) { + DOMFileSystem* domFileSystem = DraggedIsolatedFileSystem::getDOMFileSystem(item.clipboard()->dataObject().get(), executionContext); + if (!domFileSystem) { // IsolatedFileSystem may not be enabled. return 0; } - ASSERT(domFileSystem); - // The dropped entries are mapped as top-level entries in the isolated filesystem. String virtualPath = DOMFilePath::append("/", toFile(file)->name()); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.h b/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.h index 98bbd8e8ea5..c9d135497ff 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.h @@ -31,7 +31,7 @@ #ifndef DataTransferItemFileSystem_h #define DataTransferItemFileSystem_h -#include "wtf/PassRefPtr.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -41,7 +41,7 @@ class ExecutionContext; class DataTransferItemFileSystem { public: - static PassRefPtr<Entry> webkitGetAsEntry(ExecutionContext*, DataTransferItem*); + static Entry* webkitGetAsEntry(ExecutionContext*, DataTransferItem&); private: DataTransferItemFileSystem(); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.idl b/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.idl index 19dd9f9c29b..28f3151b515 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DataTransferItemFileSystem.idl @@ -31,4 +31,3 @@ partial interface DataTransferItem { [CallWith=ExecutionContext] Entry webkitGetAsEntry(); }; - diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntry.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntry.cpp index d0ec7a7e4c6..dce565cb2c5 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntry.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntry.cpp @@ -39,13 +39,13 @@ namespace WebCore { -DirectoryEntry::DirectoryEntry(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +DirectoryEntry::DirectoryEntry(DOMFileSystemBase* fileSystem, const String& fullPath) : Entry(fileSystem, fullPath) { ScriptWrappable::init(this); } -PassRefPtr<DirectoryReader> DirectoryEntry::createReader() +DirectoryReader* DirectoryEntry::createReader() { return DirectoryReader::create(m_fileSystem, m_fullPath); } @@ -67,4 +67,9 @@ void DirectoryEntry::removeRecursively(PassOwnPtr<VoidCallback> successCallback, m_fileSystem->removeRecursively(this, successCallback, errorCallback); } +void DirectoryEntry::trace(Visitor* visitor) +{ + Entry::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntry.h b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntry.h index 68b16ce9d64..a1e8365e372 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntry.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntry.h @@ -33,8 +33,7 @@ #include "modules/filesystem/Entry.h" #include "modules/filesystem/FileSystemFlags.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -45,21 +44,23 @@ class EntryCallback; class ErrorCallback; class VoidCallback; -class DirectoryEntry : public Entry { +class DirectoryEntry FINAL : public Entry { public: - static PassRefPtr<DirectoryEntry> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) + static DirectoryEntry* create(DOMFileSystemBase* fileSystem, const String& fullPath) { - return adoptRef(new DirectoryEntry(fileSystem, fullPath)); + return new DirectoryEntry(fileSystem, fullPath); } - virtual bool isDirectory() const { return true; } + virtual bool isDirectory() const OVERRIDE { return true; } - PassRefPtr<DirectoryReader> createReader(); + DirectoryReader* createReader(); void getFile(const String& path, const Dictionary&, PassOwnPtr<EntryCallback> = nullptr, PassOwnPtr<ErrorCallback> = nullptr); void getDirectory(const String& path, const Dictionary&, PassOwnPtr<EntryCallback> = nullptr, PassOwnPtr<ErrorCallback> = nullptr); void removeRecursively(PassOwnPtr<VoidCallback> successCallback = nullptr, PassOwnPtr<ErrorCallback> = nullptr) const; + virtual void trace(Visitor*) OVERRIDE; + private: - DirectoryEntry(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + DirectoryEntry(DOMFileSystemBase*, const String& fullPath); }; DEFINE_TYPE_CASTS(DirectoryEntry, Entry, entry, entry->isDirectory(), entry.isDirectory()); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntrySync.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntrySync.cpp index 678bbbf3e33..552ca8cbbd0 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntrySync.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntrySync.cpp @@ -40,38 +40,43 @@ namespace WebCore { -DirectoryEntrySync::DirectoryEntrySync(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +DirectoryEntrySync::DirectoryEntrySync(DOMFileSystemBase* fileSystem, const String& fullPath) : EntrySync(fileSystem, fullPath) { ScriptWrappable::init(this); } -PassRefPtr<DirectoryReaderSync> DirectoryEntrySync::createReader() +DirectoryReaderSync* DirectoryEntrySync::createReader() { return DirectoryReaderSync::create(m_fileSystem, m_fullPath); } -PassRefPtr<FileEntrySync> DirectoryEntrySync::getFile(const String& path, const Dictionary& options, ExceptionState& exceptionState) +FileEntrySync* DirectoryEntrySync::getFile(const String& path, const Dictionary& options, ExceptionState& exceptionState) { FileSystemFlags flags(options); - EntrySyncCallbackHelper helper; - m_fileSystem->getFile(this, path, flags, helper.successCallback(), helper.errorCallback(), DOMFileSystemBase::Synchronous); - return static_pointer_cast<FileEntrySync>(helper.getResult(exceptionState)); + RefPtr<EntrySyncCallbackHelper> helper = EntrySyncCallbackHelper::create(); + m_fileSystem->getFile(this, path, flags, helper->successCallback(), helper->errorCallback(), DOMFileSystemBase::Synchronous); + return static_cast<FileEntrySync*>(helper->getResult(exceptionState)); } -PassRefPtr<DirectoryEntrySync> DirectoryEntrySync::getDirectory(const String& path, const Dictionary& options, ExceptionState& exceptionState) +DirectoryEntrySync* DirectoryEntrySync::getDirectory(const String& path, const Dictionary& options, ExceptionState& exceptionState) { FileSystemFlags flags(options); - EntrySyncCallbackHelper helper; - m_fileSystem->getDirectory(this, path, flags, helper.successCallback(), helper.errorCallback(), DOMFileSystemBase::Synchronous); - return static_pointer_cast<DirectoryEntrySync>(helper.getResult(exceptionState)); + RefPtr<EntrySyncCallbackHelper> helper = EntrySyncCallbackHelper::create(); + m_fileSystem->getDirectory(this, path, flags, helper->successCallback(), helper->errorCallback(), DOMFileSystemBase::Synchronous); + return static_cast<DirectoryEntrySync*>(helper->getResult(exceptionState)); } void DirectoryEntrySync::removeRecursively(ExceptionState& exceptionState) { - VoidSyncCallbackHelper helper; - m_fileSystem->removeRecursively(this, helper.successCallback(), helper.errorCallback(), DOMFileSystemBase::Synchronous); - helper.getResult(exceptionState); + RefPtr<VoidSyncCallbackHelper> helper = VoidSyncCallbackHelper::create(); + m_fileSystem->removeRecursively(this, helper->successCallback(), helper->errorCallback(), DOMFileSystemBase::Synchronous); + helper->getResult(exceptionState); +} + +void DirectoryEntrySync::trace(Visitor* visitor) +{ + EntrySync::trace(visitor); } } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntrySync.h b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntrySync.h index 7192fdea10b..b4f2999c3ef 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntrySync.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryEntrySync.h @@ -33,8 +33,6 @@ #include "modules/filesystem/EntrySync.h" #include "modules/filesystem/FileSystemFlags.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -43,22 +41,23 @@ class DirectoryReaderSync; class ExceptionState; class FileEntrySync; -class DirectoryEntrySync : public EntrySync { +class DirectoryEntrySync FINAL : public EntrySync { public: - static PassRefPtr<DirectoryEntrySync> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) + static DirectoryEntrySync* create(DOMFileSystemBase* fileSystem, const String& fullPath) { - return adoptRef(new DirectoryEntrySync(fileSystem, fullPath)); + return new DirectoryEntrySync(fileSystem, fullPath); } - virtual bool isDirectory() const { return true; } + virtual bool isDirectory() const OVERRIDE { return true; } - PassRefPtr<DirectoryReaderSync> createReader(); - PassRefPtr<FileEntrySync> getFile(const String& path, const Dictionary&, ExceptionState&); - PassRefPtr<DirectoryEntrySync> getDirectory(const String& path, const Dictionary&, ExceptionState&); + DirectoryReaderSync* createReader(); + FileEntrySync* getFile(const String& path, const Dictionary&, ExceptionState&); + DirectoryEntrySync* getDirectory(const String& path, const Dictionary&, ExceptionState&); void removeRecursively(ExceptionState&); + virtual void trace(Visitor*) OVERRIDE; + private: - friend class EntrySync; - DirectoryEntrySync(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + DirectoryEntrySync(DOMFileSystemBase*, const String& fullPath); }; DEFINE_TYPE_CASTS(DirectoryEntrySync, EntrySync, entry, entry->isDirectory(), entry.isDirectory()); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.cpp index 338d1081b54..c09ae005634 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.cpp @@ -38,19 +38,105 @@ namespace WebCore { -DirectoryReader::DirectoryReader(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +class DirectoryReader::EntriesCallbackHelper : public EntriesCallback { +public: + explicit EntriesCallbackHelper(DirectoryReader* reader) + : m_reader(reader) + { + } + + virtual void handleEvent(const EntryHeapVector& entries) OVERRIDE + { + m_reader->addEntries(entries); + } + +private: + // FIXME: This Persistent keeps the reader alive until all of the readDirectory results are received. crbug.com/350285 + Persistent<DirectoryReader> m_reader; +}; + +class DirectoryReader::ErrorCallbackHelper : public ErrorCallback { +public: + explicit ErrorCallbackHelper(DirectoryReader* reader) + : m_reader(reader) + { + } + + virtual void handleEvent(FileError* error) OVERRIDE + { + m_reader->onError(error); + } + +private: + Persistent<DirectoryReader> m_reader; +}; + +DirectoryReader::DirectoryReader(DOMFileSystemBase* fileSystem, const String& fullPath) : DirectoryReaderBase(fileSystem, fullPath) + , m_isReading(false) { ScriptWrappable::init(this); } +DirectoryReader::~DirectoryReader() +{ +} + void DirectoryReader::readEntries(PassOwnPtr<EntriesCallback> entriesCallback, PassOwnPtr<ErrorCallback> errorCallback) { - if (!m_hasMoreEntries) { - filesystem()->scheduleCallback(entriesCallback, EntryVector()); + if (!m_isReading) { + m_isReading = true; + filesystem()->readDirectory(this, m_fullPath, adoptPtr(new EntriesCallbackHelper(this)), adoptPtr(new ErrorCallbackHelper(this))); + } + + if (m_error) { + filesystem()->scheduleCallback(errorCallback, PassRefPtrWillBeRawPtr<FileError>(m_error.get())); return; } - filesystem()->readDirectory(this, m_fullPath, entriesCallback, errorCallback); + + if (m_entriesCallback) { + // Non-null m_entriesCallback means multiple readEntries() calls are made concurrently. We don't allow doing it. + filesystem()->scheduleCallback(errorCallback, FileError::create(FileError::INVALID_STATE_ERR)); + return; + } + + if (!m_hasMoreEntries || !m_entries.isEmpty()) { + filesystem()->scheduleCallback(entriesCallback, m_entries); + m_entries.clear(); + return; + } + + m_entriesCallback = entriesCallback; + m_errorCallback = errorCallback; +} + +void DirectoryReader::addEntries(const EntryHeapVector& entries) +{ + m_entries.appendVector(entries); + m_errorCallback = nullptr; + if (m_entriesCallback) { + OwnPtr<EntriesCallback> entriesCallback = m_entriesCallback.release(); + EntryHeapVector entries; + entries.swap(m_entries); + entriesCallback->handleEvent(entries); + } +} + +void DirectoryReader::onError(FileError* error) +{ + m_error = error; + m_entriesCallback = nullptr; + if (m_errorCallback) { + OwnPtr<ErrorCallback> errorCallback = m_errorCallback.release(); + errorCallback->handleEvent(error); + } +} + +void DirectoryReader::trace(Visitor* visitor) +{ + visitor->trace(m_entries); + visitor->trace(m_error); + DirectoryReaderBase::trace(visitor); } } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.h b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.h index 7ec604d2718..218c18cf694 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.h @@ -34,29 +34,44 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/filesystem/DOMFileSystem.h" #include "modules/filesystem/DirectoryReaderBase.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" +#include "modules/filesystem/EntriesCallback.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { -class EntriesCallback; -class EntriesCallbacks; class ErrorCallback; class DirectoryReader : public DirectoryReaderBase, public ScriptWrappable { public: - static PassRefPtr<DirectoryReader> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) + static DirectoryReader* create(DOMFileSystemBase* fileSystem, const String& fullPath) { - return adoptRef(new DirectoryReader(fileSystem, fullPath)); + return new DirectoryReader(fileSystem, fullPath); } + virtual ~DirectoryReader(); + void readEntries(PassOwnPtr<EntriesCallback>, PassOwnPtr<ErrorCallback> = nullptr); DOMFileSystem* filesystem() const { return static_cast<DOMFileSystem*>(m_fileSystem.get()); } + virtual void trace(Visitor*) OVERRIDE; + private: - DirectoryReader(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + class EntriesCallbackHelper; + class ErrorCallbackHelper; + + DirectoryReader(DOMFileSystemBase*, const String& fullPath); + + void addEntries(const EntryHeapVector& entries); + + void onError(FileError*); + + bool m_isReading; + EntryHeapVector m_entries; + RefPtrWillBeMember<FileError> m_error; + OwnPtr<EntriesCallback> m_entriesCallback; + OwnPtr<ErrorCallback> m_errorCallback; }; } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.idl b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.idl index 7660917f3f1..f4971fad43e 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReader.idl @@ -29,7 +29,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + GarbageCollected, ] interface DirectoryReader { void readEntries(EntriesCallback successCallback, optional ErrorCallback errorCallback); }; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderBase.h b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderBase.h index 5e1ac5e4fac..7b3e06ff7c6 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderBase.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderBase.h @@ -32,26 +32,32 @@ #define DirectoryReaderBase_h #include "modules/filesystem/DOMFileSystemBase.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { -class DirectoryReaderBase : public RefCounted<DirectoryReaderBase> { +class DirectoryReaderBase : public GarbageCollectedFinalized<DirectoryReaderBase> { public: DOMFileSystemBase* filesystem() const { return m_fileSystem.get(); } void setHasMoreEntries(bool hasMoreEntries) { m_hasMoreEntries = hasMoreEntries; } + virtual ~DirectoryReaderBase() { } + + virtual void trace(Visitor* visitor) + { + visitor->trace(m_fileSystem); + } + protected: - DirectoryReaderBase(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) + DirectoryReaderBase(DOMFileSystemBase* fileSystem, const String& fullPath) : m_fileSystem(fileSystem) , m_fullPath(fullPath) , m_hasMoreEntries(true) { } - RefPtr<DOMFileSystemBase> m_fileSystem; + Member<DOMFileSystemBase> m_fileSystem; // This is a virtual path. String m_fullPath; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.cpp index 5f83d945020..5e2dbc01ceb 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.cpp @@ -35,30 +35,84 @@ #include "core/dom/ExceptionCode.h" #include "modules/filesystem/DirectoryEntry.h" #include "modules/filesystem/DirectoryEntrySync.h" +#include "modules/filesystem/EntriesCallback.h" #include "modules/filesystem/EntrySync.h" +#include "modules/filesystem/ErrorCallback.h" #include "modules/filesystem/FileEntrySync.h" -#include "modules/filesystem/SyncCallbackHelper.h" namespace WebCore { -DirectoryReaderSync::DirectoryReaderSync(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +class DirectoryReaderSync::EntriesCallbackHelper : public EntriesCallback { +public: + explicit EntriesCallbackHelper(DirectoryReaderSync* reader) + : m_reader(reader) + { + } + + virtual void handleEvent(const EntryHeapVector& entries) OVERRIDE + { + EntrySyncHeapVector syncEntries; + syncEntries.reserveInitialCapacity(entries.size()); + for (size_t i = 0; i < entries.size(); ++i) + syncEntries.uncheckedAppend(EntrySync::create(entries[i].get())); + m_reader->addEntries(syncEntries); + } + +private: + Persistent<DirectoryReaderSync> m_reader; +}; + +class DirectoryReaderSync::ErrorCallbackHelper : public ErrorCallback { +public: + explicit ErrorCallbackHelper(DirectoryReaderSync* reader) + : m_reader(reader) + { + } + + virtual void handleEvent(FileError* error) OVERRIDE + { + m_reader->setError(error->code()); + } + +private: + Persistent<DirectoryReaderSync> m_reader; +}; + +DirectoryReaderSync::DirectoryReaderSync(DOMFileSystemBase* fileSystem, const String& fullPath) : DirectoryReaderBase(fileSystem, fullPath) + , m_callbacksId(0) + , m_errorCode(FileError::OK) { ScriptWrappable::init(this); } -EntrySyncVector DirectoryReaderSync::readEntries(ExceptionState& exceptionState) +DirectoryReaderSync::~DirectoryReaderSync() { - if (!m_hasMoreEntries) - return EntrySyncVector(); - - EntriesSyncCallbackHelper helper; - if (!m_fileSystem->readDirectory(this, m_fullPath, helper.successCallback(), helper.errorCallback(), DOMFileSystemBase::Synchronous)) { - exceptionState.throwDOMException(InvalidModificationError, "Failed to read the directory."); - setHasMoreEntries(false); - return EntrySyncVector(); +} + +EntrySyncHeapVector DirectoryReaderSync::readEntries(ExceptionState& exceptionState) +{ + if (!m_callbacksId) { + m_callbacksId = filesystem()->readDirectory(this, m_fullPath, adoptPtr(new EntriesCallbackHelper(this)), adoptPtr(new ErrorCallbackHelper(this)), DOMFileSystemBase::Synchronous); + } + + if (m_errorCode == FileError::OK && m_hasMoreEntries && m_entries.isEmpty()) + m_fileSystem->waitForAdditionalResult(m_callbacksId); + + if (m_errorCode != FileError::OK) { + FileError::throwDOMException(exceptionState, m_errorCode); + return EntrySyncHeapVector(); } - return helper.getResult(exceptionState); + + EntrySyncHeapVector result; + result.swap(m_entries); + return result; +} + +void DirectoryReaderSync::trace(Visitor* visitor) +{ + visitor->trace(m_entries); + DirectoryReaderBase::trace(visitor); } } // namespace diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.h b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.h index 1ecdf82a4d5..5dd42642952 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.h @@ -32,10 +32,9 @@ #define DirectoryReaderSync_h #include "bindings/v8/ScriptWrappable.h" +#include "core/fileapi/FileError.h" #include "modules/filesystem/DirectoryReaderBase.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/Vector.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -43,19 +42,40 @@ namespace WebCore { class EntrySync; class ExceptionState; -typedef Vector<RefPtr<EntrySync> > EntrySyncVector; +typedef HeapVector<Member<EntrySync> > EntrySyncHeapVector; class DirectoryReaderSync : public DirectoryReaderBase, public ScriptWrappable { public: - static PassRefPtr<DirectoryReaderSync> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) + static DirectoryReaderSync* create(DOMFileSystemBase* fileSystem, const String& fullPath) { - return adoptRef(new DirectoryReaderSync(fileSystem, fullPath)); + return new DirectoryReaderSync(fileSystem, fullPath); } - EntrySyncVector readEntries(ExceptionState&); + virtual ~DirectoryReaderSync(); + + EntrySyncHeapVector readEntries(ExceptionState&); + + void addEntries(const EntrySyncHeapVector& entries) + { + m_entries.appendVector(entries); + } + + void setError(FileError::ErrorCode code) + { + m_errorCode = code; + } + + virtual void trace(Visitor*) OVERRIDE; private: - DirectoryReaderSync(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + class EntriesCallbackHelper; + class ErrorCallbackHelper; + + DirectoryReaderSync(DOMFileSystemBase*, const String& fullPath); + + int m_callbacksId; + EntrySyncHeapVector m_entries; + FileError::ErrorCode m_errorCode; }; } // namespace diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.idl b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.idl index cf4937cf556..2f30b1c8586 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DirectoryReaderSync.idl @@ -29,7 +29,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + GarbageCollected, ] interface DirectoryReaderSync { [RaisesException] EntrySync[] readEntries(); }; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DraggedIsolatedFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/DraggedIsolatedFileSystem.cpp index d9c368a0c1a..bbf64c4ab38 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DraggedIsolatedFileSystem.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DraggedIsolatedFileSystem.cpp @@ -43,14 +43,14 @@ DraggedIsolatedFileSystem::~DraggedIsolatedFileSystem() { } -DOMFileSystem* DraggedIsolatedFileSystem::getDOMFileSystem(ExecutionContext* executionContext) +DOMFileSystem* DraggedIsolatedFileSystem::getDOMFileSystem(DataObject* host, ExecutionContext* executionContext) { - ASSERT(!m_filesystemId.isEmpty()); - if (!m_filesystem) { - ASSERT(executionContext); - m_filesystem = DOMFileSystem::createIsolatedFileSystem(executionContext, m_filesystemId); - } - return m_filesystem.get(); + DraggedIsolatedFileSystem* draggedIsolatedFileSystem = from(host); + if (!draggedIsolatedFileSystem) + return 0; + if (!draggedIsolatedFileSystem->m_filesystem) + draggedIsolatedFileSystem->m_filesystem = DOMFileSystem::createIsolatedFileSystem(executionContext, host->filesystemId()); + return draggedIsolatedFileSystem->m_filesystem.get(); } // static @@ -60,9 +60,20 @@ const char* DraggedIsolatedFileSystem::supplementName() return "DraggedIsolatedFileSystem"; } -DraggedIsolatedFileSystem::DraggedIsolatedFileSystem(const String& filesystemId) - : m_filesystemId(filesystemId) +DraggedIsolatedFileSystem* DraggedIsolatedFileSystem::from(DataObject* dataObject) { + return static_cast<DraggedIsolatedFileSystem*>(WillBeHeapSupplement<DataObject>::from(dataObject, supplementName())); +} + +DraggedIsolatedFileSystem::DraggedIsolatedFileSystem(DataObject& host, const String& filesystemId) +{ + host.setFilesystemId(filesystemId); +} + +void DraggedIsolatedFileSystem::trace(Visitor* visitor) +{ + visitor->trace(m_filesystem); + WillBeHeapSupplement<DataObject>::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/DraggedIsolatedFileSystem.h b/chromium/third_party/WebKit/Source/modules/filesystem/DraggedIsolatedFileSystem.h index d5c5b4f4941..be671c8b8f9 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/DraggedIsolatedFileSystem.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/DraggedIsolatedFileSystem.h @@ -31,7 +31,8 @@ #ifndef DraggedIsolatedFileSystem_h #define DraggedIsolatedFileSystem_h -#include "core/platform/chromium/ChromiumDataObject.h" +#include "core/clipboard/DataObject.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/text/WTFString.h" @@ -39,25 +40,26 @@ namespace WebCore { class DOMFileSystem; -class DraggedIsolatedFileSystem : public Supplement<ChromiumDataObject> { +class DraggedIsolatedFileSystem FINAL : public NoBaseWillBeGarbageCollectedFinalized<DraggedIsolatedFileSystem>, public WillBeHeapSupplement<DataObject> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DraggedIsolatedFileSystem); public: - ~DraggedIsolatedFileSystem(); + virtual ~DraggedIsolatedFileSystem(); - static PassOwnPtr<DraggedIsolatedFileSystem> create(const String& filesystemId) + static PassOwnPtrWillBeRawPtr<DraggedIsolatedFileSystem> create(DataObject& host, const String& filesystemId) { - return adoptPtr(new DraggedIsolatedFileSystem(filesystemId)); + return adoptPtrWillBeNoop(new DraggedIsolatedFileSystem(host, filesystemId)); } - const String& filesystemId() const { return m_filesystemId; } - DOMFileSystem* getDOMFileSystem(ExecutionContext*); + static DOMFileSystem* getDOMFileSystem(DataObject* host, ExecutionContext*); static const char* supplementName(); - static DraggedIsolatedFileSystem* from(ChromiumDataObject* dataObject) { return static_cast<DraggedIsolatedFileSystem*>(Supplement<ChromiumDataObject>::from(dataObject, supplementName())); } + static DraggedIsolatedFileSystem* from(DataObject*); + + void trace(Visitor*); private: - DraggedIsolatedFileSystem(const String& filesystemId); - RefPtr<DOMFileSystem> m_filesystem; - String m_filesystemId; + DraggedIsolatedFileSystem(DataObject& host, const String& filesystemId); + PersistentWillBeMember<DOMFileSystem> m_filesystem; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/EntriesCallback.h b/chromium/third_party/WebKit/Source/modules/filesystem/EntriesCallback.h index 4bb71353509..85e0d8e59b1 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/EntriesCallback.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/EntriesCallback.h @@ -31,17 +31,17 @@ #ifndef EntriesCallback_h #define EntriesCallback_h -#include "wtf/Vector.h" +#include "platform/heap/Handle.h" namespace WebCore { class Entry; -typedef Vector<RefPtr<Entry> > EntryVector; +typedef HeapVector<Member<Entry> > EntryHeapVector; class EntriesCallback { public: virtual ~EntriesCallback() { } - virtual void handleEvent(const EntryVector&) = 0; + virtual void handleEvent(const EntryHeapVector&) = 0; }; } // namespace diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/Entry.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/Entry.cpp index d518d966f00..530cb5ed5f9 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/Entry.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/Entry.cpp @@ -43,7 +43,7 @@ namespace WebCore { -Entry::Entry(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +Entry::Entry(DOMFileSystemBase* fileSystem, const String& fullPath) : EntryBase(fileSystem, fullPath) { ScriptWrappable::init(this); @@ -54,14 +54,14 @@ void Entry::getMetadata(PassOwnPtr<MetadataCallback> successCallback, PassOwnPtr m_fileSystem->getMetadata(this, successCallback, errorCallback); } -void Entry::moveTo(PassRefPtr<DirectoryEntry> parent, const String& name, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) const +void Entry::moveTo(DirectoryEntry* parent, const String& name, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) const { - m_fileSystem->move(this, parent.get(), name, successCallback, errorCallback); + m_fileSystem->move(this, parent, name, successCallback, errorCallback); } -void Entry::copyTo(PassRefPtr<DirectoryEntry> parent, const String& name, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) const +void Entry::copyTo(DirectoryEntry* parent, const String& name, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) const { - m_fileSystem->copy(this, parent.get(), name, successCallback, errorCallback); + m_fileSystem->copy(this, parent, name, successCallback, errorCallback); } void Entry::remove(PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) const @@ -74,4 +74,9 @@ void Entry::getParent(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<Erro m_fileSystem->getParent(this, successCallback, errorCallback); } +void Entry::trace(Visitor* visitor) +{ + EntryBase::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/Entry.h b/chromium/third_party/WebKit/Source/modules/filesystem/Entry.h index c709619b629..746355877d9 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/Entry.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/Entry.h @@ -34,8 +34,7 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/filesystem/DOMFileSystem.h" #include "modules/filesystem/EntryBase.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -51,13 +50,15 @@ public: DOMFileSystem* filesystem() const { return static_cast<DOMFileSystem*>(m_fileSystem.get()); } void getMetadata(PassOwnPtr<MetadataCallback> successCallback = nullptr, PassOwnPtr<ErrorCallback> = nullptr); - void moveTo(PassRefPtr<DirectoryEntry> parent, const String& name = String(), PassOwnPtr<EntryCallback> successCallback = nullptr, PassOwnPtr<ErrorCallback> = nullptr) const; - void copyTo(PassRefPtr<DirectoryEntry> parent, const String& name = String(), PassOwnPtr<EntryCallback> successCallback = nullptr, PassOwnPtr<ErrorCallback> = nullptr) const; + void moveTo(DirectoryEntry* parent, const String& name = String(), PassOwnPtr<EntryCallback> successCallback = nullptr, PassOwnPtr<ErrorCallback> = nullptr) const; + void copyTo(DirectoryEntry* parent, const String& name = String(), PassOwnPtr<EntryCallback> successCallback = nullptr, PassOwnPtr<ErrorCallback> = nullptr) const; void remove(PassOwnPtr<VoidCallback> successCallback = nullptr, PassOwnPtr<ErrorCallback> = nullptr) const; void getParent(PassOwnPtr<EntryCallback> successCallback = nullptr, PassOwnPtr<ErrorCallback> = nullptr) const; + virtual void trace(Visitor*) OVERRIDE; + protected: - Entry(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + Entry(DOMFileSystemBase*, const String& fullPath); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/Entry.idl b/chromium/third_party/WebKit/Source/modules/filesystem/Entry.idl index 734272f93e2..5c3fed44601 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/Entry.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/Entry.idl @@ -31,6 +31,7 @@ [ Custom=Wrap, NoInterfaceObject, + GarbageCollected, ] interface Entry { readonly attribute boolean isFile; readonly attribute boolean isDirectory; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/EntryBase.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/EntryBase.cpp index 5013bd0956b..ba9e1c5a810 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/EntryBase.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/EntryBase.cpp @@ -34,11 +34,10 @@ #include "modules/filesystem/DOMFilePath.h" #include "modules/filesystem/DOMFileSystemBase.h" #include "platform/weborigin/SecurityOrigin.h" -#include "wtf/PassRefPtr.h" namespace WebCore { -EntryBase::EntryBase(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +EntryBase::EntryBase(DOMFileSystemBase* fileSystem, const String& fullPath) : m_fileSystem(fileSystem) , m_fullPath(fullPath) , m_name(DOMFilePath::getName(fullPath)) @@ -51,11 +50,20 @@ EntryBase::~EntryBase() String EntryBase::toURL() const { + if (!m_cachedURL.isNull()) + return m_cachedURL; + // Some filesystem type may not support toURL. if (!m_fileSystem->supportsToURL()) - return String(); + m_cachedURL = emptyString(); + else + m_cachedURL = m_fileSystem->createFileSystemURL(this).string(); + return m_cachedURL; +} - return m_fileSystem->createFileSystemURL(this).string(); +void EntryBase::trace(Visitor* visitor) +{ + visitor->trace(m_fileSystem); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/EntryBase.h b/chromium/third_party/WebKit/Source/modules/filesystem/EntryBase.h index 31119d76e85..068ef5a6434 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/EntryBase.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/EntryBase.h @@ -31,7 +31,7 @@ #ifndef EntryBase_h #define EntryBase_h -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -40,7 +40,7 @@ class DOMFileSystemBase; class EntrySync; // A common base class for Entry and EntrySync. -class EntryBase : public RefCounted<EntryBase> { +class EntryBase : public GarbageCollectedFinalized<EntryBase> { public: virtual ~EntryBase(); @@ -54,16 +54,19 @@ public: String toURL() const; + virtual void trace(Visitor*); + protected: - EntryBase(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + EntryBase(DOMFileSystemBase*, const String& fullPath); friend class EntrySync; - RefPtr<DOMFileSystemBase> m_fileSystem; + Member<DOMFileSystemBase> m_fileSystem; // This is a virtual path. - String m_fullPath; + const String m_fullPath; + const String m_name; - String m_name; + mutable String m_cachedURL; }; } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.cpp index b5b4d5d9dcf..11806640795 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.cpp @@ -43,52 +43,57 @@ namespace WebCore { -PassRefPtr<EntrySync> EntrySync::create(EntryBase* entry) +EntrySync* EntrySync::create(EntryBase* entry) { if (entry->isFile()) - return adoptRef(new FileEntrySync(entry->m_fileSystem, entry->m_fullPath)); - return adoptRef(new DirectoryEntrySync(entry->m_fileSystem, entry->m_fullPath)); + return FileEntrySync::create(entry->m_fileSystem, entry->m_fullPath); + return DirectoryEntrySync::create(entry->m_fileSystem, entry->m_fullPath); } -PassRefPtr<Metadata> EntrySync::getMetadata(ExceptionState& exceptionState) +Metadata* EntrySync::getMetadata(ExceptionState& exceptionState) { - MetadataSyncCallbackHelper helper; - m_fileSystem->getMetadata(this, helper.successCallback(), helper.errorCallback(), DOMFileSystemBase::Synchronous); - return helper.getResult(exceptionState); + RefPtr<MetadataSyncCallbackHelper> helper = MetadataSyncCallbackHelper::create(); + m_fileSystem->getMetadata(this, helper->successCallback(), helper->errorCallback(), DOMFileSystemBase::Synchronous); + return helper->getResult(exceptionState); } -PassRefPtr<EntrySync> EntrySync::moveTo(PassRefPtr<DirectoryEntrySync> parent, const String& name, ExceptionState& exceptionState) const +EntrySync* EntrySync::moveTo(DirectoryEntrySync* parent, const String& name, ExceptionState& exceptionState) const { - EntrySyncCallbackHelper helper; - m_fileSystem->move(this, parent.get(), name, helper.successCallback(), helper.errorCallback(), DOMFileSystemBase::Synchronous); - return helper.getResult(exceptionState); + RefPtr<EntrySyncCallbackHelper> helper = EntrySyncCallbackHelper::create(); + m_fileSystem->move(this, parent, name, helper->successCallback(), helper->errorCallback(), DOMFileSystemBase::Synchronous); + return helper->getResult(exceptionState); } -PassRefPtr<EntrySync> EntrySync::copyTo(PassRefPtr<DirectoryEntrySync> parent, const String& name, ExceptionState& exceptionState) const +EntrySync* EntrySync::copyTo(DirectoryEntrySync* parent, const String& name, ExceptionState& exceptionState) const { - EntrySyncCallbackHelper helper; - m_fileSystem->copy(this, parent.get(), name, helper.successCallback(), helper.errorCallback(), DOMFileSystemBase::Synchronous); - return helper.getResult(exceptionState); + RefPtr<EntrySyncCallbackHelper> helper = EntrySyncCallbackHelper::create(); + m_fileSystem->copy(this, parent, name, helper->successCallback(), helper->errorCallback(), DOMFileSystemBase::Synchronous); + return helper->getResult(exceptionState); } void EntrySync::remove(ExceptionState& exceptionState) const { - VoidSyncCallbackHelper helper; - m_fileSystem->remove(this, helper.successCallback(), helper.errorCallback(), DOMFileSystemBase::Synchronous); - helper.getResult(exceptionState); + RefPtr<VoidSyncCallbackHelper> helper = VoidSyncCallbackHelper::create(); + m_fileSystem->remove(this, helper->successCallback(), helper->errorCallback(), DOMFileSystemBase::Synchronous); + helper->getResult(exceptionState); } -PassRefPtr<EntrySync> EntrySync::getParent() const +EntrySync* EntrySync::getParent() const { // Sync verion of getParent doesn't throw exceptions. String parentPath = DOMFilePath::getDirectory(fullPath()); return DirectoryEntrySync::create(m_fileSystem, parentPath); } -EntrySync::EntrySync(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +EntrySync::EntrySync(DOMFileSystemBase* fileSystem, const String& fullPath) : EntryBase(fileSystem, fullPath) { ScriptWrappable::init(this); } +void EntrySync::trace(Visitor* visitor) +{ + EntryBase::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.h b/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.h index ff5e9540b0a..0acd8ab9b23 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.h @@ -34,9 +34,8 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/filesystem/DOMFileSystemSync.h" #include "modules/filesystem/EntryBase.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" namespace WebCore { @@ -44,20 +43,22 @@ class DirectoryEntrySync; class Metadata; class ExceptionState; -class EntrySync : public ScriptWrappable, public EntryBase { +class EntrySync : public EntryBase, public ScriptWrappable { public: - static PassRefPtr<EntrySync> create(EntryBase*); + static EntrySync* create(EntryBase*); DOMFileSystemSync* filesystem() const { return static_cast<DOMFileSystemSync*>(m_fileSystem.get()); } - PassRefPtr<Metadata> getMetadata(ExceptionState&); - PassRefPtr<EntrySync> moveTo(PassRefPtr<DirectoryEntrySync> parent, const String& name, ExceptionState&) const; - PassRefPtr<EntrySync> copyTo(PassRefPtr<DirectoryEntrySync> parent, const String& name, ExceptionState&) const; + Metadata* getMetadata(ExceptionState&); + EntrySync* moveTo(DirectoryEntrySync* parent, const String& name, ExceptionState&) const; + EntrySync* copyTo(DirectoryEntrySync* parent, const String& name, ExceptionState&) const; void remove(ExceptionState&) const; - PassRefPtr<EntrySync> getParent() const; + EntrySync* getParent() const; + + virtual void trace(Visitor*) OVERRIDE; protected: - EntrySync(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + EntrySync(DOMFileSystemBase*, const String& fullPath); }; } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.idl b/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.idl index 192c50bcddf..b8f6b72cfe6 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/EntrySync.idl @@ -31,6 +31,7 @@ [ Custom=Wrap, NoInterfaceObject, + GarbageCollected, ] interface EntrySync { readonly attribute boolean isFile; readonly attribute boolean isDirectory; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileEntry.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/FileEntry.cpp index 082953cf4a6..b039d1ba509 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileEntry.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileEntry.cpp @@ -39,7 +39,7 @@ namespace WebCore { -FileEntry::FileEntry(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +FileEntry::FileEntry(DOMFileSystemBase* fileSystem, const String& fullPath) : Entry(fileSystem, fullPath) { ScriptWrappable::init(this); @@ -55,4 +55,9 @@ void FileEntry::file(PassOwnPtr<FileCallback> successCallback, PassOwnPtr<ErrorC filesystem()->createFile(this, successCallback, errorCallback); } +void FileEntry::trace(Visitor* visitor) +{ + Entry::trace(visitor); +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileEntry.h b/chromium/third_party/WebKit/Source/modules/filesystem/FileEntry.h index 1bb3d488e69..bde2c05e0b8 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileEntry.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileEntry.h @@ -32,6 +32,7 @@ #define FileEntry_h #include "modules/filesystem/Entry.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -39,20 +40,22 @@ class DOMFileSystemBase; class FileCallback; class FileWriterCallback; -class FileEntry : public Entry { +class FileEntry FINAL : public Entry { public: - static PassRefPtr<FileEntry> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) + static FileEntry* create(DOMFileSystemBase* fileSystem, const String& fullPath) { - return adoptRef(new FileEntry(fileSystem, fullPath)); + return new FileEntry(fileSystem, fullPath); } void createWriter(PassOwnPtr<FileWriterCallback>, PassOwnPtr<ErrorCallback> = nullptr); void file(PassOwnPtr<FileCallback>, PassOwnPtr<ErrorCallback> = nullptr); - virtual bool isFile() const { return true; } + virtual bool isFile() const OVERRIDE { return true; } + + virtual void trace(Visitor*) OVERRIDE; private: - FileEntry(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + FileEntry(DOMFileSystemBase*, const String& fullPath); }; DEFINE_TYPE_CASTS(FileEntry, Entry, entry, entry->isFile(), entry.isFile()); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileEntrySync.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/FileEntrySync.cpp index ae80784c9c6..7c991184188 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileEntrySync.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileEntrySync.cpp @@ -37,20 +37,25 @@ namespace WebCore { -FileEntrySync::FileEntrySync(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) +FileEntrySync::FileEntrySync(DOMFileSystemBase* fileSystem, const String& fullPath) : EntrySync(fileSystem, fullPath) { ScriptWrappable::init(this); } -PassRefPtr<File> FileEntrySync::file(ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<File> FileEntrySync::file(ExceptionState& exceptionState) { return filesystem()->createFile(this, exceptionState); } -PassRefPtr<FileWriterSync> FileEntrySync::createWriter(ExceptionState& exceptionState) +FileWriterSync* FileEntrySync::createWriter(ExceptionState& exceptionState) { return filesystem()->createWriter(this, exceptionState); } +void FileEntrySync::trace(Visitor* visitor) +{ + EntrySync::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileEntrySync.h b/chromium/third_party/WebKit/Source/modules/filesystem/FileEntrySync.h index 441e4e136fc..5de8f4c7787 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileEntrySync.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileEntrySync.h @@ -32,8 +32,7 @@ #define FileEntrySync_h #include "modules/filesystem/EntrySync.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -42,21 +41,22 @@ class ExceptionState; class File; class FileWriterSync; -class FileEntrySync : public EntrySync { +class FileEntrySync FINAL : public EntrySync { public: - static PassRefPtr<FileEntrySync> create(PassRefPtr<DOMFileSystemBase> fileSystem, const String& fullPath) + static FileEntrySync* create(DOMFileSystemBase* fileSystem, const String& fullPath) { - return adoptRef(new FileEntrySync(fileSystem, fullPath)); + return new FileEntrySync(fileSystem, fullPath); } - virtual bool isFile() const { return true; } + virtual bool isFile() const OVERRIDE { return true; } - PassRefPtr<File> file(ExceptionState&); - PassRefPtr<FileWriterSync> createWriter(ExceptionState&); + PassRefPtrWillBeRawPtr<File> file(ExceptionState&); + FileWriterSync* createWriter(ExceptionState&); + + virtual void trace(Visitor*) OVERRIDE; private: - friend class EntrySync; - FileEntrySync(PassRefPtr<DOMFileSystemBase>, const String& fullPath); + FileEntrySync(DOMFileSystemBase*, const String& fullPath); }; DEFINE_TYPE_CASTS(FileEntrySync, EntrySync, entry, entry->isFile(), entry.isFile()); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemCallbacks.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemCallbacks.cpp index 85a7c86a868..708fa9c1989 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemCallbacks.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemCallbacks.cpp @@ -35,6 +35,7 @@ #include "core/fileapi/FileError.h" #include "core/html/VoidCallback.h" #include "modules/filesystem/DOMFilePath.h" +#include "modules/filesystem/DOMFileSystem.h" #include "modules/filesystem/DOMFileSystemBase.h" #include "modules/filesystem/DirectoryEntry.h" #include "modules/filesystem/DirectoryReader.h" @@ -52,9 +53,10 @@ namespace WebCore { -FileSystemCallbacksBase::FileSystemCallbacksBase(PassOwnPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem) +FileSystemCallbacksBase::FileSystemCallbacksBase(PassOwnPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem, ExecutionContext* context) : m_errorCallback(errorCallback) , m_fileSystem(fileSystem) + , m_executionContext(context) { if (m_fileSystem) m_fileSystem->addPendingCallbacks(); @@ -68,21 +70,57 @@ FileSystemCallbacksBase::~FileSystemCallbacksBase() void FileSystemCallbacksBase::didFail(int code) { - if (m_errorCallback) { - m_errorCallback->handleEvent(FileError::create(static_cast<FileError::ErrorCode>(code)).get()); - m_errorCallback.clear(); - } + if (m_errorCallback) + handleEventOrScheduleCallback(m_errorCallback.release(), FileError::create(static_cast<FileError::ErrorCode>(code))); +} + +bool FileSystemCallbacksBase::shouldScheduleCallback() const +{ + return !shouldBlockUntilCompletion() && m_executionContext && m_executionContext->activeDOMObjectsAreSuspended(); +} + +template <typename CB, typename CBArg> +void FileSystemCallbacksBase::handleEventOrScheduleCallback(PassOwnPtr<CB> callback, CBArg* arg) +{ + ASSERT(callback.get()); + if (shouldScheduleCallback()) + DOMFileSystem::scheduleCallback(m_executionContext.get(), callback, arg); + else if (callback) + callback->handleEvent(arg); + m_executionContext.clear(); +} + +template <typename CB, typename CBArg> +void FileSystemCallbacksBase::handleEventOrScheduleCallback(PassOwnPtr<CB> callback, PassRefPtrWillBeRawPtr<CBArg> arg) +{ + ASSERT(callback.get()); + if (shouldScheduleCallback()) + DOMFileSystem::scheduleCallback(m_executionContext.get(), callback, arg); + else if (callback) + callback->handleEvent(arg.get()); + m_executionContext.clear(); +} + +template <typename CB> +void FileSystemCallbacksBase::handleEventOrScheduleCallback(PassOwnPtr<CB> callback) +{ + ASSERT(callback.get()); + if (shouldScheduleCallback()) + DOMFileSystem::scheduleCallback(m_executionContext.get(), callback); + else if (callback) + callback->handleEvent(); + m_executionContext.clear(); } // EntryCallbacks ------------------------------------------------------------- -PassOwnPtr<AsyncFileSystemCallbacks> EntryCallbacks::create(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory) +PassOwnPtr<AsyncFileSystemCallbacks> EntryCallbacks::create(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem, const String& expectedPath, bool isDirectory) { - return adoptPtr(new EntryCallbacks(successCallback, errorCallback, fileSystem, expectedPath, isDirectory)); + return adoptPtr(new EntryCallbacks(successCallback, errorCallback, context, fileSystem, expectedPath, isDirectory)); } -EntryCallbacks::EntryCallbacks(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, PassRefPtr<DOMFileSystemBase> fileSystem, const String& expectedPath, bool isDirectory) - : FileSystemCallbacksBase(errorCallback, fileSystem.get()) +EntryCallbacks::EntryCallbacks(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem, const String& expectedPath, bool isDirectory) + : FileSystemCallbacksBase(errorCallback, fileSystem, context) , m_successCallback(successCallback) , m_expectedPath(expectedPath) , m_isDirectory(isDirectory) @@ -93,22 +131,21 @@ void EntryCallbacks::didSucceed() { if (m_successCallback) { if (m_isDirectory) - m_successCallback->handleEvent(DirectoryEntry::create(m_fileSystem, m_expectedPath).get()); + handleEventOrScheduleCallback(m_successCallback.release(), DirectoryEntry::create(m_fileSystem, m_expectedPath)); else - m_successCallback->handleEvent(FileEntry::create(m_fileSystem, m_expectedPath).get()); + handleEventOrScheduleCallback(m_successCallback.release(), FileEntry::create(m_fileSystem, m_expectedPath)); } - m_successCallback.clear(); } // EntriesCallbacks ----------------------------------------------------------- -PassOwnPtr<AsyncFileSystemCallbacks> EntriesCallbacks::create(PassOwnPtr<EntriesCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath) +PassOwnPtr<AsyncFileSystemCallbacks> EntriesCallbacks::create(PassOwnPtr<EntriesCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DirectoryReaderBase* directoryReader, const String& basePath) { - return adoptPtr(new EntriesCallbacks(successCallback, errorCallback, directoryReader, basePath)); + return adoptPtr(new EntriesCallbacks(successCallback, errorCallback, context, directoryReader, basePath)); } -EntriesCallbacks::EntriesCallbacks(PassOwnPtr<EntriesCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, PassRefPtr<DirectoryReaderBase> directoryReader, const String& basePath) - : FileSystemCallbacksBase(errorCallback, directoryReader->filesystem()) +EntriesCallbacks::EntriesCallbacks(PassOwnPtr<EntriesCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DirectoryReaderBase* directoryReader, const String& basePath) + : FileSystemCallbacksBase(errorCallback, directoryReader->filesystem(), context) , m_successCallback(successCallback) , m_directoryReader(directoryReader) , m_basePath(basePath) @@ -127,77 +164,72 @@ void EntriesCallbacks::didReadDirectoryEntry(const String& name, bool isDirector void EntriesCallbacks::didReadDirectoryEntries(bool hasMore) { m_directoryReader->setHasMoreEntries(hasMore); + EntryHeapVector entries; + entries.swap(m_entries); + // FIXME: delay the callback iff shouldScheduleCallback() is true. if (m_successCallback) - m_successCallback->handleEvent(m_entries); + m_successCallback->handleEvent(entries); } // FileSystemCallbacks -------------------------------------------------------- -PassOwnPtr<AsyncFileSystemCallbacks> FileSystemCallbacks::create(PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* executionContext, FileSystemType type) +PassOwnPtr<AsyncFileSystemCallbacks> FileSystemCallbacks::create(PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, FileSystemType type) { - return adoptPtr(new FileSystemCallbacks(successCallback, errorCallback, executionContext, type)); + return adoptPtr(new FileSystemCallbacks(successCallback, errorCallback, context, type)); } FileSystemCallbacks::FileSystemCallbacks(PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, FileSystemType type) - : FileSystemCallbacksBase(errorCallback, 0) + : FileSystemCallbacksBase(errorCallback, nullptr, context) , m_successCallback(successCallback) - , m_executionContext(context) , m_type(type) { } void FileSystemCallbacks::didOpenFileSystem(const String& name, const KURL& rootURL) { - if (m_successCallback) { - RefPtr<DOMFileSystem> fileSystem = DOMFileSystem::create(m_executionContext.get(), name, m_type, rootURL); - m_successCallback->handleEvent(fileSystem.get()); - m_executionContext.clear(); - } - m_successCallback.clear(); + if (m_successCallback) + handleEventOrScheduleCallback(m_successCallback.release(), DOMFileSystem::create(m_executionContext.get(), name, m_type, rootURL)); } // ResolveURICallbacks -------------------------------------------------------- -PassOwnPtr<AsyncFileSystemCallbacks> ResolveURICallbacks::create(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* executionContext) +PassOwnPtr<AsyncFileSystemCallbacks> ResolveURICallbacks::create(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context) { - return adoptPtr(new ResolveURICallbacks(successCallback, errorCallback, executionContext)); + return adoptPtr(new ResolveURICallbacks(successCallback, errorCallback, context)); } ResolveURICallbacks::ResolveURICallbacks(PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context) - : FileSystemCallbacksBase(errorCallback, 0) + : FileSystemCallbacksBase(errorCallback, nullptr, context) , m_successCallback(successCallback) - , m_executionContext(context) { } void ResolveURICallbacks::didResolveURL(const String& name, const KURL& rootURL, FileSystemType type, const String& filePath, bool isDirectory) { - RefPtr<DOMFileSystem> filesystem = DOMFileSystem::create(m_executionContext.get(), name, type, rootURL); - RefPtr<DirectoryEntry> root = filesystem->root(); + DOMFileSystem* filesystem = DOMFileSystem::create(m_executionContext.get(), name, type, rootURL); + DirectoryEntry* root = filesystem->root(); String absolutePath; - if (!DOMFileSystemBase::pathToAbsolutePath(type, root.get(), filePath, absolutePath)) { - m_errorCallback->handleEvent(FileError::create(FileError::INVALID_MODIFICATION_ERR).get()); - m_errorCallback.clear(); + if (!DOMFileSystemBase::pathToAbsolutePath(type, root, filePath, absolutePath)) { + handleEventOrScheduleCallback(m_errorCallback.release(), FileError::create(FileError::INVALID_MODIFICATION_ERR)); return; } if (isDirectory) - m_successCallback->handleEvent(DirectoryEntry::create(filesystem, absolutePath).get()); + handleEventOrScheduleCallback(m_successCallback.release(), DirectoryEntry::create(filesystem, absolutePath)); else - m_successCallback->handleEvent(FileEntry::create(filesystem, absolutePath).get()); - m_successCallback.clear(); + handleEventOrScheduleCallback(m_successCallback.release(), FileEntry::create(filesystem, absolutePath)); } // MetadataCallbacks ---------------------------------------------------------- -PassOwnPtr<AsyncFileSystemCallbacks> MetadataCallbacks::create(PassOwnPtr<MetadataCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem) +PassOwnPtr<AsyncFileSystemCallbacks> MetadataCallbacks::create(PassOwnPtr<MetadataCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem) { - return adoptPtr(new MetadataCallbacks(successCallback, errorCallback, fileSystem)); + return adoptPtr(new MetadataCallbacks(successCallback, errorCallback, context, fileSystem)); } -MetadataCallbacks::MetadataCallbacks(PassOwnPtr<MetadataCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem) - : FileSystemCallbacksBase(errorCallback, fileSystem) +MetadataCallbacks::MetadataCallbacks(PassOwnPtr<MetadataCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem) + : FileSystemCallbacksBase(errorCallback, fileSystem, context) , m_successCallback(successCallback) { } @@ -205,20 +237,19 @@ MetadataCallbacks::MetadataCallbacks(PassOwnPtr<MetadataCallback> successCallbac void MetadataCallbacks::didReadMetadata(const FileMetadata& metadata) { if (m_successCallback) - m_successCallback->handleEvent(Metadata::create(metadata).get()); - m_successCallback.clear(); + handleEventOrScheduleCallback(m_successCallback.release(), Metadata::create(metadata)); } // FileWriterBaseCallbacks ---------------------------------------------------------- -PassOwnPtr<AsyncFileSystemCallbacks> FileWriterBaseCallbacks::create(PassRefPtr<FileWriterBase> fileWriter, PassOwnPtr<FileWriterBaseCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) +PassOwnPtr<AsyncFileSystemCallbacks> FileWriterBaseCallbacks::create(PassRefPtrWillBeRawPtr<FileWriterBase> fileWriter, PassOwnPtr<FileWriterBaseCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context) { - return adoptPtr(new FileWriterBaseCallbacks(fileWriter, successCallback, errorCallback)); + return adoptPtr(new FileWriterBaseCallbacks(fileWriter, successCallback, errorCallback, context)); } -FileWriterBaseCallbacks::FileWriterBaseCallbacks(PassRefPtr<FileWriterBase> fileWriter, PassOwnPtr<FileWriterBaseCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) - : FileSystemCallbacksBase(errorCallback, 0) - , m_fileWriter(fileWriter) +FileWriterBaseCallbacks::FileWriterBaseCallbacks(PassRefPtrWillBeRawPtr<FileWriterBase> fileWriter, PassOwnPtr<FileWriterBaseCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context) + : FileSystemCallbacksBase(errorCallback, nullptr, context) + , m_fileWriter(fileWriter.get()) , m_successCallback(successCallback) { } @@ -227,19 +258,18 @@ void FileWriterBaseCallbacks::didCreateFileWriter(PassOwnPtr<blink::WebFileWrite { m_fileWriter->initialize(fileWriter, length); if (m_successCallback) - m_successCallback->handleEvent(m_fileWriter.release().get()); - m_successCallback.clear(); + handleEventOrScheduleCallback(m_successCallback.release(), m_fileWriter.release()); } // VoidCallbacks -------------------------------------------------------------- -PassOwnPtr<AsyncFileSystemCallbacks> VoidCallbacks::create(PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem) +PassOwnPtr<AsyncFileSystemCallbacks> VoidCallbacks::create(PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem) { - return adoptPtr(new VoidCallbacks(successCallback, errorCallback, fileSystem)); + return adoptPtr(new VoidCallbacks(successCallback, errorCallback, context, fileSystem)); } -VoidCallbacks::VoidCallbacks(PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, DOMFileSystemBase* fileSystem) - : FileSystemCallbacksBase(errorCallback, fileSystem) +VoidCallbacks::VoidCallbacks(PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem) + : FileSystemCallbacksBase(errorCallback, fileSystem, context) , m_successCallback(successCallback) { } @@ -247,8 +277,7 @@ VoidCallbacks::VoidCallbacks(PassOwnPtr<VoidCallback> successCallback, PassOwnPt void VoidCallbacks::didSucceed() { if (m_successCallback) - m_successCallback->handleEvent(); - m_successCallback.clear(); + handleEventOrScheduleCallback(m_successCallback.release()); } } // namespace diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemCallbacks.h b/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemCallbacks.h index 970ce8dd443..2bda769fba1 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemCallbacks.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemCallbacks.h @@ -34,7 +34,6 @@ #include "modules/filesystem/EntriesCallback.h" #include "platform/AsyncFileSystemCallbacks.h" #include "platform/FileSystemType.h" -#include "wtf/PassRefPtr.h" #include "wtf/Vector.h" #include "wtf/text/WTFString.h" @@ -58,95 +57,106 @@ public: virtual ~FileSystemCallbacksBase(); // For ErrorCallback. - virtual void didFail(int code) OVERRIDE; + virtual void didFail(int code) OVERRIDE FINAL; // Other callback methods are implemented by each subclass. protected: - FileSystemCallbacksBase(PassOwnPtr<ErrorCallback>, DOMFileSystemBase*); + FileSystemCallbacksBase(PassOwnPtr<ErrorCallback>, DOMFileSystemBase*, ExecutionContext*); + + bool shouldScheduleCallback() const; + + template <typename CB, typename CBArg> + void handleEventOrScheduleCallback(PassOwnPtr<CB>, CBArg*); + + template <typename CB, typename CBArg> + void handleEventOrScheduleCallback(PassOwnPtr<CB>, PassRefPtrWillBeRawPtr<CBArg>); + + template <typename CB> + void handleEventOrScheduleCallback(PassOwnPtr<CB>); + OwnPtr<ErrorCallback> m_errorCallback; - DOMFileSystemBase* m_fileSystem; + Persistent<DOMFileSystemBase> m_fileSystem; + RefPtrWillBePersistent<ExecutionContext> m_executionContext; }; // Subclasses ---------------------------------------------------------------- -class EntryCallbacks : public FileSystemCallbacksBase { +class EntryCallbacks FINAL : public FileSystemCallbacksBase { public: - static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>, PassRefPtr<DOMFileSystemBase>, const String& expectedPath, bool isDirectory); - virtual void didSucceed(); + static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, DOMFileSystemBase*, const String& expectedPath, bool isDirectory); + virtual void didSucceed() OVERRIDE; private: - EntryCallbacks(PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>, PassRefPtr<DOMFileSystemBase>, const String& expectedPath, bool isDirectory); + EntryCallbacks(PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, DOMFileSystemBase*, const String& expectedPath, bool isDirectory); OwnPtr<EntryCallback> m_successCallback; String m_expectedPath; bool m_isDirectory; }; -class EntriesCallbacks : public FileSystemCallbacksBase { +class EntriesCallbacks FINAL : public FileSystemCallbacksBase { public: - static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<EntriesCallback>, PassOwnPtr<ErrorCallback>, PassRefPtr<DirectoryReaderBase>, const String& basePath); - virtual void didReadDirectoryEntry(const String& name, bool isDirectory); - virtual void didReadDirectoryEntries(bool hasMore); + static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<EntriesCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, DirectoryReaderBase*, const String& basePath); + virtual void didReadDirectoryEntry(const String& name, bool isDirectory) OVERRIDE; + virtual void didReadDirectoryEntries(bool hasMore) OVERRIDE; private: - EntriesCallbacks(PassOwnPtr<EntriesCallback>, PassOwnPtr<ErrorCallback>, PassRefPtr<DirectoryReaderBase>, const String& basePath); + EntriesCallbacks(PassOwnPtr<EntriesCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, DirectoryReaderBase*, const String& basePath); OwnPtr<EntriesCallback> m_successCallback; - RefPtr<DirectoryReaderBase> m_directoryReader; + Persistent<DirectoryReaderBase> m_directoryReader; String m_basePath; - EntryVector m_entries; + PersistentHeapVector<Member<Entry> > m_entries; }; -class FileSystemCallbacks : public FileSystemCallbacksBase { +class FileSystemCallbacks FINAL : public FileSystemCallbacksBase { public: static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<FileSystemCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, FileSystemType); - virtual void didOpenFileSystem(const String& name, const KURL& rootURL); + virtual void didOpenFileSystem(const String& name, const KURL& rootURL) OVERRIDE; private: FileSystemCallbacks(PassOwnPtr<FileSystemCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, FileSystemType); OwnPtr<FileSystemCallback> m_successCallback; - RefPtr<ExecutionContext> m_executionContext; FileSystemType m_type; }; -class ResolveURICallbacks : public FileSystemCallbacksBase { +class ResolveURICallbacks FINAL : public FileSystemCallbacksBase { public: static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*); - virtual void didResolveURL(const String& name, const KURL& rootURL, FileSystemType, const String& filePath, bool isDirectry); + virtual void didResolveURL(const String& name, const KURL& rootURL, FileSystemType, const String& filePath, bool isDirectry) OVERRIDE; private: ResolveURICallbacks(PassOwnPtr<EntryCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*); OwnPtr<EntryCallback> m_successCallback; - RefPtr<ExecutionContext> m_executionContext; }; -class MetadataCallbacks : public FileSystemCallbacksBase { +class MetadataCallbacks FINAL : public FileSystemCallbacksBase { public: - static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<MetadataCallback>, PassOwnPtr<ErrorCallback>, DOMFileSystemBase*); - virtual void didReadMetadata(const FileMetadata&); + static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<MetadataCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, DOMFileSystemBase*); + virtual void didReadMetadata(const FileMetadata&) OVERRIDE; private: - MetadataCallbacks(PassOwnPtr<MetadataCallback>, PassOwnPtr<ErrorCallback>, DOMFileSystemBase*); + MetadataCallbacks(PassOwnPtr<MetadataCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, DOMFileSystemBase*); OwnPtr<MetadataCallback> m_successCallback; }; -class FileWriterBaseCallbacks : public FileSystemCallbacksBase { +class FileWriterBaseCallbacks FINAL : public FileSystemCallbacksBase { public: - static PassOwnPtr<AsyncFileSystemCallbacks> create(PassRefPtr<FileWriterBase>, PassOwnPtr<FileWriterBaseCallback>, PassOwnPtr<ErrorCallback>); - virtual void didCreateFileWriter(PassOwnPtr<blink::WebFileWriter>, long long length); + static PassOwnPtr<AsyncFileSystemCallbacks> create(PassRefPtrWillBeRawPtr<FileWriterBase>, PassOwnPtr<FileWriterBaseCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*); + virtual void didCreateFileWriter(PassOwnPtr<blink::WebFileWriter>, long long length) OVERRIDE; private: - FileWriterBaseCallbacks(PassRefPtr<FileWriterBase>, PassOwnPtr<FileWriterBaseCallback>, PassOwnPtr<ErrorCallback>); - RefPtr<FileWriterBase> m_fileWriter; + FileWriterBaseCallbacks(PassRefPtrWillBeRawPtr<FileWriterBase>, PassOwnPtr<FileWriterBaseCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*); + Persistent<FileWriterBase> m_fileWriter; OwnPtr<FileWriterBaseCallback> m_successCallback; }; -class VoidCallbacks : public FileSystemCallbacksBase { +class VoidCallbacks FINAL : public FileSystemCallbacksBase { public: - static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<VoidCallback>, PassOwnPtr<ErrorCallback>, DOMFileSystemBase*); - virtual void didSucceed(); + static PassOwnPtr<AsyncFileSystemCallbacks> create(PassOwnPtr<VoidCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, DOMFileSystemBase*); + virtual void didSucceed() OVERRIDE; private: - VoidCallbacks(PassOwnPtr<VoidCallback>, PassOwnPtr<ErrorCallback>, DOMFileSystemBase*); + VoidCallbacks(PassOwnPtr<VoidCallback>, PassOwnPtr<ErrorCallback>, ExecutionContext*, DOMFileSystemBase*); OwnPtr<VoidCallback> m_successCallback; }; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemClient.h b/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemClient.h index 07a29db1d96..f47893b37a4 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemClient.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileSystemClient.h @@ -37,8 +37,9 @@ namespace WebCore { -class Page; class ExecutionContext; +class LocalFrame; +class PermissionCallbacks; class WorkerClients; class FileSystemClient { @@ -47,10 +48,11 @@ public: FileSystemClient() { } virtual ~FileSystemClient() { } - virtual bool allowFileSystem(ExecutionContext*) = 0; + virtual bool requestFileSystemAccessSync(ExecutionContext*) = 0; + virtual void requestFileSystemAccessAsync(ExecutionContext*, PassOwnPtr<WebCore::PermissionCallbacks>) = 0; }; -void provideLocalFileSystemTo(Page*, PassOwnPtr<FileSystemClient>); +void provideLocalFileSystemTo(LocalFrame&, PassOwnPtr<FileSystemClient>); void provideLocalFileSystemToWorker(WorkerClients*, PassOwnPtr<FileSystemClient>); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.cpp index a22fac948d3..d090bba5743 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.cpp @@ -44,11 +44,11 @@ namespace WebCore { static const int kMaxRecursionDepth = 3; static const double progressNotificationIntervalMS = 50; -PassRefPtr<FileWriter> FileWriter::create(ExecutionContext* context) +FileWriter* FileWriter::create(ExecutionContext* context) { - RefPtr<FileWriter> fileWriter(adoptRef(new FileWriter(context))); + FileWriter* fileWriter = adoptRefCountedGarbageCollected(new FileWriter(context)); fileWriter->suspendIfNeeded(); - return fileWriter.release(); + return fileWriter; } FileWriter::FileWriter(ExecutionContext* context) @@ -232,7 +232,6 @@ void FileWriter::didFail(blink::WebFileError code) completeAbort(); return; } - ASSERT(static_cast<FileError::ErrorCode>(code) != FileError::ABORT_ERR); ASSERT(m_queuedOperation == OperationNone); ASSERT(m_readyState == WRITING); m_blobBeingWritten.clear(); @@ -319,4 +318,12 @@ void FileWriter::setError(FileError::ErrorCode errorCode, ExceptionState& except m_error = FileError::create(errorCode); } +void FileWriter::trace(Visitor* visitor) +{ + visitor->trace(m_error); + visitor->trace(m_blobBeingWritten); + FileWriterBase::trace(visitor); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.h b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.h index 2cc757875a2..c3a8cea9997 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.h @@ -34,11 +34,11 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" #include "core/dom/ExecutionContext.h" -#include "core/events/EventTarget.h" #include "core/fileapi/FileError.h" +#include "modules/EventTargetModules.h" #include "modules/filesystem/FileWriterBase.h" +#include "platform/heap/Handle.h" #include "public/platform/WebFileWriterClient.h" -#include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" namespace WebCore { @@ -47,10 +47,11 @@ class Blob; class ExceptionState; class ExecutionContext; -class FileWriter : public ScriptWrappable, public FileWriterBase, public ActiveDOMObject, public EventTargetWithInlineData, public blink::WebFileWriterClient { - DEFINE_EVENT_TARGET_REFCOUNTING(FileWriterBase); +class FileWriter FINAL : public FileWriterBase, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData, public blink::WebFileWriterClient { + DEFINE_EVENT_TARGET_REFCOUNTING(RefCountedGarbageCollected<FileWriterBase>); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FileWriter); public: - static PassRefPtr<FileWriter> create(ExecutionContext*); + static FileWriter* create(ExecutionContext*); enum ReadyState { INIT = 0, @@ -71,7 +72,7 @@ public: virtual void didFail(blink::WebFileError) OVERRIDE; // ActiveDOMObject - virtual void stop(); + virtual void stop() OVERRIDE; // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE; @@ -84,6 +85,8 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(error); DEFINE_ATTRIBUTE_EVENT_LISTENER(writeend); + virtual void trace(Visitor*) OVERRIDE; + private: enum Operation { OperationNone, @@ -106,7 +109,7 @@ private: void setError(FileError::ErrorCode, ExceptionState&); - RefPtr<FileError> m_error; + RefPtrWillBeMember<FileError> m_error; ReadyState m_readyState; Operation m_operationInProgress; Operation m_queuedOperation; @@ -116,7 +119,7 @@ private: long long m_numAborts; long long m_recursionDepth; double m_lastProgressNotificationTimeMS; - RefPtr<Blob> m_blobBeingWritten; + RefPtrWillBeMember<Blob> m_blobBeingWritten; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.idl b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.idl index 2d4b54babda..4cac0d009ba 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriter.idl @@ -31,7 +31,8 @@ [ NoInterfaceObject, - ActiveDOMObject + ActiveDOMObject, + GarbageCollected, ] interface FileWriter : EventTarget { // ready states const unsigned short INIT = 0; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterBase.h b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterBase.h index 8cf9b87c0df..3f8689bf32e 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterBase.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterBase.h @@ -31,15 +31,17 @@ #ifndef FileWriterBase_h #define FileWriterBase_h +#include "platform/heap/Handle.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" -#include "wtf/RefCounted.h" namespace blink { class WebFileWriter; } namespace WebCore { -class FileWriterBase : public RefCounted<FileWriterBase> { +// FIXME: Oilpan: Change this to GarbageCollectedFinalized once FileWriter stops using +// ActiveDOMObject::setPendingActivity. +class FileWriterBase : public RefCountedGarbageCollected<FileWriterBase> { public: virtual ~FileWriterBase(); void initialize(PassOwnPtr<blink::WebFileWriter>, long long length); @@ -53,6 +55,8 @@ public: return m_length; } + virtual void trace(Visitor*) { } + protected: FileWriterBase(); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterSync.h b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterSync.h index d7c50508015..448080c4c5d 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterSync.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterSync.h @@ -34,19 +34,19 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/fileapi/FileError.h" #include "modules/filesystem/FileWriterBase.h" +#include "platform/heap/Handle.h" #include "public/platform/WebFileWriterClient.h" -#include "wtf/PassRefPtr.h" namespace WebCore { class Blob; class ExceptionState; -class FileWriterSync : public ScriptWrappable, public FileWriterBase, public blink::WebFileWriterClient { +class FileWriterSync FINAL : public FileWriterBase, public ScriptWrappable, public blink::WebFileWriterClient { public: - static PassRefPtr<FileWriterSync> create() + static FileWriterSync* create() { - return adoptRef(new FileWriterSync()); + return adoptRefCountedGarbageCollected(new FileWriterSync()); } virtual ~FileWriterSync(); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterSync.idl b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterSync.idl index 9b746bd1e29..40fca495ad4 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterSync.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/FileWriterSync.idl @@ -29,7 +29,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + GarbageCollected, ] interface FileWriterSync { // synchronous write/modify methods [RaisesException] void write(Blob data); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.cpp index d0ef31ed5d3..b2ec90a2534 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.cpp @@ -39,19 +39,20 @@ #include "modules/filesystem/Entry.h" #include "modules/filesystem/FileEntry.h" #include "platform/FileMetadata.h" +#include "platform/heap/Handle.h" namespace WebCore { // static -EntryVector HTMLInputElementFileSystem::webkitEntries(ExecutionContext* executionContext, HTMLInputElement* input) +EntryHeapVector HTMLInputElementFileSystem::webkitEntries(ExecutionContext* executionContext, HTMLInputElement& input) { - EntryVector entries; - FileList* files = input->files(); + EntryHeapVector entries; + FileList* files = input.files(); if (!files) return entries; - RefPtr<DOMFileSystem> filesystem = DOMFileSystem::createIsolatedFileSystem(executionContext, input->droppedFileSystemId()); + DOMFileSystem* filesystem = DOMFileSystem::createIsolatedFileSystem(executionContext, input.droppedFileSystemId()); if (!filesystem) { // Drag-drop isolated filesystem is not available. return entries; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.h b/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.h index a64c7b49c50..8f567f16482 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.h @@ -32,7 +32,6 @@ #define HTMLInputElementFileSystem_h #include "modules/filesystem/EntriesCallback.h" -#include "wtf/PassRefPtr.h" namespace WebCore { @@ -42,7 +41,7 @@ class ExecutionContext; class HTMLInputElementFileSystem { public: - static EntryVector webkitEntries(ExecutionContext*, HTMLInputElement*); + static EntryHeapVector webkitEntries(ExecutionContext*, HTMLInputElement&); private: HTMLInputElementFileSystem(); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.idl b/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.idl index 836e25d20d0..c55dcd91674 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/HTMLInputElementFileSystem.idl @@ -28,7 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -partial interface HTMLInputElement { -[RuntimeEnabled=FileSystem,CallWith=ExecutionContext] readonly attribute Entry[] webkitEntries; +[ + RuntimeEnabled=FileSystem, +] partial interface HTMLInputElement { + [CallWith=ExecutionContext] readonly attribute Entry[] webkitEntries; }; - diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFileSystemAgent.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFileSystemAgent.cpp new file mode 100644 index 00000000000..23648bf2e7c --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFileSystemAgent.cpp @@ -0,0 +1,730 @@ +/* + * Copyright (C) 2011, 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/filesystem/InspectorFileSystemAgent.h" + +#include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/dom/DOMImplementation.h" +#include "core/dom/Document.h" +#include "core/fileapi/File.h" +#include "core/fileapi/FileError.h" +#include "core/fileapi/FileReader.h" +#include "core/frame/LocalFrame.h" +#include "core/html/VoidCallback.h" +#include "core/html/parser/TextResourceDecoder.h" +#include "core/inspector/InspectorState.h" +#include "core/page/Page.h" +#include "modules/filesystem/DOMFileSystem.h" +#include "modules/filesystem/DirectoryEntry.h" +#include "modules/filesystem/DirectoryReader.h" +#include "modules/filesystem/EntriesCallback.h" +#include "modules/filesystem/Entry.h" +#include "modules/filesystem/EntryCallback.h" +#include "modules/filesystem/ErrorCallback.h" +#include "modules/filesystem/FileCallback.h" +#include "modules/filesystem/FileEntry.h" +#include "modules/filesystem/FileSystemCallbacks.h" +#include "modules/filesystem/LocalFileSystem.h" +#include "modules/filesystem/Metadata.h" +#include "modules/filesystem/MetadataCallback.h" +#include "platform/MIMETypeRegistry.h" +#include "platform/heap/Handle.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "wtf/ArrayBuffer.h" +#include "wtf/text/Base64.h" +#include "wtf/text/TextEncoding.h" + +using WebCore::TypeBuilder::Array; + +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileSystemRootCallback RequestFileSystemRootCallback; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestDirectoryContentCallback RequestDirectoryContentCallback; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestMetadataCallback RequestMetadataCallback; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileContentCallback RequestFileContentCallback; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::DeleteEntryCallback DeleteEntryCallback; + +namespace WebCore { + +namespace FileSystemAgentState { +static const char fileSystemAgentEnabled[] = "fileSystemAgentEnabled"; +} + +namespace { + +template<typename BaseCallback, typename Handler, typename Argument> +class CallbackDispatcher FINAL : public BaseCallback { +public: + typedef bool (Handler::*HandlingMethod)(Argument); + + static PassOwnPtr<CallbackDispatcher> create(PassRefPtr<Handler> handler, HandlingMethod handlingMethod) + { + return adoptPtr(new CallbackDispatcher(handler, handlingMethod)); + } + + virtual void handleEvent(Argument argument) OVERRIDE + { + (m_handler.get()->*m_handlingMethod)(argument); + } + +private: + CallbackDispatcher(PassRefPtr<Handler> handler, HandlingMethod handlingMethod) + : m_handler(handler) + , m_handlingMethod(handlingMethod) { } + + RefPtr<Handler> m_handler; + HandlingMethod m_handlingMethod; +}; + +template<typename BaseCallback> +class CallbackDispatcherFactory { +public: + template<typename Handler, typename Argument> + static PassOwnPtr<CallbackDispatcher<BaseCallback, Handler, Argument> > create(Handler* handler, bool (Handler::*handlingMethod)(Argument)) + { + return CallbackDispatcher<BaseCallback, Handler, Argument>::create(PassRefPtr<Handler>(handler), handlingMethod); + } +}; + +class FileSystemRootRequest : public RefCounted<FileSystemRootRequest> { + WTF_MAKE_NONCOPYABLE(FileSystemRootRequest); +public: + static PassRefPtr<FileSystemRootRequest> create(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type) + { + return adoptRef(new FileSystemRootRequest(requestCallback, type)); + } + + void start(ExecutionContext*); + +private: + bool didHitError(FileError* error) + { + reportResult(error->code()); + return true; + } + + bool didGetEntry(Entry*); + + void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Entry> entry = nullptr) + { + m_requestCallback->sendSuccess(static_cast<int>(errorCode), entry); + } + + FileSystemRootRequest(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type) + : m_requestCallback(requestCallback) + , m_type(type) { } + + RefPtr<RequestFileSystemRootCallback> m_requestCallback; + String m_type; +}; + +void FileSystemRootRequest::start(ExecutionContext* executionContext) +{ + ASSERT(executionContext); + + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileSystemRootRequest::didHitError); + + FileSystemType type; + if (!DOMFileSystemBase::pathPrefixToFileSystemType(m_type, type)) { + errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get()); + return; + } + + KURL rootURL = DOMFileSystemBase::createFileSystemRootURL(executionContext->securityOrigin()->toString(), type); + if (!rootURL.isValid()) { + errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get()); + return; + } + + OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileSystemRootRequest::didGetEntry); + OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext); + LocalFileSystem::from(*executionContext)->resolveURL(executionContext, rootURL, fileSystemCallbacks.release()); +} + +bool FileSystemRootRequest::didGetEntry(Entry* entry) +{ + RefPtr<TypeBuilder::FileSystem::Entry> result = TypeBuilder::FileSystem::Entry::create() + .setUrl(entry->toURL()) + .setName("/") + .setIsDirectory(true); + reportResult(static_cast<FileError::ErrorCode>(0), result); + return true; +} + +class DirectoryContentRequest FINAL : public RefCounted<DirectoryContentRequest> { + WTF_MAKE_NONCOPYABLE(DirectoryContentRequest); +public: + static PassRefPtr<DirectoryContentRequest> create(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url) + { + return adoptRef(new DirectoryContentRequest(requestCallback, url)); + } + + ~DirectoryContentRequest() + { + reportResult(FileError::ABORT_ERR); + } + + void start(ExecutionContext*); + +private: + bool didHitError(FileError* error) + { + reportResult(error->code()); + return true; + } + + bool didGetEntry(Entry*); + bool didReadDirectoryEntries(const EntryHeapVector&); + + void reportResult(FileError::ErrorCode errorCode, PassRefPtr<Array<TypeBuilder::FileSystem::Entry> > entries = nullptr) + { + m_requestCallback->sendSuccess(static_cast<int>(errorCode), entries); + } + + DirectoryContentRequest(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url) + : m_requestCallback(requestCallback) + , m_url(ParsedURLString, url) { } + + void readDirectoryEntries(); + + RefPtr<RequestDirectoryContentCallback> m_requestCallback; + KURL m_url; + RefPtr<Array<TypeBuilder::FileSystem::Entry> > m_entries; + Persistent<DirectoryReader> m_directoryReader; +}; + +void DirectoryContentRequest::start(ExecutionContext* executionContext) +{ + ASSERT(executionContext); + + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError); + OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DirectoryContentRequest::didGetEntry); + + OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext); + + LocalFileSystem::from(*executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release()); +} + +bool DirectoryContentRequest::didGetEntry(Entry* entry) +{ + if (!entry->isDirectory()) { + reportResult(FileError::TYPE_MISMATCH_ERR); + return true; + } + + m_directoryReader = toDirectoryEntry(entry)->createReader(); + m_entries = Array<TypeBuilder::FileSystem::Entry>::create(); + readDirectoryEntries(); + return true; +} + +void DirectoryContentRequest::readDirectoryEntries() +{ + if (!m_directoryReader->filesystem()->executionContext()) { + reportResult(FileError::ABORT_ERR); + return; + } + + OwnPtr<EntriesCallback> successCallback = CallbackDispatcherFactory<EntriesCallback>::create(this, &DirectoryContentRequest::didReadDirectoryEntries); + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError); + m_directoryReader->readEntries(successCallback.release(), errorCallback.release()); +} + +bool DirectoryContentRequest::didReadDirectoryEntries(const EntryHeapVector& entries) +{ + if (entries.isEmpty()) { + reportResult(static_cast<FileError::ErrorCode>(0), m_entries); + return true; + } + + for (size_t i = 0; i < entries.size(); ++i) { + Entry* entry = entries[i]; + RefPtr<TypeBuilder::FileSystem::Entry> entryForFrontend = TypeBuilder::FileSystem::Entry::create() + .setUrl(entry->toURL()) + .setName(entry->name()) + .setIsDirectory(entry->isDirectory()); + + using TypeBuilder::Page::ResourceType; + if (!entry->isDirectory()) { + String mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name()); + ResourceType::Enum resourceType; + if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) { + resourceType = ResourceType::Image; + entryForFrontend->setIsTextFile(false); + } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)) { + resourceType = ResourceType::Script; + entryForFrontend->setIsTextFile(true); + } else if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) { + resourceType = ResourceType::Document; + entryForFrontend->setIsTextFile(true); + } else { + resourceType = ResourceType::Other; + entryForFrontend->setIsTextFile(DOMImplementation::isXMLMIMEType(mimeType) || DOMImplementation::isTextMIMEType(mimeType)); + } + + entryForFrontend->setMimeType(mimeType); + entryForFrontend->setResourceType(resourceType); + } + + m_entries->addItem(entryForFrontend); + } + readDirectoryEntries(); + return true; +} + +class MetadataRequest FINAL : public RefCounted<MetadataRequest> { + WTF_MAKE_NONCOPYABLE(MetadataRequest); +public: + static PassRefPtr<MetadataRequest> create(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url) + { + return adoptRef(new MetadataRequest(requestCallback, url)); + } + + ~MetadataRequest() + { + reportResult(FileError::ABORT_ERR); + } + + void start(ExecutionContext*); + +private: + bool didHitError(FileError* error) + { + reportResult(error->code()); + return true; + } + + bool didGetEntry(Entry*); + bool didGetMetadata(Metadata*); + + void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Metadata> metadata = nullptr) + { + m_requestCallback->sendSuccess(static_cast<int>(errorCode), metadata); + } + + MetadataRequest(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url) + : m_requestCallback(requestCallback) + , m_url(ParsedURLString, url) { } + + RefPtr<RequestMetadataCallback> m_requestCallback; + KURL m_url; + bool m_isDirectory; +}; + +void MetadataRequest::start(ExecutionContext* executionContext) +{ + ASSERT(executionContext); + + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError); + OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &MetadataRequest::didGetEntry); + OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext); + LocalFileSystem::from(*executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release()); +} + +bool MetadataRequest::didGetEntry(Entry* entry) +{ + if (!entry->filesystem()->executionContext()) { + reportResult(FileError::ABORT_ERR); + return true; + } + + OwnPtr<MetadataCallback> successCallback = CallbackDispatcherFactory<MetadataCallback>::create(this, &MetadataRequest::didGetMetadata); + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError); + entry->getMetadata(successCallback.release(), errorCallback.release()); + m_isDirectory = entry->isDirectory(); + return true; +} + +bool MetadataRequest::didGetMetadata(Metadata* metadata) +{ + using TypeBuilder::FileSystem::Metadata; + RefPtr<Metadata> result = Metadata::create() + .setModificationTime(metadata->modificationTime()) + .setSize(metadata->size()); + reportResult(static_cast<FileError::ErrorCode>(0), result); + return true; +} + +class FileContentRequest FINAL : public EventListener { + WTF_MAKE_NONCOPYABLE(FileContentRequest); +public: + static PassRefPtr<FileContentRequest> create(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset) + { + return adoptRef(new FileContentRequest(requestCallback, url, readAsText, start, end, charset)); + } + + virtual ~FileContentRequest() + { + reportResult(FileError::ABORT_ERR); + } + + void start(ExecutionContext*); + + virtual bool operator==(const EventListener& other) OVERRIDE + { + return this == &other; + } + + virtual void handleEvent(ExecutionContext*, Event* event) OVERRIDE + { + if (event->type() == EventTypeNames::load) + didRead(); + else if (event->type() == EventTypeNames::error) + didHitError(m_reader->error().get()); + } + +private: + bool didHitError(FileError* error) + { + reportResult(error->code()); + return true; + } + + bool didGetEntry(Entry*); + bool didGetFile(File*); + void didRead(); + + void reportResult(FileError::ErrorCode errorCode, const String* result = 0, const String* charset = 0) + { + m_requestCallback->sendSuccess(static_cast<int>(errorCode), result, charset); + } + + FileContentRequest(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset) + : EventListener(EventListener::CPPEventListenerType) + , m_requestCallback(requestCallback) + , m_url(ParsedURLString, url) + , m_readAsText(readAsText) + , m_start(start) + , m_end(end) + , m_charset(charset) { } + + RefPtr<RequestFileContentCallback> m_requestCallback; + KURL m_url; + bool m_readAsText; + int m_start; + long long m_end; + String m_mimeType; + String m_charset; + + RefPtrWillBePersistent<FileReader> m_reader; +}; + +void FileContentRequest::start(ExecutionContext* executionContext) +{ + ASSERT(executionContext); + + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError); + OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileContentRequest::didGetEntry); + + OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext); + LocalFileSystem::from(*executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release()); +} + +bool FileContentRequest::didGetEntry(Entry* entry) +{ + if (entry->isDirectory()) { + reportResult(FileError::TYPE_MISMATCH_ERR); + return true; + } + + if (!entry->filesystem()->executionContext()) { + reportResult(FileError::ABORT_ERR); + return true; + } + + OwnPtr<FileCallback> successCallback = CallbackDispatcherFactory<FileCallback>::create(this, &FileContentRequest::didGetFile); + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError); + toFileEntry(entry)->file(successCallback.release(), errorCallback.release()); + + m_reader = FileReader::create(entry->filesystem()->executionContext()); + m_mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name()); + + return true; +} + +bool FileContentRequest::didGetFile(File* file) +{ + RefPtrWillBeRawPtr<Blob> blob = static_cast<Blob*>(file)->slice(m_start, m_end, IGNORE_EXCEPTION); + m_reader->setOnload(this); + m_reader->setOnerror(this); + + m_reader->readAsArrayBuffer(blob.get(), IGNORE_EXCEPTION); + return true; +} + +void FileContentRequest::didRead() +{ + RefPtr<ArrayBuffer> buffer = m_reader->arrayBufferResult(); + + if (!m_readAsText) { + String result = base64Encode(static_cast<char*>(buffer->data()), buffer->byteLength()); + reportResult(static_cast<FileError::ErrorCode>(0), &result, 0); + return; + } + + OwnPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(m_mimeType, m_charset, true); + String result = decoder->decode(static_cast<char*>(buffer->data()), buffer->byteLength()); + result = result + decoder->flush(); + m_charset = decoder->encoding().name(); + reportResult(static_cast<FileError::ErrorCode>(0), &result, &m_charset); +} + +class DeleteEntryRequest FINAL : public RefCounted<DeleteEntryRequest> { +public: + static PassRefPtr<DeleteEntryRequest> create(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url) + { + return adoptRef(new DeleteEntryRequest(requestCallback, url)); + } + + ~DeleteEntryRequest() + { + reportResult(FileError::ABORT_ERR); + } + + void start(ExecutionContext*); + +private: + // CallbackDispatcherFactory doesn't handle 0-arg handleEvent methods + class VoidCallbackImpl FINAL : public VoidCallback { + public: + explicit VoidCallbackImpl(PassRefPtr<DeleteEntryRequest> handler) + : m_handler(handler) + { + } + + virtual void handleEvent() OVERRIDE + { + m_handler->didDeleteEntry(); + } + + private: + RefPtr<DeleteEntryRequest> m_handler; + }; + + bool didHitError(FileError* error) + { + reportResult(error->code()); + return true; + } + + bool didGetEntry(Entry*); + bool didDeleteEntry(); + + void reportResult(FileError::ErrorCode errorCode) + { + m_requestCallback->sendSuccess(static_cast<int>(errorCode)); + } + + DeleteEntryRequest(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url) + : m_requestCallback(requestCallback) + , m_url(url) { } + + RefPtr<DeleteEntryCallback> m_requestCallback; + KURL m_url; +}; + +void DeleteEntryRequest::start(ExecutionContext* executionContext) +{ + ASSERT(executionContext); + + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError); + + FileSystemType type; + String path; + if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) { + errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get()); + return; + } + + if (path == "/") { + OwnPtr<VoidCallback> successCallback = adoptPtr(new VoidCallbackImpl(this)); + OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = VoidCallbacks::create(successCallback.release(), errorCallback.release(), executionContext, nullptr); + LocalFileSystem::from(*executionContext)->deleteFileSystem(executionContext, type, fileSystemCallbacks.release()); + } else { + OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DeleteEntryRequest::didGetEntry); + OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext); + LocalFileSystem::from(*executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release()); + } +} + +bool DeleteEntryRequest::didGetEntry(Entry* entry) +{ + OwnPtr<VoidCallback> successCallback = adoptPtr(new VoidCallbackImpl(this)); + OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError); + if (entry->isDirectory()) { + DirectoryEntry* directoryEntry = toDirectoryEntry(entry); + directoryEntry->removeRecursively(successCallback.release(), errorCallback.release()); + } else { + entry->remove(successCallback.release(), errorCallback.release()); + } + return true; +} + +bool DeleteEntryRequest::didDeleteEntry() +{ + reportResult(static_cast<FileError::ErrorCode>(0)); + return true; +} + +} // anonymous namespace + +// static +PassOwnPtr<InspectorFileSystemAgent> InspectorFileSystemAgent::create(Page* page) +{ + return adoptPtr(new InspectorFileSystemAgent(page)); +} + +InspectorFileSystemAgent::~InspectorFileSystemAgent() +{ +} + +void InspectorFileSystemAgent::enable(ErrorString*) +{ + if (m_enabled) + return; + m_enabled = true; + m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled); +} + +void InspectorFileSystemAgent::disable(ErrorString*) +{ + if (!m_enabled) + return; + m_enabled = false; + m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled); +} + +void InspectorFileSystemAgent::requestFileSystemRoot(ErrorString* error, const String& origin, const String& type, PassRefPtr<RequestFileSystemRootCallback> requestCallback) +{ + if (!assertEnabled(error)) + return; + + ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(origin).get()); + if (!executionContext) + return; + + FileSystemRootRequest::create(requestCallback, type)->start(executionContext); +} + +void InspectorFileSystemAgent::requestDirectoryContent(ErrorString* error, const String& url, PassRefPtr<RequestDirectoryContentCallback> requestCallback) +{ + if (!assertEnabled(error)) + return; + + ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get()); + if (!executionContext) + return; + + DirectoryContentRequest::create(requestCallback, url)->start(executionContext); +} + +void InspectorFileSystemAgent::requestMetadata(ErrorString* error, const String& url, PassRefPtr<RequestMetadataCallback> requestCallback) +{ + if (!assertEnabled(error)) + return; + + ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get()); + if (!executionContext) + return; + + MetadataRequest::create(requestCallback, url)->start(executionContext); +} + +void InspectorFileSystemAgent::requestFileContent(ErrorString* error, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtr<RequestFileContentCallback> requestCallback) +{ + if (!assertEnabled(error)) + return; + + ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get()); + if (!executionContext) + return; + + long long startPosition = start ? *start : 0; + long long endPosition = end ? *end : std::numeric_limits<long long>::max(); + FileContentRequest::create(requestCallback, url, readAsText, startPosition, endPosition, charset ? *charset : "")->start(executionContext); +} + +void InspectorFileSystemAgent::deleteEntry(ErrorString* error, const String& urlString, PassRefPtr<DeleteEntryCallback> requestCallback) +{ + if (!assertEnabled(error)) + return; + + KURL url(ParsedURLString, urlString); + + ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::create(url).get()); + if (!executionContext) + return; + + DeleteEntryRequest::create(requestCallback, url)->start(executionContext); +} + +void InspectorFileSystemAgent::clearFrontend() +{ + m_enabled = false; + m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled); +} + +void InspectorFileSystemAgent::restore() +{ + m_enabled = m_state->getBoolean(FileSystemAgentState::fileSystemAgentEnabled); +} + +InspectorFileSystemAgent::InspectorFileSystemAgent(Page* page) + : InspectorBaseAgent<InspectorFileSystemAgent>("FileSystem") + , m_page(page) + , m_enabled(false) +{ + ASSERT(m_page); +} + +bool InspectorFileSystemAgent::assertEnabled(ErrorString* error) +{ + if (!m_enabled) { + *error = "FileSystem agent is not enabled."; + return false; + } + return true; +} + +ExecutionContext* InspectorFileSystemAgent::assertExecutionContextForOrigin(ErrorString* error, SecurityOrigin* origin) +{ + for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { + if (!frame->isLocalFrame()) + continue; + LocalFrame* localFrame = toLocalFrame(frame); + if (localFrame->document() && localFrame->document()->securityOrigin()->isSameSchemeHostPort(origin)) + return localFrame->document(); + } + + *error = "No frame is available for the request"; + return 0; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/notifications/WebKitNotification.h b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFileSystemAgent.h index 5039adc6ac3..26f9a0cd5ac 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/WebKitNotification.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFileSystemAgent.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2011, 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,48 +28,45 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebKitNotification_h -#define WebKitNotification_h +#ifndef InspectorFileSystemAgent_h +#define InspectorFileSystemAgent_h -#if ENABLE(LEGACY_NOTIFICATIONS) - -#include "core/events/EventTarget.h" -#include "modules/notifications/NotificationBase.h" +#include "core/inspector/InspectorBaseAgent.h" +#include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" namespace WebCore { -class ExceptionState; class ExecutionContext; -class NotificationCenter; - -// Implementation of the legacy notification API as specified the following page: -// http://chromium.org/developers/design-documents/desktop-notifications/api-specification -class WebKitNotification : public RefCounted<WebKitNotification>, public NotificationBase { - REFCOUNTED_EVENT_TARGET(WebKitNotification); +class Page; +class SecurityOrigin; +class InspectorFileSystemAgent FINAL : public InspectorBaseAgent<InspectorFileSystemAgent>, public InspectorBackendDispatcher::FileSystemCommandHandler { public: - static PassRefPtr<WebKitNotification> create(const String& title, const String& body, const String& iconUrl, ExecutionContext*, ExceptionState&, PassRefPtr<NotificationCenter> provider); - - virtual ~WebKitNotification(); + static PassOwnPtr<InspectorFileSystemAgent> create(Page*); + virtual ~InspectorFileSystemAgent(); - void cancel() { close(); } + virtual void enable(ErrorString*) OVERRIDE; + virtual void disable(ErrorString*) OVERRIDE; - DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(display, show); + virtual void requestFileSystemRoot(ErrorString*, const String& origin, const String& typeString, PassRefPtr<RequestFileSystemRootCallback>) OVERRIDE; + virtual void requestDirectoryContent(ErrorString*, const String& url, PassRefPtr<RequestDirectoryContentCallback>) OVERRIDE; + virtual void requestMetadata(ErrorString*, const String& url, PassRefPtr<RequestMetadataCallback>) OVERRIDE; + virtual void requestFileContent(ErrorString*, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtr<RequestFileContentCallback>) OVERRIDE; + virtual void deleteEntry(ErrorString*, const String& url, PassRefPtr<DeleteEntryCallback>) OVERRIDE; - String replaceId() const { return tag(); } - void setReplaceId(const String& replaceId) { setTag(replaceId); } - - // EventTarget interface - virtual const AtomicString& interfaceName() const OVERRIDE; + virtual void clearFrontend() OVERRIDE; + virtual void restore() OVERRIDE; private: - WebKitNotification(const String& title, const String& body, const String& iconUrl, ExecutionContext*, ExceptionState&, PassRefPtr<NotificationCenter> provider); + InspectorFileSystemAgent(Page*); + bool assertEnabled(ErrorString*); + ExecutionContext* assertExecutionContextForOrigin(ErrorString*, SecurityOrigin*); + + Page* m_page; + bool m_enabled; }; } // namespace WebCore -#endif // ENABLE(LEGACY_NOTIFICATIONS) - -#endif // WebKitNotification_h +#endif // InspectorFileSystemAgent_h diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.cpp new file mode 100644 index 00000000000..8c7c8ee5596 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.cpp @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/filesystem/InspectorFrontendHostFileSystem.h" + +#include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" +#include "core/inspector/InspectorFrontendHost.h" +#include "core/page/Page.h" +#include "modules/filesystem/DOMFileSystem.h" +#include "platform/JSONValues.h" + +namespace WebCore { + +DOMFileSystem* InspectorFrontendHostFileSystem::isolatedFileSystem(InspectorFrontendHost& host, const String& fileSystemName, const String& rootURL) +{ + ExecutionContext* context = host.frontendPage()->deprecatedLocalMainFrame()->document(); + return DOMFileSystem::create(context, fileSystemName, FileSystemTypeIsolated, KURL(ParsedURLString, rootURL)); +} + +void InspectorFrontendHostFileSystem::upgradeDraggedFileSystemPermissions(InspectorFrontendHost& host, DOMFileSystem* domFileSystem) +{ + RefPtr<JSONObject> message = JSONObject::create(); + message->setNumber("id", 0); + message->setString("method", "upgradeDraggedFileSystemPermissions"); + RefPtr<JSONArray> params = JSONArray::create(); + message->setArray("params", params); + params->pushString(domFileSystem->rootURL().string()); + host.sendMessageToEmbedder(message->toJSONString()); +} + +InspectorFrontendHostFileSystem::InspectorFrontendHostFileSystem() { } + +InspectorFrontendHostFileSystem::~InspectorFrontendHostFileSystem() { } + + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.h b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.h new file mode 100644 index 00000000000..7f593459765 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.h @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef InspectorFrontendHostFileSystem_h +#define InspectorFrontendHostFileSystem_h + +#include "platform/heap/Handle.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class DOMFileSystem; +class InspectorFrontendHost; + +class InspectorFrontendHostFileSystem { +public: + static DOMFileSystem* isolatedFileSystem(InspectorFrontendHost&, const String& fileSystemName, const String& rootURL); + static void upgradeDraggedFileSystemPermissions(InspectorFrontendHost&, DOMFileSystem*); +private: + InspectorFrontendHostFileSystem(); + ~InspectorFrontendHostFileSystem(); +}; + +} // namespace WebCore + +#endif // !defined(InspectorFrontendHostFileSystem_h) diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.idl b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.idl new file mode 100644 index 00000000000..d871faba210 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/filesystem/InspectorFrontendHostFileSystem.idl @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=FileSystem, +] partial interface InspectorFrontendHost { + DOMFileSystem isolatedFileSystem(DOMString fileSystemId, DOMString registeredName); + void upgradeDraggedFileSystemPermissions(DOMFileSystem domFileSystem); +}; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp index ab73471c492..ec2820833a8 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp @@ -36,11 +36,15 @@ #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" #include "core/fileapi/FileError.h" +#include "core/frame/LocalFrame.h" #include "core/workers/WorkerGlobalScope.h" #include "modules/filesystem/FileSystemClient.h" #include "platform/AsyncFileSystemCallbacks.h" +#include "platform/PermissionCallbacks.h" #include "public/platform/Platform.h" #include "public/platform/WebFileSystem.h" +#include "wtf/Functional.h" +#include "wtf/RefCounted.h" namespace WebCore { @@ -53,9 +57,25 @@ void fileSystemNotAllowed(ExecutionContext*, PassOwnPtr<AsyncFileSystemCallbacks } // namespace -PassOwnPtr<LocalFileSystem> LocalFileSystem::create(PassOwnPtr<FileSystemClient> client) +class CallbackWrapper : public RefCounted<CallbackWrapper> { +public: + CallbackWrapper(PassOwnPtr<AsyncFileSystemCallbacks> c) + : m_callbacks(c) + { + } + virtual ~CallbackWrapper() { } + PassOwnPtr<AsyncFileSystemCallbacks> release() + { + return m_callbacks.release(); + } + +private: + OwnPtr<AsyncFileSystemCallbacks> m_callbacks; +}; + +PassOwnPtrWillBeRawPtr<LocalFileSystem> LocalFileSystem::create(PassOwnPtr<FileSystemClient> client) { - return adoptPtr(new LocalFileSystem(client)); + return adoptPtrWillBeNoop(new LocalFileSystem(client)); } LocalFileSystem::~LocalFileSystem() @@ -64,34 +84,80 @@ LocalFileSystem::~LocalFileSystem() void LocalFileSystem::resolveURL(ExecutionContext* context, const KURL& fileSystemURL, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) { - if (!client() || !client()->allowFileSystem(context)) { - context->postTask(createCallbackTask(&fileSystemNotAllowed, callbacks)); - return; - } - blink::Platform::current()->fileSystem()->resolveURL(fileSystemURL, callbacks); + RefPtr<CallbackWrapper> wrapper = adoptRef(new CallbackWrapper(callbacks)); + requestFileSystemAccessInternal(context, + bind(&LocalFileSystem::resolveURLInternal, this, fileSystemURL, wrapper), + bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, PassRefPtrWillBeRawPtr<ExecutionContext>(context), wrapper)); } void LocalFileSystem::requestFileSystem(ExecutionContext* context, FileSystemType type, long long size, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) { - if (!client() || !client()->allowFileSystem(context)) { - context->postTask(createCallbackTask(&fileSystemNotAllowed, callbacks)); - return; - } - KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString()); - blink::Platform::current()->fileSystem()->openFileSystem(storagePartition, static_cast<blink::WebFileSystemType>(type), callbacks); + RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context); + RefPtr<CallbackWrapper> wrapper = adoptRef(new CallbackWrapper(callbacks)); + requestFileSystemAccessInternal(context, + bind(&LocalFileSystem::fileSystemAllowedInternal, this, contextPtr, type, wrapper), + bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper)); } void LocalFileSystem::deleteFileSystem(ExecutionContext* context, FileSystemType type, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) { + RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context); ASSERT(context); ASSERT_WITH_SECURITY_IMPLICATION(context->isDocument()); - if (!client() || !client()->allowFileSystem(context)) { - context->postTask(createCallbackTask(&fileSystemNotAllowed, callbacks)); + RefPtr<CallbackWrapper> wrapper = adoptRef(new CallbackWrapper(callbacks)); + requestFileSystemAccessInternal(context, + bind(&LocalFileSystem::deleteFileSystemInternal, this, contextPtr, type, wrapper), + bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper)); +} + +void LocalFileSystem::requestFileSystemAccessInternal(ExecutionContext* context, const Closure& allowed, const Closure& denied) +{ + if (!client()) { + denied(); + return; + } + if (!context->isDocument()) { + if (!client()->requestFileSystemAccessSync(context)) { + denied(); + return; + } + allowed(); return; } + client()->requestFileSystemAccessAsync(context, PermissionCallbacks::create(allowed, denied)); +} + +void LocalFileSystem::fileSystemNotAllowedInternal( + PassRefPtrWillBeRawPtr<ExecutionContext> context, + PassRefPtr<CallbackWrapper> callbacks) +{ + context->postTask(createCallbackTask(&fileSystemNotAllowed, callbacks->release())); +} + +void LocalFileSystem::fileSystemAllowedInternal( + PassRefPtrWillBeRawPtr<ExecutionContext> context, + FileSystemType type, + PassRefPtr<CallbackWrapper> callbacks) +{ + KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString()); + blink::Platform::current()->fileSystem()->openFileSystem(storagePartition, static_cast<blink::WebFileSystemType>(type), callbacks->release()); +} + +void LocalFileSystem::resolveURLInternal( + const KURL& fileSystemURL, + PassRefPtr<CallbackWrapper> callbacks) +{ + blink::Platform::current()->fileSystem()->resolveURL(fileSystemURL, callbacks->release()); +} + +void LocalFileSystem::deleteFileSystemInternal( + PassRefPtrWillBeRawPtr<ExecutionContext> context, + FileSystemType type, + PassRefPtr<CallbackWrapper> callbacks) +{ KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString()); - blink::Platform::current()->fileSystem()->deleteFileSystem(storagePartition, static_cast<blink::WebFileSystemType>(type), callbacks); + blink::Platform::current()->fileSystem()->deleteFileSystem(storagePartition, static_cast<blink::WebFileSystemType>(type), callbacks->release()); } LocalFileSystem::LocalFileSystem(PassOwnPtr<FileSystemClient> client) @@ -104,18 +170,18 @@ const char* LocalFileSystem::supplementName() return "LocalFileSystem"; } -LocalFileSystem* LocalFileSystem::from(ExecutionContext* context) +LocalFileSystem* LocalFileSystem::from(ExecutionContext& context) { - if (context->isDocument()) { - return static_cast<LocalFileSystem*>(Supplement<Page>::from(toDocument(context)->page(), supplementName())); + if (context.isDocument()) { + return static_cast<LocalFileSystem*>(WillBeHeapSupplement<LocalFrame>::from(toDocument(context).frame(), supplementName())); } - ASSERT(context->isWorkerGlobalScope()); - return static_cast<LocalFileSystem*>(Supplement<WorkerClients>::from(toWorkerGlobalScope(context)->clients(), supplementName())); + ASSERT(context.isWorkerGlobalScope()); + return static_cast<LocalFileSystem*>(WillBeHeapSupplement<WorkerClients>::from(toWorkerGlobalScope(context).clients(), supplementName())); } -void provideLocalFileSystemTo(Page* page, PassOwnPtr<FileSystemClient> client) +void provideLocalFileSystemTo(LocalFrame& frame, PassOwnPtr<FileSystemClient> client) { - page->provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client)); + frame.provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client)); } void provideLocalFileSystemToWorker(WorkerClients* clients, PassOwnPtr<FileSystemClient> client) diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h b/chromium/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h index ecc11fa1a2f..93125da76de 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h @@ -31,21 +31,25 @@ #ifndef LocalFileSystem_h #define LocalFileSystem_h -#include "core/page/Page.h" #include "core/workers/WorkerClients.h" #include "platform/FileSystemType.h" #include "wtf/Forward.h" +#include "wtf/Functional.h" namespace WebCore { class AsyncFileSystemCallbacks; +class CallbackWrapper; class FileSystemClient; class ExecutionContext; +class KURL; +class LocalFrame; -class LocalFileSystem : public Supplement<Page>, public Supplement<WorkerClients> { +class LocalFileSystem FINAL : public NoBaseWillBeGarbageCollectedFinalized<LocalFileSystem>, public WillBeHeapSupplement<LocalFrame>, public WillBeHeapSupplement<WorkerClients> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(LocalFileSystem); WTF_MAKE_NONCOPYABLE(LocalFileSystem); public: - static PassOwnPtr<LocalFileSystem> create(PassOwnPtr<FileSystemClient>); + static PassOwnPtrWillBeRawPtr<LocalFileSystem> create(PassOwnPtr<FileSystemClient>); virtual ~LocalFileSystem(); void resolveURL(ExecutionContext*, const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); @@ -55,11 +59,23 @@ public: FileSystemClient* client() { return m_client.get(); } static const char* supplementName(); - static LocalFileSystem* from(ExecutionContext*); + static LocalFileSystem* from(ExecutionContext&); + + virtual void trace(Visitor* visitor) OVERRIDE + { + WillBeHeapSupplement<LocalFrame>::trace(visitor); + WillBeHeapSupplement<WorkerClients>::trace(visitor); + } protected: explicit LocalFileSystem(PassOwnPtr<FileSystemClient>); +private: + void requestFileSystemAccessInternal(ExecutionContext*, const Closure& allowed, const Closure& denied); + void fileSystemNotAllowedInternal(PassRefPtrWillBeRawPtr<ExecutionContext>, PassRefPtr<CallbackWrapper>); + void fileSystemAllowedInternal(PassRefPtrWillBeRawPtr<ExecutionContext>, FileSystemType, PassRefPtr<CallbackWrapper>); + void resolveURLInternal(const KURL&, PassRefPtr<CallbackWrapper>); + void deleteFileSystemInternal(PassRefPtrWillBeRawPtr<ExecutionContext>, FileSystemType, PassRefPtr<CallbackWrapper>); OwnPtr<FileSystemClient> m_client; }; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/Metadata.h b/chromium/third_party/WebKit/Source/modules/filesystem/Metadata.h index d4681ed9b9b..683793c6aae 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/Metadata.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/Metadata.h @@ -33,26 +33,28 @@ #include "bindings/v8/ScriptWrappable.h" #include "platform/FileMetadata.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" namespace WebCore { -class Metadata : public RefCounted<Metadata>, public ScriptWrappable { +class Metadata : public GarbageCollectedFinalized<Metadata>, public ScriptWrappable { public: - static PassRefPtr<Metadata> create(const FileMetadata& platformMetadata) + static Metadata* create(const FileMetadata& platformMetadata) { - return adoptRef(new Metadata(platformMetadata)); + return new Metadata(platformMetadata); } - static PassRefPtr<Metadata> create(Metadata* metadata) + static Metadata* create(Metadata* metadata) { - return adoptRef(new Metadata(metadata->m_platformMetadata)); + return new Metadata(metadata->m_platformMetadata); } // Needs to return epoch time in milliseconds for Date while FileMetadata's modificationTime is in seconds. double modificationTime() const { return m_platformMetadata.modificationTime * 1000.0; } unsigned long long size() const { return static_cast<unsigned long long>(m_platformMetadata.length); } + void trace(Visitor*) { } + private: explicit Metadata(const FileMetadata& platformMetadata) : m_platformMetadata(platformMetadata) diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/Metadata.idl b/chromium/third_party/WebKit/Source/modules/filesystem/Metadata.idl index ee77c0ce2dd..5e556fe0ce5 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/Metadata.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/Metadata.idl @@ -29,7 +29,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + GarbageCollected, ] interface Metadata { readonly attribute Date modificationTime; readonly attribute unsigned long long size; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/OWNERS b/chromium/third_party/WebKit/Source/modules/filesystem/OWNERS index 4b079f8448c..6cff4023bfe 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/filesystem/OWNERS @@ -1,3 +1,5 @@ ericu@chromium.org kinuko@chromium.org michaeln@chromium.org +nhiroki@chromium.org +tzik@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/SyncCallbackHelper.h b/chromium/third_party/WebKit/Source/modules/filesystem/SyncCallbackHelper.h index ad39e1c636c..76b8ae31951 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/SyncCallbackHelper.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/SyncCallbackHelper.h @@ -36,7 +36,6 @@ #include "core/fileapi/FileError.h" #include "core/html/VoidCallback.h" #include "modules/filesystem/DirectoryEntry.h" -#include "modules/filesystem/DirectoryReaderSync.h" #include "modules/filesystem/EntriesCallback.h" #include "modules/filesystem/EntryCallback.h" #include "modules/filesystem/EntrySync.h" @@ -44,6 +43,7 @@ #include "modules/filesystem/FileEntry.h" #include "modules/filesystem/FileSystemCallback.h" #include "modules/filesystem/MetadataCallback.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -51,8 +51,10 @@ namespace WebCore { template <typename ResultType, typename CallbackArg> struct HelperResultType { - typedef PassRefPtr<ResultType> ReturnType; - typedef RefPtr<ResultType> StorageType; + DISALLOW_ALLOCATION(); +public: + typedef ResultType* ReturnType; + typedef Persistent<ResultType> StorageType; static ReturnType createFromCallbackArg(CallbackArg argument) { @@ -60,36 +62,18 @@ struct HelperResultType { } }; -template <> -struct HelperResultType<EntrySyncVector, const EntryVector&> { - typedef EntrySyncVector ReturnType; - typedef EntrySyncVector StorageType; - - static EntrySyncVector createFromCallbackArg(const EntryVector& entries) - { - EntrySyncVector result; - size_t entryCount = entries.size(); - result.reserveInitialCapacity(entryCount); - for (size_t i = 0; i < entryCount; ++i) - result.uncheckedAppend(EntrySync::create(entries[i].get())); - return result; - } -}; - // A helper template for FileSystemSync implementation. template <typename SuccessCallback, typename CallbackArg, typename ResultType> -class SyncCallbackHelper { - WTF_MAKE_NONCOPYABLE(SyncCallbackHelper); +class SyncCallbackHelper FINAL : public RefCounted<SyncCallbackHelper<SuccessCallback, CallbackArg, ResultType> > { public: typedef SyncCallbackHelper<SuccessCallback, CallbackArg, ResultType> HelperType; typedef HelperResultType<ResultType, CallbackArg> ResultTypeTrait; typedef typename ResultTypeTrait::StorageType ResultStorageType; typedef typename ResultTypeTrait::ReturnType ResultReturnType; - SyncCallbackHelper() - : m_errorCode(FileError::OK) - , m_completed(false) + static PassRefPtr<HelperType> create() { + return adoptRef(new SyncCallbackHelper()); } ResultReturnType getResult(ExceptionState& exceptionState) @@ -104,9 +88,15 @@ public: PassOwnPtr<ErrorCallback> errorCallback() { return ErrorCallbackImpl::create(this); } private: - class SuccessCallbackImpl : public SuccessCallback { + SyncCallbackHelper() + : m_errorCode(FileError::OK) + , m_completed(false) + { + } + + class SuccessCallbackImpl FINAL : public SuccessCallback { public: - static PassOwnPtr<SuccessCallbackImpl> create(HelperType* helper) + static PassOwnPtr<SuccessCallbackImpl> create(PassRefPtr<HelperType> helper) { return adoptPtr(new SuccessCallbackImpl(helper)); } @@ -122,32 +112,32 @@ private: } private: - explicit SuccessCallbackImpl(HelperType* helper) + explicit SuccessCallbackImpl(PassRefPtr<HelperType> helper) : m_helper(helper) { } - HelperType* m_helper; + RefPtr<HelperType> m_helper; }; - class ErrorCallbackImpl : public ErrorCallback { + class ErrorCallbackImpl FINAL : public ErrorCallback { public: - static PassOwnPtr<ErrorCallbackImpl> create(HelperType* helper) + static PassOwnPtr<ErrorCallbackImpl> create(PassRefPtr<HelperType> helper) { return adoptPtr(new ErrorCallbackImpl(helper)); } - virtual void handleEvent(FileError* error) + virtual void handleEvent(FileError* error) OVERRIDE { ASSERT(error); m_helper->setError(error->code()); } private: - explicit ErrorCallbackImpl(HelperType* helper) + explicit ErrorCallbackImpl(PassRefPtr<HelperType> helper) : m_helper(helper) { } - HelperType* m_helper; + RefPtr<HelperType> m_helper; }; void setError(FileError::ErrorCode code) @@ -167,15 +157,16 @@ private: bool m_completed; }; -struct EmptyType : public RefCounted<EmptyType> { - static PassRefPtr<EmptyType> create(EmptyType*) +struct EmptyType : public GarbageCollected<EmptyType> { + static EmptyType* create(EmptyType*) { return 0; } + + void trace(Visitor*) { } }; typedef SyncCallbackHelper<EntryCallback, Entry*, EntrySync> EntrySyncCallbackHelper; -typedef SyncCallbackHelper<EntriesCallback, const EntryVector&, EntrySyncVector> EntriesSyncCallbackHelper; typedef SyncCallbackHelper<MetadataCallback, Metadata*, Metadata> MetadataSyncCallbackHelper; typedef SyncCallbackHelper<VoidCallback, EmptyType*, EmptyType> VoidSyncCallbackHelper; typedef SyncCallbackHelper<FileSystemCallback, DOMFileSystem*, DOMFileSystemSync> FileSystemSyncCallbackHelper; diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/WindowFileSystem.idl b/chromium/third_party/WebKit/Source/modules/filesystem/WindowFileSystem.idl index dcbe807f838..b35cc8ad495 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/WindowFileSystem.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/WindowFileSystem.idl @@ -25,7 +25,7 @@ */ [ - ImplementedAs=DOMWindowFileSystem + ImplementedAs=DOMWindowFileSystem, ] partial interface Window { const unsigned short TEMPORARY = 0; const unsigned short PERSISTENT = 1; @@ -35,4 +35,3 @@ [RuntimeEnabled=FileSystem] void webkitResolveLocalFileSystemURL(DOMString url, EntryCallback successCallback, optional ErrorCallback errorCallback); }; - diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.cpp index 0bfc69c07a1..e2b097c33cb 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.cpp +++ b/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.cpp @@ -45,26 +45,26 @@ namespace WebCore { -void WorkerGlobalScopeFileSystem::webkitRequestFileSystem(WorkerGlobalScope* worker, int type, long long size, PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) +void WorkerGlobalScopeFileSystem::webkitRequestFileSystem(WorkerGlobalScope& worker, int type, long long size, PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) { - ExecutionContext* secureContext = worker->executionContext(); + ExecutionContext* secureContext = worker.executionContext(); if (!secureContext->securityOrigin()->canAccessFileSystem()) { - DOMFileSystem::scheduleCallback(worker, errorCallback, FileError::create(FileError::SECURITY_ERR)); + DOMFileSystem::scheduleCallback(&worker, errorCallback, FileError::create(FileError::SECURITY_ERR)); return; } FileSystemType fileSystemType = static_cast<FileSystemType>(type); if (!DOMFileSystemBase::isValidType(fileSystemType)) { - DOMFileSystem::scheduleCallback(worker, errorCallback, FileError::create(FileError::INVALID_MODIFICATION_ERR)); + DOMFileSystem::scheduleCallback(&worker, errorCallback, FileError::create(FileError::INVALID_MODIFICATION_ERR)); return; } - LocalFileSystem::from(worker)->requestFileSystem(worker, fileSystemType, size, FileSystemCallbacks::create(successCallback, errorCallback, worker, fileSystemType)); + LocalFileSystem::from(worker)->requestFileSystem(&worker, fileSystemType, size, FileSystemCallbacks::create(successCallback, errorCallback, &worker, fileSystemType)); } -PassRefPtr<DOMFileSystemSync> WorkerGlobalScopeFileSystem::webkitRequestFileSystemSync(WorkerGlobalScope* worker, int type, long long size, ExceptionState& exceptionState) +DOMFileSystemSync* WorkerGlobalScopeFileSystem::webkitRequestFileSystemSync(WorkerGlobalScope& worker, int type, long long size, ExceptionState& exceptionState) { - ExecutionContext* secureContext = worker->executionContext(); + ExecutionContext* secureContext = worker.executionContext(); if (!secureContext->securityOrigin()->canAccessFileSystem()) { exceptionState.throwSecurityError(FileError::securityErrorMessage); return 0; @@ -76,35 +76,35 @@ PassRefPtr<DOMFileSystemSync> WorkerGlobalScopeFileSystem::webkitRequestFileSyst return 0; } - FileSystemSyncCallbackHelper helper; - OwnPtr<AsyncFileSystemCallbacks> callbacks = FileSystemCallbacks::create(helper.successCallback(), helper.errorCallback(), worker, fileSystemType); + RefPtr<FileSystemSyncCallbackHelper> helper = FileSystemSyncCallbackHelper::create(); + OwnPtr<AsyncFileSystemCallbacks> callbacks = FileSystemCallbacks::create(helper->successCallback(), helper->errorCallback(), &worker, fileSystemType); callbacks->setShouldBlockUntilCompletion(true); - LocalFileSystem::from(worker)->requestFileSystem(worker, fileSystemType, size, callbacks.release()); - return helper.getResult(exceptionState); + LocalFileSystem::from(worker)->requestFileSystem(&worker, fileSystemType, size, callbacks.release()); + return helper->getResult(exceptionState); } -void WorkerGlobalScopeFileSystem::webkitResolveLocalFileSystemURL(WorkerGlobalScope* worker, const String& url, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) +void WorkerGlobalScopeFileSystem::webkitResolveLocalFileSystemURL(WorkerGlobalScope& worker, const String& url, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback> errorCallback) { - KURL completedURL = worker->completeURL(url); - ExecutionContext* secureContext = worker->executionContext(); + KURL completedURL = worker.completeURL(url); + ExecutionContext* secureContext = worker.executionContext(); if (!secureContext->securityOrigin()->canAccessFileSystem() || !secureContext->securityOrigin()->canRequest(completedURL)) { - DOMFileSystem::scheduleCallback(worker, errorCallback, FileError::create(FileError::SECURITY_ERR)); + DOMFileSystem::scheduleCallback(&worker, errorCallback, FileError::create(FileError::SECURITY_ERR)); return; } if (!completedURL.isValid()) { - DOMFileSystem::scheduleCallback(worker, errorCallback, FileError::create(FileError::ENCODING_ERR)); + DOMFileSystem::scheduleCallback(&worker, errorCallback, FileError::create(FileError::ENCODING_ERR)); return; } - LocalFileSystem::from(worker)->resolveURL(worker, completedURL, ResolveURICallbacks::create(successCallback, errorCallback, worker)); + LocalFileSystem::from(worker)->resolveURL(&worker, completedURL, ResolveURICallbacks::create(successCallback, errorCallback, &worker)); } -PassRefPtr<EntrySync> WorkerGlobalScopeFileSystem::webkitResolveLocalFileSystemSyncURL(WorkerGlobalScope* worker, const String& url, ExceptionState& exceptionState) +EntrySync* WorkerGlobalScopeFileSystem::webkitResolveLocalFileSystemSyncURL(WorkerGlobalScope& worker, const String& url, ExceptionState& exceptionState) { - KURL completedURL = worker->completeURL(url); - ExecutionContext* secureContext = worker->executionContext(); + KURL completedURL = worker.completeURL(url); + ExecutionContext* secureContext = worker.executionContext(); if (!secureContext->securityOrigin()->canAccessFileSystem() || !secureContext->securityOrigin()->canRequest(completedURL)) { exceptionState.throwSecurityError(FileError::securityErrorMessage); return 0; @@ -115,16 +115,13 @@ PassRefPtr<EntrySync> WorkerGlobalScopeFileSystem::webkitResolveLocalFileSystemS return 0; } - EntrySyncCallbackHelper resolveURLHelper; - OwnPtr<AsyncFileSystemCallbacks> callbacks = ResolveURICallbacks::create(resolveURLHelper.successCallback(), resolveURLHelper.errorCallback(), worker); + RefPtr<EntrySyncCallbackHelper> resolveURLHelper = EntrySyncCallbackHelper::create(); + OwnPtr<AsyncFileSystemCallbacks> callbacks = ResolveURICallbacks::create(resolveURLHelper->successCallback(), resolveURLHelper->errorCallback(), &worker); callbacks->setShouldBlockUntilCompletion(true); - LocalFileSystem::from(worker)->resolveURL(worker, completedURL, callbacks.release()); + LocalFileSystem::from(worker)->resolveURL(&worker, completedURL, callbacks.release()); - RefPtr<EntrySync> entry = resolveURLHelper.getResult(exceptionState); - if (!entry) - return 0; - return entry.release(); + return resolveURLHelper->getResult(exceptionState); } COMPILE_ASSERT(static_cast<int>(WorkerGlobalScopeFileSystem::TEMPORARY) == static_cast<int>(FileSystemTypeTemporary), enum_mismatch); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.h b/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.h index ee8e38ffa82..a2fa8deced0 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.h +++ b/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.h @@ -28,7 +28,7 @@ #define WorkerGlobalScopeFileSystem_h #include "modules/filesystem/DOMFileSystemSync.h" -#include "wtf/PassRefPtr.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -46,10 +46,10 @@ public: PERSISTENT, }; - static void webkitRequestFileSystem(WorkerGlobalScope*, int type, long long size, PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback>); - static PassRefPtr<DOMFileSystemSync> webkitRequestFileSystemSync(WorkerGlobalScope*, int type, long long size, ExceptionState&); - static void webkitResolveLocalFileSystemURL(WorkerGlobalScope*, const String& url, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback>); - static PassRefPtr<EntrySync> webkitResolveLocalFileSystemSyncURL(WorkerGlobalScope*, const String& url, ExceptionState&); + static void webkitRequestFileSystem(WorkerGlobalScope&, int type, long long size, PassOwnPtr<FileSystemCallback> successCallback, PassOwnPtr<ErrorCallback>); + static DOMFileSystemSync* webkitRequestFileSystemSync(WorkerGlobalScope&, int type, long long size, ExceptionState&); + static void webkitResolveLocalFileSystemURL(WorkerGlobalScope&, const String& url, PassOwnPtr<EntryCallback> successCallback, PassOwnPtr<ErrorCallback>); + static EntrySync* webkitResolveLocalFileSystemSyncURL(WorkerGlobalScope&, const String& url, ExceptionState&); private: WorkerGlobalScopeFileSystem(); diff --git a/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.idl b/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.idl index 3762bc5067f..1e13f7f83d4 100644 --- a/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.idl +++ b/chromium/third_party/WebKit/Source/modules/filesystem/WorkerGlobalScopeFileSystem.idl @@ -35,4 +35,3 @@ partial interface WorkerGlobalScope { [RuntimeEnabled=FileSystem] attribute FileErrorConstructor FileError; }; - diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.cpp index a83ec8a59cc..f2950ec5566 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.cpp +++ b/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.cpp @@ -29,28 +29,30 @@ namespace WebCore { Gamepad::Gamepad() - : m_index(0) - , m_timestamp(0) { ScriptWrappable::init(this); } -void Gamepad::axes(unsigned count, float* data) +Gamepad::~Gamepad() { - m_axes.resize(count); - if (count) - std::copy(data, data + count, m_axes.begin()); } -void Gamepad::buttons(unsigned count, float* data) +void Gamepad::setButtons(unsigned count, const blink::WebGamepadButton* data) { - m_buttons.resize(count); - if (count) - std::copy(data, data + count, m_buttons.begin()); + if (m_buttons.size() != count) { + m_buttons.resize(count); + for (unsigned i = 0; i < count; ++i) + m_buttons[i] = GamepadButton::create(); + } + for (unsigned i = 0; i < count; ++i) { + m_buttons[i]->setValue(data[i].value); + m_buttons[i]->setPressed(data[i].pressed); + } } -Gamepad::~Gamepad() +void Gamepad::trace(Visitor* visitor) { + visitor->trace(m_buttons); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.h b/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.h index 067fb20cc35..c240668751e 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.h +++ b/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.h @@ -27,44 +27,30 @@ #define Gamepad_h #include "bindings/v8/ScriptWrappable.h" +#include "modules/gamepad/GamepadButton.h" +#include "modules/gamepad/GamepadCommon.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebGamepad.h" #include "wtf/RefCounted.h" -#include "wtf/Vector.h" -#include "wtf/text/WTFString.h" namespace WebCore { -class Gamepad: public RefCounted<Gamepad>, public ScriptWrappable { +class Gamepad FINAL : public GarbageCollectedFinalized<Gamepad>, public GamepadCommon, public ScriptWrappable { public: - static PassRefPtr<Gamepad> create() + static Gamepad* create() { - return adoptRef(new Gamepad); + return new Gamepad; } ~Gamepad(); - typedef Vector<float> FloatVector; + const GamepadButtonVector& buttons() const { return m_buttons; } + void setButtons(unsigned count, const blink::WebGamepadButton* data); - const String& id() const { return m_id; } - void id(const String& id) { m_id = id; } - - unsigned index() const { return m_index; } - void index(unsigned val) { m_index = val; } - - unsigned long long timestamp() const { return m_timestamp; } - void timestamp(unsigned long long val) { m_timestamp = val; } - - const FloatVector& axes() const { return m_axes; } - void axes(unsigned count, float* data); - - const FloatVector& buttons() const { return m_buttons; } - void buttons(unsigned count, float* data); + void trace(Visitor*); private: Gamepad(); - String m_id; - unsigned m_index; - unsigned long long m_timestamp; - FloatVector m_axes; - FloatVector m_buttons; + GamepadButtonVector m_buttons; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.idl b/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.idl index b2639293602..9459de1275d 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.idl +++ b/chromium/third_party/WebKit/Source/modules/gamepad/Gamepad.idl @@ -24,12 +24,13 @@ */ [ - NoInterfaceObject + GarbageCollected, ] interface Gamepad { readonly attribute DOMString id; readonly attribute unsigned long index; + readonly attribute boolean connected; readonly attribute unsigned long long timestamp; - readonly attribute float[] axes; - readonly attribute float[] buttons; + readonly attribute DOMString mapping; + readonly attribute double[] axes; + readonly attribute GamepadButton[] buttons; }; - diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.cpp new file mode 100644 index 00000000000..cb64dc9ca77 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.cpp @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/gamepad/Gamepad.h" + +namespace WebCore { + +GamepadButton* GamepadButton::create() +{ + return new GamepadButton(); +} + +GamepadButton::GamepadButton() + : m_value(0.) + , m_pressed(false) +{ + ScriptWrappable::init(this); +} + +GamepadButton::~GamepadButton() +{ +} + +void GamepadButton::trace(Visitor* visitor) +{ +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.h b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.h new file mode 100644 index 00000000000..422cf1df858 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GamepadButton_h +#define GamepadButton_h + +#include "bindings/v8/ScriptWrappable.h" +#include "platform/heap/Handle.h" +#include "wtf/RefCounted.h" +#include "wtf/Vector.h" + +namespace WebCore { + +class GamepadButton FINAL : public GarbageCollectedFinalized<GamepadButton>, public ScriptWrappable { +public: + static GamepadButton* create(); + ~GamepadButton(); + + double value() const { return m_value; } + void setValue(double val) { m_value = val; } + + bool pressed() const { return m_pressed; } + void setPressed(bool val) { m_pressed = val; } + + void trace(Visitor*); + +private: + GamepadButton(); + double m_value; + bool m_pressed; +}; + +typedef HeapVector<Member<GamepadButton> > GamepadButtonVector; + +} // namespace WebCore + +#endif // GamepadButton_h diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.idl b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.idl new file mode 100644 index 00000000000..19d88ce77cd --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadButton.idl @@ -0,0 +1,11 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, + GarbageCollected, +] interface GamepadButton { + readonly attribute boolean pressed; + readonly attribute double value; +}; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/PageGroupIndexedDatabase.h b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadCommon.cpp index 97d152a3482..f66d61f540d 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/PageGroupIndexedDatabase.h +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadCommon.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, Google Inc. All rights reserved. + * Copyright (C) 2011, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE @@ -23,30 +23,26 @@ * DAMAGE. */ -#ifndef PageGroupIndexedDatabase_h -#define PageGroupIndexedDatabase_h - -#include "platform/Supplementable.h" +#include "config.h" +#include "modules/gamepad/GamepadCommon.h" namespace WebCore { -class IDBFactoryBackendInterface; -class PageGroup; - -class PageGroupIndexedDatabase : public Supplement<PageGroup> { -public: - virtual ~PageGroupIndexedDatabase(); - static PageGroupIndexedDatabase* from(PageGroup&); +GamepadCommon::GamepadCommon() + : m_index(0) + , m_timestamp(0) +{ +} - IDBFactoryBackendInterface* factoryBackend(); +GamepadCommon::~GamepadCommon() +{ +} -private: - PageGroupIndexedDatabase(); - static const char* supplementName(); - - RefPtr<IDBFactoryBackendInterface> m_factoryBackend; -}; +void GamepadCommon::setAxes(unsigned count, const double* data) +{ + m_axes.resize(count); + if (count) + std::copy(data, data + count, m_axes.begin()); +} } // namespace WebCore - -#endif // PageGroupIndexedDatabase_h diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/PageGroupIndexedDatabase.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadCommon.h index 81c0be5e03d..9371a6a3568 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/PageGroupIndexedDatabase.cpp +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, Google Inc. All rights reserved. + * Copyright (C) 2011, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE @@ -23,44 +23,48 @@ * DAMAGE. */ -#include "config.h" -#include "modules/indexeddb/PageGroupIndexedDatabase.h" +#ifndef GamepadCommon_h +#define GamepadCommon_h -#include "core/page/PageGroup.h" -#include "modules/indexeddb/IDBFactoryBackendInterface.h" +#include "public/platform/WebGamepad.h" +#include "wtf/Vector.h" +#include "wtf/text/WTFString.h" namespace WebCore { -PageGroupIndexedDatabase::PageGroupIndexedDatabase() -{ -} +class GamepadCommon { +public: + GamepadCommon(); + ~GamepadCommon(); + typedef Vector<double> DoubleVector; -PageGroupIndexedDatabase::~PageGroupIndexedDatabase() -{ -} + const String& id() const { return m_id; } + void setId(const String& id) { m_id = id; } -const char* PageGroupIndexedDatabase::supplementName() -{ - return "PageGroupIndexedDatabase"; -} + unsigned index() const { return m_index; } + void setIndex(unsigned val) { m_index = val; } -PageGroupIndexedDatabase* PageGroupIndexedDatabase::from(PageGroup& group) -{ - PageGroupIndexedDatabase* supplement = static_cast<PageGroupIndexedDatabase*>(Supplement<PageGroup>::from(&group, supplementName())); - if (!supplement) { - supplement = new PageGroupIndexedDatabase(); - provideTo(&group, supplementName(), adoptPtr(supplement)); - } - return supplement; -} + bool connected() const { return m_connected; } + void setConnected(bool val) { m_connected = val; } -IDBFactoryBackendInterface* PageGroupIndexedDatabase::factoryBackend() -{ - // Do not add page setting based access control here since this object is shared by all pages in - // the group and having per-page controls is misleading. - if (!m_factoryBackend) - m_factoryBackend = IDBFactoryBackendInterface::create(); - return m_factoryBackend.get(); -} + unsigned long long timestamp() const { return m_timestamp; } + void setTimestamp(unsigned long long val) { m_timestamp = val; } + + const String& mapping() const { return m_mapping; } + void setMapping(const String& val) { m_mapping = val; } + + const DoubleVector& axes() const { return m_axes; } + void setAxes(unsigned count, const double* data); + +protected: + String m_id; + unsigned m_index; + bool m_connected; + unsigned long long m_timestamp; + String m_mapping; + DoubleVector m_axes; +}; } // namespace WebCore + +#endif // GamepadCommon_h diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.cpp new file mode 100644 index 00000000000..adef38d117f --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.cpp @@ -0,0 +1,63 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/gamepad/GamepadDispatcher.h" + +#include "modules/gamepad/NavigatorGamepad.h" +#include "public/platform/Platform.h" +#include "wtf/TemporaryChange.h" + +namespace WebCore { + +GamepadDispatcher& GamepadDispatcher::instance() +{ + DEFINE_STATIC_LOCAL(GamepadDispatcher, gamepadDispatcher, ()); + return gamepadDispatcher; +} + +void GamepadDispatcher::sampleGamepads(blink::WebGamepads& gamepads) +{ + blink::Platform::current()->sampleGamepads(gamepads); +} + +GamepadDispatcher::GamepadDispatcher() +{ +} + +GamepadDispatcher::~GamepadDispatcher() +{ +} + +void GamepadDispatcher::didConnectGamepad(unsigned index, const blink::WebGamepad& gamepad) +{ + dispatchDidConnectOrDisconnectGamepad(index, gamepad, true); +} + +void GamepadDispatcher::didDisconnectGamepad(unsigned index, const blink::WebGamepad& gamepad) +{ + dispatchDidConnectOrDisconnectGamepad(index, gamepad, false); +} + +void GamepadDispatcher::dispatchDidConnectOrDisconnectGamepad(unsigned index, const blink::WebGamepad& gamepad, bool connected) +{ + ASSERT(index < blink::WebGamepads::itemsLengthCap); + ASSERT(connected == gamepad.connected); + + m_latestChange.pad = gamepad; + m_latestChange.index = index; + notifyControllers(); +} + +void GamepadDispatcher::startListening() +{ + blink::Platform::current()->setGamepadListener(this); +} + +void GamepadDispatcher::stopListening() +{ + blink::Platform::current()->setGamepadListener(0); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.h b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.h new file mode 100644 index 00000000000..f86eeefd09a --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.h @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GamepadDispatcher_h +#define GamepadDispatcher_h + +#include "core/frame/DeviceEventDispatcherBase.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebGamepad.h" +#include "public/platform/WebGamepadListener.h" + +namespace blink { +class WebGamepads; +} + +namespace WebCore { + +class NavigatorGamepad; + +class GamepadDispatcher : public DeviceEventDispatcherBase, public blink::WebGamepadListener { +public: + static GamepadDispatcher& instance(); + + void sampleGamepads(blink::WebGamepads&); + + struct ConnectionChange { + blink::WebGamepad pad; + unsigned index; + }; + + const ConnectionChange& latestConnectionChange() const { return m_latestChange; } + +private: + GamepadDispatcher(); + virtual ~GamepadDispatcher(); + + // WebGamepadListener + virtual void didConnectGamepad(unsigned index, const blink::WebGamepad&) OVERRIDE; + virtual void didDisconnectGamepad(unsigned index, const blink::WebGamepad&) OVERRIDE; + + // DeviceEventDispatcherBase + virtual void startListening() OVERRIDE; + virtual void stopListening() OVERRIDE; + + void dispatchDidConnectOrDisconnectGamepad(unsigned index, const blink::WebGamepad&, bool connected); + + ConnectionChange m_latestChange; +}; + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.cpp new file mode 100644 index 00000000000..4893ead9cf0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.cpp @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/gamepad/GamepadEvent.h" + +namespace WebCore { + +GamepadEventInit::GamepadEventInit() +{ +} + +GamepadEvent::GamepadEvent() +{ + ScriptWrappable::init(this); +} + +GamepadEvent::GamepadEvent(const AtomicString& type, bool canBubble, bool cancelable, Gamepad* gamepad) + : Event(type, canBubble, cancelable) + , m_gamepad(gamepad) +{ + ScriptWrappable::init(this); +} + +GamepadEvent::GamepadEvent(const AtomicString& type, const GamepadEventInit& initializer) + : Event(type, initializer) + , m_gamepad(initializer.gamepad) +{ + ScriptWrappable::init(this); +} + +GamepadEvent::~GamepadEvent() +{ +} + +const AtomicString& GamepadEvent::interfaceName() const +{ + return EventNames::GamepadEvent; +} + +void GamepadEvent::trace(Visitor* visitor) +{ + visitor->trace(m_gamepad); + Event::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.h b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.h new file mode 100644 index 00000000000..c5502d633c9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.h @@ -0,0 +1,51 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GamepadEvent_h +#define GamepadEvent_h + +#include "modules/EventModules.h" +#include "modules/gamepad/Gamepad.h" + +namespace WebCore { + +struct GamepadEventInit : public EventInit { + GamepadEventInit(); + + Member<Gamepad> gamepad; +}; + +class GamepadEvent FINAL : public Event { +public: + static PassRefPtrWillBeRawPtr<GamepadEvent> create() + { + return adoptRefWillBeNoop(new GamepadEvent); + } + static PassRefPtrWillBeRawPtr<GamepadEvent> create(const AtomicString& type, bool canBubble, bool cancelable, Gamepad* gamepad) + { + return adoptRefWillBeNoop(new GamepadEvent(type, canBubble, cancelable, gamepad)); + } + static PassRefPtrWillBeRawPtr<GamepadEvent> create(const AtomicString& type, const GamepadEventInit& initializer) + { + return adoptRefWillBeNoop(new GamepadEvent(type, initializer)); + } + virtual ~GamepadEvent(); + + Gamepad* gamepad() const { return m_gamepad.get(); } + + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; + +private: + GamepadEvent(); + GamepadEvent(const AtomicString& type, bool canBubble, bool cancelable, Gamepad*); + GamepadEvent(const AtomicString&, const GamepadEventInit&); + + PersistentWillBeMember<Gamepad> m_gamepad; +}; + +} // namespace WebCore + +#endif // GamepadEvent_h diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.idl b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.idl new file mode 100644 index 00000000000..718226e2499 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadEvent.idl @@ -0,0 +1,9 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + EventConstructor, +] interface GamepadEvent : Event { + [InitializedByEventConstructor] readonly attribute Gamepad gamepad; +}; diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.cpp index 33f3027427a..0a956c35a0b 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.cpp +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.cpp @@ -26,28 +26,34 @@ #include "config.h" #include "modules/gamepad/GamepadList.h" - namespace WebCore { +GamepadList::GamepadList() +{ + ScriptWrappable::init(this); +} + GamepadList::~GamepadList() { } -void GamepadList::set(unsigned index, PassRefPtr<Gamepad> gamepad) +void GamepadList::set(unsigned index, Gamepad* gamepad) { - if (index >= kMaximumGamepads) + if (index >= blink::WebGamepads::itemsLengthCap) return; m_items[index] = gamepad; } -unsigned GamepadList::length() const +Gamepad* GamepadList::item(unsigned index) { - return kMaximumGamepads; + return index < length() ? m_items[index].get() : 0; } -Gamepad* GamepadList::item(unsigned index) +void GamepadList::trace(Visitor* visitor) { - return index < length() ? m_items[index].get() : 0; + for (unsigned index = 0; index < blink::WebGamepads::itemsLengthCap; index++) { + visitor->trace(m_items[index]); + } } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.h b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.h index 2f36298149f..ce07d8b3149 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.h +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.h @@ -28,31 +28,30 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/gamepad/Gamepad.h" -#include "wtf/PassRefPtr.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebGamepads.h" #include "wtf/RefCounted.h" #include "wtf/Vector.h" namespace WebCore { -typedef Vector<RefPtr<Gamepad> > GamepadVector; - -class GamepadList : public RefCounted<GamepadList>, public ScriptWrappable { +class GamepadList FINAL : public GarbageCollectedFinalized<GamepadList>, public ScriptWrappable { public: - static PassRefPtr<GamepadList> create() { return adoptRef(new GamepadList); } + static GamepadList* create() + { + return new GamepadList(); + } ~GamepadList(); - void set(unsigned index, PassRefPtr<Gamepad>); + void set(unsigned index, Gamepad*); Gamepad* item(unsigned index); - unsigned length() const; + unsigned length() const { return blink::WebGamepads::itemsLengthCap; } -private: - enum { kMaximumGamepads = 4 }; - GamepadList() - { - ScriptWrappable::init(this); - } + void trace(Visitor*); - RefPtr<Gamepad> m_items[kMaximumGamepads]; +private: + GamepadList(); + Member<Gamepad> m_items[blink::WebGamepads::itemsLengthCap]; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.idl b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.idl index 396c01357e3..03602d47420 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.idl +++ b/chromium/third_party/WebKit/Source/modules/gamepad/GamepadList.idl @@ -24,9 +24,9 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + GarbageCollected, ] interface GamepadList { readonly attribute unsigned long length; getter Gamepad item([Default=Undefined] optional unsigned long index); }; - diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp index f677c55d80e..0b39cea0a47 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp +++ b/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp @@ -26,30 +26,45 @@ #include "config.h" #include "modules/gamepad/NavigatorGamepad.h" +#include "core/dom/Document.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" +#include "core/page/Page.h" +#include "modules/gamepad/GamepadDispatcher.h" +#include "modules/gamepad/GamepadEvent.h" #include "modules/gamepad/GamepadList.h" -#include "public/platform/Platform.h" -#include "wtf/PassOwnPtr.h" +#include "modules/gamepad/WebKitGamepadList.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { -static void sampleGamepads(GamepadList* into) +template<typename T> +static void sampleGamepad(unsigned index, T& gamepad, const blink::WebGamepad& webGamepad) +{ + gamepad.setId(webGamepad.id); + gamepad.setIndex(index); + gamepad.setConnected(webGamepad.connected); + gamepad.setTimestamp(webGamepad.timestamp); + gamepad.setMapping(webGamepad.mapping); + gamepad.setAxes(webGamepad.axesLength, webGamepad.axes); + gamepad.setButtons(webGamepad.buttonsLength, webGamepad.buttons); +} + +template<typename GamepadType, typename ListType> +static void sampleGamepads(ListType* into) { blink::WebGamepads gamepads; - blink::Platform::current()->sampleGamepads(gamepads); + GamepadDispatcher::instance().sampleGamepads(gamepads); for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) { blink::WebGamepad& webGamepad = gamepads.items[i]; if (i < gamepads.length && webGamepad.connected) { - RefPtr<Gamepad> gamepad = into->item(i); + GamepadType* gamepad = into->item(i); if (!gamepad) - gamepad = Gamepad::create(); - gamepad->id(webGamepad.id); - gamepad->index(i); - gamepad->timestamp(webGamepad.timestamp); - gamepad->axes(webGamepad.axesLength, webGamepad.axes); - gamepad->buttons(webGamepad.buttonsLength, webGamepad.buttons); + gamepad = GamepadType::create(); + sampleGamepad(i, *gamepad, webGamepad); into->set(i, gamepad); } else { into->set(i, 0); @@ -57,40 +72,160 @@ static void sampleGamepads(GamepadList* into) } } -NavigatorGamepad::NavigatorGamepad() +NavigatorGamepad* NavigatorGamepad::from(Document& document) { + if (!document.frame() || !document.frame()->domWindow()) + return 0; + Navigator& navigator = document.frame()->domWindow()->navigator(); + return &from(navigator); } -NavigatorGamepad::~NavigatorGamepad() +NavigatorGamepad& NavigatorGamepad::from(Navigator& navigator) { + NavigatorGamepad* supplement = static_cast<NavigatorGamepad*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); + if (!supplement) { + supplement = new NavigatorGamepad(navigator.frame()); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; } -const char* NavigatorGamepad::supplementName() +WebKitGamepadList* NavigatorGamepad::webkitGetGamepads(Navigator& navigator) { - return "NavigatorGamepad"; + return NavigatorGamepad::from(navigator).webkitGamepads(); } -NavigatorGamepad* NavigatorGamepad::from(Navigator* navigator) +GamepadList* NavigatorGamepad::getGamepads(Navigator& navigator) { - NavigatorGamepad* supplement = static_cast<NavigatorGamepad*>(Supplement<Navigator>::from(navigator, supplementName())); - if (!supplement) { - supplement = new NavigatorGamepad(); - provideTo(navigator, supplementName(), adoptPtr(supplement)); - } - return supplement; + return NavigatorGamepad::from(navigator).gamepads(); } -GamepadList* NavigatorGamepad::webkitGetGamepads(Navigator* navigator) +WebKitGamepadList* NavigatorGamepad::webkitGamepads() { - return NavigatorGamepad::from(navigator)->gamepads(); + if (!m_webkitGamepads) + m_webkitGamepads = WebKitGamepadList::create(); + if (window()) { + startUpdating(); + sampleGamepads<WebKitGamepad>(m_webkitGamepads.get()); + } + return m_webkitGamepads.get(); } GamepadList* NavigatorGamepad::gamepads() { if (!m_gamepads) m_gamepads = GamepadList::create(); - sampleGamepads(m_gamepads.get()); + if (window()) { + startUpdating(); + sampleGamepads<Gamepad>(m_gamepads.get()); + } return m_gamepads.get(); } +void NavigatorGamepad::trace(Visitor* visitor) +{ + visitor->trace(m_gamepads); + visitor->trace(m_webkitGamepads); + WillBeHeapSupplement<Navigator>::trace(visitor); +} + +void NavigatorGamepad::didUpdateData() +{ + // We should stop listening once we detached. + ASSERT(window()); + + // We register to the dispatcher before sampling gamepads so we need to check if we actually have an event listener. + if (!m_hasEventListener) + return; + + if (window()->document()->activeDOMObjectsAreStopped() || window()->document()->activeDOMObjectsAreSuspended()) + return; + + const GamepadDispatcher::ConnectionChange& change = GamepadDispatcher::instance().latestConnectionChange(); + + if (!m_gamepads) + m_gamepads = GamepadList::create(); + + Gamepad* gamepad = m_gamepads->item(change.index); + if (!gamepad) + gamepad = Gamepad::create(); + sampleGamepad(change.index, *gamepad, change.pad); + m_gamepads->set(change.index, gamepad); + + const AtomicString& eventName = change.pad.connected ? EventTypeNames::gamepadconnected : EventTypeNames::gamepaddisconnected; + window()->dispatchEvent(GamepadEvent::create(eventName, false, true, gamepad)); +} + +NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) + : DOMWindowProperty(frame) + , DeviceEventControllerBase(frame ? frame->page() : 0) + , DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0) +{ +} + +NavigatorGamepad::~NavigatorGamepad() +{ +} + +const char* NavigatorGamepad::supplementName() +{ + return "NavigatorGamepad"; +} + +void NavigatorGamepad::willDestroyGlobalObjectInFrame() +{ + stopUpdating(); + DOMWindowProperty::willDestroyGlobalObjectInFrame(); +} + +void NavigatorGamepad::willDetachGlobalObjectFromFrame() +{ + stopUpdating(); + DOMWindowProperty::willDetachGlobalObjectFromFrame(); +} + +void NavigatorGamepad::registerWithDispatcher() +{ + GamepadDispatcher::instance().addController(this); +} + +void NavigatorGamepad::unregisterWithDispatcher() +{ + GamepadDispatcher::instance().removeController(this); +} + +bool NavigatorGamepad::hasLastData() +{ + // Gamepad data is polled instead of pushed. + return false; +} + +static bool isGamepadEvent(const AtomicString& eventType) +{ + return eventType == EventTypeNames::gamepadconnected || eventType == EventTypeNames::gamepaddisconnected; +} + +void NavigatorGamepad::didAddEventListener(LocalDOMWindow*, const AtomicString& eventType) +{ + if (RuntimeEnabledFeatures::gamepadEnabled() && isGamepadEvent(eventType)) { + if (page() && page()->visibilityState() == PageVisibilityStateVisible) + startUpdating(); + m_hasEventListener = true; + } +} + +void NavigatorGamepad::didRemoveEventListener(LocalDOMWindow* window, const AtomicString& eventType) +{ + if (isGamepadEvent(eventType) + && !window->hasEventListeners(EventTypeNames::gamepadconnected) + && !window->hasEventListeners(EventTypeNames::gamepaddisconnected)) { + m_hasEventListener = false; + } +} + +void NavigatorGamepad::didRemoveAllEventListeners(LocalDOMWindow*) +{ + m_hasEventListener = false; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h b/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h index d8eaf8d20c5..89df5d78a27 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h +++ b/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h @@ -26,27 +26,64 @@ #ifndef NavigatorGamepad_h #define NavigatorGamepad_h +#include "core/frame/DOMWindowLifecycleObserver.h" +#include "core/frame/DOMWindowProperty.h" +#include "core/frame/DeviceEventControllerBase.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebGamepads.h" + +namespace blink { +class WebGamepad; +class WebGamepads; +} namespace WebCore { +class Document; class GamepadList; class Navigator; +class WebKitGamepadList; -class NavigatorGamepad : public Supplement<Navigator> { +class NavigatorGamepad FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorGamepad>, public WillBeHeapSupplement<Navigator>, public DOMWindowProperty, public DeviceEventControllerBase, public DOMWindowLifecycleObserver { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorGamepad); public: + static NavigatorGamepad* from(Document&); + static NavigatorGamepad& from(Navigator&); virtual ~NavigatorGamepad(); - static NavigatorGamepad* from(Navigator*); - static GamepadList* webkitGetGamepads(Navigator*); + static WebKitGamepadList* webkitGetGamepads(Navigator&); + static GamepadList* getGamepads(Navigator&); + WebKitGamepadList* webkitGamepads(); GamepadList* gamepads(); + virtual void trace(Visitor*); + + void didConnectOrDisconnectGamepad(unsigned index, const blink::WebGamepad&, bool connected); + private: - NavigatorGamepad(); + explicit NavigatorGamepad(LocalFrame*); + static const char* supplementName(); - RefPtr<GamepadList> m_gamepads; + // DOMWindowProperty + virtual void willDestroyGlobalObjectInFrame() OVERRIDE; + virtual void willDetachGlobalObjectFromFrame() OVERRIDE; + + // DeviceEventControllerBase + virtual void registerWithDispatcher() OVERRIDE; + virtual void unregisterWithDispatcher() OVERRIDE; + virtual bool hasLastData() OVERRIDE; + virtual void didUpdateData() OVERRIDE; + + // DOMWindowLifecycleObserver + virtual void didAddEventListener(LocalDOMWindow*, const AtomicString&) OVERRIDE; + virtual void didRemoveEventListener(LocalDOMWindow*, const AtomicString&) OVERRIDE; + virtual void didRemoveAllEventListeners(LocalDOMWindow*) OVERRIDE; + + PersistentWillBeMember<GamepadList> m_gamepads; + PersistentWillBeMember<WebKitGamepadList> m_webkitGamepads; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.idl b/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.idl index 0fbceeea7cc..81b1f29ce33 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.idl +++ b/chromium/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.idl @@ -17,7 +17,9 @@ * Boston, MA 02110-1301, USA. */ -partial interface Navigator { - [RuntimeEnabled=Gamepad] GamepadList webkitGetGamepads(); +[ + RuntimeEnabled=Gamepad, +] partial interface Navigator { + [DeprecateAs=PrefixedGamepad] WebKitGamepadList webkitGetGamepads(); + GamepadList getGamepads(); }; - diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/OWNERS b/chromium/third_party/WebKit/Source/modules/gamepad/OWNERS index 3f809e82b19..4adf6277296 100644 --- a/chromium/third_party/WebKit/Source/modules/gamepad/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/gamepad/OWNERS @@ -1 +1,2 @@ -scottmg@chromium.org +b.kelemen@samsung.com +bajones@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.cpp new file mode 100644 index 00000000000..c83e6604e38 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.cpp @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/gamepad/WebKitGamepad.h" + +namespace WebCore { + +WebKitGamepad::WebKitGamepad() +{ + ScriptWrappable::init(this); +} + +WebKitGamepad::~WebKitGamepad() +{ +} + +void WebKitGamepad::setButtons(unsigned count, const blink::WebGamepadButton* data) +{ + m_buttons.resize(count); + for (unsigned i = 0; i < count; ++i) + m_buttons[i] = data[i].value; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.h b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.h new file mode 100644 index 00000000000..b52c9945a48 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebKitGamepad_h +#define WebKitGamepad_h + +#include "bindings/v8/ScriptWrappable.h" +#include "modules/gamepad/GamepadCommon.h" +#include "platform/heap/Handle.h" +#include "wtf/RefCounted.h" +#include "wtf/Vector.h" + +namespace WebCore { + +class WebKitGamepad FINAL : public GarbageCollectedFinalized<WebKitGamepad>, public GamepadCommon, public ScriptWrappable { +public: + static WebKitGamepad* create() + { + return new WebKitGamepad(); + } + ~WebKitGamepad(); + + typedef Vector<float> FloatVector; + + const FloatVector& buttons() const { return m_buttons; } + void setButtons(unsigned count, const blink::WebGamepadButton* data); + + void trace(Visitor*) { } + +private: + WebKitGamepad(); + FloatVector m_buttons; +}; + +} // namespace WebCore + +#endif // WebKitGamepad_h diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.idl b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.idl new file mode 100644 index 00000000000..d8d2cb2c7c1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepad.idl @@ -0,0 +1,15 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + GarbageCollected, +] interface WebKitGamepad { + readonly attribute DOMString id; + readonly attribute unsigned long index; + readonly attribute boolean connected; + readonly attribute unsigned long long timestamp; + readonly attribute DOMString mapping; + readonly attribute float[] axes; + readonly attribute float[] buttons; +}; diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.cpp b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.cpp new file mode 100644 index 00000000000..21a2a6fe0dc --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.cpp @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/gamepad/WebKitGamepadList.h" + +namespace WebCore { + +WebKitGamepadList::WebKitGamepadList() +{ + ScriptWrappable::init(this); +} + +WebKitGamepadList::~WebKitGamepadList() +{ +} + +void WebKitGamepadList::set(unsigned index, WebKitGamepad* gamepad) +{ + if (index >= blink::WebGamepads::itemsLengthCap) + return; + m_items[index] = gamepad; +} + +WebKitGamepad* WebKitGamepadList::item(unsigned index) +{ + return index < length() ? m_items[index].get() : 0; +} + +void WebKitGamepadList::trace(Visitor* visitor) +{ + for (unsigned index = 0; index < blink::WebGamepads::itemsLengthCap; index++) { + visitor->trace(m_items[index]); + } +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.h b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.h new file mode 100644 index 00000000000..06d37a6a04e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebKitGamepadList_h +#define WebKitGamepadList_h + +#include "bindings/v8/ScriptWrappable.h" +#include "modules/gamepad/WebKitGamepad.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebGamepads.h" +#include "wtf/RefCounted.h" +#include "wtf/Vector.h" + +namespace WebCore { + +class WebKitGamepadList FINAL : public GarbageCollectedFinalized<WebKitGamepadList>, public ScriptWrappable { +public: + static WebKitGamepadList* create() + { + return new WebKitGamepadList; + } + ~WebKitGamepadList(); + + void set(unsigned index, WebKitGamepad*); + WebKitGamepad* item(unsigned index); + unsigned length() const { return blink::WebGamepads::itemsLengthCap; } + + void trace(Visitor*); + +private: + WebKitGamepadList(); + Member<WebKitGamepad> m_items[blink::WebGamepads::itemsLengthCap]; +}; + +} // namespace WebCore + +#endif // WebKitGamepadList_h diff --git a/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.idl b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.idl new file mode 100644 index 00000000000..2b35c565c70 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/gamepad/WebKitGamepadList.idl @@ -0,0 +1,11 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, + GarbageCollected, +] interface WebKitGamepadList { + readonly attribute unsigned long length; + getter WebKitGamepad item([Default=Undefined] optional unsigned long index); +}; diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/Coordinates.h b/chromium/third_party/WebKit/Source/modules/geolocation/Coordinates.h index 82d37e671a8..8f6ed80bdad 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/Coordinates.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/Coordinates.h @@ -27,19 +27,18 @@ #define Coordinates_h #include "bindings/v8/ScriptWrappable.h" -#include "core/events/Event.h" -#include "wtf/RefCounted.h" +#include "modules/EventModules.h" +#include "platform/heap/Handle.h" namespace WebCore { -class Coordinates : public RefCounted<Coordinates>, public ScriptWrappable { +class Coordinates : public GarbageCollectedFinalized<Coordinates>, public ScriptWrappable { public: - static PassRefPtr<Coordinates> create(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { return adoptRef(new Coordinates(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed)); } - - PassRefPtr<Coordinates> isolatedCopy() const + static Coordinates* create(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { - return Coordinates::create(m_latitude, m_longitude, m_canProvideAltitude, m_altitude, m_accuracy, m_canProvideAltitudeAccuracy, m_altitudeAccuracy, m_canProvideHeading, m_heading, m_canProvideSpeed, m_speed); + return new Coordinates(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed); } + void trace(Visitor*) { } double latitude() const { return m_latitude; } double longitude() const { return m_longitude; } diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/Coordinates.idl b/chromium/third_party/WebKit/Source/modules/geolocation/Coordinates.idl index ed2b8bf6c37..9ff3e281787 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/Coordinates.idl +++ b/chromium/third_party/WebKit/Source/modules/geolocation/Coordinates.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject ] interface Coordinates { readonly attribute double latitude; diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp b/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp index 187a12a5a27..fd6675f6b52 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp +++ b/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp @@ -29,12 +29,11 @@ #include "modules/geolocation/Geolocation.h" #include "core/dom/Document.h" -#include "wtf/CurrentTime.h" - #include "modules/geolocation/Coordinates.h" #include "modules/geolocation/GeolocationController.h" #include "modules/geolocation/GeolocationError.h" #include "modules/geolocation/GeolocationPosition.h" +#include "wtf/CurrentTime.h" namespace WebCore { @@ -42,18 +41,27 @@ static const char permissionDeniedErrorMessage[] = "User denied Geolocation"; static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocation service"; static const char framelessDocumentErrorMessage[] = "Geolocation cannot be used in frameless documents"; -static PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position) +static Geoposition* createGeoposition(GeolocationPosition* position) { if (!position) - return 0; + return nullptr; - RefPtr<Coordinates> coordinates = Coordinates::create(position->latitude(), position->longitude(), position->canProvideAltitude(), position->altitude(), - position->accuracy(), position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(), - position->canProvideHeading(), position->heading(), position->canProvideSpeed(), position->speed()); - return Geoposition::create(coordinates.release(), convertSecondsToDOMTimeStamp(position->timestamp())); + Coordinates* coordinates = Coordinates::create( + position->latitude(), + position->longitude(), + position->canProvideAltitude(), + position->altitude(), + position->accuracy(), + position->canProvideAltitudeAccuracy(), + position->altitudeAccuracy(), + position->canProvideHeading(), + position->heading(), + position->canProvideSpeed(), + position->speed()); + return Geoposition::create(coordinates, convertSecondsToDOMTimeStamp(position->timestamp())); } -static PassRefPtr<PositionError> createPositionError(GeolocationError* error) +static PositionError* createPositionError(GeolocationError* error) { PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE; switch (error->code()) { @@ -68,7 +76,7 @@ static PassRefPtr<PositionError> createPositionError(GeolocationError* error) return PositionError::create(code, error->message()); } -Geolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassOwnPtr<PositionCallback> successCallback, PassOwnPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) +Geolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassOwnPtr<PositionCallback> successCallback, PassOwnPtr<PositionErrorCallback> errorCallback, PositionOptions* options) : m_geolocation(geolocation) , m_successCallback(successCallback) , m_errorCallback(errorCallback) @@ -83,7 +91,14 @@ Geolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassOwnPtr<Posit ASSERT(m_options); } -void Geolocation::GeoNotifier::setFatalError(PassRefPtr<PositionError> error) +void Geolocation::GeoNotifier::trace(Visitor* visitor) +{ + visitor->trace(m_geolocation); + visitor->trace(m_options); + visitor->trace(m_fatalError); +} + +void Geolocation::GeoNotifier::setFatalError(PositionError* error) { // If a fatal error has already been set, stick with it. This makes sure that // when permission is denied, this is the error reported, as required by the @@ -94,18 +109,13 @@ void Geolocation::GeoNotifier::setFatalError(PassRefPtr<PositionError> error) m_fatalError = error; // An existing timer may not have a zero timeout. m_timer.stop(); - m_timer.startOneShot(0); + m_timer.startOneShot(0, FROM_HERE); } void Geolocation::GeoNotifier::setUseCachedPosition() { m_useCachedPosition = true; - m_timer.startOneShot(0); -} - -bool Geolocation::GeoNotifier::hasZeroTimeout() const -{ - return m_options->hasTimeout() && m_options->timeout() == 0; + m_timer.startOneShot(0, FROM_HERE); } void Geolocation::GeoNotifier::runSuccessCallback(Geoposition* position) @@ -124,10 +134,9 @@ void Geolocation::GeoNotifier::runErrorCallback(PositionError* error) m_errorCallback->handleEvent(error); } -void Geolocation::GeoNotifier::startTimerIfNeeded() +void Geolocation::GeoNotifier::startTimer() { - if (m_options->hasTimeout()) - m_timer.startOneShot(m_options->timeout() / 1000.0); + m_timer.startOneShot(m_options->timeout() / 1000.0, FROM_HERE); } void Geolocation::GeoNotifier::stopTimer() @@ -139,11 +148,7 @@ void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*) { m_timer.stop(); - // Protect this GeoNotifier object, since it - // could be deleted by a call to clearWatch in a callback. - RefPtr<GeoNotifier> protect(this); - - // Test for fatal error first. This is required for the case where the Frame is + // Test for fatal error first. This is required for the case where the LocalFrame is // disconnected and requests are cancelled. if (m_fatalError) { runErrorCallback(m_fatalError.get()); @@ -160,21 +165,23 @@ void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*) return; } - if (m_errorCallback) { - RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, "Timeout expired"); - m_errorCallback->handleEvent(error.get()); - } + if (m_errorCallback) + m_errorCallback->handleEvent(PositionError::create(PositionError::TIMEOUT, "Timeout expired")); m_geolocation->requestTimedOut(this); } -bool Geolocation::Watchers::add(int id, PassRefPtr<GeoNotifier> prpNotifier) +void Geolocation::Watchers::trace(Visitor* visitor) { - ASSERT(id > 0); - RefPtr<GeoNotifier> notifier = prpNotifier; + visitor->trace(m_idToNotifierMap); + visitor->trace(m_notifierToIdMap); +} - if (!m_idToNotifierMap.add(id, notifier.get()).isNewEntry) +bool Geolocation::Watchers::add(int id, GeoNotifier* notifier) +{ + ASSERT(id > 0); + if (!m_idToNotifierMap.add(id, notifier).isNewEntry) return false; - m_notifierToIdMap.set(notifier.release(), id); + m_notifierToIdMap.set(notifier, id); return true; } @@ -227,11 +234,11 @@ void Geolocation::Watchers::getNotifiersVector(GeoNotifierVector& copy) const copyValuesToVector(m_idToNotifierMap, copy); } -PassRefPtr<Geolocation> Geolocation::create(ExecutionContext* context) +Geolocation* Geolocation::create(ExecutionContext* context) { - RefPtr<Geolocation> geolocation = adoptRef(new Geolocation(context)); + Geolocation* geolocation = new Geolocation(context); geolocation->suspendIfNeeded(); - return geolocation.release(); + return geolocation; } Geolocation::Geolocation(ExecutionContext* context) @@ -246,26 +253,30 @@ Geolocation::~Geolocation() ASSERT(m_allowGeolocation != InProgress); } -Document* Geolocation::document() const +void Geolocation::trace(Visitor* visitor) { - return toDocument(executionContext()); + visitor->trace(m_oneShots); + visitor->trace(m_watchers); + visitor->trace(m_pendingForPermissionNotifiers); + visitor->trace(m_lastPosition); + visitor->trace(m_requestsAwaitingCachedPosition); } -Frame* Geolocation::frame() const +Document* Geolocation::document() const { - return document() ? document()->frame() : 0; + return toDocument(executionContext()); } -Page* Geolocation::page() const +LocalFrame* Geolocation::frame() const { - return document() ? document()->page() : 0; + return document() ? document()->frame() : 0; } void Geolocation::stop() { - Page* page = this->page(); - if (page && m_allowGeolocation == InProgress) - GeolocationController::from(page)->cancelPermissionRequest(this); + LocalFrame* frame = this->frame(); + if (frame && m_allowGeolocation == InProgress) + GeolocationController::from(frame)->cancelPermissionRequest(this); // The frame may be moving to a new page and we want to get the permissions from the new page's client. m_allowGeolocation = Unknown; cancelAllRequests(); @@ -275,33 +286,33 @@ void Geolocation::stop() Geoposition* Geolocation::lastPosition() { - Page* page = this->page(); - if (!page) + LocalFrame* frame = this->frame(); + if (!frame) return 0; - m_lastPosition = createGeoposition(GeolocationController::from(page)->lastPosition()); + m_lastPosition = createGeoposition(GeolocationController::from(frame)->lastPosition()); return m_lastPosition.get(); } -void Geolocation::getCurrentPosition(PassOwnPtr<PositionCallback> successCallback, PassOwnPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) +void Geolocation::getCurrentPosition(PassOwnPtr<PositionCallback> successCallback, PassOwnPtr<PositionErrorCallback> errorCallback, PositionOptions* options) { if (!frame()) return; - RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options); - startRequest(notifier.get()); + GeoNotifier* notifier = GeoNotifier::create(this, successCallback, errorCallback, options); + startRequest(notifier); m_oneShots.add(notifier); } -int Geolocation::watchPosition(PassOwnPtr<PositionCallback> successCallback, PassOwnPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) +int Geolocation::watchPosition(PassOwnPtr<PositionCallback> successCallback, PassOwnPtr<PositionErrorCallback> errorCallback, PositionOptions* options) { if (!frame()) return 0; - RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options); - startRequest(notifier.get()); + GeoNotifier* notifier = GeoNotifier::create(this, successCallback, errorCallback, options); + startRequest(notifier); int watchID; // Keep asking for the next id until we're given one that we don't already have. @@ -319,14 +330,14 @@ void Geolocation::startRequest(GeoNotifier *notifier) notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage)); else if (haveSuitableCachedPosition(notifier->options())) notifier->setUseCachedPosition(); - else if (notifier->hasZeroTimeout()) - notifier->startTimerIfNeeded(); + else if (!notifier->options()->timeout()) + notifier->startTimer(); else if (!isAllowed()) { // if we don't yet have permission, request for permission before calling startUpdating() m_pendingForPermissionNotifiers.add(notifier); requestPermission(); } else if (startUpdating(notifier)) - notifier->startTimerIfNeeded(); + notifier->startTimer(); else notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage)); } @@ -377,8 +388,8 @@ void Geolocation::makeCachedPositionCallbacks() if (m_oneShots.contains(notifier)) m_oneShots.remove(notifier); else if (m_watchers.contains(notifier)) { - if (notifier->hasZeroTimeout() || startUpdating(notifier)) - notifier->startTimerIfNeeded(); + if (!notifier->options()->timeout() || startUpdating(notifier)) + notifier->startTimer(); else notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage)); } @@ -404,8 +415,6 @@ bool Geolocation::haveSuitableCachedPosition(PositionOptions* options) Geoposition* cachedPosition = lastPosition(); if (!cachedPosition) return false; - if (!options->hasMaximumAge()) - return true; if (!options->maximumAge()) return false; DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime()); @@ -427,9 +436,6 @@ void Geolocation::clearWatch(int watchID) void Geolocation::setIsAllowed(bool allowed) { - // Protect the Geolocation object from garbage collection during a callback. - RefPtr<Geolocation> protect(this); - // This may be due to either a new position from the service, or a cached // position. m_allowGeolocation = allowed ? Yes : No; @@ -442,9 +448,9 @@ void Geolocation::setIsAllowed(bool allowed) } if (!isAllowed()) { - RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage); + PositionError* error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage); error->setIsFatal(true); - handleError(error.get()); + handleError(error); m_requestsAwaitingCachedPosition.clear(); return; } @@ -460,12 +466,9 @@ void Geolocation::setIsAllowed(bool allowed) void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) { - GeoNotifierVector::const_iterator end = notifiers.end(); - for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) { - RefPtr<GeoNotifier> notifier = *it; - - notifier->runErrorCallback(error); - } + GeoNotifierVector::const_iterator end = notifiers.end(); + for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) + (*it)->runErrorCallback(error); } void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* position) @@ -585,14 +588,14 @@ void Geolocation::requestPermission() if (m_allowGeolocation > Unknown) return; - Page* page = this->page(); - if (!page) + LocalFrame* frame = this->frame(); + if (!frame) return; m_allowGeolocation = InProgress; // Ask the embedder: it maintains the geolocation challenge policy itself. - GeolocationController::from(page)->requestPermission(this); + GeolocationController::from(frame)->requestPermission(this); } void Geolocation::makeSuccessCallbacks() @@ -635,27 +638,26 @@ void Geolocation::positionChanged() void Geolocation::setError(GeolocationError* error) { - RefPtr<PositionError> positionError = createPositionError(error); - handleError(positionError.get()); + handleError(createPositionError(error)); } bool Geolocation::startUpdating(GeoNotifier* notifier) { - Page* page = this->page(); - if (!page) + LocalFrame* frame = this->frame(); + if (!frame) return false; - GeolocationController::from(page)->addObserver(this, notifier->options()->enableHighAccuracy()); + GeolocationController::from(frame)->addObserver(this, notifier->options()->enableHighAccuracy()); return true; } void Geolocation::stopUpdating() { - Page* page = this->page(); - if (!page) + LocalFrame* frame = this->frame(); + if (!frame) return; - GeolocationController::from(page)->removeObserver(this); + GeolocationController::from(frame)->removeObserver(this); } void Geolocation::handlePendingPermissionNotifiers() @@ -670,7 +672,7 @@ void Geolocation::handlePendingPermissionNotifiers() // start all pending notification requests as permission granted. // The notifier is always ref'ed by m_oneShots or m_watchers. if (startUpdating(notifier)) - notifier->startTimerIfNeeded(); + notifier->startTimer(); else notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage)); } else { diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.h b/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.h index 4f8aed2daa7..a1779fbb383 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.h @@ -35,34 +35,37 @@ #include "modules/geolocation/PositionErrorCallback.h" #include "modules/geolocation/PositionOptions.h" #include "platform/Timer.h" +#include "platform/heap/Handle.h" namespace WebCore { class Document; -class Frame; +class LocalFrame; class GeolocationController; class GeolocationError; class GeolocationPosition; -class Page; class ExecutionContext; -class Geolocation : public ScriptWrappable, public RefCounted<Geolocation>, public ActiveDOMObject -{ +class Geolocation FINAL + : public GarbageCollectedFinalized<Geolocation> + , public ScriptWrappable + , public ActiveDOMObject { public: - static PassRefPtr<Geolocation> create(ExecutionContext*); - ~Geolocation(); + static Geolocation* create(ExecutionContext*); + virtual ~Geolocation(); + void trace(Visitor*); virtual void stop() OVERRIDE; Document* document() const; - Frame* frame() const; + LocalFrame* frame() const; // Creates a oneshot and attempts to obtain a position that meets the // constraints of the options. - void getCurrentPosition(PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); + void getCurrentPosition(PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PositionOptions*); // Creates a watcher that will be notified whenever a new position is // available that meets the constraints of the options. - int watchPosition(PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); + int watchPosition(PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PositionOptions*); // Removes all references to the watcher, it will not be updated again. void clearWatch(int watchID); @@ -86,21 +89,23 @@ private: explicit Geolocation(ExecutionContext*); - Page* page() const; - // Holds the success and error callbacks and the options that were provided // when a oneshot or watcher were created. Also, if specified in the // options, manages a timer to limit the time to wait for the system to // obtain a position. - class GeoNotifier : public RefCounted<GeoNotifier> { + class GeoNotifier : public GarbageCollectedFinalized<GeoNotifier> { public: - static PassRefPtr<GeoNotifier> create(Geolocation* geolocation, PassOwnPtr<PositionCallback> positionCallback, PassOwnPtr<PositionErrorCallback> positionErrorCallback, PassRefPtr<PositionOptions> options) { return adoptRef(new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options)); } + static GeoNotifier* create(Geolocation* geolocation, PassOwnPtr<PositionCallback> positionCallback, PassOwnPtr<PositionErrorCallback> positionErrorCallback, PositionOptions* options) + { + return new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options); + } + void trace(Visitor*); PositionOptions* options() const { return m_options.get(); }; // Sets the given error as the fatal error if there isn't one yet. // Starts the timer with an interval of 0. - void setFatalError(PassRefPtr<PositionError>); + void setFatalError(PositionError*); bool useCachedPosition() const { return m_useCachedPosition; } @@ -111,9 +116,7 @@ private: void runSuccessCallback(Geoposition*); void runErrorCallback(PositionError*); - // Starts the timer if a timeout was specified on the options. - void startTimerIfNeeded(); - + void startTimer(); void stopTimer(); // Runs the error callback if there is a fatal error. Otherwise, if a @@ -121,26 +124,26 @@ private: // Otherwise, the notifier has expired, and its error callback is run. void timerFired(Timer<GeoNotifier>*); - bool hasZeroTimeout() const; - private: - GeoNotifier(Geolocation*, PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); + GeoNotifier(Geolocation*, PassOwnPtr<PositionCallback>, PassOwnPtr<PositionErrorCallback>, PositionOptions*); - RefPtr<Geolocation> m_geolocation; + Member<Geolocation> m_geolocation; OwnPtr<PositionCallback> m_successCallback; OwnPtr<PositionErrorCallback> m_errorCallback; - RefPtr<PositionOptions> m_options; + Member<PositionOptions> m_options; Timer<GeoNotifier> m_timer; - RefPtr<PositionError> m_fatalError; + Member<PositionError> m_fatalError; bool m_useCachedPosition; }; - typedef Vector<RefPtr<GeoNotifier> > GeoNotifierVector; - typedef HashSet<RefPtr<GeoNotifier> > GeoNotifierSet; + typedef HeapVector<Member<GeoNotifier> > GeoNotifierVector; + typedef HeapHashSet<Member<GeoNotifier> > GeoNotifierSet; class Watchers { + DISALLOW_ALLOCATION(); public: - bool add(int id, PassRefPtr<GeoNotifier>); + void trace(Visitor*); + bool add(int id, GeoNotifier*); GeoNotifier* find(int id); void remove(int id); void remove(GeoNotifier*); @@ -149,8 +152,8 @@ private: bool isEmpty() const; void getNotifiersVector(GeoNotifierVector&) const; private: - typedef HashMap<int, RefPtr<GeoNotifier> > IdToNotifierMap; - typedef HashMap<RefPtr<GeoNotifier>, int> NotifierToIdMap; + typedef HeapHashMap<int, Member<GeoNotifier> > IdToNotifierMap; + typedef HeapHashMap<Member<GeoNotifier>, int> NotifierToIdMap; IdToNotifierMap m_idToNotifierMap; NotifierToIdMap m_notifierToIdMap; }; @@ -226,7 +229,7 @@ private: GeoNotifierSet m_oneShots; Watchers m_watchers; GeoNotifierSet m_pendingForPermissionNotifiers; - RefPtr<Geoposition> m_lastPosition; + Member<Geoposition> m_lastPosition; enum { Unknown, diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.idl b/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.idl index b8fde66b7bb..ca1b5a5e61d 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.idl +++ b/chromium/third_party/WebKit/Source/modules/geolocation/Geolocation.idl @@ -25,15 +25,18 @@ // http://www.w3.org/TR/geolocation-API/#geolocation_interface [ - NoInterfaceObject + GarbageCollected, + NoInterfaceObject, ] interface Geolocation { - [Custom, PerWorldBindings, ActivityLogging=ForIsolatedWorlds] void getCurrentPosition(PositionCallback successCallback, + // FIXME: should be: PositionOptions options: need PositionOptions.idl and dictionary http:/crbug.com/321462 + [Custom, LogActivity] void getCurrentPosition(PositionCallback successCallback, optional PositionErrorCallback errorCallback, - optional PositionOptions options); + optional object options); - [Custom, PerWorldBindings, ActivityLogging=ForIsolatedWorlds] long watchPosition(PositionCallback successCallback, + // FIXME: should be: PositionOptions options: need PositionOptions.idl and dictionary http:/crbug.com/321462 + [Custom, LogActivity] long watchPosition(PositionCallback successCallback, optional PositionErrorCallback errorCallback, - optional PositionOptions options); + optional object options); void clearWatch(long watchID); }; diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationClient.h b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationClient.h index d8938710555..c4a90dac8ac 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationClient.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationClient.h @@ -29,8 +29,9 @@ namespace WebCore { class Geolocation; +class GeolocationController; class GeolocationPosition; -class Page; +class LocalFrame; class GeolocationClient { public: @@ -38,23 +39,20 @@ public: virtual void startUpdating() = 0; virtual void stopUpdating() = 0; - // FIXME: The V2 Geolocation specification proposes that this property is - // renamed. See http://www.w3.org/2008/geolocation/track/issues/6 - // We should update WebKit to reflect this if and when the V2 specification - // is published. virtual void setEnableHighAccuracy(bool) = 0; virtual GeolocationPosition* lastPosition() = 0; virtual void requestPermission(Geolocation*) = 0; virtual void cancelPermissionRequest(Geolocation*) = 0; - void provideGeolocationTo(Page*, GeolocationClient*); + virtual void controllerForTestAdded(GeolocationController*) { } + virtual void controllerForTestRemoved(GeolocationController*) { } protected: virtual ~GeolocationClient() { } }; -void provideGeolocationTo(Page*, GeolocationClient*); +void provideGeolocationTo(LocalFrame&, GeolocationClient*); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationController.cpp b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationController.cpp index 0c7f0e44480..213bb36efdb 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationController.cpp +++ b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationController.cpp @@ -24,20 +24,44 @@ */ #include "config.h" + #include "modules/geolocation/GeolocationController.h" -#include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorController.h" +#include "core/page/Page.h" #include "modules/geolocation/GeolocationClient.h" #include "modules/geolocation/GeolocationError.h" +#include "modules/geolocation/GeolocationInspectorAgent.h" #include "modules/geolocation/GeolocationPosition.h" namespace WebCore { -GeolocationController::GeolocationController(Page* page, GeolocationClient* client) - : PageLifecycleObserver(page) +GeolocationController::GeolocationController(LocalFrame& frame, GeolocationClient* client) + : PageLifecycleObserver(frame.page()) , m_client(client) + , m_hasClientForTest(false) , m_isClientUpdating(false) + , m_inspectorAgent() { + // FIXME: Once GeolocationInspectorAgent is per frame, there will be a 1:1 relationship between + // it and this class. Until then, there's one GeolocationInspectorAgent per page that the main + // frame is responsible for creating. + if (frame.isMainFrame()) { + OwnPtr<GeolocationInspectorAgent> geolocationAgent(GeolocationInspectorAgent::create()); + m_inspectorAgent = geolocationAgent.get(); + frame.page()->inspectorController().registerModuleAgent(geolocationAgent.release()); + } else { + m_inspectorAgent = GeolocationController::from(frame.page()->deprecatedLocalMainFrame())->m_inspectorAgent; + } + + m_inspectorAgent->AddController(this); + + if (!frame.isMainFrame()) { + // internals.setGeolocationClientMock is per page. + GeolocationController* mainController = GeolocationController::from(frame.page()->deprecatedLocalMainFrame()); + if (mainController->hasClientForTest()) + setClientForTest(mainController->client()); + } } void GeolocationController::startUpdatingIfNeeded() @@ -59,14 +83,29 @@ void GeolocationController::stopUpdatingIfNeeded() GeolocationController::~GeolocationController() { ASSERT(m_observers.isEmpty()); + if (page()) + m_inspectorAgent->RemoveController(this); + if (m_hasClientForTest) + m_client->controllerForTestRemoved(this); +} + +// FIXME: Oilpan: Once GeolocationClient is on-heap m_client should be a strong +// pointer and |willBeDestroyed| can potentially be removed from Supplement. +void GeolocationController::willBeDestroyed() +{ if (m_client) m_client->geolocationDestroyed(); } -PassOwnPtr<GeolocationController> GeolocationController::create(Page* page, GeolocationClient* client) +void GeolocationController::persistentHostHasBeenDestroyed() +{ + observeContext(0); +} + +PassOwnPtrWillBeRawPtr<GeolocationController> GeolocationController::create(LocalFrame& frame, GeolocationClient* client) { - return adoptPtr(new GeolocationController(page, client)); + return adoptPtrWillBeNoop(new GeolocationController(frame, client)); } void GeolocationController::addObserver(Geolocation* observer, bool enableHighAccuracy) @@ -116,13 +155,13 @@ void GeolocationController::cancelPermissionRequest(Geolocation* geolocation) void GeolocationController::positionChanged(GeolocationPosition* position) { - position = InspectorInstrumentation::overrideGeolocationPosition(page(), position); + position = m_inspectorAgent->overrideGeolocationPosition(position); if (!position) { - errorOccurred(GeolocationError::create(GeolocationError::PositionUnavailable, "PositionUnavailable").get()); + errorOccurred(GeolocationError::create(GeolocationError::PositionUnavailable, "PositionUnavailable")); return; } m_lastPosition = position; - Vector<RefPtr<Geolocation> > observersVector; + HeapVector<Member<Geolocation> > observersVector; copyToVector(m_observers, observersVector); for (size_t i = 0; i < observersVector.size(); ++i) observersVector[i]->positionChanged(); @@ -130,7 +169,7 @@ void GeolocationController::positionChanged(GeolocationPosition* position) void GeolocationController::errorOccurred(GeolocationError* error) { - Vector<RefPtr<Geolocation> > observersVector; + HeapVector<Member<Geolocation> > observersVector; copyToVector(m_observers, observersVector); for (size_t i = 0; i < observersVector.size(); ++i) observersVector[i]->setError(error); @@ -147,6 +186,16 @@ GeolocationPosition* GeolocationController::lastPosition() return m_client->lastPosition(); } +void GeolocationController::setClientForTest(GeolocationClient* client) +{ + if (m_hasClientForTest) + m_client->controllerForTestRemoved(this); + m_client = client; + m_hasClientForTest = true; + + client->controllerForTestAdded(this); +} + void GeolocationController::pageVisibilityChanged() { if (m_observers.isEmpty() || !m_client) @@ -163,9 +212,17 @@ const char* GeolocationController::supplementName() return "GeolocationController"; } -void provideGeolocationTo(Page* page, GeolocationClient* client) +void GeolocationController::trace(Visitor* visitor) +{ + visitor->trace(m_lastPosition); + visitor->trace(m_observers); + visitor->trace(m_highAccuracyObservers); + WillBeHeapSupplement<LocalFrame>::trace(visitor); +} + +void provideGeolocationTo(LocalFrame& frame, GeolocationClient* client) { - Supplement<Page>::provideTo(page, GeolocationController::supplementName(), GeolocationController::create(page, client)); + WillBeHeapSupplement<LocalFrame>::provideTo(frame, GeolocationController::supplementName(), GeolocationController::create(frame, client)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationController.h b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationController.h index 50eaae892cb..17e5cb8f9f4 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationController.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationController.h @@ -26,26 +26,27 @@ #ifndef GeolocationController_h #define GeolocationController_h -#include "core/page/Page.h" +#include "core/frame/LocalFrame.h" #include "core/page/PageLifecycleObserver.h" #include "modules/geolocation/Geolocation.h" +#include "platform/heap/Handle.h" #include "wtf/HashSet.h" #include "wtf/Noncopyable.h" -#include "wtf/RefPtr.h" namespace WebCore { +class GeolocationInspectorAgent; class GeolocationClient; class GeolocationError; class GeolocationPosition; -class Page; -class GeolocationController : public Supplement<Page>, public PageLifecycleObserver { +class GeolocationController FINAL : public NoBaseWillBeGarbageCollectedFinalized<GeolocationController>, public WillBeHeapSupplement<LocalFrame>, public PageLifecycleObserver { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(GeolocationController); WTF_MAKE_NONCOPYABLE(GeolocationController); public: - ~GeolocationController(); + virtual ~GeolocationController(); - static PassOwnPtr<GeolocationController> create(Page*, GeolocationClient*); + static PassOwnPtrWillBeRawPtr<GeolocationController> create(LocalFrame&, GeolocationClient*); void addObserver(Geolocation*, bool enableHighAccuracy); void removeObserver(Geolocation*); @@ -58,26 +59,37 @@ public: GeolocationPosition* lastPosition(); + void setClientForTest(GeolocationClient*); + bool hasClientForTest() { return m_hasClientForTest; } + GeolocationClient* client() { return m_client; } + // Inherited from PageLifecycleObserver. virtual void pageVisibilityChanged() OVERRIDE; static const char* supplementName(); - static GeolocationController* from(Page* page) { return static_cast<GeolocationController*>(Supplement<Page>::from(page, supplementName())); } + static GeolocationController* from(LocalFrame* frame) { return static_cast<GeolocationController*>(WillBeHeapSupplement<LocalFrame>::from(frame, supplementName())); } + + // Inherited from Supplement. + virtual void trace(Visitor*) OVERRIDE; + virtual void willBeDestroyed() OVERRIDE; + virtual void persistentHostHasBeenDestroyed() OVERRIDE; private: - GeolocationController(Page*, GeolocationClient*); + GeolocationController(LocalFrame&, GeolocationClient*); void startUpdatingIfNeeded(); void stopUpdatingIfNeeded(); GeolocationClient* m_client; + bool m_hasClientForTest; - RefPtr<GeolocationPosition> m_lastPosition; - typedef HashSet<RefPtr<Geolocation> > ObserversSet; + PersistentWillBeMember<GeolocationPosition> m_lastPosition; + typedef PersistentHeapHashSetWillBeHeapHashSet<Member<Geolocation> > ObserversSet; // All observers; both those requesting high accuracy and those not. ObserversSet m_observers; ObserversSet m_highAccuracyObservers; bool m_isClientUpdating; + GeolocationInspectorAgent* m_inspectorAgent; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationError.h b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationError.h index 23ecb71aa17..f2997f119db 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationError.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationError.h @@ -26,21 +26,22 @@ #ifndef GeolocationError_h #define GeolocationError_h -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" namespace WebCore { -class GeolocationError : public RefCounted<GeolocationError> { +class GeolocationError : public GarbageCollectedFinalized<GeolocationError> { public: enum ErrorCode { PermissionDenied, PositionUnavailable }; - static PassRefPtr<GeolocationError> create(ErrorCode code, const String& message) { return adoptRef(new GeolocationError(code, message)); } + static GeolocationError* create(ErrorCode code, const String& message) + { + return new GeolocationError(code, message); + } + void trace(Visitor*) { } ErrorCode code() const { return m_code; } const String& message() const { return m_message; } diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationInspectorAgent.cpp b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationInspectorAgent.cpp new file mode 100644 index 00000000000..049d821e010 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationInspectorAgent.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/geolocation/GeolocationInspectorAgent.h" + +#include "modules/geolocation/GeolocationController.h" + +namespace WebCore { + +PassOwnPtr<GeolocationInspectorAgent> GeolocationInspectorAgent::create() +{ + return adoptPtr(new GeolocationInspectorAgent()); +} + +GeolocationInspectorAgent::~GeolocationInspectorAgent() +{ +} + +GeolocationInspectorAgent::GeolocationInspectorAgent() + : InspectorBaseAgent<GeolocationInspectorAgent>("Geolocation") + , m_geolocationOverridden(false) +{ +} + +void GeolocationInspectorAgent::setGeolocationOverride(ErrorString* error, const double* latitude, const double* longitude, const double* accuracy) +{ + GeolocationPosition* position = (*m_controllers.begin())->lastPosition(); + if (!m_geolocationOverridden && position) + m_platformGeolocationPosition = position; + + m_geolocationOverridden = true; + if (latitude && longitude && accuracy) + m_geolocationPosition = GeolocationPosition::create(currentTime(), *latitude, *longitude, *accuracy); + else + m_geolocationPosition.clear(); + + for (GeolocationControllers::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it) + (*it)->positionChanged(0); // Kick location update. +} + +void GeolocationInspectorAgent::clearGeolocationOverride(ErrorString*) +{ + if (!m_geolocationOverridden) + return; + m_geolocationOverridden = false; + m_geolocationPosition.clear(); + + if (GeolocationPosition* platformPosition = m_platformGeolocationPosition.get()) { + for (GeolocationControllers::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it) + (*it)->positionChanged(platformPosition); + } +} + +GeolocationPosition* GeolocationInspectorAgent::overrideGeolocationPosition(GeolocationPosition* position) +{ + if (m_geolocationOverridden) { + if (position) + m_platformGeolocationPosition = position; + return m_geolocationPosition.get(); + } + return position; +} + +void GeolocationInspectorAgent::AddController(GeolocationController* controller) +{ + m_controllers.add(controller); +} + +void GeolocationInspectorAgent::RemoveController(GeolocationController* controller) +{ + m_controllers.remove(controller); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessPromise.h b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationInspectorAgent.h index 074273c74cd..429ceae6167 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessPromise.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationInspectorAgent.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,62 +28,48 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MIDIAccessPromise_h -#define MIDIAccessPromise_h +#ifndef GeolocationInspectorAgent_h +#define GeolocationInspectorAgent_h -#include "bindings/v8/ScriptWrappable.h" -#include "core/dom/ActiveDOMObject.h" -#include "modules/webmidi/MIDIOptions.h" -#include "wtf/OwnPtr.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" + +#include "core/inspector/InspectorBaseAgent.h" +#include "modules/geolocation/GeolocationPosition.h" +#include "wtf/HashSet.h" +#include "wtf/text/WTFString.h" namespace WebCore { -class DOMError; -class MIDIAccess; -class MIDIErrorCallback; -class MIDISuccessCallback; -class ExecutionContext; +class GeolocationController; -struct MIDIOptions; +typedef String ErrorString; -class MIDIAccessPromise : public RefCounted<MIDIAccessPromise>, public ScriptWrappable, public ActiveDOMObject { +class GeolocationInspectorAgent FINAL : public InspectorBaseAgent<GeolocationInspectorAgent>, public InspectorBackendDispatcher::GeolocationCommandHandler { + WTF_MAKE_NONCOPYABLE(GeolocationInspectorAgent); public: - static PassRefPtr<MIDIAccessPromise> create(ExecutionContext*, const Dictionary&); - virtual ~MIDIAccessPromise(); - - // ActiveDOMObject - virtual bool hasPendingActivity() const OVERRIDE; - virtual void stop() OVERRIDE; + static PassOwnPtr<GeolocationInspectorAgent> create(); + virtual ~GeolocationInspectorAgent(); - MIDIOptions* options() { return m_options.get(); } + // Protocol methods. + virtual void setGeolocationOverride(ErrorString*, const double*, const double*, const double*) OVERRIDE; + virtual void clearGeolocationOverride(ErrorString*) OVERRIDE; - void fulfill(); - void reject(PassRefPtr<DOMError>); + // Instrumentation method. + GeolocationPosition* overrideGeolocationPosition(GeolocationPosition*); - void then(PassOwnPtr<MIDISuccessCallback>, PassOwnPtr<MIDIErrorCallback>); + void AddController(GeolocationController*); + void RemoveController(GeolocationController*); private: - enum State { - Pending, - Accepted, - Rejected, - Invoked, - }; - - MIDIAccessPromise(ExecutionContext*, const Dictionary&); - - void clear(); - - State m_state; - OwnPtr<MIDISuccessCallback> m_successCallback; - OwnPtr<MIDIErrorCallback> m_errorCallback; - OwnPtr<MIDIOptions> m_options; - RefPtr<DOMError> m_error; - RefPtr<MIDIAccess> m_access; + GeolocationInspectorAgent(); + typedef WillBeHeapHashSet<RawPtrWillBeMember<GeolocationController> > GeolocationControllers; + WillBePersistentHeapHashSet<RawPtrWillBeMember<GeolocationController> > m_controllers; + bool m_geolocationOverridden; + Persistent<GeolocationPosition> m_geolocationPosition; + Persistent<GeolocationPosition> m_platformGeolocationPosition; }; + } // namespace WebCore -#endif // MIDIAccessPromise_h + +#endif // !defined(GeolocationInspectorAgent_h) diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationPosition.h b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationPosition.h index 0b0b7da4e4d..11733df659d 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationPosition.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/GeolocationPosition.h @@ -26,17 +26,21 @@ #ifndef GeolocationPosition_h #define GeolocationPosition_h -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" +#include "platform/heap/Handle.h" namespace WebCore { -class GeolocationPosition : public RefCounted<GeolocationPosition> { +class GeolocationPosition : public GarbageCollected<GeolocationPosition> { public: - static PassRefPtr<GeolocationPosition> create(double timestamp, double latitude, double longitude, double accuracy) { return adoptRef(new GeolocationPosition(timestamp, latitude, longitude, accuracy)); } - - static PassRefPtr<GeolocationPosition> create(double timestamp, double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { return adoptRef(new GeolocationPosition(timestamp, latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed)); } + static GeolocationPosition* create(double timestamp, double latitude, double longitude, double accuracy) + { + return new GeolocationPosition(timestamp, latitude, longitude, accuracy); + } + static GeolocationPosition* create(double timestamp, double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) + { + return new GeolocationPosition(timestamp, latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed); + } + void trace(Visitor*) { } double timestamp() const { return m_timestamp; } diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/Geoposition.h b/chromium/third_party/WebKit/Source/modules/geolocation/Geoposition.h index 74a5f3dcd51..0a3bd266426 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/Geoposition.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/Geoposition.h @@ -27,30 +27,29 @@ #define Geoposition_h #include "bindings/v8/ScriptWrappable.h" -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "modules/geolocation/Coordinates.h" -#include "wtf/RefCounted.h" -#include "wtf/text/WTFString.h" +#include "platform/heap/Handle.h" namespace WebCore { -class Geoposition : public RefCounted<Geoposition>, public ScriptWrappable { +class Geoposition : public GarbageCollectedFinalized<Geoposition>, public ScriptWrappable { public: - static PassRefPtr<Geoposition> create(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp) + static Geoposition* create(Coordinates* coordinates, DOMTimeStamp timestamp) { - return adoptRef(new Geoposition(coordinates, timestamp)); + return new Geoposition(coordinates, timestamp); } - PassRefPtr<Geoposition> isolatedCopy() const + void trace(Visitor* visitor) { - return Geoposition::create(m_coordinates->isolatedCopy(), m_timestamp); + visitor->trace(m_coordinates); } DOMTimeStamp timestamp() const { return m_timestamp; } Coordinates* coords() const { return m_coordinates.get(); } private: - Geoposition(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp) + Geoposition(Coordinates* coordinates, DOMTimeStamp timestamp) : m_coordinates(coordinates) , m_timestamp(timestamp) { @@ -58,7 +57,7 @@ private: ScriptWrappable::init(this); } - RefPtr<Coordinates> m_coordinates; + Member<Coordinates> m_coordinates; DOMTimeStamp m_timestamp; }; diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/Geoposition.idl b/chromium/third_party/WebKit/Source/modules/geolocation/Geoposition.idl index 1b5e3477064..7d5c597e29e 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/Geoposition.idl +++ b/chromium/third_party/WebKit/Source/modules/geolocation/Geoposition.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject ] interface Geoposition { readonly attribute Coordinates coords; diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.cpp b/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.cpp index 72429741aa9..b30bc7480e8 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.cpp +++ b/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.cpp @@ -24,13 +24,13 @@ #include "modules/geolocation/NavigatorGeolocation.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" #include "modules/geolocation/Geolocation.h" namespace WebCore { -NavigatorGeolocation::NavigatorGeolocation(Frame* frame) +NavigatorGeolocation::NavigatorGeolocation(LocalFrame* frame) : DOMWindowProperty(frame) { } @@ -44,19 +44,19 @@ const char* NavigatorGeolocation::supplementName() return "NavigatorGeolocation"; } -NavigatorGeolocation* NavigatorGeolocation::from(Navigator* navigator) +NavigatorGeolocation& NavigatorGeolocation::from(Navigator& navigator) { - NavigatorGeolocation* supplement = static_cast<NavigatorGeolocation*>(Supplement<Navigator>::from(navigator, supplementName())); + NavigatorGeolocation* supplement = static_cast<NavigatorGeolocation*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); if (!supplement) { - supplement = new NavigatorGeolocation(navigator->frame()); - provideTo(navigator, supplementName(), adoptPtr(supplement)); + supplement = new NavigatorGeolocation(navigator.frame()); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -Geolocation* NavigatorGeolocation::geolocation(Navigator* navigator) +Geolocation* NavigatorGeolocation::geolocation(Navigator& navigator) { - return NavigatorGeolocation::from(navigator)->geolocation(); + return NavigatorGeolocation::from(navigator).geolocation(); } Geolocation* NavigatorGeolocation::geolocation() const @@ -66,4 +66,10 @@ Geolocation* NavigatorGeolocation::geolocation() const return m_geolocation.get(); } +void NavigatorGeolocation::trace(Visitor* visitor) +{ + visitor->trace(m_geolocation); + WillBeHeapSupplement<Navigator>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.h b/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.h index 37c37e55189..df8fd9a22f0 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.h @@ -22,26 +22,30 @@ #include "core/frame/DOMWindowProperty.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { -class Frame; +class LocalFrame; class Geolocation; class Navigator; -class NavigatorGeolocation : public Supplement<Navigator>, public DOMWindowProperty { +class NavigatorGeolocation FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorGeolocation>, public WillBeHeapSupplement<Navigator>, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorGeolocation); public: virtual ~NavigatorGeolocation(); - static NavigatorGeolocation* from(Navigator*); + static NavigatorGeolocation& from(Navigator&); - static Geolocation* geolocation(Navigator*); + static Geolocation* geolocation(Navigator&); Geolocation* geolocation() const; + void trace(Visitor*); + private: - NavigatorGeolocation(Frame*); + NavigatorGeolocation(LocalFrame*); static const char* supplementName(); - mutable RefPtr<Geolocation> m_geolocation; + mutable PersistentWillBeMember<Geolocation> m_geolocation; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.idl b/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.idl index 4de885ca811..9b96fd709da 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.idl +++ b/chromium/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.idl @@ -18,6 +18,5 @@ */ partial interface Navigator { - [RuntimeEnabled=Geolocation] readonly attribute Geolocation geolocation; + readonly attribute Geolocation geolocation; }; - diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/PositionError.h b/chromium/third_party/WebKit/Source/modules/geolocation/PositionError.h index d19b330d8d6..5be3f08b104 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/PositionError.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/PositionError.h @@ -27,13 +27,12 @@ #define PositionError_h #include "bindings/v8/ScriptWrappable.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { -class PositionError : public RefCounted<PositionError>, public ScriptWrappable { +class PositionError : public GarbageCollectedFinalized<PositionError>, public ScriptWrappable { public: enum ErrorCode { PERMISSION_DENIED = 1, @@ -41,7 +40,8 @@ public: TIMEOUT = 3 }; - static PassRefPtr<PositionError> create(ErrorCode code, const String& message) { return adoptRef(new PositionError(code, message)); } + static PositionError* create(ErrorCode code, const String& message) { return new PositionError(code, message); } + void trace(Visitor*) { } ErrorCode code() const { return m_code; } const String& message() const { return m_message; } diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/PositionError.idl b/chromium/third_party/WebKit/Source/modules/geolocation/PositionError.idl index 2a673c0864c..b4a7f8363db 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/PositionError.idl +++ b/chromium/third_party/WebKit/Source/modules/geolocation/PositionError.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject ] interface PositionError { readonly attribute unsigned short code; diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/PositionOptions.h b/chromium/third_party/WebKit/Source/modules/geolocation/PositionOptions.h index 1b1e48e661f..d3d9ffc8a9d 100644 --- a/chromium/third_party/WebKit/Source/modules/geolocation/PositionOptions.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/PositionOptions.h @@ -26,56 +26,48 @@ #ifndef PositionOptions_h #define PositionOptions_h -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" +#include <limits.h> namespace WebCore { -class PositionOptions : public RefCounted<PositionOptions> { +class PositionOptions : public GarbageCollected<PositionOptions> { public: - static PassRefPtr<PositionOptions> create() { return adoptRef(new PositionOptions()); } + static PositionOptions* create() { return new PositionOptions(); } + void trace(Visitor*) { } bool enableHighAccuracy() const { return m_highAccuracy; } void setEnableHighAccuracy(bool enable) { m_highAccuracy = enable; } - bool hasTimeout() const { return m_hasTimeout; } - int timeout() const + unsigned timeout() const { - ASSERT(hasTimeout()); return m_timeout; } - void setTimeout(int timeout) + void setTimeout(unsigned timeout) { - ASSERT(timeout >= 0); - m_hasTimeout = true; m_timeout = timeout; } - bool hasMaximumAge() const { return m_hasMaximumAge; } - int maximumAge() const + unsigned maximumAge() const { - ASSERT(hasMaximumAge()); return m_maximumAge; } - void clearMaximumAge() { m_hasMaximumAge = false; } - void setMaximumAge(int age) + void setMaximumAge(unsigned age) { - ASSERT(age >= 0); - m_hasMaximumAge = true; m_maximumAge = age; } private: PositionOptions() : m_highAccuracy(false) - , m_hasTimeout(false) + , m_maximumAge(0) + , m_timeout(std::numeric_limits<unsigned>::max()) + { setMaximumAge(0); } bool m_highAccuracy; - bool m_hasTimeout; - int m_timeout; - bool m_hasMaximumAge; - int m_maximumAge; + unsigned m_maximumAge; + unsigned m_timeout; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/testing/GeolocationClientMock.cpp b/chromium/third_party/WebKit/Source/modules/geolocation/testing/GeolocationClientMock.cpp new file mode 100644 index 00000000000..b82d2a94e82 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/geolocation/testing/GeolocationClientMock.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2012 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GeolocationClientMock.h" + +#include "modules/geolocation/GeolocationController.h" +#include "modules/geolocation/GeolocationError.h" +#include "modules/geolocation/GeolocationPosition.h" + +namespace WebCore { + +GeolocationClientMock::GeolocationClientMock() + : m_hasError(false) + , m_controllerTimer(this, &GeolocationClientMock::controllerTimerFired) + , m_permissionTimer(this, &GeolocationClientMock::permissionTimerFired) + , m_isActive(false) + , m_permissionState(PermissionStateUnset) +{ +} + +GeolocationClientMock::~GeolocationClientMock() +{ + ASSERT(!m_isActive); +} + +void GeolocationClientMock::setPosition(GeolocationPosition* position) +{ + m_lastPosition = position; + clearError(); + asyncUpdateController(); +} + +void GeolocationClientMock::setPositionUnavailableError(const String& errorMessage) +{ + m_hasError = true; + m_errorMessage = errorMessage; + m_lastPosition = nullptr; + asyncUpdateController(); +} + +void GeolocationClientMock::setPermission(bool allowed) +{ + m_permissionState = allowed ? PermissionStateAllowed : PermissionStateDenied; + asyncUpdatePermission(); +} + +int GeolocationClientMock::numberOfPendingPermissionRequests() const +{ + return m_pendingPermissions.size(); +} + +void GeolocationClientMock::requestPermission(Geolocation* geolocation) +{ + m_pendingPermissions.add(geolocation); + if (m_permissionState != PermissionStateUnset) + asyncUpdatePermission(); +} + +void GeolocationClientMock::cancelPermissionRequest(Geolocation* geolocation) +{ + // Called from Geolocation::disconnectFrame() in response to LocalFrame destruction. + m_pendingPermissions.remove(geolocation); + if (m_pendingPermissions.isEmpty() && m_permissionTimer.isActive()) + m_permissionTimer.stop(); +} + +void GeolocationClientMock::controllerForTestAdded(GeolocationController* controller) +{ + m_controllers.add(controller); +} + +void GeolocationClientMock::controllerForTestRemoved(GeolocationController* controller) +{ + m_controllers.remove(controller); +} + +void GeolocationClientMock::asyncUpdatePermission() +{ + ASSERT(m_permissionState != PermissionStateUnset); + if (!m_permissionTimer.isActive()) + m_permissionTimer.startOneShot(0, FROM_HERE); +} + +void GeolocationClientMock::permissionTimerFired(Timer<GeolocationClientMock>* timer) +{ + ASSERT_UNUSED(timer, timer == &m_permissionTimer); + ASSERT(m_permissionState != PermissionStateUnset); + bool allowed = m_permissionState == PermissionStateAllowed; + GeolocationSet::iterator end = m_pendingPermissions.end(); + + // Once permission has been set (or denied) on a Geolocation object, there can be + // no further requests for permission to the mock. Consequently the callbacks + // which fire synchronously from Geolocation::setIsAllowed() cannot reentrantly modify + // m_pendingPermissions. + for (GeolocationSet::iterator it = m_pendingPermissions.begin(); it != end; ++it) + (*it)->setIsAllowed(allowed); + m_pendingPermissions.clear(); +} + +void GeolocationClientMock::geolocationDestroyed() +{ + ASSERT(!m_isActive); +} + +void GeolocationClientMock::startUpdating() +{ + ASSERT(!m_isActive); + m_isActive = true; + asyncUpdateController(); +} + +void GeolocationClientMock::stopUpdating() +{ + ASSERT(m_isActive); + m_isActive = false; + m_controllerTimer.stop(); +} + +void GeolocationClientMock::setEnableHighAccuracy(bool) +{ + // FIXME: We need to add some tests regarding "high accuracy" mode. + // See https://bugs.webkit.org/show_bug.cgi?id=49438 +} + +GeolocationPosition* GeolocationClientMock::lastPosition() +{ + return m_lastPosition.get(); +} + +void GeolocationClientMock::asyncUpdateController() +{ + if (m_isActive && !m_controllerTimer.isActive()) + m_controllerTimer.startOneShot(0, FROM_HERE); +} + +void GeolocationClientMock::controllerTimerFired(Timer<GeolocationClientMock>* timer) +{ + ASSERT_UNUSED(timer, timer == &m_controllerTimer); + + // Make a copy of the set of controllers since it might be modified while iterating. + GeolocationControllers controllers = m_controllers; + if (m_lastPosition.get()) { + ASSERT(!m_hasError); + for (GeolocationControllers::iterator it = controllers.begin(); it != controllers.end(); ++it) + (*it)->positionChanged(m_lastPosition.get()); + } else if (m_hasError) { + for (GeolocationControllers::iterator it = controllers.begin(); it != controllers.end(); ++it) + (*it)->errorOccurred(GeolocationError::create(GeolocationError::PositionUnavailable, m_errorMessage)); + } +} + +void GeolocationClientMock::clearError() +{ + m_hasError = false; + m_errorMessage = String(); +} + +} // WebCore diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/testing/GeolocationClientMock.h b/chromium/third_party/WebKit/Source/modules/geolocation/testing/GeolocationClientMock.h new file mode 100644 index 00000000000..b75f3cc05b4 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/geolocation/testing/GeolocationClientMock.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2012 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationClientMock_h +#define GeolocationClientMock_h + +#include "modules/geolocation/GeolocationClient.h" +#include "platform/Timer.h" +#include "platform/heap/Handle.h" +#include "wtf/HashSet.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class GeolocationController; +class GeolocationPosition; + +// Provides a mock object for the geolocation client. +class GeolocationClientMock : public GeolocationClient { +public: + GeolocationClientMock(); + virtual ~GeolocationClientMock(); + + void setPosition(GeolocationPosition*); + void setPositionUnavailableError(const String& errorMessage); + void setPermission(bool allowed); + int numberOfPendingPermissionRequests() const; + + // GeolocationClient + virtual void geolocationDestroyed() OVERRIDE; + virtual void startUpdating() OVERRIDE; + virtual void stopUpdating() OVERRIDE; + virtual void setEnableHighAccuracy(bool) OVERRIDE; + virtual GeolocationPosition* lastPosition() OVERRIDE; + virtual void requestPermission(Geolocation*) OVERRIDE; + virtual void cancelPermissionRequest(Geolocation*) OVERRIDE; + void controllerForTestAdded(GeolocationController*) OVERRIDE; + void controllerForTestRemoved(GeolocationController*) OVERRIDE; + +private: + void asyncUpdateController(); + void controllerTimerFired(Timer<GeolocationClientMock>*); + + void asyncUpdatePermission(); + void permissionTimerFired(Timer<GeolocationClientMock>*); + + void clearError(); + + typedef WillBeHeapHashSet<RawPtrWillBeMember<GeolocationController> > GeolocationControllers; + WillBePersistentHeapHashSet<RawPtrWillBeMember<GeolocationController> > m_controllers; + Persistent<GeolocationPosition> m_lastPosition; + bool m_hasError; + String m_errorMessage; + Timer<GeolocationClientMock> m_controllerTimer; + Timer<GeolocationClientMock> m_permissionTimer; + bool m_isActive; + + enum PermissionState { + PermissionStateUnset, + PermissionStateAllowed, + PermissionStateDenied + }; + + PermissionState m_permissionState; + typedef HeapHashSet<Member<Geolocation> > GeolocationSet; + PersistentHeapHashSet<Member<Geolocation> > m_pendingPermissions; +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/testing/InternalsGeolocation.cpp b/chromium/third_party/WebKit/Source/modules/geolocation/testing/InternalsGeolocation.cpp new file mode 100644 index 00000000000..a349b47576b --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/geolocation/testing/InternalsGeolocation.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InternalsGeolocation.h" + +#include "core/dom/Document.h" +#include "core/page/Page.h" +#include "core/testing/Internals.h" +#include "modules/geolocation/GeolocationController.h" +#include "modules/geolocation/GeolocationError.h" +#include "modules/geolocation/GeolocationPosition.h" +#include "modules/geolocation/testing/GeolocationClientMock.h" +#include "wtf/CurrentTime.h" + +namespace WebCore { + +void InternalsGeolocation::setGeolocationClientMock(Internals&, Document* document) +{ + ASSERT(document && document->frame()); + GeolocationClientMock* client = new GeolocationClientMock(); + + for (Frame* childFrame = document->page()->mainFrame(); childFrame; childFrame = childFrame->tree().traverseNext()) { + if (childFrame->isLocalFrame()) + GeolocationController::from(toLocalFrame(childFrame))->setClientForTest(client); + } +} + +void InternalsGeolocation::setGeolocationPosition(Internals&, Document* document, double latitude, double longitude, double accuracy) +{ + ASSERT(document && document->frame()); + GeolocationClientMock* client = geolocationClient(document); + if (!client) + return; + client->setPosition(GeolocationPosition::create(currentTime(), latitude, longitude, accuracy)); +} + +void InternalsGeolocation::setGeolocationPositionUnavailableError(Internals&, Document* document, const String& message) +{ + ASSERT(document && document->frame()); + GeolocationClientMock* client = geolocationClient(document); + if (!client) + return; + client->setPositionUnavailableError(message); +} + +void InternalsGeolocation::setGeolocationPermission(Internals&, Document* document, bool allowed) +{ + ASSERT(document && document->frame()); + GeolocationClientMock* client = geolocationClient(document); + if (!client) + return; + client->setPermission(allowed); +} + +int InternalsGeolocation::numberOfPendingGeolocationPermissionRequests(Internals&, Document* document) +{ + ASSERT(document && document->frame()); + GeolocationClientMock* client = geolocationClient(document); + if (!client) + return -1; + return client->numberOfPendingPermissionRequests(); +} + +GeolocationClientMock* InternalsGeolocation::geolocationClient(Document* document) +{ + GeolocationController* controller = GeolocationController::from(document->frame()); + if (!controller->hasClientForTest()) + return 0; + return static_cast<GeolocationClientMock*>(controller->client()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesCbcParams.h b/chromium/third_party/WebKit/Source/modules/geolocation/testing/InternalsGeolocation.h index 223ca2bd161..c76656758e2 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesCbcParams.h +++ b/chromium/third_party/WebKit/Source/modules/geolocation/testing/InternalsGeolocation.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,26 +28,30 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AesCbcParams_h -#define AesCbcParams_h +#ifndef InternalsGeolocation_h +#define InternalsGeolocation_h -#include "modules/crypto/Algorithm.h" -#include "wtf/Uint8Array.h" +#include "platform/Timer.h" +#include "wtf/text/WTFString.h" namespace WebCore { -class AesCbcParams : public Algorithm { -public: - static PassRefPtr<AesCbcParams> create(const blink::WebCryptoAlgorithm& algorithm) { return adoptRef(new AesCbcParams(algorithm)); } +class Document; +class GeolocationClientMock; +class Internals; - Uint8Array* iv(); +class InternalsGeolocation { +public: + static void setGeolocationClientMock(Internals&, Document*); + static void setGeolocationPosition(Internals&, Document*, double latitude, double longitude, double accuracy); + static void setGeolocationPositionUnavailableError(Internals&, Document*, const String& message); + static void setGeolocationPermission(Internals&, Document*, bool allowed); + static int numberOfPendingGeolocationPermissionRequests(Internals&, Document*); private: - explicit AesCbcParams(const blink::WebCryptoAlgorithm&); - - RefPtr<Uint8Array> m_iv; + static GeolocationClientMock* geolocationClient(Document*); }; } // namespace WebCore -#endif +#endif // InternalsGeolocation_h diff --git a/chromium/third_party/WebKit/Source/modules/geolocation/testing/InternalsGeolocation.idl b/chromium/third_party/WebKit/Source/modules/geolocation/testing/InternalsGeolocation.idl new file mode 100644 index 00000000000..ac6b2d34c1e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/geolocation/testing/InternalsGeolocation.idl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +partial interface Internals { + void setGeolocationClientMock(Document document); + void setGeolocationPosition(Document document, double latitude, double longitude, double accuracy); + void setGeolocationPositionUnavailableError(Document document, DOMString message); + void setGeolocationPermission(Document document, boolean allowed); + long numberOfPendingGeolocationPermissionRequests(Document document); +}; diff --git a/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.cpp b/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.cpp index ede92760472..5d994bf4c16 100644 --- a/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.cpp +++ b/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.cpp @@ -32,20 +32,23 @@ #include "modules/imagebitmap/ImageBitmapFactories.h" #include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptScope.h" +#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "core/dom/ExecutionContext.h" #include "core/fileapi/Blob.h" #include "core/html/HTMLCanvasElement.h" #include "core/html/HTMLImageElement.h" #include "core/html/HTMLVideoElement.h" #include "core/html/ImageData.h" #include "core/html/canvas/CanvasRenderingContext2D.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "core/frame/ImageBitmap.h" #include "core/workers/WorkerGlobalScope.h" #include "platform/SharedBuffer.h" #include "platform/graphics/BitmapImage.h" #include "platform/graphics/ImageSource.h" #include "platform/graphics/skia/NativeImageSkia.h" +#include <v8.h> namespace WebCore { @@ -58,206 +61,178 @@ static LayoutSize sizeFor(HTMLImageElement* image) static IntSize sizeFor(HTMLVideoElement* video) { - if (MediaPlayer* player = video->player()) - return player->naturalSize(); + if (blink::WebMediaPlayer* webMediaPlayer = video->webMediaPlayer()) + return webMediaPlayer->naturalSize(); return IntSize(); } -static ScriptPromise fulfillImageBitmap(ExecutionContext* context, PassRefPtr<ImageBitmap> imageBitmap) +static ScriptPromise fulfillImageBitmap(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ImageBitmap> imageBitmap) { - ScriptPromise promise = ScriptPromise::createPending(context); - RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(promise, context); - resolver->resolve(imageBitmap); + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + if (imageBitmap) { + resolver->resolve(imageBitmap); + } else { + resolver->reject(ScriptValue(scriptState, v8::Null(scriptState->isolate()))); + } return promise; } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, HTMLImageElement* image, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, HTMLImageElement* image, ExceptionState& exceptionState) { LayoutSize s = sizeFor(image); - return createImageBitmap(eventTarget, image, 0, 0, s.width(), s.height(), exceptionState); + return createImageBitmap(scriptState, eventTarget, image, 0, 0, s.width(), s.height(), exceptionState); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, HTMLImageElement* image, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, HTMLImageElement* image, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { // This variant does not work in worker threads. - ASSERT(eventTarget->toDOMWindow()); + ASSERT(eventTarget.toDOMWindow()); - if (!image) { - exceptionState.throwUninformativeAndGenericTypeError(); - return ScriptPromise(); - } if (!image->cachedImage()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "No image can be retrieved from the provided element."); return ScriptPromise(); } if (image->cachedImage()->image()->isSVGImage()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "The image element contains an SVG image, which is unsupported."); return ScriptPromise(); } if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } if (!image->cachedImage()->image()->currentFrameHasSingleSecurityOrigin()) { - exceptionState.throwSecurityError("the source image contains cross-origin image data."); + exceptionState.throwSecurityError("The source image contains image data from multiple origins."); return ScriptPromise(); } - if (!image->cachedImage()->passesAccessControlCheck(eventTarget->toDOMWindow()->document()->securityOrigin()) - && eventTarget->toDOMWindow()->document()->securityOrigin()->taintsCanvas(image->src())) { - exceptionState.throwSecurityError("cross-origin access to the source image is denied."); + if (!image->cachedImage()->passesAccessControlCheck(eventTarget.toDOMWindow()->document()->securityOrigin()) && eventTarget.toDOMWindow()->document()->securityOrigin()->taintsCanvas(image->src())) { + exceptionState.throwSecurityError("Cross-origin access to the source image is denied."); return ScriptPromise(); } // FIXME: make ImageBitmap creation asynchronous crbug.com/258082 - return fulfillImageBitmap(eventTarget->executionContext(), ImageBitmap::create(image, IntRect(sx, sy, sw, sh))); + return fulfillImageBitmap(scriptState, ImageBitmap::create(image, IntRect(sx, sy, sw, sh))); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, HTMLVideoElement* video, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, HTMLVideoElement* video, ExceptionState& exceptionState) { IntSize s = sizeFor(video); - return createImageBitmap(eventTarget, video, 0, 0, s.width(), s.height(), exceptionState); + return createImageBitmap(scriptState, eventTarget, video, 0, 0, s.width(), s.height(), exceptionState); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, HTMLVideoElement* video, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, HTMLVideoElement* video, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { // This variant does not work in worker threads. - ASSERT(eventTarget->toDOMWindow()); + ASSERT(eventTarget.toDOMWindow()); - if (!video) { - exceptionState.throwUninformativeAndGenericTypeError(); - return ScriptPromise(); - } - if (!video->player()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return ScriptPromise(); - } if (video->networkState() == HTMLMediaElement::NETWORK_EMPTY) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "The provided element has not retrieved data."); return ScriptPromise(); } - if (video->player()->readyState() <= MediaPlayer::HaveMetadata) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + // FIXME: Remove the below null check once we fix the bug 382721 + if (video->readyState() <= HTMLMediaElement::HAVE_METADATA || !video->webMediaPlayer()) { + exceptionState.throwDOMException(InvalidStateError, "The provided element's player has no current data."); return ScriptPromise(); } if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } if (!video->hasSingleSecurityOrigin()) { - exceptionState.throwSecurityError("the source video contains cross-origin image data."); + exceptionState.throwSecurityError("The source video contains image data from multiple origins."); return ScriptPromise(); } - if (!video->player()->didPassCORSAccessCheck() && eventTarget->toDOMWindow()->document()->securityOrigin()->taintsCanvas(video->currentSrc())) { - exceptionState.throwSecurityError("cross-origin access to the source video is denied."); + if (!video->webMediaPlayer()->didPassCORSAccessCheck() + && eventTarget.toDOMWindow()->document()->securityOrigin()->taintsCanvas(video->currentSrc())) { + exceptionState.throwSecurityError("Cross-origin access to the source video is denied."); return ScriptPromise(); } // FIXME: make ImageBitmap creation asynchronous crbug.com/258082 - return fulfillImageBitmap(eventTarget->executionContext(), ImageBitmap::create(video, IntRect(sx, sy, sw, sh))); + return fulfillImageBitmap(scriptState, ImageBitmap::create(video, IntRect(sx, sy, sw, sh))); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, CanvasRenderingContext2D* context, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, CanvasRenderingContext2D* context, ExceptionState& exceptionState) { - return createImageBitmap(eventTarget, context->canvas(), exceptionState); + return createImageBitmap(scriptState, eventTarget, context->canvas(), exceptionState); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, CanvasRenderingContext2D* context, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, CanvasRenderingContext2D* context, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { - return createImageBitmap(eventTarget, context->canvas(), sx, sy, sw, sh, exceptionState); + return createImageBitmap(scriptState, eventTarget, context->canvas(), sx, sy, sw, sh, exceptionState); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, HTMLCanvasElement* canvas, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, HTMLCanvasElement* canvas, ExceptionState& exceptionState) { - return createImageBitmap(eventTarget, canvas, 0, 0, canvas->width(), canvas->height(), exceptionState); + return createImageBitmap(scriptState, eventTarget, canvas, 0, 0, canvas->width(), canvas->height(), exceptionState); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, HTMLCanvasElement* canvas, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, HTMLCanvasElement* canvas, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { // This variant does not work in worker threads. - ASSERT(eventTarget->toDOMWindow()); + ASSERT(eventTarget.toDOMWindow()); - if (!canvas) { - exceptionState.throwUninformativeAndGenericTypeError(); - return ScriptPromise(); - } if (!canvas->originClean()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwSecurityError("The canvas element provided is tainted with cross-origin data."); return ScriptPromise(); } if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } + // FIXME: make ImageBitmap creation asynchronous crbug.com/258082 - return fulfillImageBitmap(eventTarget->executionContext(), ImageBitmap::create(canvas, IntRect(sx, sy, sw, sh))); + return fulfillImageBitmap(scriptState, canvas->buffer() ? ImageBitmap::create(canvas, IntRect(sx, sy, sw, sh)) : nullptr); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, Blob* blob, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Blob* blob, ExceptionState& exceptionState) { - if (!blob) { - exceptionState.throwUninformativeAndGenericDOMException(TypeError); - return ScriptPromise(); - } - ScriptPromise promise = ScriptPromise::createPending(eventTarget->executionContext()); - RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(promise, eventTarget->executionContext()); - RefPtr<ImageBitmapLoader> loader = ImageBitmapFactories::ImageBitmapLoader::create(from(eventTarget), resolver, IntRect()); - from(eventTarget)->addLoader(loader); - loader->loadBlobAsync(eventTarget->executionContext(), blob); + ImageBitmapLoader* loader = ImageBitmapFactories::ImageBitmapLoader::create(from(eventTarget), IntRect(), scriptState); + ScriptPromise promise = loader->promise(); + from(eventTarget).addLoader(loader); + loader->loadBlobAsync(eventTarget.executionContext(), blob); return promise; } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, Blob* blob, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Blob* blob, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { - if (!blob) { - exceptionState.throwUninformativeAndGenericDOMException(TypeError); - return ScriptPromise(); - } if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } - ScriptPromise promise = ScriptPromise::createPending(eventTarget->executionContext()); - RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(promise, eventTarget->executionContext()); - RefPtr<ImageBitmapLoader> loader = ImageBitmapFactories::ImageBitmapLoader::create(from(eventTarget), resolver, IntRect(sx, sy, sw, sh)); - from(eventTarget)->addLoader(loader); - loader->loadBlobAsync(eventTarget->executionContext(), blob); + ImageBitmapLoader* loader = ImageBitmapFactories::ImageBitmapLoader::create(from(eventTarget), IntRect(sx, sy, sw, sh), scriptState); + ScriptPromise promise = loader->promise(); + from(eventTarget).addLoader(loader); + loader->loadBlobAsync(eventTarget.executionContext(), blob); return promise; } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, ImageData* data, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, ImageData* data, ExceptionState& exceptionState) { - return createImageBitmap(eventTarget, data, 0, 0, data->width(), data->height(), exceptionState); + return createImageBitmap(scriptState, eventTarget, data, 0, 0, data->width(), data->height(), exceptionState); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, ImageData* data, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, ImageData* data, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { - if (!data) { - exceptionState.throwUninformativeAndGenericTypeError(); - return ScriptPromise(); - } if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } // FIXME: make ImageBitmap creation asynchronous crbug.com/258082 - return fulfillImageBitmap(eventTarget->executionContext(), ImageBitmap::create(data, IntRect(sx, sy, sw, sh))); + return fulfillImageBitmap(scriptState, ImageBitmap::create(data, IntRect(sx, sy, sw, sh))); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, ImageBitmap* bitmap, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, ImageBitmap* bitmap, ExceptionState& exceptionState) { - return createImageBitmap(eventTarget, bitmap, 0, 0, bitmap->width(), bitmap->height(), exceptionState); + return createImageBitmap(scriptState, eventTarget, bitmap, 0, 0, bitmap->width(), bitmap->height(), exceptionState); } -ScriptPromise ImageBitmapFactories::createImageBitmap(EventTarget* eventTarget, ImageBitmap* bitmap, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, ImageBitmap* bitmap, int sx, int sy, int sw, int sh, ExceptionState& exceptionState) { - if (!bitmap) { - exceptionState.throwUninformativeAndGenericTypeError(); - return ScriptPromise(); - } if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } // FIXME: make ImageBitmap creation asynchronous crbug.com/258082 - return fulfillImageBitmap(eventTarget->executionContext(), ImageBitmap::create(bitmap, IntRect(sx, sy, sw, sh))); + return fulfillImageBitmap(scriptState, ImageBitmap::create(bitmap, IntRect(sx, sy, sw, sh))); } const char* ImageBitmapFactories::supplementName() @@ -265,27 +240,27 @@ const char* ImageBitmapFactories::supplementName() return "ImageBitmapFactories"; } -ImageBitmapFactories* ImageBitmapFactories::from(EventTarget* eventTarget) +ImageBitmapFactories& ImageBitmapFactories::from(EventTarget& eventTarget) { - if (DOMWindow* window = eventTarget->toDOMWindow()) - return fromInternal(window); + if (LocalDOMWindow* window = eventTarget.toDOMWindow()) + return fromInternal(*window); - ASSERT(eventTarget->executionContext()->isWorkerGlobalScope()); - return fromInternal(toWorkerGlobalScope(eventTarget->executionContext())); + ASSERT(eventTarget.executionContext()->isWorkerGlobalScope()); + return ImageBitmapFactories::fromInternal(*toWorkerGlobalScope(eventTarget.executionContext())); } -template <class T> -ImageBitmapFactories* ImageBitmapFactories::fromInternal(T* object) +template<class GlobalObject> +ImageBitmapFactories& ImageBitmapFactories::fromInternal(GlobalObject& object) { - ImageBitmapFactories* supplement = static_cast<ImageBitmapFactories*>(Supplement<T>::from(object, supplementName())); + ImageBitmapFactories* supplement = static_cast<ImageBitmapFactories*>(WillBeHeapSupplement<GlobalObject>::from(object, supplementName())); if (!supplement) { supplement = new ImageBitmapFactories(); - Supplement<T>::provideTo(object, supplementName(), adoptPtr(supplement)); + WillBeHeapSupplement<GlobalObject>::provideTo(object, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -void ImageBitmapFactories::addLoader(PassRefPtr<ImageBitmapLoader> loader) +void ImageBitmapFactories::addLoader(ImageBitmapLoader* loader) { m_pendingLoaders.add(loader); } @@ -296,11 +271,10 @@ void ImageBitmapFactories::didFinishLoading(ImageBitmapLoader* loader) m_pendingLoaders.remove(loader); } -ImageBitmapFactories::ImageBitmapLoader::ImageBitmapLoader(ImageBitmapFactories* factory, PassRefPtr<ScriptPromiseResolver> resolver, const IntRect& cropRect) - : m_scriptState(ScriptState::current()) - , m_loader(FileReaderLoader::ReadAsArrayBuffer, this) - , m_factory(factory) - , m_resolver(resolver) +ImageBitmapFactories::ImageBitmapLoader::ImageBitmapLoader(ImageBitmapFactories& factory, const IntRect& cropRect, ScriptState* scriptState) + : m_loader(FileReaderLoader::ReadAsArrayBuffer, this) + , m_factory(&factory) + , m_resolver(ScriptPromiseResolverWithContext::create(scriptState)) , m_cropRect(cropRect) { } @@ -310,11 +284,16 @@ void ImageBitmapFactories::ImageBitmapLoader::loadBlobAsync(ExecutionContext* co m_loader.start(context, blob->blobDataHandle()); } +void ImageBitmapFactories::trace(Visitor* visitor) +{ + visitor->trace(m_pendingLoaders); + WillBeHeapSupplement<LocalDOMWindow>::trace(visitor); + WillBeHeapSupplement<WorkerGlobalScope>::trace(visitor); +} + void ImageBitmapFactories::ImageBitmapLoader::rejectPromise() { - v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_resolver->reject(ScriptValue(v8::Null(isolate), isolate)); + m_resolver->reject(ScriptValue(m_resolver->scriptState(), v8::Null(m_resolver->scriptState()->isolate()))); m_factory->didFinishLoading(this); } @@ -327,7 +306,7 @@ void ImageBitmapFactories::ImageBitmapLoader::didFinishLoading() RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create((char*)m_loader.arrayBufferResult()->data(), m_loader.arrayBufferResult()->byteLength()); OwnPtr<ImageSource> source = adoptPtr(new ImageSource()); - source->setData(sharedBuffer.get(), true); + source->setData(*sharedBuffer, true); RefPtr<NativeImageSkia> imageSkia = source->createFrameAtIndex(0); if (!imageSkia) { rejectPromise(); @@ -344,8 +323,7 @@ void ImageBitmapFactories::ImageBitmapLoader::didFinishLoading() m_cropRect = IntRect(IntPoint(), image->size()); } - RefPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), m_cropRect); - ScriptScope scope(m_scriptState); + RefPtrWillBeRawPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), m_cropRect); m_resolver->resolve(imageBitmap.release()); m_factory->didFinishLoading(this); } @@ -355,4 +333,9 @@ void ImageBitmapFactories::ImageBitmapLoader::didFail(FileError::ErrorCode) rejectPromise(); } +void ImageBitmapFactories::ImageBitmapLoader::trace(Visitor* visitor) +{ + visitor->trace(m_factory); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.h b/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.h index 99420f3496a..54357bdcce2 100644 --- a/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.h +++ b/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.h @@ -32,11 +32,10 @@ #define ImageBitmapFactories_h #include "bindings/v8/ScriptPromise.h" -#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" #include "bindings/v8/ScriptState.h" #include "core/fileapi/FileReaderLoader.h" #include "core/fileapi/FileReaderLoaderClient.h" -#include "core/workers/WorkerSupplementable.h" #include "platform/Supplementable.h" #include "platform/geometry/IntRect.h" #include "wtf/Forward.h" @@ -55,44 +54,49 @@ class ImageBitmap; class ImageData; class ExecutionContext; -class ImageBitmapFactories : public Supplement<DOMWindow>, public WorkerSupplement { - -class ImageBitmapLoader; +class ImageBitmapFactories FINAL : public NoBaseWillBeGarbageCollectedFinalized<ImageBitmapFactories>, public WillBeHeapSupplement<LocalDOMWindow>, public WillBeHeapSupplement<WorkerGlobalScope> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(ImageBitmapFactories); public: - static ScriptPromise createImageBitmap(EventTarget*, HTMLImageElement*, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, HTMLImageElement*, int sx, int sy, int sw, int sh, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, HTMLVideoElement*, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, HTMLVideoElement*, int sx, int sy, int sw, int sh, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, CanvasRenderingContext2D*, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, CanvasRenderingContext2D*, int sx, int sy, int sw, int sh, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, HTMLCanvasElement*, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, HTMLCanvasElement*, int sx, int sy, int sw, int sh, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, Blob*, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, Blob*, int sx, int sy, int sw, int sh, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, ImageData*, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, ImageData*, int sx, int sy, int sw, int sh, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, ImageBitmap*, ExceptionState&); - static ScriptPromise createImageBitmap(EventTarget*, ImageBitmap*, int sx, int sy, int sw, int sh, ExceptionState&); - - void didFinishLoading(ImageBitmapLoader*); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, HTMLImageElement*, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, HTMLImageElement*, int sx, int sy, int sw, int sh, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, HTMLVideoElement*, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, HTMLVideoElement*, int sx, int sy, int sw, int sh, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, CanvasRenderingContext2D*, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, CanvasRenderingContext2D*, int sx, int sy, int sw, int sh, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, HTMLCanvasElement*, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, HTMLCanvasElement*, int sx, int sy, int sw, int sh, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, Blob*, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, Blob*, int sx, int sy, int sw, int sh, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, ImageData*, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, ImageData*, int sx, int sy, int sw, int sh, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, ImageBitmap*, ExceptionState&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, ImageBitmap*, int sx, int sy, int sw, int sh, ExceptionState&); virtual ~ImageBitmapFactories() { } + void trace(Visitor*); + +protected: + static const char* supplementName(); + private: - class ImageBitmapLoader : public RefCounted<ImageBitmapLoader>, public FileReaderLoaderClient { + class ImageBitmapLoader FINAL : public GarbageCollectedFinalized<ImageBitmapLoader>, public FileReaderLoaderClient { public: - static PassRefPtr<ImageBitmapLoader> create(ImageBitmapFactories* factory, PassRefPtr<ScriptPromiseResolver> resolver, const IntRect& cropRect) + static ImageBitmapLoader* create(ImageBitmapFactories& factory, const IntRect& cropRect, ScriptState* scriptState) { - return adoptRef(new ImageBitmapLoader(factory, resolver, cropRect)); + return new ImageBitmapLoader(factory, cropRect, scriptState); } void loadBlobAsync(ExecutionContext*, Blob*); + ScriptPromise promise() { return m_resolver->promise(); } + + void trace(Visitor*); - ~ImageBitmapLoader() { } + virtual ~ImageBitmapLoader() { } private: - ImageBitmapLoader(ImageBitmapFactories*, PassRefPtr<ScriptPromiseResolver>, const IntRect&); + ImageBitmapLoader(ImageBitmapFactories&, const IntRect&, ScriptState*); void rejectPromise(); @@ -102,22 +106,21 @@ private: virtual void didFinishLoading() OVERRIDE; virtual void didFail(FileError::ErrorCode) OVERRIDE; - ScriptState* m_scriptState; FileReaderLoader m_loader; - ImageBitmapFactories* m_factory; - RefPtr<ScriptPromiseResolver> m_resolver; + RawPtrWillBeMember<ImageBitmapFactories> m_factory; + RefPtr<ScriptPromiseResolverWithContext> m_resolver; IntRect m_cropRect; }; - static const char* supplementName(); - static ImageBitmapFactories* from(EventTarget*); + static ImageBitmapFactories& from(EventTarget&); - template <class T> - static ImageBitmapFactories* fromInternal(T*); + template<class GlobalObject> + static ImageBitmapFactories& fromInternal(GlobalObject&); - void addLoader(PassRefPtr<ImageBitmapLoader>); + void addLoader(ImageBitmapLoader*); + void didFinishLoading(ImageBitmapLoader*); - HashSet<RefPtr<ImageBitmapLoader> > m_pendingLoaders; + PersistentHeapHashSetWillBeHeapHashSet<Member<ImageBitmapLoader> > m_pendingLoaders; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.idl b/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.idl index 7f244e10734..f095d8c13d2 100644 --- a/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.idl +++ b/chromium/third_party/WebKit/Source/modules/imagebitmap/ImageBitmapFactories.idl @@ -28,14 +28,34 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/#imagebitmapfactories + +// FIXME: should use typedef instead, but +// requires better union type support: http://crbug.com/240176 +/* +typedef (// HTMLImageElement or + // HTMLVideoElement or + // HTMLCanvasElement or + Blob or + ImageData or + // CanvasRenderingContext2D or + ImageBitmap) ImageBitmapSource; +*/ + [ - NoInterfaceObject, - RuntimeEnabled=ExperimentalCanvasFeatures + LegacyTreatAsPartialInterface, + NoInterfaceObject, // Always used on target of 'implements' + RuntimeEnabled=ExperimentalCanvasFeatures, + TypeChecking=Interface|Nullable, ] interface ImageBitmapFactories { - [RaisesException] Promise createImageBitmap(Blob blob); - [RaisesException] Promise createImageBitmap(Blob blob, long sx, long sy, long sw, long sh); - [RaisesException] Promise createImageBitmap(ImageData data); - [RaisesException] Promise createImageBitmap(ImageData data, long sx, long sy, long sw, long sh); - [RaisesException] Promise createImageBitmap(ImageBitmap bitmap); - [RaisesException] Promise createImageBitmap(ImageBitmap bitmap, long sx, long sy, long sw, long sh); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(Blob blob); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(Blob blob, long sx, long sy, long sw, long sh); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(ImageData data); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(ImageData data, long sx, long sy, long sw, long sh); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(ImageBitmap bitmap); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(ImageBitmap bitmap, long sx, long sy, long sw, long sh); }; + +Window implements ImageBitmapFactories; +WorkerGlobalScope implements ImageBitmapFactories; + diff --git a/chromium/third_party/WebKit/Source/modules/imagebitmap/WindowImageBitmapFactories.idl b/chromium/third_party/WebKit/Source/modules/imagebitmap/WindowImageBitmapFactories.idl index ced1ff8e6a7..f7b85df1b1f 100644 --- a/chromium/third_party/WebKit/Source/modules/imagebitmap/WindowImageBitmapFactories.idl +++ b/chromium/third_party/WebKit/Source/modules/imagebitmap/WindowImageBitmapFactories.idl @@ -30,14 +30,15 @@ [ ImplementedAs=ImageBitmapFactories, - RuntimeEnabled=ExperimentalCanvasFeatures + RuntimeEnabled=ExperimentalCanvasFeatures, + TypeChecking=Interface|Nullable, ] partial interface Window { - [RaisesException] Promise createImageBitmap(HTMLImageElement image); - [RaisesException] Promise createImageBitmap(HTMLImageElement image, long sx, long sy, long sw, long sh); - [RaisesException] Promise createImageBitmap(HTMLVideoElement video); - [RaisesException] Promise createImageBitmap(HTMLVideoElement video, long sx, long sy, long sw, long sh); - [RaisesException] Promise createImageBitmap(CanvasRenderingContext2D context); - [RaisesException] Promise createImageBitmap(CanvasRenderingContext2D context, long sx, long sy, long sw, long sh); - [RaisesException] Promise createImageBitmap(HTMLCanvasElement canvas); - [RaisesException] Promise createImageBitmap(HTMLCanvasElement canvas, long sx, long sy, long sw, long sh); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(HTMLImageElement image); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(HTMLImageElement image, long sx, long sy, long sw, long sh); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(HTMLVideoElement video); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(HTMLVideoElement video, long sx, long sy, long sw, long sh); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(CanvasRenderingContext2D context); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(CanvasRenderingContext2D context, long sx, long sy, long sw, long sh); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(HTMLCanvasElement canvas); + [CallWith=ScriptState, RaisesException] Promise createImageBitmap(HTMLCanvasElement canvas, long sx, long sy, long sw, long sh); }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/DOMWindowIndexedDatabase.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/DOMWindowIndexedDatabase.cpp index b77178acf4d..d6220d77582 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/DOMWindowIndexedDatabase.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/DOMWindowIndexedDatabase.cpp @@ -27,15 +27,14 @@ #include "modules/indexeddb/DOMWindowIndexedDatabase.h" #include "core/dom/Document.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "core/page/Page.h" #include "modules/indexeddb/IDBFactory.h" -#include "modules/indexeddb/PageGroupIndexedDatabase.h" namespace WebCore { -DOMWindowIndexedDatabase::DOMWindowIndexedDatabase(DOMWindow* window) - : DOMWindowProperty(window->frame()) +DOMWindowIndexedDatabase::DOMWindowIndexedDatabase(LocalDOMWindow& window) + : DOMWindowProperty(window.frame()) , m_window(window) { } @@ -44,19 +43,25 @@ DOMWindowIndexedDatabase::~DOMWindowIndexedDatabase() { } +void DOMWindowIndexedDatabase::trace(Visitor* visitor) +{ + visitor->trace(m_idbFactory); + WillBeHeapSupplement<LocalDOMWindow>::trace(visitor); +} + const char* DOMWindowIndexedDatabase::supplementName() { return "DOMWindowIndexedDatabase"; } -DOMWindowIndexedDatabase* DOMWindowIndexedDatabase::from(DOMWindow* window) +DOMWindowIndexedDatabase& DOMWindowIndexedDatabase::from(LocalDOMWindow& window) { - DOMWindowIndexedDatabase* supplement = static_cast<DOMWindowIndexedDatabase*>(Supplement<DOMWindow>::from(window, supplementName())); + DOMWindowIndexedDatabase* supplement = static_cast<DOMWindowIndexedDatabase*>(WillBeHeapSupplement<LocalDOMWindow>::from(window, supplementName())); if (!supplement) { supplement = new DOMWindowIndexedDatabase(window); - provideTo(window, supplementName(), adoptPtr(supplement)); + provideTo(window, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } void DOMWindowIndexedDatabase::willDestroyGlobalObjectInFrame() @@ -71,14 +76,14 @@ void DOMWindowIndexedDatabase::willDetachGlobalObjectFromFrame() DOMWindowProperty::willDetachGlobalObjectFromFrame(); } -IDBFactory* DOMWindowIndexedDatabase::indexedDB(DOMWindow* window) +IDBFactory* DOMWindowIndexedDatabase::indexedDB(LocalDOMWindow& window) { - return from(window)->indexedDB(); + return from(window).indexedDB(); } IDBFactory* DOMWindowIndexedDatabase::indexedDB() { - Document* document = m_window->document(); + Document* document = m_window.document(); if (!document) return 0; @@ -86,11 +91,11 @@ IDBFactory* DOMWindowIndexedDatabase::indexedDB() if (!page) return 0; - if (!m_window->isCurrentlyDisplayedInFrame()) + if (!m_window.isCurrentlyDisplayedInFrame()) return 0; if (!m_idbFactory) - m_idbFactory = IDBFactory::create(PageGroupIndexedDatabase::from(page->group())->factoryBackend()); + m_idbFactory = IDBFactory::create(IndexedDBClient::create()); return m_idbFactory.get(); } diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/DOMWindowIndexedDatabase.h b/chromium/third_party/WebKit/Source/modules/indexeddb/DOMWindowIndexedDatabase.h index 032fbf31883..e8e6725fa59 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/DOMWindowIndexedDatabase.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/DOMWindowIndexedDatabase.h @@ -27,31 +27,35 @@ #define DOMWindowIndexedDatabase_h #include "core/frame/DOMWindowProperty.h" +#include "modules/indexeddb/IndexedDBClient.h" #include "platform/Supplementable.h" namespace WebCore { class IDBFactory; -class DOMWindow; +class LocalDOMWindow; -class DOMWindowIndexedDatabase : public DOMWindowProperty, public Supplement<DOMWindow> { +class DOMWindowIndexedDatabase FINAL : public NoBaseWillBeGarbageCollectedFinalized<DOMWindowIndexedDatabase>, public WillBeHeapSupplement<LocalDOMWindow>, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DOMWindowIndexedDatabase); public: virtual ~DOMWindowIndexedDatabase(); - static DOMWindowIndexedDatabase* from(DOMWindow*); + static DOMWindowIndexedDatabase& from(LocalDOMWindow&); - static IDBFactory* indexedDB(DOMWindow*); + static IDBFactory* indexedDB(LocalDOMWindow&); virtual void willDestroyGlobalObjectInFrame() OVERRIDE; virtual void willDetachGlobalObjectFromFrame() OVERRIDE; + void trace(Visitor*); + private: - explicit DOMWindowIndexedDatabase(DOMWindow*); + explicit DOMWindowIndexedDatabase(LocalDOMWindow&); IDBFactory* indexedDB(); static const char* supplementName(); - DOMWindow* m_window; - RefPtr<IDBFactory> m_idbFactory; + LocalDOMWindow& m_window; + PersistentWillBeMember<IDBFactory> m_idbFactory; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBAny.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBAny.cpp index 956bd2258e0..f19bcc1f7b6 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBAny.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBAny.cpp @@ -34,19 +34,19 @@ namespace WebCore { -PassRefPtr<IDBAny> IDBAny::createUndefined() +IDBAny* IDBAny::createUndefined() { - return adoptRef(new IDBAny(UndefinedType)); + return new IDBAny(UndefinedType); } -PassRefPtr<IDBAny> IDBAny::createNull() +IDBAny* IDBAny::createNull() { - return adoptRef(new IDBAny(NullType)); + return new IDBAny(NullType); } -PassRefPtr<IDBAny> IDBAny::createString(const String& value) +IDBAny* IDBAny::createString(const String& value) { - return adoptRef(new IDBAny(value)); + return new IDBAny(value); } IDBAny::IDBAny(Type type) @@ -60,6 +60,12 @@ IDBAny::~IDBAny() { } +void IDBAny::contextWillBeDestroyed() +{ + if (m_idbCursor) + m_idbCursor->contextWillBeDestroyed(); +} + DOMStringList* IDBAny::domStringList() const { ASSERT(m_type == DOMStringListType); @@ -122,6 +128,12 @@ SharedBuffer* IDBAny::buffer() const return m_buffer.get(); } +const Vector<blink::WebBlobInfo>* IDBAny::blobInfo() const +{ + ASSERT(m_type == BufferType || m_type == BufferKeyAndKeyPathType); + return m_blobInfo; +} + const String& IDBAny::string() const { ASSERT(m_type == StringType); @@ -134,65 +146,67 @@ int64_t IDBAny::integer() const return m_integer; } -IDBAny::IDBAny(PassRefPtr<DOMStringList> value) +IDBAny::IDBAny(PassRefPtrWillBeRawPtr<DOMStringList> value) : m_type(DOMStringListType) , m_domStringList(value) , m_integer(0) { } -IDBAny::IDBAny(PassRefPtr<IDBCursor> value) +IDBAny::IDBAny(IDBCursor* value) : m_type(value->isCursorWithValue() ? IDBCursorWithValueType : IDBCursorType) , m_idbCursor(value) , m_integer(0) { } -IDBAny::IDBAny(PassRefPtr<IDBDatabase> value) +IDBAny::IDBAny(IDBDatabase* value) : m_type(IDBDatabaseType) , m_idbDatabase(value) , m_integer(0) { } -IDBAny::IDBAny(PassRefPtr<IDBIndex> value) +IDBAny::IDBAny(IDBIndex* value) : m_type(IDBIndexType) , m_idbIndex(value) , m_integer(0) { } -IDBAny::IDBAny(PassRefPtr<IDBTransaction> value) +IDBAny::IDBAny(IDBTransaction* value) : m_type(IDBTransactionType) , m_idbTransaction(value) , m_integer(0) { } -IDBAny::IDBAny(PassRefPtr<IDBObjectStore> value) +IDBAny::IDBAny(IDBObjectStore* value) : m_type(IDBObjectStoreType) , m_idbObjectStore(value) , m_integer(0) { } -IDBAny::IDBAny(PassRefPtr<SharedBuffer> value) +IDBAny::IDBAny(PassRefPtr<SharedBuffer> value, const Vector<blink::WebBlobInfo>* blobInfo) : m_type(BufferType) , m_buffer(value) + , m_blobInfo(blobInfo) , m_integer(0) { } -IDBAny::IDBAny(PassRefPtr<SharedBuffer> value, PassRefPtr<IDBKey> key, const IDBKeyPath& keyPath) +IDBAny::IDBAny(PassRefPtr<SharedBuffer> value, const Vector<blink::WebBlobInfo>* blobInfo, IDBKey* key, const IDBKeyPath& keyPath) : m_type(BufferKeyAndKeyPathType) , m_idbKey(key) , m_idbKeyPath(keyPath) , m_buffer(value) + , m_blobInfo(blobInfo) , m_integer(0) { } -IDBAny::IDBAny(PassRefPtr<IDBKey> key) +IDBAny::IDBAny(IDBKey* key) : m_type(KeyType) , m_idbKey(key) , m_integer(0) @@ -219,4 +233,15 @@ IDBAny::IDBAny(int64_t value) { } +void IDBAny::trace(Visitor* visitor) +{ + visitor->trace(m_domStringList); + visitor->trace(m_idbCursor); + visitor->trace(m_idbDatabase); + visitor->trace(m_idbIndex); + visitor->trace(m_idbObjectStore); + visitor->trace(m_idbTransaction); + visitor->trace(m_idbKey); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBAny.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBAny.h index 2a94777b4c3..f9c8141f6c1 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBAny.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBAny.h @@ -35,6 +35,12 @@ #include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" +namespace blink { + +class WebBlobInfo; + +} + namespace WebCore { class DOMStringList; @@ -46,35 +52,41 @@ class IDBKeyPath; class IDBObjectStore; class IDBTransaction; -class IDBAny : public RefCounted<IDBAny> { +class IDBAny : public GarbageCollectedFinalized<IDBAny> { public: - static PassRefPtr<IDBAny> createUndefined(); - static PassRefPtr<IDBAny> createNull(); - static PassRefPtr<IDBAny> createString(const String&); + static IDBAny* createUndefined(); + static IDBAny* createNull(); + static IDBAny* createString(const String&); template<typename T> - static PassRefPtr<IDBAny> create(T* idbObject) + static IDBAny* create(T* idbObject) { - return adoptRef(new IDBAny(idbObject)); + return new IDBAny(idbObject); } template<typename T> - static PassRefPtr<IDBAny> create(const T& idbObject) + static IDBAny* create(const T& idbObject) + { + return new IDBAny(idbObject); + } + static IDBAny* create(PassRefPtr<SharedBuffer> value, const Vector<blink::WebBlobInfo>* blobInfo) { - return adoptRef(new IDBAny(idbObject)); + return new IDBAny(value, blobInfo); } template<typename T> - static PassRefPtr<IDBAny> create(PassRefPtr<T> idbObject) + static IDBAny* create(PassRefPtr<T> idbObject) { - return adoptRef(new IDBAny(idbObject)); + return new IDBAny(idbObject); } - static PassRefPtr<IDBAny> create(int64_t value) + static IDBAny* create(int64_t value) { - return adoptRef(new IDBAny(value)); + return new IDBAny(value); } - static PassRefPtr<IDBAny> create(PassRefPtr<SharedBuffer> value, PassRefPtr<IDBKey> key, const IDBKeyPath& keyPath) + static IDBAny* create(PassRefPtr<SharedBuffer> value, const Vector<blink::WebBlobInfo>* blobInfo, IDBKey* key, const IDBKeyPath& keyPath) { - return adoptRef(new IDBAny(value, key, keyPath)); + return new IDBAny(value, blobInfo, key, keyPath); } ~IDBAny(); + void trace(Visitor*); + void contextWillBeDestroyed(); enum Type { UndefinedType = 0, @@ -104,6 +116,7 @@ public: IDBObjectStore* idbObjectStore() const; IDBTransaction* idbTransaction() const; SharedBuffer* buffer() const; + const Vector<blink::WebBlobInfo>* blobInfo() const; int64_t integer() const; const String& string() const; const IDBKey* key() const; @@ -111,31 +124,32 @@ public: private: explicit IDBAny(Type); - explicit IDBAny(PassRefPtr<DOMStringList>); - explicit IDBAny(PassRefPtr<IDBCursor>); - explicit IDBAny(PassRefPtr<IDBDatabase>); - explicit IDBAny(PassRefPtr<IDBIndex>); - explicit IDBAny(PassRefPtr<IDBObjectStore>); - explicit IDBAny(PassRefPtr<IDBTransaction>); - explicit IDBAny(PassRefPtr<IDBKey>); + explicit IDBAny(PassRefPtrWillBeRawPtr<DOMStringList>); + explicit IDBAny(IDBCursor*); + explicit IDBAny(IDBDatabase*); + explicit IDBAny(IDBIndex*); + explicit IDBAny(IDBObjectStore*); + explicit IDBAny(IDBTransaction*); + explicit IDBAny(IDBKey*); explicit IDBAny(const IDBKeyPath&); explicit IDBAny(const String&); - explicit IDBAny(PassRefPtr<SharedBuffer>); - explicit IDBAny(PassRefPtr<SharedBuffer>, PassRefPtr<IDBKey>, const IDBKeyPath&); + IDBAny(PassRefPtr<SharedBuffer>, const Vector<blink::WebBlobInfo>*); + IDBAny(PassRefPtr<SharedBuffer>, const Vector<blink::WebBlobInfo>*, IDBKey*, const IDBKeyPath&); explicit IDBAny(int64_t); const Type m_type; - // Only one of the following should ever be in use at any given time. - const RefPtr<DOMStringList> m_domStringList; - const RefPtr<IDBCursor> m_idbCursor; - const RefPtr<IDBDatabase> m_idbDatabase; - const RefPtr<IDBIndex> m_idbIndex; - const RefPtr<IDBObjectStore> m_idbObjectStore; - const RefPtr<IDBTransaction> m_idbTransaction; - const RefPtr<IDBKey> m_idbKey; + // Only one of the following should ever be in use at any given time, except that BufferType uses two and BufferKeyAndKeyPathType uses four. + const RefPtrWillBeMember<DOMStringList> m_domStringList; + const Member<IDBCursor> m_idbCursor; + const Member<IDBDatabase> m_idbDatabase; + const Member<IDBIndex> m_idbIndex; + const Member<IDBObjectStore> m_idbObjectStore; + const Member<IDBTransaction> m_idbTransaction; + const Member<IDBKey> m_idbKey; const IDBKeyPath m_idbKeyPath; const RefPtr<SharedBuffer> m_buffer; + const Vector<blink::WebBlobInfo>* m_blobInfo; const String m_string; const int64_t m_integer; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp index 8ea735858c5..2c79769e2c5 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp @@ -28,6 +28,7 @@ #include "bindings/v8/ExceptionState.h" #include "bindings/v8/IDBBindingUtilities.h" +#include "bindings/v8/ScriptState.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" #include "core/inspector/ScriptCallStack.h" @@ -37,17 +38,19 @@ #include "modules/indexeddb/IDBTracing.h" #include "modules/indexeddb/IDBTransaction.h" #include "modules/indexeddb/WebIDBCallbacksImpl.h" +#include "public/platform/WebBlobInfo.h" #include "public/platform/WebIDBDatabase.h" #include "public/platform/WebIDBKeyRange.h" #include <limits> +using blink::WebIDBCursor; using blink::WebIDBDatabase; namespace WebCore { -PassRefPtr<IDBCursor> IDBCursor::create(PassOwnPtr<blink::WebIDBCursor> backend, IndexedDB::CursorDirection direction, IDBRequest* request, IDBAny* source, IDBTransaction* transaction) +IDBCursor* IDBCursor::create(PassOwnPtr<blink::WebIDBCursor> backend, blink::WebIDBCursorDirection direction, IDBRequest* request, IDBAny* source, IDBTransaction* transaction) { - return adoptRef(new IDBCursor(backend, direction, request, source, transaction)); + return new IDBCursor(backend, direction, request, source, transaction); } const AtomicString& IDBCursor::directionNext() @@ -74,7 +77,7 @@ const AtomicString& IDBCursor::directionPrevUnique() return prevunique; } -IDBCursor::IDBCursor(PassOwnPtr<blink::WebIDBCursor> backend, IndexedDB::CursorDirection direction, IDBRequest* request, IDBAny* source, IDBTransaction* transaction) +IDBCursor::IDBCursor(PassOwnPtr<blink::WebIDBCursor> backend, blink::WebIDBCursorDirection direction, IDBRequest* request, IDBAny* source, IDBTransaction* transaction) : m_backend(backend) , m_request(request) , m_direction(direction) @@ -94,9 +97,19 @@ IDBCursor::IDBCursor(PassOwnPtr<blink::WebIDBCursor> backend, IndexedDB::CursorD IDBCursor::~IDBCursor() { + handleBlobAcks(); } -PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value, ExceptionState& exceptionState) +void IDBCursor::trace(Visitor* visitor) +{ + visitor->trace(m_request); + visitor->trace(m_source); + visitor->trace(m_transaction); + visitor->trace(m_key); + visitor->trace(m_primaryKey); +} + +IDBRequest* IDBCursor::update(ScriptState* scriptState, ScriptValue& value, ExceptionState& exceptionState) { IDB_TRACE("IDBCursor::update"); @@ -112,7 +125,7 @@ PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value, exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -125,23 +138,27 @@ PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value, return 0; } - RefPtr<IDBObjectStore> objectStore = effectiveObjectStore(); + IDBObjectStore* objectStore = effectiveObjectStore(); const IDBKeyPath& keyPath = objectStore->metadata().keyPath; const bool usesInLineKeys = !keyPath.isNull(); if (usesInLineKeys) { - RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(m_request->requestState(), value, keyPath); + IDBKey* keyPathKey = createIDBKeyFromScriptValueAndKeyPath(scriptState->isolate(), value, keyPath); if (!keyPathKey || !keyPathKey->isEqual(m_primaryKey.get())) { exceptionState.throwDOMException(DataError, "The effective object store of this cursor uses in-line keys and evaluating the key path of the value parameter results in a different value than the cursor's effective key."); return 0; } } - return objectStore->put(WebIDBDatabase::CursorUpdate, IDBAny::create(this), state, value, m_primaryKey, exceptionState); + return objectStore->put(scriptState, blink::WebIDBPutModeCursorUpdate, IDBAny::create(this), value, m_primaryKey, exceptionState); } void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) { IDB_TRACE("IDBCursor::advance"); + if (!count) { + exceptionState.throwTypeError("A count argument with value 0 (zero) was supplied, must be greater than 0."); + return; + } if (!m_gotValue) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValueErrorMessage); return; @@ -151,7 +168,7 @@ void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) return; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return; } @@ -160,46 +177,39 @@ void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) return; } - if (!count) { - exceptionState.throwUninformativeAndGenericTypeError(); - return; - } - m_request->setPendingCursor(this); m_gotValue = false; m_backend->advance(count, WebIDBCallbacksImpl::create(m_request).leakPtr()); } -void IDBCursor::continueFunction(ExecutionContext* context, const ScriptValue& keyValue, ExceptionState& exceptionState) +void IDBCursor::continueFunction(ScriptState* scriptState, const ScriptValue& keyValue, ExceptionState& exceptionState) { IDB_TRACE("IDBCursor::continue"); - DOMRequestState requestState(context); - RefPtr<IDBKey> key = keyValue.isUndefined() || keyValue.isNull() ? 0 : scriptValueToIDBKey(&requestState, keyValue); + IDBKey* key = keyValue.isUndefined() || keyValue.isNull() ? nullptr : scriptValueToIDBKey(scriptState->isolate(), keyValue); if (key && !key->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return; } - continueFunction(key.release(), 0, exceptionState); + continueFunction(key, 0, exceptionState); } -void IDBCursor::continuePrimaryKey(ExecutionContext* context, const ScriptValue& keyValue, const ScriptValue& primaryKeyValue, ExceptionState& exceptionState) +void IDBCursor::continuePrimaryKey(ScriptState* scriptState, const ScriptValue& keyValue, const ScriptValue& primaryKeyValue, ExceptionState& exceptionState) { IDB_TRACE("IDBCursor::continuePrimaryKey"); - DOMRequestState requestState(context); - RefPtr<IDBKey> key = scriptValueToIDBKey(&requestState, keyValue); - RefPtr<IDBKey> primaryKey = scriptValueToIDBKey(&requestState, primaryKeyValue); + IDBKey* key = scriptValueToIDBKey(scriptState->isolate(), keyValue); + IDBKey* primaryKey = scriptValueToIDBKey(scriptState->isolate(), primaryKeyValue); if (!key->isValid() || !primaryKey->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return; } - continueFunction(key.release(), primaryKey.release(), exceptionState); + continueFunction(key, primaryKey, exceptionState); } -void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, ExceptionState& exceptionState) +void IDBCursor::continueFunction(IDBKey* key, IDBKey* primaryKey, ExceptionState& exceptionState) { ASSERT(!primaryKey || (key && primaryKey)); - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return; } @@ -220,9 +230,9 @@ void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> prim if (key) { ASSERT(m_key); - if (m_direction == IndexedDB::CursorNext || m_direction == IndexedDB::CursorNextNoDuplicate) { - const bool ok = m_key->isLessThan(key.get()) - || (primaryKey && m_key->isEqual(key.get()) && m_primaryKey->isLessThan(primaryKey.get())); + if (m_direction == blink::WebIDBCursorDirectionNext || m_direction == blink::WebIDBCursorDirectionNextNoDuplicate) { + const bool ok = m_key->isLessThan(key) + || (primaryKey && m_key->isEqual(key) && m_primaryKey->isLessThan(primaryKey)); if (!ok) { exceptionState.throwDOMException(DataError, "The parameter is less than or equal to this cursor's position."); return; @@ -245,10 +255,10 @@ void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> prim m_backend->continueFunction(key, primaryKey, WebIDBCallbacksImpl::create(m_request).leakPtr()); } -PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ExecutionContext* context, ExceptionState& exceptionState) +IDBRequest* IDBCursor::deleteFunction(ScriptState* scriptState, ExceptionState& exceptionState) { IDB_TRACE("IDBCursor::delete"); - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -273,13 +283,17 @@ PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ExecutionContext* context, Exce exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceDeletedErrorMessage); return 0; } + if (!m_transaction->backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(m_primaryKey, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::only(m_primaryKey, exceptionState); ASSERT(!exceptionState.hadException()); - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); - m_transaction->backendDB()->deleteRange(m_transaction->id(), effectiveObjectStore()->id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr()); - return request.release(); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); + m_transaction->backendDB()->deleteRange(m_transaction->id(), effectiveObjectStore()->id(), keyRange, WebIDBCallbacksImpl::create(request).leakPtr()); + return request; } void IDBCursor::postSuccessHandlerCallback() @@ -290,67 +304,51 @@ void IDBCursor::postSuccessHandlerCallback() void IDBCursor::close() { - // The notifier may be the last reference to this cursor. - RefPtr<IDBCursor> protect(this); + handleBlobAcks(); m_request.clear(); m_backend.clear(); } -void IDBCursor::checkForReferenceCycle() -{ - // If this cursor and its request have the only references - // to each other, then explicitly break the cycle. - if (!m_request || m_request->getResultCursor() != this) - return; - - if (!hasOneRef() || !m_request->hasOneRef()) - return; - - m_request.clear(); -} - -ScriptValue IDBCursor::key(ExecutionContext* context) +ScriptValue IDBCursor::key(ScriptState* scriptState) { m_keyDirty = false; - DOMRequestState requestState(context); - return idbKeyToScriptValue(&requestState, m_key); + return idbKeyToScriptValue(scriptState, m_key); } -ScriptValue IDBCursor::primaryKey(ExecutionContext* context) +ScriptValue IDBCursor::primaryKey(ScriptState* scriptState) { m_primaryKeyDirty = false; - DOMRequestState requestState(context); - return idbKeyToScriptValue(&requestState, m_primaryKey); + return idbKeyToScriptValue(scriptState, m_primaryKey); } -ScriptValue IDBCursor::value(ExecutionContext* context) +ScriptValue IDBCursor::value(ScriptState* scriptState) { ASSERT(isCursorWithValue()); - DOMRequestState requestState(context); - RefPtr<IDBObjectStore> objectStore = effectiveObjectStore(); + IDBObjectStore* objectStore = effectiveObjectStore(); const IDBObjectStoreMetadata& metadata = objectStore->metadata(); - RefPtr<IDBAny> value; + IDBAny* value; if (metadata.autoIncrement && !metadata.keyPath.isNull()) { - value = IDBAny::create(m_value, m_primaryKey, metadata.keyPath); + value = IDBAny::create(m_value, m_blobInfo.get(), m_primaryKey, metadata.keyPath); #ifndef NDEBUG - assertPrimaryKeyValidOrInjectable(&requestState, m_value, m_primaryKey, metadata.keyPath); + assertPrimaryKeyValidOrInjectable(scriptState, m_value, m_blobInfo.get(), m_primaryKey, metadata.keyPath); #endif } else { - value = IDBAny::create(m_value); + value = IDBAny::create(m_value, m_blobInfo.get()); } m_valueDirty = false; - return idbAnyToScriptValue(&requestState, value); + ScriptValue scriptValue = idbAnyToScriptValue(scriptState, value); + handleBlobAcks(); + return scriptValue; } -ScriptValue IDBCursor::source(ExecutionContext* context) const +ScriptValue IDBCursor::source(ScriptState* scriptState) const { - DOMRequestState requestState(context); - return idbAnyToScriptValue(&requestState, m_source); + return idbAnyToScriptValue(scriptState, m_source); } -void IDBCursor::setValueReady(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value) +void IDBCursor::setValueReady(IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<blink::WebBlobInfo> > blobInfo) { m_key = key; m_keyDirty = true; @@ -360,18 +358,19 @@ void IDBCursor::setValueReady(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primary if (isCursorWithValue()) { m_value = value; + handleBlobAcks(); + m_blobInfo = blobInfo; m_valueDirty = true; } m_gotValue = true; } -PassRefPtr<IDBObjectStore> IDBCursor::effectiveObjectStore() const +IDBObjectStore* IDBCursor::effectiveObjectStore() const { if (m_source->type() == IDBAny::IDBObjectStoreType) return m_source->idbObjectStore(); - RefPtr<IDBIndex> index = m_source->idbIndex(); - return index->objectStore(); + return m_source->idbIndex()->objectStore(); } bool IDBCursor::isDeleted() const @@ -381,34 +380,44 @@ bool IDBCursor::isDeleted() const return m_source->idbIndex()->isDeleted(); } -IndexedDB::CursorDirection IDBCursor::stringToDirection(const String& directionString, ExceptionState& exceptionState) +void IDBCursor::handleBlobAcks() +{ + ASSERT(m_request || !m_blobInfo || !m_blobInfo->size()); + if (m_blobInfo.get() && m_blobInfo->size()) { + ASSERT(m_request); + m_transaction->db()->ackReceivedBlobs(m_blobInfo.get()); + m_blobInfo.clear(); + } +} + +blink::WebIDBCursorDirection IDBCursor::stringToDirection(const String& directionString, ExceptionState& exceptionState) { if (directionString.isNull() || directionString == IDBCursor::directionNext()) - return IndexedDB::CursorNext; + return blink::WebIDBCursorDirectionNext; if (directionString == IDBCursor::directionNextUnique()) - return IndexedDB::CursorNextNoDuplicate; + return blink::WebIDBCursorDirectionNextNoDuplicate; if (directionString == IDBCursor::directionPrev()) - return IndexedDB::CursorPrev; + return blink::WebIDBCursorDirectionPrev; if (directionString == IDBCursor::directionPrevUnique()) - return IndexedDB::CursorPrevNoDuplicate; + return blink::WebIDBCursorDirectionPrevNoDuplicate; - exceptionState.throwUninformativeAndGenericTypeError(); - return IndexedDB::CursorNext; + exceptionState.throwTypeError("The direction provided ('" + directionString + "') is not one of 'next', 'nextunique', 'prev', or 'prevunique'."); + return blink::WebIDBCursorDirectionNext; } const AtomicString& IDBCursor::directionToString(unsigned short direction) { switch (direction) { - case IndexedDB::CursorNext: + case blink::WebIDBCursorDirectionNext: return IDBCursor::directionNext(); - case IndexedDB::CursorNextNoDuplicate: + case blink::WebIDBCursorDirectionNextNoDuplicate: return IDBCursor::directionNextUnique(); - case IndexedDB::CursorPrev: + case blink::WebIDBCursorDirectionPrev: return IDBCursor::directionPrev(); - case IndexedDB::CursorPrevNoDuplicate: + case blink::WebIDBCursorDirectionPrevNoDuplicate: return IDBCursor::directionPrevUnique(); default: diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.h index 0fd14e89d7a..6c8725db35c 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.h @@ -32,87 +32,86 @@ #include "modules/indexeddb/IDBRequest.h" #include "modules/indexeddb/IndexedDB.h" #include "public/platform/WebIDBCursor.h" +#include "public/platform/WebIDBTypes.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/RefPtr.h" +namespace blink { + +class WebBlobInfo; + +} // namespace blink + namespace WebCore { -class DOMRequestState; class ExceptionState; class IDBAny; class IDBTransaction; class ExecutionContext; class SharedBuffer; -class IDBCursor : public ScriptWrappable, public WTF::RefCountedBase { +class IDBCursor : public GarbageCollectedFinalized<IDBCursor>, public ScriptWrappable { public: static const AtomicString& directionNext(); static const AtomicString& directionNextUnique(); static const AtomicString& directionPrev(); static const AtomicString& directionPrevUnique(); - static IndexedDB::CursorDirection stringToDirection(const String& modeString, ExceptionState&); + static blink::WebIDBCursorDirection stringToDirection(const String& modeString, ExceptionState&); static const AtomicString& directionToString(unsigned short mode); - static PassRefPtr<IDBCursor> create(PassOwnPtr<blink::WebIDBCursor>, IndexedDB::CursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*); + static IDBCursor* create(PassOwnPtr<blink::WebIDBCursor>, blink::WebIDBCursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*); virtual ~IDBCursor(); + void trace(Visitor*); + void contextWillBeDestroyed() { m_backend.clear(); } // Implement the IDL const String& direction() const { return directionToString(m_direction); } - ScriptValue key(ExecutionContext*); - ScriptValue primaryKey(ExecutionContext*); - ScriptValue value(ExecutionContext*); - ScriptValue source(ExecutionContext*) const; + ScriptValue key(ScriptState*); + ScriptValue primaryKey(ScriptState*); + ScriptValue value(ScriptState*); + ScriptValue source(ScriptState*) const; - PassRefPtr<IDBRequest> update(ScriptState*, ScriptValue&, ExceptionState&); + IDBRequest* update(ScriptState*, ScriptValue&, ExceptionState&); void advance(unsigned long, ExceptionState&); - void continueFunction(ExecutionContext*, const ScriptValue& key, ExceptionState&); - void continuePrimaryKey(ExecutionContext*, const ScriptValue& key, const ScriptValue& primaryKey, ExceptionState&); - PassRefPtr<IDBRequest> deleteFunction(ExecutionContext*, ExceptionState&); + void continueFunction(ScriptState*, const ScriptValue& key, ExceptionState&); + void continuePrimaryKey(ScriptState*, const ScriptValue& key, const ScriptValue& primaryKey, ExceptionState&); + IDBRequest* deleteFunction(ScriptState*, ExceptionState&); bool isKeyDirty() const { return m_keyDirty; } bool isPrimaryKeyDirty() const { return m_primaryKeyDirty; } bool isValueDirty() const { return m_valueDirty; } - void continueFunction(PassRefPtr<IDBKey>, PassRefPtr<IDBKey> primaryKey, ExceptionState&); + void continueFunction(IDBKey*, IDBKey* primaryKey, ExceptionState&); void postSuccessHandlerCallback(); + bool isDeleted() const; void close(); - void setValueReady(PassRefPtr<IDBKey>, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value); - PassRefPtr<IDBKey> idbPrimaryKey() const { return m_primaryKey; } + void setValueReady(IDBKey*, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<blink::WebBlobInfo> >); + IDBKey* idbPrimaryKey() const { return m_primaryKey; } IDBRequest* request() const { return m_request.get(); } virtual bool isKeyCursor() const { return true; } virtual bool isCursorWithValue() const { return false; } - void deref() - { - if (derefBase()) - delete this; - else if (hasOneRef()) - checkForReferenceCycle(); - } - protected: - IDBCursor(PassOwnPtr<blink::WebIDBCursor>, IndexedDB::CursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*); + IDBCursor(PassOwnPtr<blink::WebIDBCursor>, blink::WebIDBCursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*); private: - PassRefPtr<IDBObjectStore> effectiveObjectStore() const; - - void checkForReferenceCycle(); - bool isDeleted() const; + IDBObjectStore* effectiveObjectStore() const; + void handleBlobAcks(); OwnPtr<blink::WebIDBCursor> m_backend; - RefPtr<IDBRequest> m_request; - const IndexedDB::CursorDirection m_direction; - RefPtr<IDBAny> m_source; - RefPtr<IDBTransaction> m_transaction; + Member<IDBRequest> m_request; + const blink::WebIDBCursorDirection m_direction; + Member<IDBAny> m_source; + Member<IDBTransaction> m_transaction; bool m_gotValue; bool m_keyDirty; bool m_primaryKeyDirty; bool m_valueDirty; - RefPtr<IDBKey> m_key; - RefPtr<IDBKey> m_primaryKey; + Member<IDBKey> m_key; + Member<IDBKey> m_primaryKey; RefPtr<SharedBuffer> m_value; + OwnPtr<Vector<blink::WebBlobInfo> > m_blobInfo; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.idl index aaeb0851bd1..76bdc54170e 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursor.idl @@ -23,16 +23,18 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -interface IDBCursor { +[ + GarbageCollected +] interface IDBCursor { readonly attribute DOMString direction; - [CallWith=ExecutionContext, CachedAttribute=isKeyDirty] readonly attribute any key; - [CallWith=ExecutionContext, CachedAttribute=isPrimaryKeyDirty] readonly attribute any primaryKey; - [CallWith=ExecutionContext] readonly attribute any source; + [CallWith=ScriptState, CachedAttribute=isKeyDirty] readonly attribute any key; + [CallWith=ScriptState, CachedAttribute=isPrimaryKeyDirty] readonly attribute any primaryKey; + [CallWith=ScriptState] readonly attribute any source; [CallWith=ScriptState, RaisesException] IDBRequest update(any value); [RaisesException] void advance([EnforceRange] unsigned long count); - [CallWith=ExecutionContext, ImplementedAs=continueFunction, RaisesException] void continue([Default=Undefined] optional any key); - [CallWith=ExecutionContext, RaisesException, RuntimeEnabled=IndexedDBExperimental] void continuePrimaryKey(any key, any primaryKey); - [CallWith=ExecutionContext, ImplementedAs=deleteFunction, RaisesException] IDBRequest delete(); + [CallWith=ScriptState, ImplementedAs=continueFunction, RaisesException] void continue([Default=Undefined] optional any key); + [CallWith=ScriptState, RaisesException, RuntimeEnabled=IndexedDBExperimental] void continuePrimaryKey(any key, any primaryKey); + [CallWith=ScriptState, ImplementedAs=deleteFunction, RaisesException] IDBRequest delete(); }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.cpp index 4b83dfe62f7..40deba1afc4 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.cpp @@ -28,14 +28,16 @@ #include "modules/indexeddb/IDBKey.h" +using blink::WebIDBCursor; + namespace WebCore { -PassRefPtr<IDBCursorWithValue> IDBCursorWithValue::create(PassOwnPtr<blink::WebIDBCursor> backend, IndexedDB::CursorDirection direction, IDBRequest* request, IDBAny* source, IDBTransaction* transaction) +IDBCursorWithValue* IDBCursorWithValue::create(PassOwnPtr<blink::WebIDBCursor> backend, blink::WebIDBCursorDirection direction, IDBRequest* request, IDBAny* source, IDBTransaction* transaction) { - return adoptRef(new IDBCursorWithValue(backend, direction, request, source, transaction)); + return new IDBCursorWithValue(backend, direction, request, source, transaction); } -IDBCursorWithValue::IDBCursorWithValue(PassOwnPtr<blink::WebIDBCursor> backend, IndexedDB::CursorDirection direction, IDBRequest* request, IDBAny* source, IDBTransaction* transaction) +IDBCursorWithValue::IDBCursorWithValue(PassOwnPtr<blink::WebIDBCursor> backend, blink::WebIDBCursorDirection direction, IDBRequest* request, IDBAny* source, IDBTransaction* transaction) : IDBCursor(backend, direction, request, source, transaction) { ScriptWrappable::init(this); diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.h index 862baff8355..bf89431a689 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.h @@ -29,6 +29,7 @@ #include "modules/indexeddb/IDBCursor.h" #include "modules/indexeddb/IndexedDB.h" #include "public/platform/WebIDBCursor.h" +#include "public/platform/WebIDBTypes.h" #include "wtf/PassOwnPtr.h" namespace WebCore { @@ -37,9 +38,9 @@ class IDBAny; class IDBRequest; class IDBTransaction; -class IDBCursorWithValue : public IDBCursor { +class IDBCursorWithValue FINAL : public IDBCursor { public: - static PassRefPtr<IDBCursorWithValue> create(PassOwnPtr<blink::WebIDBCursor>, IndexedDB::CursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*); + static IDBCursorWithValue* create(PassOwnPtr<blink::WebIDBCursor>, blink::WebIDBCursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*); virtual ~IDBCursorWithValue(); // The value attribute defined in the IDL is simply implemented in IDBCursor (but not exposed via @@ -49,14 +50,10 @@ public: virtual bool isCursorWithValue() const OVERRIDE { return true; } private: - IDBCursorWithValue(PassOwnPtr<blink::WebIDBCursor>, IndexedDB::CursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*); + IDBCursorWithValue(PassOwnPtr<blink::WebIDBCursor>, blink::WebIDBCursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*); }; -inline IDBCursorWithValue* toIDBCursorWithValue(IDBCursor* cursor) -{ - ASSERT_WITH_SECURITY_IMPLICATION(!cursor || cursor->isCursorWithValue()); - return static_cast<IDBCursorWithValue*>(cursor); -} +DEFINE_TYPE_CASTS(IDBCursorWithValue, IDBCursor, cursor, cursor->isCursorWithValue(), cursor.isCursorWithValue()); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl index cad30a656a7..719aa1e02ef 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBCursorWithValue.idl @@ -23,6 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -interface IDBCursorWithValue : IDBCursor { - [CallWith=ExecutionContext,CachedAttribute=isValueDirty] readonly attribute any value; +[ +] interface IDBCursorWithValue : IDBCursor { + [CallWith=ScriptState, CachedAttribute=isValueDirty] readonly attribute any value; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp index 8106fdc1cfb..5d72e759300 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.cpp @@ -29,6 +29,8 @@ #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "bindings/v8/IDBBindingUtilities.h" +#include "bindings/v8/Nullable.h" +#include "bindings/v8/SerializedScriptValue.h" #include "core/dom/ExecutionContext.h" #include "core/events/EventQueue.h" #include "core/inspector/ScriptCallStack.h" @@ -42,6 +44,7 @@ #include "modules/indexeddb/WebIDBDatabaseCallbacksImpl.h" #include "public/platform/Platform.h" #include "public/platform/WebIDBKeyPath.h" +#include "public/platform/WebIDBTypes.h" #include "wtf/Atomics.h" #include <limits> @@ -62,30 +65,42 @@ const char IDBDatabase::requestNotFinishedErrorMessage[] = "The request has not const char IDBDatabase::sourceDeletedErrorMessage[] = "The cursor's source or effective object store has been deleted."; const char IDBDatabase::transactionInactiveErrorMessage[] = "The transaction is not active."; const char IDBDatabase::transactionFinishedErrorMessage[] = "The transaction has finished."; +const char IDBDatabase::transactionReadOnlyErrorMessage[] = "The transaction is read-only."; +const char IDBDatabase::databaseClosedErrorMessage[] = "The database connection is closed."; -PassRefPtr<IDBDatabase> IDBDatabase::create(ExecutionContext* context, PassOwnPtr<WebIDBDatabase> database, PassRefPtr<IDBDatabaseCallbacks> callbacks) +IDBDatabase* IDBDatabase::create(ExecutionContext* context, PassOwnPtr<WebIDBDatabase> database, IDBDatabaseCallbacks* callbacks) { - RefPtr<IDBDatabase> idbDatabase(adoptRef(new IDBDatabase(context, database, callbacks))); + IDBDatabase* idbDatabase = adoptRefCountedGarbageCollectedWillBeNoop(new IDBDatabase(context, database, callbacks)); idbDatabase->suspendIfNeeded(); - return idbDatabase.release(); + return idbDatabase; } -IDBDatabase::IDBDatabase(ExecutionContext* context, PassOwnPtr<WebIDBDatabase> backend, PassRefPtr<IDBDatabaseCallbacks> callbacks) +IDBDatabase::IDBDatabase(ExecutionContext* context, PassOwnPtr<WebIDBDatabase> backend, IDBDatabaseCallbacks* callbacks) : ActiveDOMObject(context) , m_backend(backend) , m_closePending(false) , m_contextStopped(false) , m_databaseCallbacks(callbacks) { - // We pass a reference of this object before it can be adopted. - relaxAdoptionRequirement(); ScriptWrappable::init(this); m_databaseCallbacks->connect(this); } IDBDatabase::~IDBDatabase() { - close(); + if (!m_closePending && m_backend) + m_backend->close(); +} + +void IDBDatabase::trace(Visitor* visitor) +{ + visitor->trace(m_versionChangeTransaction); + visitor->trace(m_transactions); +#if ENABLE(OILPAN) + visitor->trace(m_enqueuedEvents); +#endif + visitor->trace(m_databaseCallbacks); + EventTargetWithInlineData::trace(visitor); } int64_t IDBDatabase::nextTransactionId() @@ -96,6 +111,19 @@ int64_t IDBDatabase::nextTransactionId() return atomicIncrement(¤tTransactionId); } +void IDBDatabase::ackReceivedBlobs(const Vector<blink::WebBlobInfo>* blobInfo) +{ + ASSERT(blobInfo); + if (!blobInfo->size() || !m_backend) + return; + Vector<blink::WebBlobInfo>::const_iterator iter; + Vector<String> uuids; + uuids.reserveCapacity(blobInfo->size()); + for (iter = blobInfo->begin(); iter != blobInfo->end(); ++iter) + uuids.append(iter->uuid()); + m_backend->ackReceivedBlobs(uuids); +} + void IDBDatabase::indexCreated(int64_t objectStoreId, const IDBIndexMetadata& metadata) { IDBDatabaseMetadata::ObjectStoreMap::iterator it = m_metadata.objectStores.find(objectStoreId); @@ -131,14 +159,14 @@ void IDBDatabase::transactionFinished(const IDBTransaction* transaction) if (transaction->isVersionChange()) { ASSERT(m_versionChangeTransaction == transaction); - m_versionChangeTransaction = 0; + m_versionChangeTransaction = nullptr; } if (m_closePending && m_transactions.isEmpty()) closeConnection(); } -void IDBDatabase::onAbort(int64_t transactionId, PassRefPtr<DOMError> error) +void IDBDatabase::onAbort(int64_t transactionId, PassRefPtrWillBeRawPtr<DOMError> error) { ASSERT(m_transactions.contains(transactionId)); m_transactions.get(transactionId)->onAbort(error); @@ -150,26 +178,25 @@ void IDBDatabase::onComplete(int64_t transactionId) m_transactions.get(transactionId)->onComplete(); } -PassRefPtr<DOMStringList> IDBDatabase::objectStoreNames() const +PassRefPtrWillBeRawPtr<DOMStringList> IDBDatabase::objectStoreNames() const { - RefPtr<DOMStringList> objectStoreNames = DOMStringList::create(); + RefPtrWillBeRawPtr<DOMStringList> objectStoreNames = DOMStringList::create(); for (IDBDatabaseMetadata::ObjectStoreMap::const_iterator it = m_metadata.objectStores.begin(); it != m_metadata.objectStores.end(); ++it) objectStoreNames->append(it->value.name); objectStoreNames->sort(); return objectStoreNames.release(); } -ScriptValue IDBDatabase::version(ExecutionContext* context) const +ScriptValue IDBDatabase::version(ScriptState* scriptState) const { - DOMRequestState requestState(context); int64_t intVersion = m_metadata.intVersion; if (intVersion == IDBDatabaseMetadata::NoIntVersion) - return idbAnyToScriptValue(&requestState, IDBAny::createString(m_metadata.version)); + return idbAnyToScriptValue(scriptState, IDBAny::createString(m_metadata.version)); - return idbAnyToScriptValue(&requestState, IDBAny::create(intVersion)); + return idbAnyToScriptValue(scriptState, IDBAny::create(intVersion)); } -PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const Dictionary& options, ExceptionState& exceptionState) +IDBObjectStore* IDBDatabase::createObjectStore(const String& name, const Dictionary& options, ExceptionState& exceptionState) { IDBKeyPath keyPath; bool autoIncrement = false; @@ -187,7 +214,7 @@ PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, co return createObjectStore(name, keyPath, autoIncrement, exceptionState); } -PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, ExceptionState& exceptionState) +IDBObjectStore* IDBDatabase::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, ExceptionState& exceptionState) { IDB_TRACE("IDBDatabase::createObjectStore"); blink::Platform::current()->histogramEnumeration("WebCore.IndexedDB.FrontEndAPICalls", IDBCreateObjectStoreCall, IDBMethodsMax); @@ -195,7 +222,7 @@ PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, co exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVersionChangeTransactionErrorMessage); return 0; } - if (m_versionChangeTransaction->isFinished()) { + if (m_versionChangeTransaction->isFinished() || m_versionChangeTransaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -219,16 +246,21 @@ PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, co return 0; } + if (!m_backend) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } + int64_t objectStoreId = m_metadata.maxObjectStoreId + 1; m_backend->createObjectStore(m_versionChangeTransaction->id(), objectStoreId, name, keyPath, autoIncrement); IDBObjectStoreMetadata metadata(name, objectStoreId, keyPath, autoIncrement, WebIDBDatabase::minimumIndexId); - RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(metadata, m_versionChangeTransaction.get()); + IDBObjectStore* objectStore = IDBObjectStore::create(metadata, m_versionChangeTransaction.get()); m_metadata.objectStores.set(metadata.id, metadata); ++m_metadata.maxObjectStoreId; m_versionChangeTransaction->objectStoreCreated(name, objectStore); - return objectStore.release(); + return objectStore; } void IDBDatabase::deleteObjectStore(const String& name, ExceptionState& exceptionState) @@ -239,7 +271,7 @@ void IDBDatabase::deleteObjectStore(const String& name, ExceptionState& exceptio exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVersionChangeTransactionErrorMessage); return; } - if (m_versionChangeTransaction->isFinished()) { + if (m_versionChangeTransaction->isFinished() || m_versionChangeTransaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return; } @@ -254,12 +286,17 @@ void IDBDatabase::deleteObjectStore(const String& name, ExceptionState& exceptio return; } + if (!m_backend) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return; + } + m_backend->deleteObjectStore(m_versionChangeTransaction->id(), objectStoreId); m_versionChangeTransaction->objectStoreDeleted(name); m_metadata.objectStores.remove(objectStoreId); } -PassRefPtr<IDBTransaction> IDBDatabase::transaction(ExecutionContext* context, const Vector<String>& scope, const String& modeString, ExceptionState& exceptionState) +IDBTransaction* IDBDatabase::transaction(ExecutionContext* context, const Vector<String>& scope, const String& modeString, ExceptionState& exceptionState) { IDB_TRACE("IDBDatabase::transaction"); blink::Platform::current()->histogramEnumeration("WebCore.IndexedDB.FrontEndAPICalls", IDBTransactionCall, IDBMethodsMax); @@ -268,7 +305,7 @@ PassRefPtr<IDBTransaction> IDBDatabase::transaction(ExecutionContext* context, c return 0; } - IndexedDB::TransactionMode mode = IDBTransaction::stringToMode(modeString, exceptionState); + blink::WebIDBTransactionMode mode = IDBTransaction::stringToMode(modeString, exceptionState); if (exceptionState.hadException()) return 0; @@ -292,16 +329,20 @@ PassRefPtr<IDBTransaction> IDBDatabase::transaction(ExecutionContext* context, c objectStoreIds.append(objectStoreId); } + if (!m_backend) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } + int64_t transactionId = nextTransactionId(); m_backend->createTransaction(transactionId, WebIDBDatabaseCallbacksImpl::create(m_databaseCallbacks).leakPtr(), objectStoreIds, mode); - RefPtr<IDBTransaction> transaction = IDBTransaction::create(context, transactionId, scope, mode, this); - return transaction.release(); + return IDBTransaction::create(context, transactionId, scope, mode, this); } -PassRefPtr<IDBTransaction> IDBDatabase::transaction(ExecutionContext* context, const String& storeName, const String& mode, ExceptionState& exceptionState) +IDBTransaction* IDBDatabase::transaction(ExecutionContext* context, const String& storeName, const String& mode, ExceptionState& exceptionState) { - RefPtr<DOMStringList> storeNames = DOMStringList::create(); + RefPtrWillBeRawPtr<DOMStringList> storeNames = DOMStringList::create(); storeNames->append(storeName); return transaction(context, storeNames, mode, exceptionState); } @@ -331,8 +372,10 @@ void IDBDatabase::closeConnection() ASSERT(m_closePending); ASSERT(m_transactions.isEmpty()); - m_backend->close(); - m_backend.clear(); + if (m_backend) { + m_backend->close(); + m_backend.clear(); + } if (m_contextStopped || !executionContext()) return; @@ -357,11 +400,11 @@ void IDBDatabase::onVersionChange(int64_t oldVersion, int64_t newVersion) if (m_closePending) return; - RefPtr<IDBAny> newVersionAny = newVersion == IDBDatabaseMetadata::NoIntVersion ? IDBAny::createNull() : IDBAny::create(newVersion); - enqueueEvent(IDBVersionChangeEvent::create(IDBAny::create(oldVersion), newVersionAny.release(), EventTypeNames::versionchange)); + Nullable<unsigned long long> newVersionNullable = (newVersion == IDBDatabaseMetadata::NoIntVersion) ? Nullable<unsigned long long>() : Nullable<unsigned long long>(newVersion); + enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::versionchange, oldVersion, newVersionNullable)); } -void IDBDatabase::enqueueEvent(PassRefPtr<Event> event) +void IDBDatabase::enqueueEvent(PassRefPtrWillBeRawPtr<Event> event) { ASSERT(!m_contextStopped); ASSERT(executionContext()); @@ -371,9 +414,11 @@ void IDBDatabase::enqueueEvent(PassRefPtr<Event> event) m_enqueuedEvents.append(event); } -bool IDBDatabase::dispatchEvent(PassRefPtr<Event> event) +bool IDBDatabase::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { IDB_TRACE("IDBDatabase::dispatchEvent"); + if (m_contextStopped || !executionContext()) + return false; ASSERT(event->type() == EventTypeNames::versionchange || event->type() == EventTypeNames::close); for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) { if (m_enqueuedEvents[i].get() == event.get()) @@ -402,10 +447,15 @@ bool IDBDatabase::hasPendingActivity() const void IDBDatabase::stop() { - // Stop fires at a deterministic time, so we need to call close in it. - close(); - m_contextStopped = true; + + // Immediately close the connection to the back end. Don't attempt a + // normal close() since that may wait on transactions which require a + // round trip to the back-end to abort. + if (m_backend) { + m_backend->close(); + m_backend.clear(); + } } const AtomicString& IDBDatabase::interfaceName() const diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h index af70e168a41..b862877cc03 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.h @@ -30,18 +30,18 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" #include "core/dom/DOMStringList.h" -#include "core/events/Event.h" -#include "core/events/EventTarget.h" +#include "modules/EventModules.h" +#include "modules/EventTargetModules.h" #include "modules/indexeddb/IDBDatabaseCallbacks.h" #include "modules/indexeddb/IDBMetadata.h" #include "modules/indexeddb/IDBObjectStore.h" #include "modules/indexeddb/IDBTransaction.h" #include "modules/indexeddb/IndexedDB.h" +#include "platform/heap/Handle.h" #include "public/platform/WebIDBDatabase.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/RefPtr.h" namespace WebCore { @@ -50,12 +50,17 @@ class DOMError; class ExceptionState; class ExecutionContext; -class IDBDatabase : public RefCounted<IDBDatabase>, public ScriptWrappable, public EventTargetWithInlineData, public ActiveDOMObject { - REFCOUNTED_EVENT_TARGET(IDBDatabase); - +class IDBDatabase FINAL + : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<IDBDatabase> + , public ScriptWrappable + , public EventTargetWithInlineData + , public ActiveDOMObject { + DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<IDBDatabase>); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(IDBDatabase); public: - static PassRefPtr<IDBDatabase> create(ExecutionContext*, PassOwnPtr<blink::WebIDBDatabase>, PassRefPtr<IDBDatabaseCallbacks>); - ~IDBDatabase(); + static IDBDatabase* create(ExecutionContext*, PassOwnPtr<blink::WebIDBDatabase>, IDBDatabaseCallbacks*); + virtual ~IDBDatabase(); + virtual void trace(Visitor*) OVERRIDE; void setMetadata(const IDBDatabaseMetadata& metadata) { m_metadata = metadata; } void indexCreated(int64_t objectStoreId, const IDBIndexMetadata&); @@ -65,14 +70,14 @@ public: // Implement the IDL const String& name() const { return m_metadata.name; } - ScriptValue version(ExecutionContext*) const; - PassRefPtr<DOMStringList> objectStoreNames() const; - - PassRefPtr<IDBObjectStore> createObjectStore(const String& name, const Dictionary&, ExceptionState&); - PassRefPtr<IDBObjectStore> createObjectStore(const String& name, const IDBKeyPath&, bool autoIncrement, ExceptionState&); - PassRefPtr<IDBTransaction> transaction(ExecutionContext* context, PassRefPtr<DOMStringList> scope, const String& mode, ExceptionState& exceptionState) { return transaction(context, *scope, mode, exceptionState); } - PassRefPtr<IDBTransaction> transaction(ExecutionContext*, const Vector<String>&, const String& mode, ExceptionState&); - PassRefPtr<IDBTransaction> transaction(ExecutionContext*, const String&, const String& mode, ExceptionState&); + ScriptValue version(ScriptState*) const; + PassRefPtrWillBeRawPtr<DOMStringList> objectStoreNames() const; + + IDBObjectStore* createObjectStore(const String& name, const Dictionary&, ExceptionState&); + IDBObjectStore* createObjectStore(const String& name, const IDBKeyPath&, bool autoIncrement, ExceptionState&); + IDBTransaction* transaction(ExecutionContext* context, PassRefPtrWillBeRawPtr<DOMStringList> scope, const String& mode, ExceptionState& exceptionState) { return transaction(context, *scope, mode, exceptionState); } + IDBTransaction* transaction(ExecutionContext*, const Vector<String>&, const String& mode, ExceptionState&); + IDBTransaction* transaction(ExecutionContext*, const String&, const String& mode, ExceptionState&); void deleteObjectStore(const String& name, ExceptionState&); void close(); @@ -82,9 +87,9 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(versionchange); // IDBDatabaseCallbacks - virtual void onVersionChange(int64_t oldVersion, int64_t newVersion); - virtual void onAbort(int64_t, PassRefPtr<DOMError>); - virtual void onComplete(int64_t); + void onVersionChange(int64_t oldVersion, int64_t newVersion); + void onAbort(int64_t, PassRefPtrWillBeRawPtr<DOMError>); + void onComplete(int64_t); // ActiveDOMObject virtual bool hasPendingActivity() const OVERRIDE; @@ -97,10 +102,10 @@ public: bool isClosePending() const { return m_closePending; } void forceClose(); const IDBDatabaseMetadata& metadata() const { return m_metadata; } - void enqueueEvent(PassRefPtr<Event>); + void enqueueEvent(PassRefPtrWillBeRawPtr<Event>); using EventTarget::dispatchEvent; - virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE; + virtual bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>) OVERRIDE; int64_t findObjectStoreId(const String& name) const; bool containsObjectStore(const String& name) const @@ -108,10 +113,13 @@ public: return findObjectStoreId(name) != IDBObjectStoreMetadata::InvalidId; } + // Will return nullptr if this database is stopped. blink::WebIDBDatabase* backend() const { return m_backend.get(); } static int64_t nextTransactionId(); + void ackReceivedBlobs(const Vector<blink::WebBlobInfo>*); + static const char indexDeletedErrorMessage[]; static const char isKeyCursorErrorMessage[]; static const char noKeyOrKeyRangeErrorMessage[]; @@ -125,16 +133,18 @@ public: static const char sourceDeletedErrorMessage[]; static const char transactionFinishedErrorMessage[]; static const char transactionInactiveErrorMessage[]; + static const char transactionReadOnlyErrorMessage[]; + static const char databaseClosedErrorMessage[]; private: - IDBDatabase(ExecutionContext*, PassOwnPtr<blink::WebIDBDatabase>, PassRefPtr<IDBDatabaseCallbacks>); + IDBDatabase(ExecutionContext*, PassOwnPtr<blink::WebIDBDatabase>, IDBDatabaseCallbacks*); void closeConnection(); IDBDatabaseMetadata m_metadata; OwnPtr<blink::WebIDBDatabase> m_backend; - RefPtr<IDBTransaction> m_versionChangeTransaction; - typedef HashMap<int64_t, RefPtr<IDBTransaction> > TransactionMap; + Member<IDBTransaction> m_versionChangeTransaction; + typedef HeapHashMap<int64_t, Member<IDBTransaction> > TransactionMap; TransactionMap m_transactions; bool m_closePending; @@ -142,9 +152,9 @@ private: // Keep track of the versionchange events waiting to be fired on this // database so that we can cancel them if the database closes. - Vector<RefPtr<Event> > m_enqueuedEvents; + WillBeHeapVector<RefPtrWillBeMember<Event> > m_enqueuedEvents; - RefPtr<IDBDatabaseCallbacks> m_databaseCallbacks; + Member<IDBDatabaseCallbacks> m_databaseCallbacks; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.idl index c8e80d373b9..41e8ff059f2 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabase.idl @@ -24,23 +24,24 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// https://dvcs.w3.org/hg/IndexedDB/raw-file/default/Overview.html#idl-def-IDBDatabase + [ - ActiveDOMObject + ActiveDOMObject, + GarbageCollected, ] interface IDBDatabase : EventTarget { readonly attribute DOMString name; - [CallWith=ExecutionContext] readonly attribute any version; + [CallWith=ScriptState] readonly attribute any version; readonly attribute DOMStringList objectStoreNames; - + [RaisesException] IDBObjectStore createObjectStore(DOMString name, optional Dictionary options); + [RaisesException] void deleteObjectStore(DOMString name); + // FIXME: should be union type http://crbug.com/240176 + [CallWith=ExecutionContext, RaisesException] IDBTransaction transaction(DOMString storeName, optional DOMString mode = null); + [CallWith=ExecutionContext, RaisesException] IDBTransaction transaction(sequence<DOMString> storeNames, optional DOMString mode = null); + [CallWith=ExecutionContext, RaisesException] IDBTransaction transaction(DOMStringList storeNames, optional DOMString mode = null); + void close(); attribute EventHandler onabort; attribute EventHandler onclose; attribute EventHandler onerror; attribute EventHandler onversionchange; - - [RaisesException] IDBObjectStore createObjectStore(DOMString name, optional Dictionary options); - [RaisesException] void deleteObjectStore(DOMString name); - [CallWith=ExecutionContext, RaisesException] IDBTransaction transaction(DOMStringList storeNames, [Default=NullString] optional DOMString mode); - [CallWith=ExecutionContext, RaisesException] IDBTransaction transaction(sequence<DOMString> storeNames, [Default=NullString] optional DOMString mode); - [CallWith=ExecutionContext, RaisesException] IDBTransaction transaction(DOMString storeName, [Default=NullString] optional DOMString mode); - - void close(); }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.cpp index 900b62ea805..e055f0d7b39 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.cpp @@ -30,13 +30,13 @@ namespace WebCore { -PassRefPtr<IDBDatabaseCallbacks> IDBDatabaseCallbacks::create() +IDBDatabaseCallbacks* IDBDatabaseCallbacks::create() { - return adoptRef(new IDBDatabaseCallbacks()); + return new IDBDatabaseCallbacks(); } IDBDatabaseCallbacks::IDBDatabaseCallbacks() - : m_database(0) + : m_database(nullptr) { } @@ -44,6 +44,11 @@ IDBDatabaseCallbacks::~IDBDatabaseCallbacks() { } +void IDBDatabaseCallbacks::trace(Visitor* visitor) +{ + visitor->trace(m_database); +} + void IDBDatabaseCallbacks::onForcedClose() { if (m_database) @@ -63,7 +68,7 @@ void IDBDatabaseCallbacks::connect(IDBDatabase* database) m_database = database; } -void IDBDatabaseCallbacks::onAbort(int64_t transactionId, PassRefPtr<DOMError> error) +void IDBDatabaseCallbacks::onAbort(int64_t transactionId, PassRefPtrWillBeRawPtr<DOMError> error) { if (m_database) m_database->onAbort(transactionId, error); diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.h index 5f3c43b1b16..b20231437c5 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBDatabaseCallbacks.h @@ -26,24 +26,25 @@ #ifndef IDBDatabaseCallbacks_h #define IDBDatabaseCallbacks_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" namespace WebCore { class DOMError; class IDBDatabase; -class IDBDatabaseCallbacks : public RefCounted<IDBDatabaseCallbacks> { +class IDBDatabaseCallbacks : public GarbageCollectedFinalized<IDBDatabaseCallbacks> { public: - static PassRefPtr<IDBDatabaseCallbacks> create(); + static IDBDatabaseCallbacks* create(); virtual ~IDBDatabaseCallbacks(); + void trace(Visitor*); // IDBDatabaseCallbacks virtual void onForcedClose(); virtual void onVersionChange(int64_t oldVersion, int64_t newVersion); - virtual void onAbort(int64_t transactionId, PassRefPtr<DOMError>); + virtual void onAbort(int64_t transactionId, PassRefPtrWillBeRawPtr<DOMError>); virtual void onComplete(int64_t transactionId); void connect(IDBDatabase*); @@ -53,8 +54,14 @@ protected: IDBDatabaseCallbacks(); private: - // The initial IDBOpenDBRequest or final IDBDatabase maintains a RefPtr to this - IDBDatabase* m_database; + // The initial IDBOpenDBRequest, final IDBDatabase, and/or + // WebIDBDatabaseCallbacks have strong references to an IDBDatabaseCallbacks + // object. + // Oilpan: We'd like to delete an IDBDatabase object by a + // GC. WebIDBDatabaseCallbacks can survive the GC, and IDBDatabaseCallbacks + // can survive too. m_database should be a weak reference to avoid that an + // IDBDatabase survives the GC with the IDBDatabaseCallbacks. + WeakMember<IDBDatabase> m_database; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.cpp index c6e428523b8..7cee2ebfac9 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.cpp @@ -29,12 +29,12 @@ #include "config.h" #include "modules/indexeddb/IDBEventDispatcher.h" -#include "core/events/Event.h" -#include "core/events/EventTarget.h" +#include "modules/EventModules.h" +#include "modules/EventTargetModules.h" namespace WebCore { -bool IDBEventDispatcher::dispatch(Event* event, Vector<RefPtr<EventTarget> >& eventTargets) +bool IDBEventDispatcher::dispatch(Event* event, WillBeHeapVector<RefPtrWillBeMember<EventTarget> >& eventTargets) { size_t size = eventTargets.size(); ASSERT(size); @@ -61,24 +61,6 @@ bool IDBEventDispatcher::dispatch(Event* event, Vector<RefPtr<EventTarget> >& ev goto doneDispatching; } - // FIXME: "...However, we also wanted to integrate the window.onerror feature in - // HTML5. So after we've fired an "error" event, if .preventDefault() was - // never called on the event, we fire an error event on the window (can't - // remember if this happens before or after we abort the transaction). - // This is a separate event, which for example means that even if you - // attach a capturing "error" handler on window, you won't see any events - // unless an error really went unhandled. And you also can't call - // .preventDefault on the error event fired on the window in order to - // prevent the transaction from being aborted. It's purely there for - // error reporting and distinctly different from the event propagating to - // the window. - // - // This is similar to how "error" events are handled in workers. - // - // (I think that so far webkit hasn't implemented the window.onerror - // feature yet, so you probably don't want to fire the separate error - // event on the window until that has been implemented)." -- Jonas Sicking - doneDispatching: event->setCurrentTarget(0); event->setEventPhase(0); diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.h index 254055c68b8..86ed11102e1 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.h @@ -29,6 +29,7 @@ #ifndef IDBEventDispatcher_h #define IDBEventDispatcher_h +#include "platform/heap/Handle.h" #include "wtf/RefPtr.h" #include "wtf/Vector.h" @@ -39,7 +40,7 @@ class EventTarget; class IDBEventDispatcher { public: - static bool dispatch(Event*, Vector<RefPtr<EventTarget> >&); // The target first and then its ancestors in order of how the event bubbles. + static bool dispatch(Event*, WillBeHeapVector<RefPtrWillBeMember<EventTarget> >&); // The target first and then its ancestors in order of how the event bubbles. private: IDBEventDispatcher(); diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp index 8b2c42efe92..6412ffb4413 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp @@ -35,10 +35,10 @@ #include "core/dom/ExceptionCode.h" #include "modules/indexeddb/IDBDatabase.h" #include "modules/indexeddb/IDBDatabaseCallbacks.h" -#include "modules/indexeddb/IDBFactoryBackendInterface.h" #include "modules/indexeddb/IDBHistograms.h" #include "modules/indexeddb/IDBKey.h" #include "modules/indexeddb/IDBTracing.h" +#include "modules/indexeddb/IndexedDBClient.h" #include "modules/indexeddb/WebIDBCallbacksImpl.h" #include "modules/indexeddb/WebIDBDatabaseCallbacksImpl.h" #include "platform/weborigin/DatabaseIdentifier.h" @@ -50,11 +50,9 @@ namespace WebCore { static const char permissionDeniedErrorMessage[] = "The user denied permission to access the database."; -IDBFactory::IDBFactory(IDBFactoryBackendInterface* permissionClient) +IDBFactory::IDBFactory(IndexedDBClient* permissionClient) : m_permissionClient(permissionClient) { - // We pass a reference to this object before it can be adopted. - relaxAdoptionRequirement(); ScriptWrappable::init(this); } @@ -62,6 +60,11 @@ IDBFactory::~IDBFactory() { } +void IDBFactory::trace(Visitor* visitor) +{ + visitor->trace(m_permissionClient); +} + static bool isContextValid(ExecutionContext* context) { ASSERT(context->isDocument() || context->isWorkerGlobalScope()); @@ -72,102 +75,101 @@ static bool isContextValid(ExecutionContext* context) return true; } -PassRefPtr<IDBRequest> IDBFactory::getDatabaseNames(ExecutionContext* context, ExceptionState& exceptionState) +IDBRequest* IDBFactory::getDatabaseNames(ScriptState* scriptState, ExceptionState& exceptionState) { IDB_TRACE("IDBFactory::getDatabaseNames"); - if (!isContextValid(context)) - return 0; - if (!context->securityOrigin()->canAccessDatabase()) { + if (!isContextValid(scriptState->executionContext())) + return nullptr; + if (!scriptState->executionContext()->securityOrigin()->canAccessDatabase()) { exceptionState.throwSecurityError("access to the Indexed Database API is denied in this context."); return 0; } - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::createNull(), 0); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::createNull(), 0); - if (!m_permissionClient->allowIndexedDB(context, "Database Listing")) { + if (!m_permissionClient->allowIndexedDB(scriptState->executionContext(), "Database Listing")) { request->onError(DOMError::create(UnknownError, permissionDeniedErrorMessage)); return request; } - blink::Platform::current()->idbFactory()->getDatabaseNames(WebIDBCallbacksImpl::create(request).leakPtr(), createDatabaseIdentifierFromSecurityOrigin(context->securityOrigin())); + blink::Platform::current()->idbFactory()->getDatabaseNames(WebIDBCallbacksImpl::create(request).leakPtr(), createDatabaseIdentifierFromSecurityOrigin(scriptState->executionContext()->securityOrigin())); return request; } -PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ExecutionContext* context, const String& name, unsigned long long version, ExceptionState& exceptionState) +IDBOpenDBRequest* IDBFactory::open(ScriptState* scriptState, const String& name, unsigned long long version, ExceptionState& exceptionState) { IDB_TRACE("IDBFactory::open"); if (!version) { - exceptionState.throwUninformativeAndGenericTypeError(); + exceptionState.throwTypeError("The version provided must not be 0."); return 0; } - return openInternal(context, name, version, exceptionState); + return openInternal(scriptState, name, version, exceptionState); } -PassRefPtr<IDBOpenDBRequest> IDBFactory::openInternal(ExecutionContext* context, const String& name, int64_t version, ExceptionState& exceptionState) +IDBOpenDBRequest* IDBFactory::openInternal(ScriptState* scriptState, const String& name, int64_t version, ExceptionState& exceptionState) { blink::Platform::current()->histogramEnumeration("WebCore.IndexedDB.FrontEndAPICalls", IDBOpenCall, IDBMethodsMax); ASSERT(version >= 1 || version == IDBDatabaseMetadata::NoIntVersion); if (name.isNull()) { - exceptionState.throwUninformativeAndGenericTypeError(); + exceptionState.throwTypeError("The name provided must not be empty."); return 0; } - if (!isContextValid(context)) - return 0; - if (!context->securityOrigin()->canAccessDatabase()) { + if (!isContextValid(scriptState->executionContext())) + return nullptr; + if (!scriptState->executionContext()->securityOrigin()->canAccessDatabase()) { exceptionState.throwSecurityError("access to the Indexed Database API is denied in this context."); return 0; } - RefPtr<IDBDatabaseCallbacks> databaseCallbacks = IDBDatabaseCallbacks::create(); + IDBDatabaseCallbacks* databaseCallbacks = IDBDatabaseCallbacks::create(); int64_t transactionId = IDBDatabase::nextTransactionId(); - RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, databaseCallbacks, transactionId, version); + IDBOpenDBRequest* request = IDBOpenDBRequest::create(scriptState, databaseCallbacks, transactionId, version); - if (!m_permissionClient->allowIndexedDB(context, name)) { + if (!m_permissionClient->allowIndexedDB(scriptState->executionContext(), name)) { request->onError(DOMError::create(UnknownError, permissionDeniedErrorMessage)); return request; } - blink::Platform::current()->idbFactory()->open(name, version, transactionId, WebIDBCallbacksImpl::create(request).leakPtr(), WebIDBDatabaseCallbacksImpl::create(databaseCallbacks.release()).leakPtr(), createDatabaseIdentifierFromSecurityOrigin(context->securityOrigin())); + blink::Platform::current()->idbFactory()->open(name, version, transactionId, WebIDBCallbacksImpl::create(request).leakPtr(), WebIDBDatabaseCallbacksImpl::create(databaseCallbacks).leakPtr(), createDatabaseIdentifierFromSecurityOrigin(scriptState->executionContext()->securityOrigin())); return request; } -PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ExecutionContext* context, const String& name, ExceptionState& exceptionState) +IDBOpenDBRequest* IDBFactory::open(ScriptState* scriptState, const String& name, ExceptionState& exceptionState) { IDB_TRACE("IDBFactory::open"); - return openInternal(context, name, IDBDatabaseMetadata::NoIntVersion, exceptionState); + return openInternal(scriptState, name, IDBDatabaseMetadata::NoIntVersion, exceptionState); } -PassRefPtr<IDBOpenDBRequest> IDBFactory::deleteDatabase(ExecutionContext* context, const String& name, ExceptionState& exceptionState) +IDBOpenDBRequest* IDBFactory::deleteDatabase(ScriptState* scriptState, const String& name, ExceptionState& exceptionState) { IDB_TRACE("IDBFactory::deleteDatabase"); blink::Platform::current()->histogramEnumeration("WebCore.IndexedDB.FrontEndAPICalls", IDBDeleteDatabaseCall, IDBMethodsMax); if (name.isNull()) { - exceptionState.throwUninformativeAndGenericTypeError(); + exceptionState.throwTypeError("The name provided must not be empty."); return 0; } - if (!isContextValid(context)) - return 0; - if (!context->securityOrigin()->canAccessDatabase()) { + if (!isContextValid(scriptState->executionContext())) + return nullptr; + if (!scriptState->executionContext()->securityOrigin()->canAccessDatabase()) { exceptionState.throwSecurityError("access to the Indexed Database API is denied in this context."); return 0; } - RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, 0, 0, IDBDatabaseMetadata::DefaultIntVersion); + IDBOpenDBRequest* request = IDBOpenDBRequest::create(scriptState, nullptr, 0, IDBDatabaseMetadata::DefaultIntVersion); - if (!m_permissionClient->allowIndexedDB(context, name)) { + if (!m_permissionClient->allowIndexedDB(scriptState->executionContext(), name)) { request->onError(DOMError::create(UnknownError, permissionDeniedErrorMessage)); return request; } - blink::Platform::current()->idbFactory()->deleteDatabase(name, WebIDBCallbacksImpl::create(request).leakPtr(), createDatabaseIdentifierFromSecurityOrigin(context->securityOrigin())); + blink::Platform::current()->idbFactory()->deleteDatabase(name, WebIDBCallbacksImpl::create(request).leakPtr(), createDatabaseIdentifierFromSecurityOrigin(scriptState->executionContext()->securityOrigin())); return request; } -short IDBFactory::cmp(ExecutionContext* context, const ScriptValue& firstValue, const ScriptValue& secondValue, ExceptionState& exceptionState) +short IDBFactory::cmp(ScriptState* scriptState, const ScriptValue& firstValue, const ScriptValue& secondValue, ExceptionState& exceptionState) { - DOMRequestState requestState(context); - RefPtr<IDBKey> first = scriptValueToIDBKey(&requestState, firstValue); - RefPtr<IDBKey> second = scriptValueToIDBKey(&requestState, secondValue); + IDBKey* first = scriptValueToIDBKey(scriptState->isolate(), firstValue); + IDBKey* second = scriptValueToIDBKey(scriptState->isolate(), secondValue); ASSERT(first); ASSERT(second); @@ -177,7 +179,7 @@ short IDBFactory::cmp(ExecutionContext* context, const ScriptValue& firstValue, return 0; } - return static_cast<short>(first->compare(second.get())); + return static_cast<short>(first->compare(second)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.h index 2e845b338bb..06e69ce7454 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.h @@ -30,41 +30,40 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/indexeddb/IDBOpenDBRequest.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" +#include "modules/indexeddb/IndexedDBClient.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { class ExceptionState; -class IDBFactoryBackendInterface; class IDBKey; class IDBKeyRange; class ExecutionContext; -class IDBFactory : public ScriptWrappable, public RefCounted<IDBFactory> { +class IDBFactory : public GarbageCollectedFinalized<IDBFactory>, public ScriptWrappable { public: - static PassRefPtr<IDBFactory> create(IDBFactoryBackendInterface* factory) + static IDBFactory* create(IndexedDBClient* client) { - return adoptRef(new IDBFactory(factory)); + return new IDBFactory(client); } ~IDBFactory(); + void trace(Visitor*); - PassRefPtr<IDBRequest> getDatabaseNames(ExecutionContext*, ExceptionState&); + IDBRequest* getDatabaseNames(ScriptState*, ExceptionState&); - PassRefPtr<IDBOpenDBRequest> open(ExecutionContext*, const String& name, ExceptionState&); - PassRefPtr<IDBOpenDBRequest> open(ExecutionContext*, const String& name, unsigned long long version, ExceptionState&); - PassRefPtr<IDBOpenDBRequest> deleteDatabase(ExecutionContext*, const String& name, ExceptionState&); + IDBOpenDBRequest* open(ScriptState*, const String& name, ExceptionState&); + IDBOpenDBRequest* open(ScriptState*, const String& name, unsigned long long version, ExceptionState&); + IDBOpenDBRequest* deleteDatabase(ScriptState*, const String& name, ExceptionState&); - short cmp(ExecutionContext*, const ScriptValue& first, const ScriptValue& second, ExceptionState&); + short cmp(ScriptState*, const ScriptValue& first, const ScriptValue& second, ExceptionState&); private: - explicit IDBFactory(IDBFactoryBackendInterface*); + explicit IDBFactory(IndexedDBClient*); - PassRefPtr<IDBOpenDBRequest> openInternal(ExecutionContext*, const String& name, int64_t version, ExceptionState&); + IDBOpenDBRequest* openInternal(ScriptState*, const String& name, int64_t version, ExceptionState&); - RefPtr<IDBFactoryBackendInterface> m_permissionClient; + Member<IndexedDBClient> m_permissionClient; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl index 7e0013cecb9..7e9186296fc 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactory.idl @@ -24,11 +24,12 @@ */ [ + GarbageCollected ] interface IDBFactory { - [CallWith=ExecutionContext, ImplementedAs=getDatabaseNames, RaisesException] IDBRequest webkitGetDatabaseNames(); + [CallWith=ScriptState, ImplementedAs=getDatabaseNames, RaisesException] IDBRequest webkitGetDatabaseNames(); - [CallWith=ExecutionContext, RaisesException] IDBOpenDBRequest open(DOMString name, [EnforceRange] optional unsigned long long version); - [CallWith=ExecutionContext, RaisesException] IDBOpenDBRequest deleteDatabase(DOMString name); + [CallWith=ScriptState, RaisesException] IDBOpenDBRequest open(DOMString name, [EnforceRange] optional unsigned long long version); + [CallWith=ScriptState, RaisesException] IDBOpenDBRequest deleteDatabase(DOMString name); - [CallWith=ExecutionContext, RaisesException] short cmp(any first, any second); + [CallWith=ScriptState, RaisesException] short cmp(any first, any second); }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp index fad31a9ab8d..c9a27acae7f 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp @@ -32,13 +32,15 @@ #include "core/dom/ExecutionContext.h" #include "modules/indexeddb/IDBDatabase.h" #include "modules/indexeddb/IDBKey.h" +#include "modules/indexeddb/IDBObjectStore.h" #include "modules/indexeddb/IDBTracing.h" #include "modules/indexeddb/IDBTransaction.h" #include "modules/indexeddb/WebIDBCallbacksImpl.h" #include "public/platform/WebIDBKeyRange.h" -using blink::WebIDBDatabase; using blink::WebIDBCallbacks; +using blink::WebIDBCursor; +using blink::WebIDBDatabase; namespace WebCore { @@ -58,20 +60,25 @@ IDBIndex::~IDBIndex() { } -ScriptValue IDBIndex::keyPath(ExecutionContext* context) const +void IDBIndex::trace(Visitor* visitor) +{ + visitor->trace(m_objectStore); + visitor->trace(m_transaction); +} + +ScriptValue IDBIndex::keyPath(ScriptState* scriptState) const { - DOMRequestState requestState(context); - return idbAnyToScriptValue(&requestState, IDBAny::create(m_metadata.keyPath)); + return idbAnyToScriptValue(scriptState, IDBAny::create(m_metadata.keyPath)); } -PassRefPtr<IDBRequest> IDBIndex::openCursor(ExecutionContext* context, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState) +IDBRequest* IDBIndex::openCursor(ScriptState* scriptState, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState) { IDB_TRACE("IDBIndex::openCursor"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -79,33 +86,38 @@ PassRefPtr<IDBRequest> IDBIndex::openCursor(ExecutionContext* context, const Scr exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage); return 0; } - IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState); + blink::WebIDBCursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState); if (exceptionState.hadException()) return 0; - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState); if (exceptionState.hadException()) return 0; - return openCursor(context, keyRange.release(), direction); + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } + + return openCursor(scriptState, keyRange, direction); } -PassRefPtr<IDBRequest> IDBIndex::openCursor(ExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, IndexedDB::CursorDirection direction) +IDBRequest* IDBIndex::openCursor(ScriptState* scriptState, IDBKeyRange* keyRange, blink::WebIDBCursorDirection direction) { - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); request->setCursorDetails(IndexedDB::CursorKeyAndValue, direction); - backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, false, WebIDBDatabase::NormalTask, WebIDBCallbacksImpl::create(request).leakPtr()); + backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, false, blink::WebIDBTaskTypeNormal, WebIDBCallbacksImpl::create(request).leakPtr()); return request; } -PassRefPtr<IDBRequest> IDBIndex::count(ExecutionContext* context, const ScriptValue& range, ExceptionState& exceptionState) +IDBRequest* IDBIndex::count(ScriptState* scriptState, const ScriptValue& range, ExceptionState& exceptionState) { IDB_TRACE("IDBIndex::count"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -114,23 +126,28 @@ PassRefPtr<IDBRequest> IDBIndex::count(ExecutionContext* context, const ScriptVa return 0; } - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState); if (exceptionState.hadException()) return 0; - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); - backendDB()->count(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr()); + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } + + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); + backendDB()->count(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, WebIDBCallbacksImpl::create(request).leakPtr()); return request; } -PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ExecutionContext* context, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState) +IDBRequest* IDBIndex::openKeyCursor(ScriptState* scriptState, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState) { IDB_TRACE("IDBIndex::openKeyCursor"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -138,57 +155,43 @@ PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ExecutionContext* context, const exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage); return 0; } - IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState); + blink::WebIDBCursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState); if (exceptionState.hadException()) return 0; - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState); if (exceptionState.hadException()) return 0; + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); request->setCursorDetails(IndexedDB::CursorKeyOnly, direction); - backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange.release(), direction, true, WebIDBDatabase::NormalTask, WebIDBCallbacksImpl::create(request).leakPtr()); + backendDB()->openCursor(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, direction, true, blink::WebIDBTaskTypeNormal, WebIDBCallbacksImpl::create(request).leakPtr()); return request; } -PassRefPtr<IDBRequest> IDBIndex::get(ExecutionContext* context, const ScriptValue& key, ExceptionState& exceptionState) +IDBRequest* IDBIndex::get(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState) { IDB_TRACE("IDBIndex::get"); - if (isDeleted()) { - exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage); - return 0; - } - if (m_transaction->isFinished()) { - exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); - return 0; - } - if (!m_transaction->isActive()) { - exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage); - return 0; - } - - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, key, exceptionState); - if (exceptionState.hadException()) - return 0; - if (!keyRange) { - exceptionState.throwDOMException(DataError, IDBDatabase::noKeyOrKeyRangeErrorMessage); - return 0; - } - - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); - backendDB()->get(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange.release(), false, WebIDBCallbacksImpl::create(request).leakPtr()); - return request; + return getInternal(scriptState, key, exceptionState, false); } -PassRefPtr<IDBRequest> IDBIndex::getKey(ExecutionContext* context, const ScriptValue& key, ExceptionState& exceptionState) +IDBRequest* IDBIndex::getKey(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState) { IDB_TRACE("IDBIndex::getKey"); + return getInternal(scriptState, key, exceptionState, true); +} + +IDBRequest* IDBIndex::getInternal(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState, bool keyOnly) +{ if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::indexDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -197,16 +200,20 @@ PassRefPtr<IDBRequest> IDBIndex::getKey(ExecutionContext* context, const ScriptV return 0; } - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, key, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), key, exceptionState); if (exceptionState.hadException()) return 0; if (!keyRange) { exceptionState.throwDOMException(DataError, IDBDatabase::noKeyOrKeyRangeErrorMessage); return 0; } + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); - backendDB()->get(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange.release(), true, WebIDBCallbacksImpl::create(request).leakPtr()); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); + backendDB()->get(m_transaction->id(), m_objectStore->id(), m_metadata.id, keyRange, keyOnly, WebIDBCallbacksImpl::create(request).leakPtr()); return request; } diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.h index 2638de42748..d220351a268 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.h @@ -31,9 +31,10 @@ #include "modules/indexeddb/IDBKeyPath.h" #include "modules/indexeddb/IDBKeyRange.h" #include "modules/indexeddb/IDBMetadata.h" -#include "modules/indexeddb/IDBObjectStore.h" #include "modules/indexeddb/IDBRequest.h" +#include "public/platform/WebIDBCursor.h" #include "public/platform/WebIDBDatabase.h" +#include "public/platform/WebIDBTypes.h" #include "wtf/Forward.h" #include "wtf/text/WTFString.h" @@ -42,41 +43,44 @@ namespace WebCore { class ExceptionState; class IDBObjectStore; -class IDBIndex : public ScriptWrappable, public RefCounted<IDBIndex> { +class IDBIndex : public GarbageCollectedFinalized<IDBIndex>, public ScriptWrappable { public: - static PassRefPtr<IDBIndex> create(const IDBIndexMetadata& metadata, IDBObjectStore* objectStore, IDBTransaction* transaction) + static IDBIndex* create(const IDBIndexMetadata& metadata, IDBObjectStore* objectStore, IDBTransaction* transaction) { - return adoptRef(new IDBIndex(metadata, objectStore, transaction)); + return new IDBIndex(metadata, objectStore, transaction); } ~IDBIndex(); + void trace(Visitor*); // Implement the IDL const String& name() const { return m_metadata.name; } - PassRefPtr<IDBObjectStore> objectStore() const { return m_objectStore; } - ScriptValue keyPath(ExecutionContext*) const; + IDBObjectStore* objectStore() const { return m_objectStore.get(); } + ScriptValue keyPath(ScriptState*) const; bool unique() const { return m_metadata.unique; } bool multiEntry() const { return m_metadata.multiEntry; } - PassRefPtr<IDBRequest> openCursor(ExecutionContext*, const ScriptValue& key, const String& direction, ExceptionState&); - PassRefPtr<IDBRequest> openKeyCursor(ExecutionContext*, const ScriptValue& range, const String& direction, ExceptionState&); - PassRefPtr<IDBRequest> count(ExecutionContext*, const ScriptValue& range, ExceptionState&); - PassRefPtr<IDBRequest> get(ExecutionContext*, const ScriptValue& key, ExceptionState&); - PassRefPtr<IDBRequest> getKey(ExecutionContext*, const ScriptValue& key, ExceptionState&); + IDBRequest* openCursor(ScriptState*, const ScriptValue& key, const String& direction, ExceptionState&); + IDBRequest* openKeyCursor(ScriptState*, const ScriptValue& range, const String& direction, ExceptionState&); + IDBRequest* count(ScriptState*, const ScriptValue& range, ExceptionState&); + IDBRequest* get(ScriptState*, const ScriptValue& key, ExceptionState&); + IDBRequest* getKey(ScriptState*, const ScriptValue& key, ExceptionState&); void markDeleted() { m_deleted = true; } bool isDeleted() const; // Used internally and by InspectorIndexedDBAgent: - PassRefPtr<IDBRequest> openCursor(ExecutionContext*, PassRefPtr<IDBKeyRange>, IndexedDB::CursorDirection); + IDBRequest* openCursor(ScriptState*, IDBKeyRange*, blink::WebIDBCursorDirection); blink::WebIDBDatabase* backendDB() const; private: IDBIndex(const IDBIndexMetadata&, IDBObjectStore*, IDBTransaction*); + IDBRequest* getInternal(ScriptState*, const ScriptValue& key, ExceptionState&, bool keyOnly); + IDBIndexMetadata m_metadata; - RefPtr<IDBObjectStore> m_objectStore; - RefPtr<IDBTransaction> m_transaction; + Member<IDBObjectStore> m_objectStore; + Member<IDBTransaction> m_transaction; bool m_deleted; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.idl index d2607ab0972..5087716a127 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBIndex.idl @@ -24,17 +24,18 @@ */ [ + GarbageCollected ] interface IDBIndex { readonly attribute DOMString name; readonly attribute IDBObjectStore objectStore; - [CallWith=ExecutionContext] readonly attribute any keyPath; + [CallWith=ScriptState] readonly attribute any keyPath; readonly attribute boolean unique; readonly attribute boolean multiEntry; - [CallWith=ExecutionContext, RaisesException] IDBRequest openCursor([Default=Undefined] optional any range, [Default=NullString] optional DOMString direction); - [CallWith=ExecutionContext, RaisesException] IDBRequest openKeyCursor([Default=Undefined] optional any range, [Default=NullString] optional DOMString direction); + [CallWith=ScriptState, RaisesException] IDBRequest openCursor([Default=Undefined] optional any range, optional DOMString direction = null); + [CallWith=ScriptState, RaisesException] IDBRequest openKeyCursor([Default=Undefined] optional any range, optional DOMString direction = null); - [CallWith=ExecutionContext, RaisesException] IDBRequest get(any key); - [CallWith=ExecutionContext, RaisesException] IDBRequest getKey(any key); - [CallWith=ExecutionContext, RaisesException] IDBRequest count([Default=Undefined] optional any key); + [CallWith=ScriptState, RaisesException] IDBRequest get(any key); + [CallWith=ScriptState, RaisesException] IDBRequest getKey(any key); + [CallWith=ScriptState, RaisesException] IDBRequest count([Default=Undefined] optional any key); }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKey.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKey.cpp index b193a6bb090..bde037593f9 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKey.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKey.cpp @@ -32,6 +32,11 @@ IDBKey::~IDBKey() { } +void IDBKey::trace(Visitor* visitor) +{ + visitor->trace(m_array); +} + bool IDBKey::isValid() const { if (m_type == InvalidType) diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKey.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKey.h index 7c048a9da62..050dcb95577 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKey.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKey.h @@ -27,43 +27,43 @@ #define IDBKey_h #include "platform/SharedBuffer.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" -#include "wtf/RefCounted.h" #include "wtf/Vector.h" #include "wtf/text/WTFString.h" namespace WebCore { -class IDBKey : public RefCounted<IDBKey> { +class IDBKey : public GarbageCollectedFinalized<IDBKey> { public: - typedef Vector<RefPtr<IDBKey> > KeyArray; + typedef HeapVector<Member<IDBKey> > KeyArray; - static PassRefPtr<IDBKey> createInvalid() + static IDBKey* createInvalid() { - return adoptRef(new IDBKey()); + return new IDBKey(); } - static PassRefPtr<IDBKey> createNumber(double number) + static IDBKey* createNumber(double number) { - return adoptRef(new IDBKey(NumberType, number)); + return new IDBKey(NumberType, number); } - static PassRefPtr<IDBKey> createBinary(PassRefPtr<SharedBuffer> binary) + static IDBKey* createBinary(PassRefPtr<SharedBuffer> binary) { - return adoptRef(new IDBKey(binary)); + return new IDBKey(binary); } - static PassRefPtr<IDBKey> createString(const String& string) + static IDBKey* createString(const String& string) { - return adoptRef(new IDBKey(string)); + return new IDBKey(string); } - static PassRefPtr<IDBKey> createDate(double date) + static IDBKey* createDate(double date) { - return adoptRef(new IDBKey(DateType, date)); + return new IDBKey(DateType, date); } - static PassRefPtr<IDBKey> createMultiEntryArray(const KeyArray& array) + static IDBKey* createMultiEntryArray(const KeyArray& array) { KeyArray result; @@ -82,17 +82,18 @@ public: result.append(array[i]); } } - RefPtr<IDBKey> idbKey = adoptRef(new IDBKey(result)); + IDBKey* idbKey = new IDBKey(result); ASSERT(idbKey->isValid()); - return idbKey.release(); + return idbKey; } - static PassRefPtr<IDBKey> createArray(const KeyArray& array) + static IDBKey* createArray(const KeyArray& array) { - return adoptRef(new IDBKey(array)); + return new IDBKey(array); } ~IDBKey(); + void trace(Visitor*); // In order of the least to the highest precedent in terms of sort order. enum Type { @@ -142,9 +143,6 @@ public: bool isLessThan(const IDBKey* other) const; bool isEqual(const IDBKey* other) const; - using RefCounted<IDBKey>::ref; - using RefCounted<IDBKey>::deref; - private: IDBKey() : m_type(InvalidType), m_number(0) { } IDBKey(Type type, double number) : m_type(type), m_number(number) { } diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.cpp index 8764f09152d..1b8a2d8cf7d 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "modules/indexeddb/IDBKeyRange.h" -#include "bindings/v8/DOMRequestState.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/IDBBindingUtilities.h" #include "core/dom/ExceptionCode.h" @@ -34,26 +33,25 @@ namespace WebCore { -PassRefPtr<IDBKeyRange> IDBKeyRange::fromScriptValue(ExecutionContext* context, const ScriptValue& value, ExceptionState& exceptionState) +IDBKeyRange* IDBKeyRange::fromScriptValue(ExecutionContext* context, const ScriptValue& value, ExceptionState& exceptionState) { - DOMRequestState requestState(context); if (value.isUndefined() || value.isNull()) return 0; - RefPtr<IDBKeyRange> range = scriptValueToIDBKeyRange(&requestState, value); + IDBKeyRange* range = scriptValueToIDBKeyRange(toIsolate(context), value); if (range) - return range.release(); + return range; - RefPtr<IDBKey> key = scriptValueToIDBKey(&requestState, value); + IDBKey* key = scriptValueToIDBKey(toIsolate(context), value); if (!key || !key->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; } - return adoptRef(new IDBKeyRange(key, key, LowerBoundClosed, UpperBoundClosed)); + return new IDBKeyRange(key, key, LowerBoundClosed, UpperBoundClosed); } -IDBKeyRange::IDBKeyRange(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, LowerBoundType lowerType, UpperBoundType upperType) +IDBKeyRange::IDBKeyRange(IDBKey* lower, IDBKey* upper, LowerBoundType lowerType, UpperBoundType upperType) : m_lower(lower) , m_upper(upper) , m_lowerType(lowerType) @@ -62,21 +60,24 @@ IDBKeyRange::IDBKeyRange(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, Low ScriptWrappable::init(this); } -ScriptValue IDBKeyRange::lowerValue(ExecutionContext* context) const +void IDBKeyRange::trace(Visitor* visitor) { - DOMRequestState requestState(context); - return idbKeyToScriptValue(&requestState, m_lower); + visitor->trace(m_lower); + visitor->trace(m_upper); } -ScriptValue IDBKeyRange::upperValue(ExecutionContext* context) const +ScriptValue IDBKeyRange::lowerValue(ScriptState* scriptState) const { - DOMRequestState requestState(context); - return idbKeyToScriptValue(&requestState, m_upper); + return idbKeyToScriptValue(scriptState, m_lower); } -PassRefPtr<IDBKeyRange> IDBKeyRange::only(PassRefPtr<IDBKey> prpKey, ExceptionState& exceptionState) +ScriptValue IDBKeyRange::upperValue(ScriptState* scriptState) const +{ + return idbKeyToScriptValue(scriptState, m_upper); +} + +IDBKeyRange* IDBKeyRange::only(IDBKey* key, ExceptionState& exceptionState) { - RefPtr<IDBKey> key = prpKey; if (!key || !key->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; @@ -85,10 +86,9 @@ PassRefPtr<IDBKeyRange> IDBKeyRange::only(PassRefPtr<IDBKey> prpKey, ExceptionSt return IDBKeyRange::create(key, key, LowerBoundClosed, UpperBoundClosed); } -PassRefPtr<IDBKeyRange> IDBKeyRange::only(ExecutionContext* context, const ScriptValue& keyValue, ExceptionState& exceptionState) +IDBKeyRange* IDBKeyRange::only(ExecutionContext* context, const ScriptValue& keyValue, ExceptionState& exceptionState) { - DOMRequestState requestState(context); - RefPtr<IDBKey> key = scriptValueToIDBKey(&requestState, keyValue); + IDBKey* key = scriptValueToIDBKey(toIsolate(context), keyValue); if (!key || !key->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; @@ -97,10 +97,9 @@ PassRefPtr<IDBKeyRange> IDBKeyRange::only(ExecutionContext* context, const Scrip return IDBKeyRange::create(key, key, LowerBoundClosed, UpperBoundClosed); } -PassRefPtr<IDBKeyRange> IDBKeyRange::lowerBound(ExecutionContext* context, const ScriptValue& boundValue, bool open, ExceptionState& exceptionState) +IDBKeyRange* IDBKeyRange::lowerBound(ExecutionContext* context, const ScriptValue& boundValue, bool open, ExceptionState& exceptionState) { - DOMRequestState requestState(context); - RefPtr<IDBKey> bound = scriptValueToIDBKey(&requestState, boundValue); + IDBKey* bound = scriptValueToIDBKey(toIsolate(context), boundValue); if (!bound || !bound->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; @@ -109,10 +108,9 @@ PassRefPtr<IDBKeyRange> IDBKeyRange::lowerBound(ExecutionContext* context, const return IDBKeyRange::create(bound, 0, open ? LowerBoundOpen : LowerBoundClosed, UpperBoundOpen); } -PassRefPtr<IDBKeyRange> IDBKeyRange::upperBound(ExecutionContext* context, const ScriptValue& boundValue, bool open, ExceptionState& exceptionState) +IDBKeyRange* IDBKeyRange::upperBound(ExecutionContext* context, const ScriptValue& boundValue, bool open, ExceptionState& exceptionState) { - DOMRequestState requestState(context); - RefPtr<IDBKey> bound = scriptValueToIDBKey(&requestState, boundValue); + IDBKey* bound = scriptValueToIDBKey(toIsolate(context), boundValue); if (!bound || !bound->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; @@ -121,21 +119,20 @@ PassRefPtr<IDBKeyRange> IDBKeyRange::upperBound(ExecutionContext* context, const return IDBKeyRange::create(0, bound, LowerBoundOpen, open ? UpperBoundOpen : UpperBoundClosed); } -PassRefPtr<IDBKeyRange> IDBKeyRange::bound(ExecutionContext* context, const ScriptValue& lowerValue, const ScriptValue& upperValue, bool lowerOpen, bool upperOpen, ExceptionState& exceptionState) +IDBKeyRange* IDBKeyRange::bound(ExecutionContext* context, const ScriptValue& lowerValue, const ScriptValue& upperValue, bool lowerOpen, bool upperOpen, ExceptionState& exceptionState) { - DOMRequestState requestState(context); - RefPtr<IDBKey> lower = scriptValueToIDBKey(&requestState, lowerValue); - RefPtr<IDBKey> upper = scriptValueToIDBKey(&requestState, upperValue); + IDBKey* lower = scriptValueToIDBKey(toIsolate(context), lowerValue); + IDBKey* upper = scriptValueToIDBKey(toIsolate(context), upperValue); if (!lower || !lower->isValid() || !upper || !upper->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; } - if (upper->isLessThan(lower.get())) { + if (upper->isLessThan(lower)) { exceptionState.throwDOMException(DataError, "The lower key is greater than the upper key."); return 0; } - if (upper->isEqual(lower.get()) && (lowerOpen || upperOpen)) { + if (upper->isEqual(lower) && (lowerOpen || upperOpen)) { exceptionState.throwDOMException(DataError, "The lower key and upper key are equal and one of the bounds is open."); return 0; } diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.h index 59305176214..d383d99b27a 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.h @@ -36,7 +36,7 @@ namespace WebCore { class ExceptionState; -class IDBKeyRange : public ScriptWrappable, public RefCounted<IDBKeyRange> { +class IDBKeyRange : public GarbageCollectedFinalized<IDBKeyRange>, public ScriptWrappable { public: enum LowerBoundType { LowerBoundOpen, @@ -47,36 +47,37 @@ public: UpperBoundClosed }; - static PassRefPtr<IDBKeyRange> create(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, LowerBoundType lowerType, UpperBoundType upperType) + static IDBKeyRange* create(IDBKey* lower, IDBKey* upper, LowerBoundType lowerType, UpperBoundType upperType) { - return adoptRef(new IDBKeyRange(lower, upper, lowerType, upperType)); + return new IDBKeyRange(lower, upper, lowerType, upperType); } // Null if the script value is null or undefined, the range if it is one, otherwise tries to convert to a key and throws if it fails. - static PassRefPtr<IDBKeyRange> fromScriptValue(ExecutionContext*, const ScriptValue&, ExceptionState&); + static IDBKeyRange* fromScriptValue(ExecutionContext*, const ScriptValue&, ExceptionState&); ~IDBKeyRange() { } + void trace(Visitor*); // Implement the IDBKeyRange IDL - PassRefPtr<IDBKey> lower() const { return m_lower; } - PassRefPtr<IDBKey> upper() const { return m_upper; } + IDBKey* lower() const { return m_lower.get(); } + IDBKey* upper() const { return m_upper.get(); } - ScriptValue lowerValue(ExecutionContext*) const; - ScriptValue upperValue(ExecutionContext*) const; + ScriptValue lowerValue(ScriptState*) const; + ScriptValue upperValue(ScriptState*) const; bool lowerOpen() const { return m_lowerType == LowerBoundOpen; } bool upperOpen() const { return m_upperType == UpperBoundOpen; } - static PassRefPtr<IDBKeyRange> only(ExecutionContext*, const ScriptValue& key, ExceptionState&); - static PassRefPtr<IDBKeyRange> lowerBound(ExecutionContext*, const ScriptValue& bound, bool open, ExceptionState&); - static PassRefPtr<IDBKeyRange> upperBound(ExecutionContext*, const ScriptValue& bound, bool open, ExceptionState&); - static PassRefPtr<IDBKeyRange> bound(ExecutionContext*, const ScriptValue& lower, const ScriptValue& upper, bool lowerOpen, bool upperOpen, ExceptionState&); + static IDBKeyRange* only(ExecutionContext*, const ScriptValue& key, ExceptionState&); + static IDBKeyRange* lowerBound(ExecutionContext*, const ScriptValue& bound, bool open, ExceptionState&); + static IDBKeyRange* upperBound(ExecutionContext*, const ScriptValue& bound, bool open, ExceptionState&); + static IDBKeyRange* bound(ExecutionContext*, const ScriptValue& lower, const ScriptValue& upper, bool lowerOpen, bool upperOpen, ExceptionState&); - static PassRefPtr<IDBKeyRange> only(PassRefPtr<IDBKey> value, ExceptionState&); + static IDBKeyRange* only(IDBKey* value, ExceptionState&); private: - IDBKeyRange(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, LowerBoundType lowerType, UpperBoundType upperType); + IDBKeyRange(IDBKey* lower, IDBKey* upper, LowerBoundType lowerType, UpperBoundType upperType); - RefPtr<IDBKey> m_lower; - RefPtr<IDBKey> m_upper; + Member<IDBKey> m_lower; + Member<IDBKey> m_upper; LowerBoundType m_lowerType; UpperBoundType m_upperType; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl index 031bfca1280..fa3a088e9f2 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBKeyRange.idl @@ -24,9 +24,10 @@ */ [ + GarbageCollected ] interface IDBKeyRange { - [ImplementedAs=lowerValue,CallWith=ExecutionContext] readonly attribute any lower; - [ImplementedAs=upperValue,CallWith=ExecutionContext] readonly attribute any upper; + [ImplementedAs=lowerValue, CallWith=ScriptState] readonly attribute any lower; + [ImplementedAs=upperValue, CallWith=ScriptState] readonly attribute any upper; readonly attribute boolean lowerOpen; readonly attribute boolean upperOpen; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp index 5eec9b0c3ae..91f35eee1d8 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp @@ -40,12 +40,18 @@ #include "modules/indexeddb/IDBTracing.h" #include "modules/indexeddb/WebIDBCallbacksImpl.h" #include "platform/SharedBuffer.h" +#include "public/platform/WebBlobInfo.h" #include "public/platform/WebData.h" #include "public/platform/WebIDBKey.h" #include "public/platform/WebIDBKeyRange.h" +#include "public/platform/WebVector.h" +#include <v8.h> -using blink::WebIDBDatabase; +using blink::WebBlobInfo; using blink::WebIDBCallbacks; +using blink::WebIDBCursor; +using blink::WebIDBDatabase; +using blink::WebVector; namespace WebCore { @@ -55,35 +61,38 @@ IDBObjectStore::IDBObjectStore(const IDBObjectStoreMetadata& metadata, IDBTransa , m_deleted(false) { ASSERT(m_transaction); - // We pass a reference to this object before it can be adopted. - relaxAdoptionRequirement(); ScriptWrappable::init(this); } -ScriptValue IDBObjectStore::keyPath(ExecutionContext* context) const +void IDBObjectStore::trace(Visitor* visitor) +{ + visitor->trace(m_transaction); + visitor->trace(m_indexMap); +} + +ScriptValue IDBObjectStore::keyPath(ScriptState* scriptState) const { - DOMRequestState requestState(context); - return idbAnyToScriptValue(&requestState, IDBAny::create(m_metadata.keyPath)); + return idbAnyToScriptValue(scriptState, IDBAny::create(m_metadata.keyPath)); } -PassRefPtr<DOMStringList> IDBObjectStore::indexNames() const +PassRefPtrWillBeRawPtr<DOMStringList> IDBObjectStore::indexNames() const { IDB_TRACE("IDBObjectStore::indexNames"); - RefPtr<DOMStringList> indexNames = DOMStringList::create(); + RefPtrWillBeRawPtr<DOMStringList> indexNames = DOMStringList::create(); for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) indexNames->append(it->value.name); indexNames->sort(); return indexNames.release(); } -PassRefPtr<IDBRequest> IDBObjectStore::get(ExecutionContext* context, const ScriptValue& key, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::get(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::get"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -91,23 +100,27 @@ PassRefPtr<IDBRequest> IDBObjectStore::get(ExecutionContext* context, const Scri exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage); return 0; } - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, key, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), key, exceptionState); if (exceptionState.hadException()) return 0; if (!keyRange) { exceptionState.throwDOMException(DataError, IDBDatabase::noKeyOrKeyRangeErrorMessage); return 0; } + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); - backendDB()->get(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange.release(), false, WebIDBCallbacksImpl::create(request).leakPtr()); - return request.release(); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); + backendDB()->get(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange, false, WebIDBCallbacksImpl::create(request).leakPtr()); + return request; } -static void generateIndexKeysForValue(DOMRequestState* requestState, const IDBIndexMetadata& indexMetadata, const ScriptValue& objectValue, IDBObjectStore::IndexKeys* indexKeys) +static void generateIndexKeysForValue(v8::Isolate* isolate, const IDBIndexMetadata& indexMetadata, const ScriptValue& objectValue, IDBObjectStore::IndexKeys* indexKeys) { ASSERT(indexKeys); - RefPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(requestState, objectValue, indexMetadata.keyPath); + IDBKey* indexKey = createIDBKeyFromScriptValueAndKeyPath(isolate, objectValue, indexMetadata.keyPath); if (!indexKey) return; @@ -127,34 +140,31 @@ static void generateIndexKeysForValue(DOMRequestState* requestState, const IDBIn } } -PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptState* state, ScriptValue& value, const ScriptValue& key, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::add(ScriptState* scriptState, ScriptValue& value, const ScriptValue& key, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::add"); - return put(WebIDBDatabase::AddOnly, IDBAny::create(this), state, value, key, exceptionState); + return put(scriptState, blink::WebIDBPutModeAddOnly, IDBAny::create(this), value, key, exceptionState); } -PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptState* state, ScriptValue& value, const ScriptValue& key, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::put(ScriptState* scriptState, ScriptValue& value, const ScriptValue& key, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::put"); - return put(WebIDBDatabase::AddOrUpdate, IDBAny::create(this), state, value, key, exceptionState); + return put(scriptState, blink::WebIDBPutModeAddOrUpdate, IDBAny::create(this), value, key, exceptionState); } -PassRefPtr<IDBRequest> IDBObjectStore::put(WebIDBDatabase::PutMode putMode, PassRefPtr<IDBAny> source, ScriptState* state, ScriptValue& value, const ScriptValue& keyValue, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::put(ScriptState* scriptState, blink::WebIDBPutMode putMode, IDBAny* source, ScriptValue& value, const ScriptValue& keyValue, ExceptionState& exceptionState) { - ExecutionContext* context = state->executionContext(); - DOMRequestState requestState(context); - RefPtr<IDBKey> key = keyValue.isUndefined() ? 0 : scriptValueToIDBKey(&requestState, keyValue); - return put(putMode, source, state, value, key.release(), exceptionState); + IDBKey* key = keyValue.isUndefined() ? nullptr : scriptValueToIDBKey(scriptState->isolate(), keyValue); + return put(scriptState, putMode, source, value, key, exceptionState); } -PassRefPtr<IDBRequest> IDBObjectStore::put(WebIDBDatabase::PutMode putMode, PassRefPtr<IDBAny> source, ScriptState* state, ScriptValue& value, PassRefPtr<IDBKey> prpKey, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::put(ScriptState* scriptState, blink::WebIDBPutMode putMode, IDBAny* source, ScriptValue& value, IDBKey* key, ExceptionState& exceptionState) { - RefPtr<IDBKey> key = prpKey; if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -163,30 +173,20 @@ PassRefPtr<IDBRequest> IDBObjectStore::put(WebIDBDatabase::PutMode putMode, Pass return 0; } if (m_transaction->isReadOnly()) { - exceptionState.throwUninformativeAndGenericDOMException(ReadOnlyError); + exceptionState.throwDOMException(ReadOnlyError, IDBDatabase::transactionReadOnlyErrorMessage); return 0; } - // FIXME: Make SerializedScriptValue::create etc take an ExceptionState or use ScriptState::setDOMException. - bool didThrow = false; - RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(value, didThrow, state); - if (didThrow) - return 0; - - if (serializedValue->containsBlobs()) { - // FIXME: Add Blob/File/FileList support - exceptionState.throwUninformativeAndGenericDOMException(DataCloneError); + Vector<WebBlobInfo> blobInfo; + RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(value, &blobInfo, exceptionState, scriptState->isolate()); + if (exceptionState.hadException()) return 0; - } const IDBKeyPath& keyPath = m_metadata.keyPath; const bool usesInLineKeys = !keyPath.isNull(); const bool hasKeyGenerator = autoIncrement(); - ExecutionContext* context = state->executionContext(); - DOMRequestState requestState(context); - - if (putMode != WebIDBDatabase::CursorUpdate && usesInLineKeys && key) { + if (putMode != blink::WebIDBPutModeCursorUpdate && usesInLineKeys && key) { exceptionState.throwDOMException(DataError, "The object store uses in-line keys and the key parameter was provided."); return 0; } @@ -195,7 +195,7 @@ PassRefPtr<IDBRequest> IDBObjectStore::put(WebIDBDatabase::PutMode putMode, Pass return 0; } if (usesInLineKeys) { - RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(&requestState, value, keyPath); + IDBKey* keyPathKey = createIDBKeyFromScriptValueAndKeyPath(scriptState->isolate(), value, keyPath); if (keyPathKey && !keyPathKey->isValid()) { exceptionState.throwDOMException(DataError, "Evaluating the object store's key path yielded a value that is not a valid key."); return 0; @@ -205,7 +205,7 @@ PassRefPtr<IDBRequest> IDBObjectStore::put(WebIDBDatabase::PutMode putMode, Pass return 0; } if (hasKeyGenerator && !keyPathKey) { - if (!canInjectIDBKeyIntoScriptValue(&requestState, value, keyPath)) { + if (!canInjectIDBKeyIntoScriptValue(scriptState->isolate(), value, keyPath)) { exceptionState.throwDOMException(DataError, "A generated key could not be inserted into the value."); return 0; } @@ -218,31 +218,37 @@ PassRefPtr<IDBRequest> IDBObjectStore::put(WebIDBDatabase::PutMode putMode, Pass return 0; } + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } + Vector<int64_t> indexIds; - Vector<IndexKeys> indexKeys; + HeapVector<IndexKeys> indexKeys; for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) { IndexKeys keys; - generateIndexKeysForValue(&requestState, it->value, value, &keys); + generateIndexKeysForValue(scriptState->isolate(), it->value, value, &keys); indexIds.append(it->key); indexKeys.append(keys); } - RefPtr<IDBRequest> request = IDBRequest::create(context, source, m_transaction.get()); + IDBRequest* request = IDBRequest::create(scriptState, source, m_transaction.get()); Vector<char> wireBytes; serializedValue->toWireBytes(wireBytes); RefPtr<SharedBuffer> valueBuffer = SharedBuffer::adoptVector(wireBytes); - backendDB()->put(m_transaction->id(), id(), blink::WebData(valueBuffer), key.release(), static_cast<WebIDBDatabase::PutMode>(putMode), WebIDBCallbacksImpl::create(request).leakPtr(), indexIds, indexKeys); - return request.release(); + + backendDB()->put(m_transaction->id(), id(), blink::WebData(valueBuffer), blobInfo, key, static_cast<blink::WebIDBPutMode>(putMode), WebIDBCallbacksImpl::create(request).leakPtr(), indexIds, indexKeys); + return request; } -PassRefPtr<IDBRequest> IDBObjectStore::deleteFunction(ExecutionContext* context, const ScriptValue& key, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::deleteFunction(ScriptState* scriptState, const ScriptValue& key, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::delete"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -251,31 +257,35 @@ PassRefPtr<IDBRequest> IDBObjectStore::deleteFunction(ExecutionContext* context, return 0; } if (m_transaction->isReadOnly()) { - exceptionState.throwUninformativeAndGenericDOMException(ReadOnlyError); + exceptionState.throwDOMException(ReadOnlyError, IDBDatabase::transactionReadOnlyErrorMessage); return 0; } - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, key, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), key, exceptionState); if (exceptionState.hadException()) return 0; if (!keyRange) { exceptionState.throwDOMException(DataError, IDBDatabase::noKeyOrKeyRangeErrorMessage); return 0; } + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); - backendDB()->deleteRange(m_transaction->id(), id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr()); - return request.release(); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); + backendDB()->deleteRange(m_transaction->id(), id(), keyRange, WebIDBCallbacksImpl::create(request).leakPtr()); + return request; } -PassRefPtr<IDBRequest> IDBObjectStore::clear(ExecutionContext* context, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::clear(ScriptState* scriptState, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::clear"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -284,13 +294,17 @@ PassRefPtr<IDBRequest> IDBObjectStore::clear(ExecutionContext* context, Exceptio return 0; } if (m_transaction->isReadOnly()) { - exceptionState.throwUninformativeAndGenericDOMException(ReadOnlyError); + exceptionState.throwDOMException(ReadOnlyError, IDBDatabase::transactionReadOnlyErrorMessage); + return 0; + } + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); return 0; } - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); backendDB()->clear(m_transaction->id(), id(), WebIDBCallbacksImpl::create(request).leakPtr()); - return request.release(); + return request; } namespace { @@ -299,21 +313,22 @@ namespace { // the objectStore. It only needs to be kept alive by virtue of being // a listener on an IDBRequest object, in the same way that JavaScript // cursor success handlers are kept alive. -class IndexPopulator : public EventListener { +class IndexPopulator FINAL : public EventListener { public: - static PassRefPtr<IndexPopulator> create(PassRefPtr<IDBDatabase> database, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) + static PassRefPtr<IndexPopulator> create(ScriptState* scriptState, IDBDatabase* database, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) { - return adoptRef(new IndexPopulator(database, transactionId, objectStoreId, indexMetadata)); + return adoptRef(new IndexPopulator(scriptState, database, transactionId, objectStoreId, indexMetadata)); } - virtual bool operator==(const EventListener& other) + virtual bool operator==(const EventListener& other) OVERRIDE { return this == &other; } private: - IndexPopulator(PassRefPtr<IDBDatabase> database, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) + IndexPopulator(ScriptState* scriptState, IDBDatabase* database, int64_t transactionId, int64_t objectStoreId, const IDBIndexMetadata& indexMetadata) : EventListener(CPPEventListenerType) + , m_scriptState(scriptState) , m_database(database) , m_transactionId(transactionId) , m_objectStoreId(objectStoreId) @@ -321,32 +336,36 @@ private: { } - virtual void handleEvent(ExecutionContext* context, Event* event) + virtual void handleEvent(ExecutionContext* executionContext, Event* event) OVERRIDE { + ASSERT(m_scriptState->executionContext() == executionContext); ASSERT(event->type() == EventTypeNames::success); EventTarget* target = event->target(); IDBRequest* request = static_cast<IDBRequest*>(target); - RefPtr<IDBAny> cursorAny = request->resultAsAny(); - RefPtr<IDBCursorWithValue> cursor; + if (!m_database->backend()) // If database is stopped? + return; + + IDBAny* cursorAny = request->resultAsAny(); + IDBCursorWithValue* cursor = 0; if (cursorAny->type() == IDBAny::IDBCursorWithValueType) cursor = cursorAny->idbCursorWithValue(); Vector<int64_t> indexIds; indexIds.append(m_indexMetadata.id); - if (cursor) { + if (cursor && !cursor->isDeleted()) { cursor->continueFunction(static_cast<IDBKey*>(0), static_cast<IDBKey*>(0), ASSERT_NO_EXCEPTION); - RefPtr<IDBKey> primaryKey = cursor->idbPrimaryKey(); - ScriptValue value = cursor->value(context); + IDBKey* primaryKey = cursor->idbPrimaryKey(); + ScriptValue value = cursor->value(m_scriptState.get()); IDBObjectStore::IndexKeys indexKeys; - generateIndexKeysForValue(request->requestState(), m_indexMetadata, value, &indexKeys); + generateIndexKeysForValue(m_scriptState->isolate(), m_indexMetadata, value, &indexKeys); - Vector<IDBObjectStore::IndexKeys> indexKeysList; + HeapVector<IDBObjectStore::IndexKeys> indexKeysList; indexKeysList.append(indexKeys); - m_database->backend()->setIndexKeys(m_transactionId, m_objectStoreId, primaryKey.release(), indexIds, indexKeysList); + m_database->backend()->setIndexKeys(m_transactionId, m_objectStoreId, primaryKey, indexIds, indexKeysList); } else { // Now that we are done indexing, tell the backend to go // back to processing tasks of type NormalTask. @@ -356,14 +375,15 @@ private: } - RefPtr<IDBDatabase> m_database; + RefPtr<ScriptState> m_scriptState; + Persistent<IDBDatabase> m_database; const int64_t m_transactionId; const int64_t m_objectStoreId; const IDBIndexMetadata m_indexMetadata; }; } -PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ExecutionContext* context, const String& name, const IDBKeyPath& keyPath, const Dictionary& options, ExceptionState& exceptionState) +IDBIndex* IDBObjectStore::createIndex(ScriptState* scriptState, const String& name, const IDBKeyPath& keyPath, const Dictionary& options, ExceptionState& exceptionState) { bool unique = false; options.get("unique", unique); @@ -371,10 +391,10 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ExecutionContext* context, cons bool multiEntry = false; options.get("multiEntry", multiEntry); - return createIndex(context, name, keyPath, unique, multiEntry, exceptionState); + return createIndex(scriptState, name, keyPath, unique, multiEntry, exceptionState); } -PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ExecutionContext* context, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionState& exceptionState) +IDBIndex* IDBObjectStore::createIndex(ScriptState* scriptState, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::createIndex"); if (!m_transaction->isVersionChange()) { @@ -385,7 +405,7 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ExecutionContext* context, cons exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -398,7 +418,7 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ExecutionContext* context, cons return 0; } if (name.isNull()) { - exceptionState.throwUninformativeAndGenericTypeError(); + exceptionState.throwTypeError("The name provided is null."); return 0; } if (containsIndex(name)) { @@ -410,6 +430,10 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ExecutionContext* context, cons exceptionState.throwDOMException(InvalidAccessError, "The keyPath argument was an array and the multiEntry option is true."); return 0; } + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } int64_t indexId = m_metadata.maxIndexId + 1; backendDB()->createIndex(m_transaction->id(), id(), indexId, name, keyPath, unique, multiEntry); @@ -417,7 +441,7 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ExecutionContext* context, cons ++m_metadata.maxIndexId; IDBIndexMetadata metadata(name, indexId, keyPath, unique, multiEntry); - RefPtr<IDBIndex> index = IDBIndex::create(metadata, this, m_transaction.get()); + IDBIndex* index = IDBIndex::create(metadata, this, m_transaction.get()); m_indexMap.set(name, index); m_metadata.indexes.set(indexId, metadata); m_transaction->db()->indexCreated(id(), metadata); @@ -426,24 +450,23 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ExecutionContext* context, cons if (exceptionState.hadException()) return 0; - RefPtr<IDBRequest> indexRequest = openCursor(context, static_cast<IDBKeyRange*>(0), IndexedDB::CursorNext, WebIDBDatabase::PreemptiveTask); + IDBRequest* indexRequest = openCursor(scriptState, static_cast<IDBKeyRange*>(0), blink::WebIDBCursorDirectionNext, blink::WebIDBTaskTypePreemptive); indexRequest->preventPropagation(); // This is kept alive by being the success handler of the request, which is in turn kept alive by the owning transaction. - RefPtr<IndexPopulator> indexPopulator = IndexPopulator::create(transaction()->db(), m_transaction->id(), id(), metadata); + RefPtr<IndexPopulator> indexPopulator = IndexPopulator::create(scriptState, transaction()->db(), m_transaction->id(), id(), metadata); indexRequest->setOnsuccess(indexPopulator); - - return index.release(); + return index; } -PassRefPtr<IDBIndex> IDBObjectStore::index(const String& name, ExceptionState& exceptionState) +IDBIndex* IDBObjectStore::index(const String& name, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::index"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -468,9 +491,9 @@ PassRefPtr<IDBIndex> IDBObjectStore::index(const String& name, ExceptionState& e ASSERT(indexMetadata); ASSERT(indexMetadata->id != IDBIndexMetadata::InvalidId); - RefPtr<IDBIndex> index = IDBIndex::create(*indexMetadata, this, m_transaction.get()); + IDBIndex* index = IDBIndex::create(*indexMetadata, this, m_transaction.get()); m_indexMap.set(name, index); - return index.release(); + return index; } void IDBObjectStore::deleteIndex(const String& name, ExceptionState& exceptionState) @@ -484,7 +507,7 @@ void IDBObjectStore::deleteIndex(const String& name, ExceptionState& exceptionSt exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return; } @@ -497,6 +520,10 @@ void IDBObjectStore::deleteIndex(const String& name, ExceptionState& exceptionSt exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchIndexErrorMessage); return; } + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return; + } backendDB()->deleteIndex(m_transaction->id(), id(), indexId); @@ -509,14 +536,14 @@ void IDBObjectStore::deleteIndex(const String& name, ExceptionState& exceptionSt } } -PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ExecutionContext* context, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::openCursor(ScriptState* scriptState, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::openCursor"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -525,34 +552,39 @@ PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ExecutionContext* context, con return 0; } - IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState); + blink::WebIDBCursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState); if (exceptionState.hadException()) return 0; - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState); if (exceptionState.hadException()) return 0; - return openCursor(context, keyRange, direction, WebIDBDatabase::NormalTask); + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } + + return openCursor(scriptState, keyRange, direction, blink::WebIDBTaskTypeNormal); } -PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ExecutionContext* context, PassRefPtr<IDBKeyRange> range, IndexedDB::CursorDirection direction, WebIDBDatabase::TaskType taskType) +IDBRequest* IDBObjectStore::openCursor(ScriptState* scriptState, IDBKeyRange* range, blink::WebIDBCursorDirection direction, blink::WebIDBTaskType taskType) { - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); request->setCursorDetails(IndexedDB::CursorKeyAndValue, direction); backendDB()->openCursor(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, range, direction, false, taskType, WebIDBCallbacksImpl::create(request).leakPtr()); - return request.release(); + return request; } -PassRefPtr<IDBRequest> IDBObjectStore::openKeyCursor(ExecutionContext* context, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::openKeyCursor(ScriptState* scriptState, const ScriptValue& range, const String& directionString, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::openKeyCursor"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -561,29 +593,34 @@ PassRefPtr<IDBRequest> IDBObjectStore::openKeyCursor(ExecutionContext* context, return 0; } - IndexedDB::CursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState); + blink::WebIDBCursorDirection direction = IDBCursor::stringToDirection(directionString, exceptionState); if (exceptionState.hadException()) return 0; - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState); if (exceptionState.hadException()) return 0; - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } + + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); request->setCursorDetails(IndexedDB::CursorKeyOnly, direction); - backendDB()->openCursor(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange.release(), direction, true, WebIDBDatabase::NormalTask, WebIDBCallbacksImpl::create(request).leakPtr()); - return request.release(); + backendDB()->openCursor(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange, direction, true, blink::WebIDBTaskTypeNormal, WebIDBCallbacksImpl::create(request).leakPtr()); + return request; } -PassRefPtr<IDBRequest> IDBObjectStore::count(ExecutionContext* context, const ScriptValue& range, ExceptionState& exceptionState) +IDBRequest* IDBObjectStore::count(ScriptState* scriptState, const ScriptValue& range, ExceptionState& exceptionState) { IDB_TRACE("IDBObjectStore::count"); if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } - if (m_transaction->isFinished()) { + if (m_transaction->isFinished() || m_transaction->isFinishing()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } @@ -592,13 +629,18 @@ PassRefPtr<IDBRequest> IDBObjectStore::count(ExecutionContext* context, const Sc return 0; } - RefPtr<IDBKeyRange> keyRange = IDBKeyRange::fromScriptValue(context, range, exceptionState); + IDBKeyRange* keyRange = IDBKeyRange::fromScriptValue(scriptState->executionContext(), range, exceptionState); if (exceptionState.hadException()) return 0; - RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); - backendDB()->count(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr()); - return request.release(); + if (!backendDB()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return 0; + } + + IDBRequest* request = IDBRequest::create(scriptState, IDBAny::create(this), m_transaction.get()); + backendDB()->count(m_transaction->id(), id(), IDBIndexMetadata::InvalidId, keyRange, WebIDBCallbacksImpl::create(request).leakPtr()); + return request; } void IDBObjectStore::transactionFinished() diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.h index b9ca6a67ad0..33b4a144648 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.h @@ -36,9 +36,10 @@ #include "modules/indexeddb/IDBMetadata.h" #include "modules/indexeddb/IDBRequest.h" #include "modules/indexeddb/IDBTransaction.h" +#include "public/platform/WebIDBCursor.h" #include "public/platform/WebIDBDatabase.h" +#include "public/platform/WebIDBTypes.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" @@ -48,42 +49,49 @@ class DOMStringList; class IDBAny; class ExceptionState; -class IDBObjectStore : public ScriptWrappable, public RefCounted<IDBObjectStore> { +class IDBObjectStore : public GarbageCollectedFinalized<IDBObjectStore>, public ScriptWrappable { public: - static PassRefPtr<IDBObjectStore> create(const IDBObjectStoreMetadata& metadata, IDBTransaction* transaction) + static IDBObjectStore* create(const IDBObjectStoreMetadata& metadata, IDBTransaction* transaction) { - return adoptRef(new IDBObjectStore(metadata, transaction)); + return new IDBObjectStore(metadata, transaction); } ~IDBObjectStore() { } + void trace(Visitor*); // Implement the IDBObjectStore IDL int64_t id() const { return m_metadata.id; } const String& name() const { return m_metadata.name; } - ScriptValue keyPath(ExecutionContext*) const; - PassRefPtr<DOMStringList> indexNames() const; - PassRefPtr<IDBTransaction> transaction() const { return m_transaction; } + ScriptValue keyPath(ScriptState*) const; + PassRefPtrWillBeRawPtr<DOMStringList> indexNames() const; + IDBTransaction* transaction() const { return m_transaction.get(); } bool autoIncrement() const { return m_metadata.autoIncrement; } - PassRefPtr<IDBRequest> openCursor(ExecutionContext*, const ScriptValue& range, const String& direction, ExceptionState&); - PassRefPtr<IDBRequest> openKeyCursor(ExecutionContext*, const ScriptValue& range, const String& direction, ExceptionState&); - PassRefPtr<IDBRequest> get(ExecutionContext*, const ScriptValue& key, ExceptionState&); - PassRefPtr<IDBRequest> add(ScriptState*, ScriptValue&, const ScriptValue& key, ExceptionState&); - PassRefPtr<IDBRequest> put(ScriptState*, ScriptValue&, const ScriptValue& key, ExceptionState&); - PassRefPtr<IDBRequest> deleteFunction(ExecutionContext*, const ScriptValue& key, ExceptionState&); - PassRefPtr<IDBRequest> clear(ExecutionContext*, ExceptionState&); - - PassRefPtr<IDBIndex> createIndex(ExecutionContext* context, const String& name, const String& keyPath, const Dictionary& options, ExceptionState& exceptionState) { return createIndex(context, name, IDBKeyPath(keyPath), options, exceptionState); } - PassRefPtr<IDBIndex> createIndex(ExecutionContext* context, const String& name, const Vector<String>& keyPath, const Dictionary& options, ExceptionState& exceptionState) { return createIndex(context, name, IDBKeyPath(keyPath), options, exceptionState); } - PassRefPtr<IDBIndex> index(const String& name, ExceptionState&); + IDBRequest* openCursor(ScriptState*, const ScriptValue& range, const String& direction, ExceptionState&); + IDBRequest* openKeyCursor(ScriptState*, const ScriptValue& range, const String& direction, ExceptionState&); + IDBRequest* get(ScriptState*, const ScriptValue& key, ExceptionState&); + IDBRequest* add(ScriptState*, ScriptValue&, const ScriptValue& key, ExceptionState&); + IDBRequest* put(ScriptState*, ScriptValue&, const ScriptValue& key, ExceptionState&); + IDBRequest* deleteFunction(ScriptState*, const ScriptValue& key, ExceptionState&); + IDBRequest* clear(ScriptState*, ExceptionState&); + + IDBIndex* createIndex(ScriptState* scriptState, const String& name, const String& keyPath, const Dictionary& options, ExceptionState& exceptionState) + { + return createIndex(scriptState, name, IDBKeyPath(keyPath), options, exceptionState); + } + IDBIndex* createIndex(ScriptState* scriptState, const String& name, const Vector<String>& keyPath, const Dictionary& options, ExceptionState& exceptionState) + { + return createIndex(scriptState, name, IDBKeyPath(keyPath), options, exceptionState); + } + IDBIndex* index(const String& name, ExceptionState&); void deleteIndex(const String& name, ExceptionState&); - PassRefPtr<IDBRequest> count(ExecutionContext*, const ScriptValue& range, ExceptionState&); + IDBRequest* count(ScriptState*, const ScriptValue& range, ExceptionState&); // Used by IDBCursor::update(): - PassRefPtr<IDBRequest> put(blink::WebIDBDatabase::PutMode, PassRefPtr<IDBAny> source, ScriptState*, ScriptValue&, PassRefPtr<IDBKey>, ExceptionState&); + IDBRequest* put(ScriptState*, blink::WebIDBPutMode, IDBAny* source, ScriptValue&, IDBKey*, ExceptionState&); // Used internally and by InspectorIndexedDBAgent: - PassRefPtr<IDBRequest> openCursor(ExecutionContext*, PassRefPtr<IDBKeyRange>, IndexedDB::CursorDirection, blink::WebIDBDatabase::TaskType = blink::WebIDBDatabase::NormalTask); + IDBRequest* openCursor(ScriptState*, IDBKeyRange*, blink::WebIDBCursorDirection, blink::WebIDBTaskType = blink::WebIDBTaskTypeNormal); void markDeleted() { m_deleted = true; } bool isDeleted() const { return m_deleted; } @@ -92,17 +100,16 @@ public: const IDBObjectStoreMetadata& metadata() const { return m_metadata; } void setMetadata(const IDBObjectStoreMetadata& metadata) { m_metadata = metadata; } - typedef Vector<RefPtr<IDBKey> > IndexKeys; - typedef HashMap<String, IndexKeys> IndexKeyMap; + typedef HeapVector<Member<IDBKey> > IndexKeys; blink::WebIDBDatabase* backendDB() const; private: IDBObjectStore(const IDBObjectStoreMetadata&, IDBTransaction*); - PassRefPtr<IDBIndex> createIndex(ExecutionContext*, const String& name, const IDBKeyPath&, const Dictionary&, ExceptionState&); - PassRefPtr<IDBIndex> createIndex(ExecutionContext*, const String& name, const IDBKeyPath&, bool unique, bool multiEntry, ExceptionState&); - PassRefPtr<IDBRequest> put(blink::WebIDBDatabase::PutMode, PassRefPtr<IDBAny> source, ScriptState*, ScriptValue&, const ScriptValue& key, ExceptionState&); + IDBIndex* createIndex(ScriptState*, const String& name, const IDBKeyPath&, const Dictionary&, ExceptionState&); + IDBIndex* createIndex(ScriptState*, const String& name, const IDBKeyPath&, bool unique, bool multiEntry, ExceptionState&); + IDBRequest* put(ScriptState*, blink::WebIDBPutMode, IDBAny* source, ScriptValue&, const ScriptValue& key, ExceptionState&); int64_t findIndexId(const String& name) const; bool containsIndex(const String& name) const @@ -111,10 +118,10 @@ private: } IDBObjectStoreMetadata m_metadata; - RefPtr<IDBTransaction> m_transaction; + Member<IDBTransaction> m_transaction; bool m_deleted; - typedef HashMap<String, RefPtr<IDBIndex> > IDBIndexMap; + typedef HeapHashMap<String, Member<IDBIndex> > IDBIndexMap; IDBIndexMap m_indexMap; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.idl index daa79234f59..14bd1daf49c 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.idl @@ -23,25 +23,28 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// https://dvcs.w3.org/hg/IndexedDB/raw-file/default/Overview.html#idl-def-IDBObjectStore + [ + GarbageCollected, ] interface IDBObjectStore { [TreatReturnedNullStringAs=Null] readonly attribute DOMString name; - [CallWith=ExecutionContext] readonly attribute any keyPath; + [CallWith=ScriptState] readonly attribute any keyPath; readonly attribute DOMStringList indexNames; readonly attribute IDBTransaction transaction; readonly attribute boolean autoIncrement; [CallWith=ScriptState, RaisesException] IDBRequest put(any value, [Default=Undefined] optional any key); [CallWith=ScriptState, RaisesException] IDBRequest add(any value, [Default=Undefined] optional any key); - [CallWith=ExecutionContext, ImplementedAs=deleteFunction, RaisesException] IDBRequest delete(any key); - [CallWith=ExecutionContext, RaisesException] IDBRequest clear(); - [CallWith=ExecutionContext, RaisesException] IDBRequest get(any key); - [CallWith=ExecutionContext, RaisesException] IDBRequest openCursor([Default=Undefined] optional any range, [Default=NullString] optional DOMString direction); - [CallWith=ExecutionContext, RaisesException, RuntimeEnabled=IndexedDBExperimental] IDBRequest openKeyCursor([Default=Undefined] optional any range, [Default=NullString] optional DOMString direction); - - [CallWith=ExecutionContext, RaisesException] IDBIndex createIndex(DOMString name, sequence<DOMString> keyPath, optional Dictionary options); - [CallWith=ExecutionContext, RaisesException] IDBIndex createIndex(DOMString name, DOMString keyPath, optional Dictionary options); + [CallWith=ScriptState, ImplementedAs=deleteFunction, RaisesException] IDBRequest delete(any key); + [CallWith=ScriptState, RaisesException] IDBRequest get(any key); + [CallWith=ScriptState, RaisesException] IDBRequest clear(); + [CallWith=ScriptState, RaisesException] IDBRequest openCursor([Default=Undefined] optional any range, optional DOMString direction = null); + [CallWith=ScriptState, RaisesException, RuntimeEnabled=IndexedDBExperimental] IDBRequest openKeyCursor([Default=Undefined] optional any range, optional DOMString direction = null); + // FIXME: should be union type http://crbug.com/240176 + [CallWith=ScriptState, RaisesException] IDBIndex createIndex(DOMString name, DOMString keyPath, optional Dictionary options); + [CallWith=ScriptState, RaisesException] IDBIndex createIndex(DOMString name, sequence<DOMString> keyPath, optional Dictionary options); [RaisesException] IDBIndex index(DOMString name); [RaisesException] void deleteIndex(DOMString name); - [CallWith=ExecutionContext, RaisesException] IDBRequest count([Default=Undefined] optional any key); + [CallWith=ScriptState, RaisesException] IDBRequest count([Default=Undefined] optional any key); }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp index fa8d5cc6f12..42af143ddf0 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "modules/indexeddb/IDBOpenDBRequest.h" +#include "bindings/v8/Nullable.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" #include "modules/indexeddb/IDBDatabase.h" @@ -38,15 +39,15 @@ using blink::WebIDBDatabase; namespace WebCore { -PassRefPtr<IDBOpenDBRequest> IDBOpenDBRequest::create(ExecutionContext* context, PassRefPtr<IDBDatabaseCallbacks> callbacks, int64_t transactionId, int64_t version) +IDBOpenDBRequest* IDBOpenDBRequest::create(ScriptState* scriptState, IDBDatabaseCallbacks* callbacks, int64_t transactionId, int64_t version) { - RefPtr<IDBOpenDBRequest> request(adoptRef(new IDBOpenDBRequest(context, callbacks, transactionId, version))); + IDBOpenDBRequest* request = adoptRefCountedGarbageCollectedWillBeNoop(new IDBOpenDBRequest(scriptState, callbacks, transactionId, version)); request->suspendIfNeeded(); - return request.release(); + return request; } -IDBOpenDBRequest::IDBOpenDBRequest(ExecutionContext* context, PassRefPtr<IDBDatabaseCallbacks> callbacks, int64_t transactionId, int64_t version) - : IDBRequest(context, IDBAny::createNull(), 0) +IDBOpenDBRequest::IDBOpenDBRequest(ScriptState* scriptState, IDBDatabaseCallbacks* callbacks, int64_t transactionId, int64_t version) + : IDBRequest(scriptState, IDBAny::createNull(), 0) , m_databaseCallbacks(callbacks) , m_transactionId(transactionId) , m_version(version) @@ -59,6 +60,12 @@ IDBOpenDBRequest::~IDBOpenDBRequest() { } +void IDBOpenDBRequest::trace(Visitor* visitor) +{ + visitor->trace(m_databaseCallbacks); + IDBRequest::trace(visitor); +} + const AtomicString& IDBOpenDBRequest::interfaceName() const { return EventTargetNames::IDBOpenDBRequest; @@ -69,8 +76,8 @@ void IDBOpenDBRequest::onBlocked(int64_t oldVersion) IDB_TRACE("IDBOpenDBRequest::onBlocked()"); if (!shouldEnqueueEvent()) return; - RefPtr<IDBAny> newVersionAny = (m_version == IDBDatabaseMetadata::DefaultIntVersion) ? IDBAny::createNull() : IDBAny::create(m_version); - enqueueEvent(IDBVersionChangeEvent::create(IDBAny::create(oldVersion), newVersionAny.release(), EventTypeNames::blocked)); + Nullable<unsigned long long> newVersionNullable = (m_version == IDBDatabaseMetadata::DefaultIntVersion) ? Nullable<unsigned long long>() : Nullable<unsigned long long>(m_version); + enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::blocked, oldVersion, newVersionNullable)); } void IDBOpenDBRequest::onUpgradeNeeded(int64_t oldVersion, PassOwnPtr<WebIDBDatabase> backend, const IDBDatabaseMetadata& metadata, blink::WebIDBDataLoss dataLoss, String dataLossMessage) @@ -87,7 +94,7 @@ void IDBOpenDBRequest::onUpgradeNeeded(int64_t oldVersion, PassOwnPtr<WebIDBData ASSERT(m_databaseCallbacks); - RefPtr<IDBDatabase> idbDatabase = IDBDatabase::create(executionContext(), backend, m_databaseCallbacks.release()); + IDBDatabase* idbDatabase = IDBDatabase::create(executionContext(), backend, m_databaseCallbacks.release()); idbDatabase->setMetadata(metadata); if (oldVersion == IDBDatabaseMetadata::NoIntVersion) { @@ -97,12 +104,12 @@ void IDBOpenDBRequest::onUpgradeNeeded(int64_t oldVersion, PassOwnPtr<WebIDBData IDBDatabaseMetadata oldMetadata(metadata); oldMetadata.intVersion = oldVersion; - m_transaction = IDBTransaction::create(executionContext(), m_transactionId, idbDatabase.get(), this, oldMetadata); - setResult(IDBAny::create(idbDatabase.release())); + m_transaction = IDBTransaction::create(executionContext(), m_transactionId, idbDatabase, this, oldMetadata); + setResult(IDBAny::create(idbDatabase)); if (m_version == IDBDatabaseMetadata::NoIntVersion) m_version = 1; - enqueueEvent(IDBVersionChangeEvent::create(IDBAny::create(oldVersion), IDBAny::create(m_version), EventTypeNames::upgradeneeded, dataLoss, dataLossMessage)); + enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::upgradeneeded, oldVersion, m_version, dataLoss, dataLossMessage)); } void IDBOpenDBRequest::onSuccess(PassOwnPtr<WebIDBDatabase> backend, const IDBDatabaseMetadata& metadata) @@ -117,7 +124,7 @@ void IDBOpenDBRequest::onSuccess(PassOwnPtr<WebIDBDatabase> backend, const IDBDa if (!shouldEnqueueEvent()) return; - RefPtr<IDBDatabase> idbDatabase; + IDBDatabase* idbDatabase = 0; if (resultAsAny()) { // Previous onUpgradeNeeded call delivered the backend. ASSERT(!backend.get()); @@ -128,12 +135,25 @@ void IDBOpenDBRequest::onSuccess(PassOwnPtr<WebIDBDatabase> backend, const IDBDa ASSERT(backend.get()); ASSERT(m_databaseCallbacks); idbDatabase = IDBDatabase::create(executionContext(), backend, m_databaseCallbacks.release()); - setResult(IDBAny::create(idbDatabase.get())); + setResult(IDBAny::create(idbDatabase)); } idbDatabase->setMetadata(metadata); enqueueEvent(Event::create(EventTypeNames::success)); } +void IDBOpenDBRequest::onSuccess(int64_t oldVersion) +{ + IDB_TRACE("IDBOpenDBRequest::onSuccess()"); + if (!shouldEnqueueEvent()) + return; + if (oldVersion == IDBDatabaseMetadata::NoIntVersion) { + // This database hasn't had an integer version before. + oldVersion = IDBDatabaseMetadata::DefaultIntVersion; + } + setResult(IDBAny::createUndefined()); + enqueueEvent(IDBVersionChangeEvent::create(EventTypeNames::success, oldVersion, Nullable<unsigned long long>())); +} + bool IDBOpenDBRequest::shouldEnqueueEvent() const { if (m_contextStopped || !executionContext()) @@ -144,7 +164,7 @@ bool IDBOpenDBRequest::shouldEnqueueEvent() const return true; } -bool IDBOpenDBRequest::dispatchEvent(PassRefPtr<Event> event) +bool IDBOpenDBRequest::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { // If the connection closed between onUpgradeNeeded and the delivery of the "success" event, // an "error" event should be fired instead. diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.h index 221b1bba2f3..784d0d1ea5b 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.h @@ -33,20 +33,22 @@ namespace WebCore { class IDBDatabaseCallbacks; -class IDBOpenDBRequest : public IDBRequest { +class IDBOpenDBRequest FINAL : public IDBRequest { public: - static PassRefPtr<IDBOpenDBRequest> create(ExecutionContext*, PassRefPtr<IDBDatabaseCallbacks>, int64_t transactionId, int64_t version); + static IDBOpenDBRequest* create(ScriptState*, IDBDatabaseCallbacks*, int64_t transactionId, int64_t version); virtual ~IDBOpenDBRequest(); + virtual void trace(Visitor*) OVERRIDE; using IDBRequest::onSuccess; virtual void onBlocked(int64_t existingVersion) OVERRIDE; virtual void onUpgradeNeeded(int64_t oldVersion, PassOwnPtr<blink::WebIDBDatabase>, const IDBDatabaseMetadata&, blink::WebIDBDataLoss, String dataLossMessage) OVERRIDE; virtual void onSuccess(PassOwnPtr<blink::WebIDBDatabase>, const IDBDatabaseMetadata&) OVERRIDE; + virtual void onSuccess(int64_t oldVersion) OVERRIDE; // EventTarget - virtual const AtomicString& interfaceName() const; - virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE; + virtual const AtomicString& interfaceName() const OVERRIDE; + virtual bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>) OVERRIDE; DEFINE_ATTRIBUTE_EVENT_LISTENER(blocked); DEFINE_ATTRIBUTE_EVENT_LISTENER(upgradeneeded); @@ -55,9 +57,9 @@ protected: virtual bool shouldEnqueueEvent() const OVERRIDE; private: - IDBOpenDBRequest(ExecutionContext*, PassRefPtr<IDBDatabaseCallbacks>, int64_t transactionId, int64_t version); + IDBOpenDBRequest(ScriptState*, IDBDatabaseCallbacks*, int64_t transactionId, int64_t version); - RefPtr<IDBDatabaseCallbacks> m_databaseCallbacks; + Member<IDBDatabaseCallbacks> m_databaseCallbacks; const int64_t m_transactionId; int64_t m_version; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBPendingTransactionMonitor.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBPendingTransactionMonitor.cpp index 5c931bf275f..e336b4d36e4 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBPendingTransactionMonitor.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBPendingTransactionMonitor.cpp @@ -25,37 +25,46 @@ #include "config.h" #include "modules/indexeddb/IDBPendingTransactionMonitor.h" -#include "modules/indexeddb/IDBTransaction.h" -#include "wtf/ThreadSpecific.h" -#include "wtf/Threading.h" -using WTF::ThreadSpecific; +#include "core/dom/ExecutionContext.h" +#include "modules/indexeddb/IDBTransaction.h" namespace WebCore { -typedef Vector<RefPtr<IDBTransaction> > TransactionList; -static ThreadSpecific<TransactionList>& transactions() +const char* IDBPendingTransactionMonitor::supplementName() { - // FIXME: Move the Vector to ExecutionContext to avoid dealing with - // thread-local storage. - AtomicallyInitializedStatic(ThreadSpecific<TransactionList>*, transactions = new ThreadSpecific<TransactionList>); - return *transactions; + return "IDBPendingTransactionMonitor"; } -void IDBPendingTransactionMonitor::addNewTransaction(PassRefPtr<IDBTransaction> transaction) +inline IDBPendingTransactionMonitor::IDBPendingTransactionMonitor() { - transactions()->append(transaction); } -void IDBPendingTransactionMonitor::deactivateNewTransactions() +IDBPendingTransactionMonitor& IDBPendingTransactionMonitor::from(Supplementable<ExecutionContext>& context) { - ThreadSpecific<TransactionList>& list = transactions(); - for (size_t i = 0; i < list->size(); ++i) { - RefPtr<IDBTransaction> transaction = list->at(i); - transaction->setActive(false); + IDBPendingTransactionMonitor* supplement = static_cast<IDBPendingTransactionMonitor*>(Supplement<ExecutionContext>::from(context, supplementName())); + if (!supplement) { + supplement = new IDBPendingTransactionMonitor(); + provideTo(context, supplementName(), adoptPtr(supplement)); } + return *supplement; +} + +IDBPendingTransactionMonitor::~IDBPendingTransactionMonitor() +{ +} + +void IDBPendingTransactionMonitor::addNewTransaction(IDBTransaction& transaction) +{ + m_transactions.append(&transaction); +} + +void IDBPendingTransactionMonitor::deactivateNewTransactions() +{ + for (size_t i = 0; i < m_transactions.size(); ++i) + m_transactions[i]->setActive(false); // FIXME: Exercise this call to clear() in a layout test. - list->clear(); + m_transactions.clear(); } }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBPendingTransactionMonitor.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBPendingTransactionMonitor.h index a197fcb67fd..5ed0ffb450f 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBPendingTransactionMonitor.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBPendingTransactionMonitor.h @@ -26,11 +26,14 @@ #ifndef IDBPendingTransactionMonitor_h #define IDBPendingTransactionMonitor_h +#include "platform/Supplementable.h" #include "wtf/Noncopyable.h" +#include "wtf/PassOwnPtr.h" #include "wtf/Vector.h" namespace WebCore { +class ExecutionContext; class IDBTransaction; // This class keeps track of the transactions created during the current @@ -38,15 +41,24 @@ class IDBTransaction; // which is set to true on creation, but must be set to false when control // returns to the event loop. -class IDBPendingTransactionMonitor { +class IDBPendingTransactionMonitor : public Supplement<ExecutionContext> { WTF_MAKE_NONCOPYABLE(IDBPendingTransactionMonitor); public: - static void addNewTransaction(PassRefPtr<IDBTransaction>); - static void deactivateNewTransactions(); + static IDBPendingTransactionMonitor& from(Supplementable<ExecutionContext>&); + virtual ~IDBPendingTransactionMonitor(); + // The trace functino doesn't work until ExecutionContext is moved to Oilpan + // heap. + virtual void trace(Visitor* visitor) OVERRIDE { Supplement<ExecutionContext>::trace(visitor); } + void addNewTransaction(IDBTransaction&); + void deactivateNewTransactions(); private: IDBPendingTransactionMonitor(); + static const char* supplementName(); + + typedef PersistentHeapVector<Member<IDBTransaction> > TransactionList; + TransactionList m_transactions; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp index 6ae59586dca..03ffbbd78ef 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp @@ -39,34 +39,37 @@ #include "modules/indexeddb/IDBEventDispatcher.h" #include "modules/indexeddb/IDBTracing.h" #include "platform/SharedBuffer.h" +#include "public/platform/WebBlobInfo.h" + +using blink::WebIDBCursor; namespace WebCore { -PassRefPtr<IDBRequest> IDBRequest::create(ExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction) +IDBRequest* IDBRequest::create(ScriptState* scriptState, IDBAny* source, IDBTransaction* transaction) { - RefPtr<IDBRequest> request(adoptRef(new IDBRequest(context, source, transaction))); + IDBRequest* request = adoptRefCountedGarbageCollectedWillBeNoop(new IDBRequest(scriptState, source, transaction)); request->suspendIfNeeded(); // Requests associated with IDBFactory (open/deleteDatabase/getDatabaseNames) are not associated with transactions. if (transaction) - transaction->registerRequest(request.get()); - return request.release(); + transaction->registerRequest(request); + return request; } -IDBRequest::IDBRequest(ExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction) - : ActiveDOMObject(context) +IDBRequest::IDBRequest(ScriptState* scriptState, IDBAny* source, IDBTransaction* transaction) + : ActiveDOMObject(scriptState->executionContext()) , m_contextStopped(false) , m_transaction(transaction) , m_readyState(PENDING) , m_requestAborted(false) + , m_scriptState(scriptState) , m_source(source) , m_hasPendingActivity(true) , m_cursorType(IndexedDB::CursorKeyAndValue) - , m_cursorDirection(IndexedDB::CursorNext) - , m_pendingCursor(0) + , m_cursorDirection(blink::WebIDBCursorDirectionNext) + , m_pendingCursor(nullptr) , m_didFireUpgradeNeededEvent(false) , m_preventPropagation(false) , m_resultDirty(true) - , m_requestState(context) { ScriptWrappable::init(this); } @@ -74,6 +77,22 @@ IDBRequest::IDBRequest(ExecutionContext* context, PassRefPtr<IDBAny> source, IDB IDBRequest::~IDBRequest() { ASSERT(m_readyState == DONE || m_readyState == EarlyDeath || !executionContext()); + handleBlobAcks(); +} + +void IDBRequest::trace(Visitor* visitor) +{ + visitor->trace(m_transaction); + visitor->trace(m_source); + visitor->trace(m_result); + visitor->trace(m_error); +#if ENABLE(OILPAN) + visitor->trace(m_enqueuedEvents); +#endif + visitor->trace(m_pendingCursor); + visitor->trace(m_cursorKey); + visitor->trace(m_cursorPrimaryKey); + EventTargetWithInlineData::trace(visitor); } ScriptValue IDBRequest::result(ExceptionState& exceptionState) @@ -82,23 +101,29 @@ ScriptValue IDBRequest::result(ExceptionState& exceptionState) exceptionState.throwDOMException(InvalidStateError, IDBDatabase::requestNotFinishedErrorMessage); return ScriptValue(); } + if (m_contextStopped || !executionContext()) + return ScriptValue(); m_resultDirty = false; - return idbAnyToScriptValue(&m_requestState, m_result); + ScriptValue value = idbAnyToScriptValue(m_scriptState.get(), m_result); + handleBlobAcks(); + return value; } -PassRefPtr<DOMError> IDBRequest::error(ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<DOMError> IDBRequest::error(ExceptionState& exceptionState) const { if (m_readyState != DONE) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::requestNotFinishedErrorMessage); - return 0; + return nullptr; } return m_error; } -ScriptValue IDBRequest::source(ExecutionContext* context) const +ScriptValue IDBRequest::source() const { - DOMRequestState requestState(context); - return idbAnyToScriptValue(&requestState, m_source); + if (m_contextStopped || !executionContext()) + return ScriptValue(); + + return idbAnyToScriptValue(m_scriptState.get(), m_source); } const String& IDBRequest::readyState() const @@ -122,9 +147,6 @@ void IDBRequest::abort() if (m_readyState == DONE) return; - // Enqueued events may be the only reference to this object. - RefPtr<IDBRequest> self(this); - EventQueue* eventQueue = executionContext()->eventQueue(); for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) { bool removed = eventQueue->cancelEvent(m_enqueuedEvents[i].get()); @@ -138,7 +160,7 @@ void IDBRequest::abort() m_requestAborted = true; } -void IDBRequest::setCursorDetails(IndexedDB::CursorType cursorType, IndexedDB::CursorDirection direction) +void IDBRequest::setCursorDetails(IndexedDB::CursorType cursorType, blink::WebIDBCursorDirection direction) { ASSERT(m_readyState == PENDING); ASSERT(!m_pendingCursor); @@ -146,7 +168,7 @@ void IDBRequest::setCursorDetails(IndexedDB::CursorType cursorType, IndexedDB::C m_cursorDirection = direction; } -void IDBRequest::setPendingCursor(PassRefPtr<IDBCursor> cursor) +void IDBRequest::setPendingCursor(IDBCursor* cursor) { ASSERT(m_readyState == DONE); ASSERT(executionContext()); @@ -156,7 +178,7 @@ void IDBRequest::setPendingCursor(PassRefPtr<IDBCursor> cursor) m_hasPendingActivity = true; m_pendingCursor = cursor; - m_result.clear(); + setResult(0); m_readyState = PENDING; m_error.clear(); m_transaction->registerRequest(this); @@ -173,28 +195,24 @@ IDBCursor* IDBRequest::getResultCursor() const return 0; } -void IDBRequest::setResultCursor(PassRefPtr<IDBCursor> cursor, PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value) +void IDBRequest::setResultCursor(IDBCursor* cursor, IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<blink::WebBlobInfo> > blobInfo) { ASSERT(m_readyState == PENDING); m_cursorKey = key; m_cursorPrimaryKey = primaryKey; m_cursorValue = value; + ASSERT(!m_blobInfo.get()); + m_blobInfo = blobInfo; onSuccessInternal(IDBAny::create(cursor)); } -void IDBRequest::checkForReferenceCycle() +void IDBRequest::handleBlobAcks() { - // If this request and its cursor have the only references - // to each other, then explicitly break the cycle. - IDBCursor* cursor = getResultCursor(); - if (!cursor || cursor->request() != this) - return; - - if (!hasOneRef() || !cursor->hasOneRef()) - return; - - m_result.clear(); + if (m_blobInfo.get() && m_blobInfo->size()) { + m_transaction->db()->ackReceivedBlobs(m_blobInfo.get()); + m_blobInfo.clear(); + } } bool IDBRequest::shouldEnqueueEvent() const @@ -209,13 +227,14 @@ bool IDBRequest::shouldEnqueueEvent() const return true; } -void IDBRequest::onError(PassRefPtr<DOMError> error) +void IDBRequest::onError(PassRefPtrWillBeRawPtr<DOMError> error) { IDB_TRACE("IDBRequest::onError()"); if (!shouldEnqueueEvent()) return; m_error = error; + setResult(IDBAny::createUndefined()); m_pendingCursor.clear(); enqueueEvent(Event::createCancelableBubble(EventTypeNames::error)); } @@ -226,20 +245,20 @@ void IDBRequest::onSuccess(const Vector<String>& stringList) if (!shouldEnqueueEvent()) return; - RefPtr<DOMStringList> domStringList = DOMStringList::create(); + RefPtrWillBeRawPtr<DOMStringList> domStringList = DOMStringList::create(); for (size_t i = 0; i < stringList.size(); ++i) domStringList->append(stringList[i]); onSuccessInternal(IDBAny::create(domStringList.release())); } -void IDBRequest::onSuccess(PassOwnPtr<blink::WebIDBCursor> backend, PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value) +void IDBRequest::onSuccess(PassOwnPtr<blink::WebIDBCursor> backend, IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<blink::WebBlobInfo> > blobInfo) { IDB_TRACE("IDBRequest::onSuccess(IDBCursor)"); if (!shouldEnqueueEvent()) return; ASSERT(!m_pendingCursor); - RefPtr<IDBCursor> cursor; + IDBCursor* cursor = 0; switch (m_cursorType) { case IndexedDB::CursorKeyOnly: cursor = IDBCursor::create(backend, m_cursorDirection, this, m_source.get(), m_transaction.get()); @@ -250,10 +269,10 @@ void IDBRequest::onSuccess(PassOwnPtr<blink::WebIDBCursor> backend, PassRefPtr<I default: ASSERT_NOT_REACHED(); } - setResultCursor(cursor, key, primaryKey, value); + setResultCursor(cursor, key, primaryKey, value, blobInfo); } -void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey) +void IDBRequest::onSuccess(IDBKey* idbKey) { IDB_TRACE("IDBRequest::onSuccess(IDBKey)"); if (!shouldEnqueueEvent()) @@ -265,7 +284,7 @@ void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey) onSuccessInternal(IDBAny::createUndefined()); } -void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer) +void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer, PassOwnPtr<Vector<blink::WebBlobInfo> > blobInfo) { IDB_TRACE("IDBRequest::onSuccess(SharedBuffer)"); if (!shouldEnqueueEvent()) @@ -274,15 +293,18 @@ void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer) if (m_pendingCursor) { // Value should be null, signifying the end of the cursor's range. ASSERT(!valueBuffer.get()); + ASSERT(!blobInfo->size()); m_pendingCursor->close(); m_pendingCursor.clear(); } - onSuccessInternal(IDBAny::create(valueBuffer)); + ASSERT(!m_blobInfo.get()); + m_blobInfo = blobInfo; + onSuccessInternal(IDBAny::create(valueBuffer, m_blobInfo.get())); } #ifndef NDEBUG -static PassRefPtr<IDBObjectStore> effectiveObjectStore(PassRefPtr<IDBAny> source) +static IDBObjectStore* effectiveObjectStore(IDBAny* source) { if (source->type() == IDBAny::IDBObjectStoreType) return source->idbObjectStore(); @@ -294,7 +316,7 @@ static PassRefPtr<IDBObjectStore> effectiveObjectStore(PassRefPtr<IDBAny> source } #endif -void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> prpValueBuffer, PassRefPtr<IDBKey> prpPrimaryKey, const IDBKeyPath& keyPath) +void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> prpValueBuffer, PassOwnPtr<Vector<blink::WebBlobInfo> > blobInfo, IDBKey* prpPrimaryKey, const IDBKeyPath& keyPath) { IDB_TRACE("IDBRequest::onSuccess(SharedBuffer, IDBKey, IDBKeyPath)"); if (!shouldEnqueueEvent()) @@ -305,13 +327,15 @@ void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> prpValueBuffer, PassRefPtr<I #endif RefPtr<SharedBuffer> valueBuffer = prpValueBuffer; - RefPtr<IDBKey> primaryKey = prpPrimaryKey; + IDBKey* primaryKey = prpPrimaryKey; + ASSERT(!m_blobInfo.get()); + m_blobInfo = blobInfo; #ifndef NDEBUG - assertPrimaryKeyValidOrInjectable(&m_requestState, valueBuffer, primaryKey, keyPath); + assertPrimaryKeyValidOrInjectable(m_scriptState.get(), valueBuffer, m_blobInfo.get(), primaryKey, keyPath); #endif - onSuccessInternal(IDBAny::create(valueBuffer, primaryKey, keyPath)); + onSuccessInternal(IDBAny::create(valueBuffer, m_blobInfo.get(), primaryKey, keyPath)); } void IDBRequest::onSuccess(int64_t value) @@ -330,7 +354,7 @@ void IDBRequest::onSuccess() onSuccessInternal(IDBAny::createUndefined()); } -void IDBRequest::onSuccessInternal(PassRefPtr<IDBAny> result) +void IDBRequest::onSuccessInternal(IDBAny* result) { ASSERT(!m_contextStopped); ASSERT(!m_pendingCursor); @@ -338,20 +362,20 @@ void IDBRequest::onSuccessInternal(PassRefPtr<IDBAny> result) enqueueEvent(Event::create(EventTypeNames::success)); } -void IDBRequest::setResult(PassRefPtr<IDBAny> result) +void IDBRequest::setResult(IDBAny* result) { m_result = result; m_resultDirty = true; } -void IDBRequest::onSuccess(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value) +void IDBRequest::onSuccess(IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<blink::WebBlobInfo> > blobInfo) { IDB_TRACE("IDBRequest::onSuccess(key, primaryKey, value)"); if (!shouldEnqueueEvent()) return; ASSERT(m_pendingCursor); - setResultCursor(m_pendingCursor.release(), key, primaryKey, value); + setResultCursor(m_pendingCursor.release(), key, primaryKey, value, blobInfo); } bool IDBRequest::hasPendingActivity() const @@ -368,9 +392,6 @@ void IDBRequest::stop() return; m_contextStopped = true; - m_requestState.clear(); - - RefPtr<IDBRequest> protect(this); if (m_readyState == PENDING) { m_readyState = EarlyDeath; @@ -381,6 +402,12 @@ void IDBRequest::stop() } m_enqueuedEvents.clear(); + if (m_source) + m_source->contextWillBeDestroyed(); + if (m_result) + m_result->contextWillBeDestroyed(); + if (m_pendingCursor) + m_pendingCursor->contextWillBeDestroyed(); } const AtomicString& IDBRequest::interfaceName() const @@ -393,24 +420,23 @@ ExecutionContext* IDBRequest::executionContext() const return ActiveDOMObject::executionContext(); } -bool IDBRequest::dispatchEvent(PassRefPtr<Event> event) +bool IDBRequest::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { IDB_TRACE("IDBRequest::dispatchEvent"); if (m_contextStopped || !executionContext()) return false; - ASSERT(m_requestState.isValid()); ASSERT(m_readyState == PENDING); ASSERT(m_hasPendingActivity); ASSERT(m_enqueuedEvents.size()); ASSERT(event->target() == this); - DOMRequestState::Scope scope(m_requestState); + ScriptState::Scope scope(m_scriptState.get()); if (event->type() != EventTypeNames::blocked) m_readyState = DONE; dequeueEvent(event.get()); - Vector<RefPtr<EventTarget> > targets; + WillBeHeapVector<RefPtrWillBeMember<EventTarget> > targets; targets.append(this); if (m_transaction && !m_preventPropagation) { targets.append(m_transaction); @@ -422,11 +448,11 @@ bool IDBRequest::dispatchEvent(PassRefPtr<Event> event) } // Cursor properties should not be updated until the success event is being dispatched. - RefPtr<IDBCursor> cursorToNotify; + IDBCursor* cursorToNotify = 0; if (event->type() == EventTypeNames::success) { cursorToNotify = getResultCursor(); if (cursorToNotify) - cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release()); + cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release(), m_blobInfo.release()); } if (event->type() == EventTypeNames::upgradeneeded) { @@ -435,7 +461,7 @@ bool IDBRequest::dispatchEvent(PassRefPtr<Event> event) } // FIXME: When we allow custom event dispatching, this will probably need to change. - ASSERT_WITH_MESSAGE(event->type() == EventTypeNames::success || event->type() == EventTypeNames::error || event->type() == EventTypeNames::blocked || event->type() == EventTypeNames::upgradeneeded, "event type was %s", event->type().string().utf8().data()); + ASSERT_WITH_MESSAGE(event->type() == EventTypeNames::success || event->type() == EventTypeNames::error || event->type() == EventTypeNames::blocked || event->type() == EventTypeNames::upgradeneeded, "event type was %s", event->type().utf8().data()); const bool setTransactionActive = m_transaction && (event->type() == EventTypeNames::success || event->type() == EventTypeNames::upgradeneeded || (event->type() == EventTypeNames::error && !m_requestAborted)); if (setTransactionActive) @@ -493,14 +519,14 @@ void IDBRequest::transactionDidFinishAndDispatch() m_readyState = PENDING; } -void IDBRequest::enqueueEvent(PassRefPtr<Event> event) +void IDBRequest::enqueueEvent(PassRefPtrWillBeRawPtr<Event> event) { ASSERT(m_readyState == PENDING || m_readyState == DONE); if (m_contextStopped || !executionContext()) return; - ASSERT_WITH_MESSAGE(m_readyState == PENDING || m_didFireUpgradeNeededEvent, "When queueing event %s, m_readyState was %d", event->type().string().utf8().data(), m_readyState); + ASSERT_WITH_MESSAGE(m_readyState == PENDING || m_didFireUpgradeNeededEvent, "When queueing event %s, m_readyState was %d", event->type().utf8().data(), m_readyState); EventQueue* eventQueue = executionContext()->eventQueue(); event->setTarget(this); diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h index 6a3cbaa39e0..442257e3778 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h @@ -29,50 +29,49 @@ #ifndef IDBRequest_h #define IDBRequest_h -#include "bindings/v8/DOMRequestState.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" #include "core/dom/DOMError.h" #include "core/dom/DOMStringList.h" -#include "core/events/Event.h" #include "core/events/EventListener.h" #include "core/events/EventTarget.h" -#include "core/events/ThreadLocalEventNames.h" +#include "modules/EventModules.h" #include "modules/indexeddb/IDBAny.h" -#include "modules/indexeddb/IDBCursor.h" #include "modules/indexeddb/IDBTransaction.h" #include "modules/indexeddb/IndexedDB.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebBlobInfo.h" #include "public/platform/WebIDBCursor.h" +#include "public/platform/WebIDBTypes.h" namespace WebCore { class ExceptionState; +class IDBCursor; struct IDBDatabaseMetadata; class SharedBuffer; -// Base class to simplify usage of event target refcounting. -class IDBRequestBase : public WTF::RefCountedBase { +class IDBRequest + : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<IDBRequest> + , public ScriptWrappable + , public EventTargetWithInlineData + , public ActiveDOMObject { + DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<IDBRequest>); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(IDBRequest); public: - virtual void deref() = 0; - -protected: - virtual ~IDBRequestBase() { } -}; - -class IDBRequest : public IDBRequestBase, public ScriptWrappable, public EventTargetWithInlineData, public ActiveDOMObject { - DEFINE_EVENT_TARGET_REFCOUNTING(IDBRequestBase); - -public: - static PassRefPtr<IDBRequest> create(ExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*); + static IDBRequest* create(ScriptState*, IDBAny* source, IDBTransaction*); virtual ~IDBRequest(); + virtual void trace(Visitor*) OVERRIDE; ScriptValue result(ExceptionState&); - PassRefPtr<DOMError> error(ExceptionState&) const; - ScriptValue source(ExecutionContext*) const; - PassRefPtr<IDBTransaction> transaction() const { return m_transaction; } + PassRefPtrWillBeRawPtr<DOMError> error(ExceptionState&) const; + ScriptValue source() const; + IDBTransaction* transaction() const { return m_transaction.get(); } bool isResultDirty() const { return m_resultDirty; } - PassRefPtr<IDBAny> resultAsAny() const { return m_result; } + IDBAny* resultAsAny() const { return m_result; } // Requests made during index population are implementation details and so // events should not be visible to script. @@ -90,19 +89,19 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(success); DEFINE_ATTRIBUTE_EVENT_LISTENER(error); - void setCursorDetails(IndexedDB::CursorType, IndexedDB::CursorDirection); - void setPendingCursor(PassRefPtr<IDBCursor>); + void setCursorDetails(IndexedDB::CursorType, blink::WebIDBCursorDirection); + void setPendingCursor(IDBCursor*); void abort(); - virtual void onError(PassRefPtr<DOMError>); + virtual void onError(PassRefPtrWillBeRawPtr<DOMError>); virtual void onSuccess(const Vector<String>&); - virtual void onSuccess(PassOwnPtr<blink::WebIDBCursor>, PassRefPtr<IDBKey>, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer>); - virtual void onSuccess(PassRefPtr<IDBKey>); - virtual void onSuccess(PassRefPtr<SharedBuffer>); - virtual void onSuccess(PassRefPtr<SharedBuffer>, PassRefPtr<IDBKey>, const IDBKeyPath&); + virtual void onSuccess(PassOwnPtr<blink::WebIDBCursor>, IDBKey*, IDBKey* primaryKey, PassRefPtr<SharedBuffer>, PassOwnPtr<Vector<blink::WebBlobInfo> >); + virtual void onSuccess(IDBKey*); + virtual void onSuccess(PassRefPtr<SharedBuffer>, PassOwnPtr<Vector<blink::WebBlobInfo> >); + virtual void onSuccess(PassRefPtr<SharedBuffer>, PassOwnPtr<Vector<blink::WebBlobInfo> >, IDBKey*, const IDBKeyPath&); virtual void onSuccess(int64_t); virtual void onSuccess(); - virtual void onSuccess(PassRefPtr<IDBKey>, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer>); + virtual void onSuccess(IDBKey*, IDBKey* primaryKey, PassRefPtr<SharedBuffer>, PassOwnPtr<Vector<blink::WebBlobInfo> >); // Only IDBOpenDBRequest instances should receive these: virtual void onBlocked(int64_t oldVersion) { ASSERT_NOT_REACHED(); } @@ -110,72 +109,63 @@ public: virtual void onSuccess(PassOwnPtr<blink::WebIDBDatabase>, const IDBDatabaseMetadata&) { ASSERT_NOT_REACHED(); } // ActiveDOMObject - virtual bool hasPendingActivity() const OVERRIDE; - virtual void stop() OVERRIDE; + virtual bool hasPendingActivity() const OVERRIDE FINAL; + virtual void stop() OVERRIDE FINAL; // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE; - virtual ExecutionContext* executionContext() const OVERRIDE; - virtual void uncaughtExceptionInEventHandler() OVERRIDE; + virtual ExecutionContext* executionContext() const OVERRIDE FINAL; + virtual void uncaughtExceptionInEventHandler() OVERRIDE FINAL; using EventTarget::dispatchEvent; - virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE; + virtual bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>) OVERRIDE; // Called by a version change transaction that has finished to set this // request back from DONE (following "upgradeneeded") back to PENDING (for // the upcoming "success" or "error"). void transactionDidFinishAndDispatch(); - virtual void deref() OVERRIDE - { - if (derefBase()) - delete this; - else if (hasOneRef()) - checkForReferenceCycle(); - } - - DOMRequestState* requestState() { return &m_requestState; } IDBCursor* getResultCursor() const; protected: - IDBRequest(ExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*); - void enqueueEvent(PassRefPtr<Event>); + IDBRequest(ScriptState*, IDBAny* source, IDBTransaction*); + void enqueueEvent(PassRefPtrWillBeRawPtr<Event>); void dequeueEvent(Event*); virtual bool shouldEnqueueEvent() const; - void onSuccessInternal(PassRefPtr<IDBAny>); - void setResult(PassRefPtr<IDBAny>); + void onSuccessInternal(IDBAny*); + void setResult(IDBAny*); bool m_contextStopped; - RefPtr<IDBTransaction> m_transaction; + Member<IDBTransaction> m_transaction; ReadyState m_readyState; bool m_requestAborted; // May be aborted by transaction then receive async onsuccess; ignore vs. assert. private: - void setResultCursor(PassRefPtr<IDBCursor>, PassRefPtr<IDBKey>, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value); - void checkForReferenceCycle(); + void setResultCursor(IDBCursor*, IDBKey*, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<blink::WebBlobInfo> >); + void handleBlobAcks(); - RefPtr<IDBAny> m_source; - RefPtr<IDBAny> m_result; - RefPtr<DOMError> m_error; + RefPtr<ScriptState> m_scriptState; + Member<IDBAny> m_source; + Member<IDBAny> m_result; + RefPtrWillBeMember<DOMError> m_error; bool m_hasPendingActivity; - Vector<RefPtr<Event> > m_enqueuedEvents; + WillBeHeapVector<RefPtrWillBeMember<Event> > m_enqueuedEvents; // Only used if the result type will be a cursor. IndexedDB::CursorType m_cursorType; - IndexedDB::CursorDirection m_cursorDirection; + blink::WebIDBCursorDirection m_cursorDirection; // When a cursor is continued/advanced, m_result is cleared and m_pendingCursor holds it. - RefPtr<IDBCursor> m_pendingCursor; + Member<IDBCursor> m_pendingCursor; // New state is not applied to the cursor object until the event is dispatched. - RefPtr<IDBKey> m_cursorKey; - RefPtr<IDBKey> m_cursorPrimaryKey; + Member<IDBKey> m_cursorKey; + Member<IDBKey> m_cursorPrimaryKey; RefPtr<SharedBuffer> m_cursorValue; + OwnPtr<Vector<blink::WebBlobInfo> > m_blobInfo; bool m_didFireUpgradeNeededEvent; bool m_preventPropagation; bool m_resultDirty; - - DOMRequestState m_requestState; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl index 139810f3d86..a52b55b029c 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequest.idl @@ -28,12 +28,13 @@ */ [ - ActiveDOMObject + ActiveDOMObject, + GarbageCollected, ] interface IDBRequest : EventTarget { [RaisesException=Getter, CachedAttribute=isResultDirty] readonly attribute any result; [RaisesException=Getter] readonly attribute DOMError error; - [CallWith=ExecutionContext] readonly attribute any source; + readonly attribute any source; readonly attribute IDBTransaction transaction; // States diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp index b9f4343687c..cfcc1851d83 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp @@ -26,92 +26,77 @@ #include "config.h" #include "modules/indexeddb/IDBRequest.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8Binding.h" #include "core/dom/DOMError.h" -#include "core/dom/Document.h" -#include "core/events/EventQueue.h" +#include "core/dom/ExecutionContext.h" +#include "core/testing/NullExecutionContext.h" #include "modules/indexeddb/IDBDatabaseCallbacks.h" +#include "modules/indexeddb/IDBKey.h" #include "modules/indexeddb/IDBKeyRange.h" #include "modules/indexeddb/IDBOpenDBRequest.h" #include "platform/SharedBuffer.h" +#include "public/platform/WebBlobInfo.h" #include "public/platform/WebIDBDatabase.h" +#include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" +#include "wtf/PassRefPtr.h" +#include "wtf/Vector.h" +#include "wtf/dtoa/utils.h" #include <gtest/gtest.h> +#include <v8.h> +using blink::WebBlobInfo; using namespace WebCore; namespace { -class NullEventQueue : public EventQueue { -public: - NullEventQueue() { } - virtual ~NullEventQueue() { } - virtual bool enqueueEvent(PassRefPtr<Event>) OVERRIDE { return true; } - virtual bool cancelEvent(Event*) OVERRIDE { return true; } - virtual void close() OVERRIDE { } -}; - -class NullExecutionContext : public ExecutionContext, public RefCounted<NullExecutionContext> { -public: - using RefCounted<NullExecutionContext>::ref; - using RefCounted<NullExecutionContext>::deref; - - virtual void refExecutionContext() OVERRIDE { ref(); } - virtual void derefExecutionContext() OVERRIDE { deref(); } - virtual EventQueue* eventQueue() const OVERRIDE { return m_queue.get(); } - - NullExecutionContext(); -private: - OwnPtr<EventQueue> m_queue; -}; - -NullExecutionContext::NullExecutionContext() - : m_queue(adoptPtr(new NullEventQueue())) -{ -} - class IDBRequestTest : public testing::Test { public: IDBRequestTest() - : m_handleScope(v8::Isolate::GetCurrent()) - , m_scope(v8::Context::New(v8::Isolate::GetCurrent())) - , m_context(adoptRef(new NullExecutionContext())) + : m_scope(v8::Isolate::GetCurrent()) + , m_executionContext(adoptRefWillBeNoop(new NullExecutionContext())) { + m_scope.scriptState()->setExecutionContext(m_executionContext.get()); } - ExecutionContext* executionContext() + ~IDBRequestTest() { - return m_context.get(); + m_scope.scriptState()->setExecutionContext(0); } + v8::Isolate* isolate() const { return m_scope.isolate(); } + ScriptState* scriptState() const { return m_scope.scriptState(); } + ExecutionContext* executionContext() const { return m_scope.scriptState()->executionContext(); } + private: - v8::HandleScope m_handleScope; - v8::Context::Scope m_scope; - RefPtr<ExecutionContext> m_context; + V8TestingScope m_scope; + RefPtrWillBePersistent<ExecutionContext> m_executionContext; }; TEST_F(IDBRequestTest, EventsAfterStopping) { IDBTransaction* transaction = 0; - RefPtr<IDBRequest> request = IDBRequest::create(executionContext(), IDBAny::createUndefined(), transaction); + IDBRequest* request = IDBRequest::create(scriptState(), IDBAny::createUndefined(), transaction); EXPECT_EQ(request->readyState(), "pending"); executionContext()->stopActiveDOMObjects(); // Ensure none of the following raise assertions in stopped state: request->onError(DOMError::create(AbortError, "Description goes here.")); request->onSuccess(Vector<String>()); - request->onSuccess(nullptr, IDBKey::createInvalid(), IDBKey::createInvalid(), 0); + request->onSuccess(nullptr, IDBKey::createInvalid(), IDBKey::createInvalid(), nullptr, adoptPtr(new Vector<WebBlobInfo>())); request->onSuccess(IDBKey::createInvalid()); - request->onSuccess(PassRefPtr<SharedBuffer>(0)); - request->onSuccess(PassRefPtr<SharedBuffer>(0), IDBKey::createInvalid(), IDBKeyPath()); - request->onSuccess(0LL); + request->onSuccess(PassRefPtr<SharedBuffer>(nullptr), adoptPtr(new Vector<WebBlobInfo>())); + request->onSuccess(PassRefPtr<SharedBuffer>(nullptr), adoptPtr(new Vector<WebBlobInfo>()), IDBKey::createInvalid(), IDBKeyPath()); + request->onSuccess(static_cast<int64_t>(0)); request->onSuccess(); - request->onSuccess(IDBKey::createInvalid(), IDBKey::createInvalid(), 0); + request->onSuccess(IDBKey::createInvalid(), IDBKey::createInvalid(), nullptr, adoptPtr(new Vector<WebBlobInfo>())); } TEST_F(IDBRequestTest, AbortErrorAfterAbort) { IDBTransaction* transaction = 0; - RefPtr<IDBRequest> request = IDBRequest::create(executionContext(), IDBAny::createUndefined(), transaction); + IDBRequest* request = IDBRequest::create(scriptState(), IDBAny::createUndefined(), transaction); EXPECT_EQ(request->readyState(), "pending"); // Simulate the IDBTransaction having received onAbort from back end and aborting the request: @@ -154,11 +139,11 @@ TEST_F(IDBRequestTest, ConnectionsAfterStopping) const int64_t version = 1; const int64_t oldVersion = 0; const IDBDatabaseMetadata metadata; - RefPtr<IDBDatabaseCallbacks> callbacks = IDBDatabaseCallbacks::create(); + Persistent<IDBDatabaseCallbacks> callbacks = IDBDatabaseCallbacks::create(); { OwnPtr<MockWebIDBDatabase> backend = MockWebIDBDatabase::create(); - RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(executionContext(), callbacks, transactionId, version); + IDBOpenDBRequest* request = IDBOpenDBRequest::create(scriptState(), callbacks, transactionId, version); EXPECT_EQ(request->readyState(), "pending"); executionContext()->stopActiveDOMObjects(); @@ -167,7 +152,7 @@ TEST_F(IDBRequestTest, ConnectionsAfterStopping) { OwnPtr<MockWebIDBDatabase> backend = MockWebIDBDatabase::create(); - RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(executionContext(), callbacks, transactionId, version); + IDBOpenDBRequest* request = IDBOpenDBRequest::create(scriptState(), callbacks, transactionId, version); EXPECT_EQ(request->readyState(), "pending"); executionContext()->stopActiveDOMObjects(); diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp index 0b6efd00d36..2f8ee47fc7c 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp @@ -39,21 +39,23 @@ #include "modules/indexeddb/IDBPendingTransactionMonitor.h" #include "modules/indexeddb/IDBTracing.h" +using blink::WebIDBDatabase; + namespace WebCore { -PassRefPtr<IDBTransaction> IDBTransaction::create(ExecutionContext* context, int64_t id, const Vector<String>& objectStoreNames, IndexedDB::TransactionMode mode, IDBDatabase* db) +IDBTransaction* IDBTransaction::create(ExecutionContext* context, int64_t id, const Vector<String>& objectStoreNames, blink::WebIDBTransactionMode mode, IDBDatabase* db) { IDBOpenDBRequest* openDBRequest = 0; - RefPtr<IDBTransaction> transaction(adoptRef(new IDBTransaction(context, id, objectStoreNames, mode, db, openDBRequest, IDBDatabaseMetadata()))); + IDBTransaction* transaction = adoptRefCountedGarbageCollectedWillBeNoop(new IDBTransaction(context, id, objectStoreNames, mode, db, openDBRequest, IDBDatabaseMetadata())); transaction->suspendIfNeeded(); - return transaction.release(); + return transaction; } -PassRefPtr<IDBTransaction> IDBTransaction::create(ExecutionContext* context, int64_t id, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata) +IDBTransaction* IDBTransaction::create(ExecutionContext* context, int64_t id, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata) { - RefPtr<IDBTransaction> transaction(adoptRef(new IDBTransaction(context, id, Vector<String>(), IndexedDB::TransactionVersionChange, db, openDBRequest, previousMetadata))); + IDBTransaction* transaction = adoptRefCountedGarbageCollectedWillBeNoop(new IDBTransaction(context, id, Vector<String>(), blink::WebIDBTransactionModeVersionChange, db, openDBRequest, previousMetadata)); transaction->suspendIfNeeded(); - return transaction.release(); + return transaction; } const AtomicString& IDBTransaction::modeReadOnly() @@ -74,7 +76,7 @@ const AtomicString& IDBTransaction::modeVersionChange() return versionchange; } -IDBTransaction::IDBTransaction(ExecutionContext* context, int64_t id, const Vector<String>& objectStoreNames, IndexedDB::TransactionMode mode, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata) +IDBTransaction::IDBTransaction(ExecutionContext* context, int64_t id, const Vector<String>& objectStoreNames, blink::WebIDBTransactionMode mode, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata) : ActiveDOMObject(context) , m_id(id) , m_database(db) @@ -87,15 +89,13 @@ IDBTransaction::IDBTransaction(ExecutionContext* context, int64_t id, const Vect , m_previousMetadata(previousMetadata) { ScriptWrappable::init(this); - if (mode == IndexedDB::TransactionVersionChange) { + if (mode == blink::WebIDBTransactionModeVersionChange) { // Not active until the callback. m_state = Inactive; } - // We pass a reference of this object before it can be adopted. - relaxAdoptionRequirement(); if (m_state == Active) - IDBPendingTransactionMonitor::addNewTransaction(this); + IDBPendingTransactionMonitor::from(*context).addNewTransaction(*this); m_database->transactionCreated(this); } @@ -105,12 +105,24 @@ IDBTransaction::~IDBTransaction() ASSERT(m_requestList.isEmpty() || m_contextStopped); } +void IDBTransaction::trace(Visitor* visitor) +{ + visitor->trace(m_database); + visitor->trace(m_openDBRequest); + visitor->trace(m_error); + visitor->trace(m_requestList); + visitor->trace(m_objectStoreMap); + visitor->trace(m_deletedObjectStores); + visitor->trace(m_objectStoreCleanupMap); + EventTargetWithInlineData::trace(visitor); +} + const String& IDBTransaction::mode() const { return modeToString(m_mode); } -void IDBTransaction::setError(PassRefPtr<DOMError> error) +void IDBTransaction::setError(PassRefPtrWillBeRawPtr<DOMError> error) { ASSERT(m_state != Finished); ASSERT(error); @@ -122,7 +134,7 @@ void IDBTransaction::setError(PassRefPtr<DOMError> error) } } -PassRefPtr<IDBObjectStore> IDBTransaction::objectStore(const String& name, ExceptionState& exceptionState) +IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState& exceptionState) { if (m_state == Finished) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transactionFinishedErrorMessage); @@ -147,15 +159,14 @@ PassRefPtr<IDBObjectStore> IDBTransaction::objectStore(const String& name, Excep const IDBDatabaseMetadata& metadata = m_database->metadata(); - RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(metadata.objectStores.get(objectStoreId), this); + IDBObjectStore* objectStore = IDBObjectStore::create(metadata.objectStores.get(objectStoreId), this); objectStoreCreated(name, objectStore); - return objectStore.release(); + return objectStore; } -void IDBTransaction::objectStoreCreated(const String& name, PassRefPtr<IDBObjectStore> prpObjectStore) +void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* objectStore) { ASSERT(m_state != Finished); - RefPtr<IDBObjectStore> objectStore = prpObjectStore; m_objectStoreMap.set(name, objectStore); if (isVersionChange()) m_objectStoreCleanupMap.set(objectStore, objectStore->metadata()); @@ -167,7 +178,7 @@ void IDBTransaction::objectStoreDeleted(const String& name) ASSERT(isVersionChange()); IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name); if (it != m_objectStoreMap.end()) { - RefPtr<IDBObjectStore> objectStore = it->value; + IDBObjectStore* objectStore = it->value; m_objectStoreMap.remove(name); objectStore->markDeleted(); m_objectStoreCleanupMap.set(objectStore, objectStore->metadata()); @@ -183,7 +194,7 @@ void IDBTransaction::setActive(bool active) ASSERT(active != (m_state == Active)); m_state = active ? Active : Inactive; - if (!active && m_requestList.isEmpty()) + if (!active && m_requestList.isEmpty() && backendDB()) backendDB()->commit(m_id); } @@ -196,16 +207,17 @@ void IDBTransaction::abort(ExceptionState& exceptionState) m_state = Finishing; - if (!m_contextStopped) { - while (!m_requestList.isEmpty()) { - RefPtr<IDBRequest> request = *m_requestList.begin(); - m_requestList.remove(request); - request->abort(); - } + if (m_contextStopped) + return; + + while (!m_requestList.isEmpty()) { + IDBRequest* request = *m_requestList.begin(); + m_requestList.remove(request); + request->abort(); } - RefPtr<IDBTransaction> selfRef = this; - backendDB()->abort(m_id); + if (backendDB()) + backendDB()->abort(m_id); } void IDBTransaction::registerRequest(IDBRequest* request) @@ -222,10 +234,15 @@ void IDBTransaction::unregisterRequest(IDBRequest* request) m_requestList.remove(request); } -void IDBTransaction::onAbort(PassRefPtr<DOMError> prpError) +void IDBTransaction::onAbort(PassRefPtrWillBeRawPtr<DOMError> prpError) { IDB_TRACE("IDBTransaction::onAbort"); - RefPtr<DOMError> error = prpError; + if (m_contextStopped) { + m_database->transactionFinished(this); + return; + } + + RefPtrWillBeRawPtr<DOMError> error = prpError; ASSERT(m_state != Finished); if (m_state != Finishing) { @@ -235,7 +252,7 @@ void IDBTransaction::onAbort(PassRefPtr<DOMError> prpError) // Abort was not triggered by front-end, so outstanding requests must // be aborted now. while (!m_requestList.isEmpty()) { - RefPtr<IDBRequest> request = *m_requestList.begin(); + IDBRequest* request = *m_requestList.begin(); m_requestList.remove(request); request->abort(); } @@ -253,14 +270,17 @@ void IDBTransaction::onAbort(PassRefPtr<DOMError> prpError) // Enqueue events before notifying database, as database may close which enqueues more events and order matters. enqueueEvent(Event::createBubble(EventTypeNames::abort)); - // If script has stopped and GC has completed, database may have last reference to this object. - RefPtr<IDBTransaction> protect(this); m_database->transactionFinished(this); } void IDBTransaction::onComplete() { IDB_TRACE("IDBTransaction::onComplete"); + if (m_contextStopped) { + m_database->transactionFinished(this); + return; + } + ASSERT(m_state != Finished); m_state = Finishing; m_objectStoreCleanupMap.clear(); @@ -268,8 +288,6 @@ void IDBTransaction::onComplete() // Enqueue events before notifying database, as database may close which enqueues more events and order matters. enqueueEvent(Event::create(EventTypeNames::complete)); - // If script has stopped and GC has completed, database may have last reference to this object. - RefPtr<IDBTransaction> protect(this); m_database->transactionFinished(this); } @@ -281,30 +299,30 @@ bool IDBTransaction::hasPendingActivity() const return m_hasPendingActivity && !m_contextStopped; } -IndexedDB::TransactionMode IDBTransaction::stringToMode(const String& modeString, ExceptionState& exceptionState) +blink::WebIDBTransactionMode IDBTransaction::stringToMode(const String& modeString, ExceptionState& exceptionState) { if (modeString.isNull() || modeString == IDBTransaction::modeReadOnly()) - return IndexedDB::TransactionReadOnly; + return blink::WebIDBTransactionModeReadOnly; if (modeString == IDBTransaction::modeReadWrite()) - return IndexedDB::TransactionReadWrite; + return blink::WebIDBTransactionModeReadWrite; - exceptionState.throwUninformativeAndGenericTypeError(); - return IndexedDB::TransactionReadOnly; + exceptionState.throwTypeError("The mode provided ('" + modeString + "') is not one of 'readonly' or 'readwrite'."); + return blink::WebIDBTransactionModeReadOnly; } -const AtomicString& IDBTransaction::modeToString(IndexedDB::TransactionMode mode) +const AtomicString& IDBTransaction::modeToString(blink::WebIDBTransactionMode mode) { switch (mode) { - case IndexedDB::TransactionReadOnly: + case blink::WebIDBTransactionModeReadOnly: return IDBTransaction::modeReadOnly(); break; - case IndexedDB::TransactionReadWrite: + case blink::WebIDBTransactionModeReadWrite: return IDBTransaction::modeReadWrite(); break; - case IndexedDB::TransactionVersionChange: + case blink::WebIDBTransactionModeVersionChange: return IDBTransaction::modeVersionChange(); break; } @@ -323,9 +341,13 @@ ExecutionContext* IDBTransaction::executionContext() const return ActiveDOMObject::executionContext(); } -bool IDBTransaction::dispatchEvent(PassRefPtr<Event> event) +bool IDBTransaction::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { IDB_TRACE("IDBTransaction::dispatchEvent"); + if (m_contextStopped || !executionContext()) { + m_state = Finished; + return false; + } ASSERT(m_state != Finished); ASSERT(m_hasPendingActivity); ASSERT(executionContext()); @@ -340,7 +362,7 @@ bool IDBTransaction::dispatchEvent(PassRefPtr<Event> event) (*it)->transactionFinished(); m_deletedObjectStores.clear(); - Vector<RefPtr<EventTarget> > targets; + WillBeHeapVector<RefPtrWillBeMember<EventTarget> > targets; targets.append(this); targets.append(db()); @@ -367,9 +389,9 @@ void IDBTransaction::stop() abort(IGNORE_EXCEPTION); } -void IDBTransaction::enqueueEvent(PassRefPtr<Event> event) +void IDBTransaction::enqueueEvent(PassRefPtrWillBeRawPtr<Event> event) { - ASSERT_WITH_MESSAGE(m_state != Finished, "A finished transaction tried to enqueue an event of type %s.", event->type().string().utf8().data()); + ASSERT_WITH_MESSAGE(m_state != Finished, "A finished transaction tried to enqueue an event of type %s.", event->type().utf8().data()); if (m_contextStopped || !executionContext()) return; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h index 0359192529f..c0bbfed0376 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h @@ -29,15 +29,15 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" #include "core/dom/DOMError.h" -#include "core/events/Event.h" #include "core/events/EventListener.h" -#include "core/events/EventTarget.h" -#include "core/events/ThreadLocalEventNames.h" +#include "modules/EventModules.h" +#include "modules/EventTargetModules.h" #include "modules/indexeddb/IDBMetadata.h" #include "modules/indexeddb/IndexedDB.h" +#include "platform/heap/Handle.h" #include "public/platform/WebIDBDatabase.h" +#include "public/platform/WebIDBTypes.h" #include "wtf/HashSet.h" -#include "wtf/RefCounted.h" namespace WebCore { @@ -49,65 +49,72 @@ class IDBObjectStore; class IDBOpenDBRequest; struct IDBObjectStoreMetadata; -class IDBTransaction : public ScriptWrappable, public RefCounted<IDBTransaction>, public EventTargetWithInlineData, public ActiveDOMObject { - REFCOUNTED_EVENT_TARGET(IDBTransaction); - +class IDBTransaction FINAL + : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<IDBTransaction> + , public ScriptWrappable + , public EventTargetWithInlineData + , public ActiveDOMObject { + DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<IDBTransaction>); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(IDBTransaction); public: - static PassRefPtr<IDBTransaction> create(ExecutionContext*, int64_t, const Vector<String>& objectStoreNames, IndexedDB::TransactionMode, IDBDatabase*); - static PassRefPtr<IDBTransaction> create(ExecutionContext*, int64_t, IDBDatabase*, IDBOpenDBRequest*, const IDBDatabaseMetadata& previousMetadata); + static IDBTransaction* create(ExecutionContext*, int64_t, const Vector<String>& objectStoreNames, blink::WebIDBTransactionMode, IDBDatabase*); + static IDBTransaction* create(ExecutionContext*, int64_t, IDBDatabase*, IDBOpenDBRequest*, const IDBDatabaseMetadata& previousMetadata); virtual ~IDBTransaction(); + virtual void trace(Visitor*) OVERRIDE; static const AtomicString& modeReadOnly(); static const AtomicString& modeReadWrite(); static const AtomicString& modeVersionChange(); - static IndexedDB::TransactionMode stringToMode(const String&, ExceptionState&); - static const AtomicString& modeToString(IndexedDB::TransactionMode); + static blink::WebIDBTransactionMode stringToMode(const String&, ExceptionState&); + static const AtomicString& modeToString(blink::WebIDBTransactionMode); + // When the connection is closed backend will be 0. blink::WebIDBDatabase* backendDB() const; int64_t id() const { return m_id; } bool isActive() const { return m_state == Active; } bool isFinished() const { return m_state == Finished; } - bool isReadOnly() const { return m_mode == IndexedDB::TransactionReadOnly; } - bool isVersionChange() const { return m_mode == IndexedDB::TransactionVersionChange; } + bool isFinishing() const { return m_state == Finishing; } + bool isReadOnly() const { return m_mode == blink::WebIDBTransactionModeReadOnly; } + bool isVersionChange() const { return m_mode == blink::WebIDBTransactionModeVersionChange; } // Implement the IDBTransaction IDL const String& mode() const; IDBDatabase* db() const { return m_database.get(); } - PassRefPtr<DOMError> error() const { return m_error; } - PassRefPtr<IDBObjectStore> objectStore(const String& name, ExceptionState&); + PassRefPtrWillBeRawPtr<DOMError> error() const { return m_error; } + IDBObjectStore* objectStore(const String& name, ExceptionState&); void abort(ExceptionState&); void registerRequest(IDBRequest*); void unregisterRequest(IDBRequest*); - void objectStoreCreated(const String&, PassRefPtr<IDBObjectStore>); + void objectStoreCreated(const String&, IDBObjectStore*); void objectStoreDeleted(const String&); void setActive(bool); - void setError(PassRefPtr<DOMError>); + void setError(PassRefPtrWillBeRawPtr<DOMError>); DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); DEFINE_ATTRIBUTE_EVENT_LISTENER(complete); DEFINE_ATTRIBUTE_EVENT_LISTENER(error); - virtual void onAbort(PassRefPtr<DOMError>); - virtual void onComplete(); + void onAbort(PassRefPtrWillBeRawPtr<DOMError>); + void onComplete(); // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE; using EventTarget::dispatchEvent; - virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE; + virtual bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>) OVERRIDE; // ActiveDOMObject virtual bool hasPendingActivity() const OVERRIDE; virtual void stop() OVERRIDE; private: - IDBTransaction(ExecutionContext*, int64_t, const Vector<String>&, IndexedDB::TransactionMode, IDBDatabase*, IDBOpenDBRequest*, const IDBDatabaseMetadata&); + IDBTransaction(ExecutionContext*, int64_t, const Vector<String>&, blink::WebIDBTransactionMode, IDBDatabase*, IDBOpenDBRequest*, const IDBDatabaseMetadata&); - void enqueueEvent(PassRefPtr<Event>); + void enqueueEvent(PassRefPtrWillBeRawPtr<Event>); enum State { Inactive, // Created or started, but not in an event callback @@ -117,24 +124,24 @@ private: }; int64_t m_id; - RefPtr<IDBDatabase> m_database; + Member<IDBDatabase> m_database; const Vector<String> m_objectStoreNames; - IDBOpenDBRequest* m_openDBRequest; - const IndexedDB::TransactionMode m_mode; + Member<IDBOpenDBRequest> m_openDBRequest; + const blink::WebIDBTransactionMode m_mode; State m_state; bool m_hasPendingActivity; bool m_contextStopped; - RefPtr<DOMError> m_error; + RefPtrWillBeMember<DOMError> m_error; - ListHashSet<RefPtr<IDBRequest> > m_requestList; + HeapListHashSet<Member<IDBRequest> > m_requestList; - typedef HashMap<String, RefPtr<IDBObjectStore> > IDBObjectStoreMap; + typedef HeapHashMap<String, Member<IDBObjectStore> > IDBObjectStoreMap; IDBObjectStoreMap m_objectStoreMap; - typedef HashSet<RefPtr<IDBObjectStore> > IDBObjectStoreSet; + typedef HeapHashSet<Member<IDBObjectStore> > IDBObjectStoreSet; IDBObjectStoreSet m_deletedObjectStores; - typedef HashMap<RefPtr<IDBObjectStore>, IDBObjectStoreMetadata> IDBObjectStoreMetadataMap; + typedef HeapHashMap<Member<IDBObjectStore>, IDBObjectStoreMetadata> IDBObjectStoreMetadataMap; IDBObjectStoreMetadataMap m_objectStoreCleanupMap; IDBDatabaseMetadata m_previousMetadata; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.idl index 1787cb4ceda..f68c86e4dae 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.idl @@ -25,7 +25,8 @@ */ [ - ActiveDOMObject + ActiveDOMObject, + GarbageCollected ] interface IDBTransaction : EventTarget { // Properties diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp index a7d5e8bc82f..bb992f51e09 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp @@ -38,34 +38,39 @@ #include "modules/indexeddb/IDBPendingTransactionMonitor.h" #include "platform/SharedBuffer.h" #include "public/platform/WebIDBDatabase.h" - #include <gtest/gtest.h> +#include <v8.h> using namespace WebCore; +using blink::WebIDBDatabase; + namespace { class IDBTransactionTest : public testing::Test { public: IDBTransactionTest() - : m_handleScope(v8::Isolate::GetCurrent()) - , m_scope(v8::Context::New(v8::Isolate::GetCurrent())) - , m_document(Document::create()) + : m_scope(v8::Isolate::GetCurrent()) + , m_executionContext(Document::create()) { + m_scope.scriptState()->setExecutionContext(m_executionContext.get()); } - ExecutionContext* executionContext() + ~IDBTransactionTest() { - return m_document.get(); + m_scope.scriptState()->setExecutionContext(0); } + v8::Isolate* isolate() const { return m_scope.isolate(); } + ScriptState* scriptState() const { return m_scope.scriptState(); } + ExecutionContext* executionContext() { return m_scope.scriptState()->executionContext(); } + private: - v8::HandleScope m_handleScope; - v8::Context::Scope m_scope; - RefPtr<Document> m_document; + V8TestingScope m_scope; + RefPtrWillBePersistent<ExecutionContext> m_executionContext; }; -class FakeWebIDBDatabase : public blink::WebIDBDatabase { +class FakeWebIDBDatabase FINAL : public blink::WebIDBDatabase { public: static PassOwnPtr<FakeWebIDBDatabase> create() { return adoptPtr(new FakeWebIDBDatabase()); } @@ -77,12 +82,12 @@ private: FakeWebIDBDatabase() { } }; -class FakeIDBDatabaseCallbacks : public IDBDatabaseCallbacks { +class FakeIDBDatabaseCallbacks FINAL : public IDBDatabaseCallbacks { public: - static PassRefPtr<FakeIDBDatabaseCallbacks> create() { return adoptRef(new FakeIDBDatabaseCallbacks()); } + static FakeIDBDatabaseCallbacks* create() { return new FakeIDBDatabaseCallbacks(); } virtual void onVersionChange(int64_t oldVersion, int64_t newVersion) OVERRIDE { } virtual void onForcedClose() OVERRIDE { } - virtual void onAbort(int64_t transactionId, PassRefPtr<DOMError> error) OVERRIDE { } + virtual void onAbort(int64_t transactionId, PassRefPtrWillBeRawPtr<DOMError> error) OVERRIDE { } virtual void onComplete(int64_t transactionId) OVERRIDE { } private: FakeIDBDatabaseCallbacks() { } @@ -91,53 +96,56 @@ private: TEST_F(IDBTransactionTest, EnsureLifetime) { OwnPtr<FakeWebIDBDatabase> backend = FakeWebIDBDatabase::create(); - RefPtr<FakeIDBDatabaseCallbacks> connection = FakeIDBDatabaseCallbacks::create(); - RefPtr<IDBDatabase> db = IDBDatabase::create(executionContext(), backend.release(), connection); + Persistent<IDBDatabase> db = IDBDatabase::create(executionContext(), backend.release(), FakeIDBDatabaseCallbacks::create()); const int64_t transactionId = 1234; const Vector<String> transactionScope; - RefPtr<IDBTransaction> transaction = IDBTransaction::create(executionContext(), transactionId, transactionScope, IndexedDB::TransactionReadOnly, db.get()); + Persistent<IDBTransaction> transaction = IDBTransaction::create(executionContext(), transactionId, transactionScope, blink::WebIDBTransactionModeReadOnly, db.get()); + PersistentHeapHashSet<WeakMember<IDBTransaction> > set; + set.add(transaction); - // Local reference, IDBDatabase's reference and IDBPendingTransactionMonitor's reference: - EXPECT_EQ(3, transaction->refCount()); + Heap::collectAllGarbage(); + EXPECT_EQ(1u, set.size()); - RefPtr<IDBRequest> request = IDBRequest::create(executionContext(), IDBAny::createUndefined(), transaction.get()); - IDBPendingTransactionMonitor::deactivateNewTransactions(); + Persistent<IDBRequest> request = IDBRequest::create(scriptState(), IDBAny::createUndefined(), transaction.get()); + IDBPendingTransactionMonitor::from(*executionContext()).deactivateNewTransactions(); - // Local reference, IDBDatabase's reference, and the IDBRequest's reference - EXPECT_EQ(3, transaction->refCount()); + Heap::collectAllGarbage(); + EXPECT_EQ(1u, set.size()); // This will generate an abort() call to the back end which is dropped by the fake proxy, // so an explicit onAbort call is made. executionContext()->stopActiveDOMObjects(); transaction->onAbort(DOMError::create(AbortError, "Aborted")); + transaction.clear(); - EXPECT_EQ(1, transaction->refCount()); + Heap::collectAllGarbage(); + EXPECT_EQ(0u, set.size()); } TEST_F(IDBTransactionTest, TransactionFinish) { OwnPtr<FakeWebIDBDatabase> backend = FakeWebIDBDatabase::create(); - RefPtr<FakeIDBDatabaseCallbacks> connection = FakeIDBDatabaseCallbacks::create(); - RefPtr<IDBDatabase> db = IDBDatabase::create(executionContext(), backend.release(), connection); + Persistent<IDBDatabase> db = IDBDatabase::create(executionContext(), backend.release(), FakeIDBDatabaseCallbacks::create()); const int64_t transactionId = 1234; const Vector<String> transactionScope; - RefPtr<IDBTransaction> transaction = IDBTransaction::create(executionContext(), transactionId, transactionScope, IndexedDB::TransactionReadOnly, db.get()); + Persistent<IDBTransaction> transaction = IDBTransaction::create(executionContext(), transactionId, transactionScope, blink::WebIDBTransactionModeReadOnly, db.get()); + PersistentHeapHashSet<WeakMember<IDBTransaction> > set; + set.add(transaction); - // Local reference, IDBDatabase's reference and IDBPendingTransactionMonitor's reference: - EXPECT_EQ(3, transaction->refCount()); + Heap::collectAllGarbage(); + EXPECT_EQ(1u, set.size()); - IDBPendingTransactionMonitor::deactivateNewTransactions(); + IDBPendingTransactionMonitor::from(*executionContext()).deactivateNewTransactions(); - // Local reference, IDBDatabase's reference - EXPECT_EQ(2, transaction->refCount()); + Heap::collectAllGarbage(); + EXPECT_EQ(1u, set.size()); - IDBTransaction* transactionPtr = transaction.get(); transaction.clear(); - // IDBDatabase's reference - EXPECT_EQ(1, transactionPtr->refCount()); + Heap::collectAllGarbage(); + EXPECT_EQ(1u, set.size()); // Stop the context, so events don't get queued (which would keep the transaction alive). executionContext()->stopActiveDOMObjects(); @@ -145,6 +153,10 @@ TEST_F(IDBTransactionTest, TransactionFinish) // Fire an abort to make sure this doesn't free the transaction during use. The test // will not fail if it is, but ASAN would notice the error. db->onAbort(transactionId, DOMError::create(AbortError, "Aborted")); + + // onAbort() should have cleared the transaction's reference to the database. + Heap::collectAllGarbage(); + EXPECT_EQ(0u, set.size()); } } // namespace diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.cpp index 798b9ac4c40..e1802055dbe 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.cpp @@ -27,16 +27,22 @@ #include "modules/indexeddb/IDBVersionChangeEvent.h" #include "bindings/v8/IDBBindingUtilities.h" -#include "core/events/ThreadLocalEventNames.h" namespace WebCore { -PassRefPtr<IDBVersionChangeEvent> IDBVersionChangeEvent::create(PassRefPtr<IDBAny> oldVersion, PassRefPtr<IDBAny> newVersion, const AtomicString& eventType, blink::WebIDBDataLoss dataLoss, const String& dataLossMessage) + +IDBVersionChangeEventInit::IDBVersionChangeEventInit() + : oldVersion(0) { - return adoptRef(new IDBVersionChangeEvent(oldVersion, newVersion, eventType, dataLoss, dataLossMessage)); } -IDBVersionChangeEvent::IDBVersionChangeEvent(PassRefPtr<IDBAny> oldVersion, PassRefPtr<IDBAny> newVersion, const AtomicString& eventType, blink::WebIDBDataLoss dataLoss, const String& dataLossMessage) +IDBVersionChangeEvent::IDBVersionChangeEvent() + : m_dataLoss(blink::WebIDBDataLossNone) +{ + ScriptWrappable::init(this); +} + +IDBVersionChangeEvent::IDBVersionChangeEvent(const AtomicString& eventType, unsigned long long oldVersion, const Nullable<unsigned long long>& newVersion, blink::WebIDBDataLoss dataLoss, const String& dataLossMessage) : Event(eventType, false /*canBubble*/, false /*cancelable*/) , m_oldVersion(oldVersion) , m_newVersion(newVersion) @@ -46,20 +52,19 @@ IDBVersionChangeEvent::IDBVersionChangeEvent(PassRefPtr<IDBAny> oldVersion, Pass ScriptWrappable::init(this); } -IDBVersionChangeEvent::~IDBVersionChangeEvent() -{ -} - -ScriptValue IDBVersionChangeEvent::oldVersion(ExecutionContext* context) const +IDBVersionChangeEvent::IDBVersionChangeEvent(const AtomicString& eventType, const IDBVersionChangeEventInit& initializer) + : Event(eventType, false /*canBubble*/, false /*cancelable*/) + , m_oldVersion(initializer.oldVersion) + , m_newVersion(initializer.newVersion) + , m_dataLoss(blink::WebIDBDataLossNone) { - DOMRequestState requestState(context); - return idbAnyToScriptValue(&requestState, m_oldVersion); + ScriptWrappable::init(this); } -ScriptValue IDBVersionChangeEvent::newVersion(ExecutionContext* context) const +unsigned long long IDBVersionChangeEvent::newVersion(bool& isNull) const { - DOMRequestState requestState(context); - return idbAnyToScriptValue(&requestState, m_newVersion); + isNull = m_newVersion.isNull(); + return isNull ? 0 : m_newVersion.get(); } const AtomicString& IDBVersionChangeEvent::dataLoss() const @@ -76,4 +81,9 @@ const AtomicString& IDBVersionChangeEvent::interfaceName() const return EventNames::IDBVersionChangeEvent; } +void IDBVersionChangeEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.h index 1c00b0574d1..dfc333a307a 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.h @@ -26,7 +26,9 @@ #ifndef IDBVersionChangeEvent_h #define IDBVersionChangeEvent_h -#include "core/events/Event.h" +#include "bindings/v8/Nullable.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "modules/EventModules.h" #include "modules/indexeddb/IDBAny.h" #include "modules/indexeddb/IDBRequest.h" #include "public/platform/WebIDBTypes.h" @@ -36,23 +38,45 @@ namespace WebCore { -class IDBVersionChangeEvent : public Event { +struct IDBVersionChangeEventInit : public EventInit { + IDBVersionChangeEventInit(); + + unsigned long long oldVersion; + Nullable<unsigned long long> newVersion; +}; + +class IDBVersionChangeEvent FINAL : public Event { public: - static PassRefPtr<IDBVersionChangeEvent> create(PassRefPtr<IDBAny> oldVersion = IDBAny::createNull(), PassRefPtr<IDBAny> newVersion = IDBAny::createNull(), const AtomicString& eventType = AtomicString(), blink::WebIDBDataLoss = blink::WebIDBDataLossNone, const String& dataLossMessage = String()); - virtual ~IDBVersionChangeEvent(); + static PassRefPtrWillBeRawPtr<IDBVersionChangeEvent> create() + { + return adoptRefWillBeNoop(new IDBVersionChangeEvent()); + } + static PassRefPtrWillBeRawPtr<IDBVersionChangeEvent> create(const AtomicString& eventType, unsigned long long oldVersion, const Nullable<unsigned long long>& newVersion, blink::WebIDBDataLoss dataLoss = blink::WebIDBDataLossNone, const String& dataLossMessage = String()) + { + return adoptRefWillBeNoop(new IDBVersionChangeEvent(eventType, oldVersion, newVersion, dataLoss, dataLossMessage)); + } + static PassRefPtrWillBeRawPtr<IDBVersionChangeEvent> create(const AtomicString& eventType, const IDBVersionChangeEventInit& initializer) + { + return adoptRefWillBeNoop(new IDBVersionChangeEvent(eventType, initializer)); + } + + unsigned long long oldVersion() const { return m_oldVersion; } + unsigned long long newVersion(bool& isNull) const; - ScriptValue oldVersion(ExecutionContext*) const; - ScriptValue newVersion(ExecutionContext*) const; const AtomicString& dataLoss() const; const String& dataLossMessage() const { return m_dataLossMessage; } - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: - IDBVersionChangeEvent(PassRefPtr<IDBAny> oldVersion, PassRefPtr<IDBAny> newVersion, const AtomicString& eventType, blink::WebIDBDataLoss, const String& dataLoss); + IDBVersionChangeEvent(); + IDBVersionChangeEvent(const AtomicString& eventType, unsigned long long oldVersion, const Nullable<unsigned long long>& newVersion, blink::WebIDBDataLoss, const String& dataLoss); + IDBVersionChangeEvent(const AtomicString& eventType, const IDBVersionChangeEventInit&); - RefPtr<IDBAny> m_oldVersion; - RefPtr<IDBAny> m_newVersion; + unsigned long long m_oldVersion; + Nullable<unsigned long long> m_newVersion; bool m_dataLoss; String m_dataLossMessage; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl index 2d81f437ed5..3ee0c58a0a1 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IDBVersionChangeEvent.idl @@ -23,9 +23,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -interface IDBVersionChangeEvent : Event { - [CallWith=ExecutionContext] readonly attribute any oldVersion; - [CallWith=ExecutionContext] readonly attribute any newVersion; +[ + EventConstructor +] interface IDBVersionChangeEvent : Event { + [InitializedByEventConstructor] readonly attribute unsigned long long oldVersion; + [InitializedByEventConstructor] readonly attribute unsigned long long? newVersion; // FIXME: These are non-standard, see // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22370 diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDB.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDB.h index 05da27e3a22..b7e0085ba3d 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDB.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDB.h @@ -30,19 +30,6 @@ namespace WebCore { namespace IndexedDB { -enum TransactionMode { - TransactionReadOnly = 0, - TransactionReadWrite = 1, - TransactionVersionChange = 2 -}; - -enum CursorDirection { - CursorNext = 0, - CursorNextNoDuplicate = 1, - CursorPrev = 2, - CursorPrevNoDuplicate = 3, -}; - enum CursorType { CursorKeyAndValue = 0, CursorKeyOnly diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp new file mode 100644 index 00000000000..6f91ad851be --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp @@ -0,0 +1,25 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/indexeddb/IndexedDBClient.h" + +namespace WebCore { + +static CreateIndexedDBClient* idbClientCreateFunction = 0; + +void setIndexedDBClientCreateFunction(CreateIndexedDBClient createFunction) +{ + idbClientCreateFunction = createFunction; +} + +IndexedDBClient* IndexedDBClient::create() +{ + ASSERT(idbClientCreateFunction); + // There's no reason why we need to allocate a new proxy each time, but + // there's also no strong reason not to. + return idbClientCreateFunction(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactoryBackendInterface.h b/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h index e5284f5ef85..b9eca00063e 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/IDBFactoryBackendInterface.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h @@ -25,9 +25,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef IDBFactoryBackendInterface_h -#define IDBFactoryBackendInterface_h +#ifndef IndexedDBClient_h +#define IndexedDBClient_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" @@ -36,15 +37,18 @@ namespace WebCore { class ExecutionContext; -// FIXME: This is just a permission client at this point. Rename/refactor. -class IDBFactoryBackendInterface : public RefCounted<IDBFactoryBackendInterface> { +class IndexedDBClient : public GarbageCollected<IndexedDBClient> { public: - static PassRefPtr<IDBFactoryBackendInterface> create(); - virtual ~IDBFactoryBackendInterface() { } + static IndexedDBClient* create(); + void trace(Visitor*) { } virtual bool allowIndexedDB(ExecutionContext*, const String& name) = 0; }; +typedef IndexedDBClient* CreateIndexedDBClient(); + +void setIndexedDBClientCreateFunction(CreateIndexedDBClient); + } // namespace WebCore -#endif // IDBFactoryBackendInterface_h +#endif // IndexedDBClient_h diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp new file mode 100644 index 00000000000..17213cf94af --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp @@ -0,0 +1,777 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/indexeddb/InspectorIndexedDBAgent.h" + +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/ExceptionStatePlaceholder.h" +#include "bindings/v8/ScriptController.h" +#include "bindings/v8/ScriptState.h" +#include "core/dom/DOMStringList.h" +#include "core/dom/Document.h" +#include "core/events/EventListener.h" +#include "core/frame/LocalFrame.h" +#include "core/inspector/InspectorController.h" +#include "core/inspector/InspectorState.h" +#include "core/page/Page.h" +#include "modules/indexeddb/DOMWindowIndexedDatabase.h" +#include "modules/indexeddb/IDBCursor.h" +#include "modules/indexeddb/IDBCursorWithValue.h" +#include "modules/indexeddb/IDBDatabase.h" +#include "modules/indexeddb/IDBFactory.h" +#include "modules/indexeddb/IDBIndex.h" +#include "modules/indexeddb/IDBKey.h" +#include "modules/indexeddb/IDBKeyPath.h" +#include "modules/indexeddb/IDBKeyRange.h" +#include "modules/indexeddb/IDBMetadata.h" +#include "modules/indexeddb/IDBObjectStore.h" +#include "modules/indexeddb/IDBOpenDBRequest.h" +#include "modules/indexeddb/IDBPendingTransactionMonitor.h" +#include "modules/indexeddb/IDBRequest.h" +#include "modules/indexeddb/IDBTransaction.h" +#include "platform/JSONValues.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "public/platform/WebIDBCursor.h" +#include "public/platform/WebIDBTypes.h" +#include "wtf/Vector.h" + +using WebCore::TypeBuilder::Array; +using WebCore::TypeBuilder::IndexedDB::DatabaseWithObjectStores; +using WebCore::TypeBuilder::IndexedDB::DataEntry; +using WebCore::TypeBuilder::IndexedDB::Key; +using WebCore::TypeBuilder::IndexedDB::KeyPath; +using WebCore::TypeBuilder::IndexedDB::KeyRange; +using WebCore::TypeBuilder::IndexedDB::ObjectStore; +using WebCore::TypeBuilder::IndexedDB::ObjectStoreIndex; + +typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseNamesCallback RequestDatabaseNamesCallback; +typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseCallback RequestDatabaseCallback; +typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDataCallback RequestDataCallback; +typedef WebCore::InspectorBackendDispatcher::CallbackBase RequestCallback; +typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::ClearObjectStoreCallback ClearObjectStoreCallback; + +namespace WebCore { + +namespace IndexedDBAgentState { +static const char indexedDBAgentEnabled[] = "indexedDBAgentEnabled"; +}; + +namespace { + +class GetDatabaseNamesCallback FINAL : public EventListener { + WTF_MAKE_NONCOPYABLE(GetDatabaseNamesCallback); +public: + static PassRefPtr<GetDatabaseNamesCallback> create(PassRefPtr<RequestDatabaseNamesCallback> requestCallback, const String& securityOrigin) + { + return adoptRef(new GetDatabaseNamesCallback(requestCallback, securityOrigin)); + } + + virtual ~GetDatabaseNamesCallback() { } + + virtual bool operator==(const EventListener& other) OVERRIDE + { + return this == &other; + } + + virtual void handleEvent(ExecutionContext*, Event* event) OVERRIDE + { + if (!m_requestCallback->isActive()) + return; + if (event->type() != EventTypeNames::success) { + m_requestCallback->sendFailure("Unexpected event type."); + return; + } + + IDBRequest* idbRequest = static_cast<IDBRequest*>(event->target()); + IDBAny* requestResult = idbRequest->resultAsAny(); + if (requestResult->type() != IDBAny::DOMStringListType) { + m_requestCallback->sendFailure("Unexpected result type."); + return; + } + + RefPtrWillBeRawPtr<DOMStringList> databaseNamesList = requestResult->domStringList(); + RefPtr<TypeBuilder::Array<String> > databaseNames = TypeBuilder::Array<String>::create(); + for (size_t i = 0; i < databaseNamesList->length(); ++i) + databaseNames->addItem(databaseNamesList->item(i)); + m_requestCallback->sendSuccess(databaseNames.release()); + } + +private: + GetDatabaseNamesCallback(PassRefPtr<RequestDatabaseNamesCallback> requestCallback, const String& securityOrigin) + : EventListener(EventListener::CPPEventListenerType) + , m_requestCallback(requestCallback) + , m_securityOrigin(securityOrigin) { } + RefPtr<RequestDatabaseNamesCallback> m_requestCallback; + String m_securityOrigin; +}; + +class ExecutableWithDatabase : public RefCounted<ExecutableWithDatabase> { +public: + ExecutableWithDatabase(ScriptState* scriptState) + : m_scriptState(scriptState) { } + virtual ~ExecutableWithDatabase() { }; + void start(IDBFactory*, SecurityOrigin*, const String& databaseName); + virtual void execute(IDBDatabase*) = 0; + virtual RequestCallback* requestCallback() = 0; + ExecutionContext* context() const { return m_scriptState->executionContext(); } + ScriptState* scriptState() const { return m_scriptState.get(); } +private: + RefPtr<ScriptState> m_scriptState; +}; + +class OpenDatabaseCallback FINAL : public EventListener { +public: + static PassRefPtr<OpenDatabaseCallback> create(ExecutableWithDatabase* executableWithDatabase) + { + return adoptRef(new OpenDatabaseCallback(executableWithDatabase)); + } + + virtual ~OpenDatabaseCallback() { } + + virtual bool operator==(const EventListener& other) OVERRIDE + { + return this == &other; + } + + virtual void handleEvent(ExecutionContext* context, Event* event) OVERRIDE + { + if (event->type() != EventTypeNames::success) { + m_executableWithDatabase->requestCallback()->sendFailure("Unexpected event type."); + return; + } + + IDBOpenDBRequest* idbOpenDBRequest = static_cast<IDBOpenDBRequest*>(event->target()); + IDBAny* requestResult = idbOpenDBRequest->resultAsAny(); + if (requestResult->type() != IDBAny::IDBDatabaseType) { + m_executableWithDatabase->requestCallback()->sendFailure("Unexpected result type."); + return; + } + + IDBDatabase* idbDatabase = requestResult->idbDatabase(); + m_executableWithDatabase->execute(idbDatabase); + IDBPendingTransactionMonitor::from(*context).deactivateNewTransactions(); + idbDatabase->close(); + } + +private: + OpenDatabaseCallback(ExecutableWithDatabase* executableWithDatabase) + : EventListener(EventListener::CPPEventListenerType) + , m_executableWithDatabase(executableWithDatabase) { } + RefPtr<ExecutableWithDatabase> m_executableWithDatabase; +}; + +void ExecutableWithDatabase::start(IDBFactory* idbFactory, SecurityOrigin*, const String& databaseName) +{ + RefPtr<OpenDatabaseCallback> callback = OpenDatabaseCallback::create(this); + TrackExceptionState exceptionState; + IDBOpenDBRequest* idbOpenDBRequest = idbFactory->open(scriptState(), databaseName, exceptionState); + if (exceptionState.hadException()) { + requestCallback()->sendFailure("Could not open database."); + return; + } + idbOpenDBRequest->addEventListener(EventTypeNames::success, callback, false); +} + +static IDBTransaction* transactionForDatabase(ExecutionContext* executionContext, IDBDatabase* idbDatabase, const String& objectStoreName, const String& mode = IDBTransaction::modeReadOnly()) +{ + TrackExceptionState exceptionState; + IDBTransaction* idbTransaction = idbDatabase->transaction(executionContext, objectStoreName, mode, exceptionState); + if (exceptionState.hadException()) + return 0; + return idbTransaction; +} + +static IDBObjectStore* objectStoreForTransaction(IDBTransaction* idbTransaction, const String& objectStoreName) +{ + TrackExceptionState exceptionState; + IDBObjectStore* idbObjectStore = idbTransaction->objectStore(objectStoreName, exceptionState); + if (exceptionState.hadException()) + return 0; + return idbObjectStore; +} + +static IDBIndex* indexForObjectStore(IDBObjectStore* idbObjectStore, const String& indexName) +{ + TrackExceptionState exceptionState; + IDBIndex* idbIndex = idbObjectStore->index(indexName, exceptionState); + if (exceptionState.hadException()) + return 0; + return idbIndex; +} + +static PassRefPtr<KeyPath> keyPathFromIDBKeyPath(const IDBKeyPath& idbKeyPath) +{ + RefPtr<KeyPath> keyPath; + switch (idbKeyPath.type()) { + case IDBKeyPath::NullType: + keyPath = KeyPath::create().setType(KeyPath::Type::Null); + break; + case IDBKeyPath::StringType: + keyPath = KeyPath::create().setType(KeyPath::Type::String); + keyPath->setString(idbKeyPath.string()); + break; + case IDBKeyPath::ArrayType: { + keyPath = KeyPath::create().setType(KeyPath::Type::Array); + RefPtr<TypeBuilder::Array<String> > array = TypeBuilder::Array<String>::create(); + const Vector<String>& stringArray = idbKeyPath.array(); + for (size_t i = 0; i < stringArray.size(); ++i) + array->addItem(stringArray[i]); + keyPath->setArray(array); + break; + } + default: + ASSERT_NOT_REACHED(); + } + + return keyPath.release(); +} + +class DatabaseLoader FINAL : public ExecutableWithDatabase { +public: + static PassRefPtr<DatabaseLoader> create(ScriptState* scriptState, PassRefPtr<RequestDatabaseCallback> requestCallback) + { + return adoptRef(new DatabaseLoader(scriptState, requestCallback)); + } + + virtual ~DatabaseLoader() { } + + virtual void execute(IDBDatabase* idbDatabase) OVERRIDE + { + if (!requestCallback()->isActive()) + return; + + const IDBDatabaseMetadata databaseMetadata = idbDatabase->metadata(); + + RefPtr<TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStore> > objectStores = TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStore>::create(); + + for (IDBDatabaseMetadata::ObjectStoreMap::const_iterator it = databaseMetadata.objectStores.begin(); it != databaseMetadata.objectStores.end(); ++it) { + const IDBObjectStoreMetadata& objectStoreMetadata = it->value; + + RefPtr<TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStoreIndex> > indexes = TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStoreIndex>::create(); + + for (IDBObjectStoreMetadata::IndexMap::const_iterator it = objectStoreMetadata.indexes.begin(); it != objectStoreMetadata.indexes.end(); ++it) { + const IDBIndexMetadata& indexMetadata = it->value; + + RefPtr<ObjectStoreIndex> objectStoreIndex = ObjectStoreIndex::create() + .setName(indexMetadata.name) + .setKeyPath(keyPathFromIDBKeyPath(indexMetadata.keyPath)) + .setUnique(indexMetadata.unique) + .setMultiEntry(indexMetadata.multiEntry); + indexes->addItem(objectStoreIndex); + } + + RefPtr<ObjectStore> objectStore = ObjectStore::create() + .setName(objectStoreMetadata.name) + .setKeyPath(keyPathFromIDBKeyPath(objectStoreMetadata.keyPath)) + .setAutoIncrement(objectStoreMetadata.autoIncrement) + .setIndexes(indexes); + objectStores->addItem(objectStore); + } + RefPtr<DatabaseWithObjectStores> result = DatabaseWithObjectStores::create() + .setName(databaseMetadata.name) + .setIntVersion(databaseMetadata.intVersion) + .setVersion(databaseMetadata.version) + .setObjectStores(objectStores); + + m_requestCallback->sendSuccess(result); + } + + virtual RequestCallback* requestCallback() OVERRIDE { return m_requestCallback.get(); } +private: + DatabaseLoader(ScriptState* scriptState, PassRefPtr<RequestDatabaseCallback> requestCallback) + : ExecutableWithDatabase(scriptState) + , m_requestCallback(requestCallback) { } + RefPtr<RequestDatabaseCallback> m_requestCallback; +}; + +static IDBKey* idbKeyFromInspectorObject(JSONObject* key) +{ + IDBKey* idbKey; + + String type; + if (!key->getString("type", &type)) + return 0; + + DEFINE_STATIC_LOCAL(String, number, ("number")); + DEFINE_STATIC_LOCAL(String, string, ("string")); + DEFINE_STATIC_LOCAL(String, date, ("date")); + DEFINE_STATIC_LOCAL(String, array, ("array")); + + if (type == number) { + double number; + if (!key->getNumber("number", &number)) + return 0; + idbKey = IDBKey::createNumber(number); + } else if (type == string) { + String string; + if (!key->getString("string", &string)) + return 0; + idbKey = IDBKey::createString(string); + } else if (type == date) { + double date; + if (!key->getNumber("date", &date)) + return 0; + idbKey = IDBKey::createDate(date); + } else if (type == array) { + IDBKey::KeyArray keyArray; + RefPtr<JSONArray> array = key->getArray("array"); + for (size_t i = 0; i < array->length(); ++i) { + RefPtr<JSONValue> value = array->get(i); + RefPtr<JSONObject> object; + if (!value->asObject(&object)) + return 0; + keyArray.append(idbKeyFromInspectorObject(object.get())); + } + idbKey = IDBKey::createArray(keyArray); + } else { + return 0; + } + + return idbKey; +} + +static IDBKeyRange* idbKeyRangeFromKeyRange(JSONObject* keyRange) +{ + RefPtr<JSONObject> lower = keyRange->getObject("lower"); + IDBKey* idbLower = lower ? idbKeyFromInspectorObject(lower.get()) : 0; + if (lower && !idbLower) + return 0; + + RefPtr<JSONObject> upper = keyRange->getObject("upper"); + IDBKey* idbUpper = upper ? idbKeyFromInspectorObject(upper.get()) : 0; + if (upper && !idbUpper) + return 0; + + bool lowerOpen; + if (!keyRange->getBoolean("lowerOpen", &lowerOpen)) + return 0; + IDBKeyRange::LowerBoundType lowerBoundType = lowerOpen ? IDBKeyRange::LowerBoundOpen : IDBKeyRange::LowerBoundClosed; + + bool upperOpen; + if (!keyRange->getBoolean("upperOpen", &upperOpen)) + return 0; + IDBKeyRange::UpperBoundType upperBoundType = upperOpen ? IDBKeyRange::UpperBoundOpen : IDBKeyRange::UpperBoundClosed; + + return IDBKeyRange::create(idbLower, idbUpper, lowerBoundType, upperBoundType); +} + +class DataLoader; + +class OpenCursorCallback FINAL : public EventListener { +public: + static PassRefPtr<OpenCursorCallback> create(ScriptState* scriptState, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize) + { + return adoptRef(new OpenCursorCallback(scriptState, requestCallback, skipCount, pageSize)); + } + + virtual ~OpenCursorCallback() { } + + virtual bool operator==(const EventListener& other) OVERRIDE + { + return this == &other; + } + + virtual void handleEvent(ExecutionContext*, Event* event) OVERRIDE + { + if (event->type() != EventTypeNames::success) { + m_requestCallback->sendFailure("Unexpected event type."); + return; + } + + IDBRequest* idbRequest = static_cast<IDBRequest*>(event->target()); + IDBAny* requestResult = idbRequest->resultAsAny(); + if (requestResult->type() == IDBAny::BufferType) { + end(false); + return; + } + if (requestResult->type() != IDBAny::IDBCursorWithValueType) { + m_requestCallback->sendFailure("Unexpected result type."); + return; + } + + IDBCursorWithValue* idbCursor = requestResult->idbCursorWithValue(); + + if (m_skipCount) { + TrackExceptionState exceptionState; + idbCursor->advance(m_skipCount, exceptionState); + if (exceptionState.hadException()) + m_requestCallback->sendFailure("Could not advance cursor."); + m_skipCount = 0; + return; + } + + if (m_result->length() == m_pageSize) { + end(true); + return; + } + + // Continue cursor before making injected script calls, otherwise transaction might be finished. + TrackExceptionState exceptionState; + idbCursor->continueFunction(0, 0, exceptionState); + if (exceptionState.hadException()) { + m_requestCallback->sendFailure("Could not continue cursor."); + return; + } + + Document* document = toDocument(m_scriptState->executionContext()); + if (!document) + return; + RefPtr<DataEntry> dataEntry = DataEntry::create() + .setKey(idbCursor->key(m_scriptState.get()).toJSONValue(m_scriptState.get())->toJSONString()) + .setPrimaryKey(idbCursor->primaryKey(m_scriptState.get()).toJSONValue(m_scriptState.get())->toJSONString()) + .setValue(idbCursor->value(m_scriptState.get()).toJSONValue(m_scriptState.get())->toJSONString()); + m_result->addItem(dataEntry); + + } + + void end(bool hasMore) + { + if (!m_requestCallback->isActive()) + return; + m_requestCallback->sendSuccess(m_result.release(), hasMore); + } + +private: + OpenCursorCallback(ScriptState* scriptState, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize) + : EventListener(EventListener::CPPEventListenerType) + , m_scriptState(scriptState) + , m_requestCallback(requestCallback) + , m_skipCount(skipCount) + , m_pageSize(pageSize) + { + m_result = Array<DataEntry>::create(); + } + + RefPtr<ScriptState> m_scriptState; + RefPtr<RequestDataCallback> m_requestCallback; + int m_skipCount; + unsigned m_pageSize; + RefPtr<Array<DataEntry> > m_result; +}; + +class DataLoader FINAL : public ExecutableWithDatabase { +public: + static PassRefPtr<DataLoader> create(ScriptState* scriptState, PassRefPtr<RequestDataCallback> requestCallback, const String& objectStoreName, const String& indexName, IDBKeyRange* idbKeyRange, int skipCount, unsigned pageSize) + { + return adoptRef(new DataLoader(scriptState, requestCallback, objectStoreName, indexName, idbKeyRange, skipCount, pageSize)); + } + + virtual ~DataLoader() { } + + virtual void execute(IDBDatabase* idbDatabase) OVERRIDE + { + if (!requestCallback()->isActive()) + return; + IDBTransaction* idbTransaction = transactionForDatabase(context(), idbDatabase, m_objectStoreName); + if (!idbTransaction) { + m_requestCallback->sendFailure("Could not get transaction"); + return; + } + IDBObjectStore* idbObjectStore = objectStoreForTransaction(idbTransaction, m_objectStoreName); + if (!idbObjectStore) { + m_requestCallback->sendFailure("Could not get object store"); + return; + } + + RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(scriptState(), m_requestCallback, m_skipCount, m_pageSize); + + IDBRequest* idbRequest; + if (!m_indexName.isEmpty()) { + IDBIndex* idbIndex = indexForObjectStore(idbObjectStore, m_indexName); + if (!idbIndex) { + m_requestCallback->sendFailure("Could not get index"); + return; + } + + idbRequest = idbIndex->openCursor(scriptState(), m_idbKeyRange.get(), blink::WebIDBCursorDirectionNext); + } else { + idbRequest = idbObjectStore->openCursor(scriptState(), m_idbKeyRange.get(), blink::WebIDBCursorDirectionNext); + } + idbRequest->addEventListener(EventTypeNames::success, openCursorCallback, false); + } + + virtual RequestCallback* requestCallback() OVERRIDE { return m_requestCallback.get(); } + DataLoader(ScriptState* scriptState, PassRefPtr<RequestDataCallback> requestCallback, const String& objectStoreName, const String& indexName, IDBKeyRange* idbKeyRange, int skipCount, unsigned pageSize) + : ExecutableWithDatabase(scriptState) + , m_requestCallback(requestCallback) + , m_objectStoreName(objectStoreName) + , m_indexName(indexName) + , m_idbKeyRange(idbKeyRange) + , m_skipCount(skipCount) + , m_pageSize(pageSize) + { + } + + RefPtr<RequestDataCallback> m_requestCallback; + String m_objectStoreName; + String m_indexName; + Persistent<IDBKeyRange> m_idbKeyRange; + int m_skipCount; + unsigned m_pageSize; +}; + +LocalFrame* findFrameWithSecurityOrigin(Page* page, const String& securityOrigin) +{ + for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) { + if (!frame->isLocalFrame()) + continue; + RefPtr<SecurityOrigin> documentOrigin = toLocalFrame(frame)->document()->securityOrigin(); + if (documentOrigin->toRawString() == securityOrigin) + return toLocalFrame(frame); + } + return 0; +} + +} // namespace + +void InspectorIndexedDBAgent::provideTo(Page* page) +{ + OwnPtr<InspectorIndexedDBAgent> agent(adoptPtr(new InspectorIndexedDBAgent(page))); + page->inspectorController().registerModuleAgent(agent.release()); +} + +InspectorIndexedDBAgent::InspectorIndexedDBAgent(Page* page) + : InspectorBaseAgent<InspectorIndexedDBAgent>("IndexedDB") + , m_page(page) +{ +} + +InspectorIndexedDBAgent::~InspectorIndexedDBAgent() +{ +} + +void InspectorIndexedDBAgent::clearFrontend() +{ + disable(0); +} + +void InspectorIndexedDBAgent::restore() +{ + if (m_state->getBoolean(IndexedDBAgentState::indexedDBAgentEnabled)) { + ErrorString error; + enable(&error); + } +} + +void InspectorIndexedDBAgent::enable(ErrorString*) +{ + m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, true); +} + +void InspectorIndexedDBAgent::disable(ErrorString*) +{ + m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, false); +} + +static Document* assertDocument(ErrorString* errorString, LocalFrame* frame) +{ + Document* document = frame ? frame->document() : 0; + + if (!document) + *errorString = "No document for given frame found"; + + return document; +} + +static IDBFactory* assertIDBFactory(ErrorString* errorString, Document* document) +{ + LocalDOMWindow* domWindow = document->domWindow(); + if (!domWindow) { + *errorString = "No IndexedDB factory for given frame found"; + return 0; + } + IDBFactory* idbFactory = DOMWindowIndexedDatabase::indexedDB(*domWindow); + + if (!idbFactory) + *errorString = "No IndexedDB factory for given frame found"; + + return idbFactory; +} + +void InspectorIndexedDBAgent::requestDatabaseNames(ErrorString* errorString, const String& securityOrigin, PassRefPtr<RequestDatabaseNamesCallback> requestCallback) +{ + LocalFrame* frame = findFrameWithSecurityOrigin(m_page, securityOrigin); + Document* document = assertDocument(errorString, frame); + if (!document) + return; + IDBFactory* idbFactory = assertIDBFactory(errorString, document); + if (!idbFactory) + return; + + ScriptState* scriptState = ScriptState::forMainWorld(frame); + ScriptState::Scope scope(scriptState); + TrackExceptionState exceptionState; + IDBRequest* idbRequest = idbFactory->getDatabaseNames(scriptState, exceptionState); + if (exceptionState.hadException()) { + requestCallback->sendFailure("Could not obtain database names."); + return; + } + idbRequest->addEventListener(EventTypeNames::success, GetDatabaseNamesCallback::create(requestCallback, document->securityOrigin()->toRawString()), false); +} + +void InspectorIndexedDBAgent::requestDatabase(ErrorString* errorString, const String& securityOrigin, const String& databaseName, PassRefPtr<RequestDatabaseCallback> requestCallback) +{ + LocalFrame* frame = findFrameWithSecurityOrigin(m_page, securityOrigin); + Document* document = assertDocument(errorString, frame); + if (!document) + return; + IDBFactory* idbFactory = assertIDBFactory(errorString, document); + if (!idbFactory) + return; + + ScriptState* scriptState = ScriptState::forMainWorld(frame); + ScriptState::Scope scope(scriptState); + RefPtr<DatabaseLoader> databaseLoader = DatabaseLoader::create(scriptState, requestCallback); + databaseLoader->start(idbFactory, document->securityOrigin(), databaseName); +} + +void InspectorIndexedDBAgent::requestData(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<JSONObject>* keyRange, PassRefPtr<RequestDataCallback> requestCallback) +{ + LocalFrame* frame = findFrameWithSecurityOrigin(m_page, securityOrigin); + Document* document = assertDocument(errorString, frame); + if (!document) + return; + IDBFactory* idbFactory = assertIDBFactory(errorString, document); + if (!idbFactory) + return; + + IDBKeyRange* idbKeyRange = keyRange ? idbKeyRangeFromKeyRange(keyRange->get()) : 0; + if (keyRange && !idbKeyRange) { + *errorString = "Can not parse key range."; + return; + } + + ScriptState* scriptState = ScriptState::forMainWorld(frame); + ScriptState::Scope scope(scriptState); + RefPtr<DataLoader> dataLoader = DataLoader::create(scriptState, requestCallback, objectStoreName, indexName, idbKeyRange, skipCount, pageSize); + dataLoader->start(idbFactory, document->securityOrigin(), databaseName); +} + +class ClearObjectStoreListener FINAL : public EventListener { + WTF_MAKE_NONCOPYABLE(ClearObjectStoreListener); +public: + static PassRefPtr<ClearObjectStoreListener> create(PassRefPtr<ClearObjectStoreCallback> requestCallback) + { + return adoptRef(new ClearObjectStoreListener(requestCallback)); + } + + virtual ~ClearObjectStoreListener() { } + + virtual bool operator==(const EventListener& other) OVERRIDE + { + return this == &other; + } + + virtual void handleEvent(ExecutionContext*, Event* event) OVERRIDE + { + if (!m_requestCallback->isActive()) + return; + if (event->type() != EventTypeNames::complete) { + m_requestCallback->sendFailure("Unexpected event type."); + return; + } + + m_requestCallback->sendSuccess(); + } +private: + ClearObjectStoreListener(PassRefPtr<ClearObjectStoreCallback> requestCallback) + : EventListener(EventListener::CPPEventListenerType) + , m_requestCallback(requestCallback) + { + } + + RefPtr<ClearObjectStoreCallback> m_requestCallback; +}; + + +class ClearObjectStore FINAL : public ExecutableWithDatabase { +public: + static PassRefPtr<ClearObjectStore> create(ScriptState* scriptState, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback) + { + return adoptRef(new ClearObjectStore(scriptState, objectStoreName, requestCallback)); + } + + ClearObjectStore(ScriptState* scriptState, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback) + : ExecutableWithDatabase(scriptState) + , m_objectStoreName(objectStoreName) + , m_requestCallback(requestCallback) + { + } + + virtual void execute(IDBDatabase* idbDatabase) OVERRIDE + { + if (!requestCallback()->isActive()) + return; + IDBTransaction* idbTransaction = transactionForDatabase(context(), idbDatabase, m_objectStoreName, IDBTransaction::modeReadWrite()); + if (!idbTransaction) { + m_requestCallback->sendFailure("Could not get transaction"); + return; + } + IDBObjectStore* idbObjectStore = objectStoreForTransaction(idbTransaction, m_objectStoreName); + if (!idbObjectStore) { + m_requestCallback->sendFailure("Could not get object store"); + return; + } + + TrackExceptionState exceptionState; + idbObjectStore->clear(scriptState(), exceptionState); + ASSERT(!exceptionState.hadException()); + if (exceptionState.hadException()) { + ExceptionCode ec = exceptionState.code(); + m_requestCallback->sendFailure(String::format("Could not clear object store '%s': %d", m_objectStoreName.utf8().data(), ec)); + return; + } + idbTransaction->addEventListener(EventTypeNames::complete, ClearObjectStoreListener::create(m_requestCallback), false); + } + + virtual RequestCallback* requestCallback() OVERRIDE { return m_requestCallback.get(); } +private: + const String m_objectStoreName; + RefPtr<ClearObjectStoreCallback> m_requestCallback; +}; + +void InspectorIndexedDBAgent::clearObjectStore(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback) +{ + LocalFrame* frame = findFrameWithSecurityOrigin(m_page, securityOrigin); + Document* document = assertDocument(errorString, frame); + if (!document) + return; + IDBFactory* idbFactory = assertIDBFactory(errorString, document); + if (!idbFactory) + return; + + ScriptState* scriptState = ScriptState::forMainWorld(frame); + ScriptState::Scope scope(scriptState); + RefPtr<ClearObjectStore> clearObjectStore = ClearObjectStore::create(scriptState, objectStoreName, requestCallback); + clearObjectStore->start(idbFactory, document->securityOrigin(), databaseName); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitMediaSource.h b/chromium/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.h index d9287d40d6b..37e8878569e 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitMediaSource.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.h @@ -28,48 +28,42 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebKitMediaSource_h -#define WebKitMediaSource_h +#ifndef InspectorIndexedDBAgent_h +#define InspectorIndexedDBAgent_h -#include "bindings/v8/ScriptWrappable.h" -#include "modules/mediasource/MediaSourceBase.h" -#include "modules/mediasource/WebKitSourceBuffer.h" -#include "modules/mediasource/WebKitSourceBufferList.h" -#include "wtf/RefCounted.h" +#include "core/inspector/InspectorBaseAgent.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/text/WTFString.h" namespace WebCore { -class ExceptionState; +class Page; -class WebKitMediaSource : public MediaSourceBase, public ScriptWrappable { +typedef String ErrorString; + +class InspectorIndexedDBAgent FINAL : public InspectorBaseAgent<InspectorIndexedDBAgent>, public InspectorBackendDispatcher::IndexedDBCommandHandler { public: - static PassRefPtr<WebKitMediaSource> create(ExecutionContext*); - virtual ~WebKitMediaSource() { } + static void provideTo(Page*); - // WebKitMediaSource.idl methods - WebKitSourceBufferList* sourceBuffers(); - WebKitSourceBufferList* activeSourceBuffers(); - WebKitSourceBuffer* addSourceBuffer(const String& type, ExceptionState&); - void removeSourceBuffer(WebKitSourceBuffer*, ExceptionState&); - static bool isTypeSupported(const String& type); + virtual ~InspectorIndexedDBAgent(); - // EventTarget interface - virtual const AtomicString& interfaceName() const OVERRIDE; + virtual void clearFrontend() OVERRIDE; + virtual void restore() OVERRIDE; - using RefCounted<MediaSourceBase>::ref; - using RefCounted<MediaSourceBase>::deref; + // Called from the front-end. + virtual void enable(ErrorString*) OVERRIDE; + virtual void disable(ErrorString*) OVERRIDE; + virtual void requestDatabaseNames(ErrorString*, const String& securityOrigin, PassRefPtr<RequestDatabaseNamesCallback>) OVERRIDE; + virtual void requestDatabase(ErrorString*, const String& securityOrigin, const String& databaseName, PassRefPtr<RequestDatabaseCallback>) OVERRIDE; + virtual void requestData(ErrorString*, const String& securityOrigin, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<JSONObject>* keyRange, PassRefPtr<RequestDataCallback>) OVERRIDE; + virtual void clearObjectStore(ErrorString*, const String& in_securityOrigin, const String& in_databaseName, const String& in_objectStoreName, PassRefPtr<ClearObjectStoreCallback>) OVERRIDE; private: - explicit WebKitMediaSource(ExecutionContext*); - - // MediaSourceBase interface - virtual void onReadyStateChange(const AtomicString&, const AtomicString&) OVERRIDE; - virtual Vector<RefPtr<TimeRanges> > activeRanges() const OVERRIDE; + InspectorIndexedDBAgent(Page*); - RefPtr<WebKitSourceBufferList> m_sourceBuffers; - RefPtr<WebKitSourceBufferList> m_activeSourceBuffers; + Page* m_page; }; } // namespace WebCore -#endif +#endif // !defined(InspectorIndexedDBAgent_h) diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp index 9fa9f2fd6ab..e62ac8608b8 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.cpp @@ -33,12 +33,14 @@ #include "modules/indexeddb/IDBMetadata.h" #include "modules/indexeddb/IDBRequest.h" #include "platform/SharedBuffer.h" +#include "public/platform/WebBlobInfo.h" #include "public/platform/WebData.h" #include "public/platform/WebIDBCursor.h" #include "public/platform/WebIDBDatabase.h" #include "public/platform/WebIDBDatabaseError.h" #include "public/platform/WebIDBKey.h" +using blink::WebBlobInfo; using blink::WebData; using blink::WebIDBCursor; using blink::WebIDBDatabase; @@ -47,16 +49,17 @@ using blink::WebIDBIndex; using blink::WebIDBKey; using blink::WebIDBKeyPath; using blink::WebIDBMetadata; +using blink::WebVector; namespace WebCore { // static -PassOwnPtr<WebIDBCallbacksImpl> WebIDBCallbacksImpl::create(PassRefPtr<IDBRequest> request) +PassOwnPtr<WebIDBCallbacksImpl> WebIDBCallbacksImpl::create(IDBRequest* request) { return adoptPtr(new WebIDBCallbacksImpl(request)); } -WebIDBCallbacksImpl::WebIDBCallbacksImpl(PassRefPtr<IDBRequest> request) +WebIDBCallbacksImpl::WebIDBCallbacksImpl(IDBRequest* request) : m_request(request) { } @@ -65,12 +68,20 @@ WebIDBCallbacksImpl::~WebIDBCallbacksImpl() { } +static PassOwnPtr<Vector<WebBlobInfo> > ConvertBlobInfo(const WebVector<WebBlobInfo>& webBlobInfo) +{ + OwnPtr<Vector<WebBlobInfo> > blobInfo = adoptPtr(new Vector<WebBlobInfo>(webBlobInfo.size())); + for (size_t i = 0; i < webBlobInfo.size(); ++i) + (*blobInfo)[i] = webBlobInfo[i]; + return blobInfo.release(); +} + void WebIDBCallbacksImpl::onError(const WebIDBDatabaseError& error) { m_request->onError(error); } -void WebIDBCallbacksImpl::onSuccess(const blink::WebVector<blink::WebString>& webStringList) +void WebIDBCallbacksImpl::onSuccess(const WebVector<blink::WebString>& webStringList) { Vector<String> stringList; for (size_t i = 0; i < webStringList.size(); ++i) @@ -78,9 +89,9 @@ void WebIDBCallbacksImpl::onSuccess(const blink::WebVector<blink::WebString>& we m_request->onSuccess(stringList); } -void WebIDBCallbacksImpl::onSuccess(WebIDBCursor* cursor, const WebIDBKey& key, const WebIDBKey& primaryKey, const WebData& value) +void WebIDBCallbacksImpl::onSuccess(WebIDBCursor* cursor, const WebIDBKey& key, const WebIDBKey& primaryKey, const WebData& value, const WebVector<WebBlobInfo>& webBlobInfo) { - m_request->onSuccess(adoptPtr(cursor), key, primaryKey, value); + m_request->onSuccess(adoptPtr(cursor), key, primaryKey, value, ConvertBlobInfo(webBlobInfo)); } void WebIDBCallbacksImpl::onSuccess(WebIDBDatabase* backend, const WebIDBMetadata& metadata) @@ -93,14 +104,14 @@ void WebIDBCallbacksImpl::onSuccess(const WebIDBKey& key) m_request->onSuccess(key); } -void WebIDBCallbacksImpl::onSuccess(const WebData& value) +void WebIDBCallbacksImpl::onSuccess(const WebData& value, const WebVector<WebBlobInfo>& webBlobInfo) { - m_request->onSuccess(value); + m_request->onSuccess(value, ConvertBlobInfo(webBlobInfo)); } -void WebIDBCallbacksImpl::onSuccess(const WebData& value, const WebIDBKey& key, const WebIDBKeyPath& keyPath) +void WebIDBCallbacksImpl::onSuccess(const WebData& value, const WebVector<WebBlobInfo>& webBlobInfo, const WebIDBKey& key, const WebIDBKeyPath& keyPath) { - m_request->onSuccess(value, key, keyPath); + m_request->onSuccess(value, ConvertBlobInfo(webBlobInfo), key, keyPath); } void WebIDBCallbacksImpl::onSuccess(long long value) @@ -113,9 +124,9 @@ void WebIDBCallbacksImpl::onSuccess() m_request->onSuccess(); } -void WebIDBCallbacksImpl::onSuccess(const WebIDBKey& key, const WebIDBKey& primaryKey, const WebData& value) +void WebIDBCallbacksImpl::onSuccess(const WebIDBKey& key, const WebIDBKey& primaryKey, const WebData& value, const WebVector<WebBlobInfo>& webBlobInfo) { - m_request->onSuccess(key, primaryKey, value); + m_request->onSuccess(key, primaryKey, value, ConvertBlobInfo(webBlobInfo)); } void WebIDBCallbacksImpl::onBlocked(long long oldVersion) diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.h b/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.h index 86a2d1f4597..08ea840e393 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBCallbacksImpl.h @@ -35,6 +35,7 @@ #include "wtf/RefPtr.h" namespace blink { +class WebBlobInfo; class WebData; class WebIDBCursor; class WebIDBDatabase; @@ -48,30 +49,30 @@ struct WebIDBMetadata; namespace WebCore { class IDBRequest; -class WebIDBCallbacksImpl : public blink::WebIDBCallbacks { +class WebIDBCallbacksImpl FINAL : public blink::WebIDBCallbacks { public: - static PassOwnPtr<WebIDBCallbacksImpl> create(PassRefPtr<IDBRequest>); + static PassOwnPtr<WebIDBCallbacksImpl> create(IDBRequest*); virtual ~WebIDBCallbacksImpl(); // Pointers transfer ownership. - virtual void onError(const blink::WebIDBDatabaseError&); - virtual void onSuccess(const blink::WebVector<blink::WebString>&); - virtual void onSuccess(blink::WebIDBCursor*, const blink::WebIDBKey&, const blink::WebIDBKey& primaryKey, const blink::WebData&); - virtual void onSuccess(blink::WebIDBDatabase*, const blink::WebIDBMetadata&); - virtual void onSuccess(const blink::WebIDBKey&); - virtual void onSuccess(const blink::WebData&); - virtual void onSuccess(const blink::WebData&, const blink::WebIDBKey&, const blink::WebIDBKeyPath&); - virtual void onSuccess(long long); - virtual void onSuccess(); - virtual void onSuccess(const blink::WebIDBKey&, const blink::WebIDBKey& primaryKey, const blink::WebData&); - virtual void onBlocked(long long oldVersion); - virtual void onUpgradeNeeded(long long oldVersion, blink::WebIDBDatabase*, const blink::WebIDBMetadata&, unsigned short dataLoss, blink::WebString dataLossMessage); + virtual void onError(const blink::WebIDBDatabaseError&) OVERRIDE; + virtual void onSuccess(const blink::WebVector<blink::WebString>&) OVERRIDE; + virtual void onSuccess(blink::WebIDBCursor*, const blink::WebIDBKey&, const blink::WebIDBKey& primaryKey, const blink::WebData&, const blink::WebVector<blink::WebBlobInfo>&) OVERRIDE; + virtual void onSuccess(blink::WebIDBDatabase*, const blink::WebIDBMetadata&) OVERRIDE; + virtual void onSuccess(const blink::WebIDBKey&) OVERRIDE; + virtual void onSuccess(const blink::WebData&, const blink::WebVector<blink::WebBlobInfo>&) OVERRIDE; + virtual void onSuccess(const blink::WebData&, const blink::WebVector<blink::WebBlobInfo>&, const blink::WebIDBKey&, const blink::WebIDBKeyPath&) OVERRIDE; + virtual void onSuccess(long long) OVERRIDE; + virtual void onSuccess() OVERRIDE; + virtual void onSuccess(const blink::WebIDBKey&, const blink::WebIDBKey& primaryKey, const blink::WebData&, const blink::WebVector<blink::WebBlobInfo>&) OVERRIDE; + virtual void onBlocked(long long oldVersion) OVERRIDE; + virtual void onUpgradeNeeded(long long oldVersion, blink::WebIDBDatabase*, const blink::WebIDBMetadata&, unsigned short dataLoss, blink::WebString dataLossMessage) OVERRIDE; private: - explicit WebIDBCallbacksImpl(PassRefPtr<IDBRequest>); + explicit WebIDBCallbacksImpl(IDBRequest*); - RefPtr<IDBRequest> m_request; + Persistent<IDBRequest> m_request; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp index 7f447a72e30..03124541449 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.cpp @@ -31,12 +31,12 @@ namespace WebCore { // static -PassOwnPtr<WebIDBDatabaseCallbacksImpl> WebIDBDatabaseCallbacksImpl::create(PassRefPtr<IDBDatabaseCallbacks> callbacks) +PassOwnPtr<WebIDBDatabaseCallbacksImpl> WebIDBDatabaseCallbacksImpl::create(IDBDatabaseCallbacks* callbacks) { return adoptPtr(new WebIDBDatabaseCallbacksImpl(callbacks)); } -WebIDBDatabaseCallbacksImpl::WebIDBDatabaseCallbacksImpl(PassRefPtr<IDBDatabaseCallbacks> callbacks) +WebIDBDatabaseCallbacksImpl::WebIDBDatabaseCallbacksImpl(IDBDatabaseCallbacks* callbacks) : m_callbacks(callbacks) { } diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.h b/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.h index b20d7829c72..872bcaa0b9c 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/WebIDBDatabaseCallbacksImpl.h @@ -36,21 +36,21 @@ namespace WebCore { -class WebIDBDatabaseCallbacksImpl : public blink::WebIDBDatabaseCallbacks { +class WebIDBDatabaseCallbacksImpl FINAL : public blink::WebIDBDatabaseCallbacks { public: - static PassOwnPtr<WebIDBDatabaseCallbacksImpl> create(PassRefPtr<IDBDatabaseCallbacks>); + static PassOwnPtr<WebIDBDatabaseCallbacksImpl> create(IDBDatabaseCallbacks*); virtual ~WebIDBDatabaseCallbacksImpl(); - virtual void onForcedClose(); - virtual void onVersionChange(long long oldVersion, long long newVersion); - virtual void onAbort(long long transactionId, const blink::WebIDBDatabaseError&); - virtual void onComplete(long long transactionId); + virtual void onForcedClose() OVERRIDE; + virtual void onVersionChange(long long oldVersion, long long newVersion) OVERRIDE; + virtual void onAbort(long long transactionId, const blink::WebIDBDatabaseError&) OVERRIDE; + virtual void onComplete(long long transactionId) OVERRIDE; private: - explicit WebIDBDatabaseCallbacksImpl(PassRefPtr<IDBDatabaseCallbacks>); + explicit WebIDBDatabaseCallbacksImpl(IDBDatabaseCallbacks*); - RefPtr<IDBDatabaseCallbacks> m_callbacks; + Persistent<IDBDatabaseCallbacks> m_callbacks; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/WindowIndexedDatabase.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/WindowIndexedDatabase.idl index 3823e4f2a5e..5b80cb802db 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/WindowIndexedDatabase.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/WindowIndexedDatabase.idl @@ -25,9 +25,18 @@ */ [ - ImplementedAs=DOMWindowIndexedDatabase + ImplementedAs=DOMWindowIndexedDatabase, ] partial interface Window { - [ImplementedAs=indexedDB,MeasureAs=PrefixedIndexedDB] readonly attribute IDBFactory webkitIndexedDB; + [ImplementedAs=indexedDB, MeasureAs=PrefixedIndexedDB] readonly attribute IDBFactory webkitIndexedDB; [MeasureAs=UnprefixedIndexedDB] readonly attribute IDBFactory indexedDB; + + [MeasureAs=PrefixedIDBCursorConstructor] attribute IDBCursorConstructor webkitIDBCursor; + [MeasureAs=PrefixedIDBDatabaseConstructor] attribute IDBDatabaseConstructor webkitIDBDatabase; + [MeasureAs=PrefixedIDBFactoryConstructor] attribute IDBFactoryConstructor webkitIDBFactory; + [MeasureAs=PrefixedIDBIndexConstructor] attribute IDBIndexConstructor webkitIDBIndex; + [MeasureAs=PrefixedIDBKeyRangeConstructor] attribute IDBKeyRangeConstructor webkitIDBKeyRange; + [MeasureAs=PrefixedIDBObjectStoreConstructor] attribute IDBObjectStoreConstructor webkitIDBObjectStore; + [MeasureAs=PrefixedIDBRequestConstructor] attribute IDBRequestConstructor webkitIDBRequest; + [MeasureAs=PrefixedIDBTransactionConstructor] attribute IDBTransactionConstructor webkitIDBTransaction; }; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.cpp b/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.cpp index 04fcbae3082..007c4eff6bc 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.cpp +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.cpp @@ -31,7 +31,7 @@ #include "core/dom/ExecutionContext.h" #include "modules/indexeddb/IDBFactory.h" -#include "modules/indexeddb/IDBFactoryBackendInterface.h" +#include "modules/indexeddb/IndexedDBClient.h" namespace WebCore { @@ -48,28 +48,32 @@ const char* WorkerGlobalScopeIndexedDatabase::supplementName() return "WorkerGlobalScopeIndexedDatabase"; } -WorkerGlobalScopeIndexedDatabase* WorkerGlobalScopeIndexedDatabase::from(WorkerSupplementable* context) +WorkerGlobalScopeIndexedDatabase& WorkerGlobalScopeIndexedDatabase::from(WillBeHeapSupplementable<WorkerGlobalScope>& context) { - WorkerGlobalScopeIndexedDatabase* supplement = static_cast<WorkerGlobalScopeIndexedDatabase*>(WorkerSupplement::from(context, supplementName())); + WorkerGlobalScopeIndexedDatabase* supplement = static_cast<WorkerGlobalScopeIndexedDatabase*>(WillBeHeapSupplement<WorkerGlobalScope>::from(context, supplementName())); if (!supplement) { supplement = new WorkerGlobalScopeIndexedDatabase(); - provideTo(context, supplementName(), adoptPtr(supplement)); + provideTo(context, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -IDBFactory* WorkerGlobalScopeIndexedDatabase::indexedDB(WorkerSupplementable* context) +IDBFactory* WorkerGlobalScopeIndexedDatabase::indexedDB(WillBeHeapSupplementable<WorkerGlobalScope>& context) { - return from(context)->indexedDB(); + return from(context).indexedDB(); } IDBFactory* WorkerGlobalScopeIndexedDatabase::indexedDB() { - if (!m_factoryBackend) - m_factoryBackend = IDBFactoryBackendInterface::create(); if (!m_idbFactory) - m_idbFactory = IDBFactory::create(m_factoryBackend.get()); + m_idbFactory = IDBFactory::create(IndexedDBClient::create()); return m_idbFactory.get(); } +void WorkerGlobalScopeIndexedDatabase::trace(Visitor* visitor) +{ + visitor->trace(m_idbFactory); + WillBeHeapSupplement<WorkerGlobalScope>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.h b/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.h index ac3ae68cd5c..9d7a272cc04 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.h +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.h @@ -27,20 +27,24 @@ #ifndef WorkerGlobalScopeIndexedDatabase_h #define WorkerGlobalScopeIndexedDatabase_h -#include "core/workers/WorkerSupplementable.h" +#include "platform/Supplementable.h" namespace WebCore { class IDBFactory; -class IDBFactoryBackendInterface; +class IndexedDBClient; class ExecutionContext; +class WorkerGlobalScope; -class WorkerGlobalScopeIndexedDatabase : public WorkerSupplement { +class WorkerGlobalScopeIndexedDatabase FINAL : public NoBaseWillBeGarbageCollectedFinalized<WorkerGlobalScopeIndexedDatabase>, public WillBeHeapSupplement<WorkerGlobalScope> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WorkerGlobalScopeIndexedDatabase); public: virtual ~WorkerGlobalScopeIndexedDatabase(); - static WorkerGlobalScopeIndexedDatabase* from(WorkerSupplementable*); + static WorkerGlobalScopeIndexedDatabase& from(WillBeHeapSupplementable<WorkerGlobalScope>&); - static IDBFactory* indexedDB(WorkerSupplementable*); + static IDBFactory* indexedDB(WillBeHeapSupplementable<WorkerGlobalScope>&); + + virtual void trace(Visitor*); private: WorkerGlobalScopeIndexedDatabase(); @@ -48,8 +52,7 @@ private: IDBFactory* indexedDB(); static const char* supplementName(); - RefPtr<IDBFactoryBackendInterface> m_factoryBackend; - RefPtr<IDBFactory> m_idbFactory; + PersistentWillBeMember<IDBFactory> m_idbFactory; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.idl b/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.idl index 9b2c2083b7b..8ca9e62fa9b 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.idl +++ b/chromium/third_party/WebKit/Source/modules/indexeddb/WorkerGlobalScopeIndexedDatabase.idl @@ -25,7 +25,7 @@ */ partial interface WorkerGlobalScope { - [ImplementedAs=indexedDB, RuntimeEnabled=IndexedDB] readonly attribute IDBFactory webkitIndexedDB; + [ImplementedAs=indexedDB] readonly attribute IDBFactory webkitIndexedDB; attribute IDBCursorConstructor webkitIDBCursor; attribute IDBDatabaseConstructor webkitIDBDatabase; @@ -36,7 +36,7 @@ partial interface WorkerGlobalScope { attribute IDBRequestConstructor webkitIDBRequest; attribute IDBTransactionConstructor webkitIDBTransaction; - [RuntimeEnabled=IndexedDB] readonly attribute IDBFactory indexedDB; + readonly attribute IDBFactory indexedDB; attribute IDBCursorConstructor IDBCursor; attribute IDBCursorWithValueConstructor IDBCursorWithValue; diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/chromium/IDBFactoryBackendInterfaceChromium.h b/chromium/third_party/WebKit/Source/modules/indexeddb/chromium/IDBFactoryBackendInterfaceChromium.h deleted file mode 100644 index 53dadb6b06e..00000000000 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/chromium/IDBFactoryBackendInterfaceChromium.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef IDBFactoryBackendInterfaceChromium_h -#define IDBFactoryBackendInterfaceChromium_h - -#include "modules/indexeddb/IDBFactoryBackendInterface.h" - -namespace WebCore { - -typedef PassRefPtr<IDBFactoryBackendInterface> IDBFactoryBackendInterfaceCreate(); - -void setIDBFactoryBackendInterfaceCreateFunction(IDBFactoryBackendInterfaceCreate); - -} // namespace WebCore - -#endif // IDBFactoryBackendInterfaceChromium_h diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.cpp index 2da4127ef9a..1c92ffe5cfe 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.cpp @@ -40,19 +40,19 @@ HTMLVideoElementMediaSource::HTMLVideoElementMediaSource() { } HTMLVideoElementMediaSource::~HTMLVideoElementMediaSource() { } -PassRefPtr<VideoPlaybackQuality> HTMLVideoElementMediaSource::getVideoPlaybackQuality(HTMLVideoElement* videoElement) +PassRefPtrWillBeRawPtr<VideoPlaybackQuality> HTMLVideoElementMediaSource::getVideoPlaybackQuality(HTMLVideoElement& videoElement) { unsigned total = 0; unsigned dropped = 0; unsigned corrupted = 0; - MediaPlayer* player = videoElement->player(); - if (player) { - total = player->decodedFrameCount(); - dropped = player->droppedFrameCount(); - corrupted = player->corruptedFrameCount(); + blink::WebMediaPlayer* webMediaPlayer = videoElement.webMediaPlayer(); + if (webMediaPlayer) { + total = webMediaPlayer->decodedFrameCount(); + dropped = webMediaPlayer->droppedFrameCount(); + corrupted = webMediaPlayer->corruptedFrameCount(); } - return VideoPlaybackQuality::create(videoElement->document(), total, dropped, corrupted); + return VideoPlaybackQuality::create(videoElement.document(), total, dropped, corrupted); } } diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.h b/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.h index 72adceb3863..96b1d7a9f04 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.h +++ b/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.h @@ -31,6 +31,7 @@ #ifndef HTMLVideoElementMediaSource_h #define HTMLVideoElementMediaSource_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" namespace WebCore { @@ -40,7 +41,7 @@ class VideoPlaybackQuality; class HTMLVideoElementMediaSource { public: - static PassRefPtr<VideoPlaybackQuality> getVideoPlaybackQuality(HTMLVideoElement*); + static PassRefPtrWillBeRawPtr<VideoPlaybackQuality> getVideoPlaybackQuality(HTMLVideoElement&); private: HTMLVideoElementMediaSource(); diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.idl b/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.idl index 79a51ab39cd..57de64f8938 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.idl +++ b/chromium/third_party/WebKit/Source/modules/mediasource/HTMLVideoElementMediaSource.idl @@ -27,6 +27,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -partial interface HTMLVideoElement { - [RuntimeEnabled=MediaSourceExperimental] VideoPlaybackQuality getVideoPlaybackQuality(); + +[ + RuntimeEnabled=MediaSourceExperimental, +] partial interface HTMLVideoElement { + VideoPlaybackQuality getVideoPlaybackQuality(); }; diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp index 975b98bf4b1..9dc2ff704c4 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp @@ -31,37 +31,79 @@ #include "config.h" #include "modules/mediasource/MediaSource.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "core/dom/ExceptionCode.h" +#include "core/events/Event.h" #include "core/events/GenericEventQueue.h" +#include "core/html/HTMLMediaElement.h" #include "core/html/TimeRanges.h" #include "modules/mediasource/MediaSourceRegistry.h" #include "platform/ContentType.h" #include "platform/Logging.h" #include "platform/MIMETypeRegistry.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/TraceEvent.h" +#include "public/platform/WebMediaSource.h" #include "public/platform/WebSourceBuffer.h" #include "wtf/Uint8Array.h" #include "wtf/text/CString.h" +using blink::WebMediaSource; using blink::WebSourceBuffer; namespace WebCore { -PassRefPtr<MediaSource> MediaSource::create(ExecutionContext* context) +static bool throwExceptionIfClosedOrUpdating(bool isOpen, bool isUpdating, ExceptionState& exceptionState) { - RefPtr<MediaSource> mediaSource(adoptRef(new MediaSource(context))); + if (!isOpen) { + exceptionState.throwDOMException(InvalidStateError, "The MediaSource's readyState is not 'open'."); + return true; + } + if (isUpdating) { + exceptionState.throwDOMException(InvalidStateError, "The 'updating' attribute is true on one or more of this MediaSource's SourceBuffers."); + return true; + } + + return false; +} + +const AtomicString& MediaSource::openKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, open, ("open", AtomicString::ConstructFromLiteral)); + return open; +} + +const AtomicString& MediaSource::closedKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, closed, ("closed", AtomicString::ConstructFromLiteral)); + return closed; +} + +const AtomicString& MediaSource::endedKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, ended, ("ended", AtomicString::ConstructFromLiteral)); + return ended; +} + +PassRefPtrWillBeRawPtr<MediaSource> MediaSource::create(ExecutionContext* context) +{ + RefPtrWillBeRawPtr<MediaSource> mediaSource(adoptRefWillBeRefCountedGarbageCollected(new MediaSource(context))); mediaSource->suspendIfNeeded(); return mediaSource.release(); } MediaSource::MediaSource(ExecutionContext* context) - : MediaSourceBase(context) + : ActiveDOMObject(context) + , m_readyState(closedKeyword()) + , m_asyncEventQueue(GenericEventQueue::create(this)) + , m_attachedElement(0) + , m_sourceBuffers(SourceBufferList::create(executionContext(), m_asyncEventQueue.get())) + , m_activeSourceBuffers(SourceBufferList::create(executionContext(), m_asyncEventQueue.get())) { WTF_LOG(Media, "MediaSource::MediaSource %p", this); ScriptWrappable::init(this); - m_sourceBuffers = SourceBufferList::create(executionContext(), asyncEventQueue()); - m_activeSourceBuffers = SourceBufferList::create(executionContext(), asyncEventQueue()); } MediaSource::~MediaSource() @@ -75,24 +117,24 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type, ExceptionState& e WTF_LOG(Media, "MediaSource::addSourceBuffer(%s) %p", type.ascii().data(), this); // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type - // 1. If type is null or an empty then throw an InvalidAccessError exception and - // abort these steps. - if (type.isNull() || type.isEmpty()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + // 1. If type is an empty string then throw an InvalidAccessError exception + // and abort these steps. + if (type.isEmpty()) { + exceptionState.throwDOMException(InvalidAccessError, "The type provided is empty."); return 0; } // 2. If type contains a MIME type that is not supported ..., then throw a // NotSupportedError exception and abort these steps. if (!isTypeSupported(type)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + exceptionState.throwDOMException(NotSupportedError, "The type provided ('" + type + "') is unsupported."); return 0; } // 4. If the readyState attribute is not in the "open" state then throw an // InvalidStateError exception and abort these steps. if (!isOpen()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "The MediaSource's readyState is not 'open'."); return 0; } @@ -108,7 +150,7 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type, ExceptionState& e return 0; } - RefPtr<SourceBuffer> buffer = SourceBuffer::create(webSourceBuffer.release(), this, asyncEventQueue()); + RefPtrWillBeRawPtr<SourceBuffer> buffer = SourceBuffer::create(webSourceBuffer.release(), this, m_asyncEventQueue.get()); // 6. Add the new object to sourceBuffers and fire a addsourcebuffer on that object. m_sourceBuffers->add(buffer); m_activeSourceBuffers->add(buffer); @@ -122,34 +164,28 @@ void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionState& excep RefPtr<SourceBuffer> protect(buffer); // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-removeSourceBuffer-void-SourceBuffer-sourceBuffer - // 1. If sourceBuffer is null then throw an InvalidAccessError exception and - // abort these steps. - if (!buffer) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } - // 2. If sourceBuffer specifies an object that is not in sourceBuffers then + // 1. If sourceBuffer specifies an object that is not in sourceBuffers then // throw a NotFoundError exception and abort these steps. if (!m_sourceBuffers->length() || !m_sourceBuffers->contains(buffer)) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "The SourceBuffer provided is not contained in this MediaSource."); return; } - // 3. If the sourceBuffer.updating attribute equals true, then run the following steps: ... + // 2. If the sourceBuffer.updating attribute equals true, then run the following steps: ... buffer->abortIfUpdating(); - // Steps 4-9 are related to updating audioTracks, videoTracks, and textTracks which aren't implmented yet. + // Steps 3-8 are related to updating audioTracks, videoTracks, and textTracks which aren't implmented yet. // FIXME(91649): support track selection - // 10. If sourceBuffer is in activeSourceBuffers, then remove sourceBuffer from activeSourceBuffers ... + // 9. If sourceBuffer is in activeSourceBuffers, then remove sourceBuffer from activeSourceBuffers ... m_activeSourceBuffers->remove(buffer); - // 11. Remove sourceBuffer from sourceBuffers and fire a removesourcebuffer event + // 10. Remove sourceBuffer from sourceBuffers and fire a removesourcebuffer event // on that object. m_sourceBuffers->remove(buffer); - // 12. Destroy all resources for sourceBuffer. + // 11. Destroy all resources for sourceBuffer. buffer->removedFromMediaSource(); } @@ -177,13 +213,15 @@ void MediaSource::onReadyStateChange(const AtomicString& oldState, const AtomicS scheduleEvent(EventTypeNames::sourceclose); } -Vector<RefPtr<TimeRanges> > MediaSource::activeRanges() const +bool MediaSource::isUpdating() const { - Vector<RefPtr<TimeRanges> > activeRanges(m_activeSourceBuffers->length()); - for (size_t i = 0; i < m_activeSourceBuffers->length(); ++i) - activeRanges[i] = m_activeSourceBuffers->item(i)->buffered(ASSERT_NO_EXCEPTION); + // Return true if any member of |m_sourceBuffers| is updating. + for (unsigned long i = 0; i < m_sourceBuffers->length(); ++i) { + if (m_sourceBuffers->item(i)->updating()) + return true; + } - return activeRanges; + return false; } bool MediaSource::isTypeSupported(const String& type) @@ -215,4 +253,296 @@ const AtomicString& MediaSource::interfaceName() const return EventTargetNames::MediaSource; } +ExecutionContext* MediaSource::executionContext() const +{ + return ActiveDOMObject::executionContext(); +} + +void MediaSource::trace(Visitor* visitor) +{ + visitor->trace(m_asyncEventQueue); + visitor->trace(m_sourceBuffers); + visitor->trace(m_activeSourceBuffers); + EventTargetWithInlineData::trace(visitor); +} + +void MediaSource::setWebMediaSourceAndOpen(PassOwnPtr<WebMediaSource> webMediaSource) +{ + TRACE_EVENT_ASYNC_END0("media", "MediaSource::attachToElement", this); + ASSERT(webMediaSource); + ASSERT(!m_webMediaSource); + ASSERT(m_attachedElement); + m_webMediaSource = webMediaSource; + setReadyState(openKeyword()); +} + +void MediaSource::addedToRegistry() +{ + setPendingActivity(this); +} + +void MediaSource::removedFromRegistry() +{ + unsetPendingActivity(this); +} + +double MediaSource::duration() const +{ + return isClosed() ? std::numeric_limits<float>::quiet_NaN() : m_webMediaSource->duration(); +} + +PassRefPtr<TimeRanges> MediaSource::buffered() const +{ + // Implements MediaSource algorithm for HTMLMediaElement.buffered. + // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#htmlmediaelement-extensions + Vector<RefPtr<TimeRanges> > ranges(m_activeSourceBuffers->length()); + for (size_t i = 0; i < m_activeSourceBuffers->length(); ++i) + ranges[i] = m_activeSourceBuffers->item(i)->buffered(ASSERT_NO_EXCEPTION); + + // 1. If activeSourceBuffers.length equals 0 then return an empty TimeRanges object and abort these steps. + if (ranges.isEmpty()) + return TimeRanges::create(); + + // 2. Let active ranges be the ranges returned by buffered for each SourceBuffer object in activeSourceBuffers. + // 3. Let highest end time be the largest range end time in the active ranges. + double highestEndTime = -1; + for (size_t i = 0; i < ranges.size(); ++i) { + unsigned length = ranges[i]->length(); + if (length) + highestEndTime = std::max(highestEndTime, ranges[i]->end(length - 1, ASSERT_NO_EXCEPTION)); + } + + // Return an empty range if all ranges are empty. + if (highestEndTime < 0) + return TimeRanges::create(); + + // 4. Let intersection ranges equal a TimeRange object containing a single range from 0 to highest end time. + RefPtr<TimeRanges> intersectionRanges = TimeRanges::create(0, highestEndTime); + + // 5. For each SourceBuffer object in activeSourceBuffers run the following steps: + bool ended = readyState() == endedKeyword(); + for (size_t i = 0; i < ranges.size(); ++i) { + // 5.1 Let source ranges equal the ranges returned by the buffered attribute on the current SourceBuffer. + TimeRanges* sourceRanges = ranges[i].get(); + + // 5.2 If readyState is "ended", then set the end time on the last range in source ranges to highest end time. + if (ended && sourceRanges->length()) + sourceRanges->add(sourceRanges->start(sourceRanges->length() - 1, ASSERT_NO_EXCEPTION), highestEndTime); + + // 5.3 Let new intersection ranges equal the the intersection between the intersection ranges and the source ranges. + // 5.4 Replace the ranges in intersection ranges with the new intersection ranges. + intersectionRanges->intersectWith(sourceRanges); + } + + return intersectionRanges.release(); +} + +void MediaSource::setDuration(double duration, ExceptionState& exceptionState) +{ + // 2.1 http://www.w3.org/TR/media-source/#widl-MediaSource-duration + // 1. If the value being set is negative or NaN then throw an InvalidAccessError + // exception and abort these steps. + if (std::isnan(duration)) { + exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::notAFiniteNumber(duration, "duration")); + return; + } + if (duration < 0.0) { + exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("duration", duration, 0.0)); + return; + } + + // 2. If the readyState attribute is not "open" then throw an InvalidStateError + // exception and abort these steps. + // 3. If the updating attribute equals true on any SourceBuffer in sourceBuffers, + // then throw an InvalidStateError exception and abort these steps. + if (throwExceptionIfClosedOrUpdating(isOpen(), isUpdating(), exceptionState)) + return; + + // 4. Run the duration change algorithm with new duration set to the value being + // assigned to this attribute. + durationChangeAlgorithm(duration); +} + +void MediaSource::durationChangeAlgorithm(double newDuration) +{ + // Section 2.6.4 Duration change + // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#duration-change-algorithm + // 1. If the current value of duration is equal to new duration, then return. + if (newDuration == duration()) + return; + + // 2. Set old duration to the current value of duration. + double oldDuration = duration(); + + bool requestSeek = m_attachedElement->currentTime() > newDuration; + + // 3. Update duration to new duration. + m_webMediaSource->setDuration(newDuration); + + // 4. If the new duration is less than old duration, then call remove(new duration, old duration) on all all objects in sourceBuffers. + if (newDuration < oldDuration) { + for (size_t i = 0; i < m_sourceBuffers->length(); ++i) + m_sourceBuffers->item(i)->remove(newDuration, oldDuration, ASSERT_NO_EXCEPTION); + } + + // 5. If a user agent is unable to partially render audio frames or text cues that start before and end after the duration, then run the following steps: + // NOTE: Currently we assume that the media engine is able to render partial frames/cues. If a media + // engine gets added that doesn't support this, then we'll need to add logic to handle the substeps. + + // 6. Update the media controller duration to new duration and run the HTMLMediaElement duration change algorithm. + m_attachedElement->durationChanged(newDuration, requestSeek); +} + +void MediaSource::setReadyState(const AtomicString& state) +{ + ASSERT(state == openKeyword() || state == closedKeyword() || state == endedKeyword()); + + AtomicString oldState = readyState(); + WTF_LOG(Media, "MediaSource::setReadyState() %p : %s -> %s", this, oldState.ascii().data(), state.ascii().data()); + + if (state == closedKeyword()) { + m_webMediaSource.clear(); + m_attachedElement = 0; + } + + if (oldState == state) + return; + + m_readyState = state; + + onReadyStateChange(oldState, state); +} + +void MediaSource::endOfStream(const AtomicString& error, ExceptionState& exceptionState) +{ + DEFINE_STATIC_LOCAL(const AtomicString, network, ("network", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, decode, ("decode", AtomicString::ConstructFromLiteral)); + + if (error == network) { + endOfStreamInternal(blink::WebMediaSource::EndOfStreamStatusNetworkError, exceptionState); + } else if (error == decode) { + endOfStreamInternal(blink::WebMediaSource::EndOfStreamStatusDecodeError, exceptionState); + } else { + ASSERT_NOT_REACHED(); // IDL enforcement should prevent this case. + } +} + +void MediaSource::endOfStream(ExceptionState& exceptionState) +{ + endOfStreamInternal(blink::WebMediaSource::EndOfStreamStatusNoError, exceptionState); +} + +void MediaSource::endOfStreamInternal(const blink::WebMediaSource::EndOfStreamStatus eosStatus, ExceptionState& exceptionState) +{ + // 2.2 http://www.w3.org/TR/media-source/#widl-MediaSource-endOfStream-void-EndOfStreamError-error + // 1. If the readyState attribute is not in the "open" state then throw an + // InvalidStateError exception and abort these steps. + // 2. If the updating attribute equals true on any SourceBuffer in sourceBuffers, then throw an + // InvalidStateError exception and abort these steps. + if (throwExceptionIfClosedOrUpdating(isOpen(), isUpdating(), exceptionState)) + return; + + // 3. Run the end of stream algorithm with the error parameter set to error. + // 1. Change the readyState attribute value to "ended". + // 2. Queue a task to fire a simple event named sourceended at the MediaSource. + setReadyState(endedKeyword()); + + // 3. Do various steps based on |eosStatus|. + m_webMediaSource->markEndOfStream(eosStatus); +} + +bool MediaSource::isOpen() const +{ + return readyState() == openKeyword(); +} + +bool MediaSource::isClosed() const +{ + return readyState() == closedKeyword(); +} + +void MediaSource::close() +{ + setReadyState(closedKeyword()); +} + +bool MediaSource::attachToElement(HTMLMediaElement* element) +{ + if (m_attachedElement) + return false; + + ASSERT(isClosed()); + + TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSource::attachToElement", this); + m_attachedElement = element; + return true; +} + +void MediaSource::openIfInEndedState() +{ + if (m_readyState != endedKeyword()) + return; + + setReadyState(openKeyword()); + m_webMediaSource->unmarkEndOfStream(); +} + +bool MediaSource::hasPendingActivity() const +{ + return m_attachedElement || m_webMediaSource + || m_asyncEventQueue->hasPendingEvents() + || ActiveDOMObject::hasPendingActivity(); +} + +void MediaSource::stop() +{ + m_asyncEventQueue->close(); + if (!isClosed()) + setReadyState(closedKeyword()); + m_webMediaSource.clear(); +} + +PassOwnPtr<WebSourceBuffer> MediaSource::createWebSourceBuffer(const String& type, const Vector<String>& codecs, ExceptionState& exceptionState) +{ + WebSourceBuffer* webSourceBuffer = 0; + + switch (m_webMediaSource->addSourceBuffer(type, codecs, &webSourceBuffer)) { + case WebMediaSource::AddStatusOk: + return adoptPtr(webSourceBuffer); + case WebMediaSource::AddStatusNotSupported: + ASSERT(!webSourceBuffer); + // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type + // Step 2: If type contains a MIME type ... that is not supported with the types + // specified for the other SourceBuffer objects in sourceBuffers, then throw + // a NotSupportedError exception and abort these steps. + exceptionState.throwDOMException(NotSupportedError, "The type provided ('" + type + "') is not supported."); + return nullptr; + case WebMediaSource::AddStatusReachedIdLimit: + ASSERT(!webSourceBuffer); + // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type + // Step 3: If the user agent can't handle any more SourceBuffer objects then throw + // a QuotaExceededError exception and abort these steps. + exceptionState.throwDOMException(QuotaExceededError, "This MediaSource has reached the limit of SourceBuffer objects it can handle. No additional SourceBuffer objects may be added."); + return nullptr; + } + + ASSERT_NOT_REACHED(); + return nullptr; +} + +void MediaSource::scheduleEvent(const AtomicString& eventName) +{ + ASSERT(m_asyncEventQueue); + + RefPtrWillBeRawPtr<Event> event = Event::create(eventName); + event->setTarget(this); + + m_asyncEventQueue->enqueueEvent(event.release()); +} + +URLRegistry& MediaSource::registry() const +{ + return MediaSourceRegistry::registry(); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.h b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.h index 5a07035d91a..6a892c143dc 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.h +++ b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.h @@ -32,18 +32,40 @@ #define MediaSource_h #include "bindings/v8/ScriptWrappable.h" -#include "modules/mediasource/MediaSourceBase.h" +#include "core/dom/ActiveDOMObject.h" +#include "core/events/EventTarget.h" +#include "core/html/HTMLMediaSource.h" +#include "core/html/URLRegistry.h" #include "modules/mediasource/SourceBuffer.h" #include "modules/mediasource/SourceBufferList.h" +#include "public/platform/WebMediaSource.h" +#include "wtf/PassOwnPtr.h" #include "wtf/RefCounted.h" +#include "wtf/Vector.h" + +namespace blink { +class WebSourceBuffer; +} namespace WebCore { class ExceptionState; +class GenericEventQueue; -class MediaSource : public MediaSourceBase, public ScriptWrappable { +class MediaSource FINAL + : public RefCountedWillBeRefCountedGarbageCollected<MediaSource> + , public HTMLMediaSource + , public ActiveDOMObject + , public EventTargetWithInlineData + , public ScriptWrappable { + REFCOUNTED_EVENT_TARGET(MediaSource); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaSource); public: - static PassRefPtr<MediaSource> create(ExecutionContext*); + static const AtomicString& openKeyword(); + static const AtomicString& closedKeyword(); + static const AtomicString& endedKeyword(); + + static PassRefPtrWillBeRawPtr<MediaSource> create(ExecutionContext*); virtual ~MediaSource(); // MediaSource.idl methods @@ -51,23 +73,67 @@ public: SourceBufferList* activeSourceBuffers() { return m_activeSourceBuffers.get(); } SourceBuffer* addSourceBuffer(const String& type, ExceptionState&); void removeSourceBuffer(SourceBuffer*, ExceptionState&); + void setDuration(double, ExceptionState&); + const AtomicString& readyState() const { return m_readyState; } + void endOfStream(const AtomicString& error, ExceptionState&); + void endOfStream(ExceptionState&); static bool isTypeSupported(const String& type); + // HTMLMediaSource + virtual bool attachToElement(HTMLMediaElement*) OVERRIDE; + virtual void setWebMediaSourceAndOpen(PassOwnPtr<blink::WebMediaSource>) OVERRIDE; + virtual void close() OVERRIDE; + virtual bool isClosed() const OVERRIDE; + virtual double duration() const OVERRIDE; + virtual PassRefPtr<TimeRanges> buffered() const OVERRIDE; + virtual void refHTMLMediaSource() OVERRIDE { ref(); } + virtual void derefHTMLMediaSource() OVERRIDE { deref(); } + // EventTarget interface virtual const AtomicString& interfaceName() const OVERRIDE; + virtual ExecutionContext* executionContext() const OVERRIDE; + + // ActiveDOMObject interface + virtual bool hasPendingActivity() const OVERRIDE; + virtual void stop() OVERRIDE; + + // URLRegistrable interface + virtual URLRegistry& registry() const OVERRIDE; + + // Used by SourceBuffer. + void openIfInEndedState(); + bool isOpen() const; - using RefCounted<MediaSourceBase>::ref; - using RefCounted<MediaSourceBase>::deref; + // Used by MediaSourceRegistry. + void addedToRegistry(); + void removedFromRegistry(); + + void trace(Visitor*); private: explicit MediaSource(ExecutionContext*); - // MediaSourceBase interface - virtual void onReadyStateChange(const AtomicString&, const AtomicString&) OVERRIDE; - virtual Vector<RefPtr<TimeRanges> > activeRanges() const OVERRIDE; + void setReadyState(const AtomicString&); + void onReadyStateChange(const AtomicString&, const AtomicString&); + + bool isUpdating() const; + + PassOwnPtr<blink::WebSourceBuffer> createWebSourceBuffer(const String& type, const Vector<String>& codecs, ExceptionState&); + void scheduleEvent(const AtomicString& eventName); + void endOfStreamInternal(const blink::WebMediaSource::EndOfStreamStatus, ExceptionState&); + + // Implements the duration change algorithm. + // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#duration-change-algorithm + void durationChangeAlgorithm(double newDuration); + + OwnPtr<blink::WebMediaSource> m_webMediaSource; + AtomicString m_readyState; + OwnPtrWillBeMember<GenericEventQueue> m_asyncEventQueue; + // FIXME: oilpan: This should become a Member. For now, m_attachedElement will be cleared by the HTMLMediaElement destructor. + HTMLMediaElement* m_attachedElement; - RefPtr<SourceBufferList> m_sourceBuffers; - RefPtr<SourceBufferList> m_activeSourceBuffers; + RefPtrWillBeMember<SourceBufferList> m_sourceBuffers; + RefPtrWillBeMember<SourceBufferList> m_activeSourceBuffers; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.idl b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.idl index a5bf84f12e0..a03cde5dee5 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.idl +++ b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSource.idl @@ -28,11 +28,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#idl-def-MediaSource + +enum EndOfStreamError { + "network", + "decode" +}; + [ ActiveDOMObject, Constructor, ConstructorCallWith=ExecutionContext, RuntimeEnabled=MediaSource, + TypeChecking=Interface|Nullable|Unrestricted, ] interface MediaSource : EventTarget { // All the source buffers created by this object. readonly attribute SourceBufferList sourceBuffers; @@ -40,14 +48,14 @@ // Subset of sourceBuffers that provide data for the selected/enabled tracks. readonly attribute SourceBufferList activeSourceBuffers; - [RaisesException=Setter] attribute double duration; + [RaisesException=Setter] attribute unrestricted double duration; [RaisesException] SourceBuffer addSourceBuffer(DOMString type); [RaisesException] void removeSourceBuffer(SourceBuffer buffer); readonly attribute DOMString readyState; - [RaisesException] void endOfStream([Default=NullString] optional DOMString error); + [RaisesException] void endOfStream(optional EndOfStreamError error); static boolean isTypeSupported (DOMString type); }; diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceBase.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceBase.cpp deleted file mode 100644 index c2de62e52b1..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceBase.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/mediasource/MediaSourceBase.h" - -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ExceptionStatePlaceholder.h" -#include "core/dom/ExceptionCode.h" -#include "core/events/Event.h" -#include "core/events/GenericEventQueue.h" -#include "core/html/TimeRanges.h" -#include "modules/mediasource/MediaSourceRegistry.h" -#include "platform/Logging.h" -#include "platform/TraceEvent.h" -#include "public/platform/WebMediaSource.h" -#include "public/platform/WebSourceBuffer.h" -#include "wtf/text/WTFString.h" - -using blink::WebMediaSource; -using blink::WebSourceBuffer; - -namespace WebCore { - -MediaSourceBase::MediaSourceBase(ExecutionContext* context) - : ActiveDOMObject(context) - , m_readyState(closedKeyword()) - , m_asyncEventQueue(GenericEventQueue::create(this)) - , m_attachedElement(0) -{ -} - -MediaSourceBase::~MediaSourceBase() -{ -} - -const AtomicString& MediaSourceBase::openKeyword() -{ - DEFINE_STATIC_LOCAL(const AtomicString, open, ("open", AtomicString::ConstructFromLiteral)); - return open; -} - -const AtomicString& MediaSourceBase::closedKeyword() -{ - DEFINE_STATIC_LOCAL(const AtomicString, closed, ("closed", AtomicString::ConstructFromLiteral)); - return closed; -} - -const AtomicString& MediaSourceBase::endedKeyword() -{ - DEFINE_STATIC_LOCAL(const AtomicString, ended, ("ended", AtomicString::ConstructFromLiteral)); - return ended; -} - -void MediaSourceBase::setWebMediaSourceAndOpen(PassOwnPtr<WebMediaSource> webMediaSource) -{ - TRACE_EVENT_ASYNC_END0("media", "MediaSourceBase::attachToElement", this); - ASSERT(webMediaSource); - ASSERT(!m_webMediaSource); - ASSERT(m_attachedElement); - m_webMediaSource = webMediaSource; - setReadyState(openKeyword()); -} - -void MediaSourceBase::addedToRegistry() -{ - setPendingActivity(this); -} - -void MediaSourceBase::removedFromRegistry() -{ - unsetPendingActivity(this); -} - -double MediaSourceBase::duration() const -{ - return isClosed() ? std::numeric_limits<float>::quiet_NaN() : m_webMediaSource->duration(); -} - -PassRefPtr<TimeRanges> MediaSourceBase::buffered() const -{ - // Implements MediaSource algorithm for HTMLMediaElement.buffered. - // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#htmlmediaelement-extensions - Vector<RefPtr<TimeRanges> > ranges = activeRanges(); - - // 1. If activeSourceBuffers.length equals 0 then return an empty TimeRanges object and abort these steps. - if (ranges.isEmpty()) - return TimeRanges::create(); - - // 2. Let active ranges be the ranges returned by buffered for each SourceBuffer object in activeSourceBuffers. - // 3. Let highest end time be the largest range end time in the active ranges. - double highestEndTime = -1; - for (size_t i = 0; i < ranges.size(); ++i) { - unsigned length = ranges[i]->length(); - if (length) - highestEndTime = std::max(highestEndTime, ranges[i]->end(length - 1, ASSERT_NO_EXCEPTION)); - } - - // Return an empty range if all ranges are empty. - if (highestEndTime < 0) - return TimeRanges::create(); - - // 4. Let intersection ranges equal a TimeRange object containing a single range from 0 to highest end time. - RefPtr<TimeRanges> intersectionRanges = TimeRanges::create(0, highestEndTime); - - // 5. For each SourceBuffer object in activeSourceBuffers run the following steps: - bool ended = readyState() == endedKeyword(); - for (size_t i = 0; i < ranges.size(); ++i) { - // 5.1 Let source ranges equal the ranges returned by the buffered attribute on the current SourceBuffer. - TimeRanges* sourceRanges = ranges[i].get(); - - // 5.2 If readyState is "ended", then set the end time on the last range in source ranges to highest end time. - if (ended && sourceRanges->length()) - sourceRanges->add(sourceRanges->start(sourceRanges->length() - 1, ASSERT_NO_EXCEPTION), highestEndTime); - - // 5.3 Let new intersection ranges equal the the intersection between the intersection ranges and the source ranges. - // 5.4 Replace the ranges in intersection ranges with the new intersection ranges. - intersectionRanges->intersectWith(sourceRanges); - } - - return intersectionRanges.release(); -} - -void MediaSourceBase::setDuration(double duration, ExceptionState& exceptionState) -{ - if (duration < 0.0 || std::isnan(duration)) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } - if (!isOpen()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - // Synchronously process duration change algorithm to enforce any required - // seek is started prior to returning. - m_attachedElement->durationChanged(duration); - m_webMediaSource->setDuration(duration); -} - - -void MediaSourceBase::setReadyState(const AtomicString& state) -{ - ASSERT(state == openKeyword() || state == closedKeyword() || state == endedKeyword()); - - AtomicString oldState = readyState(); - WTF_LOG(Media, "MediaSourceBase::setReadyState() %p : %s -> %s", this, oldState.string().ascii().data(), state.string().ascii().data()); - - if (state == closedKeyword()) { - m_webMediaSource.clear(); - m_attachedElement = 0; - } - - if (oldState == state) - return; - - m_readyState = state; - - onReadyStateChange(oldState, state); -} - -void MediaSourceBase::endOfStream(const AtomicString& error, ExceptionState& exceptionState) -{ - DEFINE_STATIC_LOCAL(const AtomicString, network, ("network", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(const AtomicString, decode, ("decode", AtomicString::ConstructFromLiteral)); - - // 3.1 http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#dom-endofstream - // 1. If the readyState attribute is not in the "open" state then throw an - // InvalidStateError exception and abort these steps. - if (!isOpen()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - WebMediaSource::EndOfStreamStatus eosStatus = WebMediaSource::EndOfStreamStatusNoError; - - if (error.isNull() || error.isEmpty()) { - eosStatus = WebMediaSource::EndOfStreamStatusNoError; - } else if (error == network) { - eosStatus = WebMediaSource::EndOfStreamStatusNetworkError; - } else if (error == decode) { - eosStatus = WebMediaSource::EndOfStreamStatusDecodeError; - } else { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } - - // 2. Change the readyState attribute value to "ended". - setReadyState(endedKeyword()); - m_webMediaSource->markEndOfStream(eosStatus); -} - -bool MediaSourceBase::isOpen() const -{ - return readyState() == openKeyword(); -} - -bool MediaSourceBase::isClosed() const -{ - return readyState() == closedKeyword(); -} - -void MediaSourceBase::close() -{ - setReadyState(closedKeyword()); -} - -bool MediaSourceBase::attachToElement(HTMLMediaElement* element) -{ - if (m_attachedElement) - return false; - - ASSERT(isClosed()); - - TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourceBase::attachToElement", this); - m_attachedElement = element; - return true; -} - -void MediaSourceBase::openIfInEndedState() -{ - if (m_readyState != endedKeyword()) - return; - - setReadyState(openKeyword()); - m_webMediaSource->unmarkEndOfStream(); -} - -bool MediaSourceBase::hasPendingActivity() const -{ - return m_attachedElement || m_webMediaSource - || m_asyncEventQueue->hasPendingEvents() - || ActiveDOMObject::hasPendingActivity(); -} - -void MediaSourceBase::stop() -{ - m_asyncEventQueue->close(); - if (!isClosed()) - setReadyState(closedKeyword()); - m_webMediaSource.clear(); -} - -PassOwnPtr<WebSourceBuffer> MediaSourceBase::createWebSourceBuffer(const String& type, const Vector<String>& codecs, ExceptionState& exceptionState) -{ - WebSourceBuffer* webSourceBuffer = 0; - switch (m_webMediaSource->addSourceBuffer(type, codecs, &webSourceBuffer)) { - case WebMediaSource::AddStatusOk: - return adoptPtr(webSourceBuffer); - case WebMediaSource::AddStatusNotSupported: - ASSERT(!webSourceBuffer); - // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type - // Step 2: If type contains a MIME type ... that is not supported with the types - // specified for the other SourceBuffer objects in sourceBuffers, then throw - // a NotSupportedError exception and abort these steps. - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return nullptr; - case WebMediaSource::AddStatusReachedIdLimit: - ASSERT(!webSourceBuffer); - // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type - // Step 3: If the user agent can't handle any more SourceBuffer objects then throw - // a QuotaExceededError exception and abort these steps. - exceptionState.throwUninformativeAndGenericDOMException(QuotaExceededError); - return nullptr; - } - - ASSERT_NOT_REACHED(); - return nullptr; -} - -void MediaSourceBase::scheduleEvent(const AtomicString& eventName) -{ - ASSERT(m_asyncEventQueue); - - RefPtr<Event> event = Event::create(eventName); - event->setTarget(this); - - m_asyncEventQueue->enqueueEvent(event.release()); -} - -ExecutionContext* MediaSourceBase::executionContext() const -{ - return ActiveDOMObject::executionContext(); -} - -URLRegistry& MediaSourceBase::registry() const -{ - return MediaSourceRegistry::registry(); -} - -} diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceBase.h b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceBase.h deleted file mode 100644 index bd6de4eb61a..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceBase.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef MediaSourceBase_h -#define MediaSourceBase_h - -#include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" -#include "core/html/HTMLMediaSource.h" -#include "core/html/URLRegistry.h" -#include "wtf/PassOwnPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/Vector.h" - -namespace blink { -class WebMediaSource; -class WebSourceBuffer; -} - -namespace WebCore { - -class ExceptionState; -class GenericEventQueue; - -class MediaSourceBase : public RefCounted<MediaSourceBase>, public HTMLMediaSource, public ActiveDOMObject, public EventTargetWithInlineData { - REFCOUNTED_EVENT_TARGET(MediaSourceBase); -public: - static const AtomicString& openKeyword(); - static const AtomicString& closedKeyword(); - static const AtomicString& endedKeyword(); - - virtual ~MediaSourceBase(); - - void addedToRegistry(); - void removedFromRegistry(); - void openIfInEndedState(); - bool isOpen() const; - - // HTMLMediaSource - virtual bool attachToElement(HTMLMediaElement*) OVERRIDE; - virtual void setWebMediaSourceAndOpen(PassOwnPtr<blink::WebMediaSource>) OVERRIDE; - virtual void close() OVERRIDE; - virtual bool isClosed() const OVERRIDE; - virtual double duration() const OVERRIDE; - virtual PassRefPtr<TimeRanges> buffered() const OVERRIDE; - virtual void refHTMLMediaSource() OVERRIDE { ref(); } - virtual void derefHTMLMediaSource() OVERRIDE { deref(); } - - void setDuration(double, ExceptionState&); - const AtomicString& readyState() const { return m_readyState; } - void setReadyState(const AtomicString&); - void endOfStream(const AtomicString& error, ExceptionState&); - - - // ActiveDOMObject interface - virtual bool hasPendingActivity() const OVERRIDE; - virtual void stop() OVERRIDE; - - // EventTarget interface - virtual ExecutionContext* executionContext() const OVERRIDE; - - // URLRegistrable interface - virtual URLRegistry& registry() const OVERRIDE; - -protected: - explicit MediaSourceBase(ExecutionContext*); - - virtual void onReadyStateChange(const AtomicString& oldState, const AtomicString& newState) = 0; - virtual Vector<RefPtr<TimeRanges> > activeRanges() const = 0; - - PassOwnPtr<blink::WebSourceBuffer> createWebSourceBuffer(const String& type, const Vector<String>& codecs, ExceptionState&); - void scheduleEvent(const AtomicString& eventName); - GenericEventQueue* asyncEventQueue() const { return m_asyncEventQueue.get(); } - -private: - OwnPtr<blink::WebMediaSource> m_webMediaSource; - AtomicString m_readyState; - OwnPtr<GenericEventQueue> m_asyncEventQueue; - HTMLMediaElement* m_attachedElement; -}; - -} - -#endif diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceRegistry.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceRegistry.cpp index cdd7e1c7644..439d1b1a81c 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceRegistry.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceRegistry.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "modules/mediasource/MediaSourceRegistry.h" -#include "modules/mediasource/MediaSourceBase.h" +#include "modules/mediasource/MediaSource.h" #include "platform/weborigin/KURL.h" #include "wtf/MainThread.h" @@ -49,7 +49,7 @@ void MediaSourceRegistry::registerURL(SecurityOrigin*, const KURL& url, URLRegis ASSERT(®istrable->registry() == this); ASSERT(isMainThread()); - MediaSourceBase* source = static_cast<MediaSourceBase*>(registrable); + MediaSource* source = static_cast<MediaSource*>(registrable); source->addedToRegistry(); m_mediaSources.set(url.string(), source); } @@ -57,11 +57,11 @@ void MediaSourceRegistry::registerURL(SecurityOrigin*, const KURL& url, URLRegis void MediaSourceRegistry::unregisterURL(const KURL& url) { ASSERT(isMainThread()); - HashMap<String, RefPtr<MediaSourceBase> >::iterator iter = m_mediaSources.find(url.string()); + WillBePersistentHeapHashMap<String, RefPtrWillBeMember<MediaSource> >::iterator iter = m_mediaSources.find(url.string()); if (iter == m_mediaSources.end()) return; - RefPtr<MediaSourceBase> source = iter->value; + RefPtrWillBeRawPtr<MediaSource> source = iter->value; m_mediaSources.remove(iter); source->removedFromRegistry(); } diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceRegistry.h b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceRegistry.h index de6963c0c01..b8c13051b8c 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceRegistry.h +++ b/chromium/third_party/WebKit/Source/modules/mediasource/MediaSourceRegistry.h @@ -32,6 +32,7 @@ #define MediaSourceRegistry_h #include "core/html/URLRegistry.h" +#include "platform/heap/Handle.h" #include "wtf/HashMap.h" #include "wtf/PassRefPtr.h" #include "wtf/text/StringHash.h" @@ -39,9 +40,9 @@ namespace WebCore { class KURL; -class MediaSourceBase; +class MediaSource; -class MediaSourceRegistry : public URLRegistry { +class MediaSourceRegistry FINAL : public URLRegistry { public: // Returns a single instance of MediaSourceRegistry. static MediaSourceRegistry& registry(); @@ -53,7 +54,7 @@ public: private: MediaSourceRegistry(); - HashMap<String, RefPtr<MediaSourceBase> > m_mediaSources; + WillBePersistentHeapHashMap<String, RefPtrWillBeMember<MediaSource> > m_mediaSources; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp index 4c08f27d953..bda5206fd58 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp @@ -31,10 +31,10 @@ #include "config.h" #include "modules/mediasource/SourceBuffer.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "core/events/Event.h" #include "core/events/GenericEventQueue.h" #include "core/fileapi/FileReaderLoader.h" #include "core/fileapi/Stream.h" @@ -53,9 +53,27 @@ using blink::WebSourceBuffer; namespace WebCore { -PassRefPtr<SourceBuffer> SourceBuffer::create(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSource* source, GenericEventQueue* asyncEventQueue) +namespace { + +static bool throwExceptionIfRemovedOrUpdating(bool isRemoved, bool isUpdating, ExceptionState& exceptionState) +{ + if (isRemoved) { + exceptionState.throwDOMException(InvalidStateError, "This SourceBuffer has been removed from the parent media source."); + return true; + } + if (isUpdating) { + exceptionState.throwDOMException(InvalidStateError, "This SourceBuffer is still processing an 'appendBuffer', 'appendStream', or 'remove' operation."); + return true; + } + + return false; +} + +} // namespace + +PassRefPtrWillBeRawPtr<SourceBuffer> SourceBuffer::create(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSource* source, GenericEventQueue* asyncEventQueue) { - RefPtr<SourceBuffer> sourceBuffer(adoptRef(new SourceBuffer(webSourceBuffer, source, asyncEventQueue))); + RefPtrWillBeRawPtr<SourceBuffer> sourceBuffer(adoptRefWillBeRefCountedGarbageCollected(new SourceBuffer(webSourceBuffer, source, asyncEventQueue))); sourceBuffer->suspendIfNeeded(); return sourceBuffer.release(); } @@ -65,10 +83,12 @@ SourceBuffer::SourceBuffer(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSou , m_webSourceBuffer(webSourceBuffer) , m_source(source) , m_asyncEventQueue(asyncEventQueue) + , m_mode(segmentsKeyword()) , m_updating(false) , m_timestampOffset(0) , m_appendWindowStart(0) , m_appendWindowEnd(std::numeric_limits<double>::infinity()) + , m_pendingAppendDataOffset(0) , m_appendBufferAsyncPartRunner(this, &SourceBuffer::appendBufferAsyncPart) , m_pendingRemoveStart(-1) , m_pendingRemoveEnd(-1) @@ -89,14 +109,55 @@ SourceBuffer::~SourceBuffer() ASSERT(!m_stream); } +const AtomicString& SourceBuffer::segmentsKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, segments, ("segments", AtomicString::ConstructFromLiteral)); + return segments; +} + +const AtomicString& SourceBuffer::sequenceKeyword() +{ + DEFINE_STATIC_LOCAL(const AtomicString, sequence, ("sequence", AtomicString::ConstructFromLiteral)); + return sequence; +} + +void SourceBuffer::setMode(const AtomicString& newMode, ExceptionState& exceptionState) +{ + // Section 3.1 On setting mode attribute steps. + // 1. Let new mode equal the new value being assigned to this attribute. + // 2. If this object has been removed from the sourceBuffers attribute of the parent media source, then throw + // an INVALID_STATE_ERR exception and abort these steps. + // 3. If the updating attribute equals true, then throw an INVALID_STATE_ERR exception and abort these steps. + if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState)) + return; + + // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: + // 4.1 Set the readyState attribute of the parent media source to "open" + // 4.2 Queue a task to fire a simple event named sourceopen at the parent media source. + m_source->openIfInEndedState(); + + // 5. If the append state equals PARSING_MEDIA_SEGMENT, then throw an INVALID_STATE_ERR and abort these steps. + // 6. If the new mode equals "sequence", then set the group start timestamp to the highest presentation end timestamp. + WebSourceBuffer::AppendMode appendMode = WebSourceBuffer::AppendModeSegments; + if (newMode == sequenceKeyword()) + appendMode = WebSourceBuffer::AppendModeSequence; + if (!m_webSourceBuffer->setMode(appendMode)) { + exceptionState.throwDOMException(InvalidStateError, "The mode may not be set while the SourceBuffer's append state is 'PARSING_MEDIA_SEGMENT'."); + return; + } + + // 7. Update the attribute to new mode. + m_mode = newMode; +} + PassRefPtr<TimeRanges> SourceBuffer::buffered(ExceptionState& exceptionState) const { // Section 3.1 buffered attribute steps. // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an // InvalidStateError exception and abort these steps. if (isRemoved()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return 0; + exceptionState.throwDOMException(InvalidStateError, "This SourceBuffer has been removed from the parent media source."); + return nullptr; } // 2. Return a new static normalized TimeRanges object for the media segments buffered. @@ -111,26 +172,23 @@ double SourceBuffer::timestampOffset() const void SourceBuffer::setTimestampOffset(double offset, ExceptionState& exceptionState) { // Section 3.1 timestampOffset attribute setter steps. + // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-SourceBuffer-timestampOffset // 1. Let new timestamp offset equal the new value being assigned to this attribute. // 2. If this object has been removed from the sourceBuffers attribute of the parent media source, then throw an // InvalidStateError exception and abort these steps. // 3. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps. - if (isRemoved() || m_updating) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState)) return; - } // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: // 4.1 Set the readyState attribute of the parent media source to "open" // 4.2 Queue a task to fire a simple event named sourceopen at the parent media source. m_source->openIfInEndedState(); - // 5. If this object is waiting for the end of a media segment to be appended, then throw an InvalidStateError - // and abort these steps. - // - // FIXME: Add step 6 text when mode attribute is implemented. + // 5. If the append state equals PARSING_MEDIA_SEGMENT, then throw an INVALID_STATE_ERR and abort these steps. + // 6. If the mode attribute equals "sequence", then set the group start timestamp to new timestamp offset. if (!m_webSourceBuffer->setTimestampOffset(offset)) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "The timestamp offset may not be set while the SourceBuffer's append state is 'PARSING_MEDIA_SEGMENT'."); return; } @@ -145,27 +203,18 @@ double SourceBuffer::appendWindowStart() const void SourceBuffer::setAppendWindowStart(double start, ExceptionState& exceptionState) { - // Enforce throwing an exception on restricted double values. - if (std::isnan(start) - || start == std::numeric_limits<double>::infinity() - || start == -std::numeric_limits<double>::infinity()) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - // Section 3.1 appendWindowStart attribute setter steps. + // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-SourceBuffer-appendWindowStart // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an // InvalidStateError exception and abort these steps. // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps. - if (isRemoved() || m_updating) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState)) return; - } // 3. If the new value is less than 0 or greater than or equal to appendWindowEnd then throw an InvalidAccessError // exception and abort these steps. if (start < 0 || start >= m_appendWindowEnd) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexOutsideRange("value", start, 0.0, ExceptionMessages::ExclusiveBound, m_appendWindowEnd, ExceptionMessages::InclusiveBound)); return; } @@ -183,19 +232,22 @@ double SourceBuffer::appendWindowEnd() const void SourceBuffer::setAppendWindowEnd(double end, ExceptionState& exceptionState) { // Section 3.1 appendWindowEnd attribute setter steps. + // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-SourceBuffer-appendWindowEnd // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an // InvalidStateError exception and abort these steps. // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps. - if (isRemoved() || m_updating) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState)) return; - } // 3. If the new value equals NaN, then throw an InvalidAccessError and abort these steps. + if (std::isnan(end)) { + exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::notAFiniteNumber(end)); + return; + } // 4. If the new value is less than or equal to appendWindowStart then throw an InvalidAccessError // exception and abort these steps. - if (std::isnan(end) || end <= m_appendWindowStart) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + if (end <= m_appendWindowStart) { + exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("value", end, m_appendWindowStart)); return; } @@ -209,12 +261,6 @@ void SourceBuffer::appendBuffer(PassRefPtr<ArrayBuffer> data, ExceptionState& ex { // Section 3.2 appendBuffer() // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data - // 1. If data is null then throw an InvalidAccessError exception and abort these steps. - if (!data) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } - appendBufferInternal(static_cast<const unsigned char*>(data->data()), data->byteLength(), exceptionState); } @@ -222,22 +268,16 @@ void SourceBuffer::appendBuffer(PassRefPtr<ArrayBufferView> data, ExceptionState { // Section 3.2 appendBuffer() // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data - // 1. If data is null then throw an InvalidAccessError exception and abort these steps. - if (!data) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } - appendBufferInternal(static_cast<const unsigned char*>(data->baseAddress()), data->byteLength(), exceptionState); } -void SourceBuffer::appendStream(PassRefPtr<Stream> stream, ExceptionState& exceptionState) +void SourceBuffer::appendStream(PassRefPtrWillBeRawPtr<Stream> stream, ExceptionState& exceptionState) { m_streamMaxSizeValid = false; appendStreamInternal(stream, exceptionState); } -void SourceBuffer::appendStream(PassRefPtr<Stream> stream, unsigned long long maxSize, ExceptionState& exceptionState) +void SourceBuffer::appendStream(PassRefPtrWillBeRawPtr<Stream> stream, unsigned long long maxSize, ExceptionState& exceptionState) { m_streamMaxSizeValid = maxSize > 0; if (m_streamMaxSizeValid) @@ -253,8 +293,12 @@ void SourceBuffer::abort(ExceptionState& exceptionState) // then throw an InvalidStateError exception and abort these steps. // 2. If the readyState attribute of the parent media source is not in the "open" state // then throw an InvalidStateError exception and abort these steps. - if (isRemoved() || !m_source->isOpen()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (isRemoved()) { + exceptionState.throwDOMException(InvalidStateError, "This SourceBuffer has been removed from the parent media source."); + return; + } + if (!m_source->isOpen()) { + exceptionState.throwDOMException(InvalidStateError, "The parent media source's readyState is not 'open'."); return; } @@ -276,18 +320,21 @@ void SourceBuffer::remove(double start, double end, ExceptionState& exceptionSta // Section 3.2 remove() method steps. // 1. If start is negative or greater than duration, then throw an InvalidAccessError exception and abort these steps. // 2. If end is less than or equal to start, then throw an InvalidAccessError exception and abort these steps. - if (start < 0 || (m_source && (std::isnan(m_source->duration()) || start > m_source->duration())) || end <= start) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + + if (start < 0 || (m_source && (std::isnan(m_source->duration()) || start > m_source->duration()))) { + exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexOutsideRange("start", start, 0.0, ExceptionMessages::ExclusiveBound, !m_source || std::isnan(m_source->duration()) ? 0 : m_source->duration(), ExceptionMessages::ExclusiveBound)); + return; + } + if (end <= start) { + exceptionState.throwDOMException(InvalidAccessError, "The end value provided (" + String::number(end) + ") must be greater than the start value provided (" + String::number(start) + ")."); return; } // 3. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an // InvalidStateError exception and abort these steps. // 4. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps. - if (isRemoved() || m_updating) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState)) return; - } TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::remove", this); @@ -330,6 +377,7 @@ void SourceBuffer::abortIfUpdating() // 3.1. Abort the buffer append and stream append loop algorithms if they are running. m_appendBufferAsyncPartRunner.stop(); m_pendingAppendData.clear(); + m_pendingAppendDataOffset = 0; m_removeAsyncPartRunner.stop(); m_pendingRemoveStart = -1; @@ -359,7 +407,7 @@ void SourceBuffer::removedFromMediaSource() m_webSourceBuffer->removedFromMediaSource(); m_webSourceBuffer.clear(); - m_source = 0; + m_source = nullptr; m_asyncEventQueue = 0; } @@ -408,7 +456,7 @@ void SourceBuffer::scheduleEvent(const AtomicString& eventName) { ASSERT(m_asyncEventQueue); - RefPtr<Event> event = Event::create(eventName); + RefPtrWillBeRawPtr<Event> event = Event::create(eventName); event->setTarget(this); m_asyncEventQueue->enqueueEvent(event.release()); @@ -419,59 +467,83 @@ void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size // Section 3.2 appendBuffer() // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data - // Step 1 is enforced by the caller. - // 2. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps. - // 3. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps. - if (isRemoved() || m_updating) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + // 1. Run the prepare append algorithm. + // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-prepare-append + // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps. + // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps. + if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState)) return; - } - TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendBuffer", this); + TRACE_EVENT_ASYNC_BEGIN1("media", "SourceBuffer::appendBuffer", this, "size", size); - // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ... + // 3. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ... m_source->openIfInEndedState(); - // Steps 5-6 + // Steps 4-5 - end "prepare append" algorithm. - // 7. Add data to the end of the input buffer. - m_pendingAppendData.append(data, size); + // 2. Add data to the end of the input buffer. + ASSERT(data || size == 0); + if (data) + m_pendingAppendData.append(data, size); + m_pendingAppendDataOffset = 0; - // 8. Set the updating attribute to true. + // 3. Set the updating attribute to true. m_updating = true; - // 9. Queue a task to fire a simple event named updatestart at this SourceBuffer object. + // 4. Queue a task to fire a simple event named updatestart at this SourceBuffer object. scheduleEvent(EventTypeNames::updatestart); - // 10. Asynchronously run the buffer append algorithm. + // 5. Asynchronously run the buffer append algorithm. m_appendBufferAsyncPartRunner.runAsync(); - TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "waiting"); + TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "initialDelay"); } void SourceBuffer::appendBufferAsyncPart() { ASSERT(m_updating); - TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "appending"); - // Section 3.5.4 Buffer Append Algorithm // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-buffer-append // 1. Run the segment parser loop algorithm. // Step 2 doesn't apply since we run Step 1 synchronously here. - size_t appendSize = m_pendingAppendData.size(); - if (!appendSize) { - // Resize buffer for 0 byte appends so we always have a valid pointer. - // We need to convey all appends, even 0 byte ones to |m_webSourceBuffer| - // so that it can clear its end of stream state if necessary. - m_pendingAppendData.resize(1); + ASSERT(m_pendingAppendData.size() >= m_pendingAppendDataOffset); + size_t appendSize = m_pendingAppendData.size() - m_pendingAppendDataOffset; + + // Impose an arbitrary max size for a single append() call so that an append + // doesn't block the renderer event loop very long. This value was selected + // by looking at YouTube SourceBuffer usage across a variety of bitrates. + // This value allows relatively large appends while keeping append() call + // duration in the ~5-15ms range. + const size_t MaxAppendSize = 128 * 1024; + if (appendSize > MaxAppendSize) + appendSize = MaxAppendSize; + + TRACE_EVENT_ASYNC_STEP_INTO1("media", "SourceBuffer::appendBuffer", this, "appending", "appendSize", static_cast<unsigned>(appendSize)); + + // |zero| is used for 0 byte appends so we always have a valid pointer. + // We need to convey all appends, even 0 byte ones to |m_webSourceBuffer| + // so that it can clear its end of stream state if necessary. + unsigned char zero = 0; + unsigned char* appendData = &zero; + if (appendSize) + appendData = m_pendingAppendData.data() + m_pendingAppendDataOffset; + + m_webSourceBuffer->append(appendData, appendSize, &m_timestampOffset); + + m_pendingAppendDataOffset += appendSize; + + if (m_pendingAppendDataOffset < m_pendingAppendData.size()) { + m_appendBufferAsyncPartRunner.runAsync(); + TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "nextPieceDelay"); + return; } - m_webSourceBuffer->append(m_pendingAppendData.data(), appendSize); // 3. Set the updating attribute to false. m_updating = false; m_pendingAppendData.clear(); + m_pendingAppendDataOffset = 0; // 4. Queue a task to fire a simple event named update at this SourceBuffer object. scheduleEvent(EventTypeNames::update); @@ -505,25 +577,23 @@ void SourceBuffer::removeAsyncPart() scheduleEvent(EventTypeNames::updateend); } -void SourceBuffer::appendStreamInternal(PassRefPtr<Stream> stream, ExceptionState& exceptionState) +void SourceBuffer::appendStreamInternal(PassRefPtrWillBeRawPtr<Stream> stream, ExceptionState& exceptionState) { // Section 3.2 appendStream() // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendStream-void-Stream-stream-unsigned-long-long-maxSize - // 1. If stream is null then throw an InvalidAccessError exception and abort these steps. - if (!stream || stream->isNeutered()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + // (0. If the stream has been neutered, then throw an InvalidAccessError exception and abort these steps.) + if (stream->isNeutered()) { + exceptionState.throwDOMException(InvalidAccessError, "The stream provided has been neutered."); return; } - // 2. Run the prepare append algorithm. + // 1. Run the prepare append algorithm. // Section 3.5.4 Prepare Append Algorithm. // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-prepare-append // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps. // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps. - if (isRemoved() || m_updating) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState)) return; - } TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendStream", this); @@ -532,13 +602,13 @@ void SourceBuffer::appendStreamInternal(PassRefPtr<Stream> stream, ExceptionStat // Steps 4-5 of the prepare append algorithm are handled by m_webSourceBuffer. - // 3. Set the updating attribute to true. + // 2. Set the updating attribute to true. m_updating = true; - // 4. Queue a task to fire a simple event named updatestart at this SourceBuffer object. + // 3. Queue a task to fire a simple event named updatestart at this SourceBuffer object. scheduleEvent(EventTypeNames::updatestart); - // 5. Asynchronously run the stream append loop algorithm with stream and maxSize. + // 4. Asynchronously run the stream append loop algorithm with stream and maxSize. stream->neuter(); m_loader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadByClient, this)); @@ -610,7 +680,7 @@ void SourceBuffer::clearAppendStreamState() m_streamMaxSizeValid = false; m_streamMaxSize = 0; m_loader.clear(); - m_stream = 0; + m_stream = nullptr; } void SourceBuffer::didStartLoading() @@ -623,8 +693,7 @@ void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength WTF_LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, this); ASSERT(m_updating); ASSERT(m_loader); - - m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), dataLength); + m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), dataLength, &m_timestampOffset); } void SourceBuffer::didFinishLoading() @@ -639,4 +708,11 @@ void SourceBuffer::didFail(FileError::ErrorCode errorCode) appendStreamDone(false); } +void SourceBuffer::trace(Visitor* visitor) +{ + visitor->trace(m_source); + visitor->trace(m_stream); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.h b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.h index 1d2d2998058..27c14124b83 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.h +++ b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.h @@ -33,8 +33,8 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" #include "core/fileapi/FileReaderLoaderClient.h" +#include "modules/EventTargetModules.h" #include "platform/AsyncMethodRunner.h" #include "platform/weborigin/KURL.h" #include "wtf/OwnPtr.h" @@ -57,22 +57,27 @@ class MediaSource; class Stream; class TimeRanges; -class SourceBuffer : public RefCounted<SourceBuffer>, public ActiveDOMObject, public EventTargetWithInlineData, public ScriptWrappable, public FileReaderLoaderClient { +class SourceBuffer FINAL : public RefCountedWillBeRefCountedGarbageCollected<SourceBuffer>, public ActiveDOMObject, public EventTargetWithInlineData, public ScriptWrappable, public FileReaderLoaderClient { REFCOUNTED_EVENT_TARGET(SourceBuffer); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(SourceBuffer); public: - static PassRefPtr<SourceBuffer> create(PassOwnPtr<blink::WebSourceBuffer>, MediaSource*, GenericEventQueue*); + static PassRefPtrWillBeRawPtr<SourceBuffer> create(PassOwnPtr<blink::WebSourceBuffer>, MediaSource*, GenericEventQueue*); + static const AtomicString& segmentsKeyword(); + static const AtomicString& sequenceKeyword(); virtual ~SourceBuffer(); // SourceBuffer.idl methods + const AtomicString& mode() const { return m_mode; } + void setMode(const AtomicString&, ExceptionState&); bool updating() const { return m_updating; } PassRefPtr<TimeRanges> buffered(ExceptionState&) const; double timestampOffset() const; void setTimestampOffset(double, ExceptionState&); void appendBuffer(PassRefPtr<ArrayBuffer> data, ExceptionState&); void appendBuffer(PassRefPtr<ArrayBufferView> data, ExceptionState&); - void appendStream(PassRefPtr<Stream>, ExceptionState&); - void appendStream(PassRefPtr<Stream>, unsigned long long maxSize, ExceptionState&); + void appendStream(PassRefPtrWillBeRawPtr<Stream>, ExceptionState&); + void appendStream(PassRefPtrWillBeRawPtr<Stream>, unsigned long long maxSize, ExceptionState&); void abort(ExceptionState&); void remove(double start, double end, ExceptionState&); double appendWindowStart() const; @@ -93,6 +98,8 @@ public: virtual ExecutionContext* executionContext() const OVERRIDE; virtual const AtomicString& interfaceName() const OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: SourceBuffer(PassOwnPtr<blink::WebSourceBuffer>, MediaSource*, GenericEventQueue*); @@ -104,7 +111,7 @@ private: void removeAsyncPart(); - void appendStreamInternal(PassRefPtr<Stream>, ExceptionState&); + void appendStreamInternal(PassRefPtrWillBeRawPtr<Stream>, ExceptionState&); void appendStreamAsyncPart(); void appendStreamDone(bool success); void clearAppendStreamState(); @@ -116,15 +123,17 @@ private: virtual void didFail(FileError::ErrorCode) OVERRIDE; OwnPtr<blink::WebSourceBuffer> m_webSourceBuffer; - MediaSource* m_source; + RawPtrWillBeMember<MediaSource> m_source; GenericEventQueue* m_asyncEventQueue; + AtomicString m_mode; bool m_updating; double m_timestampOffset; double m_appendWindowStart; double m_appendWindowEnd; Vector<unsigned char> m_pendingAppendData; + size_t m_pendingAppendDataOffset; AsyncMethodRunner<SourceBuffer> m_appendBufferAsyncPartRunner; double m_pendingRemoveStart; @@ -134,7 +143,7 @@ private: bool m_streamMaxSizeValid; unsigned long long m_streamMaxSize; AsyncMethodRunner<SourceBuffer> m_appendStreamAsyncPartRunner; - RefPtr<Stream> m_stream; + RefPtrWillBeMember<Stream> m_stream; OwnPtr<FileReaderLoader> m_loader; }; diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl index e2712bdb9ad..7827d60d74b 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl +++ b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBuffer.idl @@ -28,12 +28,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#idl-def-SourceBuffer + +enum AppendMode { + "segments", + "sequence" +}; + [ - NoInterfaceObject, ActiveDOMObject, - RuntimeEnabled=MediaSource + NoInterfaceObject, + RuntimeEnabled=MediaSource, + TypeChecking=Interface|Nullable|Unrestricted, ] interface SourceBuffer : EventTarget { + // Gets or sets the AppendMode. + // FIXME: Remove MediaSourceExperimental once mode attribute is implemented and stabilized. See http://crbug.com/249422. + [RaisesException=Setter, RuntimeEnabled=MediaSourceExperimental] attribute AppendMode mode; + readonly attribute boolean updating; // Returns the time ranges buffered. @@ -46,7 +58,7 @@ [RaisesException=Setter] attribute double appendWindowStart; // Presentation timestamp for the end of append window. - [RaisesException=Setter] attribute double appendWindowEnd; + [RaisesException=Setter] attribute unrestricted double appendWindowEnd; // Append segment data. [RaisesException] void appendBuffer(ArrayBuffer data); @@ -56,6 +68,8 @@ // Abort the current segment append sequence. [RaisesException] void abort(); + // Pending W3C bug: "Change SourceBuffer.remove() end parameter to 'unrestricted double'", + // https://www.w3.org/Bugs/Public/show_bug.cgi?id=25518 [RaisesException] void remove(double start, double end); }; diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.cpp index b647933f4b6..87e6b824a4f 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "modules/mediasource/SourceBufferList.h" -#include "core/events/Event.h" #include "core/events/GenericEventQueue.h" +#include "modules/EventModules.h" #include "modules/mediasource/SourceBuffer.h" namespace WebCore { @@ -49,7 +49,7 @@ SourceBufferList::~SourceBufferList() ASSERT(m_list.isEmpty()); } -void SourceBufferList::add(PassRefPtr<SourceBuffer> buffer) +void SourceBufferList::add(PassRefPtrWillBeRawPtr<SourceBuffer> buffer) { m_list.append(buffer); scheduleEvent(EventTypeNames::addsourcebuffer); @@ -74,7 +74,7 @@ void SourceBufferList::scheduleEvent(const AtomicString& eventName) { ASSERT(m_asyncEventQueue); - RefPtr<Event> event = Event::create(eventName); + RefPtrWillBeRawPtr<Event> event = Event::create(eventName); event->setTarget(this); m_asyncEventQueue->enqueueEvent(event.release()); @@ -90,4 +90,10 @@ ExecutionContext* SourceBufferList::executionContext() const return m_executionContext; } +void SourceBufferList::trace(Visitor* visitor) +{ + visitor->trace(m_list); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.h b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.h index 21311fc1afc..fab0d568869 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.h +++ b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.h @@ -32,7 +32,8 @@ #define SourceBufferList_h #include "bindings/v8/ScriptWrappable.h" -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" #include "wtf/Vector.h" @@ -41,19 +42,20 @@ namespace WebCore { class SourceBuffer; class GenericEventQueue; -class SourceBufferList : public RefCounted<SourceBufferList>, public ScriptWrappable, public EventTargetWithInlineData { +class SourceBufferList FINAL : public RefCountedWillBeRefCountedGarbageCollected<SourceBufferList>, public ScriptWrappable, public EventTargetWithInlineData { REFCOUNTED_EVENT_TARGET(SourceBufferList); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(SourceBufferList); public: - static PassRefPtr<SourceBufferList> create(ExecutionContext* context, GenericEventQueue* asyncEventQueue) + static PassRefPtrWillBeRawPtr<SourceBufferList> create(ExecutionContext* context, GenericEventQueue* asyncEventQueue) { - return adoptRef(new SourceBufferList(context, asyncEventQueue)); + return adoptRefWillBeRefCountedGarbageCollected(new SourceBufferList(context, asyncEventQueue)); } virtual ~SourceBufferList(); unsigned long length() const { return m_list.size(); } SourceBuffer* item(unsigned long index) const { return (index < m_list.size()) ? m_list[index].get() : 0; } - void add(PassRefPtr<SourceBuffer>); + void add(PassRefPtrWillBeRawPtr<SourceBuffer>); void remove(SourceBuffer*); bool contains(SourceBuffer* buffer) { return m_list.find(buffer) != kNotFound; } void clear(); @@ -62,6 +64,8 @@ public: virtual const AtomicString& interfaceName() const OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: SourceBufferList(ExecutionContext*, GenericEventQueue*); @@ -70,7 +74,7 @@ private: ExecutionContext* m_executionContext; GenericEventQueue* m_asyncEventQueue; - Vector<RefPtr<SourceBuffer> > m_list; + WillBeHeapVector<RefPtrWillBeMember<SourceBuffer> > m_list; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.idl b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.idl index 4b5f1803206..bbac1f0402d 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.idl +++ b/chromium/third_party/WebKit/Source/modules/mediasource/SourceBufferList.idl @@ -29,6 +29,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject, RuntimeEnabled=MediaSource, ] interface SourceBufferList : EventTarget { diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.cpp index 96fe6c2e4d8..b1e799d7c99 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.cpp @@ -32,17 +32,17 @@ #include "modules/mediasource/URLMediaSource.h" #include "core/dom/DOMURL.h" -#include "modules/mediasource/MediaSourceBase.h" +#include "modules/mediasource/MediaSource.h" #include "wtf/MainThread.h" namespace WebCore { -String URLMediaSource::createObjectURL(ExecutionContext* executionContext, MediaSourceBase* source) +String URLMediaSource::createObjectURL(ExecutionContext* executionContext, MediaSource* source) { // Since WebWorkers cannot obtain MediaSource objects, we should be on the main thread. ASSERT(isMainThread()); - if (!executionContext || !source) + if (!executionContext) return String(); return DOMURL::createPublicURL(executionContext, source); } diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.h b/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.h index 9f002d47792..c8b13192c8a 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.h +++ b/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.h @@ -35,12 +35,12 @@ namespace WebCore { -class MediaSourceBase; +class MediaSource; class ExecutionContext; class URLMediaSource { public: - static String createObjectURL(ExecutionContext*, MediaSourceBase*); + static String createObjectURL(ExecutionContext*, MediaSource*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.idl b/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.idl index e259be034c9..0d336fde060 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.idl +++ b/chromium/third_party/WebKit/Source/modules/mediasource/URLMediaSource.idl @@ -27,7 +27,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -partial interface URL { - [CallWith=ExecutionContext,TreatReturnedNullStringAs=Null] static DOMString createObjectURL(MediaSource? source); - [CallWith=ExecutionContext,TreatReturnedNullStringAs=Null] static DOMString createObjectURL(WebKitMediaSource? source); + +// https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#idl-def-URL + +[ + TypeChecking=Interface|Nullable, +] partial interface URL { + [CallWith=ExecutionContext, TreatReturnedNullStringAs=Null] static DOMString createObjectURL(MediaSource source); }; diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.cpp index 1c73fdb7ac9..5a6ecb7e1a6 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.cpp @@ -32,15 +32,15 @@ #include "modules/mediasource/VideoPlaybackQuality.h" #include "core/dom/Document.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "core/timing/Performance.h" namespace WebCore { -PassRefPtr<VideoPlaybackQuality> VideoPlaybackQuality::create( +PassRefPtrWillBeRawPtr<VideoPlaybackQuality> VideoPlaybackQuality::create( const Document& document, unsigned totalVideoFrames, unsigned droppedVideoFrames, unsigned corruptedVideoFrames) { - return adoptRef(new VideoPlaybackQuality(document, totalVideoFrames, droppedVideoFrames, corruptedVideoFrames)); + return adoptRefWillBeNoop(new VideoPlaybackQuality(document, totalVideoFrames, droppedVideoFrames, corruptedVideoFrames)); } VideoPlaybackQuality::VideoPlaybackQuality( @@ -50,8 +50,8 @@ VideoPlaybackQuality::VideoPlaybackQuality( , m_droppedVideoFrames(droppedVideoFrames) , m_corruptedVideoFrames(corruptedVideoFrames) { - if (document.domWindow() && document.domWindow()->performance()) - m_creationTime = document.domWindow()->performance()->now(); + if (document.domWindow()) + m_creationTime = document.domWindow()->performance().now(); } } diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.h b/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.h index 104957e3c47..98d1c183563 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.h +++ b/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.h @@ -31,6 +31,7 @@ #ifndef VideoPlaybackQuality_h #define VideoPlaybackQuality_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -38,15 +39,17 @@ namespace WebCore { class Document; -class VideoPlaybackQuality : public RefCounted<VideoPlaybackQuality> { +class VideoPlaybackQuality : public RefCountedWillBeGarbageCollected<VideoPlaybackQuality> { public: - static PassRefPtr<VideoPlaybackQuality> create(const Document&, unsigned totalVideoFrames, unsigned droppedVideoFrames, unsigned corruptedVideoFrames); + static PassRefPtrWillBeRawPtr<VideoPlaybackQuality> create(const Document&, unsigned totalVideoFrames, unsigned droppedVideoFrames, unsigned corruptedVideoFrames); double creationTime() const { return m_creationTime; } unsigned totalVideoFrames() const { return m_totalVideoFrames; } unsigned droppedVideoFrames() const { return m_droppedVideoFrames; } unsigned corruptedVideoFrames() const { return m_corruptedVideoFrames; } + void trace(Visitor*) { } + private: VideoPlaybackQuality(const Document&, unsigned totalVideoFrames, unsigned droppedVideoFrames, unsigned corruptedVideoFrames); diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.idl b/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.idl index 746f53c4b9b..104bcabc469 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.idl +++ b/chromium/third_party/WebKit/Source/modules/mediasource/VideoPlaybackQuality.idl @@ -28,6 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ [ + WillBeGarbageCollected, RuntimeEnabled=MediaSourceExperimental, ] interface VideoPlaybackQuality { readonly attribute double creationTime; diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitMediaSource.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/WebKitMediaSource.cpp deleted file mode 100644 index dc1897236a3..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitMediaSource.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/mediasource/WebKitMediaSource.h" - -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ExceptionStatePlaceholder.h" -#include "core/dom/ExceptionCode.h" -#include "core/html/TimeRanges.h" -#include "modules/mediasource/MediaSourceRegistry.h" -#include "platform/ContentType.h" -#include "platform/MIMETypeRegistry.h" -#include "public/platform/WebSourceBuffer.h" -#include "wtf/Uint8Array.h" - -using blink::WebSourceBuffer; - -namespace WebCore { - -PassRefPtr<WebKitMediaSource> WebKitMediaSource::create(ExecutionContext* context) -{ - RefPtr<WebKitMediaSource> mediaSource(adoptRef(new WebKitMediaSource(context))); - mediaSource->suspendIfNeeded(); - return mediaSource.release(); -} - -WebKitMediaSource::WebKitMediaSource(ExecutionContext* context) - : MediaSourceBase(context) -{ - ScriptWrappable::init(this); - m_sourceBuffers = WebKitSourceBufferList::create(executionContext(), asyncEventQueue()); - m_activeSourceBuffers = WebKitSourceBufferList::create(executionContext(), asyncEventQueue()); -} - -WebKitSourceBufferList* WebKitMediaSource::sourceBuffers() -{ - return m_sourceBuffers.get(); -} - -WebKitSourceBufferList* WebKitMediaSource::activeSourceBuffers() -{ - // FIXME(91649): support track selection - return m_activeSourceBuffers.get(); -} - -WebKitSourceBuffer* WebKitMediaSource::addSourceBuffer(const String& type, ExceptionState& exceptionState) -{ - // 3.1 http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#dom-addsourcebuffer - // 1. If type is null or an empty then throw an InvalidAccessError exception and - // abort these steps. - if (type.isNull() || type.isEmpty()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return 0; - } - - // 2. If type contains a MIME type that is not supported ..., then throw a - // NotSupportedError exception and abort these steps. - if (!isTypeSupported(type)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } - - // 4. If the readyState attribute is not in the "open" state then throw an - // InvalidStateError exception and abort these steps. - if (!isOpen()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return 0; - } - - // 5. Create a new SourceBuffer object and associated resources. - ContentType contentType(type); - Vector<String> codecs = contentType.codecs(); - OwnPtr<WebSourceBuffer> webSourceBuffer = createWebSourceBuffer(contentType.type(), codecs, exceptionState); - if (!webSourceBuffer) - return 0; - - RefPtr<WebKitSourceBuffer> buffer = WebKitSourceBuffer::create(webSourceBuffer.release(), this); - // 6. Add the new object to sourceBuffers and fire a addsourcebuffer on that object. - m_sourceBuffers->add(buffer); - m_activeSourceBuffers->add(buffer); - // 7. Return the new object to the caller. - return buffer.get(); -} - -void WebKitMediaSource::removeSourceBuffer(WebKitSourceBuffer* buffer, ExceptionState& exceptionState) -{ - // 3.1 http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#dom-removesourcebuffer - // 1. If sourceBuffer is null then throw an InvalidAccessError exception and - // abort these steps. - if (!buffer) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } - - // 2. If sourceBuffers is empty then throw an InvalidStateError exception and - // abort these steps. - if (isClosed() || !m_sourceBuffers->length()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - // 3. If sourceBuffer specifies an object that is not in sourceBuffers then - // throw a NotFoundError exception and abort these steps. - // 6. Remove sourceBuffer from sourceBuffers and fire a removesourcebuffer event - // on that object. - if (!m_sourceBuffers->remove(buffer)) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); - return; - } - - // 7. Destroy all resources for sourceBuffer. - m_activeSourceBuffers->remove(buffer); - - // 4. Remove track information from audioTracks, videoTracks, and textTracks for all tracks - // associated with sourceBuffer and fire a simple event named change on the modified lists. - // FIXME(91649): support track selection - - // 5. If sourceBuffer is in activeSourceBuffers, then remove it from that list and fire a - // removesourcebuffer event on that object. - // FIXME(91649): support track selection -} - -void WebKitMediaSource::onReadyStateChange(const AtomicString& oldState, const AtomicString& newState) -{ - if (isClosed()) { - m_sourceBuffers->clear(); - m_activeSourceBuffers->clear(); - scheduleEvent(EventTypeNames::webkitsourceclose); - return; - } - - if (oldState == openKeyword() && newState == endedKeyword()) { - scheduleEvent(EventTypeNames::webkitsourceended); - return; - } - - if (isOpen()) { - scheduleEvent(EventTypeNames::webkitsourceopen); - return; - } -} - -Vector<RefPtr<TimeRanges> > WebKitMediaSource::activeRanges() const -{ - Vector<RefPtr<TimeRanges> > activeRanges(m_activeSourceBuffers->length()); - for (size_t i = 0; i < m_activeSourceBuffers->length(); ++i) - activeRanges[i] = m_activeSourceBuffers->item(i)->buffered(ASSERT_NO_EXCEPTION); - - return activeRanges; -} - -bool WebKitMediaSource::isTypeSupported(const String& type) -{ - // Section 2.1 isTypeSupported() method steps. - // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-isTypeSupported-boolean-DOMString-type - // 1. If type is an empty string, then return false. - if (type.isNull() || type.isEmpty()) - return false; - - ContentType contentType(type); - String codecs = contentType.parameter("codecs"); - - // 2. If type does not contain a valid MIME type string, then return false. - if (contentType.type().isEmpty()) - return false; - - // 3. If type contains a media type or media subtype that the MediaSource does not support, then return false. - // 4. If type contains at a codec that the MediaSource does not support, then return false. - // 5. If the MediaSource does not support the specified combination of media type, media subtype, and codecs then return false. - // 6. Return true. - return MIMETypeRegistry::isSupportedMediaSourceMIMEType(contentType.type(), codecs); -} - -const AtomicString& WebKitMediaSource::interfaceName() const -{ - return EventTargetNames::WebKitMediaSource; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitMediaSource.idl b/chromium/third_party/WebKit/Source/modules/mediasource/WebKitMediaSource.idl deleted file mode 100644 index 4ceea5b9886..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitMediaSource.idl +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - ActiveDOMObject, - Constructor, - ConstructorCallWith=ExecutionContext, - NoInterfaceObject, - RuntimeEnabled=WebKitMediaSource, -] interface WebKitMediaSource : EventTarget { - // All the source buffers created by this object. - readonly attribute WebKitSourceBufferList sourceBuffers; - - // Subset of sourceBuffers that provide data for the selected/enabled tracks. - readonly attribute WebKitSourceBufferList activeSourceBuffers; - - [RaisesException=Setter] attribute double duration; - - [RaisesException] WebKitSourceBuffer addSourceBuffer(DOMString type); - [RaisesException] void removeSourceBuffer(WebKitSourceBuffer buffer); - - readonly attribute DOMString readyState; - - [RaisesException] void endOfStream([Default=NullString] optional DOMString error); - - static boolean isTypeSupported (DOMString type); -}; diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBuffer.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBuffer.cpp deleted file mode 100644 index 905a0203766..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBuffer.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/mediasource/WebKitSourceBuffer.h" - -#include "bindings/v8/ExceptionState.h" -#include "core/dom/ExceptionCode.h" -#include "core/html/TimeRanges.h" -#include "modules/mediasource/WebKitMediaSource.h" -#include "platform/TraceEvent.h" -#include "public/platform/WebSourceBuffer.h" -#include "wtf/Uint8Array.h" - -using blink::WebSourceBuffer; - -namespace WebCore { - -PassRefPtr<WebKitSourceBuffer> WebKitSourceBuffer::create(PassOwnPtr<WebSourceBuffer> webSourceBuffer, PassRefPtr<WebKitMediaSource> source) -{ - return adoptRef(new WebKitSourceBuffer(webSourceBuffer, source)); -} - -WebKitSourceBuffer::WebKitSourceBuffer(PassOwnPtr<WebSourceBuffer> webSourceBuffer, PassRefPtr<WebKitMediaSource> source) - : m_webSourceBuffer(webSourceBuffer) - , m_source(source) - , m_timestampOffset(0) -{ - ASSERT(m_webSourceBuffer); - ASSERT(m_source); - ScriptWrappable::init(this); -} - -WebKitSourceBuffer::~WebKitSourceBuffer() -{ -} - -PassRefPtr<TimeRanges> WebKitSourceBuffer::buffered(ExceptionState& exceptionState) const -{ - // Section 3.1 buffered attribute steps. - // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an - // InvalidStateError exception and abort these steps. - if (isRemoved()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return 0; - } - - // 2. Return a new static normalized TimeRanges object for the media segments buffered. - return TimeRanges::create(m_webSourceBuffer->buffered()); -} - -double WebKitSourceBuffer::timestampOffset() const -{ - return m_timestampOffset; -} - -void WebKitSourceBuffer::setTimestampOffset(double offset, ExceptionState& exceptionState) -{ - // Section 3.1 timestampOffset attribute setter steps. - // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an - // InvalidStateError exception and abort these steps. - if (isRemoved()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: - // 4.1 Set the readyState attribute of the parent media source to "open" - // 4.2 Queue a task to fire a simple event named sourceopen at the parent media source. - m_source->openIfInEndedState(); - - // 5. If this object is waiting for the end of a media segment to be appended, then throw an InvalidStateError - // and abort these steps. - if (!m_webSourceBuffer->setTimestampOffset(offset)) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - // 6. Update the attribute to the new value. - m_timestampOffset = offset; -} - -void WebKitSourceBuffer::append(PassRefPtr<Uint8Array> data, ExceptionState& exceptionState) -{ - TRACE_EVENT0("media", "SourceBuffer::append"); - - // SourceBuffer.append() steps from October 1st version of the Media Source Extensions spec. - // https://dvcs.w3.org/hg/html-media/raw-file/7bab66368f2c/media-source/media-source.html#dom-append - - // 2. If data is null then throw an InvalidAccessError exception and abort these steps. - if (!data) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return; - } - - // 3. If this object has been removed from the sourceBuffers attribute of media source then throw - // an InvalidStateError exception and abort these steps. - if (isRemoved()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - // 5. If the readyState attribute of media source is in the "ended" state then run the following steps: - // 5.1. Set the readyState attribute of media source to "open" - // 5.2. Queue a task to fire a simple event named sourceopen at media source. - m_source->openIfInEndedState(); - - // Steps 6 & beyond are handled by m_webSourceBuffer. - m_webSourceBuffer->append(data->data(), data->length()); -} - -void WebKitSourceBuffer::abort(ExceptionState& exceptionState) -{ - // Section 3.2 abort() method steps. - // 1. If this object has been removed from the sourceBuffers attribute of the parent media source - // then throw an InvalidStateError exception and abort these steps. - // 2. If the readyState attribute of the parent media source is not in the "open" state - // then throw an InvalidStateError exception and abort these steps. - if (isRemoved() || !m_source->isOpen()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - // 4. Run the reset parser state algorithm. - m_webSourceBuffer->abort(); -} - -void WebKitSourceBuffer::removedFromMediaSource() -{ - if (isRemoved()) - return; - - m_webSourceBuffer->removedFromMediaSource(); - m_source.clear(); -} - -bool WebKitSourceBuffer::isRemoved() const -{ - return !m_source; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBuffer.idl b/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBuffer.idl deleted file mode 100644 index c896a673d2c..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBuffer.idl +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - NoInterfaceObject, - RuntimeEnabled=WebKitMediaSource -] interface WebKitSourceBuffer { - - // Returns the time ranges buffered. - [RaisesException=Getter] readonly attribute TimeRanges buffered; - - // Applies an offset to media segment timestamps. - [RaisesException=Setter] attribute double timestampOffset; - - // Append segment data. - [RaisesException] void append(Uint8Array data); - - // Abort the current segment append sequence. - [RaisesException] void abort(); -}; - diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.cpp b/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.cpp deleted file mode 100644 index 301e2cf03e7..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/mediasource/WebKitSourceBufferList.h" - -#include "core/events/Event.h" -#include "core/events/GenericEventQueue.h" -#include "modules/mediasource/WebKitSourceBuffer.h" - -namespace WebCore { - -WebKitSourceBufferList::WebKitSourceBufferList(ExecutionContext* context, GenericEventQueue* asyncEventQueue) - : m_executionContext(context) - , m_asyncEventQueue(asyncEventQueue) -{ - ScriptWrappable::init(this); -} - -unsigned long WebKitSourceBufferList::length() const -{ - return m_list.size(); -} - -WebKitSourceBuffer* WebKitSourceBufferList::item(unsigned index) const -{ - if (index >= m_list.size()) - return 0; - return m_list[index].get(); -} - -void WebKitSourceBufferList::add(PassRefPtr<WebKitSourceBuffer> buffer) -{ - m_list.append(buffer); - createAndFireEvent(EventTypeNames::webkitaddsourcebuffer); -} - -bool WebKitSourceBufferList::remove(WebKitSourceBuffer* buffer) -{ - size_t index = m_list.find(buffer); - if (index == kNotFound) - return false; - - buffer->removedFromMediaSource(); - m_list.remove(index); - createAndFireEvent(EventTypeNames::webkitremovesourcebuffer); - return true; -} - -void WebKitSourceBufferList::clear() -{ - for (size_t i = 0; i < m_list.size(); ++i) - m_list[i]->removedFromMediaSource(); - m_list.clear(); - createAndFireEvent(EventTypeNames::webkitremovesourcebuffer); -} - -void WebKitSourceBufferList::createAndFireEvent(const AtomicString& eventName) -{ - ASSERT(m_asyncEventQueue); - - RefPtr<Event> event = Event::create(eventName); - event->setTarget(this); - - m_asyncEventQueue->enqueueEvent(event.release()); -} - -const AtomicString& WebKitSourceBufferList::interfaceName() const -{ - return EventTargetNames::WebKitSourceBufferList; -} - -ExecutionContext* WebKitSourceBufferList::executionContext() const -{ - return m_executionContext; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.h b/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.h deleted file mode 100644 index 86ca9700777..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebKitSourceBufferList_h -#define WebKitSourceBufferList_h - -#include "bindings/v8/ScriptWrappable.h" -#include "core/events/EventTarget.h" -#include "wtf/RefCounted.h" -#include "wtf/Vector.h" - -namespace WebCore { - -class WebKitSourceBuffer; -class GenericEventQueue; - -class WebKitSourceBufferList : public RefCounted<WebKitSourceBufferList>, public ScriptWrappable, public EventTargetWithInlineData { - REFCOUNTED_EVENT_TARGET(WebKitSourceBufferList); -public: - static PassRefPtr<WebKitSourceBufferList> create(ExecutionContext* context, GenericEventQueue* asyncEventQueue) - { - return adoptRef(new WebKitSourceBufferList(context, asyncEventQueue)); - } - virtual ~WebKitSourceBufferList() { } - - unsigned long length() const; - WebKitSourceBuffer* item(unsigned index) const; - - void add(PassRefPtr<WebKitSourceBuffer>); - bool remove(WebKitSourceBuffer*); - void clear(); - - // EventTarget interface - virtual const AtomicString& interfaceName() const OVERRIDE; - virtual ExecutionContext* executionContext() const OVERRIDE; - -private: - WebKitSourceBufferList(ExecutionContext*, GenericEventQueue*); - - void createAndFireEvent(const AtomicString&); - - ExecutionContext* m_executionContext; - GenericEventQueue* m_asyncEventQueue; - - Vector<RefPtr<WebKitSourceBuffer> > m_list; -}; - -} // namespace WebCore - -#endif diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.idl b/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.idl deleted file mode 100644 index b3d2ec44b0e..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBufferList.idl +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - NoInterfaceObject, - RuntimeEnabled=WebKitMediaSource -] interface WebKitSourceBufferList : EventTarget { - readonly attribute unsigned long length; - getter WebKitSourceBuffer item(unsigned long index); -}; - diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WindowMediaSource.idl b/chromium/third_party/WebKit/Source/modules/mediasource/WindowMediaSource.idl deleted file mode 100644 index 6221f9e53b1..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WindowMediaSource.idl +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -partial interface Window { - [RuntimeEnabled=WebKitMediaSource] attribute WebKitMediaSourceConstructor WebKitMediaSource; - [RuntimeEnabled=WebKitMediaSource] attribute WebKitSourceBufferConstructor WebKitSourceBuffer; - [RuntimeEnabled=WebKitMediaSource] attribute WebKitSourceBufferListConstructor WebKitSourceBufferList; -}; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/DOMWindowMediaStream.h b/chromium/third_party/WebKit/Source/modules/mediastream/DOMWindowMediaStream.h new file mode 100644 index 00000000000..03f01d5c617 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/mediastream/DOMWindowMediaStream.h @@ -0,0 +1,7 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO: This is a dummy header file required by the generated binding code. +// This file should be removed after fixing the code generator. + diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp index 2a93b96818f..f1c002734a6 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp @@ -36,55 +36,50 @@ #include "bindings/v8/Dictionary.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" +#include "wtf/HashMap.h" +#include "wtf/Vector.h" #include "wtf/text/StringHash.h" namespace WebCore { +namespace MediaConstraintsImpl { -PassRefPtr<MediaConstraintsImpl> MediaConstraintsImpl::create(const Dictionary& constraints, ExceptionState& exceptionState) +static bool parse(const Dictionary& constraintsDictionary, blink::WebVector<blink::WebMediaConstraint>& optional, blink::WebVector<blink::WebMediaConstraint>& mandatory) { - RefPtr<MediaConstraintsImpl> object = adoptRef(new MediaConstraintsImpl()); - if (!object->initialize(constraints)) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; - } - return object.release(); -} - -PassRefPtr<MediaConstraintsImpl> MediaConstraintsImpl::create() -{ - return adoptRef(new MediaConstraintsImpl()); -} - -bool MediaConstraintsImpl::initialize(const Dictionary& constraints) -{ - if (constraints.isUndefinedOrNull()) + if (constraintsDictionary.isUndefinedOrNull()) return true; Vector<String> names; - constraints.getOwnPropertyNames(names); + constraintsDictionary.getOwnPropertyNames(names); - String mandatory("mandatory"); - String optional("optional"); + String mandatoryName("mandatory"); + String optionalName("optional"); for (Vector<String>::iterator it = names.begin(); it != names.end(); ++it) { - if (*it != mandatory && *it != optional) + if (*it != mandatoryName && *it != optionalName) return false; } - if (names.contains(mandatory)) { - Dictionary mandatoryConstraints; - bool ok = constraints.get(mandatory, mandatoryConstraints); - if (!ok || mandatoryConstraints.isUndefinedOrNull()) + Vector<blink::WebMediaConstraint> mandatoryConstraintsVector; + if (names.contains(mandatoryName)) { + Dictionary mandatoryConstraintsDictionary; + bool ok = constraintsDictionary.get(mandatoryName, mandatoryConstraintsDictionary); + if (!ok || mandatoryConstraintsDictionary.isUndefinedOrNull()) return false; - ok = mandatoryConstraints.getOwnPropertiesAsStringHashMap(m_mandatoryConstraints); + HashMap<String, String> mandatoryConstraintsHashMap; + ok = mandatoryConstraintsDictionary.getOwnPropertiesAsStringHashMap(mandatoryConstraintsHashMap); if (!ok) return false; + + HashMap<String, String>::const_iterator iter = mandatoryConstraintsHashMap.begin(); + for (; iter != mandatoryConstraintsHashMap.end(); ++iter) + mandatoryConstraintsVector.append(blink::WebMediaConstraint(iter->key, iter->value)); } - if (names.contains(optional)) { + Vector<blink::WebMediaConstraint> optionalConstraintsVector; + if (names.contains(optionalName)) { ArrayValue optionalConstraints; - bool ok = constraints.get(optional, optionalConstraints); + bool ok = constraintsDictionary.get(optionalName, optionalConstraints); if (!ok || optionalConstraints.isUndefinedOrNull()) return false; @@ -107,52 +102,36 @@ bool MediaConstraintsImpl::initialize(const Dictionary& constraints) ok = constraint.get(key, value); if (!ok) return false; - m_optionalConstraints.append(MediaConstraint(key, value)); + optionalConstraintsVector.append(blink::WebMediaConstraint(key, value)); } } + optional.assign(optionalConstraintsVector); + mandatory.assign(mandatoryConstraintsVector); return true; } -MediaConstraintsImpl::~MediaConstraintsImpl() -{ -} -void MediaConstraintsImpl::getMandatoryConstraints(Vector<MediaConstraint>& constraints) const +blink::WebMediaConstraints create(const Dictionary& constraintsDictionary, ExceptionState& exceptionState) { - constraints.clear(); - HashMap<String, String>::const_iterator i = m_mandatoryConstraints.begin(); - for (; i != m_mandatoryConstraints.end(); ++i) - constraints.append(MediaConstraint(i->key, i->value)); -} - -void MediaConstraintsImpl::getOptionalConstraints(Vector<MediaConstraint>& constraints) const -{ - constraints.clear(); - constraints.append(m_optionalConstraints); -} - -bool MediaConstraintsImpl::getMandatoryConstraintValue(const String& name, String& value) const -{ - HashMap<String, String>::const_iterator i = m_mandatoryConstraints.find(name); - if (i == m_mandatoryConstraints.end()) - return false; + blink::WebVector<blink::WebMediaConstraint> optional; + blink::WebVector<blink::WebMediaConstraint> mandatory; + if (!parse(constraintsDictionary, optional, mandatory)) { + exceptionState.throwTypeError("Malformed constraints object."); + return blink::WebMediaConstraints(); + } - value = i->value; - return true; + blink::WebMediaConstraints constraints; + constraints.initialize(optional, mandatory); + return constraints; } -bool MediaConstraintsImpl::getOptionalConstraintValue(const String& name, String& value) const +blink::WebMediaConstraints create() { - Vector<MediaConstraint>::const_iterator i = m_optionalConstraints.begin(); - for (; i != m_optionalConstraints.end(); ++i) { - if (i->m_name == name) { - value = i->m_value; - return true; - } - } - - return false; + blink::WebMediaConstraints constraints; + constraints.initialize(); + return constraints; } +} // namespace MediaConstraintsImpl } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.h index d7073c66fd4..08b7cf95263 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.h @@ -31,35 +31,19 @@ #ifndef MediaConstraintsImpl_h #define MediaConstraintsImpl_h -#include "platform/mediastream/MediaConstraints.h" -#include "wtf/HashMap.h" -#include "wtf/Vector.h" +#include "public/platform/WebMediaConstraints.h" namespace WebCore { class Dictionary; - class ExceptionState; -class MediaConstraintsImpl : public MediaConstraints { -public: - static PassRefPtr<MediaConstraintsImpl> create(); - static PassRefPtr<MediaConstraintsImpl> create(const Dictionary&, ExceptionState&); - virtual ~MediaConstraintsImpl(); - - virtual void getMandatoryConstraints(Vector<MediaConstraint>&) const OVERRIDE; - virtual void getOptionalConstraints(Vector<MediaConstraint>&) const OVERRIDE; - - virtual bool getMandatoryConstraintValue(const String& name, String& value) const OVERRIDE; - virtual bool getOptionalConstraintValue(const String& name, String& value) const OVERRIDE; +namespace MediaConstraintsImpl { -private: - MediaConstraintsImpl() { } - bool initialize(const Dictionary&); +blink::WebMediaConstraints create(); +blink::WebMediaConstraints create(const Dictionary&, ExceptionState&); - HashMap<String, String> m_mandatoryConstraints; - Vector<MediaConstraint> m_optionalConstraints; -}; +} } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfo.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfo.cpp new file mode 100644 index 00000000000..17826923a5e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfo.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/mediastream/MediaDeviceInfo.h" + +#include "wtf/text/WTFString.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<MediaDeviceInfo> MediaDeviceInfo::create(const blink::WebMediaDeviceInfo& webMediaDeviceInfo) +{ + ASSERT(!webMediaDeviceInfo.isNull()); + return adoptRefWillBeNoop(new MediaDeviceInfo(webMediaDeviceInfo)); +} + +MediaDeviceInfo::MediaDeviceInfo(const blink::WebMediaDeviceInfo& webMediaDeviceInfo) + : m_webMediaDeviceInfo(webMediaDeviceInfo) +{ +} + +String MediaDeviceInfo::deviceId() const +{ + return m_webMediaDeviceInfo.deviceId(); +} + +String MediaDeviceInfo::kind() const +{ + switch (m_webMediaDeviceInfo.kind()) { + case blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput: + return "audioinput"; + case blink::WebMediaDeviceInfo::MediaDeviceKindAudioOutput: + return "audiooutput"; + case blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput: + return "videoinput"; + } + + ASSERT_NOT_REACHED(); + return String(); +} + +String MediaDeviceInfo::label() const +{ + return m_webMediaDeviceInfo.label(); +} + +String MediaDeviceInfo::groupId() const +{ + return m_webMediaDeviceInfo.groupId(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/notifications/WorkerGlobalScopeNotifications.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfo.h index e52816039ea..64903434136 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/WorkerGlobalScopeNotifications.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -21,41 +21,38 @@ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ -#ifndef WorkerGlobalScopeNotifications_h -#define WorkerGlobalScopeNotifications_h - -#if ENABLE(LEGACY_NOTIFICATIONS) +#ifndef MediaDeviceInfo_h +#define MediaDeviceInfo_h -#include "core/workers/WorkerSupplementable.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebMediaDeviceInfo.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" +#include "wtf/Vector.h" namespace WebCore { -class NotificationCenter; -class ExecutionContext; -class WorkerGlobalScope; - -class WorkerGlobalScopeNotifications : public WorkerSupplement { +class MediaDeviceInfo FINAL : public RefCountedWillBeGarbageCollectedFinalized<MediaDeviceInfo> { public: - virtual ~WorkerGlobalScopeNotifications(); + static PassRefPtrWillBeRawPtr<MediaDeviceInfo> create(const blink::WebMediaDeviceInfo&); - static NotificationCenter* webkitNotifications(WorkerGlobalScope*); - static WorkerGlobalScopeNotifications* from(WorkerGlobalScope*); + String deviceId() const; + String kind() const; + String label() const; + String groupId() const; -private: - explicit WorkerGlobalScopeNotifications(WorkerGlobalScope*); + void trace(Visitor*) { } - NotificationCenter* webkitNotifications(); - static const char* supplementName(); +private: + explicit MediaDeviceInfo(const blink::WebMediaDeviceInfo&); - WorkerGlobalScope* m_context; - RefPtr<NotificationCenter> m_notificationCenter; + blink::WebMediaDeviceInfo m_webMediaDeviceInfo; }; -} // namespace WebCore +typedef WillBeHeapVector<RefPtrWillBeMember<MediaDeviceInfo> > MediaDeviceInfoVector; -#endif // WorkerGlobalScopeNotifications_h +} // namespace WebCore -#endif // ENABLE(LEGACY_NOTIFICATIONS) +#endif // MediaDeviceInfo_h diff --git a/chromium/third_party/WebKit/Source/modules/notifications/WindowNotifications.idl b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfo.idl index 9f74cf00abb..1698fc77a88 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/WindowNotifications.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfo.idl @@ -1,6 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -11,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,9 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum MediaDeviceKind { + "audioinput", + "audiooutput", + "videoinput" +}; + [ - Conditional=LEGACY_NOTIFICATIONS, - ImplementedAs=DOMWindowNotifications -] partial interface Window { - [RuntimeEnabled=Notifications, MeasureAs=LegacyNotifications, PerWorldBindings, ActivityLogging=GetterForIsolatedWorlds] readonly attribute NotificationCenter webkitNotifications; + WillBeGarbageCollected, + NoInterfaceObject +] interface MediaDeviceInfo { + readonly attribute DOMString deviceId; + readonly attribute MediaDeviceKind kind; + readonly attribute DOMString label; + readonly attribute DOMString groupId; }; diff --git a/chromium/third_party/WebKit/Source/modules/notifications/DOMWindowNotifications.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfoCallback.h index 7fd6f897474..97d9d2175b0 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/DOMWindowNotifications.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfoCallback.h @@ -1,6 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -11,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,42 +23,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DOMWindowNotifications_h -#define DOMWindowNotifications_h +#ifndef MediaDeviceInfoCallback_h +#define MediaDeviceInfoCallback_h -#if ENABLE(LEGACY_NOTIFICATIONS) - -#include "core/frame/DOMWindowProperty.h" -#include "platform/Supplementable.h" -#include "wtf/text/WTFString.h" +#include "modules/mediastream/MediaDeviceInfo.h" namespace WebCore { -class DOMWindow; -class NotificationCenter; - -class DOMWindowNotifications : public Supplement<DOMWindow>, public DOMWindowProperty { +class MediaDeviceInfoCallback { public: - virtual ~DOMWindowNotifications(); - - static NotificationCenter* webkitNotifications(DOMWindow*); - static DOMWindowNotifications* from(DOMWindow*); - - virtual void willDestroyGlobalObjectInFrame() OVERRIDE; - virtual void willDetachGlobalObjectFromFrame() OVERRIDE; - -private: - explicit DOMWindowNotifications(DOMWindow*); - - NotificationCenter* webkitNotifications(); - static const char* supplementName(); - - DOMWindow* m_window; - RefPtr<NotificationCenter> m_notificationCenter; + virtual ~MediaDeviceInfoCallback() { } + virtual void handleEvent(const MediaDeviceInfoVector&) = 0; }; } // namespace WebCore -#endif // ENABLE(LEGACY_NOTIFICATIONS) - -#endif // DOMWindowNotifications_h +#endif // MediaDeviceInfoCallback_h diff --git a/chromium/third_party/WebKit/Source/modules/notifications/WorkerGlobalScopeNotifications.idl b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfoCallback.idl index f6468a74764..f6792c9995f 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/WorkerGlobalScopeNotifications.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDeviceInfoCallback.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -21,11 +21,9 @@ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ -[ - Conditional=LEGACY_NOTIFICATIONS -] partial interface WorkerGlobalScope { - [RuntimeEnabled=Notifications] readonly attribute NotificationCenter webkitNotifications; +callback interface MediaDeviceInfoCallback { + void handleEvent(sequence<MediaDeviceInfo> devices); }; + diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaDevicesRequest.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDevicesRequest.cpp new file mode 100644 index 00000000000..06491250c30 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDevicesRequest.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "modules/mediastream/MediaDevicesRequest.h" + +#include "bindings/v8/ExceptionState.h" +#include "core/dom/Document.h" +#include "modules/mediastream/UserMediaController.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<MediaDevicesRequest> MediaDevicesRequest::create(ExecutionContext* context, UserMediaController* controller, PassOwnPtr<MediaDeviceInfoCallback> callback, ExceptionState& exceptionState) +{ + RefPtrWillBeRawPtr<MediaDevicesRequest> request = adoptRefWillBeRefCountedGarbageCollected(new MediaDevicesRequest(context, controller, callback)); + request->suspendIfNeeded(); + return request.release(); +} + +MediaDevicesRequest::MediaDevicesRequest(ExecutionContext* context, UserMediaController* controller, PassOwnPtr<MediaDeviceInfoCallback> callback) + : ActiveDOMObject(context) + , m_controller(controller) + , m_callback(callback) +{ +} + +MediaDevicesRequest::~MediaDevicesRequest() +{ +} + +Document* MediaDevicesRequest::ownerDocument() +{ + if (ExecutionContext* context = executionContext()) { + return toDocument(context); + } + + return 0; +} + +void MediaDevicesRequest::start() +{ + if (m_controller) + m_controller->requestMediaDevices(this); +} + +void MediaDevicesRequest::succeed(const MediaDeviceInfoVector& mediaDevices) +{ + if (!executionContext() || !m_callback) + return; + + m_callback->handleEvent(mediaDevices); +} + +void MediaDevicesRequest::stop() +{ + m_callback.clear(); + m_controller = 0; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaDevicesRequest.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDevicesRequest.h new file mode 100644 index 00000000000..e75632aa031 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaDevicesRequest.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaDevicesRequest_h +#define MediaDevicesRequest_h + +#include "core/dom/ActiveDOMObject.h" +#include "modules/mediastream/MediaDeviceInfo.h" +#include "modules/mediastream/MediaDeviceInfoCallback.h" +#include "platform/heap/Handle.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" + +namespace WebCore { + +class Document; +class ExceptionState; +class MediaStreamDescriptor; +class UserMediaController; + +class MediaDevicesRequest FINAL : public RefCountedWillBeRefCountedGarbageCollected<MediaDevicesRequest>, public ActiveDOMObject { +public: + static PassRefPtrWillBeRawPtr<MediaDevicesRequest> create(ExecutionContext*, UserMediaController*, PassOwnPtr<MediaDeviceInfoCallback>, ExceptionState&); + virtual ~MediaDevicesRequest(); + + MediaDeviceInfoCallback* callback() const { return m_callback.get(); } + Document* ownerDocument(); + + void start(); + + void succeed(const MediaDeviceInfoVector&); + + // ActiveDOMObject + virtual void stop() OVERRIDE; + + void trace(Visitor*) { } + +private: + MediaDevicesRequest(ExecutionContext*, UserMediaController*, PassOwnPtr<MediaDeviceInfoCallback>); + + UserMediaController* m_controller; + + OwnPtr<MediaDeviceInfoCallback> m_callback; +}; + +} // namespace WebCore + +#endif // MediaDevicesRequest_h diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.cpp index a917973498b..4f22927b528 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.cpp @@ -27,80 +27,71 @@ #include "modules/mediastream/MediaStream.h" #include "bindings/v8/ExceptionState.h" -#include "core/events/Event.h" #include "core/dom/ExceptionCode.h" -#include "core/platform/mediastream/MediaStreamCenter.h" #include "modules/mediastream/MediaStreamRegistry.h" #include "modules/mediastream/MediaStreamTrackEvent.h" +#include "platform/mediastream/MediaStreamCenter.h" #include "platform/mediastream/MediaStreamSource.h" namespace WebCore { -static bool containsSource(MediaStreamSourceVector& sourceVector, MediaStreamSource* source) +static bool containsSource(MediaStreamTrackVector& trackVector, MediaStreamSource* source) { - for (size_t i = 0; i < sourceVector.size(); ++i) { - if (source->id() == sourceVector[i]->id()) + for (size_t i = 0; i < trackVector.size(); ++i) { + if (source->id() == trackVector[i]->component()->source()->id()) return true; } return false; } -static void processTrack(MediaStreamTrack* track, MediaStreamSourceVector& sourceVector) +static void processTrack(MediaStreamTrack* track, MediaStreamTrackVector& trackVector) { if (track->ended()) return; MediaStreamSource* source = track->component()->source(); - if (!containsSource(sourceVector, source)) - sourceVector.append(source); + if (!containsSource(trackVector, source)) + trackVector.append(track); } -static PassRefPtr<MediaStream> createFromSourceVectors(ExecutionContext* context, const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources) +PassRefPtrWillBeRawPtr<MediaStream> MediaStream::create(ExecutionContext* context) { - RefPtr<MediaStreamDescriptor> descriptor = MediaStreamDescriptor::create(audioSources, videoSources); - MediaStreamCenter::instance().didCreateMediaStream(descriptor.get()); + MediaStreamTrackVector audioTracks; + MediaStreamTrackVector videoTracks; - return MediaStream::create(context, descriptor.release()); + return adoptRefWillBeRefCountedGarbageCollected(new MediaStream(context, audioTracks, videoTracks)); } -PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context) -{ - MediaStreamSourceVector audioSources; - MediaStreamSourceVector videoSources; - - return createFromSourceVectors(context, audioSources, videoSources); -} - -PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStream> stream) +PassRefPtrWillBeRawPtr<MediaStream> MediaStream::create(ExecutionContext* context, PassRefPtrWillBeRawPtr<MediaStream> stream) { ASSERT(stream); - MediaStreamSourceVector audioSources; - MediaStreamSourceVector videoSources; + MediaStreamTrackVector audioTracks; + MediaStreamTrackVector videoTracks; for (size_t i = 0; i < stream->m_audioTracks.size(); ++i) - processTrack(stream->m_audioTracks[i].get(), audioSources); + processTrack(stream->m_audioTracks[i].get(), audioTracks); for (size_t i = 0; i < stream->m_videoTracks.size(); ++i) - processTrack(stream->m_videoTracks[i].get(), videoSources); + processTrack(stream->m_videoTracks[i].get(), videoTracks); - return createFromSourceVectors(context, audioSources, videoSources); + return adoptRefWillBeRefCountedGarbageCollected(new MediaStream(context, audioTracks, videoTracks)); } -PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, const MediaStreamTrackVector& tracks) +PassRefPtrWillBeRawPtr<MediaStream> MediaStream::create(ExecutionContext* context, const MediaStreamTrackVector& tracks) { - MediaStreamSourceVector audioSources; - MediaStreamSourceVector videoSources; + MediaStreamTrackVector audioTracks; + MediaStreamTrackVector videoTracks; for (size_t i = 0; i < tracks.size(); ++i) - processTrack(tracks[i].get(), tracks[i]->kind() == "audio" ? audioSources : videoSources); + processTrack(tracks[i].get(), tracks[i]->kind() == "audio" ? audioTracks : videoTracks); - return createFromSourceVectors(context, audioSources, videoSources); + return adoptRefWillBeRefCountedGarbageCollected(new MediaStream(context, audioTracks, videoTracks)); } -PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor) +PassRefPtrWillBeRawPtr<MediaStream> MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor) { - return adoptRef(new MediaStream(context, streamDescriptor)); + return adoptRefWillBeRefCountedGarbageCollected(new MediaStream(context, streamDescriptor)); } MediaStream::MediaStream(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor) @@ -114,17 +105,59 @@ MediaStream::MediaStream(ExecutionContext* context, PassRefPtr<MediaStreamDescri size_t numberOfAudioTracks = m_descriptor->numberOfAudioComponents(); m_audioTracks.reserveCapacity(numberOfAudioTracks); - for (size_t i = 0; i < numberOfAudioTracks; i++) - m_audioTracks.append(MediaStreamTrack::create(context, m_descriptor->audioComponent(i))); + for (size_t i = 0; i < numberOfAudioTracks; i++) { + RefPtrWillBeRawPtr<MediaStreamTrack> newTrack = MediaStreamTrack::create(context, m_descriptor->audioComponent(i)); + newTrack->registerMediaStream(this); + m_audioTracks.append(newTrack.release()); + } size_t numberOfVideoTracks = m_descriptor->numberOfVideoComponents(); m_videoTracks.reserveCapacity(numberOfVideoTracks); - for (size_t i = 0; i < numberOfVideoTracks; i++) - m_videoTracks.append(MediaStreamTrack::create(context, m_descriptor->videoComponent(i))); + for (size_t i = 0; i < numberOfVideoTracks; i++) { + RefPtrWillBeRawPtr<MediaStreamTrack> newTrack = MediaStreamTrack::create(context, m_descriptor->videoComponent(i)); + newTrack->registerMediaStream(this); + m_videoTracks.append(newTrack.release()); + } +} + +MediaStream::MediaStream(ExecutionContext* context, const MediaStreamTrackVector& audioTracks, const MediaStreamTrackVector& videoTracks) + : ContextLifecycleObserver(context) + , m_stopped(false) + , m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired) +{ + ScriptWrappable::init(this); + + MediaStreamComponentVector audioComponents; + MediaStreamComponentVector videoComponents; + + MediaStreamTrackVector::const_iterator iter; + for (iter = audioTracks.begin(); iter != audioTracks.end(); ++iter) { + (*iter)->registerMediaStream(this); + audioComponents.append((*iter)->component()); + } + for (iter = videoTracks.begin(); iter != videoTracks.end(); ++iter) { + (*iter)->registerMediaStream(this); + videoComponents.append((*iter)->component()); + } + + m_descriptor = MediaStreamDescriptor::create(audioComponents, videoComponents); + m_descriptor->setClient(this); + MediaStreamCenter::instance().didCreateMediaStream(m_descriptor.get()); + + m_audioTracks = audioTracks; + m_videoTracks = videoTracks; } MediaStream::~MediaStream() { +#if !ENABLE(OILPAN) + for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) + (*iter)->unregisterMediaStream(this); + + for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) + (*iter)->unregisterMediaStream(this); +#endif + m_descriptor->setClient(0); } @@ -133,53 +166,49 @@ bool MediaStream::ended() const return m_stopped || m_descriptor->ended(); } -void MediaStream::addTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState) +void MediaStream::addTrack(PassRefPtrWillBeRawPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState) { if (ended()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "The MediaStream is finished."); return; } if (!prpTrack) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); + exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrack provided is invalid."); return; } - RefPtr<MediaStreamTrack> track = prpTrack; + RefPtrWillBeRawPtr<MediaStreamTrack> track = prpTrack; if (getTrackById(track->id())) return; - RefPtr<MediaStreamComponent> component = MediaStreamComponent::create(m_descriptor.get(), track->component()->source()); - RefPtr<MediaStreamTrack> newTrack = MediaStreamTrack::create(executionContext(), component.get()); - - switch (component->source()->type()) { + switch (track->component()->source()->type()) { case MediaStreamSource::TypeAudio: - m_audioTracks.append(newTrack); + m_audioTracks.append(track); break; case MediaStreamSource::TypeVideo: - m_videoTracks.append(newTrack); + m_videoTracks.append(track); break; } - - m_descriptor->addComponent(component.release()); - - MediaStreamCenter::instance().didAddMediaStreamTrack(m_descriptor.get(), newTrack->component()); + track->registerMediaStream(this); + m_descriptor->addComponent(track->component()); + MediaStreamCenter::instance().didAddMediaStreamTrack(m_descriptor.get(), track->component()); } -void MediaStream::removeTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState) +void MediaStream::removeTrack(PassRefPtrWillBeRawPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState) { if (ended()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwDOMException(InvalidStateError, "The MediaStream is finished."); return; } if (!prpTrack) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); + exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrack provided is invalid."); return; } - RefPtr<MediaStreamTrack> track = prpTrack; + RefPtrWillBeRawPtr<MediaStreamTrack> track = prpTrack; size_t pos = kNotFound; switch (track->component()->source()->type()) { @@ -197,7 +226,7 @@ void MediaStream::removeTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionSt if (pos == kNotFound) return; - + track->unregisterMediaStream(this); m_descriptor->removeComponent(track->component()); if (!m_audioTracks.size() && !m_videoTracks.size()) @@ -210,17 +239,27 @@ MediaStreamTrack* MediaStream::getTrackById(String id) { for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) { if ((*iter)->id() == id) - return (*iter).get(); + return iter->get(); } for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) { if ((*iter)->id() == id) - return (*iter).get(); + return iter->get(); } return 0; } +PassRefPtrWillBeRawPtr<MediaStream> MediaStream::clone(ExecutionContext* context) +{ + MediaStreamTrackVector tracks; + for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) + tracks.append((*iter)->clone(context)); + for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) + tracks.append((*iter)->clone(context)); + return MediaStream::create(context, tracks); +} + void MediaStream::stop() { if (ended()) @@ -233,13 +272,15 @@ void MediaStream::stop() void MediaStream::trackEnded() { - for (size_t i = 0; i < m_audioTracks.size(); ++i) - if (!m_audioTracks[i]->ended()) + for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) { + if (!(*iter)->ended()) return; + } - for (size_t i = 0; i < m_videoTracks.size(); ++i) - if (!m_videoTracks[i]->ended()) + for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) { + if (!(*iter)->ended()) return; + } streamEnded(); } @@ -271,13 +312,11 @@ ExecutionContext* MediaStream::executionContext() const void MediaStream::addRemoteTrack(MediaStreamComponent* component) { - ASSERT(component && !component->stream()); + ASSERT(component); if (ended()) return; - component->setStream(descriptor()); - - RefPtr<MediaStreamTrack> track = MediaStreamTrack::create(executionContext(), component); + RefPtrWillBeRawPtr<MediaStreamTrack> track = MediaStreamTrack::create(executionContext(), component); switch (component->source()->type()) { case MediaStreamSource::TypeAudio: m_audioTracks.append(track); @@ -286,6 +325,7 @@ void MediaStream::addRemoteTrack(MediaStreamComponent* component) m_videoTracks.append(track); break; } + track->registerMediaStream(this); m_descriptor->addComponent(component); scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::addtrack, false, false, track)); @@ -318,17 +358,18 @@ void MediaStream::removeRemoteTrack(MediaStreamComponent* component) m_descriptor->removeComponent(component); - RefPtr<MediaStreamTrack> track = (*tracks)[index]; + RefPtrWillBeRawPtr<MediaStreamTrack> track = (*tracks)[index]; + track->unregisterMediaStream(this); tracks->remove(index); scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::removetrack, false, false, track)); } -void MediaStream::scheduleDispatchEvent(PassRefPtr<Event> event) +void MediaStream::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { m_scheduledEvents.append(event); if (!m_scheduledEventTimer.isActive()) - m_scheduledEventTimer.startOneShot(0); + m_scheduledEventTimer.startOneShot(0, FROM_HERE); } void MediaStream::scheduledEventTimerFired(Timer<MediaStream>*) @@ -336,10 +377,10 @@ void MediaStream::scheduledEventTimerFired(Timer<MediaStream>*) if (m_stopped) return; - Vector<RefPtr<Event> > events; + WillBeHeapVector<RefPtrWillBeMember<Event> > events; events.swap(m_scheduledEvents); - Vector<RefPtr<Event> >::iterator it = events.begin(); + WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin(); for (; it != events.end(); ++it) dispatchEvent((*it).release()); @@ -351,4 +392,12 @@ URLRegistry& MediaStream::registry() const return MediaStreamRegistry::registry(); } +void MediaStream::trace(Visitor* visitor) +{ + visitor->trace(m_audioTracks); + visitor->trace(m_videoTracks); + visitor->trace(m_scheduledEvents); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.h index 867eda65f28..8b0394b7fa3 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.h @@ -28,11 +28,11 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ContextLifecycleObserver.h" -#include "core/events/EventTarget.h" #include "core/html/URLRegistry.h" -#include "core/platform/mediastream/MediaStreamDescriptor.h" +#include "modules/EventTargetModules.h" #include "modules/mediastream/MediaStreamTrack.h" #include "platform/Timer.h" +#include "platform/mediastream/MediaStreamDescriptor.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" @@ -40,13 +40,15 @@ namespace WebCore { class ExceptionState; -class MediaStream : public RefCounted<MediaStream>, public ScriptWrappable, public URLRegistrable, public MediaStreamDescriptorClient, public EventTargetWithInlineData, public ContextLifecycleObserver { +class MediaStream FINAL : public RefCountedWillBeRefCountedGarbageCollected<MediaStream>, public ScriptWrappable, + public URLRegistrable, public MediaStreamDescriptorClient, public EventTargetWithInlineData, public ContextLifecycleObserver { REFCOUNTED_EVENT_TARGET(MediaStream); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaStream); public: - static PassRefPtr<MediaStream> create(ExecutionContext*); - static PassRefPtr<MediaStream> create(ExecutionContext*, PassRefPtr<MediaStream>); - static PassRefPtr<MediaStream> create(ExecutionContext*, const MediaStreamTrackVector&); - static PassRefPtr<MediaStream> create(ExecutionContext*, PassRefPtr<MediaStreamDescriptor>); + static PassRefPtrWillBeRawPtr<MediaStream> create(ExecutionContext*); + static PassRefPtrWillBeRawPtr<MediaStream> create(ExecutionContext*, PassRefPtrWillBeRawPtr<MediaStream>); + static PassRefPtrWillBeRawPtr<MediaStream> create(ExecutionContext*, const MediaStreamTrackVector&); + static PassRefPtrWillBeRawPtr<MediaStream> create(ExecutionContext*, PassRefPtr<MediaStreamDescriptor>); virtual ~MediaStream(); // DEPRECATED @@ -54,9 +56,10 @@ public: String id() const { return m_descriptor->id(); } - void addTrack(PassRefPtr<MediaStreamTrack>, ExceptionState&); - void removeTrack(PassRefPtr<MediaStreamTrack>, ExceptionState&); + void addTrack(PassRefPtrWillBeRawPtr<MediaStreamTrack>, ExceptionState&); + void removeTrack(PassRefPtrWillBeRawPtr<MediaStreamTrack>, ExceptionState&); MediaStreamTrack* getTrackById(String); + PassRefPtrWillBeRawPtr<MediaStream> clone(ExecutionContext*); MediaStreamTrackVector getAudioTracks() const { return m_audioTracks; } MediaStreamTrackVector getVideoTracks() const { return m_videoTracks; } @@ -68,8 +71,9 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(addtrack); DEFINE_ATTRIBUTE_EVENT_LISTENER(removetrack); + void trackEnded(); + // MediaStreamDescriptorClient - virtual void trackEnded() OVERRIDE; virtual void streamEnded() OVERRIDE; MediaStreamDescriptor* descriptor() const { return m_descriptor.get(); } @@ -81,18 +85,20 @@ public: // URLRegistrable virtual URLRegistry& registry() const OVERRIDE; -protected: + virtual void trace(Visitor*) OVERRIDE; + +private: MediaStream(ExecutionContext*, PassRefPtr<MediaStreamDescriptor>); + MediaStream(ExecutionContext*, const MediaStreamTrackVector& audioTracks, const MediaStreamTrackVector& videoTracks); // ContextLifecycleObserver - virtual void contextDestroyed(); + virtual void contextDestroyed() OVERRIDE; -private: // MediaStreamDescriptorClient virtual void addRemoteTrack(MediaStreamComponent*) OVERRIDE; virtual void removeRemoteTrack(MediaStreamComponent*) OVERRIDE; - void scheduleDispatchEvent(PassRefPtr<Event>); + void scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event>); void scheduledEventTimerFired(Timer<MediaStream>*); bool m_stopped; @@ -102,10 +108,10 @@ private: RefPtr<MediaStreamDescriptor> m_descriptor; Timer<MediaStream> m_scheduledEventTimer; - Vector<RefPtr<Event> > m_scheduledEvents; + WillBeHeapVector<RefPtrWillBeMember<Event> > m_scheduledEvents; }; -typedef Vector<RefPtr<MediaStream> > MediaStreamVector; +typedef WillBeHeapVector<RefPtrWillBeMember<MediaStream> > MediaStreamVector; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.idl b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.idl index 8191d0a3285..60a9712d385 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStream.idl @@ -22,7 +22,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-MediaStream + [ + WillBeGarbageCollected, Constructor, Constructor(MediaStream stream), Constructor(MediaStreamTrack[] tracks), @@ -40,6 +43,7 @@ [RaisesException] void addTrack(MediaStreamTrack track); [RaisesException] void removeTrack(MediaStreamTrack track); MediaStreamTrack getTrackById(DOMString trackId); + [CallWith=ExecutionContext] MediaStream clone(); readonly attribute boolean ended; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamEvent.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamEvent.cpp index 0b97418f722..5768f645352 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamEvent.cpp @@ -25,28 +25,26 @@ #include "config.h" #include "modules/mediastream/MediaStreamEvent.h" -#include "core/events/ThreadLocalEventNames.h" - namespace WebCore { MediaStreamEventInit::MediaStreamEventInit() - : stream(0) + : stream(nullptr) { } -PassRefPtr<MediaStreamEvent> MediaStreamEvent::create() +PassRefPtrWillBeRawPtr<MediaStreamEvent> MediaStreamEvent::create() { - return adoptRef(new MediaStreamEvent); + return adoptRefWillBeNoop(new MediaStreamEvent); } -PassRefPtr<MediaStreamEvent> MediaStreamEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<MediaStream> stream) +PassRefPtrWillBeRawPtr<MediaStreamEvent> MediaStreamEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<MediaStream> stream) { - return adoptRef(new MediaStreamEvent(type, canBubble, cancelable, stream)); + return adoptRefWillBeNoop(new MediaStreamEvent(type, canBubble, cancelable, stream)); } -PassRefPtr<MediaStreamEvent> MediaStreamEvent::create(const AtomicString& type, const MediaStreamEventInit& initializer) +PassRefPtrWillBeRawPtr<MediaStreamEvent> MediaStreamEvent::create(const AtomicString& type, const MediaStreamEventInit& initializer) { - return adoptRef(new MediaStreamEvent(type, initializer)); + return adoptRefWillBeNoop(new MediaStreamEvent(type, initializer)); } MediaStreamEvent::MediaStreamEvent() @@ -88,5 +86,10 @@ const AtomicString& MediaStreamEvent::interfaceName() const return EventNames::MediaStreamEvent; } +void MediaStreamEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamEvent.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamEvent.h index 820f3ff33f8..7549eb18022 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamEvent.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamEvent.h @@ -25,7 +25,7 @@ #ifndef MediaStreamEvent_h #define MediaStreamEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "modules/mediastream/MediaStream.h" #include "wtf/text/AtomicString.h" @@ -37,18 +37,20 @@ struct MediaStreamEventInit : public EventInit { RefPtr<MediaStream> stream; }; -class MediaStreamEvent : public Event { +class MediaStreamEvent FINAL : public Event { public: virtual ~MediaStreamEvent(); - static PassRefPtr<MediaStreamEvent> create(); - static PassRefPtr<MediaStreamEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<MediaStream>); - static PassRefPtr<MediaStreamEvent> create(const AtomicString& type, const MediaStreamEventInit& initializer); + static PassRefPtrWillBeRawPtr<MediaStreamEvent> create(); + static PassRefPtrWillBeRawPtr<MediaStreamEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<MediaStream>); + static PassRefPtrWillBeRawPtr<MediaStreamEvent> create(const AtomicString& type, const MediaStreamEventInit& initializer); MediaStream* stream() const; MediaStream* stream(bool&) const; - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: MediaStreamEvent(); diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamRegistry.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamRegistry.cpp index bcc69b6e00d..13f9eb394a8 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamRegistry.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamRegistry.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "modules/mediastream/MediaStreamRegistry.h" +#include "core/html/HTMLMediaElement.h" #include "modules/mediastream/MediaStream.h" #include "platform/weborigin/KURL.h" #include "wtf/MainThread.h" @@ -33,7 +34,7 @@ namespace WebCore { MediaStreamRegistry& MediaStreamRegistry::registry() { - // Since WebWorkers cannot obtain MediaSource objects, we should be on the main thread. + // Since WebWorkers cannot obtain MediaStream objects, we should be on the main thread. ASSERT(isMainThread()); DEFINE_STATIC_LOCAL(MediaStreamRegistry, instance, ()); return instance; @@ -52,10 +53,21 @@ void MediaStreamRegistry::unregisterURL(const KURL& url) m_streamDescriptors.remove(url.string()); } +bool MediaStreamRegistry::contains(const String& url) +{ + ASSERT(isMainThread()); + return m_streamDescriptors.contains(url); +} + MediaStreamDescriptor* MediaStreamRegistry::lookupMediaStreamDescriptor(const String& url) { ASSERT(isMainThread()); return m_streamDescriptors.get(url); } +MediaStreamRegistry::MediaStreamRegistry() +{ + HTMLMediaElement::setMediaStreamRegistry(this); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamRegistry.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamRegistry.h index 84e31b7c4ac..db6278a0b36 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamRegistry.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamRegistry.h @@ -36,7 +36,7 @@ class KURL; class MediaStream; class MediaStreamDescriptor; -class MediaStreamRegistry : public URLRegistry { +class MediaStreamRegistry FINAL : public URLRegistry { public: // Returns a single instance of MediaStreamRegistry. static MediaStreamRegistry& registry(); @@ -44,10 +44,12 @@ public: // Registers a blob URL referring to the specified stream data. virtual void registerURL(SecurityOrigin*, const KURL&, URLRegistrable*) OVERRIDE; virtual void unregisterURL(const KURL&) OVERRIDE; + virtual bool contains(const String&) OVERRIDE; MediaStreamDescriptor* lookupMediaStreamDescriptor(const String& url); private: + MediaStreamRegistry(); HashMap<String, RefPtr<MediaStreamDescriptor> > m_streamDescriptors; }; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp index 6296fe6d2d9..352d7b9e4a7 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp @@ -29,24 +29,26 @@ #include "bindings/v8/ExceptionMessages.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "core/events/Event.h" -#include "core/platform/mediastream/MediaStreamCenter.h" +#include "modules/mediastream/MediaStream.h" #include "modules/mediastream/MediaStreamTrackSourcesCallback.h" -#include "modules/mediastream/MediaStreamTrackSourcesRequest.h" +#include "modules/mediastream/MediaStreamTrackSourcesRequestImpl.h" +#include "platform/mediastream/MediaStreamCenter.h" #include "platform/mediastream/MediaStreamComponent.h" #include "public/platform/WebSourceInfo.h" namespace WebCore { -PassRefPtr<MediaStreamTrack> MediaStreamTrack::create(ExecutionContext* context, MediaStreamComponent* component) +PassRefPtrWillBeRawPtr<MediaStreamTrack> MediaStreamTrack::create(ExecutionContext* context, MediaStreamComponent* component) { - RefPtr<MediaStreamTrack> track = adoptRef(new MediaStreamTrack(context, component)); + RefPtrWillBeRawPtr<MediaStreamTrack> track = adoptRefWillBeRefCountedGarbageCollected(new MediaStreamTrack(context, component)); track->suspendIfNeeded(); return track.release(); } MediaStreamTrack::MediaStreamTrack(ExecutionContext* context, MediaStreamComponent* component) : ActiveDOMObject(context) + , m_readyState(MediaStreamSource::ReadyStateLive) + , m_isIteratingRegisteredMediaStreams(false) , m_stopped(false) , m_component(component) { @@ -92,23 +94,21 @@ bool MediaStreamTrack::enabled() const void MediaStreamTrack::setEnabled(bool enabled) { - if (m_stopped || enabled == m_component->enabled()) + if (enabled == m_component->enabled()) return; m_component->setEnabled(enabled); - if (m_component->stream()->ended()) - return; - - MediaStreamCenter::instance().didSetMediaStreamTrackEnabled(m_component->stream(), m_component.get()); + if (!ended()) + MediaStreamCenter::instance().didSetMediaStreamTrackEnabled(m_component.get()); } String MediaStreamTrack::readyState() const { - if (m_stopped) + if (ended()) return "ended"; - switch (m_component->source()->readyState()) { + switch (m_readyState) { case MediaStreamSource::ReadyStateLive: return "live"; case MediaStreamSource::ReadyStateMuted: @@ -123,7 +123,7 @@ String MediaStreamTrack::readyState() const void MediaStreamTrack::getSources(ExecutionContext* context, PassOwnPtr<MediaStreamTrackSourcesCallback> callback, ExceptionState& exceptionState) { - RefPtr<MediaStreamTrackSourcesRequest> request = MediaStreamTrackSourcesRequest::create(context->securityOrigin()->toString(), callback); + RefPtrWillBeRawPtr<MediaStreamTrackSourcesRequest> request = MediaStreamTrackSourcesRequestImpl::create(context->securityOrigin()->toString(), callback); if (!MediaStreamCenter::instance().getMediaStreamTrackSources(request.release())) exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::failedToExecute("getSources", "MediaStreamTrack", "Functionality not implemented yet")); } @@ -133,21 +133,32 @@ void MediaStreamTrack::stopTrack(ExceptionState& exceptionState) if (ended()) return; - if (!MediaStreamCenter::instance().didStopMediaStreamTrack(component())) - exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::failedToExecute("stop", "MediaStreamTrack", "Functionality not implemented yet")); + m_readyState = MediaStreamSource::ReadyStateEnded; + MediaStreamCenter::instance().didStopMediaStreamTrack(component()); + dispatchEvent(Event::create(EventTypeNames::ended)); + propagateTrackEnded(); +} + +PassRefPtrWillBeRawPtr<MediaStreamTrack> MediaStreamTrack::clone(ExecutionContext* context) +{ + RefPtr<MediaStreamComponent> clonedComponent = MediaStreamComponent::create(component()->source()); + RefPtrWillBeRawPtr<MediaStreamTrack> clonedTrack = MediaStreamTrack::create(context, clonedComponent.get()); + MediaStreamCenter::instance().didCreateMediaStreamTrack(clonedComponent.get()); + return clonedTrack.release(); } bool MediaStreamTrack::ended() const { - return m_stopped || (m_component->source()->readyState() == MediaStreamSource::ReadyStateEnded); + return m_stopped || (m_readyState == MediaStreamSource::ReadyStateEnded); } void MediaStreamTrack::sourceChangedState() { - if (m_stopped) + if (ended()) return; - switch (m_component->source()->readyState()) { + m_readyState = m_component->source()->readyState(); + switch (m_readyState) { case MediaStreamSource::ReadyStateLive: dispatchEvent(Event::create(EventTypeNames::unmute)); break; @@ -156,22 +167,18 @@ void MediaStreamTrack::sourceChangedState() break; case MediaStreamSource::ReadyStateEnded: dispatchEvent(Event::create(EventTypeNames::ended)); - didEndTrack(); + propagateTrackEnded(); break; } } -void MediaStreamTrack::didEndTrack() +void MediaStreamTrack::propagateTrackEnded() { - MediaStreamDescriptor* stream = m_component->stream(); - if (!stream) - return; - - MediaStreamDescriptorClient* client = stream->client(); - if (!client) - return; - - client->trackEnded(); + RELEASE_ASSERT(!m_isIteratingRegisteredMediaStreams); + m_isIteratingRegisteredMediaStreams = true; + for (WillBeHeapHashSet<RawPtrWillBeMember<MediaStream> >::iterator iter = m_registeredMediaStreams.begin(); iter != m_registeredMediaStreams.end(); ++iter) + (*iter)->trackEnded(); + m_isIteratingRegisteredMediaStreams = false; } MediaStreamComponent* MediaStreamTrack::component() @@ -184,6 +191,26 @@ void MediaStreamTrack::stop() m_stopped = true; } +PassOwnPtr<AudioSourceProvider> MediaStreamTrack::createWebAudioSource() +{ + return MediaStreamCenter::instance().createWebAudioSourceFromMediaStreamTrack(component()); +} + +void MediaStreamTrack::registerMediaStream(MediaStream* mediaStream) +{ + RELEASE_ASSERT(!m_isIteratingRegisteredMediaStreams); + RELEASE_ASSERT(!m_registeredMediaStreams.contains(mediaStream)); + m_registeredMediaStreams.add(mediaStream); +} + +void MediaStreamTrack::unregisterMediaStream(MediaStream* mediaStream) +{ + RELEASE_ASSERT(!m_isIteratingRegisteredMediaStreams); + WillBeHeapHashSet<RawPtrWillBeMember<MediaStream> >::iterator iter = m_registeredMediaStreams.find(mediaStream); + RELEASE_ASSERT(iter != m_registeredMediaStreams.end()); + m_registeredMediaStreams.remove(iter); +} + const AtomicString& MediaStreamTrack::interfaceName() const { return EventTargetNames::MediaStreamTrack; @@ -194,4 +221,10 @@ ExecutionContext* MediaStreamTrack::executionContext() const return ActiveDOMObject::executionContext(); } +void MediaStreamTrack::trace(Visitor* visitor) +{ + visitor->trace(m_registeredMediaStreams); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.h index ad59cdebabe..cc2b154cc63 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.h @@ -28,10 +28,11 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" -#include "core/platform/mediastream/MediaStreamDescriptor.h" +#include "modules/EventTargetModules.h" #include "modules/mediastream/SourceInfo.h" +#include "platform/mediastream/MediaStreamDescriptor.h" #include "platform/mediastream/MediaStreamSource.h" +#include "wtf/PassOwnPtr.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/Vector.h" @@ -39,14 +40,16 @@ namespace WebCore { +class AudioSourceProvider; class ExceptionState; class MediaStreamComponent; class MediaStreamTrackSourcesCallback; -class MediaStreamTrack : public RefCounted<MediaStreamTrack>, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData, public MediaStreamSource::Observer { +class MediaStreamTrack FINAL : public RefCountedWillBeRefCountedGarbageCollected<MediaStreamTrack>, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData, public MediaStreamSource::Observer { REFCOUNTED_EVENT_TARGET(MediaStreamTrack); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaStreamTrack); public: - static PassRefPtr<MediaStreamTrack> create(ExecutionContext*, MediaStreamComponent*); + static PassRefPtrWillBeRawPtr<MediaStreamTrack> create(ExecutionContext*, MediaStreamComponent*); virtual ~MediaStreamTrack(); String kind() const; @@ -56,12 +59,11 @@ public: bool enabled() const; void setEnabled(bool); - void didEndTrack(); - String readyState() const; static void getSources(ExecutionContext*, PassOwnPtr<MediaStreamTrackSourcesCallback>, ExceptionState&); void stopTrack(ExceptionState&); + PassRefPtrWillBeRawPtr<MediaStreamTrack> clone(ExecutionContext*); DEFINE_ATTRIBUTE_EVENT_LISTENER(mute); DEFINE_ATTRIBUTE_EVENT_LISTENER(unmute); @@ -70,6 +72,9 @@ public: MediaStreamComponent* component(); bool ended() const; + void registerMediaStream(MediaStream*); + void unregisterMediaStream(MediaStream*); + // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE; @@ -77,17 +82,27 @@ public: // ActiveDOMObject virtual void stop() OVERRIDE; + PassOwnPtr<AudioSourceProvider> createWebAudioSource(); + + virtual void trace(Visitor*) OVERRIDE; + private: MediaStreamTrack(ExecutionContext*, MediaStreamComponent*); + MediaStreamSource::ReadyState m_readyState; + // MediaStreamSourceObserver virtual void sourceChangedState() OVERRIDE; + void propagateTrackEnded(); + WillBeHeapHashSet<RawPtrWillBeMember<MediaStream> > m_registeredMediaStreams; + bool m_isIteratingRegisteredMediaStreams; + bool m_stopped; RefPtr<MediaStreamComponent> m_component; }; -typedef Vector<RefPtr<MediaStreamTrack> > MediaStreamTrackVector; +typedef WillBeHeapVector<RefPtrWillBeMember<MediaStreamTrack> > MediaStreamTrackVector; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.idl b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.idl index 409d17b32d5..7249c0c4446 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.idl @@ -23,6 +23,7 @@ */ [ + WillBeGarbageCollected, ActiveDOMObject ] interface MediaStreamTrack : EventTarget { readonly attribute DOMString kind; @@ -33,6 +34,7 @@ [CallWith=ExecutionContext, RaisesException] static void getSources(MediaStreamTrackSourcesCallback callback); [ImplementedAs=stopTrack, RaisesException] void stop(); + [CallWith=ExecutionContext] MediaStreamTrack clone(); attribute EventHandler onmute; attribute EventHandler onunmute; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackEvent.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackEvent.cpp index 0a9b65f9e28..4f7eb7af32d 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackEvent.cpp @@ -25,19 +25,18 @@ #include "config.h" #include "modules/mediastream/MediaStreamTrackEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "modules/mediastream/MediaStreamTrack.h" namespace WebCore { -PassRefPtr<MediaStreamTrackEvent> MediaStreamTrackEvent::create() +PassRefPtrWillBeRawPtr<MediaStreamTrackEvent> MediaStreamTrackEvent::create() { - return adoptRef(new MediaStreamTrackEvent); + return adoptRefWillBeNoop(new MediaStreamTrackEvent); } -PassRefPtr<MediaStreamTrackEvent> MediaStreamTrackEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<MediaStreamTrack> track) +PassRefPtrWillBeRawPtr<MediaStreamTrackEvent> MediaStreamTrackEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<MediaStreamTrack> track) { - return adoptRef(new MediaStreamTrackEvent(type, canBubble, cancelable, track)); + return adoptRefWillBeNoop(new MediaStreamTrackEvent(type, canBubble, cancelable, track)); } @@ -46,7 +45,7 @@ MediaStreamTrackEvent::MediaStreamTrackEvent() ScriptWrappable::init(this); } -MediaStreamTrackEvent::MediaStreamTrackEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<MediaStreamTrack> track) +MediaStreamTrackEvent::MediaStreamTrackEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<MediaStreamTrack> track) : Event(type, canBubble, cancelable) , m_track(track) { @@ -67,5 +66,10 @@ const AtomicString& MediaStreamTrackEvent::interfaceName() const return EventNames::MediaStreamTrackEvent; } -} // namespace WebCore +void MediaStreamTrackEvent::trace(Visitor* visitor) +{ + visitor->trace(m_track); + Event::trace(visitor); +} +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackEvent.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackEvent.h index 6398bebadf9..068809d189d 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackEvent.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackEvent.h @@ -25,30 +25,32 @@ #ifndef MediaStreamTrackEvent_h #define MediaStreamTrackEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "wtf/text/AtomicString.h" namespace WebCore { class MediaStreamTrack; -class MediaStreamTrackEvent : public Event { +class MediaStreamTrackEvent FINAL : public Event { public: virtual ~MediaStreamTrackEvent(); - static PassRefPtr<MediaStreamTrackEvent> create(); - static PassRefPtr<MediaStreamTrackEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<MediaStreamTrack>); + static PassRefPtrWillBeRawPtr<MediaStreamTrackEvent> create(); + static PassRefPtrWillBeRawPtr<MediaStreamTrackEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<MediaStreamTrack>); MediaStreamTrack* track() const; // Event virtual const AtomicString& interfaceName() const OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: MediaStreamTrackEvent(); - MediaStreamTrackEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<MediaStreamTrack>); + MediaStreamTrackEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<MediaStreamTrack>); - RefPtr<MediaStreamTrack> m_track; + RefPtrWillBeMember<MediaStreamTrack> m_track; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackSourcesRequest.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackSourcesRequestImpl.cpp index a0860efa0f2..ec434134ee2 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackSourcesRequest.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackSourcesRequestImpl.cpp @@ -25,7 +25,7 @@ #include "config.h" -#include "modules/mediastream/MediaStreamTrackSourcesRequest.h" +#include "modules/mediastream/MediaStreamTrackSourcesRequestImpl.h" #include "modules/mediastream/MediaStreamTrackSourcesCallback.h" #include "platform/weborigin/SecurityOrigin.h" @@ -34,23 +34,23 @@ namespace WebCore { -PassRefPtr<MediaStreamTrackSourcesRequest> MediaStreamTrackSourcesRequest::create(const String& origin, PassOwnPtr<MediaStreamTrackSourcesCallback> callback) +PassRefPtrWillBeRawPtr<MediaStreamTrackSourcesRequestImpl> MediaStreamTrackSourcesRequestImpl::create(const String& origin, PassOwnPtr<MediaStreamTrackSourcesCallback> callback) { - return adoptRef(new MediaStreamTrackSourcesRequest(origin, callback)); + return adoptRefWillBeNoop(new MediaStreamTrackSourcesRequestImpl(origin, callback)); } -MediaStreamTrackSourcesRequest::MediaStreamTrackSourcesRequest(const String& origin, PassOwnPtr<MediaStreamTrackSourcesCallback> callback) +MediaStreamTrackSourcesRequestImpl::MediaStreamTrackSourcesRequestImpl(const String& origin, PassOwnPtr<MediaStreamTrackSourcesCallback> callback) : m_callback(callback) - , m_scheduledEventTimer(this, &MediaStreamTrackSourcesRequest::scheduledEventTimerFired) + , m_scheduledEventTimer(this, &MediaStreamTrackSourcesRequestImpl::scheduledEventTimerFired) { m_origin = origin; } -MediaStreamTrackSourcesRequest::~MediaStreamTrackSourcesRequest() +MediaStreamTrackSourcesRequestImpl::~MediaStreamTrackSourcesRequestImpl() { } -void MediaStreamTrackSourcesRequest::requestSucceeded(const blink::WebVector<blink::WebSourceInfo>& webSourceInfos) +void MediaStreamTrackSourcesRequestImpl::requestSucceeded(const blink::WebVector<blink::WebSourceInfo>& webSourceInfos) { ASSERT(m_callback && !m_scheduledEventTimer.isActive()); @@ -58,14 +58,21 @@ void MediaStreamTrackSourcesRequest::requestSucceeded(const blink::WebVector<bli m_sourceInfos.append(SourceInfo::create(webSourceInfos[i])); m_protect = this; - m_scheduledEventTimer.startOneShot(0); + m_scheduledEventTimer.startOneShot(0, FROM_HERE); } -void MediaStreamTrackSourcesRequest::scheduledEventTimerFired(Timer<MediaStreamTrackSourcesRequest>*) +void MediaStreamTrackSourcesRequestImpl::scheduledEventTimerFired(Timer<MediaStreamTrackSourcesRequestImpl>*) { m_callback->handleEvent(m_sourceInfos); m_callback.clear(); m_protect.release(); } +void MediaStreamTrackSourcesRequestImpl::trace(Visitor* visitor) +{ + visitor->trace(m_sourceInfos); + visitor->trace(m_protect); + MediaStreamTrackSourcesRequest::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackSourcesRequest.h b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackSourcesRequestImpl.h index 03ede8b4323..3aa6584c009 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackSourcesRequest.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/MediaStreamTrackSourcesRequestImpl.h @@ -23,15 +23,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MediaStreamTrackSourcesRequest_h -#define MediaStreamTrackSourcesRequest_h +#ifndef MediaStreamTrackSourcesRequestImpl_h +#define MediaStreamTrackSourcesRequestImpl_h #include "modules/mediastream/SourceInfo.h" #include "platform/Timer.h" +#include "platform/mediastream/MediaStreamTrackSourcesRequest.h" #include "public/platform/WebVector.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" namespace blink { @@ -42,36 +41,28 @@ namespace WebCore { class MediaStreamTrackSourcesCallback; -class MediaStreamTrackSourcesRequest FINAL : public RefCounted<MediaStreamTrackSourcesRequest> { +class MediaStreamTrackSourcesRequestImpl FINAL : public MediaStreamTrackSourcesRequest { public: - class ExtraData : public RefCounted<ExtraData> { - public: - virtual ~ExtraData() { } - }; + static PassRefPtrWillBeRawPtr<MediaStreamTrackSourcesRequestImpl> create(const String&, PassOwnPtr<MediaStreamTrackSourcesCallback>); + ~MediaStreamTrackSourcesRequestImpl(); - static PassRefPtr<MediaStreamTrackSourcesRequest> create(const String&, PassOwnPtr<MediaStreamTrackSourcesCallback>); - ~MediaStreamTrackSourcesRequest(); + virtual String origin() { return m_origin; } + virtual void requestSucceeded(const blink::WebVector<blink::WebSourceInfo>&); - String origin() { return m_origin; } - - void requestSucceeded(const blink::WebVector<blink::WebSourceInfo>&); - - PassRefPtr<ExtraData> extraData() const { return m_extraData; } - void setExtraData(PassRefPtr<ExtraData> extraData) { m_extraData = extraData; } + virtual void trace(Visitor*) OVERRIDE; private: - MediaStreamTrackSourcesRequest(const String&, PassOwnPtr<MediaStreamTrackSourcesCallback>); + MediaStreamTrackSourcesRequestImpl(const String&, PassOwnPtr<MediaStreamTrackSourcesCallback>); - void scheduledEventTimerFired(Timer<MediaStreamTrackSourcesRequest>*); + void scheduledEventTimerFired(Timer<MediaStreamTrackSourcesRequestImpl>*); OwnPtr<MediaStreamTrackSourcesCallback> m_callback; - RefPtr<ExtraData> m_extraData; String m_origin; - Timer<MediaStreamTrackSourcesRequest> m_scheduledEventTimer; + Timer<MediaStreamTrackSourcesRequestImpl> m_scheduledEventTimer; SourceInfoVector m_sourceInfos; - RefPtr<MediaStreamTrackSourcesRequest> m_protect; + RefPtrWillBeMember<MediaStreamTrackSourcesRequest> m_protect; }; } // namespace WebCore -#endif // MediaStreamTrackSourcesRequest_h +#endif // MediaStreamTrackSourcesRequestImpl_h diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.cpp index a5e3d4b7c54..e8b5c39555d 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.cpp @@ -27,9 +27,11 @@ #include "bindings/v8/ExceptionState.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" #include "core/page/Page.h" +#include "modules/mediastream/MediaDeviceInfoCallback.h" +#include "modules/mediastream/MediaDevicesRequest.h" #include "modules/mediastream/NavigatorUserMediaErrorCallback.h" #include "modules/mediastream/NavigatorUserMediaSuccessCallback.h" #include "modules/mediastream/UserMediaController.h" @@ -45,20 +47,38 @@ NavigatorMediaStream::~NavigatorMediaStream() { } -void NavigatorMediaStream::webkitGetUserMedia(Navigator* navigator, const Dictionary& options, PassOwnPtr<NavigatorUserMediaSuccessCallback> successCallback, PassOwnPtr<NavigatorUserMediaErrorCallback> errorCallback, ExceptionState& exceptionState) +void NavigatorMediaStream::webkitGetUserMedia(Navigator& navigator, const Dictionary& options, PassOwnPtr<NavigatorUserMediaSuccessCallback> successCallback, PassOwnPtr<NavigatorUserMediaErrorCallback> errorCallback, ExceptionState& exceptionState) { if (!successCallback) return; - UserMediaController* userMedia = UserMediaController::from(navigator->frame() ? navigator->frame()->page() : 0); + UserMediaController* userMedia = UserMediaController::from(navigator.frame()); if (!userMedia) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + exceptionState.throwDOMException(NotSupportedError, "No user media controller available; is this a detached window?"); return; } - RefPtr<UserMediaRequest> request = UserMediaRequest::create(navigator->frame()->document(), userMedia, options, successCallback, errorCallback, exceptionState); + RefPtrWillBeRawPtr<UserMediaRequest> request = UserMediaRequest::create(navigator.frame()->document(), userMedia, options, successCallback, errorCallback, exceptionState); if (!request) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + ASSERT(exceptionState.hadException()); + return; + } + + request->start(); +} + +void NavigatorMediaStream::getMediaDevices(Navigator& navigator, PassOwnPtr<MediaDeviceInfoCallback> callback, ExceptionState& exceptionState) +{ + UserMediaController* userMedia = UserMediaController::from(navigator.frame()); + if (!userMedia) { + exceptionState.throwDOMException(NotSupportedError, "No media device controller available; is this a detached window?"); + return; + } + + RefPtrWillBeRawPtr<MediaDevicesRequest> request = MediaDevicesRequest::create(navigator.frame()->document(), userMedia, callback, exceptionState); + if (!request) { + if (!exceptionState.hadException()) + exceptionState.throwDOMException(NotSupportedError, "Failed to request media devices."); return; } diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.h b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.h index b27753fdb77..c3ee4c654d6 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.h @@ -27,13 +27,16 @@ namespace WebCore { class Dictionary; class ExceptionState; +class MediaDeviceInfoCallback; class Navigator; class NavigatorUserMediaErrorCallback; class NavigatorUserMediaSuccessCallback; class NavigatorMediaStream { public: - static void webkitGetUserMedia(Navigator*, const Dictionary&, PassOwnPtr<NavigatorUserMediaSuccessCallback>, PassOwnPtr<NavigatorUserMediaErrorCallback>, ExceptionState&); + static void webkitGetUserMedia(Navigator&, const Dictionary&, PassOwnPtr<NavigatorUserMediaSuccessCallback>, PassOwnPtr<NavigatorUserMediaErrorCallback>, ExceptionState&); + + static void getMediaDevices(Navigator&, PassOwnPtr<MediaDeviceInfoCallback>, ExceptionState&); private: NavigatorMediaStream(); diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.idl b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.idl index 2f72684d36f..cef019a9eb5 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.idl @@ -17,9 +17,10 @@ * Boston, MA 02110-1301, USA. */ -partial interface Navigator { - [RuntimeEnabled=MediaStream, RaisesException] void webkitGetUserMedia(Dictionary options, - NavigatorUserMediaSuccessCallback successCallback, - optional NavigatorUserMediaErrorCallback errorCallback); +[ + RuntimeEnabled=MediaStream, +] partial interface Navigator { + [RaisesException] void webkitGetUserMedia(Dictionary options, + NavigatorUserMediaSuccessCallback successCallback, + NavigatorUserMediaErrorCallback errorCallback); }; - diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.cpp index e9cef28d55f..6c27428ef64 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.cpp @@ -33,18 +33,20 @@ namespace WebCore { -String NavigatorUserMediaError::name() const +PassRefPtrWillBeRawPtr<NavigatorUserMediaError> NavigatorUserMediaError::create(Name name, const String& message, const String& constraintName) { - switch (m_name) { + String nameString; + switch (name) { case NamePermissionDenied: - return "PermissionDeniedError"; + nameString = "PermissionDeniedError"; + break; case NameConstraintNotSatisfied: - return "ConstraintNotSatisfiedError"; + nameString = "ConstraintNotSatisfiedError"; + break; } - ASSERT_NOT_REACHED(); - return String(); + return adoptRefWillBeNoop(new NavigatorUserMediaError(nameString, message, constraintName)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.h b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.h index 928aa90fa48..24b4a2c0c8c 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.h @@ -32,30 +32,35 @@ namespace WebCore { -class NavigatorUserMediaError FINAL : public RefCounted<NavigatorUserMediaError>, public ScriptWrappable { +class NavigatorUserMediaError FINAL : public RefCountedWillBeGarbageCollectedFinalized<NavigatorUserMediaError>, public ScriptWrappable { public: enum Name { NamePermissionDenied, NameConstraintNotSatisfied }; - static PassRefPtr<NavigatorUserMediaError> create(Name name, const String& message, const String& constraintName) + static PassRefPtrWillBeRawPtr<NavigatorUserMediaError> create(Name, const String& message, const String& constraintName); + + static PassRefPtrWillBeRawPtr<NavigatorUserMediaError> create(const String& name, const String& message, const String& constraintName) { - return adoptRef(new NavigatorUserMediaError(name, message, constraintName)); + return adoptRefWillBeNoop(new NavigatorUserMediaError(name, message, constraintName)); } - String name() const; + String name() const { return m_name; } const String& message() const { return m_message; } const String& constraintName() const { return m_constraintName; } + void trace(Visitor*) { } + private: - NavigatorUserMediaError(Name name, const String& message, const String& constraintName) + NavigatorUserMediaError(const String& name, const String& message, const String& constraintName) : m_name(name), m_message(message), m_constraintName(constraintName) { + ASSERT(!name.isEmpty()); ScriptWrappable::init(this); } - Name m_name; + String m_name; String m_message; String m_constraintName; }; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.idl b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.idl index dd32480c376..e068867a39b 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/NavigatorUserMediaError.idl @@ -23,6 +23,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface NavigatorUserMediaError { readonly attribute DOMString name; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/OWNERS b/chromium/third_party/WebKit/Source/modules/mediastream/OWNERS index e09540c3c6c..4e4fd11cdad 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/mediastream/OWNERS @@ -1 +1,2 @@ +tommi@chromium.org tommyw@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.cpp index 2d51192f26d..14bbf373c8c 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.cpp @@ -26,13 +26,15 @@ #include "config.h" #include "modules/mediastream/RTCDTMFSender.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "core/platform/mediastream/RTCPeerConnectionHandler.h" #include "modules/mediastream/MediaStreamTrack.h" #include "modules/mediastream/RTCDTMFToneChangeEvent.h" -#include "platform/mediastream/RTCDTMFSenderHandler.h" +#include "public/platform/WebMediaStreamTrack.h" +#include "public/platform/WebRTCDTMFSenderHandler.h" +#include "public/platform/WebRTCPeerConnectionHandler.h" namespace WebCore { @@ -42,21 +44,21 @@ static const long maxToneDurationMs = 6000; static const long minInterToneGapMs = 50; static const long defaultInterToneGapMs = 50; -PassRefPtr<RTCDTMFSender> RTCDTMFSender::create(ExecutionContext* context, RTCPeerConnectionHandler* peerConnectionHandler, PassRefPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCDTMFSender> RTCDTMFSender::create(ExecutionContext* context, blink::WebRTCPeerConnectionHandler* peerConnectionHandler, PassRefPtrWillBeRawPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState) { - RefPtr<MediaStreamTrack> track = prpTrack; - OwnPtr<RTCDTMFSenderHandler> handler = peerConnectionHandler->createDTMFSender(track->component()); + RefPtrWillBeRawPtr<MediaStreamTrack> track = prpTrack; + OwnPtr<blink::WebRTCDTMFSenderHandler> handler = adoptPtr(peerConnectionHandler->createDTMFSender(track->component())); if (!handler) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; + exceptionState.throwDOMException(NotSupportedError, "The MediaStreamTrack provided is not an element of a MediaStream that's currently in the local streams set."); + return nullptr; } - RefPtr<RTCDTMFSender> dtmfSender = adoptRef(new RTCDTMFSender(context, track, handler.release())); + RefPtrWillBeRawPtr<RTCDTMFSender> dtmfSender = adoptRefWillBeRefCountedGarbageCollected(new RTCDTMFSender(context, track, handler.release())); dtmfSender->suspendIfNeeded(); return dtmfSender.release(); } -RTCDTMFSender::RTCDTMFSender(ExecutionContext* context, PassRefPtr<MediaStreamTrack> track, PassOwnPtr<RTCDTMFSenderHandler> handler) +RTCDTMFSender::RTCDTMFSender(ExecutionContext* context, PassRefPtrWillBeRawPtr<MediaStreamTrack> track, PassOwnPtr<blink::WebRTCDTMFSenderHandler> handler) : ActiveDOMObject(context) , m_track(track) , m_duration(defaultToneDurationMs) @@ -101,17 +103,17 @@ void RTCDTMFSender::insertDTMF(const String& tones, long duration, ExceptionStat void RTCDTMFSender::insertDTMF(const String& tones, long duration, long interToneGap, ExceptionState& exceptionState) { if (!canInsertDTMF()) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + exceptionState.throwDOMException(NotSupportedError, "The 'canInsertDTMF' attribute is false: this sender cannot send DTMF."); return; } if (duration > maxToneDurationMs || duration < minToneDurationMs) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, ExceptionMessages::indexOutsideRange("duration", duration, minToneDurationMs, ExceptionMessages::ExclusiveBound, maxToneDurationMs, ExceptionMessages::ExclusiveBound)); return; } if (interToneGap < minInterToneGapMs) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, ExceptionMessages::indexExceedsMinimumBound("intertone gap", interToneGap, minInterToneGapMs)); return; } @@ -119,10 +121,10 @@ void RTCDTMFSender::insertDTMF(const String& tones, long duration, long interTon m_interToneGap = interToneGap; if (!m_handler->insertDTMF(tones, m_duration, m_interToneGap)) - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "Could not send provided tones, '" + tones + "'."); } -void RTCDTMFSender::didPlayTone(const String& tone) +void RTCDTMFSender::didPlayTone(const blink::WebString& tone) { scheduleDispatchEvent(RTCDTMFToneChangeEvent::create(tone)); } @@ -143,12 +145,12 @@ void RTCDTMFSender::stop() m_handler->setClient(0); } -void RTCDTMFSender::scheduleDispatchEvent(PassRefPtr<Event> event) +void RTCDTMFSender::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { m_scheduledEvents.append(event); if (!m_scheduledEventTimer.isActive()) - m_scheduledEventTimer.startOneShot(0); + m_scheduledEventTimer.startOneShot(0, FROM_HERE); } void RTCDTMFSender::scheduledEventTimerFired(Timer<RTCDTMFSender>*) @@ -156,12 +158,19 @@ void RTCDTMFSender::scheduledEventTimerFired(Timer<RTCDTMFSender>*) if (m_stopped) return; - Vector<RefPtr<Event> > events; + WillBeHeapVector<RefPtrWillBeMember<Event> > events; events.swap(m_scheduledEvents); - Vector<RefPtr<Event> >::iterator it = events.begin(); + WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin(); for (; it != events.end(); ++it) dispatchEvent((*it).release()); } +void RTCDTMFSender::trace(Visitor* visitor) +{ + visitor->trace(m_track); + visitor->trace(m_scheduledEvents); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.h index 75240fbb1e4..c5254267245 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.h @@ -28,23 +28,27 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" #include "platform/Timer.h" -#include "platform/mediastream/RTCDTMFSenderHandlerClient.h" +#include "public/platform/WebRTCDTMFSenderHandlerClient.h" #include "wtf/RefCounted.h" +namespace blink { +class WebRTCDTMFSenderHandler; +class WebRTCPeerConnectionHandler; +} + namespace WebCore { class ExceptionState; class MediaStreamTrack; -class RTCDTMFSenderHandler; -class RTCPeerConnectionHandler; -class RTCDTMFSender : public RefCounted<RTCDTMFSender>, public ScriptWrappable, public EventTargetWithInlineData, public RTCDTMFSenderHandlerClient, public ActiveDOMObject { +class RTCDTMFSender FINAL : public RefCountedWillBeRefCountedGarbageCollected<RTCDTMFSender>, public ScriptWrappable, public EventTargetWithInlineData, public blink::WebRTCDTMFSenderHandlerClient, public ActiveDOMObject { REFCOUNTED_EVENT_TARGET(RTCDTMFSender); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(RTCDTMFSender); public: - static PassRefPtr<RTCDTMFSender> create(ExecutionContext*, RTCPeerConnectionHandler*, PassRefPtr<MediaStreamTrack>, ExceptionState&); - ~RTCDTMFSender(); + static PassRefPtrWillBeRawPtr<RTCDTMFSender> create(ExecutionContext*, blink::WebRTCPeerConnectionHandler*, PassRefPtrWillBeRawPtr<MediaStreamTrack>, ExceptionState&); + virtual ~RTCDTMFSender(); bool canInsertDTMF() const; MediaStreamTrack* track() const; @@ -65,25 +69,27 @@ public: // ActiveDOMObject virtual void stop() OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: - RTCDTMFSender(ExecutionContext*, PassRefPtr<MediaStreamTrack>, PassOwnPtr<RTCDTMFSenderHandler>); + RTCDTMFSender(ExecutionContext*, PassRefPtrWillBeRawPtr<MediaStreamTrack>, PassOwnPtr<blink::WebRTCDTMFSenderHandler>); - void scheduleDispatchEvent(PassRefPtr<Event>); + void scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event>); void scheduledEventTimerFired(Timer<RTCDTMFSender>*); - // RTCDTMFSenderHandlerClient - virtual void didPlayTone(const String&) OVERRIDE; + // blink::WebRTCDTMFSenderHandlerClient + virtual void didPlayTone(const blink::WebString&) OVERRIDE; - RefPtr<MediaStreamTrack> m_track; + RefPtrWillBeMember<MediaStreamTrack> m_track; long m_duration; long m_interToneGap; - OwnPtr<RTCDTMFSenderHandler> m_handler; + OwnPtr<blink::WebRTCDTMFSenderHandler> m_handler; bool m_stopped; Timer<RTCDTMFSender> m_scheduledEventTimer; - Vector<RefPtr<Event> > m_scheduledEvents; + WillBeHeapVector<RefPtrWillBeMember<Event> > m_scheduledEvents; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.idl b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.idl index 375a6a5d701..1acdc57a040 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFSender.idl @@ -24,6 +24,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject, ActiveDOMObject ] interface RTCDTMFSender : EventTarget { diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFToneChangeEvent.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFToneChangeEvent.cpp index 57e55a6dfc5..942ea8339b4 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFToneChangeEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFToneChangeEvent.cpp @@ -26,24 +26,22 @@ #include "config.h" #include "modules/mediastream/RTCDTMFToneChangeEvent.h" -#include "core/events/ThreadLocalEventNames.h" - namespace WebCore { -PassRefPtr<RTCDTMFToneChangeEvent> RTCDTMFToneChangeEvent::create() +PassRefPtrWillBeRawPtr<RTCDTMFToneChangeEvent> RTCDTMFToneChangeEvent::create() { - return adoptRef(new RTCDTMFToneChangeEvent); + return adoptRefWillBeNoop(new RTCDTMFToneChangeEvent); } -PassRefPtr<RTCDTMFToneChangeEvent> RTCDTMFToneChangeEvent::create(const String& tone) +PassRefPtrWillBeRawPtr<RTCDTMFToneChangeEvent> RTCDTMFToneChangeEvent::create(const String& tone) { - return adoptRef(new RTCDTMFToneChangeEvent(tone)); + return adoptRefWillBeNoop(new RTCDTMFToneChangeEvent(tone)); } -PassRefPtr<RTCDTMFToneChangeEvent> RTCDTMFToneChangeEvent::create(const AtomicString& type, const RTCDTMFToneChangeEventInit& initializer) +PassRefPtrWillBeRawPtr<RTCDTMFToneChangeEvent> RTCDTMFToneChangeEvent::create(const AtomicString& type, const RTCDTMFToneChangeEventInit& initializer) { ASSERT(type == EventTypeNames::tonechange); - return adoptRef(new RTCDTMFToneChangeEvent(initializer)); + return adoptRefWillBeNoop(new RTCDTMFToneChangeEvent(initializer)); } RTCDTMFToneChangeEvent::RTCDTMFToneChangeEvent() @@ -79,5 +77,10 @@ const AtomicString& RTCDTMFToneChangeEvent::interfaceName() const return EventNames::RTCDTMFToneChangeEvent; } +void RTCDTMFToneChangeEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFToneChangeEvent.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFToneChangeEvent.h index 346aae59526..670f45b0efc 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFToneChangeEvent.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDTMFToneChangeEvent.h @@ -26,7 +26,7 @@ #ifndef RTCDTMFToneChangeEvent_h #define RTCDTMFToneChangeEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "wtf/text/AtomicString.h" namespace WebCore { @@ -35,17 +35,19 @@ struct RTCDTMFToneChangeEventInit : public EventInit { String tone; }; -class RTCDTMFToneChangeEvent : public Event { +class RTCDTMFToneChangeEvent FINAL : public Event { public: virtual ~RTCDTMFToneChangeEvent(); - static PassRefPtr<RTCDTMFToneChangeEvent> create(); - static PassRefPtr<RTCDTMFToneChangeEvent> create(const String& tone); - static PassRefPtr<RTCDTMFToneChangeEvent> create(const AtomicString& type, const RTCDTMFToneChangeEventInit& initializer); + static PassRefPtrWillBeRawPtr<RTCDTMFToneChangeEvent> create(); + static PassRefPtrWillBeRawPtr<RTCDTMFToneChangeEvent> create(const String& tone); + static PassRefPtrWillBeRawPtr<RTCDTMFToneChangeEvent> create(const AtomicString& type, const RTCDTMFToneChangeEventInit& initializer); const String& tone() const; - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: RTCDTMFToneChangeEvent(); diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.cpp index e34915a8e06..90d3acf9f23 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.cpp @@ -26,13 +26,11 @@ #include "modules/mediastream/RTCDataChannel.h" #include "bindings/v8/ExceptionState.h" -#include "core/events/Event.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" #include "core/events/MessageEvent.h" #include "core/fileapi/Blob.h" -#include "core/platform/mediastream/RTCDataChannelHandler.h" -#include "core/platform/mediastream/RTCPeerConnectionHandler.h" +#include "public/platform/WebRTCPeerConnectionHandler.h" #include "wtf/ArrayBuffer.h" #include "wtf/ArrayBufferView.h" @@ -53,29 +51,32 @@ static void throwNoBlobSupportException(ExceptionState& exceptionState) exceptionState.throwDOMException(NotSupportedError, "Blob support not implemented yet"); } -PassRefPtr<RTCDataChannel> RTCDataChannel::create(ExecutionContext* context, PassOwnPtr<RTCDataChannelHandler> handler) +PassRefPtrWillBeRawPtr<RTCDataChannel> RTCDataChannel::create(ExecutionContext* context, RTCPeerConnection* connection, PassOwnPtr<blink::WebRTCDataChannelHandler> handler) { ASSERT(handler); - return adoptRef(new RTCDataChannel(context, handler)); + return adoptRefWillBeRefCountedGarbageCollected(new RTCDataChannel(context, connection, handler)); } -PassRefPtr<RTCDataChannel> RTCDataChannel::create(ExecutionContext* context, RTCPeerConnectionHandler* peerConnectionHandler, const String& label, const blink::WebRTCDataChannelInit& init, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCDataChannel> RTCDataChannel::create(ExecutionContext* context, RTCPeerConnection* connection, blink::WebRTCPeerConnectionHandler* peerConnectionHandler, const String& label, const blink::WebRTCDataChannelInit& init, ExceptionState& exceptionState) { - OwnPtr<RTCDataChannelHandler> handler = peerConnectionHandler->createDataChannel(label, init); + OwnPtr<blink::WebRTCDataChannelHandler> handler = adoptPtr(peerConnectionHandler->createDataChannel(label, init)); if (!handler) { exceptionState.throwDOMException(NotSupportedError, "RTCDataChannel is not supported"); - return 0; + return nullptr; } - return adoptRef(new RTCDataChannel(context, handler.release())); + return adoptRefWillBeRefCountedGarbageCollected(new RTCDataChannel(context, connection, handler.release())); } -RTCDataChannel::RTCDataChannel(ExecutionContext* context, PassOwnPtr<RTCDataChannelHandler> handler) +RTCDataChannel::RTCDataChannel(ExecutionContext* context, RTCPeerConnection* connection, PassOwnPtr<blink::WebRTCDataChannelHandler> handler) : m_executionContext(context) , m_handler(handler) , m_stopped(false) , m_readyState(ReadyStateConnecting) , m_binaryType(BinaryTypeArrayBuffer) , m_scheduledEventTimer(this, &RTCDataChannel::scheduledEventTimerFired) +#if ENABLE(OILPAN) + , m_connection(connection) +#endif { ScriptWrappable::init(this); m_handler->setClient(this); @@ -83,6 +84,15 @@ RTCDataChannel::RTCDataChannel(ExecutionContext* context, PassOwnPtr<RTCDataChan RTCDataChannel::~RTCDataChannel() { +#if ENABLE(OILPAN) + // If the peer connection and the data channel die in the same + // GC cycle stop has not been called and we need to notify the + // client that the channel is gone. + if (!m_stopped) + m_handler->setClient(0); +#else + ASSERT(m_stopped); +#endif } String RTCDataChannel::label() const @@ -194,9 +204,7 @@ void RTCDataChannel::send(PassRefPtr<ArrayBuffer> prpData, ExceptionState& excep if (!dataLength) return; - const char* dataPointer = static_cast<const char*>(data->data()); - - if (!m_handler->sendRawData(dataPointer, dataLength)) { + if (!m_handler->sendRawData(static_cast<const char*>((data->data())), dataLength)) { // FIXME: This should not throw an exception but instead forcefully close the data channel. throwCouldNotSendDataException(exceptionState); } @@ -204,11 +212,13 @@ void RTCDataChannel::send(PassRefPtr<ArrayBuffer> prpData, ExceptionState& excep void RTCDataChannel::send(PassRefPtr<ArrayBufferView> data, ExceptionState& exceptionState) { - RefPtr<ArrayBuffer> arrayBuffer(data->buffer()); - send(arrayBuffer.release(), exceptionState); + if (!m_handler->sendRawData(static_cast<const char*>(data->baseAddress()), data->byteLength())) { + // FIXME: This should not throw an exception but instead forcefully close the data channel. + throwCouldNotSendDataException(exceptionState); + } } -void RTCDataChannel::send(PassRefPtr<Blob> data, ExceptionState& exceptionState) +void RTCDataChannel::send(PassRefPtrWillBeRawPtr<Blob> data, ExceptionState& exceptionState) { // FIXME: implement throwNoBlobSupportException(exceptionState); @@ -222,7 +232,7 @@ void RTCDataChannel::close() m_handler->close(); } -void RTCDataChannel::didChangeReadyState(ReadyState newState) +void RTCDataChannel::didChangeReadyState(blink::WebRTCDataChannelHandlerClient::ReadyState newState) { if (m_stopped || m_readyState == ReadyStateClosed) return; @@ -241,7 +251,7 @@ void RTCDataChannel::didChangeReadyState(ReadyState newState) } } -void RTCDataChannel::didReceiveStringData(const String& text) +void RTCDataChannel::didReceiveStringData(const blink::WebString& text) { if (m_stopped) return; @@ -292,12 +302,12 @@ void RTCDataChannel::stop() m_executionContext = 0; } -void RTCDataChannel::scheduleDispatchEvent(PassRefPtr<Event> event) +void RTCDataChannel::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { m_scheduledEvents.append(event); if (!m_scheduledEventTimer.isActive()) - m_scheduledEventTimer.startOneShot(0); + m_scheduledEventTimer.startOneShot(0, FROM_HERE); } void RTCDataChannel::scheduledEventTimerFired(Timer<RTCDataChannel>*) @@ -305,14 +315,33 @@ void RTCDataChannel::scheduledEventTimerFired(Timer<RTCDataChannel>*) if (m_stopped) return; - Vector<RefPtr<Event> > events; + WillBeHeapVector<RefPtrWillBeMember<Event> > events; events.swap(m_scheduledEvents); - Vector<RefPtr<Event> >::iterator it = events.begin(); + WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin(); for (; it != events.end(); ++it) dispatchEvent((*it).release()); events.clear(); } +#if ENABLE(OILPAN) +void RTCDataChannel::clearWeakMembers(Visitor* visitor) +{ + if (visitor->isAlive(m_connection)) + return; + stop(); + m_connection = nullptr; +} +#endif + +void RTCDataChannel::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_scheduledEvents); + visitor->registerWeakMembers<RTCDataChannel, &RTCDataChannel::clearWeakMembers>(this); +#endif + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.h index 911b7053edf..61c121b3c0b 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.h @@ -26,12 +26,16 @@ #define RTCDataChannel_h #include "bindings/v8/ScriptWrappable.h" -#include "core/events/EventTarget.h" -#include "core/platform/mediastream/RTCDataChannelHandlerClient.h" +#include "modules/EventTargetModules.h" #include "platform/Timer.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebRTCDataChannelHandler.h" +#include "public/platform/WebRTCDataChannelHandlerClient.h" #include "wtf/RefCounted.h" namespace blink { +class WebRTCDataChannelHandler; +class WebRTCPeerConnectionHandler; struct WebRTCDataChannelInit; } @@ -39,15 +43,15 @@ namespace WebCore { class Blob; class ExceptionState; -class RTCDataChannelHandler; -class RTCPeerConnectionHandler; +class RTCPeerConnection; -class RTCDataChannel : public RefCounted<RTCDataChannel>, public ScriptWrappable, public EventTargetWithInlineData, public RTCDataChannelHandlerClient { +class RTCDataChannel FINAL : public RefCountedWillBeRefCountedGarbageCollected<RTCDataChannel>, public ScriptWrappable, public EventTargetWithInlineData, public blink::WebRTCDataChannelHandlerClient { REFCOUNTED_EVENT_TARGET(RTCDataChannel); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(RTCDataChannel); public: - static PassRefPtr<RTCDataChannel> create(ExecutionContext*, PassOwnPtr<RTCDataChannelHandler>); - static PassRefPtr<RTCDataChannel> create(ExecutionContext*, RTCPeerConnectionHandler*, const String& label, const blink::WebRTCDataChannelInit&, ExceptionState&); - ~RTCDataChannel(); + static PassRefPtrWillBeRawPtr<RTCDataChannel> create(ExecutionContext*, RTCPeerConnection*, PassOwnPtr<blink::WebRTCDataChannelHandler>); + static PassRefPtrWillBeRawPtr<RTCDataChannel> create(ExecutionContext*, RTCPeerConnection*, blink::WebRTCPeerConnectionHandler*, const String& label, const blink::WebRTCDataChannelInit&, ExceptionState&); + virtual ~RTCDataChannel(); String label() const; @@ -69,7 +73,7 @@ public: void send(const String&, ExceptionState&); void send(PassRefPtr<ArrayBuffer>, ExceptionState&); void send(PassRefPtr<ArrayBufferView>, ExceptionState&); - void send(PassRefPtr<Blob>, ExceptionState&); + void send(PassRefPtrWillBeRawPtr<Blob>, ExceptionState&); void close(); @@ -84,25 +88,32 @@ public: virtual const AtomicString& interfaceName() const OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE; +#if ENABLE(OILPAN) + void clearWeakMembers(Visitor*); +#endif + + virtual void trace(Visitor*) OVERRIDE; + private: - RTCDataChannel(ExecutionContext*, PassOwnPtr<RTCDataChannelHandler>); + RTCDataChannel(ExecutionContext*, RTCPeerConnection*, PassOwnPtr<blink::WebRTCDataChannelHandler>); - void scheduleDispatchEvent(PassRefPtr<Event>); + void scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event>); void scheduledEventTimerFired(Timer<RTCDataChannel>*); ExecutionContext* m_executionContext; - // RTCDataChannelHandlerClient - virtual void didChangeReadyState(ReadyState) OVERRIDE; - virtual void didReceiveStringData(const String&) OVERRIDE; + // blink::WebRTCDataChannelHandlerClient + virtual void didChangeReadyState(blink::WebRTCDataChannelHandlerClient::ReadyState) OVERRIDE; + virtual void didReceiveStringData(const blink::WebString&) OVERRIDE; virtual void didReceiveRawData(const char*, size_t) OVERRIDE; virtual void didDetectError() OVERRIDE; - OwnPtr<RTCDataChannelHandler> m_handler; + OwnPtr<blink::WebRTCDataChannelHandler> m_handler; bool m_stopped; - ReadyState m_readyState; + blink::WebRTCDataChannelHandlerClient::ReadyState m_readyState; + enum BinaryType { BinaryTypeBlob, BinaryTypeArrayBuffer @@ -110,7 +121,11 @@ private: BinaryType m_binaryType; Timer<RTCDataChannel> m_scheduledEventTimer; - Vector<RefPtr<Event> > m_scheduledEvents; + WillBeHeapVector<RefPtrWillBeMember<Event> > m_scheduledEvents; + +#if ENABLE(OILPAN) + WeakMember<RTCPeerConnection> m_connection; +#endif }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.idl b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.idl index 4a69b5addef..7827c200761 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannel.idl @@ -22,35 +22,30 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCDataChannel + [ - NoInterfaceObject + WillBeGarbageCollected, + NoInterfaceObject, ] interface RTCDataChannel : EventTarget { readonly attribute DOMString label; - - // DEPRECATED - readonly attribute boolean reliable; - + readonly attribute boolean reliable; // DEPRECATED readonly attribute boolean ordered; readonly attribute unsigned short maxRetransmitTime; readonly attribute unsigned short maxRetransmits; readonly attribute DOMString protocol; readonly attribute boolean negotiated; readonly attribute unsigned short id; - readonly attribute DOMString readyState; readonly attribute unsigned long bufferedAmount; - + attribute EventHandler onopen; + attribute EventHandler onerror; + attribute EventHandler onclose; + void close(); + attribute EventHandler onmessage; [RaisesException=Setter] attribute DOMString binaryType; - + [RaisesException] void send(DOMString data); + [RaisesException] void send(Blob data); [RaisesException] void send(ArrayBuffer data); [RaisesException] void send(ArrayBufferView data); - [RaisesException] void send(Blob data); - [RaisesException] void send(DOMString data); - - void close(); - - attribute EventHandler onopen; - attribute EventHandler onerror; - attribute EventHandler onclose; - attribute EventHandler onmessage; }; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannelEvent.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannelEvent.cpp index 42da9cf8796..8ca3fddfa4e 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannelEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannelEvent.cpp @@ -25,18 +25,16 @@ #include "config.h" #include "modules/mediastream/RTCDataChannelEvent.h" -#include "core/events/ThreadLocalEventNames.h" - namespace WebCore { -PassRefPtr<RTCDataChannelEvent> RTCDataChannelEvent::create() +PassRefPtrWillBeRawPtr<RTCDataChannelEvent> RTCDataChannelEvent::create() { - return adoptRef(new RTCDataChannelEvent); + return adoptRefWillBeNoop(new RTCDataChannelEvent); } -PassRefPtr<RTCDataChannelEvent> RTCDataChannelEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<RTCDataChannel> channel) +PassRefPtrWillBeRawPtr<RTCDataChannelEvent> RTCDataChannelEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<RTCDataChannel> channel) { - return adoptRef(new RTCDataChannelEvent(type, canBubble, cancelable, channel)); + return adoptRefWillBeNoop(new RTCDataChannelEvent(type, canBubble, cancelable, channel)); } @@ -45,7 +43,7 @@ RTCDataChannelEvent::RTCDataChannelEvent() ScriptWrappable::init(this); } -RTCDataChannelEvent::RTCDataChannelEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<RTCDataChannel> channel) +RTCDataChannelEvent::RTCDataChannelEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<RTCDataChannel> channel) : Event(type, canBubble, cancelable) , m_channel(channel) { @@ -66,5 +64,10 @@ const AtomicString& RTCDataChannelEvent::interfaceName() const return EventNames::RTCDataChannelEvent; } -} // namespace WebCore +void RTCDataChannelEvent::trace(Visitor* visitor) +{ + visitor->trace(m_channel); + Event::trace(visitor); +} +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannelEvent.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannelEvent.h index 2d05e2724b3..d4862ab59fe 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannelEvent.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCDataChannelEvent.h @@ -25,28 +25,30 @@ #ifndef RTCDataChannelEvent_h #define RTCDataChannelEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "modules/mediastream/RTCDataChannel.h" #include "wtf/text/AtomicString.h" namespace WebCore { -class RTCDataChannelEvent : public Event { +class RTCDataChannelEvent FINAL : public Event { public: virtual ~RTCDataChannelEvent(); - static PassRefPtr<RTCDataChannelEvent> create(); - static PassRefPtr<RTCDataChannelEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<RTCDataChannel>); + static PassRefPtrWillBeRawPtr<RTCDataChannelEvent> create(); + static PassRefPtrWillBeRawPtr<RTCDataChannelEvent> create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<RTCDataChannel>); RTCDataChannel* channel() const; - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: RTCDataChannelEvent(); - RTCDataChannelEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<RTCDataChannel>); + RTCDataChannelEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<RTCDataChannel>); - RefPtr<RTCDataChannel> m_channel; + RefPtrWillBeMember<RTCDataChannel> m_channel; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.cpp index 81bf82a925d..4590ced0622 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.cpp @@ -33,18 +33,19 @@ #include "modules/mediastream/RTCIceCandidate.h" #include "bindings/v8/Dictionary.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" namespace WebCore { -PassRefPtr<RTCIceCandidate> RTCIceCandidate::create(const Dictionary& dictionary, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCIceCandidate> RTCIceCandidate::create(const Dictionary& dictionary, ExceptionState& exceptionState) { String candidate; bool ok = dictionary.get("candidate", candidate); if (!ok || !candidate.length()) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::incorrectPropertyType("candidate", "is not a string, or is empty.")); + return nullptr; } String sdpMid; @@ -53,12 +54,12 @@ PassRefPtr<RTCIceCandidate> RTCIceCandidate::create(const Dictionary& dictionary unsigned short sdpMLineIndex = 0; dictionary.get("sdpMLineIndex", sdpMLineIndex); - return adoptRef(new RTCIceCandidate(blink::WebRTCICECandidate(candidate, sdpMid, sdpMLineIndex))); + return adoptRefWillBeNoop(new RTCIceCandidate(blink::WebRTCICECandidate(candidate, sdpMid, sdpMLineIndex))); } -PassRefPtr<RTCIceCandidate> RTCIceCandidate::create(blink::WebRTCICECandidate webCandidate) +PassRefPtrWillBeRawPtr<RTCIceCandidate> RTCIceCandidate::create(blink::WebRTCICECandidate webCandidate) { - return adoptRef(new RTCIceCandidate(webCandidate)); + return adoptRefWillBeNoop(new RTCIceCandidate(webCandidate)); } RTCIceCandidate::RTCIceCandidate(blink::WebRTCICECandidate webCandidate) @@ -82,9 +83,24 @@ unsigned short RTCIceCandidate::sdpMLineIndex() const return m_webCandidate.sdpMLineIndex(); } -blink::WebRTCICECandidate RTCIceCandidate::webCandidate() +blink::WebRTCICECandidate RTCIceCandidate::webCandidate() const { return m_webCandidate; } +void RTCIceCandidate::setCandidate(String candidate) +{ + m_webCandidate.setCandidate(candidate); +} + +void RTCIceCandidate::setSdpMid(String sdpMid) +{ + m_webCandidate.setSdpMid(sdpMid); +} + +void RTCIceCandidate::setSdpMLineIndex(unsigned short sdpMLineIndex) +{ + m_webCandidate.setSdpMLineIndex(sdpMLineIndex); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.h index 9d934055751..5eecfc12850 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.h @@ -43,16 +43,21 @@ namespace WebCore { class Dictionary; class ExceptionState; -class RTCIceCandidate FINAL : public RefCounted<RTCIceCandidate>, public ScriptWrappable { +class RTCIceCandidate FINAL : public RefCountedWillBeGarbageCollectedFinalized<RTCIceCandidate>, public ScriptWrappable { public: - static PassRefPtr<RTCIceCandidate> create(const Dictionary&, ExceptionState&); - static PassRefPtr<RTCIceCandidate> create(blink::WebRTCICECandidate); + static PassRefPtrWillBeRawPtr<RTCIceCandidate> create(const Dictionary&, ExceptionState&); + static PassRefPtrWillBeRawPtr<RTCIceCandidate> create(blink::WebRTCICECandidate); String candidate() const; + void setCandidate(String); String sdpMid() const; + void setSdpMid(String); unsigned short sdpMLineIndex() const; + void setSdpMLineIndex(unsigned short); - blink::WebRTCICECandidate webCandidate(); + blink::WebRTCICECandidate webCandidate() const; + + void trace(Visitor*) { } private: explicit RTCIceCandidate(blink::WebRTCICECandidate); diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.idl b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.idl index 6404c114693..74a1c60ffbc 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidate.idl @@ -29,11 +29,12 @@ */ [ + WillBeGarbageCollected, Constructor(Dictionary dictionary), RaisesException=Constructor ] interface RTCIceCandidate { - readonly attribute DOMString candidate; - readonly attribute DOMString sdpMid; - readonly attribute unsigned short sdpMLineIndex; + [TreatNullAs=NullString] attribute DOMString candidate; + [TreatNullAs=NullString] attribute DOMString sdpMid; + attribute unsigned short sdpMLineIndex; }; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidateEvent.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidateEvent.cpp index 5ea215cef40..4a403dba56b 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidateEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidateEvent.cpp @@ -26,19 +26,18 @@ #include "modules/mediastream/RTCIceCandidateEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "modules/mediastream/RTCIceCandidate.h" namespace WebCore { -PassRefPtr<RTCIceCandidateEvent> RTCIceCandidateEvent::create() +PassRefPtrWillBeRawPtr<RTCIceCandidateEvent> RTCIceCandidateEvent::create() { - return adoptRef(new RTCIceCandidateEvent); + return adoptRefWillBeNoop(new RTCIceCandidateEvent); } -PassRefPtr<RTCIceCandidateEvent> RTCIceCandidateEvent::create(bool canBubble, bool cancelable, PassRefPtr<RTCIceCandidate> candidate) +PassRefPtrWillBeRawPtr<RTCIceCandidateEvent> RTCIceCandidateEvent::create(bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<RTCIceCandidate> candidate) { - return adoptRef(new RTCIceCandidateEvent(canBubble, cancelable, candidate)); + return adoptRefWillBeNoop(new RTCIceCandidateEvent(canBubble, cancelable, candidate)); } RTCIceCandidateEvent::RTCIceCandidateEvent() @@ -46,7 +45,7 @@ RTCIceCandidateEvent::RTCIceCandidateEvent() ScriptWrappable::init(this); } -RTCIceCandidateEvent::RTCIceCandidateEvent(bool canBubble, bool cancelable, PassRefPtr<RTCIceCandidate> candidate) +RTCIceCandidateEvent::RTCIceCandidateEvent(bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<RTCIceCandidate> candidate) : Event(EventTypeNames::icecandidate, canBubble, cancelable) , m_candidate(candidate) { @@ -67,5 +66,11 @@ const AtomicString& RTCIceCandidateEvent::interfaceName() const return EventNames::RTCIceCandidateEvent; } +void RTCIceCandidateEvent::trace(Visitor* visitor) +{ + visitor->trace(m_candidate); + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidateEvent.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidateEvent.h index be7eab7d5c3..99280464572 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidateEvent.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCIceCandidateEvent.h @@ -25,28 +25,30 @@ #ifndef RTCIceCandidateEvent_h #define RTCIceCandidateEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "wtf/text/AtomicString.h" namespace WebCore { class RTCIceCandidate; -class RTCIceCandidateEvent : public Event { +class RTCIceCandidateEvent FINAL : public Event { public: virtual ~RTCIceCandidateEvent(); - static PassRefPtr<RTCIceCandidateEvent> create(); - static PassRefPtr<RTCIceCandidateEvent> create(bool canBubble, bool cancelable, PassRefPtr<RTCIceCandidate>); + static PassRefPtrWillBeRawPtr<RTCIceCandidateEvent> create(); + static PassRefPtrWillBeRawPtr<RTCIceCandidateEvent> create(bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<RTCIceCandidate>); RTCIceCandidate* candidate() const; - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: RTCIceCandidateEvent(); - RTCIceCandidateEvent(bool canBubble, bool cancelable, PassRefPtr<RTCIceCandidate>); + RTCIceCandidateEvent(bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<RTCIceCandidate>); - RefPtr<RTCIceCandidate> m_candidate; + RefPtrWillBeMember<RTCIceCandidate> m_candidate; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp index da39fa952f8..dbfbb975db2 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp @@ -33,16 +33,15 @@ #include "modules/mediastream/RTCPeerConnection.h" #include "bindings/v8/ArrayValue.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/Document.h" -#include "core/events/Event.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" +#include "core/frame/LocalFrame.h" #include "core/html/VoidCallback.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" -#include "core/platform/mediastream/RTCDataChannelHandler.h" #include "modules/mediastream/MediaConstraintsImpl.h" #include "modules/mediastream/MediaStreamEvent.h" #include "modules/mediastream/RTCDTMFSender.h" @@ -57,29 +56,50 @@ #include "modules/mediastream/RTCStatsRequestImpl.h" #include "modules/mediastream/RTCVoidRequestImpl.h" #include "platform/mediastream/RTCConfiguration.h" +#include "public/platform/Platform.h" +#include "public/platform/WebMediaStream.h" +#include "public/platform/WebRTCConfiguration.h" +#include "public/platform/WebRTCDataChannelHandler.h" #include "public/platform/WebRTCDataChannelInit.h" #include "public/platform/WebRTCICECandidate.h" #include "public/platform/WebRTCSessionDescription.h" +#include "public/platform/WebRTCSessionDescriptionRequest.h" +#include "public/platform/WebRTCStatsRequest.h" +#include "public/platform/WebRTCVoidRequest.h" namespace WebCore { +namespace { + +static bool throwExceptionIfSignalingStateClosed(RTCPeerConnection::SignalingState state, ExceptionState& exceptionState) +{ + if (state == RTCPeerConnection::SignalingStateClosed) { + exceptionState.throwDOMException(InvalidStateError, "The RTCPeerConnection's signalingState is 'closed'."); + return true; + } + + return false; +} + +} // namespace + PassRefPtr<RTCConfiguration> RTCPeerConnection::parseConfiguration(const Dictionary& configuration, ExceptionState& exceptionState) { if (configuration.isUndefinedOrNull()) - return 0; + return nullptr; ArrayValue iceServers; bool ok = configuration.get("iceServers", iceServers); if (!ok || iceServers.isUndefinedOrNull()) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; + exceptionState.throwTypeError("Malformed RTCConfiguration"); + return nullptr; } size_t numberOfServers; ok = iceServers.length(numberOfServers); if (!ok) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; + exceptionState.throwTypeError("Malformed RTCConfiguration"); + return nullptr; } RefPtr<RTCConfiguration> rtcConfiguration = RTCConfiguration::create(); @@ -88,232 +108,252 @@ PassRefPtr<RTCConfiguration> RTCPeerConnection::parseConfiguration(const Diction Dictionary iceServer; ok = iceServers.get(i, iceServer); if (!ok) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; + exceptionState.throwTypeError("Malformed RTCIceServer"); + return nullptr; } - String urlString, username, credential; - ok = iceServer.get("url", urlString); - if (!ok) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; - } - KURL url(KURL(), urlString); - if (!url.isValid() || !(url.protocolIs("turn") || url.protocolIs("turns") || url.protocolIs("stun"))) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; + Vector<String> names; + iceServer.getOwnPropertyNames(names); + + Vector<String> urlStrings; + if (names.contains("urls")) { + if (!iceServer.get("urls", urlStrings) || !urlStrings.size()) { + String urlString; + if (iceServer.get("urls", urlString)) { + urlStrings.append(urlString); + } else { + exceptionState.throwTypeError("Malformed RTCIceServer"); + return nullptr; + } + } + } else if (names.contains("url")) { + String urlString; + if (iceServer.get("url", urlString)) { + urlStrings.append(urlString); + } else { + exceptionState.throwTypeError("Malformed RTCIceServer"); + return nullptr; + } + } else { + exceptionState.throwTypeError("Malformed RTCIceServer"); + return nullptr; } + String username, credential; iceServer.get("username", username); iceServer.get("credential", credential); - rtcConfiguration->appendServer(RTCIceServer::create(url, username, credential)); + for (Vector<String>::iterator iter = urlStrings.begin(); iter != urlStrings.end(); ++iter) { + KURL url(KURL(), *iter); + if (!url.isValid() || !(url.protocolIs("turn") || url.protocolIs("turns") || url.protocolIs("stun"))) { + exceptionState.throwTypeError("Malformed URL"); + return nullptr; + } + + rtcConfiguration->appendServer(RTCIceServer::create(url, username, credential)); + } } return rtcConfiguration.release(); } -PassRefPtr<RTCPeerConnection> RTCPeerConnection::create(ExecutionContext* context, const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCPeerConnection> RTCPeerConnection::create(ExecutionContext* context, const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionState& exceptionState) { RefPtr<RTCConfiguration> configuration = parseConfiguration(rtcConfiguration, exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; - RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); + blink::WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; - RefPtr<RTCPeerConnection> peerConnection = adoptRef(new RTCPeerConnection(context, configuration.release(), constraints.release(), exceptionState)); + RefPtrWillBeRawPtr<RTCPeerConnection> peerConnection = adoptRefWillBeRefCountedGarbageCollected(new RTCPeerConnection(context, configuration.release(), constraints, exceptionState)); peerConnection->suspendIfNeeded(); if (exceptionState.hadException()) - return 0; + return nullptr; return peerConnection.release(); } -RTCPeerConnection::RTCPeerConnection(ExecutionContext* context, PassRefPtr<RTCConfiguration> configuration, PassRefPtr<MediaConstraints> constraints, ExceptionState& exceptionState) +RTCPeerConnection::RTCPeerConnection(ExecutionContext* context, PassRefPtr<RTCConfiguration> configuration, blink::WebMediaConstraints constraints, ExceptionState& exceptionState) : ActiveDOMObject(context) , m_signalingState(SignalingStateStable) - , m_iceGatheringState(IceGatheringStateNew) - , m_iceConnectionState(IceConnectionStateNew) + , m_iceGatheringState(ICEGatheringStateNew) + , m_iceConnectionState(ICEConnectionStateNew) , m_dispatchScheduledEventRunner(this, &RTCPeerConnection::dispatchScheduledEvent) , m_stopped(false) + , m_closed(false) { ScriptWrappable::init(this); Document* document = toDocument(executionContext()); + // If we fail, set |m_closed| and |m_stopped| to true, to avoid hitting the assert in the destructor. + if (!document->frame()) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + m_closed = true; + m_stopped = true; + exceptionState.throwDOMException(NotSupportedError, "PeerConnections may not be created in detached documents."); return; } - m_peerHandler = RTCPeerConnectionHandler::create(this); + m_peerHandler = adoptPtr(blink::Platform::current()->createRTCPeerConnectionHandler(this)); if (!m_peerHandler) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + m_closed = true; + m_stopped = true; + exceptionState.throwDOMException(NotSupportedError, "No PeerConnection handler can be created, perhaps WebRTC is disabled?"); return; } document->frame()->loader().client()->dispatchWillStartUsingPeerConnectionHandler(m_peerHandler.get()); if (!m_peerHandler->initialize(configuration, constraints)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + m_closed = true; + m_stopped = true; + exceptionState.throwDOMException(NotSupportedError, "Failed to initialize native PeerConnection."); return; } } RTCPeerConnection::~RTCPeerConnection() { + // This checks that close() or stop() is called before the destructor. + // We are assuming that a wrapper is always created when RTCPeerConnection is created. + ASSERT(m_closed || m_stopped); + +#if !ENABLE(OILPAN) stop(); +#endif } void RTCPeerConnection::createOffer(PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback, const Dictionary& mediaConstraints, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } - if (!successCallback) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } + ASSERT(successCallback); - RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); + blink::WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); if (exceptionState.hadException()) return; - RefPtr<RTCSessionDescriptionRequestImpl> request = RTCSessionDescriptionRequestImpl::create(executionContext(), successCallback, errorCallback); + RefPtr<RTCSessionDescriptionRequest> request = RTCSessionDescriptionRequestImpl::create(executionContext(), this, successCallback, errorCallback); m_peerHandler->createOffer(request.release(), constraints); } void RTCPeerConnection::createAnswer(PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback, const Dictionary& mediaConstraints, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } - if (!successCallback) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } + ASSERT(successCallback); - RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); + blink::WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); if (exceptionState.hadException()) return; - RefPtr<RTCSessionDescriptionRequestImpl> request = RTCSessionDescriptionRequestImpl::create(executionContext(), successCallback, errorCallback); - m_peerHandler->createAnswer(request.release(), constraints.release()); + RefPtr<RTCSessionDescriptionRequest> request = RTCSessionDescriptionRequestImpl::create(executionContext(), this, successCallback, errorCallback); + m_peerHandler->createAnswer(request.release(), constraints); } -void RTCPeerConnection::setLocalDescription(PassRefPtr<RTCSessionDescription> prpSessionDescription, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback, ExceptionState& exceptionState) +void RTCPeerConnection::setLocalDescription(PassRefPtrWillBeRawPtr<RTCSessionDescription> prpSessionDescription, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } - RefPtr<RTCSessionDescription> sessionDescription = prpSessionDescription; + RefPtrWillBeRawPtr<RTCSessionDescription> sessionDescription = prpSessionDescription; if (!sessionDescription) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "RTCSessionDescription")); return; } - RefPtr<RTCVoidRequestImpl> request = RTCVoidRequestImpl::create(executionContext(), successCallback, errorCallback); + RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback); m_peerHandler->setLocalDescription(request.release(), sessionDescription->webSessionDescription()); } -PassRefPtr<RTCSessionDescription> RTCPeerConnection::localDescription(ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCSessionDescription> RTCPeerConnection::localDescription(ExceptionState& exceptionState) { blink::WebRTCSessionDescription webSessionDescription = m_peerHandler->localDescription(); if (webSessionDescription.isNull()) - return 0; + return nullptr; - RefPtr<RTCSessionDescription> sessionDescription = RTCSessionDescription::create(webSessionDescription); - return sessionDescription.release(); + return RTCSessionDescription::create(webSessionDescription); } -void RTCPeerConnection::setRemoteDescription(PassRefPtr<RTCSessionDescription> prpSessionDescription, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback, ExceptionState& exceptionState) +void RTCPeerConnection::setRemoteDescription(PassRefPtrWillBeRawPtr<RTCSessionDescription> prpSessionDescription, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } - RefPtr<RTCSessionDescription> sessionDescription = prpSessionDescription; + RefPtrWillBeRawPtr<RTCSessionDescription> sessionDescription = prpSessionDescription; if (!sessionDescription) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "RTCSessionDescription")); return; } - RefPtr<RTCVoidRequestImpl> request = RTCVoidRequestImpl::create(executionContext(), successCallback, errorCallback); + RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback); m_peerHandler->setRemoteDescription(request.release(), sessionDescription->webSessionDescription()); } -PassRefPtr<RTCSessionDescription> RTCPeerConnection::remoteDescription(ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCSessionDescription> RTCPeerConnection::remoteDescription(ExceptionState& exceptionState) { blink::WebRTCSessionDescription webSessionDescription = m_peerHandler->remoteDescription(); if (webSessionDescription.isNull()) - return 0; + return nullptr; - RefPtr<RTCSessionDescription> desc = RTCSessionDescription::create(webSessionDescription); - return desc.release(); + return RTCSessionDescription::create(webSessionDescription); } void RTCPeerConnection::updateIce(const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } RefPtr<RTCConfiguration> configuration = parseConfiguration(rtcConfiguration, exceptionState); if (exceptionState.hadException()) return; - RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); + blink::WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); if (exceptionState.hadException()) return; - bool valid = m_peerHandler->updateIce(configuration, constraints); + bool valid = m_peerHandler->updateICE(configuration.release(), constraints); if (!valid) - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "Could not update the ICE Agent with the given configuration."); } void RTCPeerConnection::addIceCandidate(RTCIceCandidate* iceCandidate, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } if (!iceCandidate) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "RTCIceCandidate")); return; } - bool valid = m_peerHandler->addIceCandidate(iceCandidate->webCandidate()); + bool valid = m_peerHandler->addICECandidate(iceCandidate->webCandidate()); if (!valid) - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The ICE candidate could not be added."); } void RTCPeerConnection::addIceCandidate(RTCIceCandidate* iceCandidate, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } - if (!iceCandidate || !successCallback || !errorCallback) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); + if (!iceCandidate) { + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "RTCIceCandidate")); return; } + ASSERT(successCallback); + ASSERT(errorCallback); - RefPtr<RTCVoidRequestImpl> request = RTCVoidRequestImpl::create(executionContext(), successCallback, errorCallback); + RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback); - bool implemented = m_peerHandler->addIceCandidate(request.release(), iceCandidate->webCandidate()); - if (!implemented) - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); + bool implemented = m_peerHandler->addICECandidate(request.release(), iceCandidate->webCandidate()); + if (!implemented) { + exceptionState.throwDOMException(NotSupportedError, "This method is not yet implemented."); + } } String RTCPeerConnection::signalingState() const @@ -340,11 +380,11 @@ String RTCPeerConnection::signalingState() const String RTCPeerConnection::iceGatheringState() const { switch (m_iceGatheringState) { - case IceGatheringStateNew: + case ICEGatheringStateNew: return "new"; - case IceGatheringStateGathering: + case ICEGatheringStateGathering: return "gathering"; - case IceGatheringStateComplete: + case ICEGatheringStateComplete: return "complete"; } @@ -355,19 +395,19 @@ String RTCPeerConnection::iceGatheringState() const String RTCPeerConnection::iceConnectionState() const { switch (m_iceConnectionState) { - case IceConnectionStateNew: + case ICEConnectionStateNew: return "new"; - case IceConnectionStateChecking: + case ICEConnectionStateChecking: return "checking"; - case IceConnectionStateConnected: + case ICEConnectionStateConnected: return "connected"; - case IceConnectionStateCompleted: + case ICEConnectionStateCompleted: return "completed"; - case IceConnectionStateFailed: + case ICEConnectionStateFailed: return "failed"; - case IceConnectionStateDisconnected: + case ICEConnectionStateDisconnected: return "disconnected"; - case IceConnectionStateClosed: + case ICEConnectionStateClosed: return "closed"; } @@ -375,23 +415,21 @@ String RTCPeerConnection::iceConnectionState() const return String(); } -void RTCPeerConnection::addStream(PassRefPtr<MediaStream> prpStream, const Dictionary& mediaConstraints, ExceptionState& exceptionState) +void RTCPeerConnection::addStream(PassRefPtrWillBeRawPtr<MediaStream> prpStream, const Dictionary& mediaConstraints, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } - RefPtr<MediaStream> stream = prpStream; + RefPtrWillBeRawPtr<MediaStream> stream = prpStream; if (!stream) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "MediaStream")); return; } if (m_localStreams.contains(stream)) return; - RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); + blink::WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); if (exceptionState.hadException()) return; @@ -399,22 +437,20 @@ void RTCPeerConnection::addStream(PassRefPtr<MediaStream> prpStream, const Dicti bool valid = m_peerHandler->addStream(stream->descriptor(), constraints); if (!valid) - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "Unable to add the provided stream."); } -void RTCPeerConnection::removeStream(PassRefPtr<MediaStream> prpStream, ExceptionState& exceptionState) +void RTCPeerConnection::removeStream(PassRefPtrWillBeRawPtr<MediaStream> prpStream, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } if (!prpStream) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "MediaStream")); return; } - RefPtr<MediaStream> stream = prpStream; + RefPtrWillBeRawPtr<MediaStream> stream = prpStream; size_t pos = m_localStreams.find(stream); if (pos == kNotFound) @@ -452,17 +488,15 @@ MediaStream* RTCPeerConnection::getStreamById(const String& streamId) void RTCPeerConnection::getStats(PassOwnPtr<RTCStatsCallback> successCallback, PassRefPtr<MediaStreamTrack> selector) { - RefPtr<RTCStatsRequestImpl> statsRequest = RTCStatsRequestImpl::create(executionContext(), successCallback, selector); + RefPtr<RTCStatsRequest> statsRequest = RTCStatsRequestImpl::create(executionContext(), this, successCallback, selector); // FIXME: Add passing selector as part of the statsRequest. m_peerHandler->getStats(statsRequest.release()); } -PassRefPtr<RTCDataChannel> RTCPeerConnection::createDataChannel(String label, const Dictionary& options, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCDataChannel> RTCPeerConnection::createDataChannel(String label, const Dictionary& options, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return 0; - } + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) + return nullptr; blink::WebRTCDataChannelInit init; options.get("ordered", init.ordered); @@ -480,9 +514,9 @@ PassRefPtr<RTCDataChannel> RTCPeerConnection::createDataChannel(String label, co options.get("protocol", protocolString); init.protocol = protocolString; - RefPtr<RTCDataChannel> channel = RTCDataChannel::create(executionContext(), m_peerHandler.get(), label, init, exceptionState); + RefPtrWillBeRawPtr<RTCDataChannel> channel = RTCDataChannel::create(executionContext(), this, m_peerHandler.get(), label, init, exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; m_dataChannels.append(channel); return channel.release(); } @@ -496,98 +530,104 @@ bool RTCPeerConnection::hasLocalStreamWithTrackId(const String& trackId) return false; } -PassRefPtr<RTCDTMFSender> RTCPeerConnection::createDTMFSender(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCDTMFSender> RTCPeerConnection::createDTMFSender(PassRefPtrWillBeRawPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return 0; - } + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) + return nullptr; if (!prpTrack) { - exceptionState.throwUninformativeAndGenericTypeError(); - return 0; + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(1, "MediaStreamTrack")); + return nullptr; } - RefPtr<MediaStreamTrack> track = prpTrack; + RefPtrWillBeRawPtr<MediaStreamTrack> track = prpTrack; if (!hasLocalStreamWithTrackId(track->id())) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return 0; + exceptionState.throwDOMException(SyntaxError, "No local stream is available for the track provided."); + return nullptr; } - RefPtr<RTCDTMFSender> dtmfSender = RTCDTMFSender::create(executionContext(), m_peerHandler.get(), track.release(), exceptionState); + RefPtrWillBeRawPtr<RTCDTMFSender> dtmfSender = RTCDTMFSender::create(executionContext(), m_peerHandler.get(), track.release(), exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; return dtmfSender.release(); } void RTCPeerConnection::close(ExceptionState& exceptionState) { - if (m_signalingState == SignalingStateClosed) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) return; - } m_peerHandler->stop(); + m_closed = true; - changeIceConnectionState(IceConnectionStateClosed); - changeIceGatheringState(IceGatheringStateComplete); + changeIceConnectionState(ICEConnectionStateClosed); + changeIceGatheringState(ICEGatheringStateComplete); changeSignalingState(SignalingStateClosed); } void RTCPeerConnection::negotiationNeeded() { + ASSERT(!m_closed); scheduleDispatchEvent(Event::create(EventTypeNames::negotiationneeded)); } -void RTCPeerConnection::didGenerateIceCandidate(blink::WebRTCICECandidate webCandidate) +void RTCPeerConnection::didGenerateICECandidate(const blink::WebRTCICECandidate& webCandidate) { + ASSERT(!m_closed); ASSERT(executionContext()->isContextThread()); if (webCandidate.isNull()) - scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, 0)); + scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, nullptr)); else { - RefPtr<RTCIceCandidate> iceCandidate = RTCIceCandidate::create(webCandidate); + RefPtrWillBeRawPtr<RTCIceCandidate> iceCandidate = RTCIceCandidate::create(webCandidate); scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, iceCandidate.release())); } } void RTCPeerConnection::didChangeSignalingState(SignalingState newState) { + ASSERT(!m_closed); ASSERT(executionContext()->isContextThread()); changeSignalingState(newState); } -void RTCPeerConnection::didChangeIceGatheringState(IceGatheringState newState) +void RTCPeerConnection::didChangeICEGatheringState(ICEGatheringState newState) { + ASSERT(!m_closed); ASSERT(executionContext()->isContextThread()); changeIceGatheringState(newState); } -void RTCPeerConnection::didChangeIceConnectionState(IceConnectionState newState) +void RTCPeerConnection::didChangeICEConnectionState(ICEConnectionState newState) { + ASSERT(!m_closed); ASSERT(executionContext()->isContextThread()); changeIceConnectionState(newState); } -void RTCPeerConnection::didAddRemoteStream(PassRefPtr<MediaStreamDescriptor> streamDescriptor) +void RTCPeerConnection::didAddRemoteStream(const blink::WebMediaStream& remoteStream) { + ASSERT(!m_closed); ASSERT(executionContext()->isContextThread()); if (m_signalingState == SignalingStateClosed) return; - RefPtr<MediaStream> stream = MediaStream::create(executionContext(), streamDescriptor); + RefPtrWillBeRawPtr<MediaStream> stream = MediaStream::create(executionContext(), remoteStream); m_remoteStreams.append(stream); scheduleDispatchEvent(MediaStreamEvent::create(EventTypeNames::addstream, false, false, stream.release())); } -void RTCPeerConnection::didRemoveRemoteStream(MediaStreamDescriptor* streamDescriptor) +void RTCPeerConnection::didRemoveRemoteStream(const blink::WebMediaStream& remoteStream) { + ASSERT(!m_closed); ASSERT(executionContext()->isContextThread()); + + MediaStreamDescriptor* streamDescriptor = remoteStream; ASSERT(streamDescriptor->client()); - RefPtr<MediaStream> stream = static_cast<MediaStream*>(streamDescriptor->client()); + RefPtrWillBeRawPtr<MediaStream> stream = static_cast<MediaStream*>(streamDescriptor->client()); stream->streamEnded(); if (m_signalingState == SignalingStateClosed) @@ -600,19 +640,25 @@ void RTCPeerConnection::didRemoveRemoteStream(MediaStreamDescriptor* streamDescr scheduleDispatchEvent(MediaStreamEvent::create(EventTypeNames::removestream, false, false, stream.release())); } -void RTCPeerConnection::didAddRemoteDataChannel(PassOwnPtr<RTCDataChannelHandler> handler) +void RTCPeerConnection::didAddRemoteDataChannel(blink::WebRTCDataChannelHandler* handler) { + ASSERT(!m_closed); ASSERT(executionContext()->isContextThread()); if (m_signalingState == SignalingStateClosed) return; - RefPtr<RTCDataChannel> channel = RTCDataChannel::create(executionContext(), handler); + RefPtrWillBeRawPtr<RTCDataChannel> channel = RTCDataChannel::create(executionContext(), this, adoptPtr(handler)); m_dataChannels.append(channel); scheduleDispatchEvent(RTCDataChannelEvent::create(EventTypeNames::datachannel, false, false, channel.release())); } +void RTCPeerConnection::releasePeerConnectionHandler() +{ + stop(); +} + const AtomicString& RTCPeerConnection::interfaceName() const { return EventTargetNames::RTCPeerConnection; @@ -639,14 +685,17 @@ void RTCPeerConnection::stop() return; m_stopped = true; - m_iceConnectionState = IceConnectionStateClosed; + m_iceConnectionState = ICEConnectionStateClosed; m_signalingState = SignalingStateClosed; - Vector<RefPtr<RTCDataChannel> >::iterator i = m_dataChannels.begin(); + WillBeHeapVector<RefPtrWillBeMember<RTCDataChannel> >::iterator i = m_dataChannels.begin(); for (; i != m_dataChannels.end(); ++i) (*i)->stop(); + m_dataChannels.clear(); m_dispatchScheduledEventRunner.stop(); + + m_peerHandler.clear(); } void RTCPeerConnection::changeSignalingState(SignalingState signalingState) @@ -657,20 +706,20 @@ void RTCPeerConnection::changeSignalingState(SignalingState signalingState) } } -void RTCPeerConnection::changeIceGatheringState(IceGatheringState iceGatheringState) +void RTCPeerConnection::changeIceGatheringState(ICEGatheringState iceGatheringState) { m_iceGatheringState = iceGatheringState; } -void RTCPeerConnection::changeIceConnectionState(IceConnectionState iceConnectionState) +void RTCPeerConnection::changeIceConnectionState(ICEConnectionState iceConnectionState) { - if (m_iceConnectionState != IceConnectionStateClosed && m_iceConnectionState != iceConnectionState) { + if (m_iceConnectionState != ICEConnectionStateClosed && m_iceConnectionState != iceConnectionState) { m_iceConnectionState = iceConnectionState; scheduleDispatchEvent(Event::create(EventTypeNames::iceconnectionstatechange)); } } -void RTCPeerConnection::scheduleDispatchEvent(PassRefPtr<Event> event) +void RTCPeerConnection::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { m_scheduledEvents.append(event); @@ -682,14 +731,23 @@ void RTCPeerConnection::dispatchScheduledEvent() if (m_stopped) return; - Vector<RefPtr<Event> > events; + WillBeHeapVector<RefPtrWillBeMember<Event> > events; events.swap(m_scheduledEvents); - Vector<RefPtr<Event> >::iterator it = events.begin(); + WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin(); for (; it != events.end(); ++it) dispatchEvent((*it).release()); events.clear(); } +void RTCPeerConnection::trace(Visitor* visitor) +{ + visitor->trace(m_localStreams); + visitor->trace(m_remoteStreams); + visitor->trace(m_dataChannels); + visitor->trace(m_scheduledEvents); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h index 3b74ce98257..6725ef24243 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.h @@ -34,18 +34,18 @@ #include "bindings/v8/Dictionary.h" #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" -#include "core/platform/mediastream/RTCPeerConnectionHandler.h" -#include "core/platform/mediastream/RTCPeerConnectionHandlerClient.h" +#include "modules/EventTargetModules.h" #include "modules/mediastream/MediaStream.h" #include "modules/mediastream/RTCIceCandidate.h" #include "platform/AsyncMethodRunner.h" +#include "public/platform/WebMediaConstraints.h" +#include "public/platform/WebRTCPeerConnectionHandler.h" +#include "public/platform/WebRTCPeerConnectionHandlerClient.h" #include "wtf/RefCounted.h" namespace WebCore { class ExceptionState; -class MediaConstraints; class MediaStreamTrack; class RTCConfiguration; class RTCDTMFSender; @@ -56,21 +56,22 @@ class RTCSessionDescriptionCallback; class RTCStatsCallback; class VoidCallback; -class RTCPeerConnection : public RefCounted<RTCPeerConnection>, public ScriptWrappable, public RTCPeerConnectionHandlerClient, public EventTargetWithInlineData, public ActiveDOMObject { +class RTCPeerConnection FINAL : public RefCountedWillBeRefCountedGarbageCollected<RTCPeerConnection>, public ScriptWrappable, public blink::WebRTCPeerConnectionHandlerClient, public EventTargetWithInlineData, public ActiveDOMObject { REFCOUNTED_EVENT_TARGET(RTCPeerConnection); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(RTCPeerConnection); public: - static PassRefPtr<RTCPeerConnection> create(ExecutionContext*, const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionState&); - ~RTCPeerConnection(); + static PassRefPtrWillBeRawPtr<RTCPeerConnection> create(ExecutionContext*, const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionState&); + virtual ~RTCPeerConnection(); void createOffer(PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>, const Dictionary& mediaConstraints, ExceptionState&); void createAnswer(PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>, const Dictionary& mediaConstraints, ExceptionState&); - void setLocalDescription(PassRefPtr<RTCSessionDescription>, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>, ExceptionState&); - PassRefPtr<RTCSessionDescription> localDescription(ExceptionState&); + void setLocalDescription(PassRefPtrWillBeRawPtr<RTCSessionDescription>, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>, ExceptionState&); + PassRefPtrWillBeRawPtr<RTCSessionDescription> localDescription(ExceptionState&); - void setRemoteDescription(PassRefPtr<RTCSessionDescription>, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>, ExceptionState&); - PassRefPtr<RTCSessionDescription> remoteDescription(ExceptionState&); + void setRemoteDescription(PassRefPtrWillBeRawPtr<RTCSessionDescription>, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>, ExceptionState&); + PassRefPtrWillBeRawPtr<RTCSessionDescription> remoteDescription(ExceptionState&); String signalingState() const; @@ -91,18 +92,22 @@ public: MediaStream* getStreamById(const String& streamId); - void addStream(PassRefPtr<MediaStream>, const Dictionary& mediaConstraints, ExceptionState&); + void addStream(PassRefPtrWillBeRawPtr<MediaStream>, const Dictionary& mediaConstraints, ExceptionState&); - void removeStream(PassRefPtr<MediaStream>, ExceptionState&); + void removeStream(PassRefPtrWillBeRawPtr<MediaStream>, ExceptionState&); void getStats(PassOwnPtr<RTCStatsCallback> successCallback, PassRefPtr<MediaStreamTrack> selector); - PassRefPtr<RTCDataChannel> createDataChannel(String label, const Dictionary& dataChannelDict, ExceptionState&); + PassRefPtrWillBeRawPtr<RTCDataChannel> createDataChannel(String label, const Dictionary& dataChannelDict, ExceptionState&); - PassRefPtr<RTCDTMFSender> createDTMFSender(PassRefPtr<MediaStreamTrack>, ExceptionState&); + PassRefPtrWillBeRawPtr<RTCDTMFSender> createDTMFSender(PassRefPtrWillBeRawPtr<MediaStreamTrack>, ExceptionState&); void close(ExceptionState&); + // We allow getStats after close, but not other calls or callbacks. + bool shouldFireDefaultCallbacks() { return !m_closed && !m_stopped; } + bool shouldFireGetStatsCallback() { return !m_stopped; } + DEFINE_ATTRIBUTE_EVENT_LISTENER(negotiationneeded); DEFINE_ATTRIBUTE_EVENT_LISTENER(icecandidate); DEFINE_ATTRIBUTE_EVENT_LISTENER(signalingstatechange); @@ -111,15 +116,16 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(iceconnectionstatechange); DEFINE_ATTRIBUTE_EVENT_LISTENER(datachannel); - // RTCPeerConnectionHandlerClient + // blink::WebRTCPeerConnectionHandlerClient virtual void negotiationNeeded() OVERRIDE; - virtual void didGenerateIceCandidate(blink::WebRTCICECandidate) OVERRIDE; + virtual void didGenerateICECandidate(const blink::WebRTCICECandidate&) OVERRIDE; virtual void didChangeSignalingState(SignalingState) OVERRIDE; - virtual void didChangeIceGatheringState(IceGatheringState) OVERRIDE; - virtual void didChangeIceConnectionState(IceConnectionState) OVERRIDE; - virtual void didAddRemoteStream(PassRefPtr<MediaStreamDescriptor>) OVERRIDE; - virtual void didRemoveRemoteStream(MediaStreamDescriptor*) OVERRIDE; - virtual void didAddRemoteDataChannel(PassOwnPtr<RTCDataChannelHandler>) OVERRIDE; + virtual void didChangeICEGatheringState(ICEGatheringState) OVERRIDE; + virtual void didChangeICEConnectionState(ICEConnectionState) OVERRIDE; + virtual void didAddRemoteStream(const blink::WebMediaStream&) OVERRIDE; + virtual void didRemoveRemoteStream(const blink::WebMediaStream&) OVERRIDE; + virtual void didAddRemoteDataChannel(blink::WebRTCDataChannelHandler*) OVERRIDE; + virtual void releasePeerConnectionHandler() OVERRIDE; // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE; @@ -129,35 +135,42 @@ public: virtual void suspend() OVERRIDE; virtual void resume() OVERRIDE; virtual void stop() OVERRIDE; - virtual bool hasPendingActivity() const OVERRIDE { return !m_stopped; } + // We keep the this object alive until either stopped or closed. + virtual bool hasPendingActivity() const OVERRIDE + { + return !m_closed && !m_stopped; + } + + virtual void trace(Visitor*) OVERRIDE; private: - RTCPeerConnection(ExecutionContext*, PassRefPtr<RTCConfiguration>, PassRefPtr<MediaConstraints>, ExceptionState&); + RTCPeerConnection(ExecutionContext*, PassRefPtr<RTCConfiguration>, blink::WebMediaConstraints, ExceptionState&); static PassRefPtr<RTCConfiguration> parseConfiguration(const Dictionary& configuration, ExceptionState&); - void scheduleDispatchEvent(PassRefPtr<Event>); + void scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event>); void dispatchScheduledEvent(); bool hasLocalStreamWithTrackId(const String& trackId); - void changeSignalingState(SignalingState); - void changeIceGatheringState(IceGatheringState); - void changeIceConnectionState(IceConnectionState); + void changeSignalingState(blink::WebRTCPeerConnectionHandlerClient::SignalingState); + void changeIceGatheringState(blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState); + void changeIceConnectionState(blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState); SignalingState m_signalingState; - IceGatheringState m_iceGatheringState; - IceConnectionState m_iceConnectionState; + ICEGatheringState m_iceGatheringState; + ICEConnectionState m_iceConnectionState; MediaStreamVector m_localStreams; MediaStreamVector m_remoteStreams; - Vector<RefPtr<RTCDataChannel> > m_dataChannels; + WillBeHeapVector<RefPtrWillBeMember<RTCDataChannel> > m_dataChannels; - OwnPtr<RTCPeerConnectionHandler> m_peerHandler; + OwnPtr<blink::WebRTCPeerConnectionHandler> m_peerHandler; AsyncMethodRunner<RTCPeerConnection> m_dispatchScheduledEventRunner; - Vector<RefPtr<Event> > m_scheduledEvents; + WillBeHeapVector<RefPtrWillBeMember<Event> > m_scheduledEvents; bool m_stopped; + bool m_closed; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.idl b/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.idl index 1be4b240090..5b90db56e1c 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.idl @@ -29,6 +29,7 @@ */ [ + WillBeGarbageCollected, ActiveDOMObject, Constructor(Dictionary rtcIceServers, optional Dictionary mediaConstraints), ConstructorCallWith=ExecutionContext, @@ -61,8 +62,8 @@ sequence<MediaStream> getRemoteStreams(); MediaStream getStreamById(DOMString streamId); - [StrictTypeChecking, RaisesException] void addStream(MediaStream stream, optional Dictionary mediaConstraints); - [StrictTypeChecking, RaisesException] void removeStream(MediaStream stream); + [TypeChecking=Interface|Nullable, RaisesException] void addStream(MediaStream? stream, optional Dictionary mediaConstraints); + [TypeChecking=Interface|Nullable, RaisesException] void removeStream(MediaStream? stream); void getStats(RTCStatsCallback successCallback, [Default=Undefined] optional MediaStreamTrack selector); @@ -80,4 +81,3 @@ attribute EventHandler oniceconnectionstatechange; attribute EventHandler ondatachannel; }; - diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.cpp index 64589728103..8559f69660f 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.cpp @@ -48,24 +48,24 @@ static String constructIllegalTypeExceptionMessage(const String& type) return "Illegal value of attribute 'type' : " + type; } -PassRefPtr<RTCSessionDescription> RTCSessionDescription::create(const Dictionary& descriptionInitDict, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<RTCSessionDescription> RTCSessionDescription::create(const Dictionary& descriptionInitDict, ExceptionState& exceptionState) { String type; bool ok = descriptionInitDict.get("type", type); if (ok && !verifyType(type)) { exceptionState.throwDOMException(TypeMismatchError, constructIllegalTypeExceptionMessage(type)); - return 0; + return nullptr; } String sdp; descriptionInitDict.get("sdp", sdp); - return adoptRef(new RTCSessionDescription(blink::WebRTCSessionDescription(type, sdp))); + return adoptRefWillBeNoop(new RTCSessionDescription(blink::WebRTCSessionDescription(type, sdp))); } -PassRefPtr<RTCSessionDescription> RTCSessionDescription::create(blink::WebRTCSessionDescription webSessionDescription) +PassRefPtrWillBeRawPtr<RTCSessionDescription> RTCSessionDescription::create(blink::WebRTCSessionDescription webSessionDescription) { - return adoptRef(new RTCSessionDescription(webSessionDescription)); + return adoptRefWillBeNoop(new RTCSessionDescription(webSessionDescription)); } RTCSessionDescription::RTCSessionDescription(blink::WebRTCSessionDescription webSessionDescription) diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.h index 8e87f89e731..5b539694c0d 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.h @@ -42,10 +42,10 @@ namespace WebCore { class Dictionary; class ExceptionState; -class RTCSessionDescription FINAL : public RefCounted<RTCSessionDescription>, public ScriptWrappable { +class RTCSessionDescription FINAL : public RefCountedWillBeGarbageCollectedFinalized<RTCSessionDescription>, public ScriptWrappable { public: - static PassRefPtr<RTCSessionDescription> create(const Dictionary&, ExceptionState&); - static PassRefPtr<RTCSessionDescription> create(blink::WebRTCSessionDescription); + static PassRefPtrWillBeRawPtr<RTCSessionDescription> create(const Dictionary&, ExceptionState&); + static PassRefPtrWillBeRawPtr<RTCSessionDescription> create(blink::WebRTCSessionDescription); String type(); void setType(const String&, ExceptionState&); @@ -55,6 +55,8 @@ public: blink::WebRTCSessionDescription webSessionDescription(); + void trace(Visitor*) { } + private: explicit RTCSessionDescription(blink::WebRTCSessionDescription); diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.idl b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.idl index c906381b577..6aaf55e3b51 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescription.idl @@ -29,6 +29,7 @@ */ [ + WillBeGarbageCollected, Constructor(optional Dictionary descriptionInitDict), RaisesException=Constructor ] interface RTCSessionDescription { diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescriptionRequestImpl.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescriptionRequestImpl.cpp index 6183b7457ed..b81e4b428c8 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescriptionRequestImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescriptionRequestImpl.cpp @@ -37,21 +37,24 @@ #include "modules/mediastream/RTCSessionDescription.h" #include "modules/mediastream/RTCSessionDescriptionCallback.h" #include "public/platform/WebRTCSessionDescription.h" +#include "wtf/RefPtr.h" namespace WebCore { -PassRefPtr<RTCSessionDescriptionRequestImpl> RTCSessionDescriptionRequestImpl::create(ExecutionContext* context, PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback) +PassRefPtr<RTCSessionDescriptionRequestImpl> RTCSessionDescriptionRequestImpl::create(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback) { - RefPtr<RTCSessionDescriptionRequestImpl> request = adoptRef(new RTCSessionDescriptionRequestImpl(context, successCallback, errorCallback)); + RefPtr<RTCSessionDescriptionRequestImpl> request = adoptRef(new RTCSessionDescriptionRequestImpl(context, requester, successCallback, errorCallback)); request->suspendIfNeeded(); return request.release(); } -RTCSessionDescriptionRequestImpl::RTCSessionDescriptionRequestImpl(ExecutionContext* context, PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback) +RTCSessionDescriptionRequestImpl::RTCSessionDescriptionRequestImpl(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback) : ActiveDOMObject(context) , m_successCallback(successCallback) , m_errorCallback(errorCallback) + , m_requester(requester) { + ASSERT(m_requester); } RTCSessionDescriptionRequestImpl::~RTCSessionDescriptionRequestImpl() @@ -60,8 +63,9 @@ RTCSessionDescriptionRequestImpl::~RTCSessionDescriptionRequestImpl() void RTCSessionDescriptionRequestImpl::requestSucceeded(const blink::WebRTCSessionDescription& webSessionDescription) { - if (m_successCallback) { - RefPtr<RTCSessionDescription> sessionDescription = RTCSessionDescription::create(webSessionDescription); + bool shouldFireCallback = m_requester ? m_requester->shouldFireDefaultCallbacks() : false; + if (shouldFireCallback && m_successCallback) { + RefPtrWillBeRawPtr<RTCSessionDescription> sessionDescription = RTCSessionDescription::create(webSessionDescription); m_successCallback->handleEvent(sessionDescription.get()); } @@ -70,7 +74,8 @@ void RTCSessionDescriptionRequestImpl::requestSucceeded(const blink::WebRTCSessi void RTCSessionDescriptionRequestImpl::requestFailed(const String& error) { - if (m_errorCallback) + bool shouldFireCallback = m_requester ? m_requester->shouldFireDefaultCallbacks() : false; + if (shouldFireCallback && m_errorCallback) m_errorCallback->handleEvent(error); clear(); @@ -85,6 +90,7 @@ void RTCSessionDescriptionRequestImpl::clear() { m_successCallback.clear(); m_errorCallback.clear(); + m_requester.clear(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescriptionRequestImpl.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescriptionRequestImpl.h index 3d383ecbf37..a58d7403973 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescriptionRequestImpl.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCSessionDescriptionRequestImpl.h @@ -32,7 +32,10 @@ #define RTCSessionDescriptionRequestImpl_h #include "core/dom/ActiveDOMObject.h" +#include "platform/heap/Handle.h" #include "platform/mediastream/RTCSessionDescriptionRequest.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/PassRefPtr.h" namespace blink { class WebRTCSessionDescription; @@ -44,9 +47,9 @@ class RTCErrorCallback; class RTCPeerConnection; class RTCSessionDescriptionCallback; -class RTCSessionDescriptionRequestImpl : public RTCSessionDescriptionRequest, public ActiveDOMObject { +class RTCSessionDescriptionRequestImpl FINAL : public RTCSessionDescriptionRequest, public ActiveDOMObject { public: - static PassRefPtr<RTCSessionDescriptionRequestImpl> create(ExecutionContext*, PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>); + static PassRefPtr<RTCSessionDescriptionRequestImpl> create(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>); virtual ~RTCSessionDescriptionRequestImpl(); virtual void requestSucceeded(const blink::WebRTCSessionDescription&) OVERRIDE; @@ -56,16 +59,16 @@ public: virtual void stop() OVERRIDE; private: - RTCSessionDescriptionRequestImpl(ExecutionContext*, PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>); + RTCSessionDescriptionRequestImpl(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>); void clear(); OwnPtr<RTCSessionDescriptionCallback> m_successCallback; OwnPtr<RTCErrorCallback> m_errorCallback; + + RefPtrWillBePersistent<RTCPeerConnection> m_requester; }; } // namespace WebCore #endif // RTCSessionDescriptionRequestImpl_h - - diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.cpp index 303ee9c8ee4..34d0e59a586 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.cpp @@ -30,9 +30,9 @@ namespace WebCore { -PassRefPtr<RTCStatsReport> RTCStatsReport::create(const String& id, const String& type, double timestamp) +PassRefPtrWillBeRawPtr<RTCStatsReport> RTCStatsReport::create(const String& id, const String& type, double timestamp) { - return adoptRef(new RTCStatsReport(id, type, timestamp)); + return adoptRefWillBeNoop(new RTCStatsReport(id, type, timestamp)); } RTCStatsReport::RTCStatsReport(const String& id, const String& type, double timestamp) @@ -52,12 +52,12 @@ Vector<String> RTCStatsReport::names() const return result; } -const PassRefPtr<RTCStatsReport> RTCStatsReport::local() +const PassRefPtrWillBeRawPtr<RTCStatsReport> RTCStatsReport::local() { return this; } -const PassRefPtr<RTCStatsReport> RTCStatsReport::remote() +const PassRefPtrWillBeRawPtr<RTCStatsReport> RTCStatsReport::remote() { return this; } diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.h index 289f0cbf0ba..9b23ab52400 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.h @@ -35,9 +35,9 @@ namespace WebCore { -class RTCStatsReport : public RefCounted<RTCStatsReport>, public ScriptWrappable { +class RTCStatsReport FINAL : public RefCountedWillBeGarbageCollectedFinalized<RTCStatsReport>, public ScriptWrappable { public: - static PassRefPtr<RTCStatsReport> create(const String& id, const String& type, double timestamp); + static PassRefPtrWillBeRawPtr<RTCStatsReport> create(const String& id, const String& type, double timestamp); double timestamp() const { return m_timestamp; } String id() { return m_id; } @@ -46,12 +46,14 @@ public: Vector<String> names() const; // DEPRECATED - const PassRefPtr<RTCStatsReport> local(); + const PassRefPtrWillBeRawPtr<RTCStatsReport> local(); // DEPRECATED - const PassRefPtr<RTCStatsReport> remote(); + const PassRefPtrWillBeRawPtr<RTCStatsReport> remote(); void addStatistic(const String& name, const String& value); + void trace(Visitor*) { } + private: RTCStatsReport(const String& id, const String& type, double timestamp); diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.idl b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.idl index 15c193beba5..2fdce08aaf2 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsReport.idl @@ -23,6 +23,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface RTCStatsReport { readonly attribute Date timestamp; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsRequestImpl.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsRequestImpl.cpp index 109cd6c0773..d53e7a6543a 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsRequestImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsRequestImpl.cpp @@ -27,42 +27,39 @@ #include "modules/mediastream/RTCStatsRequestImpl.h" #include "modules/mediastream/MediaStreamTrack.h" +#include "modules/mediastream/RTCPeerConnection.h" #include "modules/mediastream/RTCStatsCallback.h" namespace WebCore { -PassRefPtr<RTCStatsRequestImpl> RTCStatsRequestImpl::create(ExecutionContext* context, PassOwnPtr<RTCStatsCallback> callback, PassRefPtr<MediaStreamTrack> selector) +PassRefPtr<RTCStatsRequestImpl> RTCStatsRequestImpl::create(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<RTCStatsCallback> callback, PassRefPtr<MediaStreamTrack> selector) { - RefPtr<RTCStatsRequestImpl> request = adoptRef(new RTCStatsRequestImpl(context, callback, selector)); + RefPtr<RTCStatsRequestImpl> request = adoptRef(new RTCStatsRequestImpl(context, requester, callback, selector)); request->suspendIfNeeded(); return request.release(); } -RTCStatsRequestImpl::RTCStatsRequestImpl(ExecutionContext* context, PassOwnPtr<RTCStatsCallback> callback, PassRefPtr<MediaStreamTrack> selector) +RTCStatsRequestImpl::RTCStatsRequestImpl(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<RTCStatsCallback> callback, PassRefPtr<MediaStreamTrack> selector) : ActiveDOMObject(context) , m_successCallback(callback) - , m_stream(selector ? selector->component()->stream() : 0) , m_component(selector ? selector->component() : 0) + , m_requester(requester) { + ASSERT(m_requester); } RTCStatsRequestImpl::~RTCStatsRequestImpl() { } -PassRefPtr<RTCStatsResponseBase> RTCStatsRequestImpl::createResponse() +PassRefPtrWillBeRawPtr<RTCStatsResponseBase> RTCStatsRequestImpl::createResponse() { return RTCStatsResponse::create(); } bool RTCStatsRequestImpl::hasSelector() { - return m_stream; -} - -MediaStreamDescriptor* RTCStatsRequestImpl::stream() -{ - return m_stream.get(); + return m_component; } MediaStreamComponent* RTCStatsRequestImpl::component() @@ -70,11 +67,11 @@ MediaStreamComponent* RTCStatsRequestImpl::component() return m_component.get(); } -void RTCStatsRequestImpl::requestSucceeded(PassRefPtr<RTCStatsResponseBase> response) +void RTCStatsRequestImpl::requestSucceeded(PassRefPtrWillBeRawPtr<RTCStatsResponseBase> response) { - if (!m_successCallback) - return; - m_successCallback->handleEvent(static_cast<RTCStatsResponse*>(response.get())); + bool shouldFireCallback = m_requester ? m_requester->shouldFireGetStatsCallback() : false; + if (shouldFireCallback && m_successCallback) + m_successCallback->handleEvent(static_cast<RTCStatsResponse*>(response.get())); clear(); } @@ -86,7 +83,7 @@ void RTCStatsRequestImpl::stop() void RTCStatsRequestImpl::clear() { m_successCallback.clear(); + m_requester.clear(); } - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsRequestImpl.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsRequestImpl.h index 14afa161182..b0d8a24f383 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsRequestImpl.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsRequestImpl.h @@ -26,8 +26,9 @@ #define RTCStatsRequestImpl_h #include "core/dom/ActiveDOMObject.h" -#include "core/platform/mediastream/RTCStatsRequest.h" #include "modules/mediastream/RTCStatsResponse.h" +#include "platform/heap/Handle.h" +#include "platform/mediastream/RTCStatsRequest.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" @@ -35,31 +36,32 @@ namespace WebCore { class MediaStreamTrack; +class RTCPeerConnection; class RTCStatsCallback; -class RTCStatsRequestImpl : public RTCStatsRequest, public ActiveDOMObject { +class RTCStatsRequestImpl FINAL : public RTCStatsRequest, public ActiveDOMObject { public: - static PassRefPtr<RTCStatsRequestImpl> create(ExecutionContext*, PassOwnPtr<RTCStatsCallback>, PassRefPtr<MediaStreamTrack>); + static PassRefPtr<RTCStatsRequestImpl> create(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<RTCStatsCallback>, PassRefPtr<MediaStreamTrack>); virtual ~RTCStatsRequestImpl(); - virtual PassRefPtr<RTCStatsResponseBase> createResponse() OVERRIDE; + virtual PassRefPtrWillBeRawPtr<RTCStatsResponseBase> createResponse() OVERRIDE; virtual bool hasSelector() OVERRIDE; - virtual MediaStreamDescriptor* stream() OVERRIDE; virtual MediaStreamComponent* component() OVERRIDE; - virtual void requestSucceeded(PassRefPtr<RTCStatsResponseBase>) OVERRIDE; + virtual void requestSucceeded(PassRefPtrWillBeRawPtr<RTCStatsResponseBase>) OVERRIDE; // ActiveDOMObject virtual void stop() OVERRIDE; private: - RTCStatsRequestImpl(ExecutionContext*, PassOwnPtr<RTCStatsCallback>, PassRefPtr<MediaStreamTrack>); + RTCStatsRequestImpl(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<RTCStatsCallback>, PassRefPtr<MediaStreamTrack>); void clear(); OwnPtr<RTCStatsCallback> m_successCallback; - RefPtr<MediaStreamDescriptor> m_stream; RefPtr<MediaStreamComponent> m_component; + + RefPtrWillBePersistent<RTCPeerConnection> m_requester; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.cpp index 7da82b1c9d3..1d32ab49d08 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.cpp @@ -28,9 +28,9 @@ namespace WebCore { -PassRefPtr<RTCStatsResponse> RTCStatsResponse::create() +PassRefPtrWillBeRawPtr<RTCStatsResponse> RTCStatsResponse::create() { - return adoptRef(new RTCStatsResponse()); + return adoptRefWillBeNoop(new RTCStatsResponse()); } RTCStatsResponse::RTCStatsResponse() @@ -38,11 +38,11 @@ RTCStatsResponse::RTCStatsResponse() ScriptWrappable::init(this); } -PassRefPtr<RTCStatsReport> RTCStatsResponse::namedItem(const AtomicString& name) +PassRefPtrWillBeRawPtr<RTCStatsReport> RTCStatsResponse::namedItem(const AtomicString& name) { if (m_idmap.find(name) != m_idmap.end()) return m_result[m_idmap.get(name)]; - return 0; + return nullptr; } size_t RTCStatsResponse::addReport(String id, String type, double timestamp) @@ -58,4 +58,10 @@ void RTCStatsResponse::addStatistic(size_t report, String name, String value) m_result[report]->addStatistic(name, value); } +void RTCStatsResponse::trace(Visitor* visitor) +{ + visitor->trace(m_result); + RTCStatsResponseBase::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.h index 0e1e5d02b45..e8313900f06 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.h @@ -27,6 +27,7 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/mediastream/RTCStatsReport.h" +#include "platform/heap/Handle.h" #include "platform/mediastream/RTCStatsResponseBase.h" #include "wtf/HashMap.h" #include "wtf/Vector.h" @@ -34,20 +35,22 @@ namespace WebCore { -class RTCStatsResponse : public RTCStatsResponseBase, public ScriptWrappable { +class RTCStatsResponse FINAL : public RTCStatsResponseBase, public ScriptWrappable { public: - static PassRefPtr<RTCStatsResponse> create(); + static PassRefPtrWillBeRawPtr<RTCStatsResponse> create(); - const Vector<RefPtr<RTCStatsReport> >& result() const { return m_result; }; + const WillBeHeapVector<RefPtrWillBeMember<RTCStatsReport> >& result() const { return m_result; } - PassRefPtr<RTCStatsReport> namedItem(const AtomicString& name); + PassRefPtrWillBeRawPtr<RTCStatsReport> namedItem(const AtomicString& name); virtual size_t addReport(String id, String type, double timestamp) OVERRIDE; virtual void addStatistic(size_t report, String name, String value) OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: RTCStatsResponse(); - Vector<RefPtr<RTCStatsReport> > m_result; + WillBeHeapVector<RefPtrWillBeMember<RTCStatsReport> > m_result; HashMap<String, int> m_idmap; }; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.idl b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.idl index edc759a6d8a..5e8a53b7565 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCStatsResponse.idl @@ -23,6 +23,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface RTCStatsResponse { sequence<RTCStatsReport> result(); diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCVoidRequestImpl.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/RTCVoidRequestImpl.cpp index f8422d76e37..8393cedca10 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCVoidRequestImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCVoidRequestImpl.cpp @@ -38,18 +38,20 @@ namespace WebCore { -PassRefPtr<RTCVoidRequestImpl> RTCVoidRequestImpl::create(ExecutionContext* context, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback) +PassRefPtr<RTCVoidRequestImpl> RTCVoidRequestImpl::create(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback) { - RefPtr<RTCVoidRequestImpl> request = adoptRef(new RTCVoidRequestImpl(context, successCallback, errorCallback)); + RefPtr<RTCVoidRequestImpl> request = adoptRef(new RTCVoidRequestImpl(context, requester, successCallback, errorCallback)); request->suspendIfNeeded(); return request.release(); } -RTCVoidRequestImpl::RTCVoidRequestImpl(ExecutionContext* context, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback) +RTCVoidRequestImpl::RTCVoidRequestImpl(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback) : ActiveDOMObject(context) , m_successCallback(successCallback) , m_errorCallback(errorCallback) + , m_requester(requester) { + ASSERT(m_requester); } RTCVoidRequestImpl::~RTCVoidRequestImpl() @@ -58,7 +60,8 @@ RTCVoidRequestImpl::~RTCVoidRequestImpl() void RTCVoidRequestImpl::requestSucceeded() { - if (m_successCallback) + bool shouldFireCallback = m_requester ? m_requester->shouldFireDefaultCallbacks() : false; + if (shouldFireCallback && m_successCallback) m_successCallback->handleEvent(); clear(); @@ -66,7 +69,8 @@ void RTCVoidRequestImpl::requestSucceeded() void RTCVoidRequestImpl::requestFailed(const String& error) { - if (m_errorCallback.get()) + bool shouldFireCallback = m_requester ? m_requester->shouldFireDefaultCallbacks() : false; + if (shouldFireCallback && m_errorCallback.get()) m_errorCallback->handleEvent(error); clear(); @@ -81,6 +85,7 @@ void RTCVoidRequestImpl::clear() { m_successCallback.clear(); m_errorCallback.clear(); + m_requester.clear(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/RTCVoidRequestImpl.h b/chromium/third_party/WebKit/Source/modules/mediastream/RTCVoidRequestImpl.h index 1db483fe294..704644891b1 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/RTCVoidRequestImpl.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/RTCVoidRequestImpl.h @@ -32,35 +32,38 @@ #define RTCVoidRequestImpl_h #include "core/dom/ActiveDOMObject.h" +#include "platform/heap/Handle.h" #include "platform/mediastream/RTCVoidRequest.h" namespace WebCore { class RTCErrorCallback; +class RTCPeerConnection; class VoidCallback; -class RTCVoidRequestImpl : public RTCVoidRequest, public ActiveDOMObject { +class RTCVoidRequestImpl FINAL : public RTCVoidRequest, public ActiveDOMObject { public: - static PassRefPtr<RTCVoidRequestImpl> create(ExecutionContext*, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>); + static PassRefPtr<RTCVoidRequestImpl> create(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>); virtual ~RTCVoidRequestImpl(); - virtual void requestSucceeded(); - virtual void requestFailed(const String& error); + // RTCVoidRequest + virtual void requestSucceeded() OVERRIDE; + virtual void requestFailed(const String& error) OVERRIDE; // ActiveDOMObject virtual void stop() OVERRIDE; private: - RTCVoidRequestImpl(ExecutionContext*, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>); + RTCVoidRequestImpl(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>); void clear(); OwnPtr<VoidCallback> m_successCallback; OwnPtr<RTCErrorCallback> m_errorCallback; + + RefPtrWillBePersistent<RTCPeerConnection> m_requester; }; } // namespace WebCore #endif // RTCVoidRequestImpl_h - - diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.cpp index be8dfc2561a..8a6ee176280 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.cpp @@ -30,10 +30,10 @@ namespace WebCore { -PassRefPtr<SourceInfo> SourceInfo::create(const blink::WebSourceInfo& webSourceInfo) +PassRefPtrWillBeRawPtr<SourceInfo> SourceInfo::create(const blink::WebSourceInfo& webSourceInfo) { ASSERT(!webSourceInfo.isNull()); - return adoptRef(new SourceInfo(webSourceInfo)); + return adoptRefWillBeNoop(new SourceInfo(webSourceInfo)); } SourceInfo::SourceInfo(const blink::WebSourceInfo& webSourceInfo) diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.h b/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.h index 57349887efa..4cb0becbbd3 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.h @@ -34,22 +34,24 @@ namespace WebCore { -class SourceInfo : public RefCounted<SourceInfo>, public ScriptWrappable { +class SourceInfo : public RefCountedWillBeGarbageCollectedFinalized<SourceInfo>, public ScriptWrappable { public: - static PassRefPtr<SourceInfo> create(const blink::WebSourceInfo&); + static PassRefPtrWillBeRawPtr<SourceInfo> create(const blink::WebSourceInfo&); String id() const; String kind() const; String label() const; String facing() const; + void trace(Visitor*) { } + private: explicit SourceInfo(const blink::WebSourceInfo&); blink::WebSourceInfo m_webSourceInfo; }; -typedef Vector<RefPtr<SourceInfo> > SourceInfoVector; +typedef WillBeHeapVector<RefPtrWillBeMember<SourceInfo> > SourceInfoVector; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.idl b/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.idl index 814dd65cc4d..8913dd5f8fe 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/SourceInfo.idl @@ -24,6 +24,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface SourceInfo { readonly attribute DOMString id; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/URLMediaStream.idl b/chromium/third_party/WebKit/Source/modules/mediastream/URLMediaStream.idl index d6d36cfd83b..0e9b64b826c 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/URLMediaStream.idl +++ b/chromium/third_party/WebKit/Source/modules/mediastream/URLMediaStream.idl @@ -27,6 +27,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +// http://www.w3.org/TR/mediacapture-streams/#idl-def-URL + partial interface URL { - [CallWith=ExecutionContext,TreatReturnedNullStringAs=Null] static DOMString createObjectURL(MediaStream? stream); + [CallWith=ExecutionContext, TreatReturnedNullStringAs=Null] static DOMString createObjectURL(MediaStream stream); }; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaClient.h b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaClient.h index 891f0dc11e4..164744fbda6 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaClient.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaClient.h @@ -31,23 +31,26 @@ #ifndef UserMediaClient_h #define UserMediaClient_h +#include "modules/mediastream/MediaDevicesRequest.h" #include "modules/mediastream/UserMediaRequest.h" #include "wtf/text/WTFString.h" namespace WebCore { -class Page; +class LocalFrame; class UserMediaClient { public: - virtual void requestUserMedia(PassRefPtr<UserMediaRequest>) = 0; + virtual void requestUserMedia(PassRefPtrWillBeRawPtr<UserMediaRequest>) = 0; virtual void cancelUserMediaRequest(UserMediaRequest*) = 0; + virtual void requestMediaDevices(PassRefPtrWillBeRawPtr<MediaDevicesRequest>) = 0; + virtual void cancelMediaDevicesRequest(MediaDevicesRequest*) = 0; protected: virtual ~UserMediaClient() { } }; -void provideUserMediaTo(Page*, UserMediaClient*); +void provideUserMediaTo(LocalFrame&, UserMediaClient*); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaController.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaController.cpp index b7350f6fc59..0ddca86086d 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaController.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaController.cpp @@ -37,18 +37,16 @@ UserMediaController::UserMediaController(UserMediaClient* client) { } -UserMediaController::~UserMediaController() -{ -} +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(UserMediaController) -PassOwnPtr<UserMediaController> UserMediaController::create(UserMediaClient* client) +PassOwnPtrWillBeRawPtr<UserMediaController> UserMediaController::create(UserMediaClient* client) { - return adoptPtr(new UserMediaController(client)); + return adoptPtrWillBeNoop(new UserMediaController(client)); } -void provideUserMediaTo(Page* page, UserMediaClient* client) +void provideUserMediaTo(LocalFrame& frame, UserMediaClient* client) { - UserMediaController::provideTo(page, UserMediaController::supplementName(), UserMediaController::create(client)); + UserMediaController::provideTo(frame, UserMediaController::supplementName(), UserMediaController::create(client)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaController.h b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaController.h index 6ca42021102..c751f0fd8c4 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaController.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaController.h @@ -25,25 +25,33 @@ #ifndef UserMediaController_h #define UserMediaController_h -#include "core/page/Page.h" +#include "core/frame/LocalFrame.h" #include "modules/mediastream/UserMediaClient.h" #include "wtf/PassOwnPtr.h" namespace WebCore { +class MediaDevicesRequest; class UserMediaRequest; -class UserMediaController : public Supplement<Page> { +class UserMediaController FINAL : public NoBaseWillBeGarbageCollected<UserMediaController>, public WillBeHeapSupplement<LocalFrame> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(UserMediaController); + DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(UserMediaController); public: - ~UserMediaController(); UserMediaClient* client() const { return m_client; } - void requestUserMedia(PassRefPtr<UserMediaRequest>); + + void requestUserMedia(PassRefPtrWillBeRawPtr<UserMediaRequest>); void cancelUserMediaRequest(UserMediaRequest*); - static PassOwnPtr<UserMediaController> create(UserMediaClient*); + void requestMediaDevices(PassRefPtrWillBeRawPtr<MediaDevicesRequest>); + void cancelMediaDevicesRequest(MediaDevicesRequest*); + + static PassOwnPtrWillBeRawPtr<UserMediaController> create(UserMediaClient*); static const char* supplementName(); - static UserMediaController* from(Page* page) { return static_cast<UserMediaController*>(Supplement<Page>::from(page, supplementName())); } + static UserMediaController* from(LocalFrame* frame) { return static_cast<UserMediaController*>(WillBeHeapSupplement<LocalFrame>::from(frame, supplementName())); } + + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<LocalFrame>::trace(visitor); } protected: explicit UserMediaController(UserMediaClient*); @@ -52,7 +60,7 @@ private: UserMediaClient* m_client; }; -inline void UserMediaController::requestUserMedia(PassRefPtr<UserMediaRequest> request) +inline void UserMediaController::requestUserMedia(PassRefPtrWillBeRawPtr<UserMediaRequest> request) { m_client->requestUserMedia(request); } @@ -62,6 +70,16 @@ inline void UserMediaController::cancelUserMediaRequest(UserMediaRequest* reques m_client->cancelUserMediaRequest(request); } +inline void UserMediaController::requestMediaDevices(PassRefPtrWillBeRawPtr<MediaDevicesRequest> request) +{ + m_client->requestMediaDevices(request); +} + +inline void UserMediaController::cancelMediaDevicesRequest(MediaDevicesRequest* request) +{ + m_client->cancelMediaDevicesRequest(request); +} + } // namespace WebCore #endif // UserMediaController_h diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp index 66610c342f7..b543af093fb 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp +++ b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp @@ -34,20 +34,22 @@ #include "modules/mediastream/UserMediaRequest.h" #include "bindings/v8/Dictionary.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/Document.h" +#include "core/dom/ExceptionCode.h" #include "core/dom/SpaceSplitString.h" -#include "core/platform/mediastream/MediaStreamCenter.h" -#include "core/platform/mediastream/MediaStreamDescriptor.h" #include "modules/mediastream/MediaConstraintsImpl.h" #include "modules/mediastream/MediaStream.h" #include "modules/mediastream/UserMediaController.h" +#include "platform/mediastream/MediaStreamCenter.h" +#include "platform/mediastream/MediaStreamDescriptor.h" namespace WebCore { -static PassRefPtr<MediaConstraintsImpl> parseOptions(const Dictionary& options, const String& mediaType, ExceptionState& exceptionState) +static blink::WebMediaConstraints parseOptions(const Dictionary& options, const String& mediaType, ExceptionState& exceptionState) { - RefPtr<MediaConstraintsImpl> constraints; + blink::WebMediaConstraints constraints; Dictionary constraintsDictionary; bool ok = options.get(mediaType, constraintsDictionary); @@ -60,26 +62,28 @@ static PassRefPtr<MediaConstraintsImpl> parseOptions(const Dictionary& options, constraints = MediaConstraintsImpl::create(); } - return constraints.release(); + return constraints; } -PassRefPtr<UserMediaRequest> UserMediaRequest::create(ExecutionContext* context, UserMediaController* controller, const Dictionary& options, PassOwnPtr<NavigatorUserMediaSuccessCallback> successCallback, PassOwnPtr<NavigatorUserMediaErrorCallback> errorCallback, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<UserMediaRequest> UserMediaRequest::create(ExecutionContext* context, UserMediaController* controller, const Dictionary& options, PassOwnPtr<NavigatorUserMediaSuccessCallback> successCallback, PassOwnPtr<NavigatorUserMediaErrorCallback> errorCallback, ExceptionState& exceptionState) { - RefPtr<MediaConstraintsImpl> audio = parseOptions(options, "audio", exceptionState); + blink::WebMediaConstraints audio = parseOptions(options, "audio", exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; - RefPtr<MediaConstraintsImpl> video = parseOptions(options, "video", exceptionState); + blink::WebMediaConstraints video = parseOptions(options, "video", exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; - if (!audio && !video) - return 0; + if (audio.isNull() && video.isNull()) { + exceptionState.throwDOMException(SyntaxError, "At least one of audio and video must be requested"); + return nullptr; + } - return adoptRef(new UserMediaRequest(context, controller, audio.release(), video.release(), successCallback, errorCallback)); + return adoptRefWillBeNoop(new UserMediaRequest(context, controller, audio, video, successCallback, errorCallback)); } -UserMediaRequest::UserMediaRequest(ExecutionContext* context, UserMediaController* controller, PassRefPtr<MediaConstraintsImpl> audio, PassRefPtr<MediaConstraintsImpl> video, PassOwnPtr<NavigatorUserMediaSuccessCallback> successCallback, PassOwnPtr<NavigatorUserMediaErrorCallback> errorCallback) +UserMediaRequest::UserMediaRequest(ExecutionContext* context, UserMediaController* controller, blink::WebMediaConstraints audio, blink::WebMediaConstraints video, PassOwnPtr<NavigatorUserMediaSuccessCallback> successCallback, PassOwnPtr<NavigatorUserMediaErrorCallback> errorCallback) : ContextLifecycleObserver(context) , m_audio(audio) , m_video(video) @@ -95,22 +99,22 @@ UserMediaRequest::~UserMediaRequest() bool UserMediaRequest::audio() const { - return m_audio; + return !m_audio.isNull(); } bool UserMediaRequest::video() const { - return m_video; + return !m_video.isNull(); } -MediaConstraints* UserMediaRequest::audioConstraints() const +blink::WebMediaConstraints UserMediaRequest::audioConstraints() const { - return m_audio.get(); + return m_audio; } -MediaConstraints* UserMediaRequest::videoConstraints() const +blink::WebMediaConstraints UserMediaRequest::videoConstraints() const { - return m_video.get(); + return m_video; } Document* UserMediaRequest::ownerDocument() @@ -133,7 +137,7 @@ void UserMediaRequest::succeed(PassRefPtr<MediaStreamDescriptor> streamDescripto if (!executionContext()) return; - RefPtr<MediaStream> stream = MediaStream::create(executionContext(), streamDescriptor); + RefPtrWillBeRawPtr<MediaStream> stream = MediaStream::create(executionContext(), streamDescriptor); MediaStreamTrackVector audioTracks = stream->getAudioTracks(); for (MediaStreamTrackVector::iterator iter = audioTracks.begin(); iter != audioTracks.end(); ++iter) { @@ -148,32 +152,38 @@ void UserMediaRequest::succeed(PassRefPtr<MediaStreamDescriptor> streamDescripto m_successCallback->handleEvent(stream.get()); } -void UserMediaRequest::fail(const String& description) +void UserMediaRequest::failPermissionDenied(const String& message) { if (!executionContext()) return; - if (m_errorCallback) { - RefPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create(NavigatorUserMediaError::NamePermissionDenied, description, String()); - m_errorCallback->handleEvent(error.get()); - } + RefPtrWillBeRawPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create(NavigatorUserMediaError::NamePermissionDenied, message, String()); + m_errorCallback->handleEvent(error.get()); } -void UserMediaRequest::failConstraint(const String& constraintName, const String& description) +void UserMediaRequest::failConstraint(const String& constraintName, const String& message) { ASSERT(!constraintName.isEmpty()); if (!executionContext()) return; - if (m_errorCallback) { - RefPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create(NavigatorUserMediaError::NameConstraintNotSatisfied, description, constraintName); - m_errorCallback->handleEvent(error.get()); - } + RefPtrWillBeRawPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create(NavigatorUserMediaError::NameConstraintNotSatisfied, message, constraintName); + m_errorCallback->handleEvent(error.get()); +} + +void UserMediaRequest::failUASpecific(const String& name, const String& message, const String& constraintName) +{ + ASSERT(!name.isEmpty()); + if (!executionContext()) + return; + + RefPtrWillBeRawPtr<NavigatorUserMediaError> error = NavigatorUserMediaError::create(name, message, constraintName); + m_errorCallback->handleEvent(error.get()); } void UserMediaRequest::contextDestroyed() { - RefPtr<UserMediaRequest> protect(this); + RefPtrWillBeRawPtr<UserMediaRequest> protect(this); if (m_controller) { m_controller->cancelUserMediaRequest(this); diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.h b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.h index 8ad62dd4744..b5bf69f33bc 100644 --- a/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.h +++ b/chromium/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.h @@ -35,6 +35,7 @@ #include "modules/mediastream/NavigatorUserMediaErrorCallback.h" #include "modules/mediastream/NavigatorUserMediaSuccessCallback.h" #include "platform/mediastream/MediaStreamSource.h" +#include "public/platform/WebMediaConstraints.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" @@ -44,15 +45,13 @@ namespace WebCore { class Dictionary; class Document; class ExceptionState; -class MediaConstraints; -class MediaConstraintsImpl; class MediaStreamDescriptor; class UserMediaController; -class UserMediaRequest : public RefCounted<UserMediaRequest>, public ContextLifecycleObserver { +class UserMediaRequest FINAL : public RefCountedWillBeGarbageCollectedFinalized<UserMediaRequest>, public ContextLifecycleObserver { public: - static PassRefPtr<UserMediaRequest> create(ExecutionContext*, UserMediaController*, const Dictionary& options, PassOwnPtr<NavigatorUserMediaSuccessCallback>, PassOwnPtr<NavigatorUserMediaErrorCallback>, ExceptionState&); - ~UserMediaRequest(); + static PassRefPtrWillBeRawPtr<UserMediaRequest> create(ExecutionContext*, UserMediaController*, const Dictionary& options, PassOwnPtr<NavigatorUserMediaSuccessCallback>, PassOwnPtr<NavigatorUserMediaErrorCallback>, ExceptionState&); + virtual ~UserMediaRequest(); NavigatorUserMediaSuccessCallback* successCallback() const { return m_successCallback.get(); } NavigatorUserMediaErrorCallback* errorCallback() const { return m_errorCallback.get(); } @@ -61,22 +60,25 @@ public: void start(); void succeed(PassRefPtr<MediaStreamDescriptor>); - void fail(const String& description); - void failConstraint(const String& constraintName, const String& description); + void failPermissionDenied(const String& message); + void failConstraint(const String& constraintName, const String& message); + void failUASpecific(const String& name, const String& message, const String& constraintName); bool audio() const; bool video() const; - MediaConstraints* audioConstraints() const; - MediaConstraints* videoConstraints() const; + blink::WebMediaConstraints audioConstraints() const; + blink::WebMediaConstraints videoConstraints() const; // ContextLifecycleObserver - virtual void contextDestroyed(); + virtual void contextDestroyed() OVERRIDE; + + void trace(Visitor*) { } private: - UserMediaRequest(ExecutionContext*, UserMediaController*, PassRefPtr<MediaConstraintsImpl> audio, PassRefPtr<MediaConstraintsImpl> video, PassOwnPtr<NavigatorUserMediaSuccessCallback>, PassOwnPtr<NavigatorUserMediaErrorCallback>); + UserMediaRequest(ExecutionContext*, UserMediaController*, blink::WebMediaConstraints audio, blink::WebMediaConstraints video, PassOwnPtr<NavigatorUserMediaSuccessCallback>, PassOwnPtr<NavigatorUserMediaErrorCallback>); - RefPtr<MediaConstraintsImpl> m_audio; - RefPtr<MediaConstraintsImpl> m_video; + blink::WebMediaConstraints m_audio; + blink::WebMediaConstraints m_video; UserMediaController* m_controller; diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/WebMediaStreamTrackSourcesRequest.cpp b/chromium/third_party/WebKit/Source/modules/mediastream/WebMediaStreamTrackSourcesRequest.cpp deleted file mode 100644 index bf2f972caad..00000000000 --- a/chromium/third_party/WebKit/Source/modules/mediastream/WebMediaStreamTrackSourcesRequest.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "public/platform/WebMediaStreamTrackSourcesRequest.h" - -#include "modules/mediastream/MediaStreamTrackSourcesRequest.h" -#include "public/platform/WebSourceInfo.h" -#include "wtf/PassOwnPtr.h" - -using namespace WebCore; - -namespace blink { - -namespace { - -class ExtraDataContainer : public MediaStreamTrackSourcesRequest::ExtraData { -public: - ExtraDataContainer(WebMediaStreamTrackSourcesRequest::ExtraData* extraData) : m_extraData(adoptPtr(extraData)) { } - - WebMediaStreamTrackSourcesRequest::ExtraData* extraData() { return m_extraData.get(); } - -private: - OwnPtr<WebMediaStreamTrackSourcesRequest::ExtraData> m_extraData; -}; - -} // namespace - -WebMediaStreamTrackSourcesRequest::WebMediaStreamTrackSourcesRequest(const PassRefPtr<MediaStreamTrackSourcesRequest>& request) - : m_private(request) -{ -} - -void WebMediaStreamTrackSourcesRequest::assign(const WebMediaStreamTrackSourcesRequest& other) -{ - m_private = other.m_private; -} - -void WebMediaStreamTrackSourcesRequest::reset() -{ - m_private.reset(); -} - -WebString WebMediaStreamTrackSourcesRequest::origin() const -{ - ASSERT(m_private.get()); - return m_private->origin(); -} - -void WebMediaStreamTrackSourcesRequest::requestSucceeded(const WebVector<WebSourceInfo>& sourceInfos) const -{ - ASSERT(m_private.get()); - m_private->requestSucceeded(sourceInfos); -} - -WebMediaStreamTrackSourcesRequest::ExtraData* WebMediaStreamTrackSourcesRequest::extraData() const -{ - RefPtr<MediaStreamTrackSourcesRequest::ExtraData> data = m_private->extraData(); - if (!data) - return 0; - return static_cast<ExtraDataContainer*>(data.get())->extraData(); -} - -void WebMediaStreamTrackSourcesRequest::setExtraData(ExtraData* extraData) -{ - m_private->setExtraData(adoptRef(new ExtraDataContainer(extraData))); -} - -} // namespace blink - diff --git a/chromium/third_party/WebKit/Source/modules/mediastream/WindowMediaStream.idl b/chromium/third_party/WebKit/Source/modules/mediastream/WindowMediaStream.idl new file mode 100644 index 00000000000..f5b14fcdd43 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/mediastream/WindowMediaStream.idl @@ -0,0 +1,11 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + ImplementedAs=DOMWindowMediaStream, +] partial interface Window { + [RuntimeEnabled=MediaStream] attribute MediaStreamConstructor webkitMediaStream; + + [RuntimeEnabled=PeerConnection] attribute RTCPeerConnectionConstructor webkitRTCPeerConnection; +}; diff --git a/chromium/third_party/WebKit/Source/modules/modules.gni b/chromium/third_party/WebKit/Source/modules/modules.gni new file mode 100644 index 00000000000..0f69d83a693 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/modules.gni @@ -0,0 +1,50 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file is gn GN version of modules.gypi. + +blink_modules_output_dir = "$root_gen_dir/blink/modules" + +_gypi = exec_script( + "//build/gypi_to_gn.py", + [ rebase_path("modules.gypi"), + "--replace=<(SHARED_INTERMEDIATE_DIR)=$root_gen_dir", + "--replace=<(blink_modules_output_dir)=$blink_modules_output_dir" ], + "scope", + [ "modules.gypi" ]) + +_tmp_modules_idl_files = _gypi.modules_idl_files +# modules_idl_files has a magic variable in it that is an embedder hook, +# remove that since it's not a file (need to do this before rebasing). +_tmp_modules_idl_files -= [ + "<@(extra_blink_module_idl_files)", +] +modules_idl_files = get_path_info(_tmp_modules_idl_files, "abspath") + +# 'partial interface' or target (right side of) 'implements' +modules_dependency_idl_files = + get_path_info(_gypi.modules_dependency_idl_files, "abspath") + +modules_event_idl_files = + get_path_info(_gypi.modules_event_idl_files, "abspath") + +# interfaces that inherit from Event +generated_modules_files = + get_path_info(_gypi.generated_modules_files, "abspath") + +# Remove GYP variables from the list (need to do this before rebasing). +_tmp_modules_files = _gypi.modules_files +_tmp_modules_files -= [ + "<@(extra_blink_module_files)", + "<@(generated_modules_files)", +] +modules_files = get_path_info(_tmp_modules_files, "abspath") +modules_files += generated_modules_files # Account for GYP var expansion. + +# 'partial interface' or target (right side of) 'implements' +modules_testing_dependency_idl_files = + get_path_info(_gypi.modules_testing_dependency_idl_files, "abspath") + +modules_testing_files = get_path_info(_gypi.modules_testing_files, "abspath") +modules_unittest_files = get_path_info(_gypi.modules_unittest_files, "abspath") diff --git a/chromium/third_party/WebKit/Source/modules/modules.gyp b/chromium/third_party/WebKit/Source/modules/modules.gyp index 37dcf524e18..54427584d19 100644 --- a/chromium/third_party/WebKit/Source/modules/modules.gyp +++ b/chromium/third_party/WebKit/Source/modules/modules.gyp @@ -29,10 +29,13 @@ # { 'includes': [ + '../build/scripts/scripts.gypi', '../build/win/precompile.gypi', + '../bindings/modules/modules.gypi', # modules can depend on bindings/modules, but not on bindings 'modules.gypi', ], 'targets': [{ + # GN version: //third_party/WebKit/Source/modules:modules 'target_name': 'modules', 'type': 'static_library', 'dependencies': [ @@ -40,19 +43,108 @@ '<(DEPTH)/third_party/sqlite/sqlite.gyp:sqlite', '../config.gyp:config', '../core/core.gyp:webcore', + 'make_modules_generated', ], 'defines': [ 'BLINK_IMPLEMENTATION=1', 'INSIDE_BLINK', ], + 'include_dirs': [ + # FIXME: Remove these once scripts generate qualified + # includes correctly: http://crbug.com/380054 + '<(blink_core_output_dir)', + '<(blink_modules_output_dir)', + ], 'sources': [ '<@(modules_files)', + '<@(bindings_modules_v8_generated_aggregate_files)', + ], + 'actions': [ + { + # GN version: //third_party/WebKit/Source/modules:modules_fetch_polyfill + 'action_name': 'FetchPolyfill', + 'process_outputs_as_sources': 1, + 'variables': { + 'resources': [ + 'serviceworkers/polyfills/fetchPolyfill.js', + ], + }, + 'inputs': [ + '../build/scripts/make-file-arrays.py', + '<@(resources)', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/blink/FetchPolyfill.h', + '<(SHARED_INTERMEDIATE_DIR)/blink/FetchPolyfill.cpp', + ], + 'action': [ + 'python', + '../build/scripts/make-file-arrays.py', + '--out-h=<(SHARED_INTERMEDIATE_DIR)/blink/FetchPolyfill.h', + '--out-cpp=<(SHARED_INTERMEDIATE_DIR)/blink/FetchPolyfill.cpp', + '--namespace=WebCore', + '<@(resources)', + ], + }, + { + # GN version: //third_party/WebKit/Source/modules:modules_cache_polyfill + 'action_name': 'CachePolyfill', + 'process_outputs_as_sources': 1, + 'variables': { + 'resources': [ + 'serviceworkers/polyfills/cachePolyfill.js', + ], + }, + 'inputs': [ + '../build/scripts/make-file-arrays.py', + '<@(resources)', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/blink/CachePolyfill.h', + '<(SHARED_INTERMEDIATE_DIR)/blink/CachePolyfill.cpp', + ], + 'action': [ + 'python', + '../build/scripts/make-file-arrays.py', + '--out-h=<(SHARED_INTERMEDIATE_DIR)/blink/CachePolyfill.h', + '--out-cpp=<(SHARED_INTERMEDIATE_DIR)/blink/CachePolyfill.cpp', + '--namespace=WebCore', + '<@(resources)', + ], + }, + { + # GN version: //third_party/WebKit/Source/modules:modules_cache_storage_polyfill + 'action_name': 'CacheStoragePolyfill', + 'process_outputs_as_sources': 1, + 'variables': { + 'resources': [ + 'serviceworkers/polyfills/cacheStoragePolyfill.js', + ], + }, + 'inputs': [ + '../build/scripts/make-file-arrays.py', + '<@(resources)', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/blink/CacheStoragePolyfill.h', + '<(SHARED_INTERMEDIATE_DIR)/blink/CacheStoragePolyfill.cpp', + ], + 'action': [ + 'python', + '../build/scripts/make-file-arrays.py', + '--out-h=<(SHARED_INTERMEDIATE_DIR)/blink/CacheStoragePolyfill.h', + '--out-cpp=<(SHARED_INTERMEDIATE_DIR)/blink/CacheStoragePolyfill.cpp', + '--namespace=WebCore', + '<@(resources)', + ], + }, ], # Disable c4267 warnings until we fix size_t to int truncations. 'msvs_disabled_warnings': [ 4267, 4334, ] }, { - 'target_name': 'modules_test_support', + # GN version: //third_party/WebKit/Source/modules:modules_testing + 'target_name': 'modules_testing', 'type': 'static_library', 'dependencies': [ '../config.gyp:config', @@ -63,8 +155,28 @@ 'INSIDE_BLINK', ], 'sources': [ - '<@(modules_testing_support_files)', + '<@(modules_testing_files)', ], + }, + { + # FIXME: should be in modules_generated.gyp + # GN version: //third_party/WebKit/Source/modules:make_modules_generated + 'target_name': 'make_modules_generated', + 'type': 'none', + 'hard_dependency': 1, + 'dependencies': [ + #'generated_testing_idls', + '../core/core_generated.gyp:core_event_interfaces', + '../bindings/modules/generated.gyp:modules_event_generated', + '../config.gyp:config', + ], + 'sources': [ + # bison rule + '../core/css/CSSGrammar.y', + '../core/xml/XPathGrammar.y', + ], + 'actions': [ + ], }], } diff --git a/chromium/third_party/WebKit/Source/modules/modules.gypi b/chromium/third_party/WebKit/Source/modules/modules.gypi index aeb8afed91e..f3e406e9d8e 100644 --- a/chromium/third_party/WebKit/Source/modules/modules.gypi +++ b/chromium/third_party/WebKit/Source/modules/modules.gypi @@ -1,4 +1,8 @@ { + 'includes': [ + '../core/core_generated.gypi', + 'modules_generated.gypi', + ], 'variables': { # Experimental hooks for embedder to provide extra IDL and source files. # @@ -7,28 +11,23 @@ # ways. 'extra_blink_module_idl_files': [], 'extra_blink_module_files': [], + # Files for which bindings (.cpp and .h files) will be generated 'modules_idl_files': [ '<@(extra_blink_module_idl_files)', - 'crypto/AesCbcParams.idl', - 'crypto/AesCtrParams.idl', - 'crypto/AesKeyGenParams.idl', - 'crypto/Algorithm.idl', + 'battery/BatteryManager.idl', + 'crypto/AesKeyAlgorithm.idl', 'crypto/Crypto.idl', - 'crypto/HmacKeyParams.idl', - 'crypto/HmacParams.idl', + 'crypto/HmacKeyAlgorithm.idl', 'crypto/Key.idl', - 'crypto/KeyPair.idl', - 'crypto/RsaKeyGenParams.idl', - 'crypto/RsaSsaParams.idl', + 'crypto/KeyAlgorithm.idl', + 'crypto/RsaHashedKeyAlgorithm.idl', + 'crypto/RsaKeyAlgorithm.idl', 'crypto/SubtleCrypto.idl', - 'crypto/WindowCrypto.idl', - 'crypto/WorkerCrypto.idl', - 'crypto/WorkerGlobalScopeCrypto.idl', + 'device_light/DeviceLightEvent.idl', 'device_orientation/DeviceAcceleration.idl', 'device_orientation/DeviceMotionEvent.idl', 'device_orientation/DeviceOrientationEvent.idl', 'device_orientation/DeviceRotationRate.idl', - 'donottrack/NavigatorDoNotTrack.idl', 'encoding/TextDecoder.idl', 'encoding/TextEncoder.idl', 'encryptedmedia/MediaKeyMessageEvent.idl', @@ -37,7 +36,6 @@ 'encryptedmedia/MediaKeys.idl', 'filesystem/DOMFileSystem.idl', 'filesystem/DOMFileSystemSync.idl', - 'filesystem/DataTransferItemFileSystem.idl', 'filesystem/DirectoryEntry.idl', 'filesystem/DirectoryEntrySync.idl', 'filesystem/DirectoryReader.idl', @@ -54,23 +52,20 @@ 'filesystem/FileWriter.idl', 'filesystem/FileWriterCallback.idl', 'filesystem/FileWriterSync.idl', - 'filesystem/HTMLInputElementFileSystem.idl', 'filesystem/Metadata.idl', 'filesystem/MetadataCallback.idl', - 'filesystem/WindowFileSystem.idl', - 'filesystem/WorkerGlobalScopeFileSystem.idl', 'gamepad/Gamepad.idl', + 'gamepad/GamepadButton.idl', + 'gamepad/GamepadEvent.idl', 'gamepad/GamepadList.idl', - 'gamepad/NavigatorGamepad.idl', + 'gamepad/WebKitGamepad.idl', + 'gamepad/WebKitGamepadList.idl', 'geolocation/Coordinates.idl', 'geolocation/Geolocation.idl', 'geolocation/Geoposition.idl', - 'geolocation/NavigatorGeolocation.idl', 'geolocation/PositionCallback.idl', 'geolocation/PositionError.idl', 'geolocation/PositionErrorCallback.idl', - 'imagebitmap/ImageBitmapFactories.idl', - 'imagebitmap/WindowImageBitmapFactories.idl', 'indexeddb/IDBCursor.idl', 'indexeddb/IDBCursorWithValue.idl', 'indexeddb/IDBDatabase.idl', @@ -82,24 +77,17 @@ 'indexeddb/IDBRequest.idl', 'indexeddb/IDBTransaction.idl', 'indexeddb/IDBVersionChangeEvent.idl', - 'indexeddb/WindowIndexedDatabase.idl', - 'indexeddb/WorkerGlobalScopeIndexedDatabase.idl', - 'mediasource/HTMLVideoElementMediaSource.idl', 'mediasource/MediaSource.idl', 'mediasource/SourceBuffer.idl', 'mediasource/SourceBufferList.idl', - 'mediasource/URLMediaSource.idl', 'mediasource/VideoPlaybackQuality.idl', - 'mediasource/WebKitMediaSource.idl', - 'mediasource/WebKitSourceBuffer.idl', - 'mediasource/WebKitSourceBufferList.idl', - 'mediasource/WindowMediaSource.idl', + 'mediastream/MediaDeviceInfo.idl', + 'mediastream/MediaDeviceInfoCallback.idl', 'mediastream/MediaStream.idl', 'mediastream/MediaStreamEvent.idl', 'mediastream/MediaStreamTrack.idl', 'mediastream/MediaStreamTrackEvent.idl', 'mediastream/MediaStreamTrackSourcesCallback.idl', - 'mediastream/NavigatorMediaStream.idl', 'mediastream/NavigatorUserMediaError.idl', 'mediastream/NavigatorUserMediaErrorCallback.idl', 'mediastream/NavigatorUserMediaSuccessCallback.idl', @@ -117,26 +105,31 @@ 'mediastream/RTCStatsReport.idl', 'mediastream/RTCStatsResponse.idl', 'mediastream/SourceInfo.idl', - 'mediastream/URLMediaStream.idl', - 'navigatorcontentutils/NavigatorContentUtils.idl', + 'netinfo/NetworkInformation.idl', 'notifications/Notification.idl', - 'notifications/NotificationCenter.idl', 'notifications/NotificationPermissionCallback.idl', - 'notifications/WebKitNotification.idl', - 'notifications/WindowNotifications.idl', - 'notifications/WorkerGlobalScopeNotifications.idl', - 'performance/WorkerGlobalScopePerformance.idl', 'performance/WorkerPerformance.idl', - 'quota/NavigatorStorageQuota.idl', + 'push_messaging/PushEvent.idl', + 'push_messaging/PushManager.idl', + 'push_messaging/PushRegistration.idl', + 'quota/DeprecatedStorageInfo.idl', + 'quota/DeprecatedStorageQuota.idl', 'quota/StorageErrorCallback.idl', 'quota/StorageInfo.idl', 'quota/StorageQuota.idl', 'quota/StorageQuotaCallback.idl', 'quota/StorageUsageCallback.idl', - 'quota/WindowQuota.idl', - 'quota/WorkerNavigatorStorageQuota.idl', - 'serviceworkers/NavigatorServiceWorker.idl', + 'serviceworkers/Client.idl', + 'serviceworkers/FetchEvent.idl', + 'serviceworkers/HeaderMap.idl', + 'serviceworkers/HeaderMapForEachCallback.idl', + 'serviceworkers/InstallEvent.idl', + 'serviceworkers/InstallPhaseEvent.idl', + 'serviceworkers/Request.idl', + 'serviceworkers/Response.idl', 'serviceworkers/ServiceWorker.idl', + 'serviceworkers/ServiceWorkerClients.idl', + 'serviceworkers/ServiceWorkerContainer.idl', 'serviceworkers/ServiceWorkerGlobalScope.idl', 'speech/SpeechGrammar.idl', 'speech/SpeechGrammarList.idl', @@ -150,8 +143,6 @@ 'speech/SpeechSynthesisEvent.idl', 'speech/SpeechSynthesisUtterance.idl', 'speech/SpeechSynthesisVoice.idl', - 'speech/WindowSpeechSynthesis.idl', - 'vibration/NavigatorVibration.idl', 'webaudio/AnalyserNode.idl', 'webaudio/AudioBuffer.idl', 'webaudio/AudioBufferCallback.idl', @@ -193,10 +184,7 @@ 'webdatabase/SQLTransactionErrorCallback.idl', 'webdatabase/SQLTransactionSync.idl', 'webdatabase/SQLTransactionSyncCallback.idl', - 'webdatabase/WindowWebDatabase.idl', - 'webdatabase/WorkerGlobalScopeWebDatabase.idl', 'webmidi/MIDIAccess.idl', - 'webmidi/MIDIAccessPromise.idl', 'webmidi/MIDIConnectionEvent.idl', 'webmidi/MIDIErrorCallback.idl', 'webmidi/MIDIInput.idl', @@ -204,46 +192,140 @@ 'webmidi/MIDIOutput.idl', 'webmidi/MIDIPort.idl', 'webmidi/MIDISuccessCallback.idl', - 'webmidi/NavigatorWebMIDI.idl', 'websockets/CloseEvent.idl', 'websockets/WebSocket.idl', ], + # 'partial interface' or target (right side of) 'implements' + 'modules_dependency_idl_files': [ + 'battery/NavigatorBattery.idl', + 'beacon/NavigatorBeacon.idl', + 'crypto/WindowCrypto.idl', + 'crypto/WorkerGlobalScopeCrypto.idl', + 'device_light/WindowDeviceLight.idl', + 'device_orientation/WindowDeviceMotion.idl', + 'device_orientation/WindowDeviceOrientation.idl', + 'donottrack/NavigatorDoNotTrack.idl', + 'encryptedmedia/HTMLMediaElementEncryptedMedia.idl', + 'filesystem/DataTransferItemFileSystem.idl', + 'filesystem/HTMLInputElementFileSystem.idl', + 'filesystem/InspectorFrontendHostFileSystem.idl', + 'filesystem/WindowFileSystem.idl', + 'filesystem/WorkerGlobalScopeFileSystem.idl', + 'gamepad/NavigatorGamepad.idl', + 'geolocation/NavigatorGeolocation.idl', + 'imagebitmap/ImageBitmapFactories.idl', + 'imagebitmap/WindowImageBitmapFactories.idl', + 'indexeddb/WindowIndexedDatabase.idl', + 'indexeddb/WorkerGlobalScopeIndexedDatabase.idl', + 'mediasource/HTMLVideoElementMediaSource.idl', + 'mediasource/URLMediaSource.idl', + 'mediastream/NavigatorMediaStream.idl', + 'mediastream/URLMediaStream.idl', + 'mediastream/WindowMediaStream.idl', + 'navigatorcontentutils/NavigatorContentUtils.idl', + 'netinfo/NavigatorNetworkInformation.idl', + 'netinfo/WorkerNavigatorNetworkInformation.idl', + 'performance/SharedWorkerPerformance.idl', + 'performance/WorkerGlobalScopePerformance.idl', + 'push_messaging/NavigatorPushManager.idl', + 'push_messaging/ServiceWorkerGlobalScopePush.idl', + 'quota/NavigatorStorageQuota.idl', + 'quota/WindowQuota.idl', + 'quota/WorkerNavigatorStorageQuota.idl', + 'screen_orientation/ScreenOrientation.idl', + 'serviceworkers/NavigatorServiceWorker.idl', + 'speech/WindowSpeech.idl', + 'speech/WindowSpeechSynthesis.idl', + 'vibration/NavigatorVibration.idl', + 'webaudio/WindowWebAudio.idl', + 'webdatabase/WindowWebDatabase.idl', + 'webdatabase/WorkerGlobalScopeWebDatabase.idl', + 'webmidi/NavigatorWebMIDI.idl', + ], + # interfaces that inherit from Event + 'modules_event_idl_files': [ + 'device_light/DeviceLightEvent.idl', + 'device_orientation/DeviceMotionEvent.idl', + 'device_orientation/DeviceOrientationEvent.idl', + 'encryptedmedia/MediaKeyMessageEvent.idl', + 'encryptedmedia/MediaKeyNeededEvent.idl', + 'gamepad/GamepadEvent.idl', + 'indexeddb/IDBVersionChangeEvent.idl', + 'mediastream/MediaStreamEvent.idl', + 'mediastream/MediaStreamTrackEvent.idl', + 'mediastream/RTCDTMFToneChangeEvent.idl', + 'mediastream/RTCDataChannelEvent.idl', + 'mediastream/RTCIceCandidateEvent.idl', + 'push_messaging/PushEvent.idl', + 'serviceworkers/FetchEvent.idl', + 'serviceworkers/InstallEvent.idl', + 'serviceworkers/InstallPhaseEvent.idl', + 'speech/SpeechRecognitionError.idl', + 'speech/SpeechRecognitionEvent.idl', + 'speech/SpeechSynthesisEvent.idl', + 'webaudio/AudioProcessingEvent.idl', + 'webaudio/OfflineAudioCompletionEvent.idl', + 'webmidi/MIDIConnectionEvent.idl', + 'webmidi/MIDIMessageEvent.idl', + 'websockets/CloseEvent.idl', + ], + 'generated_modules_files': [ + # .cpp files from make_modules_generated actions. + '<(blink_modules_output_dir)/EventModules.cpp', + '<(blink_modules_output_dir)/EventModulesHeaders.h', + '<(blink_modules_output_dir)/EventModulesInterfaces.h', + '<(blink_modules_output_dir)/EventModulesNames.cpp', + '<(blink_modules_output_dir)/EventModulesNames.h', + '<(blink_modules_output_dir)/EventTargetModulesHeaders.h', + '<(blink_modules_output_dir)/EventTargetModulesInterfaces.h', + '<(blink_modules_output_dir)/EventTargetModulesNames.cpp', + '<(blink_modules_output_dir)/EventTargetModulesNames.h', + ], 'modules_files': [ '<@(extra_blink_module_files)', - 'crypto/AesCbcParams.cpp', - 'crypto/AesCbcParams.h', - 'crypto/AesCtrParams.cpp', - 'crypto/AesCtrParams.h', - 'crypto/AesKeyGenParams.cpp', - 'crypto/AesKeyGenParams.h', - 'crypto/Algorithm.cpp', - 'crypto/Algorithm.h', + '<@(generated_modules_files)', + 'InitModules.cpp', + 'InitModules.h', + 'battery/BatteryDispatcher.cpp', + 'battery/BatteryDispatcher.h', + 'battery/BatteryManager.cpp', + 'battery/BatteryManager.h', + 'battery/BatteryStatus.cpp', + 'battery/BatteryStatus.h', + 'battery/NavigatorBattery.cpp', + 'battery/NavigatorBattery.h', + 'beacon/NavigatorBeacon.cpp', + 'beacon/NavigatorBeacon.h', + 'crypto/AesKeyAlgorithm.cpp', + 'crypto/AesKeyAlgorithm.h', 'crypto/Crypto.cpp', 'crypto/Crypto.h', 'crypto/CryptoResultImpl.cpp', 'crypto/CryptoResultImpl.h', 'crypto/DOMWindowCrypto.cpp', 'crypto/DOMWindowCrypto.h', - 'crypto/HmacKeyParams.cpp', - 'crypto/HmacKeyParams.h', - 'crypto/HmacParams.cpp', - 'crypto/HmacParams.h', + 'crypto/HmacKeyAlgorithm.cpp', + 'crypto/HmacKeyAlgorithm.h', 'crypto/Key.cpp', 'crypto/Key.h', - 'crypto/KeyPair.cpp', - 'crypto/KeyPair.h', + 'crypto/KeyAlgorithm.cpp', + 'crypto/KeyAlgorithm.h', 'crypto/NormalizeAlgorithm.cpp', 'crypto/NormalizeAlgorithm.h', - 'crypto/RsaKeyGenParams.cpp', - 'crypto/RsaKeyGenParams.h', - 'crypto/RsaSsaParams.cpp', - 'crypto/RsaSsaParams.h', + 'crypto/RsaHashedKeyAlgorithm.cpp', + 'crypto/RsaHashedKeyAlgorithm.h', + 'crypto/RsaKeyAlgorithm.cpp', + 'crypto/RsaKeyAlgorithm.h', 'crypto/SubtleCrypto.cpp', 'crypto/SubtleCrypto.h', - 'crypto/WorkerCrypto.cpp', - 'crypto/WorkerCrypto.h', 'crypto/WorkerGlobalScopeCrypto.cpp', 'crypto/WorkerGlobalScopeCrypto.h', + 'device_light/DeviceLightController.cpp', + 'device_light/DeviceLightController.h', + 'device_light/DeviceLightDispatcher.cpp', + 'device_light/DeviceLightDispatcher.h', + 'device_light/DeviceLightEvent.cpp', + 'device_light/DeviceLightEvent.h', 'device_orientation/DeviceAcceleration.cpp', 'device_orientation/DeviceAcceleration.h', 'device_orientation/DeviceMotionController.cpp', @@ -256,32 +338,35 @@ 'device_orientation/DeviceMotionEvent.h', 'device_orientation/DeviceOrientationController.cpp', 'device_orientation/DeviceOrientationController.h', - 'device_orientation/DeviceOrientationDispatcher.cpp', - 'device_orientation/DeviceOrientationDispatcher.h', 'device_orientation/DeviceOrientationData.cpp', 'device_orientation/DeviceOrientationData.h', + 'device_orientation/DeviceOrientationDispatcher.cpp', + 'device_orientation/DeviceOrientationDispatcher.h', 'device_orientation/DeviceOrientationEvent.cpp', 'device_orientation/DeviceOrientationEvent.h', + 'device_orientation/DeviceOrientationInspectorAgent.cpp', + 'device_orientation/DeviceOrientationInspectorAgent.h', 'device_orientation/DeviceRotationRate.cpp', 'device_orientation/DeviceRotationRate.h', - 'device_orientation/DeviceSensorEventController.cpp', - 'device_orientation/DeviceSensorEventController.h', - 'device_orientation/DeviceSensorEventDispatcher.cpp', - 'device_orientation/DeviceSensorEventDispatcher.h', 'donottrack/NavigatorDoNotTrack.cpp', 'donottrack/NavigatorDoNotTrack.h', 'encoding/TextDecoder.cpp', 'encoding/TextDecoder.h', 'encoding/TextEncoder.cpp', 'encoding/TextEncoder.h', + 'encryptedmedia/HTMLMediaElementEncryptedMedia.cpp', + 'encryptedmedia/HTMLMediaElementEncryptedMedia.h', 'encryptedmedia/MediaKeyMessageEvent.cpp', 'encryptedmedia/MediaKeyMessageEvent.h', 'encryptedmedia/MediaKeyNeededEvent.cpp', 'encryptedmedia/MediaKeyNeededEvent.h', - 'encryptedmedia/MediaKeys.cpp', - 'encryptedmedia/MediaKeys.h', 'encryptedmedia/MediaKeySession.cpp', 'encryptedmedia/MediaKeySession.h', + 'encryptedmedia/MediaKeys.cpp', + 'encryptedmedia/MediaKeys.h', + 'encryptedmedia/MediaKeysClient.h', + 'encryptedmedia/MediaKeysController.cpp', + 'encryptedmedia/MediaKeysController.h', 'filesystem/DOMFilePath.cpp', 'filesystem/DOMFilePath.h', 'filesystem/DOMFileSystem.cpp', @@ -334,6 +419,10 @@ 'filesystem/FileWriterSync.h', 'filesystem/HTMLInputElementFileSystem.cpp', 'filesystem/HTMLInputElementFileSystem.h', + 'filesystem/InspectorFileSystemAgent.cpp', + 'filesystem/InspectorFileSystemAgent.h', + 'filesystem/InspectorFrontendHostFileSystem.cpp', + 'filesystem/InspectorFrontendHostFileSystem.h', 'filesystem/LocalFileSystem.cpp', 'filesystem/LocalFileSystem.h', 'filesystem/Metadata.h', @@ -343,13 +432,26 @@ 'filesystem/WorkerGlobalScopeFileSystem.h', 'gamepad/Gamepad.cpp', 'gamepad/Gamepad.h', + 'gamepad/GamepadButton.cpp', + 'gamepad/GamepadButton.h', + 'gamepad/GamepadCommon.cpp', + 'gamepad/GamepadCommon.h', + 'gamepad/GamepadDispatcher.cpp', + 'gamepad/GamepadDispatcher.h', + 'gamepad/GamepadEvent.cpp', + 'gamepad/GamepadEvent.h', 'gamepad/GamepadList.cpp', 'gamepad/GamepadList.h', 'gamepad/NavigatorGamepad.cpp', 'gamepad/NavigatorGamepad.h', + 'gamepad/WebKitGamepad.cpp', + 'gamepad/WebKitGamepad.h', + 'gamepad/WebKitGamepadList.cpp', + 'gamepad/WebKitGamepadList.h', 'geolocation/Coordinates.cpp', 'geolocation/Geolocation.cpp', 'geolocation/GeolocationController.cpp', + 'geolocation/GeolocationInspectorAgent.cpp', 'geolocation/NavigatorGeolocation.cpp', 'geolocation/NavigatorGeolocation.h', 'imagebitmap/ImageBitmapFactories.cpp', @@ -370,7 +472,6 @@ 'indexeddb/IDBEventDispatcher.h', 'indexeddb/IDBFactory.cpp', 'indexeddb/IDBFactory.h', - 'indexeddb/IDBFactoryBackendInterface.h', 'indexeddb/IDBHistograms.h', 'indexeddb/IDBIndex.cpp', 'indexeddb/IDBIndex.h', @@ -395,22 +496,20 @@ 'indexeddb/IDBVersionChangeEvent.cpp', 'indexeddb/IDBVersionChangeEvent.h', 'indexeddb/IndexedDB.h', - 'indexeddb/PageGroupIndexedDatabase.cpp', - 'indexeddb/PageGroupIndexedDatabase.h', + 'indexeddb/IndexedDBClient.cpp', + 'indexeddb/IndexedDBClient.h', + 'indexeddb/InspectorIndexedDBAgent.cpp', + 'indexeddb/InspectorIndexedDBAgent.h', 'indexeddb/WebIDBCallbacksImpl.cpp', 'indexeddb/WebIDBCallbacksImpl.h', 'indexeddb/WebIDBDatabaseCallbacksImpl.cpp', 'indexeddb/WebIDBDatabaseCallbacksImpl.h', 'indexeddb/WorkerGlobalScopeIndexedDatabase.cpp', 'indexeddb/WorkerGlobalScopeIndexedDatabase.h', - 'indexeddb/chromium/IDBFactoryBackendInterfaceChromium.cpp', - 'indexeddb/chromium/IDBFactoryBackendInterfaceChromium.h', 'mediasource/HTMLVideoElementMediaSource.cpp', 'mediasource/HTMLVideoElementMediaSource.h', 'mediasource/MediaSource.cpp', 'mediasource/MediaSource.h', - 'mediasource/MediaSourceBase.cpp', - 'mediasource/MediaSourceBase.h', 'mediasource/MediaSourceRegistry.cpp', 'mediasource/MediaSourceRegistry.h', 'mediasource/SourceBuffer.cpp', @@ -421,14 +520,13 @@ 'mediasource/URLMediaSource.h', 'mediasource/VideoPlaybackQuality.cpp', 'mediasource/VideoPlaybackQuality.h', - 'mediasource/WebKitMediaSource.cpp', - 'mediasource/WebKitMediaSource.h', - 'mediasource/WebKitSourceBuffer.cpp', - 'mediasource/WebKitSourceBuffer.h', - 'mediasource/WebKitSourceBufferList.cpp', - 'mediasource/WebKitSourceBufferList.h', 'mediastream/MediaConstraintsImpl.cpp', 'mediastream/MediaConstraintsImpl.h', + 'mediastream/MediaDeviceInfo.cpp', + 'mediastream/MediaDeviceInfo.h', + 'mediastream/MediaDeviceInfoCallback.h', + 'mediastream/MediaDevicesRequest.cpp', + 'mediastream/MediaDevicesRequest.h', 'mediastream/MediaStream.cpp', 'mediastream/MediaStream.h', 'mediastream/MediaStreamEvent.cpp', @@ -440,8 +538,8 @@ 'mediastream/MediaStreamTrackEvent.cpp', 'mediastream/MediaStreamTrackEvent.h', 'mediastream/MediaStreamTrackSourcesCallback.h', - 'mediastream/MediaStreamTrackSourcesRequest.cpp', - 'mediastream/MediaStreamTrackSourcesRequest.h', + 'mediastream/MediaStreamTrackSourcesRequestImpl.cpp', + 'mediastream/MediaStreamTrackSourcesRequestImpl.h', 'mediastream/NavigatorMediaStream.cpp', 'mediastream/NavigatorMediaStream.h', 'mediastream/NavigatorUserMediaError.cpp', @@ -478,62 +576,117 @@ 'mediastream/RTCVoidRequestImpl.h', 'mediastream/SourceInfo.cpp', 'mediastream/SourceInfo.h', + 'mediastream/URLMediaStream.cpp', + 'mediastream/URLMediaStream.h', 'mediastream/UserMediaClient.h', 'mediastream/UserMediaController.cpp', 'mediastream/UserMediaController.h', 'mediastream/UserMediaRequest.cpp', 'mediastream/UserMediaRequest.h', - 'mediastream/URLMediaStream.cpp', - 'mediastream/URLMediaStream.h', - 'mediastream/WebMediaStreamTrackSourcesRequest.cpp', - 'serviceworkers/ServiceWorkerGlobalScope.cpp', - 'serviceworkers/ServiceWorkerGlobalScope.h', - 'serviceworkers/ServiceWorkerThread.cpp', - 'serviceworkers/ServiceWorkerThread.h', 'navigatorcontentutils/NavigatorContentUtils.cpp', 'navigatorcontentutils/NavigatorContentUtils.h', 'navigatorcontentutils/NavigatorContentUtilsClient.h', - 'notifications/DOMWindowNotifications.cpp', - 'notifications/DOMWindowNotifications.h', + 'netinfo/NavigatorNetworkInformation.cpp', + 'netinfo/NavigatorNetworkInformation.h', + 'netinfo/NetworkInformation.cpp', + 'netinfo/NetworkInformation.h', + 'netinfo/WorkerNavigatorNetworkInformation.cpp', + 'netinfo/WorkerNavigatorNetworkInformation.h', 'notifications/Notification.cpp', 'notifications/Notification.h', - 'notifications/NotificationBase.cpp', - 'notifications/NotificationBase.h', - 'notifications/NotificationCenter.cpp', - 'notifications/NotificationCenter.h', + 'notifications/NotificationClient.h', 'notifications/NotificationController.cpp', 'notifications/NotificationController.h', 'notifications/NotificationPermissionCallback.h', - 'notifications/WebKitNotification.cpp', - 'notifications/WebKitNotification.h', - 'notifications/WorkerGlobalScopeNotifications.cpp', - 'notifications/WorkerGlobalScopeNotifications.h', + 'performance/SharedWorkerPerformance.cpp', 'performance/WorkerGlobalScopePerformance.cpp', 'performance/WorkerGlobalScopePerformance.h', 'performance/WorkerPerformance.cpp', 'performance/WorkerPerformance.h', + 'push_messaging/NavigatorPushManager.cpp', + 'push_messaging/NavigatorPushManager.h', + 'push_messaging/PushController.cpp', + 'push_messaging/PushController.h', + 'push_messaging/PushError.cpp', + 'push_messaging/PushError.h', + 'push_messaging/PushEvent.cpp', + 'push_messaging/PushEvent.h', + 'push_messaging/PushManager.cpp', + 'push_messaging/PushManager.h', + 'push_messaging/PushRegistration.cpp', + 'push_messaging/PushRegistration.h', + 'push_messaging/ServiceWorkerGlobalScopePush.h', 'quota/DOMWindowQuota.cpp', 'quota/DOMWindowQuota.h', + 'quota/DeprecatedStorageInfo.cpp', + 'quota/DeprecatedStorageInfo.h', + 'quota/DeprecatedStorageQuota.cpp', + 'quota/DeprecatedStorageQuota.h', + 'quota/DeprecatedStorageQuotaCallbacksImpl.cpp', + 'quota/DeprecatedStorageQuotaCallbacksImpl.h', 'quota/NavigatorStorageQuota.cpp', 'quota/NavigatorStorageQuota.h', - 'quota/StorageInfo.cpp', - 'quota/StorageInfo.h', 'quota/StorageErrorCallback.cpp', 'quota/StorageErrorCallback.h', + 'quota/StorageInfo.cpp', + 'quota/StorageInfo.h', 'quota/StorageQuota.cpp', 'quota/StorageQuota.h', 'quota/StorageQuotaCallback.h', + 'quota/StorageQuotaCallbacksImpl.cpp', + 'quota/StorageQuotaCallbacksImpl.h', + 'quota/StorageQuotaClient.cpp', + 'quota/StorageQuotaClient.h', 'quota/StorageUsageCallback.h', - 'quota/WebStorageQuotaCallbacksImpl.cpp', - 'quota/WebStorageQuotaCallbacksImpl.h', 'quota/WorkerNavigatorStorageQuota.cpp', 'quota/WorkerNavigatorStorageQuota.h', + 'screen_orientation/LockOrientationCallback.cpp', + 'screen_orientation/LockOrientationCallback.h', + 'screen_orientation/ScreenOrientation.cpp', + 'screen_orientation/ScreenOrientation.h', + 'screen_orientation/ScreenOrientationController.cpp', + 'screen_orientation/ScreenOrientationController.h', + 'serviceworkers/Client.cpp', + 'serviceworkers/Client.h', + 'serviceworkers/FetchEvent.cpp', + 'serviceworkers/FetchEvent.h', + 'serviceworkers/FetchManager.cpp', + 'serviceworkers/FetchManager.h', + 'serviceworkers/HeaderMap.cpp', + 'serviceworkers/HeaderMap.h', + 'serviceworkers/HeaderMapForEachCallback.h', + 'serviceworkers/InstallEvent.cpp', + 'serviceworkers/InstallEvent.h', + 'serviceworkers/InstallPhaseEvent.cpp', + 'serviceworkers/InstallPhaseEvent.h', + 'serviceworkers/NavigatorServiceWorker.cpp', + 'serviceworkers/NavigatorServiceWorker.h', + 'serviceworkers/RegistrationOptionList.h', + 'serviceworkers/Request.cpp', + 'serviceworkers/Request.h', + 'serviceworkers/RequestInit.h', + 'serviceworkers/RespondWithObserver.cpp', + 'serviceworkers/RespondWithObserver.h', + 'serviceworkers/Response.cpp', + 'serviceworkers/Response.h', + 'serviceworkers/ResponseInit.h', 'serviceworkers/ServiceWorker.cpp', 'serviceworkers/ServiceWorker.h', + 'serviceworkers/ServiceWorkerClients.cpp', + 'serviceworkers/ServiceWorkerClients.h', + 'serviceworkers/ServiceWorkerContainer.cpp', + 'serviceworkers/ServiceWorkerContainer.h', + 'serviceworkers/ServiceWorkerContainerClient.cpp', + 'serviceworkers/ServiceWorkerContainerClient.h', 'serviceworkers/ServiceWorkerError.cpp', 'serviceworkers/ServiceWorkerError.h', - 'serviceworkers/NavigatorServiceWorker.cpp', - 'serviceworkers/NavigatorServiceWorker.h', + 'serviceworkers/ServiceWorkerGlobalScope.cpp', + 'serviceworkers/ServiceWorkerGlobalScope.h', + 'serviceworkers/ServiceWorkerGlobalScopeClient.cpp', + 'serviceworkers/ServiceWorkerGlobalScopeClient.h', + 'serviceworkers/ServiceWorkerThread.cpp', + 'serviceworkers/ServiceWorkerThread.h', + 'serviceworkers/WaitUntilObserver.cpp', 'speech/DOMWindowSpeechSynthesis.cpp', 'speech/DOMWindowSpeechSynthesis.h', 'speech/SpeechGrammar.cpp', @@ -565,6 +718,10 @@ 'speech/SpeechSynthesisVoice.h', 'vibration/NavigatorVibration.cpp', 'vibration/NavigatorVibration.h', + 'webaudio/AnalyserNode.cpp', + 'webaudio/AnalyserNode.h', + 'webaudio/AsyncAudioDecoder.cpp', + 'webaudio/AsyncAudioDecoder.h', 'webaudio/AudioBasicInspectorNode.cpp', 'webaudio/AudioBasicInspectorNode.h', 'webaudio/AudioBasicProcessorNode.cpp', @@ -574,16 +731,10 @@ 'webaudio/AudioBufferCallback.h', 'webaudio/AudioBufferSourceNode.cpp', 'webaudio/AudioBufferSourceNode.h', - 'webaudio/ChannelMergerNode.cpp', - 'webaudio/ChannelMergerNode.h', - 'webaudio/ChannelSplitterNode.cpp', - 'webaudio/ChannelSplitterNode.h', 'webaudio/AudioContext.cpp', 'webaudio/AudioContext.h', 'webaudio/AudioDestinationNode.cpp', 'webaudio/AudioDestinationNode.h', - 'webaudio/GainNode.cpp', - 'webaudio/GainNode.h', 'webaudio/AudioListener.cpp', 'webaudio/AudioListener.h', 'webaudio/AudioNode.cpp', @@ -592,8 +743,6 @@ 'webaudio/AudioNodeInput.h', 'webaudio/AudioNodeOutput.cpp', 'webaudio/AudioNodeOutput.h', - 'webaudio/PannerNode.cpp', - 'webaudio/PannerNode.h', 'webaudio/AudioParam.cpp', 'webaudio/AudioParam.h', 'webaudio/AudioParamTimeline.cpp', @@ -605,14 +754,16 @@ 'webaudio/AudioSourceNode.h', 'webaudio/AudioSummingJunction.cpp', 'webaudio/AudioSummingJunction.h', - 'webaudio/AsyncAudioDecoder.cpp', - 'webaudio/AsyncAudioDecoder.h', 'webaudio/BiquadDSPKernel.cpp', 'webaudio/BiquadDSPKernel.h', 'webaudio/BiquadFilterNode.cpp', 'webaudio/BiquadFilterNode.h', 'webaudio/BiquadProcessor.cpp', 'webaudio/BiquadProcessor.h', + 'webaudio/ChannelMergerNode.cpp', + 'webaudio/ChannelMergerNode.h', + 'webaudio/ChannelSplitterNode.cpp', + 'webaudio/ChannelSplitterNode.h', 'webaudio/ConvolverNode.cpp', 'webaudio/ConvolverNode.h', 'webaudio/DefaultAudioDestinationNode.cpp', @@ -625,8 +776,8 @@ 'webaudio/DelayProcessor.h', 'webaudio/DynamicsCompressorNode.cpp', 'webaudio/DynamicsCompressorNode.h', - 'webaudio/ScriptProcessorNode.cpp', - 'webaudio/ScriptProcessorNode.h', + 'webaudio/GainNode.cpp', + 'webaudio/GainNode.h', 'webaudio/MediaElementAudioSourceNode.cpp', 'webaudio/MediaElementAudioSourceNode.h', 'webaudio/MediaStreamAudioDestinationNode.cpp', @@ -641,12 +792,14 @@ 'webaudio/OfflineAudioDestinationNode.h', 'webaudio/OscillatorNode.cpp', 'webaudio/OscillatorNode.h', + 'webaudio/PannerNode.cpp', + 'webaudio/PannerNode.h', 'webaudio/PeriodicWave.cpp', 'webaudio/PeriodicWave.h', 'webaudio/RealtimeAnalyser.cpp', 'webaudio/RealtimeAnalyser.h', - 'webaudio/AnalyserNode.cpp', - 'webaudio/AnalyserNode.h', + 'webaudio/ScriptProcessorNode.cpp', + 'webaudio/ScriptProcessorNode.h', 'webaudio/WaveShaperDSPKernel.cpp', 'webaudio/WaveShaperDSPKernel.h', 'webaudio/WaveShaperNode.cpp', @@ -659,6 +812,8 @@ 'webdatabase/ChangeVersionData.h', 'webdatabase/ChangeVersionWrapper.cpp', 'webdatabase/ChangeVersionWrapper.h', + 'webdatabase/DOMWindowWebDatabase.cpp', + 'webdatabase/DOMWindowWebDatabase.h', 'webdatabase/Database.cpp', 'webdatabase/DatabaseAuthorizer.cpp', 'webdatabase/DatabaseAuthorizer.h', @@ -689,8 +844,10 @@ 'webdatabase/DatabaseThread.h', 'webdatabase/DatabaseTracker.cpp', 'webdatabase/DatabaseTracker.h', - 'webdatabase/DOMWindowWebDatabase.cpp', - 'webdatabase/DOMWindowWebDatabase.h', + 'webdatabase/InspectorDatabaseAgent.cpp', + 'webdatabase/InspectorDatabaseAgent.h', + 'webdatabase/InspectorDatabaseResource.cpp', + 'webdatabase/InspectorDatabaseResource.h', 'webdatabase/QuotaTracker.cpp', 'webdatabase/QuotaTracker.h', 'webdatabase/SQLCallbackWrapper.h', @@ -736,14 +893,15 @@ 'webdatabase/sqlite/SQLiteTransaction.h', 'webmidi/MIDIAccess.cpp', 'webmidi/MIDIAccess.h', - 'webmidi/MIDIAccessPromise.cpp', - 'webmidi/MIDIAccessPromise.h', + 'webmidi/MIDIAccessInitializer.cpp', + 'webmidi/MIDIAccessInitializer.h', 'webmidi/MIDIAccessor.cpp', 'webmidi/MIDIAccessor.h', 'webmidi/MIDIAccessorClient.h', 'webmidi/MIDIClient.h', 'webmidi/MIDIClientMock.cpp', 'webmidi/MIDIClientMock.h', + 'webmidi/MIDIConnectionEvent.cpp', 'webmidi/MIDIConnectionEvent.h', 'webmidi/MIDIController.cpp', 'webmidi/MIDIController.h', @@ -777,9 +935,9 @@ 'websockets/WebSocketDeflater.h', 'websockets/WebSocketExtensionDispatcher.cpp', 'websockets/WebSocketExtensionDispatcher.h', - 'websockets/WebSocketExtensionProcessor.h', 'websockets/WebSocketExtensionParser.cpp', 'websockets/WebSocketExtensionParser.h', + 'websockets/WebSocketExtensionProcessor.h', 'websockets/WebSocketFrame.cpp', 'websockets/WebSocketFrame.h', 'websockets/WebSocketHandshake.cpp', @@ -789,11 +947,22 @@ 'websockets/WorkerThreadableWebSocketChannel.cpp', 'websockets/WorkerThreadableWebSocketChannel.h', ], - 'modules_testing_support_idl_files' : [ + # 'partial interface' or target (right side of) 'implements' + 'modules_testing_dependency_idl_files' : [ + 'geolocation/testing/InternalsGeolocation.idl', + 'navigatorcontentutils/testing/InternalsNavigatorContentUtils.idl', 'speech/testing/InternalsSpeechSynthesis.idl', 'vibration/testing/InternalsVibration.idl', ], - 'modules_testing_support_files': [ + 'modules_testing_files': [ + 'geolocation/testing/GeolocationClientMock.cpp', + 'geolocation/testing/GeolocationClientMock.h', + 'geolocation/testing/InternalsGeolocation.cpp', + 'geolocation/testing/InternalsGeolocation.h', + 'navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp', + 'navigatorcontentutils/testing/InternalsNavigatorContentUtils.h', + 'navigatorcontentutils/testing/NavigatorContentUtilsClientMock.cpp', + 'navigatorcontentutils/testing/NavigatorContentUtilsClientMock.h', 'speech/testing/InternalsSpeechSynthesis.cpp', 'speech/testing/InternalsSpeechSynthesis.h', 'speech/testing/PlatformSpeechSynthesizerMock.cpp', @@ -809,6 +978,7 @@ 'websockets/WebSocketExtensionDispatcherTest.cpp', 'websockets/WebSocketExtensionParserTest.cpp', 'websockets/WebSocketPerMessageDeflateTest.cpp', + 'websockets/WebSocketTest.cpp', ], }, } diff --git a/chromium/third_party/WebKit/Source/modules/modules_generated.gypi b/chromium/third_party/WebKit/Source/modules/modules_generated.gypi new file mode 100644 index 00000000000..452552422ac --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/modules_generated.gypi @@ -0,0 +1,9 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'blink_modules_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/modules', + }, +} diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp index 90d0fafdfb0..9e7be6809d3 100644 --- a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2011, Google Inc. All rights reserved. - * Copyright (C) 2012, Samsung Electronics. All rights reserved. + * Copyright (C) 2014, Samsung Electronics. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -27,15 +27,14 @@ #include "config.h" #include "modules/navigatorcontentutils/NavigatorContentUtils.h" -#if ENABLE(NAVIGATOR_CONTENT_UTILS) - #include "bindings/v8/ExceptionState.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" #include "core/page/Page.h" #include "wtf/HashSet.h" +#include "wtf/text/StringBuilder.h" namespace WebCore { @@ -69,14 +68,14 @@ static void initProtocolHandlerWhitelist() protocolWhitelist->add(protocols[i]); } -static bool verifyCustomHandlerURL(const String& baseURL, const String& url, ExceptionState& exceptionState) +static bool verifyCustomHandlerURL(const KURL& baseURL, const String& url, ExceptionState& exceptionState) { // The specification requires that it is a SyntaxError if the "%s" token is // not present. static const char token[] = "%s"; int index = url.find(token); if (-1 == index) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The url provided ('" + url + "') does not contain '%s'."); return false; } @@ -85,11 +84,10 @@ static bool verifyCustomHandlerURL(const String& baseURL, const String& url, Exc String newURL = url; newURL.remove(index, WTF_ARRAY_LENGTH(token) - 1); - KURL base(ParsedURLString, baseURL); - KURL kurl(base, newURL); + KURL kurl(baseURL, newURL); if (kurl.isEmpty() || !kurl.isValid()) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The custom handler URL created by removing '%s' and prepending '" + baseURL.string() + "' is invalid."); return false; } @@ -100,7 +98,13 @@ static bool isProtocolWhitelisted(const String& scheme) { if (!protocolWhitelist) initProtocolHandlerWhitelist(); - return protocolWhitelist->contains(scheme); + + StringBuilder builder; + unsigned length = scheme.length(); + for (unsigned i = 0; i < length; ++i) + builder.append(toASCIILower(scheme[i])); + + return protocolWhitelist->contains(builder.toString()); } static bool verifyProtocolHandlerScheme(const String& scheme, const String& method, ExceptionState& exceptionState) @@ -116,36 +120,40 @@ static bool verifyProtocolHandlerScheme(const String& scheme, const String& meth return false; } + // The specification requires that schemes don't contain colons. + size_t index = scheme.find(':'); + if (index != kNotFound) { + exceptionState.throwDOMException(SyntaxError, "The scheme '" + scheme + "' contains colon."); + return false; + } + if (isProtocolWhitelisted(scheme)) return true; exceptionState.throwSecurityError("The scheme '" + scheme + "' doesn't belong to the protocol whitelist. Please prefix non-whitelisted schemes with the string 'web+'."); return false; } -NavigatorContentUtils* NavigatorContentUtils::from(Page* page) +NavigatorContentUtils* NavigatorContentUtils::from(Page& page) { - return static_cast<NavigatorContentUtils*>(RefCountedSupplement<Page, NavigatorContentUtils>::from(page, NavigatorContentUtils::supplementName())); + return static_cast<NavigatorContentUtils*>(WillBeHeapSupplement<Page>::from(page, supplementName())); } NavigatorContentUtils::~NavigatorContentUtils() { } -PassRefPtr<NavigatorContentUtils> NavigatorContentUtils::create(NavigatorContentUtilsClient* client) +PassOwnPtrWillBeRawPtr<NavigatorContentUtils> NavigatorContentUtils::create(PassOwnPtr<NavigatorContentUtilsClient> client) { - return adoptRef(new NavigatorContentUtils(client)); + return adoptPtrWillBeNoop(new NavigatorContentUtils(client)); } -void NavigatorContentUtils::registerProtocolHandler(Navigator* navigator, const String& scheme, const String& url, const String& title, ExceptionState& exceptionState) +void NavigatorContentUtils::registerProtocolHandler(Navigator& navigator, const String& scheme, const String& url, const String& title, ExceptionState& exceptionState) { - if (!navigator->frame()) + if (!navigator.frame()) return; - Document* document = navigator->frame()->document(); - if (!document) - return; - - String baseURL = document->baseURL().baseAsString(); + ASSERT(navigator.frame()->document()); + KURL baseURL = navigator.frame()->document()->baseURL(); if (!verifyCustomHandlerURL(baseURL, url, exceptionState)) return; @@ -153,10 +161,10 @@ void NavigatorContentUtils::registerProtocolHandler(Navigator* navigator, const if (!verifyProtocolHandlerScheme(scheme, "registerProtocolHandler", exceptionState)) return; - NavigatorContentUtils::from(navigator->frame()->page())->client()->registerProtocolHandler(scheme, baseURL, url, title); + ASSERT(navigator.frame()->page()); + NavigatorContentUtils::from(*navigator.frame()->page())->client()->registerProtocolHandler(scheme, baseURL, KURL(ParsedURLString, url), title); } -#if ENABLE(CUSTOM_SCHEME_HANDLER) static String customHandlersStateString(const NavigatorContentUtilsClient::CustomHandlersState state) { DEFINE_STATIC_LOCAL(const String, newHandler, ("new")); @@ -176,15 +184,19 @@ static String customHandlersStateString(const NavigatorContentUtilsClient::Custo return String(); } -String NavigatorContentUtils::isProtocolHandlerRegistered(Navigator* navigator, const String& scheme, const String& url, ExceptionState& exceptionState) +String NavigatorContentUtils::isProtocolHandlerRegistered(Navigator& navigator, const String& scheme, const String& url, ExceptionState& exceptionState) { DEFINE_STATIC_LOCAL(const String, declined, ("declined")); - if (!navigator->frame()) + if (!navigator.frame()) + return declined; + + Document* document = navigator.frame()->document(); + ASSERT(document); + if (document->activeDOMObjectsAreStopped()) return declined; - Document* document = navigator->frame()->document(); - String baseURL = document->baseURL().baseAsString(); + KURL baseURL = document->baseURL(); if (!verifyCustomHandlerURL(baseURL, url, exceptionState)) return declined; @@ -192,16 +204,17 @@ String NavigatorContentUtils::isProtocolHandlerRegistered(Navigator* navigator, if (!verifyProtocolHandlerScheme(scheme, "isProtocolHandlerRegistered", exceptionState)) return declined; - return customHandlersStateString(NavigatorContentUtils::from(navigator->frame()->page())->client()->isProtocolHandlerRegistered(scheme, baseURL, url)); + ASSERT(navigator.frame()->page()); + return customHandlersStateString(NavigatorContentUtils::from(*navigator.frame()->page())->client()->isProtocolHandlerRegistered(scheme, baseURL, KURL(ParsedURLString, url))); } -void NavigatorContentUtils::unregisterProtocolHandler(Navigator* navigator, const String& scheme, const String& url, ExceptionState& exceptionState) +void NavigatorContentUtils::unregisterProtocolHandler(Navigator& navigator, const String& scheme, const String& url, ExceptionState& exceptionState) { - if (!navigator->frame()) + if (!navigator.frame()) return; - Document* document = navigator->frame()->document(); - String baseURL = document->baseURL().baseAsString(); + ASSERT(navigator.frame()->document()); + KURL baseURL = navigator.frame()->document()->baseURL(); if (!verifyCustomHandlerURL(baseURL, url, exceptionState)) return; @@ -209,21 +222,18 @@ void NavigatorContentUtils::unregisterProtocolHandler(Navigator* navigator, cons if (!verifyProtocolHandlerScheme(scheme, "unregisterProtocolHandler", exceptionState)) return; - NavigatorContentUtils::from(navigator->frame()->page())->client()->unregisterProtocolHandler(scheme, baseURL, url); + ASSERT(navigator.frame()->page()); + NavigatorContentUtils::from(*navigator.frame()->page())->client()->unregisterProtocolHandler(scheme, baseURL, KURL(ParsedURLString, url)); } -#endif const char* NavigatorContentUtils::supplementName() { return "NavigatorContentUtils"; } -void provideNavigatorContentUtilsTo(Page* page, NavigatorContentUtilsClient* client) +void provideNavigatorContentUtilsTo(Page& page, PassOwnPtr<NavigatorContentUtilsClient> client) { - RefCountedSupplement<Page, NavigatorContentUtils>::provideTo(page, NavigatorContentUtils::supplementName(), NavigatorContentUtils::create(client)); + NavigatorContentUtils::provideTo(page, NavigatorContentUtils::supplementName(), NavigatorContentUtils::create(client)); } } // namespace WebCore - -#endif // ENABLE(NAVIGATOR_CONTENT_UTILS) - diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h index aa623077c2c..cc074ea3d14 100644 --- a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h @@ -27,11 +27,9 @@ #ifndef NavigatorContentUtils_h #define NavigatorContentUtils_h -#if ENABLE(NAVIGATOR_CONTENT_UTILS) - #include "modules/navigatorcontentutils/NavigatorContentUtilsClient.h" -#include "platform/RefCountedSupplement.h" -#include "wtf/PassRefPtr.h" +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -40,34 +38,34 @@ class ExceptionState; class Navigator; class Page; -class NavigatorContentUtils : public RefCountedSupplement<Page, NavigatorContentUtils> { +class NavigatorContentUtils FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorContentUtils>, public WillBeHeapSupplement<Page> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorContentUtils); public: virtual ~NavigatorContentUtils(); + static NavigatorContentUtils* from(Page&); static const char* supplementName(); - static NavigatorContentUtils* from(Page*); - static void registerProtocolHandler(Navigator*, const String& scheme, const String& url, const String& title, ExceptionState&); + static void registerProtocolHandler(Navigator&, const String& scheme, const String& url, const String& title, ExceptionState&); + static String isProtocolHandlerRegistered(Navigator&, const String& scheme, const String& url, ExceptionState&); + static void unregisterProtocolHandler(Navigator&, const String& scheme, const String& url, ExceptionState&); + + static PassOwnPtrWillBeRawPtr<NavigatorContentUtils> create(PassOwnPtr<NavigatorContentUtilsClient>); -#if ENABLE(CUSTOM_SCHEME_HANDLER) - static String isProtocolHandlerRegistered(Navigator*, const String& scheme, const String& url, ExceptionState&); - static void unregisterProtocolHandler(Navigator*, const String& scheme, const String& url, ExceptionState&); -#endif + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Page>::trace(visitor); } - static PassRefPtr<NavigatorContentUtils> create(NavigatorContentUtilsClient*); + void setClientForTest(PassOwnPtr<NavigatorContentUtilsClient> client) { m_client = client; } private: - explicit NavigatorContentUtils(NavigatorContentUtilsClient* client) + explicit NavigatorContentUtils(PassOwnPtr<NavigatorContentUtilsClient> client) : m_client(client) { } - NavigatorContentUtilsClient* client() { return m_client; } + NavigatorContentUtilsClient* client() { return m_client.get(); } - NavigatorContentUtilsClient* m_client; + OwnPtr<NavigatorContentUtilsClient> m_client; }; } // namespace WebCore -#endif // ENABLE(NAVIGATOR_CONTENT_UTILS) - #endif // NavigatorContentUtils_h diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl index a9f4b3114b1..66c24de0ea6 100644 --- a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.idl @@ -20,8 +20,7 @@ // http://www.w3.org/TR/html5/system-state-and-capabilities.html#custom-handlers partial interface Navigator { - [Conditional=NAVIGATOR_CONTENT_UTILS, RaisesException] void registerProtocolHandler(DOMString scheme, DOMString url, DOMString title); - [Conditional=NAVIGATOR_CONTENT_UTILS&CUSTOM_SCHEME_HANDLER, RaisesException] DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url); - [Conditional=NAVIGATOR_CONTENT_UTILS&CUSTOM_SCHEME_HANDLER, RaisesException] void unregisterProtocolHandler(DOMString scheme, DOMString url); + [RuntimeEnabled=NavigatorContentUtils, RaisesException] void registerProtocolHandler(DOMString scheme, DOMString url, DOMString title); + [RuntimeEnabled=CustomSchemeHandler, RaisesException] DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url); + [RuntimeEnabled=CustomSchemeHandler, RaisesException] void unregisterProtocolHandler(DOMString scheme, DOMString url); }; - diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClient.h b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClient.h index c592978e0ae..3348289d72e 100644 --- a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClient.h +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClient.h @@ -26,8 +26,7 @@ #ifndef NavigatorContentUtilsClient_h #define NavigatorContentUtilsClient_h -#if ENABLE(NAVIGATOR_CONTENT_UTILS) - +#include "platform/weborigin/KURL.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -37,23 +36,20 @@ class Page; class NavigatorContentUtilsClient { public: virtual ~NavigatorContentUtilsClient() { } - virtual void registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title) = 0; + virtual void registerProtocolHandler(const String& scheme, const KURL& baseURL, const KURL&, const String& title) = 0; -#if ENABLE(CUSTOM_SCHEME_HANDLER) enum CustomHandlersState { CustomHandlersNew, CustomHandlersRegistered, CustomHandlersDeclined }; - virtual CustomHandlersState isProtocolHandlerRegistered(const String& scheme, const String& baseURL, const String& url) = 0; - virtual void unregisterProtocolHandler(const String& scheme, const String& baseURL, const String& url) = 0; -#endif + virtual CustomHandlersState isProtocolHandlerRegistered(const String& scheme, const KURL& baseURL, const KURL&) = 0; + virtual void unregisterProtocolHandler(const String& scheme, const KURL& baseURL, const KURL&) = 0; }; -void provideNavigatorContentUtilsTo(Page*, NavigatorContentUtilsClient*); +void provideNavigatorContentUtilsTo(Page&, PassOwnPtr<NavigatorContentUtilsClient>); } -#endif // ENABLE(NAVIGATOR_CONTENT_UTILS) #endif // NavigatorContentUtilsClient_h diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp new file mode 100644 index 00000000000..5ca9412320a --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp @@ -0,0 +1,22 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "InternalsNavigatorContentUtils.h" + +#include "core/dom/Document.h" +#include "core/testing/Internals.h" +#include "modules/navigatorcontentutils/NavigatorContentUtils.h" +#include "modules/navigatorcontentutils/testing/NavigatorContentUtilsClientMock.h" + +namespace WebCore { + +void InternalsNavigatorContentUtils::setNavigatorContentUtilsClientMock(Internals&, Document* document) +{ + ASSERT(document && document->page()); + NavigatorContentUtils* navigatorContentUtils = NavigatorContentUtils::from(*document->page()); + navigatorContentUtils->setClientForTest(adoptPtr(new NavigatorContentUtilsClientMock())); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.h b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.h new file mode 100644 index 00000000000..d877a8326cb --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.h @@ -0,0 +1,21 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef InternalsNavigatorContentUtils_h +#define InternalsNavigatorContentUtils_h + +namespace WebCore { + +class Document; +class NavigatorContentUtilsClientMock; +class Internals; + +class InternalsNavigatorContentUtils { +public: + static void setNavigatorContentUtilsClientMock(Internals&, Document*); +}; + +} // namespace WebCore + +#endif // InternalsNavigatorContentUtils_h diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.idl b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.idl new file mode 100644 index 00000000000..0d43a955a5b --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/InternalsNavigatorContentUtils.idl @@ -0,0 +1,7 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +partial interface Internals { + void setNavigatorContentUtilsClientMock(Document document); +}; diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/NavigatorContentUtilsClientMock.cpp b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/NavigatorContentUtilsClientMock.cpp new file mode 100644 index 00000000000..6c988d837b1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/NavigatorContentUtilsClientMock.cpp @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "NavigatorContentUtilsClientMock.h" + +#include "modules/navigatorcontentutils/NavigatorContentUtilsClient.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/text/StringHash.h" + +namespace WebCore { + +void NavigatorContentUtilsClientMock::registerProtocolHandler(const String& scheme, const WebCore::KURL& baseURL, + const WebCore::KURL& url, const String& title) +{ + ProtocolInfo info; + info.scheme = scheme; + info.baseURL = baseURL; + info.url = url; + info.title = title; + + m_protocolMap.set(scheme, info); +} + +NavigatorContentUtilsClient::CustomHandlersState NavigatorContentUtilsClientMock::isProtocolHandlerRegistered(const String& scheme, + const WebCore::KURL& baseURL, const WebCore::KURL& url) +{ + // "declined" state is checked by NavigatorContentUtils::isProtocolHandlerRegistered() before calling this function. + if (m_protocolMap.contains(scheme)) + return NavigatorContentUtilsClient::CustomHandlersRegistered; + + return NavigatorContentUtilsClient::CustomHandlersNew; +} + +void NavigatorContentUtilsClientMock::unregisterProtocolHandler(const String& scheme, const WebCore::KURL& baseURL, + const WebCore::KURL& url) +{ + m_protocolMap.remove(scheme); +} + +} // WebCore diff --git a/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/NavigatorContentUtilsClientMock.h b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/NavigatorContentUtilsClientMock.h new file mode 100644 index 00000000000..49b67128cf4 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/navigatorcontentutils/testing/NavigatorContentUtilsClientMock.h @@ -0,0 +1,41 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NavigatorContentUtilsClientMock_h +#define NavigatorContentUtilsClientMock_h + +#include "modules/navigatorcontentutils/NavigatorContentUtilsClient.h" +#include "platform/weborigin/KURL.h" +#include "wtf/HashSet.h" +#include "wtf/OwnPtr.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +// Provides a mock object for the navigatorcontentutils client. +class NavigatorContentUtilsClientMock : public NavigatorContentUtilsClient { +public: + NavigatorContentUtilsClientMock() { } + virtual ~NavigatorContentUtilsClientMock() { } + + virtual void registerProtocolHandler(const String& scheme, const KURL& baseURL, const KURL&, const String& title); + + virtual CustomHandlersState isProtocolHandlerRegistered(const String& scheme, const KURL& baseURL, const KURL&); + virtual void unregisterProtocolHandler(const String& scheme, const KURL& baseURL, const KURL&); + +private: + typedef struct { + String scheme; + WebCore::KURL baseURL; + WebCore::KURL url; + String title; + } ProtocolInfo; + + typedef HashMap<String, ProtocolInfo> RegisteredProtocolMap; + RegisteredProtocolMap m_protocolMap; +}; + +} + +#endif // NavigatorContentUtilsClientMock_h diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.cpp b/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.cpp new file mode 100644 index 00000000000..5fa32f90ec8 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.cpp @@ -0,0 +1,64 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/netinfo/NavigatorNetworkInformation.h" + +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Navigator.h" +#include "modules/netinfo/NetworkInformation.h" + +namespace WebCore { + +NavigatorNetworkInformation::NavigatorNetworkInformation(Navigator& navigator) + : DOMWindowProperty(navigator.frame()) +{ +} + +NavigatorNetworkInformation::~NavigatorNetworkInformation() +{ +} + +NavigatorNetworkInformation& NavigatorNetworkInformation::from(Navigator& navigator) +{ + NavigatorNetworkInformation* supplement = toNavigatorNetworkInformation(navigator); + if (!supplement) { + supplement = new NavigatorNetworkInformation(navigator); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; +} + +NavigatorNetworkInformation* NavigatorNetworkInformation::toNavigatorNetworkInformation(Navigator& navigator) +{ + return static_cast<NavigatorNetworkInformation*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); +} + +const char* NavigatorNetworkInformation::supplementName() +{ + return "NavigatorNetworkInformation"; +} + +NetworkInformation* NavigatorNetworkInformation::connection(Navigator& navigator) +{ + return NavigatorNetworkInformation::from(navigator).connection(); +} + +NetworkInformation* NavigatorNetworkInformation::connection() +{ + if (!m_connection && frame()) { + ASSERT(frame()->domWindow()); + m_connection = NetworkInformation::create(frame()->domWindow()->executionContext()); + } + return m_connection.get(); +} + +void NavigatorNetworkInformation::trace(Visitor* visitor) +{ + visitor->trace(m_connection); + WillBeHeapSupplement<Navigator>::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.h b/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.h new file mode 100644 index 00000000000..48698c1e10d --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.h @@ -0,0 +1,41 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NavigatorNetworkInformation_h +#define NavigatorNetworkInformation_h + +#include "core/frame/DOMWindowProperty.h" +#include "platform/Supplementable.h" + +namespace WebCore { + +class Navigator; +class NetworkInformation; + +class NavigatorNetworkInformation FINAL + : public NoBaseWillBeGarbageCollectedFinalized<NavigatorNetworkInformation> + , public WillBeHeapSupplement<Navigator> + , DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorNetworkInformation); + +public: + virtual ~NavigatorNetworkInformation(); + static NavigatorNetworkInformation& from(Navigator&); + static NavigatorNetworkInformation* toNavigatorNetworkInformation(Navigator&); + static const char* supplementName(); + + static NetworkInformation* connection(Navigator&); + + virtual void trace(Visitor*) OVERRIDE; + +private: + explicit NavigatorNetworkInformation(Navigator&); + NetworkInformation* connection(); + + RefPtrWillBeMember<NetworkInformation> m_connection; +}; + +} // namespace WebCore + +#endif // NavigatorNetworkInformation_h diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.idl b/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.idl new file mode 100644 index 00000000000..c3ee9e75ddd --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/NavigatorNetworkInformation.idl @@ -0,0 +1,9 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=NetworkInformation +] partial interface Navigator { + readonly attribute NetworkInformation connection; +}; diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp b/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp new file mode 100644 index 00000000000..4aff063cb43 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.cpp @@ -0,0 +1,149 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/netinfo/NetworkInformation.h" + +#include "core/dom/ExecutionContext.h" +#include "core/page/NetworkStateNotifier.h" +#include "modules/EventTargetModules.h" +#include "wtf/text/WTFString.h" + +namespace { + +String connectionTypeToString(blink::WebConnectionType type) +{ + switch (type) { + case blink::ConnectionTypeCellular: + return "cellular"; + case blink::ConnectionTypeBluetooth: + return "bluetooth"; + case blink::ConnectionTypeEthernet: + return "ethernet"; + case blink::ConnectionTypeWifi: + return "wifi"; + case blink::ConnectionTypeOther: + return "other"; + case blink::ConnectionTypeNone: + return "none"; + } + ASSERT_NOT_REACHED(); + return "none"; +} + +} // namespace + +namespace WebCore { + +PassRefPtrWillBeRawPtr<NetworkInformation> NetworkInformation::create(ExecutionContext* context) +{ + RefPtrWillBeRawPtr<NetworkInformation> connection(adoptRefWillBeRefCountedGarbageCollected(new NetworkInformation(context))); + connection->suspendIfNeeded(); + return connection.release(); +} + +NetworkInformation::~NetworkInformation() +{ + ASSERT(!m_observing); +} + +String NetworkInformation::type() const +{ + // m_type is only updated when listening for events, so ask networkStateNotifier + // if not listening (crbug.com/379841). + if (!m_observing) + return connectionTypeToString(networkStateNotifier().connectionType()); + + // If observing, return m_type which changes when the event fires, per spec. + return connectionTypeToString(m_type); +} + +void NetworkInformation::connectionTypeChange(blink::WebConnectionType type) +{ + ASSERT(executionContext()->isContextThread()); + + // This can happen if the observer removes and then adds itself again + // during notification. + if (m_type == type) + return; + + m_type = type; + dispatchEvent(Event::create(EventTypeNames::typechange)); +} + +const AtomicString& NetworkInformation::interfaceName() const +{ + return EventTargetNames::NetworkInformation; +} + +ExecutionContext* NetworkInformation::executionContext() const +{ + return ActiveDOMObject::executionContext(); +} + +bool NetworkInformation::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) +{ + if (!EventTargetWithInlineData::addEventListener(eventType, listener, useCapture)) + return false; + startObserving(); + return true; +} + +bool NetworkInformation::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) +{ + if (!EventTargetWithInlineData::removeEventListener(eventType, listener, useCapture)) + return false; + if (!hasEventListeners()) + stopObserving(); + return true; +} + +void NetworkInformation::removeAllEventListeners() +{ + EventTargetWithInlineData::removeAllEventListeners(); + ASSERT(!hasEventListeners()); + stopObserving(); +} + +bool NetworkInformation::hasPendingActivity() const +{ + ASSERT(m_contextStopped || m_observing == hasEventListeners()); + + // Prevent collection of this object when there are active listeners. + return m_observing; +} + +void NetworkInformation::stop() +{ + m_contextStopped = true; + stopObserving(); +} + +void NetworkInformation::startObserving() +{ + if (!m_observing && !m_contextStopped) { + m_type = networkStateNotifier().connectionType(); + networkStateNotifier().addObserver(this, executionContext()); + m_observing = true; + } +} + +void NetworkInformation::stopObserving() +{ + if (m_observing) { + networkStateNotifier().removeObserver(this, executionContext()); + m_observing = false; + } +} + +NetworkInformation::NetworkInformation(ExecutionContext* context) + : ActiveDOMObject(context) + , m_type(networkStateNotifier().connectionType()) + , m_observing(false) + , m_contextStopped(false) +{ + ScriptWrappable::init(this); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.h b/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.h new file mode 100644 index 00000000000..695e3f3b67e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.h @@ -0,0 +1,65 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NetworkInformation_h +#define NetworkInformation_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/dom/ActiveDOMObject.h" +#include "core/events/EventTarget.h" +#include "core/page/NetworkStateNotifier.h" +#include "public/platform/WebConnectionType.h" + +namespace WebCore { + +class ExecutionContext; + +class NetworkInformation FINAL + : public RefCountedWillBeRefCountedGarbageCollected<NetworkInformation> + , public ScriptWrappable + , public ActiveDOMObject + , public EventTargetWithInlineData + , public NetworkStateNotifier::NetworkStateObserver { + REFCOUNTED_EVENT_TARGET(NetworkInformation); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NetworkInformation); + +public: + static PassRefPtrWillBeRawPtr<NetworkInformation> create(ExecutionContext*); + virtual ~NetworkInformation(); + + String type() const; + + virtual void connectionTypeChange(blink::WebConnectionType) OVERRIDE; + + // EventTarget overrides. + virtual const AtomicString& interfaceName() const OVERRIDE; + virtual ExecutionContext* executionContext() const OVERRIDE; + virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture = false) OVERRIDE; + virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture = false) OVERRIDE; + virtual void removeAllEventListeners() OVERRIDE; + + // ActiveDOMObject overrides. + virtual bool hasPendingActivity() const OVERRIDE; + virtual void stop() OVERRIDE; + + DEFINE_ATTRIBUTE_EVENT_LISTENER(typechange); + +private: + explicit NetworkInformation(ExecutionContext*); + void startObserving(); + void stopObserving(); + + // Touched only on context thread. + blink::WebConnectionType m_type; + + // Whether this object is listening for events from NetworkStateNotifier. + bool m_observing; + + // Whether ActiveDOMObject::stop has been called. + bool m_contextStopped; +}; + +} // namespace WebCore + +#endif // NetworkInformation_h diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.idl b/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.idl new file mode 100644 index 00000000000..7a12c36374a --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/NetworkInformation.idl @@ -0,0 +1,23 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +enum ConnectionType { + "cellular", + "bluetooth", + "ethernet", + "wifi", + "other", + "none" +}; + +[ + RuntimeEnabled=NetworkInformation, + Exposed=Window&Worker, + WillBeGarbageCollected, + ActiveDOMObject +] interface NetworkInformation : EventTarget { + readonly attribute ConnectionType type; + attribute EventHandler ontypechange; +}; + diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.cpp b/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.cpp new file mode 100644 index 00000000000..993433d1172 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.cpp @@ -0,0 +1,60 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/netinfo/WorkerNavigatorNetworkInformation.h" + +#include "core/workers/WorkerNavigator.h" +#include "modules/netinfo/NetworkInformation.h" + +namespace WebCore { + +WorkerNavigatorNetworkInformation::WorkerNavigatorNetworkInformation(WorkerNavigator& navigator, ExecutionContext* context) +{ +} + +WorkerNavigatorNetworkInformation::~WorkerNavigatorNetworkInformation() +{ +} + +WorkerNavigatorNetworkInformation& WorkerNavigatorNetworkInformation::from(WorkerNavigator& navigator, ExecutionContext* context) +{ + WorkerNavigatorNetworkInformation* supplement = toWorkerNavigatorNetworkInformation(navigator, context); + if (!supplement) { + supplement = new WorkerNavigatorNetworkInformation(navigator, context); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; +} + +WorkerNavigatorNetworkInformation* WorkerNavigatorNetworkInformation::toWorkerNavigatorNetworkInformation(WorkerNavigator& navigator, ExecutionContext* context) +{ + return static_cast<WorkerNavigatorNetworkInformation*>(WillBeHeapSupplement<WorkerNavigator>::from(navigator, supplementName())); +} + +const char* WorkerNavigatorNetworkInformation::supplementName() +{ + return "WorkerNavigatorNetworkInformation"; +} + +NetworkInformation* WorkerNavigatorNetworkInformation::connection(ExecutionContext* context, WorkerNavigator& navigator) +{ + return WorkerNavigatorNetworkInformation::from(navigator, context).connection(context); +} + +void WorkerNavigatorNetworkInformation::trace(Visitor* visitor) +{ + visitor->trace(m_connection); + WillBeHeapSupplement<WorkerNavigator>::trace(visitor); +} + +NetworkInformation* WorkerNavigatorNetworkInformation::connection(ExecutionContext* context) +{ + ASSERT(context); + if (!m_connection) + m_connection = NetworkInformation::create(context); + return m_connection.get(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.h b/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.h new file mode 100644 index 00000000000..0b48bcf317a --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.h @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WorkerNavigatorNetworkInformation_h +#define WorkerNavigatorNetworkInformation_h + +#include "platform/Supplementable.h" + +namespace WebCore { + +class ExecutionContext; +class NetworkInformation; +class WorkerNavigator; + +class WorkerNavigatorNetworkInformation FINAL + : public NoBaseWillBeGarbageCollectedFinalized<WorkerNavigatorNetworkInformation> + , public WillBeHeapSupplement<WorkerNavigator> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WorkerNavigatorNetworkInformation); + +public: + virtual ~WorkerNavigatorNetworkInformation(); + static WorkerNavigatorNetworkInformation& from(WorkerNavigator&, ExecutionContext*); + static WorkerNavigatorNetworkInformation* toWorkerNavigatorNetworkInformation(WorkerNavigator&, ExecutionContext*); + static const char* supplementName(); + + static NetworkInformation* connection(ExecutionContext*, WorkerNavigator&); + + virtual void trace(Visitor*) OVERRIDE; + +private: + WorkerNavigatorNetworkInformation(WorkerNavigator&, ExecutionContext*); + NetworkInformation* connection(ExecutionContext*); + + RefPtrWillBeMember<NetworkInformation> m_connection; +}; + +} // namespace WebCore + +#endif // WorkerNavigatorNetworkInformation_h diff --git a/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.idl b/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.idl new file mode 100644 index 00000000000..a2126fa44a6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/netinfo/WorkerNavigatorNetworkInformation.idl @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=NetworkInformation, + Exposed=Worker +] partial interface WorkerNavigator { + [CallWith=ExecutionContext] readonly attribute NetworkInformation connection; +}; diff --git a/chromium/third_party/WebKit/Source/modules/notifications/DOMWindowNotifications.cpp b/chromium/third_party/WebKit/Source/modules/notifications/DOMWindowNotifications.cpp deleted file mode 100644 index 51df57adda4..00000000000 --- a/chromium/third_party/WebKit/Source/modules/notifications/DOMWindowNotifications.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/notifications/DOMWindowNotifications.h" - -#if ENABLE(LEGACY_NOTIFICATIONS) - -#include "core/dom/Document.h" -#include "core/frame/DOMWindow.h" -#include "core/page/Page.h" -#include "modules/notifications/NotificationCenter.h" -#include "modules/notifications/NotificationController.h" - -namespace WebCore { - -DOMWindowNotifications::DOMWindowNotifications(DOMWindow* window) - : DOMWindowProperty(window->frame()) - , m_window(window) -{ -} - -DOMWindowNotifications::~DOMWindowNotifications() -{ -} - -const char* DOMWindowNotifications::supplementName() -{ - return "DOMWindowNotifications"; -} - -DOMWindowNotifications* DOMWindowNotifications::from(DOMWindow* window) -{ - DOMWindowNotifications* supplement = static_cast<DOMWindowNotifications*>(Supplement<DOMWindow>::from(window, supplementName())); - if (!supplement) { - supplement = new DOMWindowNotifications(window); - Supplement<DOMWindow>::provideTo(window, supplementName(), adoptPtr(supplement)); - } - return supplement; -} - -NotificationCenter* DOMWindowNotifications::webkitNotifications(DOMWindow* window) -{ - return DOMWindowNotifications::from(window)->webkitNotifications(); -} - -void DOMWindowNotifications::willDestroyGlobalObjectInFrame() -{ - m_notificationCenter = nullptr; - DOMWindowProperty::willDestroyGlobalObjectInFrame(); -} - -void DOMWindowNotifications::willDetachGlobalObjectFromFrame() -{ - m_notificationCenter = nullptr; - DOMWindowProperty::willDetachGlobalObjectFromFrame(); -} - -NotificationCenter* DOMWindowNotifications::webkitNotifications() -{ - if (!m_window->isCurrentlyDisplayedInFrame()) - return 0; - - if (m_notificationCenter) - return m_notificationCenter.get(); - - Document* document = m_window->document(); - if (!document) - return 0; - - Page* page = document->page(); - if (!page) - return 0; - - NotificationClient* provider = NotificationController::clientFrom(page); - if (provider) - m_notificationCenter = NotificationCenter::create(document, provider); - - return m_notificationCenter.get(); -} - -} // namespace WebCore - -#endif // ENABLE(LEGACY_NOTIFICATIONS) diff --git a/chromium/third_party/WebKit/Source/modules/notifications/Notification.cpp b/chromium/third_party/WebKit/Source/modules/notifications/Notification.cpp index d2c9a0bd4b7..4030151d7cb 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/Notification.cpp +++ b/chromium/third_party/WebKit/Source/modules/notifications/Notification.cpp @@ -1,6 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2009, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2013 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -35,15 +34,17 @@ #include "bindings/v8/Dictionary.h" #include "bindings/v8/ScriptWrappable.h" #include "core/dom/Document.h" -#include "core/dom/ExecutionContext.h" +#include "core/frame/UseCounter.h" +#include "core/page/WindowFocusAllowedIndicator.h" +#include "modules/notifications/NotificationClient.h" #include "modules/notifications/NotificationController.h" namespace WebCore { -PassRefPtr<Notification> Notification::create(ExecutionContext* context, const String& title, const Dictionary& options) +Notification* Notification::create(ExecutionContext* context, const String& title, const Dictionary& options) { - NotificationClient* client = NotificationController::clientFrom(toDocument(context)->page()); - RefPtr<Notification> notification(adoptRef(new Notification(context, title, client))); + NotificationClient& client = NotificationController::clientFrom(toDocument(context)->frame()); + Notification* notification = adoptRefCountedGarbageCollectedWillBeNoop(new Notification(title, context, &client)); String argument; if (options.get("body", argument)) @@ -61,13 +62,18 @@ PassRefPtr<Notification> Notification::create(ExecutionContext* context, const S } notification->suspendIfNeeded(); - return notification.release(); + return notification; } -Notification::Notification(ExecutionContext* context, const String& title, NotificationClient* client) - : NotificationBase(title, context, client) - , m_asyncRunner(adoptPtr(new AsyncMethodRunner<Notification>(this, &Notification::showSoon))) +Notification::Notification(const String& title, ExecutionContext* context, NotificationClient* client) + : ActiveDOMObject(context) + , m_title(title) + , m_dir("auto") + , m_state(Idle) + , m_client(client) + , m_asyncRunner(adoptPtr(new AsyncMethodRunner<Notification>(this, &Notification::show))) { + ASSERT(m_client); ScriptWrappable::init(this); m_asyncRunner->runAsync(); @@ -77,16 +83,101 @@ Notification::~Notification() { } +void Notification::show() +{ + ASSERT(m_state == Idle); + if (!toDocument(executionContext())->page()) + return; + + if (m_client->checkPermission(executionContext()) != NotificationClient::PermissionAllowed) { + dispatchErrorEvent(); + return; + } + + if (m_client->show(this)) + m_state = Showing; +} + +void Notification::close() +{ + switch (m_state) { + case Idle: + break; + case Showing: + m_client->close(this); + break; + case Closed: + break; + } +} + +void Notification::dispatchShowEvent() +{ + dispatchEvent(Event::create(EventTypeNames::show)); +} + +void Notification::dispatchClickEvent() +{ + UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); + WindowFocusAllowedIndicator windowFocusAllowed; + dispatchEvent(Event::create(EventTypeNames::click)); +} + +void Notification::dispatchErrorEvent() +{ + dispatchEvent(Event::create(EventTypeNames::error)); +} + +void Notification::dispatchCloseEvent() +{ + dispatchEvent(Event::create(EventTypeNames::close)); + m_state = Closed; +} + +TextDirection Notification::direction() const +{ + // FIXME: Resolve dir()=="auto" against the document. + return dir() == "rtl" ? RTL : LTR; +} + +const String& Notification::permissionString(NotificationClient::Permission permission) +{ + DEFINE_STATIC_LOCAL(const String, allowedPermission, ("granted")); + DEFINE_STATIC_LOCAL(const String, deniedPermission, ("denied")); + DEFINE_STATIC_LOCAL(const String, defaultPermission, ("default")); + + switch (permission) { + case NotificationClient::PermissionAllowed: + return allowedPermission; + case NotificationClient::PermissionDenied: + return deniedPermission; + case NotificationClient::PermissionNotAllowed: + return defaultPermission; + } + + ASSERT_NOT_REACHED(); + return deniedPermission; +} + const String& Notification::permission(ExecutionContext* context) { ASSERT(toDocument(context)->page()); - return permissionString(NotificationController::from(toDocument(context)->page())->client()->checkPermission(context)); + + UseCounter::count(context, UseCounter::NotificationPermission); + return permissionString(NotificationController::clientFrom(toDocument(context)->frame()).checkPermission(context)); } void Notification::requestPermission(ExecutionContext* context, PassOwnPtr<NotificationPermissionCallback> callback) { ASSERT(toDocument(context)->page()); - NotificationController::from(toDocument(context)->page())->client()->requestPermission(context, callback); + NotificationController::clientFrom(toDocument(context)->frame()).requestPermission(context, callback); +} + +bool Notification::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) +{ + ASSERT(m_state != Closed); + + return EventTarget::dispatchEvent(event); } const AtomicString& Notification::interfaceName() const @@ -96,20 +187,19 @@ const AtomicString& Notification::interfaceName() const void Notification::stop() { - NotificationBase::stop(); + if (m_client) + m_client->notificationObjectDestroyed(this); + if (m_asyncRunner) m_asyncRunner->stop(); -} -bool Notification::hasPendingActivity() const -{ - return NotificationBase::hasPendingActivity() || (m_asyncRunner && m_asyncRunner->isActive()); + m_client = 0; + m_state = Closed; } -void Notification::showSoon() +bool Notification::hasPendingActivity() const { - ASSERT(executionContext()->isDocument()); - show(); + return m_state == Showing || (m_asyncRunner && m_asyncRunner->isActive()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/notifications/Notification.h b/chromium/third_party/WebKit/Source/modules/notifications/Notification.h index 5ed78272f58..86bf1abf01f 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/Notification.h +++ b/chromium/third_party/WebKit/Source/modules/notifications/Notification.h @@ -1,6 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2009, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2013 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -32,45 +31,104 @@ #ifndef Notification_h #define Notification_h -#include "modules/notifications/NotificationBase.h" +#include "bindings/v8/ScriptWrappable.h" +#include "core/dom/ActiveDOMObject.h" +#include "modules/EventTargetModules.h" +#include "modules/notifications/NotificationClient.h" #include "platform/AsyncMethodRunner.h" +#include "platform/heap/Handle.h" +#include "platform/text/TextDirection.h" +#include "platform/weborigin/KURL.h" #include "wtf/OwnPtr.h" -#include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { class Dictionary; class ExecutionContext; -class NotificationClient; class NotificationPermissionCallback; -class Notification : public RefCounted<Notification>, public NotificationBase { - REFCOUNTED_EVENT_TARGET(Notification); - +class Notification : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<Notification>, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData { + DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<Notification>); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(Notification); public: - static PassRefPtr<Notification> create(ExecutionContext*, const String& title, const Dictionary& options); + static Notification* create(ExecutionContext*, const String& title, const Dictionary& options); virtual ~Notification(); + void close(); + + DEFINE_ATTRIBUTE_EVENT_LISTENER(click); + DEFINE_ATTRIBUTE_EVENT_LISTENER(show); + DEFINE_ATTRIBUTE_EVENT_LISTENER(error); + DEFINE_ATTRIBUTE_EVENT_LISTENER(close); + + void dispatchShowEvent(); + void dispatchClickEvent(); + void dispatchErrorEvent(); + void dispatchCloseEvent(); + + String title() const { return m_title; } + String dir() const { return m_dir; } + String lang() const { return m_lang; } + String body() const { return m_body; } + String tag() const { return m_tag; } + String icon() const { return m_iconUrl; } + + TextDirection direction() const; + KURL iconURL() const { return m_iconUrl; } + + static const String& permissionString(NotificationClient::Permission); static const String& permission(ExecutionContext*); static void requestPermission(ExecutionContext*, PassOwnPtr<NotificationPermissionCallback> = nullptr); - // EventTarget interface + // EventTarget interface. + virtual ExecutionContext* executionContext() const OVERRIDE FINAL { return ActiveDOMObject::executionContext(); } + virtual bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>) OVERRIDE FINAL; virtual const AtomicString& interfaceName() const OVERRIDE; - // ActiveDOMObject interface + // ActiveDOMObject interface. virtual void stop() OVERRIDE; virtual bool hasPendingActivity() const OVERRIDE; private: - Notification(ExecutionContext*, const String& title, NotificationClient*); + Notification(const String& title, ExecutionContext*, NotificationClient*); + + // Calling show() may start asynchronous operation. If this object has + // a V8 wrapper, hasPendingActivity() prevents the wrapper from being + // collected while m_state is Showing, and so this instance stays alive + // until the operation completes. Otherwise, you need to hold a ref on this + // instance until the operation completes. + void show(); + + void setDir(const String& dir) { m_dir = dir; } + void setLang(const String& lang) { m_lang = lang; } + void setBody(const String& body) { m_body = body; } + void setIconUrl(KURL iconUrl) { m_iconUrl = iconUrl; } + void setTag(const String& tag) { m_tag = tag; } + +private: + String m_title; + String m_dir; + String m_lang; + String m_body; + String m_tag; + + KURL m_iconUrl; + + enum NotificationState { + Idle = 0, + Showing = 1, + Closed = 2, + }; + + NotificationState m_state; - void showSoon(); + NotificationClient* m_client; OwnPtr<AsyncMethodRunner<Notification> > m_asyncRunner; }; } // namespace WebCore -#endif // Notifications_h +#endif // Notification_h diff --git a/chromium/third_party/WebKit/Source/modules/notifications/Notification.idl b/chromium/third_party/WebKit/Source/modules/notifications/Notification.idl index 1ef74c48660..51a26d91389 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/Notification.idl +++ b/chromium/third_party/WebKit/Source/modules/notifications/Notification.idl @@ -30,6 +30,7 @@ */ [ + GarbageCollected, ActiveDOMObject, Constructor(DOMString title, [Default=Undefined] optional Dictionary options), ConstructorCallWith=ExecutionContext, diff --git a/chromium/third_party/WebKit/Source/modules/notifications/NotificationBase.cpp b/chromium/third_party/WebKit/Source/modules/notifications/NotificationBase.cpp deleted file mode 100644 index eab6d928c99..00000000000 --- a/chromium/third_party/WebKit/Source/modules/notifications/NotificationBase.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/notifications/NotificationBase.h" - -#include "core/dom/Document.h" -#include "core/page/WindowFocusAllowedIndicator.h" -#include "modules/notifications/NotificationController.h" - -namespace WebCore { - -NotificationBase::NotificationBase(const String& title, ExecutionContext* context, NotificationClient* client) - : ActiveDOMObject(context) - , m_title(title) - , m_dir("auto") - , m_state(Idle) - , m_client(client) -{ - ASSERT(m_client); -} - -NotificationBase::~NotificationBase() -{ -} - -void NotificationBase::show() -{ - // prevent double-showing - if (m_state == Idle) { - if (!toDocument(executionContext())->page()) - return; - if (NotificationController::from(toDocument(executionContext())->page())->client()->checkPermission(executionContext()) != NotificationClient::PermissionAllowed) { - dispatchErrorEvent(); - return; - } - if (m_client->show(this)) { - m_state = Showing; - } - } -} - -void NotificationBase::close() -{ - switch (m_state) { - case Idle: - break; - case Showing: - m_client->cancel(this); - break; - case Closed: - break; - } -} - -void NotificationBase::dispatchShowEvent() -{ - dispatchEvent(Event::create(EventTypeNames::show)); -} - -void NotificationBase::dispatchClickEvent() -{ - UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); - WindowFocusAllowedIndicator windowFocusAllowed; - dispatchEvent(Event::create(EventTypeNames::click)); -} - -void NotificationBase::dispatchErrorEvent() -{ - dispatchEvent(Event::create(EventTypeNames::error)); -} - -void NotificationBase::dispatchCloseEvent() -{ - dispatchEvent(Event::create(EventTypeNames::close)); - m_state = Closed; -} - -TextDirection NotificationBase::direction() const -{ - // FIXME: Resolve dir()=="auto" against the document. - return dir() == "rtl" ? RTL : LTR; -} - -const String& NotificationBase::permissionString(NotificationClient::Permission permission) -{ - DEFINE_STATIC_LOCAL(const String, allowedPermission, ("granted")); - DEFINE_STATIC_LOCAL(const String, deniedPermission, ("denied")); - DEFINE_STATIC_LOCAL(const String, defaultPermission, ("default")); - - switch (permission) { - case NotificationClient::PermissionAllowed: - return allowedPermission; - case NotificationClient::PermissionDenied: - return deniedPermission; - case NotificationClient::PermissionNotAllowed: - return defaultPermission; - } - - ASSERT_NOT_REACHED(); - return deniedPermission; -} - -bool NotificationBase::dispatchEvent(PassRefPtr<Event> event) -{ - // Do not dispatch if the context is gone. - if (!executionContext()) - return false; - - return EventTarget::dispatchEvent(event); -} - -void NotificationBase::stop() -{ - if (m_client) - m_client->notificationObjectDestroyed(this); - - m_client = 0; - m_state = Closed; -} - -bool NotificationBase::hasPendingActivity() const -{ - return m_state == Showing; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/notifications/NotificationBase.h b/chromium/third_party/WebKit/Source/modules/notifications/NotificationBase.h deleted file mode 100644 index 4baea6bd975..00000000000 --- a/chromium/third_party/WebKit/Source/modules/notifications/NotificationBase.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NotificationBase_h -#define NotificationBase_h - -#include "bindings/v8/ScriptWrappable.h" -#include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" -#include "modules/notifications/NotificationClient.h" -#include "platform/text/TextDirection.h" -#include "platform/weborigin/KURL.h" - -namespace WebCore { - -class ExecutionContext; -class NotificationClient; - -class NotificationBase : public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData { -public: - virtual ~NotificationBase(); - - // Calling show() may start asynchronous operation. If this object has - // a V8 wrapper, hasPendingActivity() prevents the wrapper from being - // collected while m_state is Showing, and so this instance stays alive - // until the operation completes. Otherwise, you need to hold a ref on this - // instance until the operation completes. - void show(); - - void close(); - - DEFINE_ATTRIBUTE_EVENT_LISTENER(click); - DEFINE_ATTRIBUTE_EVENT_LISTENER(show); - DEFINE_ATTRIBUTE_EVENT_LISTENER(error); - DEFINE_ATTRIBUTE_EVENT_LISTENER(close); - - void dispatchShowEvent(); - void dispatchClickEvent(); - void dispatchErrorEvent(); - void dispatchCloseEvent(); - - String title() const { return m_title; } - String dir() const { return m_dir; } - String lang() const { return m_lang; } - String body() const { return m_body; } - String tag() const { return m_tag; } - String icon() const { return m_iconUrl; } - - TextDirection direction() const; - KURL iconURL() const { return m_iconUrl; } - - // FIXME: This should be made protected once legacy notifications have been removed. - void setDir(const String& dir) { m_dir = dir; } - - static const String& permissionString(NotificationClient::Permission); - - // EventTarget interface - virtual ExecutionContext* executionContext() const OVERRIDE { return ActiveDOMObject::executionContext(); } - virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE; - - // ActiveDOMObject interface - virtual void stop() OVERRIDE; - virtual bool hasPendingActivity() const OVERRIDE; - -protected: - NotificationBase(const String& title, ExecutionContext*, NotificationClient*); - - void setLang(const String& lang) { m_lang = lang; } - void setBody(const String& body) { m_body = body; } - void setIconUrl(KURL iconUrl) { m_iconUrl = iconUrl; } - void setTag(const String& tag) { m_tag = tag; } - -private: - String m_title; - String m_dir; - String m_lang; - String m_body; - String m_tag; - - KURL m_iconUrl; - - enum NotificationState { - Idle = 0, - Showing = 1, - Closed = 2, - }; - - NotificationState m_state; - - NotificationClient* m_client; -}; - -} // namespace WebCore - -#endif // NotificationBase_h diff --git a/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.cpp b/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.cpp deleted file mode 100644 index 952bd2a6530..00000000000 --- a/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(LEGACY_NOTIFICATIONS) - -#include "modules/notifications/NotificationCenter.h" - -#include "core/dom/Document.h" -#include "core/workers/WorkerGlobalScope.h" -#include "modules/notifications/NotificationClient.h" -#include "platform/weborigin/SecurityOrigin.h" - -namespace WebCore { - -PassRefPtr<NotificationCenter> NotificationCenter::create(ExecutionContext* context, NotificationClient* client) -{ - RefPtr<NotificationCenter> notificationCenter(adoptRef(new NotificationCenter(context, client))); - notificationCenter->suspendIfNeeded(); - return notificationCenter.release(); -} - -NotificationCenter::NotificationCenter(ExecutionContext* context, NotificationClient* client) - : ActiveDOMObject(context) - , m_client(client) -{ - ScriptWrappable::init(this); -} - -int NotificationCenter::checkPermission() -{ - if (!client() || !executionContext()) - return NotificationClient::PermissionDenied; - - switch (executionContext()->securityOrigin()->canShowNotifications()) { - case SecurityOrigin::AlwaysAllow: - return NotificationClient::PermissionAllowed; - case SecurityOrigin::AlwaysDeny: - return NotificationClient::PermissionDenied; - case SecurityOrigin::Ask: - return m_client->checkPermission(executionContext()); - } - - ASSERT_NOT_REACHED(); - return m_client->checkPermission(executionContext()); -} - -void NotificationCenter::requestPermission(PassOwnPtr<VoidCallback> callback) -{ - if (!client() || !executionContext()) - return; - - switch (executionContext()->securityOrigin()->canShowNotifications()) { - case SecurityOrigin::AlwaysAllow: - case SecurityOrigin::AlwaysDeny: { - m_callbacks.add(NotificationRequestCallback::createAndStartTimer(this, callback)); - return; - } - case SecurityOrigin::Ask: - return m_client->requestPermission(executionContext(), callback); - } - - ASSERT_NOT_REACHED(); - m_client->requestPermission(executionContext(), callback); -} - -void NotificationCenter::stop() -{ - m_client = 0; -} - -void NotificationCenter::requestTimedOut(NotificationCenter::NotificationRequestCallback* request) -{ - m_callbacks.remove(request); -} - -PassRefPtr<NotificationCenter::NotificationRequestCallback> NotificationCenter::NotificationRequestCallback::createAndStartTimer(NotificationCenter* center, PassOwnPtr<VoidCallback> callback) -{ - RefPtr<NotificationCenter::NotificationRequestCallback> requestCallback = adoptRef(new NotificationCenter::NotificationRequestCallback(center, callback)); - requestCallback->startTimer(); - return requestCallback.release(); -} - -NotificationCenter::NotificationRequestCallback::NotificationRequestCallback(NotificationCenter* center, PassOwnPtr<VoidCallback> callback) - : m_notificationCenter(center) - , m_timer(this, &NotificationCenter::NotificationRequestCallback::timerFired) - , m_callback(callback) -{ -} - -void NotificationCenter::NotificationRequestCallback::startTimer() -{ - m_timer.startOneShot(0); -} - -void NotificationCenter::NotificationRequestCallback::timerFired(Timer<NotificationCenter::NotificationRequestCallback>*) -{ - if (m_callback) - m_callback->handleEvent(); - m_notificationCenter->requestTimedOut(this); -} - -} // namespace WebCore - -#endif // ENABLE(LEGACY_NOTIFICATIONS) diff --git a/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.h b/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.h deleted file mode 100644 index 14c479f33aa..00000000000 --- a/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NotificationCenter_h -#define NotificationCenter_h - -#if ENABLE(LEGACY_NOTIFICATIONS) - -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptWrappable.h" -#include "core/dom/ExceptionCode.h" -#include "core/dom/ExecutionContext.h" -#include "core/html/VoidCallback.h" -#include "modules/notifications/WebKitNotification.h" -#include "platform/Supplementable.h" -#include "platform/Timer.h" -#include "wtf/OwnPtr.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" - -namespace WebCore { - -class NotificationClient; -class VoidCallback; - -class NotificationCenter : public RefCounted<NotificationCenter>, public ScriptWrappable, public ActiveDOMObject { -public: - static PassRefPtr<NotificationCenter> create(ExecutionContext*, NotificationClient*); - - PassRefPtr<WebKitNotification> createNotification(const String& iconUrl, const String& title, const String& body, ExceptionState& exceptionState) - { - if (!client()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return 0; - } - return WebKitNotification::create(title, body, iconUrl, executionContext(), exceptionState, this); - } - - NotificationClient* client() const { return m_client; } - - int checkPermission(); - void requestPermission(PassOwnPtr<VoidCallback> = nullptr); - - virtual void stop() OVERRIDE; - -private: - NotificationCenter(ExecutionContext*, NotificationClient*); - - class NotificationRequestCallback : public RefCounted<NotificationRequestCallback> { - public: - static PassRefPtr<NotificationRequestCallback> createAndStartTimer(NotificationCenter*, PassOwnPtr<VoidCallback>); - void startTimer(); - void timerFired(Timer<NotificationRequestCallback>*); - private: - NotificationRequestCallback(NotificationCenter*, PassOwnPtr<VoidCallback>); - - RefPtr<NotificationCenter> m_notificationCenter; - Timer<NotificationRequestCallback> m_timer; - OwnPtr<VoidCallback> m_callback; - }; - - void requestTimedOut(NotificationRequestCallback*); - - NotificationClient* m_client; - HashSet<RefPtr<NotificationRequestCallback> > m_callbacks; -}; - -} // namespace WebCore - -#endif // ENABLE(LEGACY_NOTIFICATIONS) - -#endif // NotificationCenter_h diff --git a/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.idl b/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.idl deleted file mode 100644 index bdacd3972ed..00000000000 --- a/chromium/third_party/WebKit/Source/modules/notifications/NotificationCenter.idl +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - NoInterfaceObject, - Conditional=LEGACY_NOTIFICATIONS, - ActiveDOMObject -] interface NotificationCenter { - [MeasureAs=LegacyTextNotifications, ActivityLogging=ForAllWorlds, RaisesException] WebKitNotification createNotification(DOMString iconUrl, DOMString title, DOMString body); - - long checkPermission(); - void requestPermission(optional VoidCallback callback); -}; - diff --git a/chromium/third_party/WebKit/Source/modules/notifications/NotificationClient.h b/chromium/third_party/WebKit/Source/modules/notifications/NotificationClient.h index f918245534f..ab94cbde934 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/NotificationClient.h +++ b/chromium/third_party/WebKit/Source/modules/notifications/NotificationClient.h @@ -34,16 +34,18 @@ #include "core/html/VoidCallback.h" #include "modules/notifications/NotificationPermissionCallback.h" -#include "wtf/PassRefPtr.h" +#include "wtf/PassOwnPtr.h" namespace WebCore { class ExecutionContext; -class NotificationBase; +class Notification; class NotificationClient { public: + virtual ~NotificationClient() { } + enum Permission { PermissionAllowed, // User has allowed notifications PermissionNotAllowed, // User has not yet allowed @@ -51,29 +53,23 @@ public: }; // Requests that a notification be shown. - virtual bool show(NotificationBase*) = 0; + virtual bool show(Notification*) = 0; - // Requests that a notification that has already been shown be canceled. - virtual void cancel(NotificationBase*) = 0; + // Requests that a notification that has already been shown be closed. + virtual void close(Notification*) = 0; // Informs the presenter that a Notification object has been destroyed // (such as by a page transition). The presenter may continue showing // the notification, but must not attempt to call the event handlers. - virtual void notificationObjectDestroyed(NotificationBase*) = 0; + virtual void notificationObjectDestroyed(Notification*) = 0; -#if ENABLE(LEGACY_NOTIFICATIONS) // Requests user permission to show desktop notifications from a particular // script context. The callback parameter should be run when the user has // made a decision. - virtual void requestPermission(ExecutionContext*, PassOwnPtr<VoidCallback>) = 0; -#endif virtual void requestPermission(ExecutionContext*, PassOwnPtr<NotificationPermissionCallback>) = 0; // Checks the current level of permission. virtual Permission checkPermission(ExecutionContext*) = 0; - -protected: - virtual ~NotificationClient() { } }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/notifications/NotificationController.cpp b/chromium/third_party/WebKit/Source/modules/notifications/NotificationController.cpp index b504cccf6fa..16c2863019f 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/NotificationController.cpp +++ b/chromium/third_party/WebKit/Source/modules/notifications/NotificationController.cpp @@ -31,7 +31,7 @@ namespace WebCore { -NotificationController::NotificationController(NotificationClient* client) +NotificationController::NotificationController(PassOwnPtr<NotificationClient> client) : m_client(client) { } @@ -40,16 +40,16 @@ NotificationController::~NotificationController() { } -PassOwnPtr<NotificationController> NotificationController::create(NotificationClient* client) +PassOwnPtrWillBeRawPtr<NotificationController> NotificationController::create(PassOwnPtr<NotificationClient> client) { - return adoptPtr(new NotificationController(client)); + return adoptPtrWillBeNoop(new NotificationController(client)); } -NotificationClient* NotificationController::clientFrom(Page* page) +NotificationClient& NotificationController::clientFrom(LocalFrame* frame) { - if (NotificationController* controller = NotificationController::from(page)) - return controller->client(); - return 0; + NotificationController* controller = NotificationController::from(frame); + ASSERT(controller); + return controller->client(); } const char* NotificationController::supplementName() @@ -57,9 +57,9 @@ const char* NotificationController::supplementName() return "NotificationController"; } -void provideNotification(Page* page, NotificationClient* client) +void provideNotification(LocalFrame& frame, PassOwnPtr<NotificationClient> client) { - NotificationController::provideTo(page, NotificationController::supplementName(), NotificationController::create(client)); + NotificationController::provideTo(frame, NotificationController::supplementName(), NotificationController::create(client)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/notifications/NotificationController.h b/chromium/third_party/WebKit/Source/modules/notifications/NotificationController.h index 43e028afd79..22eea093e9e 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/NotificationController.h +++ b/chromium/third_party/WebKit/Source/modules/notifications/NotificationController.h @@ -26,7 +26,7 @@ #ifndef NotificationController_h #define NotificationController_h -#include "core/page/Page.h" +#include "core/frame/LocalFrame.h" #include "wtf/Forward.h" #include "wtf/Noncopyable.h" @@ -34,25 +34,28 @@ namespace WebCore { class NotificationClient; -class NotificationController : public Supplement<Page> { +class NotificationController FINAL : public NoBaseWillBeGarbageCollectedFinalized<NotificationController>, public WillBeHeapSupplement<LocalFrame> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NotificationController); WTF_MAKE_NONCOPYABLE(NotificationController); public: - ~NotificationController(); + virtual ~NotificationController(); - static PassOwnPtr<NotificationController> create(NotificationClient*); + static PassOwnPtrWillBeRawPtr<NotificationController> create(PassOwnPtr<NotificationClient>); static const char* supplementName(); - static NotificationController* from(Page* page) { return static_cast<NotificationController*>(Supplement<Page>::from(page, supplementName())); } - static NotificationClient* clientFrom(Page*); + static NotificationController* from(LocalFrame* frame) { return static_cast<NotificationController*>(WillBeHeapSupplement<LocalFrame>::from(frame, supplementName())); } + static NotificationClient& clientFrom(LocalFrame*); - NotificationClient* client() { return m_client; } + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<LocalFrame>::trace(visitor); } private: - explicit NotificationController(NotificationClient*); + explicit NotificationController(PassOwnPtr<NotificationClient>); - NotificationClient* m_client; + NotificationClient& client() { return *m_client; } + + OwnPtr<NotificationClient> m_client; }; -void provideNotification(Page*, NotificationClient*); +void provideNotification(LocalFrame&, PassOwnPtr<NotificationClient>); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/notifications/OWNERS b/chromium/third_party/WebKit/Source/modules/notifications/OWNERS new file mode 100644 index 00000000000..2fca67fdfda --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/notifications/OWNERS @@ -0,0 +1 @@ +peter@chromium.org
\ No newline at end of file diff --git a/chromium/third_party/WebKit/Source/modules/notifications/WebKitNotification.cpp b/chromium/third_party/WebKit/Source/modules/notifications/WebKitNotification.cpp deleted file mode 100644 index 44f09dc390d..00000000000 --- a/chromium/third_party/WebKit/Source/modules/notifications/WebKitNotification.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/notifications/WebKitNotification.h" - -#if ENABLE(LEGACY_NOTIFICATIONS) - -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptWrappable.h" -#include "core/dom/ExecutionContext.h" -#include "modules/notifications/NotificationCenter.h" -#include "modules/notifications/NotificationClient.h" - -namespace WebCore { - -PassRefPtr<WebKitNotification> WebKitNotification::create(const String& title, const String& body, const String& iconUrl, ExecutionContext* context, ExceptionState& es, PassRefPtr<NotificationCenter> provider) -{ - RefPtr<WebKitNotification> notification(adoptRef(new WebKitNotification(title, body, iconUrl, context, es, provider))); - notification->suspendIfNeeded(); - - return notification.release(); -} - -WebKitNotification::WebKitNotification(const String& title, const String& body, const String& iconUrl, ExecutionContext* context, ExceptionState& es, PassRefPtr<NotificationCenter> provider) - : NotificationBase(title, context, provider->client()) -{ - ScriptWrappable::init(this); - - if (provider->checkPermission() != NotificationClient::PermissionAllowed) { - es.throwSecurityError("Notification permission has not been granted."); - return; - } - - KURL icon = iconUrl.isEmpty() ? KURL() : executionContext()->completeURL(iconUrl); - if (!icon.isEmpty() && !icon.isValid()) { - es.throwDOMException(SyntaxError, "'" + iconUrl + "' is not a valid icon URL."); - return; - } - - setBody(body); - setIconUrl(icon); -} - -WebKitNotification::~WebKitNotification() -{ -} - -const AtomicString& WebKitNotification::interfaceName() const -{ - return EventTargetNames::WebKitNotification; -} - -} // namespace WebCore - -#endif // ENABLE(LEGACY_NOTIFICATIONS) diff --git a/chromium/third_party/WebKit/Source/modules/notifications/WorkerGlobalScopeNotifications.cpp b/chromium/third_party/WebKit/Source/modules/notifications/WorkerGlobalScopeNotifications.cpp deleted file mode 100644 index 20325ee5cde..00000000000 --- a/chromium/third_party/WebKit/Source/modules/notifications/WorkerGlobalScopeNotifications.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * Copyright (C) 2009, 2011 Google Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "config.h" -#include "modules/notifications/WorkerGlobalScopeNotifications.h" - -#if ENABLE(LEGACY_NOTIFICATIONS) - -#include "core/workers/WorkerGlobalScope.h" -#include "core/workers/WorkerThread.h" -#include "modules/notifications/NotificationCenter.h" - -namespace WebCore { - -WorkerGlobalScopeNotifications::WorkerGlobalScopeNotifications(WorkerGlobalScope* context) - : m_context(context) -{ -} - -WorkerGlobalScopeNotifications::~WorkerGlobalScopeNotifications() -{ -} - -const char* WorkerGlobalScopeNotifications::supplementName() -{ - return "WorkerGlobalScopeNotifications"; -} - -WorkerGlobalScopeNotifications* WorkerGlobalScopeNotifications::from(WorkerGlobalScope* context) -{ - WorkerGlobalScopeNotifications* supplement = static_cast<WorkerGlobalScopeNotifications*>(WorkerSupplement::from(context, supplementName())); - if (!supplement) { - supplement = new WorkerGlobalScopeNotifications(context); - WorkerSupplement::provideTo(context, supplementName(), adoptPtr(supplement)); - } - return supplement; -} - -NotificationCenter* WorkerGlobalScopeNotifications::webkitNotifications(WorkerGlobalScope* context) -{ - return WorkerGlobalScopeNotifications::from(context)->webkitNotifications(); -} - -NotificationCenter* WorkerGlobalScopeNotifications::webkitNotifications() -{ - if (!m_notificationCenter) - m_notificationCenter = NotificationCenter::create(m_context, m_context->thread()->getNotificationClient()); - return m_notificationCenter.get(); -} - -} // namespace WebCore - -#endif // ENABLE(LEGACY_NOTIFICATIONS) diff --git a/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.cpp b/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.cpp new file mode 100644 index 00000000000..4e7de44b177 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014, Opera Software ASA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/performance/SharedWorkerPerformance.h" + +#include "core/dom/Document.h" +#include "core/dom/ExecutionContext.h" +#include "core/loader/DocumentLoadTiming.h" +#include "core/loader/DocumentLoader.h" +#include "core/workers/SharedWorker.h" + +namespace WebCore { + +SharedWorkerPerformance::SharedWorkerPerformance() + : m_timeOrigin(monotonicallyIncreasingTime()) +{ +} + +const char* SharedWorkerPerformance::supplementName() +{ + return "SharedWorkerPerformance"; +} + +SharedWorkerPerformance& SharedWorkerPerformance::from(SharedWorker& sharedWorker) +{ + SharedWorkerPerformance* supplement = static_cast<SharedWorkerPerformance*>(WillBeHeapSupplement<SharedWorker>::from(sharedWorker, supplementName())); + if (!supplement) { + supplement = new SharedWorkerPerformance(); + provideTo(sharedWorker, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; +} + +double SharedWorkerPerformance::workerStart(ExecutionContext* context, SharedWorker& sharedWorker) +{ + return SharedWorkerPerformance::from(sharedWorker).getWorkerStart(context, sharedWorker); +} + +double SharedWorkerPerformance::getWorkerStart(ExecutionContext* context, SharedWorker&) const +{ + ASSERT(context); + ASSERT(context->isDocument()); + Document* document = toDocument(context); + if (!document->loader()) + return 0; + + double navigationStart = document->loader()->timing()->navigationStart(); + return m_timeOrigin - navigationStart; +} + +} // namespace WebCore + diff --git a/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.h b/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.h new file mode 100644 index 00000000000..0aa2b564fbc --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Opera Software ASA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SharedWorkerPerformance_h +#define SharedWorkerPerformance_h + +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" + +namespace WebCore { + +class ExecutionContext; +class SharedWorker; + +class SharedWorkerPerformance FINAL : public NoBaseWillBeGarbageCollected<SharedWorkerPerformance>, public WillBeHeapSupplement<SharedWorker> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(SharedWorkerPerformance); +public: + static SharedWorkerPerformance& from(SharedWorker&); + + static double workerStart(ExecutionContext*, SharedWorker&); + double getWorkerStart(ExecutionContext*, SharedWorker&) const; + + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<SharedWorker>::trace(visitor); } + +private: + explicit SharedWorkerPerformance(); + static const char* supplementName(); + + double m_timeOrigin; +}; + +} // namespace WebCore + +#endif // SharedWorkerPerformance_h diff --git a/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.idl b/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.idl new file mode 100644 index 00000000000..ef8b36b7ab0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/performance/SharedWorkerPerformance.idl @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, Opera Software ASA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + RuntimeEnabled=HighResolutionTimeInWorkers, +] partial interface SharedWorker { + // See https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime2/Overview.html for details. + [CallWith=ExecutionContext] readonly attribute double workerStart; +}; diff --git a/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.cpp b/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.cpp index 3eb7adb356b..f0fe234731b 100644 --- a/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.cpp +++ b/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.cpp @@ -41,35 +41,37 @@ WorkerGlobalScopePerformance::WorkerGlobalScopePerformance() { } -WorkerGlobalScopePerformance::~WorkerGlobalScopePerformance() -{ -} - const char* WorkerGlobalScopePerformance::supplementName() { return "WorkerGlobalScopePerformance"; } -WorkerGlobalScopePerformance* WorkerGlobalScopePerformance::from(WorkerGlobalScope* context) +WorkerGlobalScopePerformance& WorkerGlobalScopePerformance::from(WorkerGlobalScope& context) { - WorkerGlobalScopePerformance* supplement = static_cast<WorkerGlobalScopePerformance*>(WorkerSupplement::from(context, supplementName())); + WorkerGlobalScopePerformance* supplement = static_cast<WorkerGlobalScopePerformance*>(WillBeHeapSupplement<WorkerGlobalScope>::from(context, supplementName())); if (!supplement) { supplement = new WorkerGlobalScopePerformance(); - provideTo(context, supplementName(), adoptPtr(supplement)); + provideTo(context, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -WorkerPerformance* WorkerGlobalScopePerformance::performance(WorkerGlobalScope* context) +WorkerPerformance* WorkerGlobalScopePerformance::performance(WorkerGlobalScope& context) { - return from(context)->getPerformance(context); + return from(context).performance(); } -WorkerPerformance* WorkerGlobalScopePerformance::getPerformance(WorkerGlobalScope* context) +WorkerPerformance* WorkerGlobalScopePerformance::performance() { if (!m_performance) - m_performance = WorkerPerformance::create(context); + m_performance = WorkerPerformance::create(); return m_performance.get(); } +void WorkerGlobalScopePerformance::trace(Visitor* visitor) +{ + visitor->trace(m_performance); + WillBeHeapSupplement<WorkerGlobalScope>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.h b/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.h index 9c1a153f275..52ce9ee44a7 100644 --- a/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.h +++ b/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.h @@ -31,26 +31,30 @@ #ifndef WorkerGlobalScopePerformance_h #define WorkerGlobalScopePerformance_h -#include "core/workers/WorkerSupplementable.h" +#include "modules/performance/WorkerPerformance.h" +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { -class WorkerPerformance; +class WorkerGlobalScope; -class WorkerGlobalScopePerformance : public WorkerSupplement { +class WorkerGlobalScopePerformance FINAL : public NoBaseWillBeGarbageCollected<WorkerGlobalScopePerformance>, public WillBeHeapSupplement<WorkerGlobalScope> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WorkerGlobalScopePerformance); public: - virtual ~WorkerGlobalScopePerformance(); - static WorkerGlobalScopePerformance* from(WorkerGlobalScope*); + static WorkerGlobalScopePerformance& from(WorkerGlobalScope&); - static WorkerPerformance* performance(WorkerGlobalScope*); + static WorkerPerformance* performance(WorkerGlobalScope&); + + virtual void trace(Visitor*); private: WorkerGlobalScopePerformance(); - WorkerPerformance* getPerformance(WorkerGlobalScope*); + WorkerPerformance* performance(); static const char* supplementName(); - RefPtr<WorkerPerformance> m_performance; + PersistentWillBeMember<WorkerPerformance> m_performance; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.idl b/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.idl index 1522a1d181e..0bbe7156fb5 100644 --- a/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.idl +++ b/chromium/third_party/WebKit/Source/modules/performance/WorkerGlobalScopePerformance.idl @@ -29,7 +29,7 @@ */ [ - RuntimeEnabled=HighResolutionTimeInWorkers + RuntimeEnabled=HighResolutionTimeInWorkers, ] partial interface WorkerGlobalScope { readonly attribute WorkerPerformance performance; }; diff --git a/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.cpp b/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.cpp index 67e77e1ba13..394fae19e9d 100644 --- a/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.cpp +++ b/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.cpp @@ -31,27 +31,34 @@ #include "config.h" #include "modules/performance/WorkerPerformance.h" +#include "core/timing/MemoryInfo.h" #include "core/workers/DedicatedWorkerGlobalScope.h" #include "core/workers/WorkerGlobalScope.h" #include "wtf/CurrentTime.h" namespace WebCore { -WorkerPerformance::WorkerPerformance(ExecutionContext* context) - : ContextLifecycleObserver(context) +WorkerPerformance::WorkerPerformance() { + ScriptWrappable::init(this); } WorkerPerformance::~WorkerPerformance() { } -double WorkerPerformance::now() const +double WorkerPerformance::now(ExecutionContext* context) const { - ExecutionContext* context = executionContext(); ASSERT(context); + ASSERT(context->isWorkerGlobalScope()); WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); return 1000.0 * (monotonicallyIncreasingTime() - workerGlobalScope->timeOrigin()); } +PassRefPtrWillBeRawPtr<MemoryInfo> WorkerPerformance::memory() const +{ + // FIXME: We shall not create a new object every time. + return MemoryInfo::create(); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.h b/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.h index 539b0e4e4ba..e7ab2356f0a 100644 --- a/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.h +++ b/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.h @@ -31,7 +31,9 @@ #ifndef WorkerPerformance_h #define WorkerPerformance_h +#include "bindings/v8/ScriptWrappable.h" #include "core/dom/ContextLifecycleObserver.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" @@ -39,16 +41,23 @@ namespace WebCore { class ExecutionContext; +class MemoryInfo; -class WorkerPerformance : public RefCounted<WorkerPerformance>, public ContextLifecycleObserver { +class WorkerPerformance : public GarbageCollectedFinalized<WorkerPerformance>, public ScriptWrappable { public: - static PassRefPtr<WorkerPerformance> create(ExecutionContext* context) { return adoptRef(new WorkerPerformance(context)); } + static WorkerPerformance* create() + { + return new WorkerPerformance(); + } ~WorkerPerformance(); - double now() const; + double now(ExecutionContext*) const; + PassRefPtrWillBeRawPtr<MemoryInfo> memory() const; + + void trace(Visitor*) { } private: - explicit WorkerPerformance(ExecutionContext*); + WorkerPerformance(); }; } diff --git a/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.idl b/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.idl index c4ab7fdbef7..df38289d8bb 100644 --- a/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.idl +++ b/chromium/third_party/WebKit/Source/modules/performance/WorkerPerformance.idl @@ -29,9 +29,12 @@ */ [ + GarbageCollected, NoInterfaceObject ] interface WorkerPerformance { // See https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime2/Overview.html for details. - double now(); + [CallWith=ExecutionContext] double now(); + + [RuntimeEnabled=MemoryInfoInWorkers] readonly attribute MemoryInfo memory; }; diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.cpp b/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.cpp new file mode 100644 index 00000000000..a3d7f16e940 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.cpp @@ -0,0 +1,55 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/push_messaging/NavigatorPushManager.h" + +#include "core/dom/Document.h" +#include "core/frame/Navigator.h" +#include "modules/push_messaging/PushManager.h" + +namespace WebCore { + +NavigatorPushManager::NavigatorPushManager() +{ +} + +NavigatorPushManager::~NavigatorPushManager() +{ +} + +const char* NavigatorPushManager::supplementName() +{ + return "NavigatorPushManager"; +} + +NavigatorPushManager& NavigatorPushManager::from(Navigator& navigator) +{ + NavigatorPushManager* supplement = static_cast<NavigatorPushManager*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); + if (!supplement) { + supplement = new NavigatorPushManager(); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; +} + +PushManager* NavigatorPushManager::push(Navigator& navigator) +{ + return NavigatorPushManager::from(navigator).pushManager(); +} + +PushManager* NavigatorPushManager::pushManager() +{ + if (!m_pushManager) + m_pushManager = PushManager::create(); + return m_pushManager.get(); +} + +void NavigatorPushManager::trace(Visitor* visitor) +{ + visitor->trace(m_pushManager); + WillBeHeapSupplement<Navigator>::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.h b/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.h new file mode 100644 index 00000000000..f62e635f51d --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.h @@ -0,0 +1,36 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NavigatorPushManager_h +#define NavigatorPushManager_h + +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" + +namespace WebCore { + +class Navigator; +class PushManager; + +class NavigatorPushManager FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorPushManager>, public WillBeHeapSupplement<Navigator> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorPushManager); +public: + virtual ~NavigatorPushManager(); + static NavigatorPushManager& from(Navigator&); + + static PushManager* push(Navigator&); + PushManager* pushManager(); + + void trace(Visitor*); + +private: + NavigatorPushManager(); + static const char* supplementName(); + + PersistentWillBeMember<PushManager> m_pushManager; +}; + +} // namespace WebCore + +#endif // NavigatorPushManager_h diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.idl b/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.idl new file mode 100644 index 00000000000..26db0dddc17 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/NavigatorPushManager.idl @@ -0,0 +1,9 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=PushMessaging, +] partial interface Navigator { + readonly attribute PushManager push; +}; diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/OWNERS b/chromium/third_party/WebKit/Source/modules/push_messaging/OWNERS new file mode 100644 index 00000000000..02b971fe8f5 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/OWNERS @@ -0,0 +1 @@ +mvanouwerkerk@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushController.cpp b/chromium/third_party/WebKit/Source/modules/push_messaging/PushController.cpp new file mode 100644 index 00000000000..e67829afcbc --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushController.cpp @@ -0,0 +1,40 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/push_messaging/PushController.h" + +#include "public/platform/WebPushClient.h" +#include "wtf/PassOwnPtr.h" + +namespace WebCore { + +PushController::PushController(blink::WebPushClient* client) + : m_client(client) +{ +} + +PassOwnPtrWillBeRawPtr<PushController> PushController::create(blink::WebPushClient* client) +{ + return adoptPtrWillBeNoop(new PushController(client)); +} + +blink::WebPushClient* PushController::clientFrom(Page* page) +{ + if (PushController* controller = PushController::from(page)) + return controller->client(); + return 0; +} + +const char* PushController::supplementName() +{ + return "PushController"; +} + +void providePushControllerTo(Page& page, blink::WebPushClient* client) +{ + PushController::provideTo(page, PushController::supplementName(), PushController::create(client)); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushController.h b/chromium/third_party/WebKit/Source/modules/push_messaging/PushController.h new file mode 100644 index 00000000000..15a338dfffb --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushController.h @@ -0,0 +1,44 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PushController_h +#define PushController_h + +#include "core/page/Page.h" +#include "platform/Supplementable.h" +#include "wtf/Forward.h" +#include "wtf/Noncopyable.h" +#include "wtf/PassOwnPtr.h" + +namespace blink { +class WebPushClient; +} // namespace blink + +namespace WebCore { + +class PushController FINAL : public NoBaseWillBeGarbageCollected<PushController>, public WillBeHeapSupplement<Page> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(PushController); + WTF_MAKE_NONCOPYABLE(PushController); + +public: + static PassOwnPtrWillBeRawPtr<PushController> create(blink::WebPushClient*); + static const char* supplementName(); + static PushController* from(Page* page) { return static_cast<PushController*>(WillBeHeapSupplement<Page>::from(page, supplementName())); } + static blink::WebPushClient* clientFrom(Page*); + + blink::WebPushClient* client() const { return m_client; } + + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Page>::trace(visitor); } + +private: + explicit PushController(blink::WebPushClient*); + + blink::WebPushClient* m_client; +}; + +void providePushControllerTo(Page&, blink::WebPushClient*); + +} // namespace WebCore + +#endif // PushController_h diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushError.cpp b/chromium/third_party/WebKit/Source/modules/push_messaging/PushError.cpp new file mode 100644 index 00000000000..8d3d9f826b6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushError.cpp @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/push_messaging/PushError.h" + +#include "core/dom/ExceptionCode.h" +#include "wtf/OwnPtr.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<DOMException> PushError::from(ScriptPromiseResolverWithContext*, WebType* webErrorRaw) +{ + OwnPtr<WebType> webError = adoptPtr(webErrorRaw); + switch (webError->errorType) { + case blink::WebPushError::ErrorTypeAbort: + return DOMException::create(AbortError, "Registration failed."); + case blink::WebPushError::ErrorTypeUnknown: + return DOMException::create(UnknownError); + } + ASSERT_NOT_REACHED(); + return DOMException::create(UnknownError); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushError.h b/chromium/third_party/WebKit/Source/modules/push_messaging/PushError.h new file mode 100644 index 00000000000..e8943b246f8 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushError.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PushError_h +#define PushError_h + +#include "core/dom/DOMException.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebPushError.h" + +namespace WebCore { + +class ScriptPromiseResolverWithContext; + +class PushError { + WTF_MAKE_NONCOPYABLE(PushError); +public: + // For CallbackPromiseAdapter. + typedef blink::WebPushError WebType; + static PassRefPtrWillBeRawPtr<DOMException> from(ScriptPromiseResolverWithContext*, WebType* webErrorRaw); + +private: + PushError() WTF_DELETED_FUNCTION; +}; + +} // namespace WebCore + +#endif // PushError_h diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.cpp b/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.cpp new file mode 100644 index 00000000000..6e54fa6f5b8 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.cpp @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/push_messaging/PushEvent.h" + +namespace WebCore { + +PushEventInit::PushEventInit() +{ +} + +PushEvent::PushEvent() +{ + ScriptWrappable::init(this); +} + +PushEvent::PushEvent(const AtomicString& type, const String& data) + : Event(type, /*canBubble=*/false, /*cancelable=*/false) + , m_data(data) +{ + ScriptWrappable::init(this); +} + +PushEvent::PushEvent(const AtomicString& type, const PushEventInit& initializer) + : Event(type, initializer) + , m_data(initializer.data) +{ + ScriptWrappable::init(this); +} + +PushEvent::~PushEvent() +{ +} + +const AtomicString& PushEvent::interfaceName() const +{ + return EventNames::PushEvent; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.h b/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.h new file mode 100644 index 00000000000..07ddca10166 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.h @@ -0,0 +1,51 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PushEvent_h +#define PushEvent_h + +#include "modules/EventModules.h" +#include "platform/heap/Handle.h" +#include "wtf/text/AtomicString.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +struct PushEventInit : public EventInit { + PushEventInit(); + + String data; +}; + +class PushEvent FINAL : public Event { +public: + static PassRefPtrWillBeRawPtr<PushEvent> create() + { + return adoptRefWillBeNoop(new PushEvent); + } + static PassRefPtrWillBeRawPtr<PushEvent> create(const AtomicString& type, const String& data) + { + return adoptRefWillBeNoop(new PushEvent(type, data)); + } + static PassRefPtrWillBeRawPtr<PushEvent> create(const AtomicString& type, const PushEventInit& initializer) + { + return adoptRefWillBeNoop(new PushEvent(type, initializer)); + } + + virtual ~PushEvent(); + + virtual const AtomicString& interfaceName() const OVERRIDE; + + String data() const { return m_data; } + +private: + PushEvent(); + PushEvent(const AtomicString& type, const String& data); + PushEvent(const AtomicString& type, const PushEventInit&); + String m_data; +}; + +} // namespace WebCore + +#endif // PushEvent_h diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.idl b/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.idl new file mode 100644 index 00000000000..a6a03ff8d78 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushEvent.idl @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + EventConstructor, + RuntimeEnabled=PushMessaging, +] interface PushEvent : Event { + [InitializedByEventConstructor] readonly attribute DOMString data; +}; diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.cpp b/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.cpp new file mode 100644 index 00000000000..ae888862bea --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.cpp @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/push_messaging/PushManager.h" + +#include "bindings/v8/CallbackPromiseAdapter.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "bindings/v8/ScriptState.h" +#include "core/dom/Document.h" +#include "core/dom/ExecutionContext.h" +#include "modules/push_messaging/PushController.h" +#include "modules/push_messaging/PushError.h" +#include "modules/push_messaging/PushRegistration.h" +#include "public/platform/WebPushClient.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +PushManager::PushManager() +{ + ScriptWrappable::init(this); +} + +PushManager::~PushManager() +{ +} + +ScriptPromise PushManager::registerPushMessaging(ScriptState* scriptState, const String& senderId) +{ + ASSERT(scriptState->executionContext()->isDocument()); + RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState); + ScriptPromise promise = resolver->promise(); + blink::WebPushClient* client = PushController::clientFrom(toDocument(scriptState->executionContext())->page()); + ASSERT(client); + client->registerPushMessaging(senderId, new CallbackPromiseAdapter<PushRegistration, PushError>(resolver)); + return promise; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.h b/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.h new file mode 100644 index 00000000000..7e5de9c3725 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.h @@ -0,0 +1,36 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PushManager_h +#define PushManager_h + +#include "bindings/v8/ScriptWrappable.h" +#include "platform/heap/Handle.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class ExecutionContext; +class ScriptPromise; +class ScriptState; + +class PushManager FINAL : public GarbageCollectedFinalized<PushManager>, public ScriptWrappable { +public: + static PushManager* create() + { + return new PushManager(); + } + virtual ~PushManager(); + + ScriptPromise registerPushMessaging(ScriptState*, const String& senderId); + + void trace(Visitor*) { } + +private: + PushManager(); +}; + +} // namespace WebCore + +#endif // PushManager_h diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.idl b/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.idl new file mode 100644 index 00000000000..4346304f2dd --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushManager.idl @@ -0,0 +1,11 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, + RuntimeEnabled=PushMessaging, + GarbageCollected, +] interface PushManager { + [CallWith=ScriptState, ImplementedAs=registerPushMessaging] Promise register(DOMString senderId); +}; diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.cpp b/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.cpp new file mode 100644 index 00000000000..284b451c91b --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.cpp @@ -0,0 +1,21 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/push_messaging/PushRegistration.h" + +namespace WebCore { + +PushRegistration::PushRegistration(const String& pushEndpoint, const String& pushRegistrationId) + : m_pushEndpoint(pushEndpoint) + , m_pushRegistrationId(pushRegistrationId) +{ + ScriptWrappable::init(this); +} + +PushRegistration::~PushRegistration() +{ +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.h b/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.h new file mode 100644 index 00000000000..b0b92206523 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.h @@ -0,0 +1,44 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PushRegistration_h +#define PushRegistration_h + +#include "bindings/v8/ScriptWrappable.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebPushRegistration.h" +#include "wtf/OwnPtr.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class ScriptPromiseResolverWithContext; + +class PushRegistration FINAL : public GarbageCollectedFinalized<PushRegistration>, public ScriptWrappable { +public: + // For CallbackPromiseAdapter. + typedef blink::WebPushRegistration WebType; + static PushRegistration* from(ScriptPromiseResolverWithContext*, WebType* registrationRaw) + { + OwnPtr<WebType> registration = adoptPtr(registrationRaw); + return new PushRegistration(registration->endpoint, registration->registrationId); + } + + virtual ~PushRegistration(); + + const String& pushEndpoint() const { return m_pushEndpoint; } + const String& pushRegistrationId() const { return m_pushRegistrationId; } + + void trace(Visitor*) { } + +private: + PushRegistration(const String& pushEndpoint, const String& pushRegistrationId); + + String m_pushEndpoint; + String m_pushRegistrationId; +}; + +} // namespace WebCore + +#endif // PushRegistration_h diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.idl b/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.idl new file mode 100644 index 00000000000..9ff2d6d04f2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/PushRegistration.idl @@ -0,0 +1,11 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, + GarbageCollected, +] interface PushRegistration { + readonly attribute DOMString pushEndpoint; + readonly attribute DOMString pushRegistrationId; +}; diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/ServiceWorkerGlobalScopePush.h b/chromium/third_party/WebKit/Source/modules/push_messaging/ServiceWorkerGlobalScopePush.h new file mode 100644 index 00000000000..4c92682f076 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/ServiceWorkerGlobalScopePush.h @@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ServiceWorkerGlobalScopePush_h +#define ServiceWorkerGlobalScopePush_h + +#include "core/events/EventTarget.h" + +namespace WebCore { + +class ServiceWorkerGlobalScopePush { +public: + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(push); +}; + +} // namespace WebCore + +#endif // ServiceWorkerGlobalScopePush_h diff --git a/chromium/third_party/WebKit/Source/modules/push_messaging/ServiceWorkerGlobalScopePush.idl b/chromium/third_party/WebKit/Source/modules/push_messaging/ServiceWorkerGlobalScopePush.idl new file mode 100644 index 00000000000..3395b3d4310 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/push_messaging/ServiceWorkerGlobalScopePush.idl @@ -0,0 +1,9 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + RuntimeEnabled=PushMessaging, +] partial interface ServiceWorkerGlobalScope { + attribute EventHandler onpush; +}; diff --git a/chromium/third_party/WebKit/Source/modules/quota/DOMWindowQuota.cpp b/chromium/third_party/WebKit/Source/modules/quota/DOMWindowQuota.cpp index ca37c8ca0a9..19597127e64 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/DOMWindowQuota.cpp +++ b/chromium/third_party/WebKit/Source/modules/quota/DOMWindowQuota.cpp @@ -32,15 +32,15 @@ #include "modules/quota/DOMWindowQuota.h" #include "core/dom/Document.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" -#include "modules/quota/StorageInfo.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "modules/quota/DeprecatedStorageInfo.h" #include "wtf/PassRefPtr.h" namespace WebCore { -DOMWindowQuota::DOMWindowQuota(DOMWindow* window) - : DOMWindowProperty(window->frame()) +DOMWindowQuota::DOMWindowQuota(LocalDOMWindow& window) + : DOMWindowProperty(window.frame()) { } @@ -54,27 +54,33 @@ const char* DOMWindowQuota::supplementName() } // static -DOMWindowQuota* DOMWindowQuota::from(DOMWindow* window) +DOMWindowQuota& DOMWindowQuota::from(LocalDOMWindow& window) { - DOMWindowQuota* supplement = static_cast<DOMWindowQuota*>(Supplement<DOMWindow>::from(window, supplementName())); + DOMWindowQuota* supplement = static_cast<DOMWindowQuota*>(WillBeHeapSupplement<LocalDOMWindow>::from(window, supplementName())); if (!supplement) { supplement = new DOMWindowQuota(window); - provideTo(window, supplementName(), adoptPtr(supplement)); + provideTo(window, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } // static -StorageInfo* DOMWindowQuota::webkitStorageInfo(DOMWindow* window) +DeprecatedStorageInfo* DOMWindowQuota::webkitStorageInfo(LocalDOMWindow& window) { - return DOMWindowQuota::from(window)->webkitStorageInfo(); + return DOMWindowQuota::from(window).webkitStorageInfo(); } -StorageInfo* DOMWindowQuota::webkitStorageInfo() const +DeprecatedStorageInfo* DOMWindowQuota::webkitStorageInfo() const { if (!m_storageInfo && frame()) - m_storageInfo = StorageInfo::create(); + m_storageInfo = DeprecatedStorageInfo::create(); return m_storageInfo.get(); } +void DOMWindowQuota::trace(Visitor* visitor) +{ + visitor->trace(m_storageInfo); + WillBeHeapSupplement<LocalDOMWindow>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/DOMWindowQuota.h b/chromium/third_party/WebKit/Source/modules/quota/DOMWindowQuota.h index b8e0bdffd09..b8017c502ca 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/DOMWindowQuota.h +++ b/chromium/third_party/WebKit/Source/modules/quota/DOMWindowQuota.h @@ -33,24 +33,28 @@ #include "core/frame/DOMWindowProperty.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { -class DOMWindow; -class StorageInfo; +class DeprecatedStorageInfo; +class LocalDOMWindow; -class DOMWindowQuota : public Supplement<DOMWindow>, public DOMWindowProperty { +class DOMWindowQuota FINAL : public NoBaseWillBeGarbageCollectedFinalized<DOMWindowQuota>, public WillBeHeapSupplement<LocalDOMWindow>, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DOMWindowQuota); public: virtual ~DOMWindowQuota(); - static DOMWindowQuota* from(DOMWindow*); - static StorageInfo* webkitStorageInfo(DOMWindow*); - StorageInfo* webkitStorageInfo() const; + static DOMWindowQuota& from(LocalDOMWindow&); + static DeprecatedStorageInfo* webkitStorageInfo(LocalDOMWindow&); + DeprecatedStorageInfo* webkitStorageInfo() const; + + void trace(Visitor*); private: - explicit DOMWindowQuota(DOMWindow*); + explicit DOMWindowQuota(LocalDOMWindow&); static const char* supplementName(); - mutable RefPtr<StorageInfo> m_storageInfo; + mutable PersistentWillBeMember<DeprecatedStorageInfo> m_storageInfo; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp new file mode 100644 index 00000000000..a92d87c3ca7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "modules/quota/DeprecatedStorageInfo.h" + +#include "core/dom/Document.h" +#include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" +#include "modules/quota/DeprecatedStorageQuota.h" +#include "modules/quota/StorageErrorCallback.h" +#include "modules/quota/StorageQuotaCallback.h" +#include "modules/quota/StorageUsageCallback.h" + +namespace WebCore { + +DeprecatedStorageInfo::DeprecatedStorageInfo() +{ + ScriptWrappable::init(this); +} + +DeprecatedStorageInfo::~DeprecatedStorageInfo() +{ +} + +void DeprecatedStorageInfo::queryUsageAndQuota(ExecutionContext* executionContext, int storageType, PassOwnPtr<StorageUsageCallback> successCallback, PassOwnPtr<StorageErrorCallback> errorCallback) +{ + // Dispatching the request to DeprecatedStorageQuota, as this interface is deprecated in favor of DeprecatedStorageQuota. + DeprecatedStorageQuota* storageQuota = getStorageQuota(storageType); + if (!storageQuota) { + // Unknown storage type is requested. + executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); + return; + } + storageQuota->queryUsageAndQuota(executionContext, successCallback, errorCallback); +} + +void DeprecatedStorageInfo::requestQuota(ExecutionContext* executionContext, int storageType, unsigned long long newQuotaInBytes, PassOwnPtr<StorageQuotaCallback> successCallback, PassOwnPtr<StorageErrorCallback> errorCallback) +{ + // Dispatching the request to DeprecatedStorageQuota, as this interface is deprecated in favor of DeprecatedStorageQuota. + DeprecatedStorageQuota* storageQuota = getStorageQuota(storageType); + if (!storageQuota) { + // Unknown storage type is requested. + executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); + return; + } + storageQuota->requestQuota(executionContext, newQuotaInBytes, successCallback, errorCallback); +} + +DeprecatedStorageQuota* DeprecatedStorageInfo::getStorageQuota(int storageType) +{ + switch (storageType) { + case TEMPORARY: + if (!m_temporaryStorage) + m_temporaryStorage = DeprecatedStorageQuota::create(DeprecatedStorageQuota::Temporary); + return m_temporaryStorage.get(); + case PERSISTENT: + if (!m_persistentStorage) + m_persistentStorage = DeprecatedStorageQuota::create(DeprecatedStorageQuota::Persistent); + return m_persistentStorage.get(); + } + return 0; +} + +void DeprecatedStorageInfo::trace(Visitor* visitor) +{ + visitor->trace(m_temporaryStorage); + visitor->trace(m_persistentStorage); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBuffer.h b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.h index 6869b16b46a..74c67e2bab1 100644 --- a/chromium/third_party/WebKit/Source/modules/mediasource/WebKitSourceBuffer.h +++ b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Google Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,50 +28,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebKitSourceBuffer_h -#define WebKitSourceBuffer_h +#ifndef DeprecatedStorageInfo_h +#define DeprecatedStorageInfo_h #include "bindings/v8/ScriptWrappable.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/text/WTFString.h" - -namespace blink { -class WebSourceBuffer; -} +#include "modules/quota/DeprecatedStorageQuota.h" +#include "platform/heap/Handle.h" +#include "wtf/PassOwnPtr.h" namespace WebCore { -class ExceptionState; -class TimeRanges; -class WebKitMediaSource; +class ExecutionContext; +class StorageErrorCallback; +class StorageQuotaCallback; +class StorageUsageCallback; -class WebKitSourceBuffer FINAL : public RefCounted<WebKitSourceBuffer>, public ScriptWrappable { +class DeprecatedStorageInfo : public GarbageCollectedFinalized<DeprecatedStorageInfo>, public ScriptWrappable { public: - static PassRefPtr<WebKitSourceBuffer> create(PassOwnPtr<blink::WebSourceBuffer>, PassRefPtr<WebKitMediaSource>); + enum { + TEMPORARY, + PERSISTENT, + }; - ~WebKitSourceBuffer(); + static DeprecatedStorageInfo* create() + { + return new DeprecatedStorageInfo(); + } - // WebKitSourceBuffer.idl methods - PassRefPtr<TimeRanges> buffered(ExceptionState&) const; - double timestampOffset() const; - void setTimestampOffset(double, ExceptionState&); - void append(PassRefPtr<Uint8Array> data, ExceptionState&); - void abort(ExceptionState&); + void queryUsageAndQuota(ExecutionContext*, int storageType, PassOwnPtr<StorageUsageCallback>, PassOwnPtr<StorageErrorCallback>); - void removedFromMediaSource(); + void requestQuota(ExecutionContext*, int storageType, unsigned long long newQuotaInBytes, PassOwnPtr<StorageQuotaCallback>, PassOwnPtr<StorageErrorCallback>); -private: - WebKitSourceBuffer(PassOwnPtr<blink::WebSourceBuffer>, PassRefPtr<WebKitMediaSource>); + ~DeprecatedStorageInfo(); - bool isRemoved() const; + void trace(Visitor*); + +private: + DeprecatedStorageInfo(); - OwnPtr<blink::WebSourceBuffer> m_webSourceBuffer; - RefPtr<WebKitMediaSource> m_source; + DeprecatedStorageQuota* getStorageQuota(int storageType); - double m_timestampOffset; + mutable Member<DeprecatedStorageQuota> m_temporaryStorage; + mutable Member<DeprecatedStorageQuota> m_persistentStorage; }; } // namespace WebCore -#endif +#endif // DeprecatedStorageInfo_h diff --git a/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.idl b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.idl new file mode 100644 index 00000000000..c69dcbca950 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.idl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + GarbageCollected, + NoInterfaceObject +] interface DeprecatedStorageInfo { + const unsigned short TEMPORARY = 0; + const unsigned short PERSISTENT = 1; + + [CallWith=ExecutionContext] void queryUsageAndQuota(unsigned short storageType, optional StorageUsageCallback usageCallback, optional StorageErrorCallback errorCallback); + [CallWith=ExecutionContext] void requestQuota(unsigned short storageType, unsigned long long newQuotaInBytes, optional StorageQuotaCallback quotaCallback, optional StorageErrorCallback errorCallback); +}; diff --git a/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp new file mode 100644 index 00000000000..6bbdea74999 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/quota/DeprecatedStorageQuota.h" + +#include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" +#include "modules/quota/DeprecatedStorageQuotaCallbacksImpl.h" +#include "modules/quota/StorageErrorCallback.h" +#include "modules/quota/StorageQuotaClient.h" +#include "modules/quota/StorageUsageCallback.h" +#include "platform/StorageQuotaCallbacks.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "public/platform/Platform.h" +#include "public/platform/WebStorageQuotaCallbacks.h" +#include "public/platform/WebStorageQuotaType.h" + +namespace WebCore { + +DeprecatedStorageQuota::DeprecatedStorageQuota(Type type) + : m_type(type) +{ + ScriptWrappable::init(this); +} + +void DeprecatedStorageQuota::queryUsageAndQuota(ExecutionContext* executionContext, PassOwnPtr<StorageUsageCallback> successCallback, PassOwnPtr<StorageErrorCallback> errorCallback) +{ + ASSERT(executionContext); + + blink::WebStorageQuotaType storageType = static_cast<blink::WebStorageQuotaType>(m_type); + if (storageType != blink::WebStorageQuotaTypeTemporary && storageType != blink::WebStorageQuotaTypePersistent) { + // Unknown storage type is requested. + executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); + return; + } + + SecurityOrigin* securityOrigin = executionContext->securityOrigin(); + if (securityOrigin->isUnique()) { + executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); + return; + } + + KURL storagePartition = KURL(KURL(), securityOrigin->toString()); + OwnPtr<StorageQuotaCallbacks> callbacks = DeprecatedStorageQuotaCallbacksImpl::create(successCallback, errorCallback); + blink::Platform::current()->queryStorageUsageAndQuota(storagePartition, storageType, callbacks.release()); +} + +void DeprecatedStorageQuota::requestQuota(ExecutionContext* executionContext, unsigned long long newQuotaInBytes, PassOwnPtr<StorageQuotaCallback> successCallback, PassOwnPtr<StorageErrorCallback> errorCallback) +{ + ASSERT(executionContext); + + blink::WebStorageQuotaType storageType = static_cast<blink::WebStorageQuotaType>(m_type); + if (storageType != blink::WebStorageQuotaTypeTemporary && storageType != blink::WebStorageQuotaTypePersistent) { + // Unknown storage type is requested. + executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); + return; + } + + StorageQuotaClient* client = StorageQuotaClient::from(executionContext); + if (!client) { + executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); + return; + } + + client->requestQuota(executionContext, storageType, newQuotaInBytes, successCallback, errorCallback); +} + +DeprecatedStorageQuota::~DeprecatedStorageQuota() +{ +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.h b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.h new file mode 100644 index 00000000000..f1959f1a5b9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DeprecatedStorageQuota_h +#define DeprecatedStorageQuota_h + +#include "bindings/v8/ScriptWrappable.h" +#include "platform/heap/Handle.h" +#include "wtf/PassOwnPtr.h" + +namespace WebCore { + +class ExecutionContext; +class StorageErrorCallback; +class StorageQuotaCallback; +class StorageUsageCallback; + +class DeprecatedStorageQuota : public GarbageCollectedFinalized<DeprecatedStorageQuota>, public ScriptWrappable { +public: + enum Type { + Temporary, + Persistent, + }; + + static DeprecatedStorageQuota* create(Type type) + { + return new DeprecatedStorageQuota(type); + } + + void queryUsageAndQuota(ExecutionContext*, PassOwnPtr<StorageUsageCallback>, PassOwnPtr<StorageErrorCallback>); + + void requestQuota(ExecutionContext*, unsigned long long newQuotaInBytes, PassOwnPtr<StorageQuotaCallback>, PassOwnPtr<StorageErrorCallback>); + + ~DeprecatedStorageQuota(); + + void trace(Visitor*) { } + +private: + explicit DeprecatedStorageQuota(Type); + Type m_type; +}; + +} // namespace WebCore + +#endif // DeprecatedStorageQuota_h diff --git a/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.idl b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.idl new file mode 100644 index 00000000000..1562bc41e70 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.idl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + GarbageCollected, + NoInterfaceObject +] interface DeprecatedStorageQuota { + [CallWith=ExecutionContext] void queryUsageAndQuota(StorageUsageCallback usageCallback, optional StorageErrorCallback errorCallback); + [CallWith=ExecutionContext] void requestQuota(unsigned long long newQuotaInBytes, optional StorageQuotaCallback quotaCallback, optional StorageErrorCallback errorCallback); +}; diff --git a/chromium/third_party/WebKit/Source/modules/quota/WebStorageQuotaCallbacksImpl.cpp b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuotaCallbacksImpl.cpp index 8427c8ca96b..ae6f2ad125a 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/WebStorageQuotaCallbacksImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuotaCallbacksImpl.cpp @@ -29,46 +29,43 @@ */ #include "config.h" -#include "modules/quota/WebStorageQuotaCallbacksImpl.h" +#include "modules/quota/DeprecatedStorageQuotaCallbacksImpl.h" #include "core/dom/DOMError.h" #include "core/dom/ExceptionCode.h" namespace WebCore { -WebStorageQuotaCallbacksImpl::WebStorageQuotaCallbacksImpl(PassOwnPtr<StorageUsageCallback> usageCallback, PassOwnPtr<StorageErrorCallback> errorCallback) +DeprecatedStorageQuotaCallbacksImpl::DeprecatedStorageQuotaCallbacksImpl(PassOwnPtr<StorageUsageCallback> usageCallback, PassOwnPtr<StorageErrorCallback> errorCallback) : m_usageCallback(usageCallback) , m_errorCallback(errorCallback) { } -WebStorageQuotaCallbacksImpl::WebStorageQuotaCallbacksImpl(PassOwnPtr<StorageQuotaCallback> quotaCallback, PassOwnPtr<StorageErrorCallback> errorCallback) +DeprecatedStorageQuotaCallbacksImpl::DeprecatedStorageQuotaCallbacksImpl(PassOwnPtr<StorageQuotaCallback> quotaCallback, PassOwnPtr<StorageErrorCallback> errorCallback) : m_quotaCallback(quotaCallback) , m_errorCallback(errorCallback) { } -WebStorageQuotaCallbacksImpl::~WebStorageQuotaCallbacksImpl() +DeprecatedStorageQuotaCallbacksImpl::~DeprecatedStorageQuotaCallbacksImpl() { } -void WebStorageQuotaCallbacksImpl::didQueryStorageUsageAndQuota(unsigned long long usageInBytes, unsigned long long quotaInBytes) +void DeprecatedStorageQuotaCallbacksImpl::didQueryStorageUsageAndQuota(unsigned long long usageInBytes, unsigned long long quotaInBytes) { - OwnPtr<WebStorageQuotaCallbacksImpl> deleter = adoptPtr(this); if (m_usageCallback) m_usageCallback->handleEvent(usageInBytes, quotaInBytes); } -void WebStorageQuotaCallbacksImpl::didGrantStorageQuota(unsigned long long grantedQuotaInBytes) +void DeprecatedStorageQuotaCallbacksImpl::didGrantStorageQuota(unsigned long long usageInBytes, unsigned long long grantedQuotaInBytes) { - OwnPtr<WebStorageQuotaCallbacksImpl> deleter = adoptPtr(this); if (m_quotaCallback) m_quotaCallback->handleEvent(grantedQuotaInBytes); } -void WebStorageQuotaCallbacksImpl::didFail(blink::WebStorageQuotaError error) +void DeprecatedStorageQuotaCallbacksImpl::didFail(blink::WebStorageQuotaError error) { - OwnPtr<WebStorageQuotaCallbacksImpl> deleter = adoptPtr(this); if (m_errorCallback) m_errorCallback->handleEvent(DOMError::create(static_cast<ExceptionCode>(error)).get()); } diff --git a/chromium/third_party/WebKit/Source/modules/quota/WebStorageQuotaCallbacksImpl.h b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuotaCallbacksImpl.h index 272c4f53156..4f524e63a3c 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/WebStorageQuotaCallbacksImpl.h +++ b/chromium/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuotaCallbacksImpl.h @@ -28,43 +28,40 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebStorageQuotaCallbacksImpl_h -#define WebStorageQuotaCallbacksImpl_h +#ifndef DeprecatedStorageQuotaCallbacksImpl_h +#define DeprecatedStorageQuotaCallbacksImpl_h #include "modules/quota/StorageErrorCallback.h" #include "modules/quota/StorageQuotaCallback.h" #include "modules/quota/StorageUsageCallback.h" -#include "public/platform/WebStorageQuotaCallbacks.h" +#include "platform/StorageQuotaCallbacks.h" #include "wtf/OwnPtr.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" namespace WebCore { -class WebStorageQuotaCallbacksImpl : public blink::WebStorageQuotaCallbacks { +class DeprecatedStorageQuotaCallbacksImpl FINAL : public StorageQuotaCallbacks { public: - // The class is self-destructed and thus we have leakedPtr constructors. - static WebStorageQuotaCallbacksImpl* createLeakedPtr(PassOwnPtr<StorageUsageCallback> success, PassOwnPtr<StorageErrorCallback> error) + static PassOwnPtr<DeprecatedStorageQuotaCallbacksImpl> create(PassOwnPtr<StorageUsageCallback> success, PassOwnPtr<StorageErrorCallback> error) { - OwnPtr<WebStorageQuotaCallbacksImpl> callbacks = adoptPtr(new WebStorageQuotaCallbacksImpl(success, error)); - return callbacks.leakPtr(); + return adoptPtr(new DeprecatedStorageQuotaCallbacksImpl(success, error)); } - static WebStorageQuotaCallbacksImpl* createLeakedPtr(PassOwnPtr<StorageQuotaCallback> success, PassOwnPtr<StorageErrorCallback> error) + static PassOwnPtr<DeprecatedStorageQuotaCallbacksImpl> create(PassOwnPtr<StorageQuotaCallback> success, PassOwnPtr<StorageErrorCallback> error) { - OwnPtr<WebStorageQuotaCallbacksImpl> callbacks = adoptPtr(new WebStorageQuotaCallbacksImpl(success, error)); - return callbacks.leakPtr(); + return adoptPtr(new DeprecatedStorageQuotaCallbacksImpl(success, error)); } - virtual ~WebStorageQuotaCallbacksImpl(); + virtual ~DeprecatedStorageQuotaCallbacksImpl(); - virtual void didQueryStorageUsageAndQuota(unsigned long long usageInBytes, unsigned long long quotaInBytes); - virtual void didGrantStorageQuota(unsigned long long grantedQuotaInBytes); - virtual void didFail(blink::WebStorageQuotaError); + virtual void didQueryStorageUsageAndQuota(unsigned long long usageInBytes, unsigned long long quotaInBytes) OVERRIDE; + virtual void didGrantStorageQuota(unsigned long long usageInBytes, unsigned long long grantedQuotaInBytes) OVERRIDE; + virtual void didFail(blink::WebStorageQuotaError) OVERRIDE; private: - WebStorageQuotaCallbacksImpl(PassOwnPtr<StorageUsageCallback>, PassOwnPtr<StorageErrorCallback>); - WebStorageQuotaCallbacksImpl(PassOwnPtr<StorageQuotaCallback>, PassOwnPtr<StorageErrorCallback>); + DeprecatedStorageQuotaCallbacksImpl(PassOwnPtr<StorageUsageCallback>, PassOwnPtr<StorageErrorCallback>); + DeprecatedStorageQuotaCallbacksImpl(PassOwnPtr<StorageQuotaCallback>, PassOwnPtr<StorageErrorCallback>); OwnPtr<StorageUsageCallback> m_usageCallback; OwnPtr<StorageQuotaCallback> m_quotaCallback; @@ -73,4 +70,4 @@ private: } // namespace -#endif // WebStorageQuotaCallbacksImpl_h +#endif // DeprecatedStorageQuotaCallbacksImpl_h diff --git a/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.cpp b/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.cpp index 0760321a4b5..35d08cb0926 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.cpp +++ b/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.cpp @@ -32,11 +32,12 @@ #include "modules/quota/NavigatorStorageQuota.h" #include "core/frame/Navigator.h" +#include "modules/quota/DeprecatedStorageQuota.h" #include "modules/quota/StorageQuota.h" namespace WebCore { -NavigatorStorageQuota::NavigatorStorageQuota(Frame* frame) +NavigatorStorageQuota::NavigatorStorageQuota(LocalFrame* frame) : DOMWindowProperty(frame) { } @@ -50,38 +51,58 @@ const char* NavigatorStorageQuota::supplementName() return "NavigatorStorageQuota"; } -NavigatorStorageQuota* NavigatorStorageQuota::from(Navigator* navigator) +NavigatorStorageQuota& NavigatorStorageQuota::from(Navigator& navigator) { - NavigatorStorageQuota* supplement = static_cast<NavigatorStorageQuota*>(Supplement<Navigator>::from(navigator, supplementName())); + NavigatorStorageQuota* supplement = static_cast<NavigatorStorageQuota*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); if (!supplement) { - supplement = new NavigatorStorageQuota(navigator->frame()); - provideTo(navigator, supplementName(), adoptPtr(supplement)); + supplement = new NavigatorStorageQuota(navigator.frame()); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -StorageQuota* NavigatorStorageQuota::webkitTemporaryStorage(Navigator* navigator) +StorageQuota* NavigatorStorageQuota::storageQuota(Navigator& navigator) { - return NavigatorStorageQuota::from(navigator)->webkitTemporaryStorage(); + return NavigatorStorageQuota::from(navigator).storageQuota(); } -StorageQuota* NavigatorStorageQuota::webkitPersistentStorage(Navigator* navigator) +DeprecatedStorageQuota* NavigatorStorageQuota::webkitTemporaryStorage(Navigator& navigator) { - return NavigatorStorageQuota::from(navigator)->webkitPersistentStorage(); + return NavigatorStorageQuota::from(navigator).webkitTemporaryStorage(); } -StorageQuota* NavigatorStorageQuota::webkitTemporaryStorage() const +DeprecatedStorageQuota* NavigatorStorageQuota::webkitPersistentStorage(Navigator& navigator) +{ + return NavigatorStorageQuota::from(navigator).webkitPersistentStorage(); +} + +StorageQuota* NavigatorStorageQuota::storageQuota() const +{ + if (!m_storageQuota && frame()) + m_storageQuota = StorageQuota::create(); + return m_storageQuota.get(); +} + +DeprecatedStorageQuota* NavigatorStorageQuota::webkitTemporaryStorage() const { if (!m_temporaryStorage && frame()) - m_temporaryStorage = StorageQuota::create(StorageQuota::Temporary); + m_temporaryStorage = DeprecatedStorageQuota::create(DeprecatedStorageQuota::Temporary); return m_temporaryStorage.get(); } -StorageQuota* NavigatorStorageQuota::webkitPersistentStorage() const +DeprecatedStorageQuota* NavigatorStorageQuota::webkitPersistentStorage() const { if (!m_persistentStorage && frame()) - m_persistentStorage = StorageQuota::create(StorageQuota::Persistent); + m_persistentStorage = DeprecatedStorageQuota::create(DeprecatedStorageQuota::Persistent); return m_persistentStorage.get(); } +void NavigatorStorageQuota::trace(Visitor* visitor) +{ + visitor->trace(m_storageQuota); + visitor->trace(m_temporaryStorage); + visitor->trace(m_persistentStorage); + WillBeHeapSupplement<Navigator>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.h b/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.h index 1b02414c174..d48f56129e5 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.h +++ b/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.h @@ -32,30 +32,39 @@ #define NavigatorStorageQuota_h #include "core/frame/DOMWindowProperty.h" +#include "modules/quota/DeprecatedStorageQuota.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { -class Frame; -class StorageQuota; +class LocalFrame; class Navigator; +class StorageQuota; -class NavigatorStorageQuota : public Supplement<Navigator>, public DOMWindowProperty { +class NavigatorStorageQuota FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorStorageQuota>, public WillBeHeapSupplement<Navigator>, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorStorageQuota); public: virtual ~NavigatorStorageQuota(); - static NavigatorStorageQuota* from(Navigator*); + static NavigatorStorageQuota& from(Navigator&); + + static StorageQuota* storageQuota(Navigator&); + static DeprecatedStorageQuota* webkitTemporaryStorage(Navigator&); + static DeprecatedStorageQuota* webkitPersistentStorage(Navigator&); + + StorageQuota* storageQuota() const; + DeprecatedStorageQuota* webkitTemporaryStorage() const; + DeprecatedStorageQuota* webkitPersistentStorage() const; - static StorageQuota* webkitTemporaryStorage(Navigator*); - static StorageQuota* webkitPersistentStorage(Navigator*); - StorageQuota* webkitTemporaryStorage() const; - StorageQuota* webkitPersistentStorage() const; + void trace(Visitor*); private: - explicit NavigatorStorageQuota(Frame*); + explicit NavigatorStorageQuota(LocalFrame*); static const char* supplementName(); - mutable RefPtr<StorageQuota> m_temporaryStorage; - mutable RefPtr<StorageQuota> m_persistentStorage; + mutable PersistentWillBeMember<StorageQuota> m_storageQuota; + mutable PersistentWillBeMember<DeprecatedStorageQuota> m_temporaryStorage; + mutable PersistentWillBeMember<DeprecatedStorageQuota> m_persistentStorage; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.idl b/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.idl index 43869b03c33..21c6e6f2a37 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.idl +++ b/chromium/third_party/WebKit/Source/modules/quota/NavigatorStorageQuota.idl @@ -18,6 +18,8 @@ */ partial interface Navigator { - readonly attribute StorageQuota webkitTemporaryStorage; - readonly attribute StorageQuota webkitPersistentStorage; + [MeasureAs=PrefixedStorageQuota] readonly attribute DeprecatedStorageQuota webkitTemporaryStorage; + [MeasureAs=PrefixedStorageQuota] readonly attribute DeprecatedStorageQuota webkitPersistentStorage; + + [RuntimeEnabled=QuotaPromise] readonly attribute StorageQuota storageQuota; }; diff --git a/chromium/third_party/WebKit/Source/modules/quota/OWNERS b/chromium/third_party/WebKit/Source/modules/quota/OWNERS index e67a8c32973..b40a9f041ab 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/quota/OWNERS @@ -1 +1,3 @@ kinuko@chromium.org +nhiroki@chromium.org +tzik@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/quota/StorageErrorCallback.h b/chromium/third_party/WebKit/Source/modules/quota/StorageErrorCallback.h index 5eced05cb60..7156710c5dd 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/StorageErrorCallback.h +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageErrorCallback.h @@ -34,7 +34,6 @@ #include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContextTask.h" #include "wtf/PassOwnPtr.h" -#include "wtf/RefCounted.h" namespace WebCore { @@ -47,14 +46,14 @@ public: virtual ~StorageErrorCallback() { } virtual void handleEvent(DOMError*) = 0; - class CallbackTask : public ExecutionContextTask { + class CallbackTask FINAL : public ExecutionContextTask { public: static PassOwnPtr<CallbackTask> create(PassOwnPtr<StorageErrorCallback> callback, ExceptionCode ec) { return adoptPtr(new CallbackTask(callback, ec)); } - virtual void performTask(ExecutionContext*); + virtual void performTask(ExecutionContext*) OVERRIDE; private: CallbackTask(PassOwnPtr<StorageErrorCallback>, ExceptionCode); diff --git a/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.cpp b/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.cpp index 19133ef88c5..0a51cee7fb5 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.cpp +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,20 +29,13 @@ */ #include "config.h" - #include "modules/quota/StorageInfo.h" -#include "core/dom/Document.h" -#include "core/dom/ExceptionCode.h" -#include "core/dom/ExecutionContext.h" -#include "modules/quota/StorageErrorCallback.h" -#include "modules/quota/StorageQuota.h" -#include "modules/quota/StorageQuotaCallback.h" -#include "modules/quota/StorageUsageCallback.h" - namespace WebCore { -StorageInfo::StorageInfo() +StorageInfo::StorageInfo(unsigned long long usage, unsigned long long quota) + : m_usage(usage) + , m_quota(quota) { ScriptWrappable::init(this); } @@ -51,43 +44,4 @@ StorageInfo::~StorageInfo() { } -void StorageInfo::queryUsageAndQuota(ExecutionContext* executionContext, int storageType, PassOwnPtr<StorageUsageCallback> successCallback, PassOwnPtr<StorageErrorCallback> errorCallback) -{ - // Dispatching the request to StorageQuota, as this interface is deprecated in favor of StorageQuota. - StorageQuota* storageQuota = getStorageQuota(storageType); - if (!storageQuota) { - // Unknown storage type is requested. - executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); - return; - } - storageQuota->queryUsageAndQuota(executionContext, successCallback, errorCallback); -} - -void StorageInfo::requestQuota(ExecutionContext* executionContext, int storageType, unsigned long long newQuotaInBytes, PassOwnPtr<StorageQuotaCallback> successCallback, PassOwnPtr<StorageErrorCallback> errorCallback) -{ - // Dispatching the request to StorageQuota, as this interface is deprecated in favor of StorageQuota. - StorageQuota* storageQuota = getStorageQuota(storageType); - if (!storageQuota) { - // Unknown storage type is requested. - executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); - return; - } - storageQuota->requestQuota(executionContext, newQuotaInBytes, successCallback, errorCallback); -} - -StorageQuota* StorageInfo::getStorageQuota(int storageType) -{ - switch (storageType) { - case TEMPORARY: - if (!m_temporaryStorage) - m_temporaryStorage = StorageQuota::create(StorageQuota::Temporary); - return m_temporaryStorage.get(); - case PERSISTENT: - if (!m_persistentStorage) - m_persistentStorage = StorageQuota::create(StorageQuota::Persistent); - return m_persistentStorage.get(); - } - return 0; -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.h b/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.h index 6ac7b55c764..8244f9f1be2 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.h +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -32,43 +32,29 @@ #define StorageInfo_h #include "bindings/v8/ScriptWrappable.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" +#include "platform/heap/Handle.h" namespace WebCore { -class ExecutionContext; -class StorageErrorCallback; -class StorageQuota; -class StorageQuotaCallback; -class StorageUsageCallback; - -class StorageInfo : public RefCounted<StorageInfo>, public ScriptWrappable { +class StorageInfo FINAL : public GarbageCollectedFinalized<StorageInfo>, public ScriptWrappable { public: - enum { - TEMPORARY, - PERSISTENT, - }; - - static PassRefPtr<StorageInfo> create() + static StorageInfo* create(unsigned long long usage, unsigned long long quota) { - return adoptRef(new StorageInfo()); + return new StorageInfo(usage, quota); } - void queryUsageAndQuota(ExecutionContext*, int storageType, PassOwnPtr<StorageUsageCallback>, PassOwnPtr<StorageErrorCallback>); - - void requestQuota(ExecutionContext*, int storageType, unsigned long long newQuotaInBytes, PassOwnPtr<StorageQuotaCallback>, PassOwnPtr<StorageErrorCallback>); + unsigned long long usage() const { return m_usage; } + unsigned long long quota() const { return m_quota; } ~StorageInfo(); -private: - StorageInfo(); + void trace(Visitor*) { } - StorageQuota* getStorageQuota(int storageType); +private: + StorageInfo(unsigned long long usage, unsigned long long quota); - mutable RefPtr<StorageQuota> m_temporaryStorage; - mutable RefPtr<StorageQuota> m_persistentStorage; + unsigned long long m_usage; + unsigned long long m_quota; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.idl b/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.idl index 7988ac38d92..112f4a472ef 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.idl +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageInfo.idl @@ -1,34 +1,38 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ [ - NoInterfaceObject + GarbageCollected, + NoInterfaceObject, + RuntimeEnabled=QuotaPromise ] interface StorageInfo { - const unsigned short TEMPORARY = 0; - const unsigned short PERSISTENT = 1; - - [CallWith=ExecutionContext] void queryUsageAndQuota(unsigned short storageType, optional StorageUsageCallback usageCallback, optional StorageErrorCallback errorCallback); - [CallWith=ExecutionContext] void requestQuota(unsigned short storageType, unsigned long long newQuotaInBytes, optional StorageQuotaCallback quotaCallback, optional StorageErrorCallback errorCallback); + readonly attribute unsigned long long usage; + readonly attribute unsigned long long quota; }; diff --git a/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.cpp b/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.cpp index 64f76853b64..59cb0bad32c 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.cpp +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,11 +31,14 @@ #include "config.h" #include "modules/quota/StorageQuota.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "core/dom/DOMError.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "modules/quota/StorageErrorCallback.h" -#include "modules/quota/StorageUsageCallback.h" -#include "modules/quota/WebStorageQuotaCallbacksImpl.h" +#include "modules/quota/StorageQuotaCallbacksImpl.h" +#include "modules/quota/StorageQuotaClient.h" #include "platform/weborigin/KURL.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" @@ -44,31 +47,71 @@ namespace WebCore { -StorageQuota::StorageQuota(Type type) - : m_type(type) +namespace { + +struct StorageTypeMapping { + blink::WebStorageQuotaType type; + const char* const name; +}; + +const StorageTypeMapping storageTypeMappings[] = { + { blink::WebStorageQuotaTypeTemporary, "temporary" }, + { blink::WebStorageQuotaTypePersistent, "persistent" }, +}; + +blink::WebStorageQuotaType stringToStorageQuotaType(const String& type) +{ + for (size_t i = 0; i < WTF_ARRAY_LENGTH(storageTypeMappings); ++i) { + if (storageTypeMappings[i].name == type) + return storageTypeMappings[i].type; + } + ASSERT_NOT_REACHED(); + return blink::WebStorageQuotaTypeTemporary; +} + +} // namespace + +StorageQuota::StorageQuota() { ScriptWrappable::init(this); } -void StorageQuota::queryUsageAndQuota(ExecutionContext* executionContext, PassOwnPtr<StorageUsageCallback> successCallback, PassOwnPtr<StorageErrorCallback> errorCallback) +Vector<String> StorageQuota::supportedTypes() const { - ASSERT(executionContext); + Vector<String> types; + for (size_t i = 0; i < WTF_ARRAY_LENGTH(storageTypeMappings); ++i) + types.append(storageTypeMappings[i].name); + return types; +} - blink::WebStorageQuotaType storageType = static_cast<blink::WebStorageQuotaType>(m_type); - if (storageType != blink::WebStorageQuotaTypeTemporary && storageType != blink::WebStorageQuotaTypePersistent) { - // Unknown storage type is requested. - executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); - return; - } +ScriptPromise StorageQuota::queryInfo(ScriptState* scriptState, String type) +{ + RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState); + ScriptPromise promise = resolver->promise(); - SecurityOrigin* securityOrigin = executionContext->securityOrigin(); + SecurityOrigin* securityOrigin = scriptState->executionContext()->securityOrigin(); if (securityOrigin->isUnique()) { - executionContext->postTask(StorageErrorCallback::CallbackTask::create(errorCallback, NotSupportedError)); - return; + resolver->reject(DOMError::create(NotSupportedError)); + return promise; } KURL storagePartition = KURL(KURL(), securityOrigin->toString()); - blink::Platform::current()->queryStorageUsageAndQuota(storagePartition, storageType, WebStorageQuotaCallbacksImpl::createLeakedPtr(successCallback, errorCallback)); + OwnPtr<StorageQuotaCallbacks> callbacks = StorageQuotaCallbacksImpl::create(resolver); + blink::Platform::current()->queryStorageUsageAndQuota(storagePartition, stringToStorageQuotaType(type), callbacks.release()); + return promise; +} + +ScriptPromise StorageQuota::requestPersistentQuota(ScriptState* scriptState, unsigned long long newQuota) +{ + StorageQuotaClient* client = StorageQuotaClient::from(scriptState->executionContext()); + if (!client) { + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + resolver->reject(DOMError::create(NotSupportedError)); + return promise; + } + + return client->requestPersistentQuota(scriptState, newQuota); } StorageQuota::~StorageQuota() diff --git a/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.h b/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.h index 285d51511da..166c36a1593 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.h +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,38 +31,33 @@ #ifndef StorageQuota_h #define StorageQuota_h +#include "bindings/v8/ScriptPromise.h" #include "bindings/v8/ScriptWrappable.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" +#include "wtf/Forward.h" namespace WebCore { class ExecutionContext; -class StorageErrorCallback; -class StorageQuotaCallback; -class StorageUsageCallback; -class StorageQuota : public RefCounted<StorageQuota>, public ScriptWrappable { +class StorageQuota FINAL : public GarbageCollectedFinalized<StorageQuota>, public ScriptWrappable { public: - enum Type { - Temporary, - Persistent, - }; - - static PassRefPtr<StorageQuota> create(Type type) + static StorageQuota* create() { - return adoptRef(new StorageQuota(type)); + return new StorageQuota(); } - void queryUsageAndQuota(ExecutionContext*, PassOwnPtr<StorageUsageCallback>, PassOwnPtr<StorageErrorCallback>); + Vector<String> supportedTypes() const; - void requestQuota(ExecutionContext*, unsigned long long newQuotaInBytes, PassOwnPtr<StorageQuotaCallback>, PassOwnPtr<StorageErrorCallback>); + ScriptPromise queryInfo(ScriptState*, String type); + ScriptPromise requestPersistentQuota(ScriptState*, unsigned long long newQuota); ~StorageQuota(); + void trace(Visitor*) { } + private: - explicit StorageQuota(Type); - Type m_type; + StorageQuota(); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.idl b/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.idl index a8f2c9c0054..1cfb28a24e2 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.idl +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageQuota.idl @@ -1,31 +1,44 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * modification, are permitted provided that the following conditions are + * met: * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum StorageType { + "temporary", + "persistent" +}; + [ - NoInterfaceObject + GarbageCollected, + NoInterfaceObject, + RuntimeEnabled=QuotaPromise ] interface StorageQuota { - [CallWith=ExecutionContext] void queryUsageAndQuota(StorageUsageCallback usageCallback, optional StorageErrorCallback errorCallback); - [CallWith=ExecutionContext] void requestQuota(unsigned long long newQuotaInBytes, optional StorageQuotaCallback quotaCallback, optional StorageErrorCallback errorCallback); + readonly attribute StorageType[] supportedTypes; + [CallWith=ScriptState] Promise queryInfo(StorageType type); + [CallWith=ScriptState] Promise requestPersistentQuota([Clamp] unsigned long long newQuota); }; diff --git a/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaCallbacksImpl.cpp b/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaCallbacksImpl.cpp new file mode 100644 index 00000000000..38ae3c7f75e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaCallbacksImpl.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/quota/StorageQuotaCallbacksImpl.h" + +#include "core/dom/DOMError.h" +#include "core/dom/ExceptionCode.h" +#include "modules/quota/StorageInfo.h" + +namespace WebCore { + +StorageQuotaCallbacksImpl::StorageQuotaCallbacksImpl(PassRefPtr<ScriptPromiseResolverWithContext> resolver) + : m_resolver(resolver) +{ +} + +StorageQuotaCallbacksImpl::~StorageQuotaCallbacksImpl() +{ +} + +void StorageQuotaCallbacksImpl::didQueryStorageUsageAndQuota(unsigned long long usageInBytes, unsigned long long quotaInBytes) +{ + m_resolver->resolve(StorageInfo::create(usageInBytes, quotaInBytes)); +} + +void StorageQuotaCallbacksImpl::didGrantStorageQuota(unsigned long long usageInBytes, unsigned long long grantedQuotaInBytes) +{ + m_resolver->resolve(StorageInfo::create(usageInBytes, grantedQuotaInBytes)); +} + +void StorageQuotaCallbacksImpl::didFail(blink::WebStorageQuotaError error) +{ + m_resolver->reject(DOMError::create(static_cast<ExceptionCode>(error)).get()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/RsaSsaParams.h b/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaCallbacksImpl.h index dd17e0152bd..71c46e73021 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/RsaSsaParams.h +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaCallbacksImpl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,26 +28,37 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RsaSsaParams_h -#define RsaSsaParams_h +#ifndef StorageQuotaCallbacksImpl_h +#define StorageQuotaCallbacksImpl_h -#include "modules/crypto/Algorithm.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "platform/StorageQuotaCallbacks.h" +#include "wtf/OwnPtr.h" +#include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" namespace WebCore { -class RsaSsaParams : public Algorithm { +class StorageQuotaCallbacksImpl FINAL : public StorageQuotaCallbacks { + WTF_MAKE_NONCOPYABLE(StorageQuotaCallbacksImpl); public: - static PassRefPtr<RsaSsaParams> create(const blink::WebCryptoAlgorithm& algorithm) { return adoptRef(new RsaSsaParams(algorithm)); } + static PassOwnPtr<StorageQuotaCallbacksImpl> create(PassRefPtr<ScriptPromiseResolverWithContext> resolver) + { + return adoptPtr(new StorageQuotaCallbacksImpl(resolver)); + } - Algorithm* hash(); + virtual ~StorageQuotaCallbacksImpl(); + + virtual void didQueryStorageUsageAndQuota(unsigned long long usageInBytes, unsigned long long quotaInBytes) OVERRIDE; + virtual void didGrantStorageQuota(unsigned long long usageInBytes, unsigned long long grantedQuotaInBytes) OVERRIDE; + virtual void didFail(blink::WebStorageQuotaError) OVERRIDE; private: - explicit RsaSsaParams(const blink::WebCryptoAlgorithm&); + StorageQuotaCallbacksImpl(PassRefPtr<ScriptPromiseResolverWithContext>); - RefPtr<Algorithm> m_hash; + RefPtr<ScriptPromiseResolverWithContext> m_resolver; }; -} // namespace WebCore +} // namespace -#endif +#endif // StorageQuotaCallbacksImpl_h diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesCtrParams.cpp b/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaClient.cpp index 9c846cb2fdf..bc178cd2ff8 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesCtrParams.cpp +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaClient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,31 +29,28 @@ */ #include "config.h" -#include "modules/crypto/AesCtrParams.h" +#include "StorageQuotaClient.h" -#include "public/platform/WebCryptoAlgorithmParams.h" +#include "core/dom/Document.h" +#include "core/workers/WorkerGlobalScope.h" namespace WebCore { -Uint8Array* AesCtrParams::counter() +const char* StorageQuotaClient::supplementName() { - if (!m_counter) { - const blink::WebVector<unsigned char>& counter = m_algorithm.aesCtrParams()->counter(); - m_counter = Uint8Array::create(counter.data(), counter.size()); - } - return m_counter.get(); + return "StorageQuotaClient"; } -unsigned char AesCtrParams::length() +StorageQuotaClient* StorageQuotaClient::from(ExecutionContext* context) { - return m_algorithm.aesCtrParams()->lengthBits(); + if (!context->isDocument()) + return 0; + return static_cast<StorageQuotaClient*>(WillBeHeapSupplement<Page>::from(toDocument(context)->page(), supplementName())); } -AesCtrParams::AesCtrParams(const blink::WebCryptoAlgorithm& algorithm) - : Algorithm(algorithm) +void provideStorageQuotaClientTo(Page& page, PassOwnPtrWillBeRawPtr<StorageQuotaClient> client) { - ASSERT(algorithm.aesCtrParams()); - ScriptWrappable::init(this); + page.provideSupplement(StorageQuotaClient::supplementName(), client); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesCtrParams.h b/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaClient.h index 1bd699401ed..09c37079237 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesCtrParams.h +++ b/chromium/third_party/WebKit/Source/modules/quota/StorageQuotaClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,27 +28,36 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AesCtrParams_h -#define AesCtrParams_h +#ifndef StorageQuotaClient_h +#define StorageQuotaClient_h -#include "modules/crypto/Algorithm.h" -#include "wtf/Uint8Array.h" +#include "core/page/Page.h" +#include "public/platform/WebStorageQuotaType.h" +#include "wtf/Forward.h" namespace WebCore { -class AesCtrParams : public Algorithm { -public: - static PassRefPtr<AesCtrParams> create(const blink::WebCryptoAlgorithm& algorithm) { return adoptRef(new AesCtrParams(algorithm)); } +class ExecutionContext; +class ScriptPromise; +class ScriptState; +class StorageErrorCallback; +class StorageQuotaCallback; - Uint8Array* counter(); - unsigned char length(); +class StorageQuotaClient : public WillBeHeapSupplement<Page> { + WTF_MAKE_NONCOPYABLE(StorageQuotaClient); +public: + StorageQuotaClient() { } + virtual ~StorageQuotaClient() { } -private: - explicit AesCtrParams(const blink::WebCryptoAlgorithm&); + virtual void requestQuota(ExecutionContext*, blink::WebStorageQuotaType, unsigned long long newQuotaInBytes, PassOwnPtr<StorageQuotaCallback>, PassOwnPtr<StorageErrorCallback>) = 0; + virtual ScriptPromise requestPersistentQuota(ScriptState*, unsigned long long newQuotaInBytes) = 0; - RefPtr<Uint8Array> m_counter; + static const char* supplementName(); + static StorageQuotaClient* from(ExecutionContext*); }; +void provideStorageQuotaClientTo(Page&, PassOwnPtrWillBeRawPtr<StorageQuotaClient>); + } // namespace WebCore -#endif +#endif // StorageQuotaClient_h diff --git a/chromium/third_party/WebKit/Source/modules/quota/WindowQuota.idl b/chromium/third_party/WebKit/Source/modules/quota/WindowQuota.idl index 1f8ce5eff35..5d14c0bfd43 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/WindowQuota.idl +++ b/chromium/third_party/WebKit/Source/modules/quota/WindowQuota.idl @@ -24,8 +24,7 @@ */ [ - ImplementedAs=DOMWindowQuota + ImplementedAs=DOMWindowQuota, ] partial interface Window { - [DeprecateAs=StorageInfo] readonly attribute StorageInfo webkitStorageInfo; + [DeprecateAs=PrefixedStorageInfo] readonly attribute DeprecatedStorageInfo webkitStorageInfo; }; - diff --git a/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.cpp b/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.cpp index d0522cbb111..c3f4dd923ca 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.cpp +++ b/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "modules/quota/WorkerNavigatorStorageQuota.h" -#include "modules/quota/StorageQuota.h" +#include "modules/quota/DeprecatedStorageQuota.h" namespace WebCore { @@ -39,47 +39,50 @@ WorkerNavigatorStorageQuota::WorkerNavigatorStorageQuota() { } -WorkerNavigatorStorageQuota::~WorkerNavigatorStorageQuota() -{ -} - const char* WorkerNavigatorStorageQuota::supplementName() { return "WorkerNavigatorStorageQuota"; } -WorkerNavigatorStorageQuota* WorkerNavigatorStorageQuota::from(WorkerNavigator* navigator) +WorkerNavigatorStorageQuota& WorkerNavigatorStorageQuota::from(WorkerNavigator& navigator) { - WorkerNavigatorStorageQuota* supplement = static_cast<WorkerNavigatorStorageQuota*>(Supplement<WorkerNavigator>::from(navigator, supplementName())); + WorkerNavigatorStorageQuota* supplement = static_cast<WorkerNavigatorStorageQuota*>(WillBeHeapSupplement<WorkerNavigator>::from(navigator, supplementName())); if (!supplement) { supplement = new WorkerNavigatorStorageQuota(); - provideTo(navigator, supplementName(), adoptPtr(supplement)); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -StorageQuota* WorkerNavigatorStorageQuota::webkitTemporaryStorage(WorkerNavigator* navigator) +DeprecatedStorageQuota* WorkerNavigatorStorageQuota::webkitTemporaryStorage(WorkerNavigator& navigator) { - return WorkerNavigatorStorageQuota::from(navigator)->webkitTemporaryStorage(); + return WorkerNavigatorStorageQuota::from(navigator).webkitTemporaryStorage(); } -StorageQuota* WorkerNavigatorStorageQuota::webkitPersistentStorage(WorkerNavigator* navigator) +DeprecatedStorageQuota* WorkerNavigatorStorageQuota::webkitPersistentStorage(WorkerNavigator& navigator) { - return WorkerNavigatorStorageQuota::from(navigator)->webkitPersistentStorage(); + return WorkerNavigatorStorageQuota::from(navigator).webkitPersistentStorage(); } -StorageQuota* WorkerNavigatorStorageQuota::webkitTemporaryStorage() const +DeprecatedStorageQuota* WorkerNavigatorStorageQuota::webkitTemporaryStorage() const { if (!m_temporaryStorage) - m_temporaryStorage = StorageQuota::create(StorageQuota::Temporary); + m_temporaryStorage = DeprecatedStorageQuota::create(DeprecatedStorageQuota::Temporary); return m_temporaryStorage.get(); } -StorageQuota* WorkerNavigatorStorageQuota::webkitPersistentStorage() const +DeprecatedStorageQuota* WorkerNavigatorStorageQuota::webkitPersistentStorage() const { if (!m_persistentStorage) - m_persistentStorage = StorageQuota::create(StorageQuota::Persistent); + m_persistentStorage = DeprecatedStorageQuota::create(DeprecatedStorageQuota::Persistent); return m_persistentStorage.get(); } +void WorkerNavigatorStorageQuota::trace(Visitor* visitor) +{ + visitor->trace(m_temporaryStorage); + visitor->trace(m_persistentStorage); + WillBeHeapSupplement<WorkerNavigator>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.h b/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.h index 278e0075a5c..09a940a2587 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.h +++ b/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.h @@ -33,29 +33,30 @@ #include "core/frame/DOMWindowProperty.h" #include "core/workers/WorkerNavigator.h" +#include "modules/quota/DeprecatedStorageQuota.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { -class StorageQuota; -class WorkerNavigator; - -class WorkerNavigatorStorageQuota : public Supplement<WorkerNavigator> { +class WorkerNavigatorStorageQuota FINAL : public NoBaseWillBeGarbageCollected<WorkerNavigatorStorageQuota>, public WillBeHeapSupplement<WorkerNavigator> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WorkerNavigatorStorageQuota); public: - virtual ~WorkerNavigatorStorageQuota(); - static WorkerNavigatorStorageQuota* from(WorkerNavigator*); + static WorkerNavigatorStorageQuota& from(WorkerNavigator&); + + static DeprecatedStorageQuota* webkitTemporaryStorage(WorkerNavigator&); + static DeprecatedStorageQuota* webkitPersistentStorage(WorkerNavigator&); + DeprecatedStorageQuota* webkitTemporaryStorage() const; + DeprecatedStorageQuota* webkitPersistentStorage() const; - static StorageQuota* webkitTemporaryStorage(WorkerNavigator*); - static StorageQuota* webkitPersistentStorage(WorkerNavigator*); - StorageQuota* webkitTemporaryStorage() const; - StorageQuota* webkitPersistentStorage() const; + virtual void trace(Visitor*); private: explicit WorkerNavigatorStorageQuota(); static const char* supplementName(); - mutable RefPtr<StorageQuota> m_temporaryStorage; - mutable RefPtr<StorageQuota> m_persistentStorage; + mutable PersistentWillBeMember<DeprecatedStorageQuota> m_temporaryStorage; + mutable PersistentWillBeMember<DeprecatedStorageQuota> m_persistentStorage; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.idl b/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.idl index be61756d438..c47cb53610a 100644 --- a/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.idl +++ b/chromium/third_party/WebKit/Source/modules/quota/WorkerNavigatorStorageQuota.idl @@ -18,6 +18,6 @@ */ partial interface WorkerNavigator { - readonly attribute StorageQuota webkitTemporaryStorage; - readonly attribute StorageQuota webkitPersistentStorage; + [MeasureAs=PrefixedStorageQuota] readonly attribute DeprecatedStorageQuota webkitTemporaryStorage; + [MeasureAs=PrefixedStorageQuota] readonly attribute DeprecatedStorageQuota webkitPersistentStorage; }; diff --git a/chromium/third_party/WebKit/Source/modules/screen_orientation/LockOrientationCallback.cpp b/chromium/third_party/WebKit/Source/modules/screen_orientation/LockOrientationCallback.cpp new file mode 100644 index 00000000000..da1088309d8 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/screen_orientation/LockOrientationCallback.cpp @@ -0,0 +1,78 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/screen_orientation/LockOrientationCallback.h" + +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "core/dom/DOMException.h" +#include "core/dom/ExceptionCode.h" +#include "modules/screen_orientation/ScreenOrientation.h" + +namespace WebCore { + +LockOrientationCallback::LockOrientationCallback(PassRefPtr<ScriptPromiseResolverWithContext> resolver) + : m_resolver(resolver) +{ +} + +LockOrientationCallback::~LockOrientationCallback() +{ +} + +void LockOrientationCallback::onSuccess(unsigned angle, blink::WebScreenOrientationType type) +{ + // FIXME: for the moment, we do nothing with the angle, we should use it and + // convert it to the appropriate type if the type == 'undefined' when the + // method will be implemented in ScreenOrientationController. + m_resolver->resolve(ScreenOrientation::orientationTypeToString(type)); +} + +void LockOrientationCallback::onError(ErrorType error) +{ + ExceptionCode code = 0; + String msg = ""; + + switch (error) { + case ErrorTypeNotAvailable: + code = NotSupportedError; + msg = "lockOrientation() is not available on this device."; + break; + case ErrorTypeFullScreenRequired: + code = SecurityError; + msg = "The page needs to be fullscreen in order to call lockOrientation()."; + break; + case ErrorTypeCanceled: + code = AbortError; + msg = "A call to lockOrientation() or unlockOrientation() canceled this call."; + break; + } + + m_resolver->reject(DOMException::create(code, msg)); +} + +void LockOrientationCallback::onError(blink::WebLockOrientationError error) +{ + ExceptionCode code = 0; + String msg = ""; + + switch (error) { + case blink::WebLockOrientationErrorNotAvailable: + code = NotSupportedError; + msg = "lockOrientation() is not available on this device."; + break; + case blink::WebLockOrientationErrorFullScreenRequired: + code = SecurityError; + msg = "The page needs to be fullscreen in order to call lockOrientation()."; + break; + case blink::WebLockOrientationErrorCanceled: + code = AbortError; + msg = "A call to lockOrientation() or unlockOrientation() canceled this call."; + break; + } + + m_resolver->reject(DOMException::create(code, msg)); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/screen_orientation/LockOrientationCallback.h b/chromium/third_party/WebKit/Source/modules/screen_orientation/LockOrientationCallback.h new file mode 100644 index 00000000000..df43a17bda0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/screen_orientation/LockOrientationCallback.h @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LockOrientationCallback_h +#define LockOrientationCallback_h + +#include "public/platform/WebLockOrientationCallback.h" +#include "public/platform/WebScreenOrientationType.h" +#include "wtf/Noncopyable.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +class ScriptPromiseResolverWithContext; + +// LockOrientationCallback is an implementation of WebLockOrientationCallback +// that will resolve the underlying promise depending on the result passed to +// the callback. +class LockOrientationCallback FINAL : public blink::WebLockOrientationCallback { + WTF_MAKE_NONCOPYABLE(LockOrientationCallback); +public: + explicit LockOrientationCallback(PassRefPtr<ScriptPromiseResolverWithContext>); + virtual ~LockOrientationCallback(); + + virtual void onSuccess(unsigned angle, blink::WebScreenOrientationType) OVERRIDE; + virtual void onError(ErrorType) OVERRIDE; + virtual void onError(blink::WebLockOrientationError) OVERRIDE; + +private: + RefPtr<ScriptPromiseResolverWithContext> m_resolver; +}; + +} // namespace WebCore + +#endif // LockOrientationCallback_h diff --git a/chromium/third_party/WebKit/Source/modules/screen_orientation/OWNERS b/chromium/third_party/WebKit/Source/modules/screen_orientation/OWNERS new file mode 100644 index 00000000000..5745f4624d0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/screen_orientation/OWNERS @@ -0,0 +1,2 @@ +ch.dumez@samsung.com +mlamouri@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.cpp b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.cpp new file mode 100644 index 00000000000..7f2a763d474 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.cpp @@ -0,0 +1,161 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/screen_orientation/ScreenOrientation.h" + +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "core/dom/DOMException.h" +#include "core/dom/Document.h" +#include "core/dom/ExceptionCode.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Screen.h" +#include "modules/screen_orientation/LockOrientationCallback.h" +#include "modules/screen_orientation/ScreenOrientationController.h" +#include "public/platform/WebScreenOrientationType.h" + +// This code assumes that WebScreenOrientationType values are included in WebScreenOrientationLockType. +#define COMPILE_ASSERT_MATCHING_ENUM(enum1, enum2) \ + COMPILE_ASSERT(static_cast<unsigned>(blink::enum1) == static_cast<unsigned>(blink::enum2), mismatching_types) +COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationPortraitPrimary, WebScreenOrientationLockPortraitPrimary); +COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationPortraitSecondary, WebScreenOrientationLockPortraitSecondary); +COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationLandscapePrimary, WebScreenOrientationLockLandscapePrimary); +COMPILE_ASSERT_MATCHING_ENUM(WebScreenOrientationLandscapeSecondary, WebScreenOrientationLockLandscapeSecondary); + +namespace WebCore { + +struct ScreenOrientationInfo { + const AtomicString& name; + unsigned orientation; +}; + +static ScreenOrientationInfo* orientationsMap(unsigned& length) +{ + DEFINE_STATIC_LOCAL(const AtomicString, portraitPrimary, ("portrait-primary", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, portraitSecondary, ("portrait-secondary", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, landscapePrimary, ("landscape-primary", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, landscapeSecondary, ("landscape-secondary", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, any, ("any", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, portrait, ("portrait", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(const AtomicString, landscape, ("landscape", AtomicString::ConstructFromLiteral)); + + static ScreenOrientationInfo orientationMap[] = { + { portraitPrimary, blink::WebScreenOrientationLockPortraitPrimary }, + { portraitSecondary, blink::WebScreenOrientationLockPortraitSecondary }, + { landscapePrimary, blink::WebScreenOrientationLockLandscapePrimary }, + { landscapeSecondary, blink::WebScreenOrientationLockLandscapeSecondary }, + { any, blink::WebScreenOrientationLockAny }, + { portrait, blink::WebScreenOrientationLockPortrait }, + { landscape, blink::WebScreenOrientationLockLandscape } + }; + length = WTF_ARRAY_LENGTH(orientationMap); + + return orientationMap; +} + +const AtomicString& ScreenOrientation::orientationTypeToString(blink::WebScreenOrientationType orientation) +{ + unsigned length = 0; + ScreenOrientationInfo* orientationMap = orientationsMap(length); + for (unsigned i = 0; i < length; ++i) { + if (static_cast<unsigned>(orientation) == orientationMap[i].orientation) + return orientationMap[i].name; + } + + ASSERT_NOT_REACHED(); + return nullAtom; +} + +static blink::WebScreenOrientationLockType stringToOrientationLock(const AtomicString& orientationLockString) +{ + unsigned length = 0; + ScreenOrientationInfo* orientationMap = orientationsMap(length); + for (unsigned i = 0; i < length; ++i) { + if (orientationMap[i].name == orientationLockString) + return static_cast<blink::WebScreenOrientationLockType>(orientationMap[i].orientation); + } + + ASSERT_NOT_REACHED(); + return blink::WebScreenOrientationLockDefault; +} + +ScreenOrientation::ScreenOrientation(Screen& screen) + : DOMWindowProperty(screen.frame()) +{ +} + +const char* ScreenOrientation::supplementName() +{ + return "ScreenOrientation"; +} + +Document* ScreenOrientation::document() const +{ + if (!m_associatedDOMWindow || !m_associatedDOMWindow->isCurrentlyDisplayedInFrame()) + return 0; + ASSERT(m_associatedDOMWindow->document()); + return m_associatedDOMWindow->document(); +} + +ScreenOrientation& ScreenOrientation::from(Screen& screen) +{ + ScreenOrientation* supplement = static_cast<ScreenOrientation*>(WillBeHeapSupplement<Screen>::from(screen, supplementName())); + if (!supplement) { + supplement = new ScreenOrientation(screen); + provideTo(screen, supplementName(), adoptPtrWillBeNoop(supplement)); + } + return *supplement; +} + +ScreenOrientation::~ScreenOrientation() +{ +} + +const AtomicString& ScreenOrientation::orientation(Screen& screen) +{ + ScreenOrientation& screenOrientation = ScreenOrientation::from(screen); + if (!screenOrientation.frame()) { + // FIXME: we should try to return a better guess, like the latest known value. + return orientationTypeToString(blink::WebScreenOrientationPortraitPrimary); + } + ScreenOrientationController& controller = ScreenOrientationController::from(*screenOrientation.frame()); + return orientationTypeToString(controller.orientation()); +} + +ScriptPromise ScreenOrientation::lockOrientation(ScriptState* state, Screen& screen, const AtomicString& lockString) +{ + RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(state); + ScriptPromise promise = resolver->promise(); + + ScreenOrientation& screenOrientation = ScreenOrientation::from(screen); + Document* document = screenOrientation.document(); + + if (!document || !screenOrientation.frame()) { + RefPtrWillBeRawPtr<DOMException> exception = DOMException::create(InvalidStateError, "The object is no longer associated to a document."); + resolver->reject(exception); + return promise; + } + + if (document->isSandboxed(SandboxOrientationLock)) { + RefPtrWillBeRawPtr<DOMException> exception = DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-orientation-lock' flag."); + resolver->reject(exception); + return promise; + } + + ScreenOrientationController::from(*screenOrientation.frame()).lockOrientation(stringToOrientationLock(lockString), new LockOrientationCallback(resolver)); + return promise; +} + +void ScreenOrientation::unlockOrientation(Screen& screen) +{ + ScreenOrientation& screenOrientation = ScreenOrientation::from(screen); + if (!screenOrientation.frame()) + return; + + ScreenOrientationController::from(*screenOrientation.frame()).unlockOrientation(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.h b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.h new file mode 100644 index 00000000000..1091cdb224e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.h @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ScreenOrientation_h +#define ScreenOrientation_h + +#include "core/frame/DOMWindowProperty.h" +#include "platform/Supplementable.h" +#include "platform/Timer.h" +#include "platform/heap/Handle.h" +#include "public/platform/WebScreenOrientationLockType.h" +#include "public/platform/WebScreenOrientationType.h" +#include "wtf/text/AtomicString.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class Document; +class ScriptPromise; +class ScriptState; +class Screen; + +class ScreenOrientation FINAL : public NoBaseWillBeGarbageCollectedFinalized<ScreenOrientation>, public WillBeHeapSupplement<Screen>, DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(ScreenOrientation); +public: + static ScreenOrientation& from(Screen&); + virtual ~ScreenOrientation(); + + static const AtomicString& orientation(Screen&); + static ScriptPromise lockOrientation(ScriptState*, Screen&, const AtomicString& orientation); + static void unlockOrientation(Screen&); + + // Helper being used by this class and LockOrientationCallback. + static const AtomicString& orientationTypeToString(blink::WebScreenOrientationType); + + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Screen>::trace(visitor); } + +private: + explicit ScreenOrientation(Screen&); + + static const char* supplementName(); + Document* document() const; +}; + +} // namespace WebCore + +#endif // ScreenOrientation_h diff --git a/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.idl b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.idl new file mode 100644 index 00000000000..c1bf5328359 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientation.idl @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +enum OrientationType { + "portrait-primary", + "portrait-secondary", + "landscape-primary", + "landscape-secondary" +}; + +enum OrientationLockType { + "any", + "landscape", + "portrait", + "portrait-primary", + "portrait-secondary", + "landscape-primary", + "landscape-secondary" +}; + +[ + RuntimeEnabled=ScreenOrientation +] partial interface Screen { + readonly attribute OrientationType orientation; + + [CallWith=ScriptState] Promise lockOrientation(OrientationLockType orientation); + + void unlockOrientation(); +}; diff --git a/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp new file mode 100644 index 00000000000..e5880ed4149 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp @@ -0,0 +1,136 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/screen_orientation/ScreenOrientationController.h" + +#include "core/dom/Document.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Screen.h" +#include "core/page/Page.h" +#include "platform/LayoutTestSupport.h" +#include "platform/PlatformScreen.h" +#include "public/platform/WebScreenOrientationClient.h" + +namespace WebCore { + +ScreenOrientationController::~ScreenOrientationController() +{ +} + +void ScreenOrientationController::persistentHostHasBeenDestroyed() +{ + // Unregister lifecycle observation once page is being torn down. + observeContext(0); +} + +void ScreenOrientationController::provideTo(LocalFrame& frame, blink::WebScreenOrientationClient* client) +{ + ScreenOrientationController* controller = new ScreenOrientationController(frame, client); + WillBeHeapSupplement<LocalFrame>::provideTo(frame, supplementName(), adoptPtrWillBeNoop(controller)); +} + +ScreenOrientationController& ScreenOrientationController::from(LocalFrame& frame) +{ + return *static_cast<ScreenOrientationController*>(WillBeHeapSupplement<LocalFrame>::from(frame, supplementName())); +} + +ScreenOrientationController::ScreenOrientationController(LocalFrame& frame, blink::WebScreenOrientationClient* client) + : PageLifecycleObserver(frame.page()) + , m_overrideOrientation(blink::WebScreenOrientationUndefined) + , m_client(client) + , m_frame(frame) +{ +} + +const char* ScreenOrientationController::supplementName() +{ + return "ScreenOrientationController"; +} + +// Compute the screen orientation using the orientation angle and the screen width / height. +blink::WebScreenOrientationType ScreenOrientationController::computeOrientation(FrameView* view) +{ + // Bypass orientation detection in layout tests to get consistent results. + // FIXME: The screen dimension should be fixed when running the layout tests to avoid such + // issues. + if (isRunningLayoutTest()) + return blink::WebScreenOrientationPortraitPrimary; + + FloatRect rect = screenRect(view); + uint16_t rotation = screenOrientationAngle(view); + bool isTallDisplay = rotation % 180 ? rect.height() < rect.width() : rect.height() > rect.width(); + switch (rotation) { + case 0: + return isTallDisplay ? blink::WebScreenOrientationPortraitPrimary : blink::WebScreenOrientationLandscapePrimary; + case 90: + return isTallDisplay ? blink::WebScreenOrientationLandscapePrimary : blink::WebScreenOrientationPortraitSecondary; + case 180: + return isTallDisplay ? blink::WebScreenOrientationPortraitSecondary : blink::WebScreenOrientationLandscapeSecondary; + case 270: + return isTallDisplay ? blink::WebScreenOrientationLandscapeSecondary : blink::WebScreenOrientationPortraitPrimary; + default: + ASSERT_NOT_REACHED(); + return blink::WebScreenOrientationPortraitPrimary; + } +} + +void ScreenOrientationController::pageVisibilityChanged() +{ + if (page() && page()->visibilityState() == PageVisibilityStateVisible) { + blink::WebScreenOrientationType oldOrientation = m_overrideOrientation; + m_overrideOrientation = blink::WebScreenOrientationUndefined; + // FIXME: sendOrientationChangeEvent() currently send an event all the + // children of the frame, so it should only be called on the frame on + // top of the tree. We would need the embedder to call + // sendOrientationChangeEvent on every WebFrame part of a WebView to be + // able to remove this. + if (m_frame == m_frame.localFrameRoot() && oldOrientation != orientation()) + m_frame.sendOrientationChangeEvent(); + } else if (m_overrideOrientation == blink::WebScreenOrientationUndefined) { + // The page is no longer visible, store the last know screen orientation + // so that we keep returning this orientation until the page becomes + // visible again. + m_overrideOrientation = orientation(); + } +} + +blink::WebScreenOrientationType ScreenOrientationController::orientation() const +{ + if (m_overrideOrientation != blink::WebScreenOrientationUndefined) { + // The page is not visible, keep returning the last known screen orientation. + ASSERT(!page() || page()->visibilityState() != PageVisibilityStateVisible); + return m_overrideOrientation; + } + + blink::WebScreenOrientationType orientationType = screenOrientationType(m_frame.view()); + if (orientationType == blink::WebScreenOrientationUndefined) { + // The embedder could not provide us with an orientation, deduce it ourselves. + orientationType = computeOrientation(m_frame.view()); + } + ASSERT(orientationType != blink::WebScreenOrientationUndefined); + return orientationType; +} + +void ScreenOrientationController::lockOrientation(blink::WebScreenOrientationLockType orientation, blink::WebLockOrientationCallback* callback) +{ + if (!m_client) { + return; + } + + m_client->lockOrientation(orientation, callback); +} + +void ScreenOrientationController::unlockOrientation() +{ + if (!m_client) { + return; + } + + m_client->unlockOrientation(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h new file mode 100644 index 00000000000..71bc9546996 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ScreenOrientationController_h +#define ScreenOrientationController_h + +#include "core/page/PageLifecycleObserver.h" +#include "platform/Supplementable.h" +#include "public/platform/WebLockOrientationCallback.h" +#include "public/platform/WebScreenOrientationLockType.h" +#include "public/platform/WebScreenOrientationType.h" + +namespace blink { +class WebScreenOrientationClient; +} + +namespace WebCore { + +class FrameView; + +class ScreenOrientationController FINAL : public NoBaseWillBeGarbageCollectedFinalized<ScreenOrientationController>, public WillBeHeapSupplement<LocalFrame>, public PageLifecycleObserver { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(ScreenOrientationController); + WTF_MAKE_NONCOPYABLE(ScreenOrientationController); +public: + virtual ~ScreenOrientationController(); + + virtual void persistentHostHasBeenDestroyed() OVERRIDE; + + blink::WebScreenOrientationType orientation() const; + + static void provideTo(LocalFrame&, blink::WebScreenOrientationClient*); + static ScreenOrientationController& from(LocalFrame&); + static const char* supplementName(); + + void lockOrientation(blink::WebScreenOrientationLockType, blink::WebLockOrientationCallback*); + void unlockOrientation(); + +private: + explicit ScreenOrientationController(LocalFrame&, blink::WebScreenOrientationClient*); + static blink::WebScreenOrientationType computeOrientation(FrameView*); + + // Inherited from PageLifecycleObserver. + virtual void pageVisibilityChanged() OVERRIDE; + + blink::WebScreenOrientationType m_overrideOrientation; + blink::WebScreenOrientationClient* m_client; + LocalFrame& m_frame; +}; + +} // namespace WebCore + +#endif // ScreenOrientationController_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.cpp new file mode 100644 index 00000000000..1ddf95d3fd1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.cpp @@ -0,0 +1,43 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/serviceworkers/Client.h" + +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h" +#include "public/platform/WebString.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +PassRefPtr<Client> Client::create(unsigned id) +{ + return adoptRef(new Client(id)); +} + +Client::Client(unsigned id) + : m_id(id) +{ + ScriptWrappable::init(this); +} + +Client::~Client() +{ +} + +void Client::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionState& exceptionState) +{ + // Disentangle the port in preparation for sending it to the remote context. + OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, exceptionState); + if (exceptionState.hadException()) + return; + + blink::WebString messageString = message->toWireString(); + OwnPtr<blink::WebMessagePortChannelArray> webChannels = MessagePort::toWebMessagePortChannelArray(channels.release()); + ServiceWorkerGlobalScopeClient::from(context)->postMessageToClient(m_id, messageString, webChannels.release()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.h new file mode 100644 index 00000000000..d467e47aab7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.h @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef Client_h +#define Client_h + +#include "bindings/v8/ScriptWrappable.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "wtf/Forward.h" + +namespace WebCore { + +class Client FINAL : public RefCounted<Client>, public ScriptWrappable { +public: + static PassRefPtr<Client> create(unsigned id); + ~Client(); + + // Client.idl + unsigned id() const { return m_id; } + void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionState&); + +private: + explicit Client(unsigned id); + + unsigned m_id; +}; + +} // namespace WebCore + +#endif // Client_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.idl new file mode 100644 index 00000000000..e30fd2b0c06 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Client.idl @@ -0,0 +1,16 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#client-interface +[ + Exposed=ServiceWorker, + RuntimeEnabled=ServiceWorker +] interface Client { + readonly attribute unsigned long id; + + // FIXME: Currently we think targetOrigin's probably not necessary, but + // re-add it if the ongoing issue [1] concludes the other way. + // [1] https://github.com/slightlyoff/ServiceWorker/issues/190 + [Custom, RaisesException, CallWith=ExecutionContext] void postMessage(SerializedScriptValue message, optional MessagePort[] messagePorts); +}; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp new file mode 100644 index 00000000000..9ca53a66627 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp @@ -0,0 +1,57 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "FetchEvent.h" + +#include "modules/serviceworkers/Request.h" +#include "modules/serviceworkers/ServiceWorkerGlobalScope.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<FetchEvent> FetchEvent::create() +{ + return adoptRefWillBeNoop(new FetchEvent()); +} + +PassRefPtrWillBeRawPtr<FetchEvent> FetchEvent::create(PassRefPtr<RespondWithObserver> observer, PassRefPtr<Request> request) +{ + return adoptRefWillBeNoop(new FetchEvent(observer, request)); +} + +Request* FetchEvent::request() const +{ + return m_request.get(); +} + +void FetchEvent::respondWith(ScriptState* scriptState, const ScriptValue& value) +{ + m_observer->respondWith(scriptState, value); +} + +const AtomicString& FetchEvent::interfaceName() const +{ + return EventNames::FetchEvent; +} + +FetchEvent::FetchEvent() +{ + ScriptWrappable::init(this); +} + +FetchEvent::FetchEvent(PassRefPtr<RespondWithObserver> observer, PassRefPtr<Request> request) + : Event(EventTypeNames::fetch, /*canBubble=*/false, /*cancelable=*/true) + , m_observer(observer) + , m_request(request) +{ + ScriptWrappable::init(this); +} + +void FetchEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h new file mode 100644 index 00000000000..50b7a729f8d --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h @@ -0,0 +1,46 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FetchEvent_h +#define FetchEvent_h + +#include "modules/EventModules.h" +#include "modules/serviceworkers/Request.h" +#include "modules/serviceworkers/RespondWithObserver.h" + +namespace WebCore { + +class ExecutionContext; +class Request; +class RespondWithObserver; + +// A fetch event is dispatched by the client to a service worker's script +// context. RespondWithObserver can be used to notify the client about the +// service worker's response. +class FetchEvent FINAL : public Event { +public: + static PassRefPtrWillBeRawPtr<FetchEvent> create(); + static PassRefPtrWillBeRawPtr<FetchEvent> create(PassRefPtr<RespondWithObserver>, PassRefPtr<Request>); + virtual ~FetchEvent() { } + + Request* request() const; + + void respondWith(ScriptState*, const ScriptValue&); + + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; + +protected: + FetchEvent(); + FetchEvent(PassRefPtr<RespondWithObserver>, PassRefPtr<Request>); + +private: + RefPtr<RespondWithObserver> m_observer; + RefPtr<Request> m_request; +}; + +} // namespace WebCore + +#endif // FetchEvent_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.idl new file mode 100644 index 00000000000..acb860f73c7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.idl @@ -0,0 +1,13 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#fetch-event-interface +[ + RuntimeEnabled=ServiceWorker, + Exposed=ServiceWorker +] interface FetchEvent : Event { + readonly attribute Request request; + + [CallWith=ScriptState] void respondWith(any value); +}; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchManager.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchManager.cpp new file mode 100644 index 00000000000..ef174005747 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchManager.cpp @@ -0,0 +1,172 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "FetchManager.h" + +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8ThrowException.h" +#include "core/dom/ExceptionCode.h" +#include "core/fileapi/Blob.h" +#include "core/loader/ThreadableLoader.h" +#include "core/loader/ThreadableLoaderClient.h" +#include "modules/serviceworkers/Response.h" +#include "platform/network/ResourceRequest.h" +#include "wtf/HashSet.h" + +namespace WebCore { + +class FetchManager::Loader : public ThreadableLoaderClient { +public: + Loader(ExecutionContext*, FetchManager*, PassRefPtr<ScriptPromiseResolverWithContext>, PassOwnPtr<ResourceRequest>); + ~Loader(); + virtual void didReceiveResponse(unsigned long, const ResourceResponse&); + virtual void didFinishLoading(unsigned long, double); + virtual void didFail(const ResourceError&); + virtual void didFailAccessControlCheck(const ResourceError&); + virtual void didFailRedirectCheck(); + virtual void didDownloadData(int); + + void start(); + void cleanup(); + +private: + void failed(); + void notifyFinished(); + + ExecutionContext* m_executionContext; + FetchManager* m_fetchManager; + RefPtr<ScriptPromiseResolverWithContext> m_resolver; + OwnPtr<ResourceRequest> m_request; + RefPtr<ThreadableLoader> m_loader; + ResourceResponse m_response; + long long m_downloadedBlobLength; + bool m_failed; +}; + +FetchManager::Loader::Loader(ExecutionContext* executionContext, FetchManager* fetchManager, PassRefPtr<ScriptPromiseResolverWithContext> resolver, PassOwnPtr<ResourceRequest> request) + : m_executionContext(executionContext) + , m_fetchManager(fetchManager) + , m_resolver(resolver) + , m_request(request) + , m_downloadedBlobLength(0) + , m_failed(false) +{ +} + +FetchManager::Loader::~Loader() +{ + if (m_loader) + m_loader->cancel(); +} + +void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceResponse& response) +{ + m_response = response; +} + +void FetchManager::Loader::didFinishLoading(unsigned long, double) +{ + OwnPtr<BlobData> blobData = BlobData::create(); + String filePath = m_response.downloadedFilePath(); + if (!filePath.isEmpty() && m_downloadedBlobLength) { + blobData->appendFile(filePath); + // FIXME: Set the ContentType correctly. + } + Dictionary options; + // FIXME: fill options. + RefPtrWillBeRawPtr<Blob> blob = Blob::create(BlobDataHandle::create(blobData.release(), m_downloadedBlobLength)); + // FIXME: Handle response status correctly. + m_resolver->resolve(Response::create(blob.get(), options)); + notifyFinished(); +} + +void FetchManager::Loader::didFail(const ResourceError& error) +{ + failed(); +} + +void FetchManager::Loader::didFailAccessControlCheck(const ResourceError& error) +{ + failed(); +} + +void FetchManager::Loader::didFailRedirectCheck() +{ + failed(); +} + +void FetchManager::Loader::didDownloadData(int dataLength) +{ + m_downloadedBlobLength += dataLength; +} + +void FetchManager::Loader::start() +{ + m_request->setDownloadToFile(true); + ThreadableLoaderOptions options; + // FIXME: Fill options. + ResourceLoaderOptions resourceLoaderOptions; + resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; + // FIXME: Fill resourceLoaderOptions. + m_loader = ThreadableLoader::create(*m_executionContext, this, *m_request, options, resourceLoaderOptions); +} + +void FetchManager::Loader::cleanup() +{ + // Prevent notification + m_fetchManager = 0; + + if (m_loader) { + m_loader->cancel(); + m_loader.clear(); + } +} + +void FetchManager::Loader::failed() +{ + if (m_failed) + return; + m_failed = true; + ScriptState* state = m_resolver->scriptState(); + ScriptState::Scope scope(state); + m_resolver->reject(V8ThrowException::createTypeError("Failed to fetch", state->isolate())); + notifyFinished(); +} + +void FetchManager::Loader::notifyFinished() +{ + if (m_fetchManager) + m_fetchManager->onLoaderFinished(this); +} + +FetchManager::FetchManager(ExecutionContext* executionContext) + : m_executionContext(executionContext) +{ +} + +FetchManager::~FetchManager() +{ + for (HashSet<OwnPtr<Loader> >::iterator it = m_loaders.begin(); it != m_loaders.end(); ++it) { + (*it)->cleanup(); + } +} + +ScriptPromise FetchManager::fetch(ScriptState* scriptState, PassOwnPtr<ResourceRequest> request) +{ + RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState); + ScriptPromise promise = resolver->promise(); + + OwnPtr<Loader> loader(adoptPtr(new Loader(m_executionContext, this, resolver.release(), request))); + (*m_loaders.add(loader.release()).storedValue)->start(); + return promise; +} + +void FetchManager::onLoaderFinished(Loader* loader) +{ + m_loaders.remove(loader); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchManager.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchManager.h new file mode 100644 index 00000000000..eadbc97ca2f --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/FetchManager.h @@ -0,0 +1,36 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FetchManager_h +#define FetchManager_h + +#include "bindings/v8/ScriptPromise.h" +#include "wtf/HashSet.h" +#include "wtf/OwnPtr.h" + +namespace WebCore { + +class ExecutionContext; +class ScriptState; +class ResourceRequest; + +class FetchManager { +public: + FetchManager(ExecutionContext*); + ~FetchManager(); + ScriptPromise fetch(ScriptState*, PassOwnPtr<ResourceRequest>); + +private: + class Loader; + + // Removes loader from |m_loaders|. + void onLoaderFinished(Loader*); + + ExecutionContext* m_executionContext; + HashSet<OwnPtr<Loader> > m_loaders; +}; + +} // namespace WebCore + +#endif // FetchManager_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.cpp new file mode 100644 index 00000000000..41c67f91438 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.cpp @@ -0,0 +1,93 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/serviceworkers/HeaderMap.h" + +#include "bindings/v8/ExceptionState.h" +#include "modules/serviceworkers/HeaderMapForEachCallback.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefPtr.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +PassRefPtr<HeaderMap> HeaderMap::create() +{ + return adoptRef(new HeaderMap); +} + +PassRefPtr<HeaderMap> HeaderMap::create(const HashMap<String, String>& headers) +{ + return adoptRef(new HeaderMap(headers)); +} + +unsigned long HeaderMap::size() const +{ + return m_headers.size(); +} + +void HeaderMap::clear() +{ + m_headers.clear(); +} + +bool HeaderMap::remove(const String& key) +{ + if (!has(key)) + return false; + m_headers.remove(key); + return true; +} + +String HeaderMap::get(const String& key) +{ + return m_headers.get(key); +} + +bool HeaderMap::has(const String& key) +{ + return m_headers.find(key) != m_headers.end(); +} + +void HeaderMap::set(const String& key, const String& value) +{ + m_headers.set(key, value); +} + +void HeaderMap::forEach(PassOwnPtr<HeaderMapForEachCallback> callback, ScriptValue& thisArg) +{ + forEachInternal(callback, &thisArg); +} + +void HeaderMap::forEach(PassOwnPtr<HeaderMapForEachCallback> callback) +{ + forEachInternal(callback, 0); +} + +HeaderMap::HeaderMap() +{ + ScriptWrappable::init(this); +} + +HeaderMap::HeaderMap(const HashMap<String, String>& headers) + : m_headers(headers) +{ + ScriptWrappable::init(this); +} + +void HeaderMap::forEachInternal(PassOwnPtr<HeaderMapForEachCallback> callback, ScriptValue* thisArg) +{ + TrackExceptionState exceptionState; + for (HashMap<String, String>::const_iterator it = m_headers.begin(); it != m_headers.end(); ++it) { + if (thisArg) + callback->handleItem(*thisArg, it->value, it->key, this); + else + callback->handleItem(it->value, it->key, this); + if (exceptionState.hadException()) + break; + } +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.h new file mode 100644 index 00000000000..3e5b47f567d --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.h @@ -0,0 +1,47 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HeaderMap_h +#define HeaderMap_h + +#include "bindings/v8/ScriptWrappable.h" +#include "wtf/Forward.h" +#include "wtf/HashMap.h" +#include "wtf/RefCounted.h" +#include "wtf/text/StringHash.h" + +namespace WebCore { + +class HeaderMapForEachCallback; +class ScriptValue; + +class HeaderMap FINAL : public ScriptWrappable, public RefCounted<HeaderMap> { +public: + static PassRefPtr<HeaderMap> create(); + static PassRefPtr<HeaderMap> create(const HashMap<String, String>& headers); + + // HeaderMap.idl implementation. + unsigned long size() const; + void clear(); + bool remove(const String& key); + String get(const String& key); + bool has(const String& key); + void set(const String& key, const String& value); + void forEach(PassOwnPtr<HeaderMapForEachCallback>, ScriptValue&); + void forEach(PassOwnPtr<HeaderMapForEachCallback>); + + const HashMap<String, String>& headerMap() const { return m_headers; } + +private: + HeaderMap(); + explicit HeaderMap(const HashMap<String, String>& headers); + void forEachInternal(PassOwnPtr<HeaderMapForEachCallback>, ScriptValue* thisArg); + + // FIXME: this doesn't preserve ordering while ES6 Map type requires it. + HashMap<String, String> m_headers; +}; + +} // namespace WebCore + +#endif // HeaderMap_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.idl new file mode 100644 index 00000000000..38d198bda48 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMap.idl @@ -0,0 +1,28 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://fetch.spec.whatwg.org/#headers-class +// FIXME: Fetch spec has renamed this to just 'Headers' +// FIXME: This should be defined as MapClass(DOMString, DOMString) +// once binding code supports it (http://crbug.com/347435). +[ + Constructor, + RuntimeEnabled=ServiceWorker, + Exposed=ServiceWorker +] interface HeaderMap { + readonly attribute unsigned long size; + + // FIXME: Define keys, values, entries. + // FIXME: Some of the method definitions (like set) don't strictly + // follow the MapClass's ones (http://heycam.github.io/webidl/#MapClass), + // as this is supposed to be a transient implementation until we have real + // MapClass. + + void clear(); + [ImplementedAs=remove] boolean delete(DOMString key); + DOMString get(DOMString key); + boolean has(DOMString key); + void set(DOMString key, DOMString value); + void forEach(HeaderMapForEachCallback callback, optional any thisArg); +}; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMapForEachCallback.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMapForEachCallback.h new file mode 100644 index 00000000000..7991c2376fe --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMapForEachCallback.h @@ -0,0 +1,23 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HeaderMapForEachCallback_h +#define HeaderMapForEachCallback_h + +#include "bindings/v8/ScriptValue.h" + +namespace WebCore { + +class HeaderMap; + +class HeaderMapForEachCallback { +public: + virtual ~HeaderMapForEachCallback() { } + virtual bool handleItem(ScriptValue thisValue, const String& value, const String& key, HeaderMap*) = 0; + virtual bool handleItem(const String& value, const String& key, HeaderMap*) = 0; +}; + +} // namespace WebCore + +#endif // HeaderMapForEachCallback_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMapForEachCallback.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMapForEachCallback.idl new file mode 100644 index 00000000000..d6bbb8dfc96 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/HeaderMapForEachCallback.idl @@ -0,0 +1,8 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +callback interface HeaderMapForEachCallback { + [CallWith=ThisValue] boolean handleItem(DOMString value, DOMString key, HeaderMap map); + boolean handleItem(DOMString value, DOMString key, HeaderMap map); +}; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallEvent.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallEvent.cpp new file mode 100644 index 00000000000..be4f1afd47d --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallEvent.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InstallEvent.h" + +#include "bindings/v8/ScriptPromiseResolver.h" +#include "modules/serviceworkers/WaitUntilObserver.h" +#include "platform/NotImplemented.h" +#include "wtf/RefPtr.h" +#include <v8.h> + +namespace WebCore { + +PassRefPtrWillBeRawPtr<InstallEvent> InstallEvent::create() +{ + return adoptRefWillBeNoop(new InstallEvent()); +} + +PassRefPtrWillBeRawPtr<InstallEvent> InstallEvent::create(const AtomicString& type, const EventInit& initializer, PassRefPtr<WaitUntilObserver> observer) +{ + return adoptRefWillBeNoop(new InstallEvent(type, initializer, observer)); +} + +void InstallEvent::replace() +{ + // FIXME: implement. + notImplemented(); +} + +ScriptPromise InstallEvent::reloadAll(ScriptState* scriptState) +{ + // FIXME: implement. + notImplemented(); + + // For now this just returns a promise which is already rejected. + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + resolver->reject(ScriptValue(scriptState, v8::Null(scriptState->isolate()))); + return promise; +} + +const AtomicString& InstallEvent::interfaceName() const +{ + return EventNames::InstallEvent; +} + +InstallEvent::InstallEvent() +{ + ScriptWrappable::init(this); +} + +InstallEvent::InstallEvent(const AtomicString& type, const EventInit& initializer, PassRefPtr<WaitUntilObserver> observer) + : InstallPhaseEvent(type, initializer, observer) +{ + ScriptWrappable::init(this); +} + +void InstallEvent::trace(Visitor* visitor) +{ + InstallPhaseEvent::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/crypto/KeyPair.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallEvent.h index 7377e93e4b4..cc2e615abaa 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/KeyPair.h +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallEvent.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,34 +28,36 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef KeyPair_h -#define KeyPair_h +#ifndef InstallEvent_h +#define InstallEvent_h -#include "bindings/v8/ScriptWrappable.h" +#include "bindings/v8/ScriptPromise.h" +#include "modules/serviceworkers/InstallPhaseEvent.h" #include "wtf/Forward.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" - -namespace blink { class WebCryptoKey; } namespace WebCore { -class Key; +class ExecutionContext; -class KeyPair : public ScriptWrappable, public RefCounted<KeyPair> { +class InstallEvent FINAL : public InstallPhaseEvent { public: - static PassRefPtr<KeyPair> create(const blink::WebCryptoKey& publicKey, const blink::WebCryptoKey& privateKey); + static PassRefPtrWillBeRawPtr<InstallEvent> create(); + static PassRefPtrWillBeRawPtr<InstallEvent> create(const AtomicString& type, const EventInit&, PassRefPtr<WaitUntilObserver>); + virtual ~InstallEvent() { } + + void replace(); + + ScriptPromise reloadAll(ScriptState*); - Key* publicKey() { return m_publicKey.get(); } - Key* privateKey() { return m_privateKey.get(); } + virtual const AtomicString& interfaceName() const OVERRIDE; -protected: - KeyPair(const PassRefPtr<Key>& publicKey, const PassRefPtr<Key>& privateKey); + virtual void trace(Visitor*) OVERRIDE; - RefPtr<Key> m_publicKey; - RefPtr<Key> m_privateKey; +private: + InstallEvent(); + InstallEvent(const AtomicString& type, const EventInit&, PassRefPtr<WaitUntilObserver>); }; } // namespace WebCore -#endif +#endif // InstallEvent_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallEvent.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallEvent.idl new file mode 100644 index 00000000000..b014697ec0b --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallEvent.idl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#install-event-interface +[ + RuntimeEnabled=ServiceWorker, + Exposed=ServiceWorker, +] interface InstallEvent : InstallPhaseEvent { + void replace(); + [CallWith=ScriptState] Promise reloadAll(); +}; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallPhaseEvent.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallPhaseEvent.cpp new file mode 100644 index 00000000000..ff41b47aed2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallPhaseEvent.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InstallPhaseEvent.h" + +#include "bindings/v8/ScriptWrappable.h" +#include "modules/serviceworkers/WaitUntilObserver.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<InstallPhaseEvent> InstallPhaseEvent::create() +{ + return adoptRefWillBeNoop(new InstallPhaseEvent()); +} + +PassRefPtrWillBeRawPtr<InstallPhaseEvent> InstallPhaseEvent::create(const AtomicString& type, const EventInit& eventInit, PassRefPtr<WaitUntilObserver> observer) +{ + return adoptRefWillBeNoop(new InstallPhaseEvent(type, eventInit, observer)); +} + +InstallPhaseEvent::~InstallPhaseEvent() +{ +} + +void InstallPhaseEvent::waitUntil(ScriptState* scriptState, const ScriptValue& value) +{ + m_observer->waitUntil(scriptState, value); +} + +InstallPhaseEvent::InstallPhaseEvent() +{ + ScriptWrappable::init(this); +} + +InstallPhaseEvent::InstallPhaseEvent(const AtomicString& type, const EventInit& initializer, PassRefPtr<WaitUntilObserver> observer) + : Event(type, initializer) + , m_observer(observer) +{ + ScriptWrappable::init(this); +} + +const AtomicString& InstallPhaseEvent::interfaceName() const +{ + return EventNames::InstallPhaseEvent; +} + +void InstallPhaseEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventDispatcher.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallPhaseEvent.h index 26c269515f9..883c1474e0f 100644 --- a/chromium/third_party/WebKit/Source/modules/device_orientation/DeviceSensorEventDispatcher.h +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallPhaseEvent.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,31 +28,35 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DeviceSensorEventDispatcher_h -#define DeviceSensorEventDispatcher_h +#ifndef InstallPhaseEvent_h +#define InstallPhaseEvent_h -#include "wtf/Vector.h" +#include "bindings/v8/ScriptValue.h" +#include "modules/EventModules.h" namespace WebCore { -class DeviceSensorEventController; -class DeviceSensorEventDispatcher { -protected: - DeviceSensorEventDispatcher(); - virtual ~DeviceSensorEventDispatcher(); +class WaitUntilObserver; + +class InstallPhaseEvent : public Event { +public: + static PassRefPtrWillBeRawPtr<InstallPhaseEvent> create(); + static PassRefPtrWillBeRawPtr<InstallPhaseEvent> create(const AtomicString& type, const EventInit&, PassRefPtr<WaitUntilObserver>); + + virtual ~InstallPhaseEvent(); - void addController(DeviceSensorEventController*); - void removeController(DeviceSensorEventController*); - void purgeControllers(); + void waitUntil(ScriptState*, const ScriptValue&); - virtual void startListening() = 0; - virtual void stopListening() = 0; + virtual const AtomicString& interfaceName() const OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + +protected: + InstallPhaseEvent(); + InstallPhaseEvent(const AtomicString& type, const EventInit&, PassRefPtr<WaitUntilObserver>); - Vector<DeviceSensorEventController*> m_controllers; - bool m_needsPurge; - bool m_isDispatching; + RefPtr<WaitUntilObserver> m_observer; }; } // namespace WebCore -#endif // DeviceSensorEventDispatcher_h +#endif // InstallPhaseEvent_h diff --git a/chromium/third_party/WebKit/Source/modules/crypto/AesCtrParams.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallPhaseEvent.idl index 58f3fdaec90..9f2637f9c56 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/AesCtrParams.idl +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/InstallPhaseEvent.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,9 +28,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#install-phase-event-interface [ - NoInterfaceObject, -] interface AesCtrParams : Algorithm { - readonly attribute Uint8Array counter; - readonly attribute octet length; + RuntimeEnabled=ServiceWorker, + Exposed=ServiceWorker, +] interface InstallPhaseEvent : Event { + [CallWith=ScriptState] void waitUntil(any value); }; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp index c68f1442c61..3af213969a3 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp @@ -1,60 +1,20 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "config.h" #include "modules/serviceworkers/NavigatorServiceWorker.h" -#include "RuntimeEnabledFeatures.h" -#include "bindings/v8/CallbackPromiseAdapter.h" -#include "bindings/v8/ScriptPromiseResolver.h" #include "core/dom/Document.h" -#include "core/dom/ExceptionCode.h" -#include "core/dom/ExecutionContext.h" -#include "core/frame/Frame.h" -#include "core/loader/DocumentLoader.h" -#include "core/loader/FrameLoaderClient.h" -#include "core/workers/SharedWorker.h" -#include "modules/serviceworkers/ServiceWorker.h" -#include "modules/serviceworkers/ServiceWorkerError.h" -#include "public/platform/WebServiceWorkerProvider.h" -#include "public/platform/WebServiceWorkerProviderClient.h" -#include "public/platform/WebString.h" -#include "public/platform/WebURL.h" - -using blink::WebServiceWorkerProvider; -using blink::WebString; +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Navigator.h" +#include "modules/serviceworkers/ServiceWorkerContainer.h" namespace WebCore { -NavigatorServiceWorker::NavigatorServiceWorker(Navigator* navigator) - : DOMWindowProperty(navigator->frame()) - , m_navigator(navigator) +NavigatorServiceWorker::NavigatorServiceWorker(Navigator& navigator) + : DOMWindowProperty(navigator.frame()) { } @@ -62,104 +22,56 @@ NavigatorServiceWorker::~NavigatorServiceWorker() { } -const char* NavigatorServiceWorker::supplementName() -{ - return "NavigatorServiceWorker"; -} - -WebServiceWorkerProvider* NavigatorServiceWorker::ensureProvider() +NavigatorServiceWorker* NavigatorServiceWorker::from(Document& document) { - ASSERT(m_navigator->frame()); - if (!m_provider) { - Frame* frame = m_navigator->frame(); - - FrameLoaderClient* client = frame->loader().client(); - // FIXME: This is temporarily hooked up here until we hook up to the loading process. - m_provider = client->createServiceWorkerProvider(nullptr); - } - return m_provider.get(); + if (!document.frame() || !document.frame()->domWindow()) + return 0; + Navigator& navigator = document.frame()->domWindow()->navigator(); + return &from(navigator); } -NavigatorServiceWorker* NavigatorServiceWorker::from(Navigator* navigator) +NavigatorServiceWorker& NavigatorServiceWorker::from(Navigator& navigator) { NavigatorServiceWorker* supplement = toNavigatorServiceWorker(navigator); if (!supplement) { supplement = new NavigatorServiceWorker(navigator); - provideTo(navigator, supplementName(), adoptPtr(supplement)); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); + // Initialize ServiceWorkerContainer too. + supplement->serviceWorker(); } - return supplement; + return *supplement; } -ScriptPromise NavigatorServiceWorker::registerServiceWorker(ExecutionContext* context, Navigator* navigator, const String& pattern, const String& url, ExceptionState& exceptionState) +NavigatorServiceWorker* NavigatorServiceWorker::toNavigatorServiceWorker(Navigator& navigator) { - return from(navigator)->registerServiceWorker(context, pattern, url, exceptionState); + return static_cast<NavigatorServiceWorker*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); } -ScriptPromise NavigatorServiceWorker::registerServiceWorker(ExecutionContext* executionContext, const String& pattern, const String& scriptSrc, ExceptionState& exceptionState) +const char* NavigatorServiceWorker::supplementName() { - ASSERT(RuntimeEnabledFeatures::serviceWorkerEnabled()); - ScriptPromise promise = ScriptPromise::createPending(executionContext); - RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(promise, executionContext); - - Frame* frame = m_navigator->frame(); - if (!frame) { - resolver->reject(DOMError::create(InvalidStateError, "No document available.")); - return promise; - } - - RefPtr<SecurityOrigin> documentOrigin = frame->document()->securityOrigin(); - - KURL patternURL = executionContext->completeURL(pattern); - if (!documentOrigin->canRequest(patternURL)) { - resolver->reject(DOMError::create(SecurityError, "Can only register for patterns in the document's origin.")); - return promise; - } - - KURL scriptURL = executionContext->completeURL(scriptSrc); - if (!documentOrigin->canRequest(scriptURL)) { - resolver->reject(DOMError::create(SecurityError, "Script must be in document's origin.")); - return promise; - } - - ensureProvider()->registerServiceWorker(patternURL, scriptURL, new CallbackPromiseAdapter<ServiceWorker, ServiceWorkerError>(resolver, executionContext)); - return promise; + return "NavigatorServiceWorker"; } -ScriptPromise NavigatorServiceWorker::unregisterServiceWorker(ExecutionContext* context, Navigator* navigator, const String& pattern, ExceptionState& exceptionState) +ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(Navigator& navigator) { - return from(navigator)->unregisterServiceWorker(context, pattern, exceptionState); + return NavigatorServiceWorker::from(navigator).serviceWorker(); } -ScriptPromise NavigatorServiceWorker::unregisterServiceWorker(ExecutionContext* executionContext, const String& pattern, ExceptionState& exceptionState) +ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker() { - ASSERT(RuntimeEnabledFeatures::serviceWorkerEnabled()); - ScriptPromise promise = ScriptPromise::createPending(executionContext); - RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(promise, executionContext); - - Frame* frame = m_navigator->frame(); - if (!frame) { - resolver->reject(DOMError::create(InvalidStateError, "No document available.")); - return promise; + if (!m_serviceWorker && frame()) { + ASSERT(frame()->domWindow()); + m_serviceWorker = ServiceWorkerContainer::create(frame()->domWindow()->executionContext()); } - - RefPtr<SecurityOrigin> documentOrigin = frame->document()->securityOrigin(); - - KURL patternURL = executionContext->completeURL(pattern); - if (!documentOrigin->canRequest(patternURL)) { - resolver->reject(DOMError::create(SecurityError, "Can only unregister for patterns in the document's origin.")); - - return promise; - } - - ensureProvider()->unregisterServiceWorker(patternURL, new CallbackPromiseAdapter<ServiceWorker, ServiceWorkerError>(resolver, executionContext)); - return promise; + return m_serviceWorker.get(); } void NavigatorServiceWorker::willDetachGlobalObjectFromFrame() { - m_provider = nullptr; - DOMWindowProperty::willDetachGlobalObjectFromFrame(); + if (m_serviceWorker) { + m_serviceWorker->detachClient(); + m_serviceWorker = nullptr; + } } - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h index c1e60e5fbab..39cc29a364a 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h @@ -1,73 +1,41 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef NavigatorServiceWorker_h #define NavigatorServiceWorker_h -#include "bindings/v8/ScriptPromise.h" #include "core/frame/Navigator.h" #include "platform/Supplementable.h" - -namespace blink { -class WebServiceWorkerProvider; -class WebServiceWorkerProviderClient; -} +#include "platform/heap/Handle.h" namespace WebCore { -class ExceptionState; +class Document; class Navigator; +class ServiceWorkerContainer; -class NavigatorServiceWorker : public Supplement<Navigator>, DOMWindowProperty { +class NavigatorServiceWorker FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorServiceWorker>, public WillBeHeapSupplement<Navigator>, DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorServiceWorker); public: virtual ~NavigatorServiceWorker(); - static NavigatorServiceWorker* from(Navigator*); - static NavigatorServiceWorker* toNavigatorServiceWorker(Navigator* navigator) { return static_cast<NavigatorServiceWorker*>(Supplement<Navigator>::from(navigator, supplementName())); } + static NavigatorServiceWorker* from(Document&); + static NavigatorServiceWorker& from(Navigator&); + static NavigatorServiceWorker* toNavigatorServiceWorker(Navigator&); + static const char* supplementName(); - static ScriptPromise registerServiceWorker(ExecutionContext*, Navigator*, const String& pattern, const String& src, ExceptionState&); - static ScriptPromise unregisterServiceWorker(ExecutionContext*, Navigator*, const String& pattern, ExceptionState&); + static ServiceWorkerContainer* serviceWorker(Navigator&); -private: - ScriptPromise registerServiceWorker(ExecutionContext*, const String& pattern, const String& src, ExceptionState&); - ScriptPromise unregisterServiceWorker(ExecutionContext*, const String& pattern, ExceptionState&); + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Navigator>::trace(visitor); } - explicit NavigatorServiceWorker(Navigator*); +private: + explicit NavigatorServiceWorker(Navigator&); + ServiceWorkerContainer* serviceWorker(); + // DOMWindowProperty override. virtual void willDetachGlobalObjectFromFrame() OVERRIDE; - blink::WebServiceWorkerProvider* ensureProvider(); - - static const char* supplementName(); - - Navigator* m_navigator; - OwnPtr<blink::WebServiceWorkerProvider> m_provider; + RefPtr<ServiceWorkerContainer> m_serviceWorker; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.idl index a2dcebf31e5..6ed88f01411 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.idl +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.idl @@ -1,35 +1,10 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#navigator-service-worker [ - RuntimeEnabled=ServiceWorker + RuntimeEnabled=ServiceWorker, ] partial interface Navigator { - [CallWith=ExecutionContext, RaisesException] Promise registerServiceWorker(DOMString pattern, DOMString src); - [CallWith=ExecutionContext, RaisesException] Promise unregisterServiceWorker(DOMString pattern); + readonly attribute ServiceWorkerContainer serviceWorker; }; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/OWNERS b/chromium/third_party/WebKit/Source/modules/serviceworkers/OWNERS index b960cf401c7..e97b8bd1d6b 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/OWNERS @@ -1,2 +1,5 @@ -alecflett@chromium.org michaeln@chromium.org +kinuko@chromium.org +jsbell@chromium.org +dominicc@chromium.org +falken@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/RegistrationOptionList.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/RegistrationOptionList.h new file mode 100644 index 00000000000..c673a2fbfe7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/RegistrationOptionList.h @@ -0,0 +1,25 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RegistrationOptionList_h +#define RegistrationOptionList_h + +#include "bindings/v8/Dictionary.h" + +namespace WebCore { + +struct RegistrationOptionList { + explicit RegistrationOptionList(const Dictionary& options) + : scope("/*") + { + // FIXME: Should be ScalarValueString. http://crbug.com/379009 + options.get("scope", scope); + } + + String scope; +}; + +} // namespace WebCore + +#endif // RegistrationOptionList_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.cpp new file mode 100644 index 00000000000..69e34b42b93 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.cpp @@ -0,0 +1,74 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "Request.h" + +#include "bindings/v8/Dictionary.h" +#include "core/dom/DOMURLUtilsReadOnly.h" +#include "modules/serviceworkers/RequestInit.h" +#include "platform/NotImplemented.h" +#include "platform/network/ResourceRequest.h" +#include "public/platform/WebServiceWorkerRequest.h" + +namespace WebCore { + +PassRefPtr<Request> Request::create() +{ + return create(Dictionary()); +} + +PassRefPtr<Request> Request::create(const Dictionary& requestInit) +{ + return adoptRef(new Request(RequestInit(requestInit))); +} + +PassRefPtr<Request> Request::create(const blink::WebServiceWorkerRequest& webRequest) +{ + return adoptRef(new Request(webRequest)); +} + +void Request::setURL(const String& value) +{ + m_url = KURL(ParsedURLString, value); +} + +void Request::setMethod(const String& value) +{ + m_method = value; +} + +String Request::origin() const +{ + return DOMURLUtilsReadOnly::origin(m_url); +} + +PassOwnPtr<ResourceRequest> Request::createResourceRequest() const +{ + OwnPtr<ResourceRequest> request = adoptPtr(new ResourceRequest(m_url)); + request->setHTTPMethod("GET"); + // FIXME: Fill more info. + return request.release(); +} + +Request::Request(const RequestInit& requestInit) + : m_url(KURL(ParsedURLString, requestInit.url)) + , m_method(requestInit.method) + , m_headers(requestInit.headers) +{ + ScriptWrappable::init(this); + + if (!m_headers) + m_headers = HeaderMap::create(); +} + +Request::Request(const blink::WebServiceWorkerRequest& webRequest) + : m_url(webRequest.url()) + , m_method(webRequest.method()) + , m_headers(HeaderMap::create(webRequest.headers())) +{ + ScriptWrappable::init(this); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.h new file mode 100644 index 00000000000..a95141e003e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.h @@ -0,0 +1,50 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef Request_h +#define Request_h + +#include "bindings/v8/Dictionary.h" +#include "bindings/v8/ScriptWrappable.h" +#include "modules/serviceworkers/HeaderMap.h" +#include "platform/weborigin/KURL.h" +#include "wtf/RefCounted.h" +#include "wtf/RefPtr.h" +#include "wtf/text/WTFString.h" + +namespace blink { class WebServiceWorkerRequest; } + +namespace WebCore { + +struct RequestInit; +class ResourceRequest; + +class Request FINAL : public ScriptWrappable, public RefCounted<Request> { +public: + static PassRefPtr<Request> create(); + static PassRefPtr<Request> create(const Dictionary&); + static PassRefPtr<Request> create(const blink::WebServiceWorkerRequest&); + ~Request() { }; + + void setURL(const String& value); + void setMethod(const String& value); + + String url() const { return m_url.string(); } + String method() const { return m_method; } + String origin() const; + PassRefPtr<HeaderMap> headers() const { return m_headers; } + + PassOwnPtr<ResourceRequest> createResourceRequest() const; + +private: + explicit Request(const RequestInit&); + explicit Request(const blink::WebServiceWorkerRequest&); + KURL m_url; + String m_method; + RefPtr<HeaderMap> m_headers; +}; + +} // namespace WebCore + +#endif // Request_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.idl new file mode 100644 index 00000000000..aea4e9110a2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Request.idl @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://fetch.spec.whatwg.org/#request-class +[ + Constructor(optional Dictionary requestInitDict), + RuntimeEnabled=ServiceWorker, + Exposed=ServiceWorker +] interface Request { + attribute ScalarValueString url; + attribute ByteString method; + readonly attribute DOMString origin; + readonly attribute HeaderMap headers; + + // FIXME: Implement the following: + // attribute unsigned long timeout; + // readonly attribute Mode mode; + // attribute boolean synchronous; + // readonly attribute unsigned long redirectCount; + // attribute boolean forcePreflight; + // attribute boolean forceSameOrigin; + // attribute boolean omitCredentials; + // readonly attribute DOMString referrer; + // attribute any body; +}; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/RequestInit.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/RequestInit.h new file mode 100644 index 00000000000..191c8eac3d3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/RequestInit.h @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RequestInit_h +#define RequestInit_h + +#include "bindings/v8/Dictionary.h" +#include "modules/serviceworkers/HeaderMap.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +struct RequestInit { + explicit RequestInit(const Dictionary& options) + : method("GET") + { + options.get("url", url); + // FIXME: Spec uses ByteString for method. http://crbug.com/347426 + options.get("method", method); + options.get("headers", headers); + } + + String url; + String method; + RefPtr<HeaderMap> headers; +}; + +} + +#endif // RequestInit_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp new file mode 100644 index 00000000000..b80696d98e9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.cpp @@ -0,0 +1,124 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/serviceworkers/RespondWithObserver.h" + +#include "V8Response.h" +#include "bindings/v8/ScriptFunction.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptValue.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/ExecutionContext.h" +#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h" +#include "wtf/Assertions.h" +#include "wtf/RefPtr.h" +#include <v8.h> + +namespace WebCore { + +class RespondWithObserver::ThenFunction FINAL : public ScriptFunction { +public: + enum ResolveType { + Fulfilled, + Rejected, + }; + + static PassOwnPtr<ScriptFunction> create(PassRefPtr<RespondWithObserver> observer, ResolveType type) + { + ExecutionContext* executionContext = observer->executionContext(); + return adoptPtr(new ThenFunction(toIsolate(executionContext), observer, type)); + } + +private: + ThenFunction(v8::Isolate* isolate, PassRefPtr<RespondWithObserver> observer, ResolveType type) + : ScriptFunction(isolate) + , m_observer(observer) + , m_resolveType(type) + { + } + + virtual ScriptValue call(ScriptValue value) OVERRIDE + { + ASSERT(m_observer); + ASSERT(m_resolveType == Fulfilled || m_resolveType == Rejected); + if (m_resolveType == Rejected) + m_observer->responseWasRejected(); + else + m_observer->responseWasFulfilled(value); + m_observer = nullptr; + return value; + } + + RefPtr<RespondWithObserver> m_observer; + ResolveType m_resolveType; +}; + +PassRefPtr<RespondWithObserver> RespondWithObserver::create(ExecutionContext* context, int eventID) +{ + return adoptRef(new RespondWithObserver(context, eventID)); +} + +RespondWithObserver::~RespondWithObserver() +{ + ASSERT(m_state == Done); +} + +void RespondWithObserver::contextDestroyed() +{ + ContextLifecycleObserver::contextDestroyed(); + m_state = Done; +} + +void RespondWithObserver::didDispatchEvent() +{ + if (m_state == Initial) + sendResponse(nullptr); +} + +void RespondWithObserver::respondWith(ScriptState* scriptState, const ScriptValue& value) +{ + if (m_state != Initial) + return; + + m_state = Pending; + ScriptPromise::cast(scriptState, value).then( + ThenFunction::create(this, ThenFunction::Fulfilled), + ThenFunction::create(this, ThenFunction::Rejected)); +} + +void RespondWithObserver::sendResponse(PassRefPtr<Response> response) +{ + if (!executionContext()) + return; + ServiceWorkerGlobalScopeClient::from(executionContext())->didHandleFetchEvent(m_eventID, response); + m_state = Done; +} + +void RespondWithObserver::responseWasRejected() +{ + // FIXME: Throw a NetworkError to service worker's execution context. + sendResponse(nullptr); +} + +void RespondWithObserver::responseWasFulfilled(const ScriptValue& value) +{ + if (!executionContext()) + return; + if (!V8Response::hasInstance(value.v8Value(), toIsolate(executionContext()))) { + responseWasRejected(); + return; + } + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value.v8Value()); + sendResponse(V8Response::toNative(object)); +} + +RespondWithObserver::RespondWithObserver(ExecutionContext* context, int eventID) + : ContextLifecycleObserver(context) + , m_eventID(eventID) + , m_state(Initial) +{ +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.h new file mode 100644 index 00000000000..567edb5dc27 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/RespondWithObserver.h @@ -0,0 +1,54 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RespondWithObserver_h +#define RespondWithObserver_h + +#include "core/dom/ContextLifecycleObserver.h" +#include "wtf/Forward.h" +#include "wtf/RefCounted.h" + +namespace WebCore { + +class ExecutionContext; +class Response; +class ScriptState; +class ScriptValue; + +// This class observes the service worker's handling of a FetchEvent and +// notifies the client. +class RespondWithObserver FINAL : public ContextLifecycleObserver, public RefCounted<RespondWithObserver> { +public: + static PassRefPtr<RespondWithObserver> create(ExecutionContext*, int eventID); + ~RespondWithObserver(); + + virtual void contextDestroyed() OVERRIDE; + + void didDispatchEvent(); + + // Observes the promise and delays calling didHandleFetchEvent() until the + // given promise is resolved or rejected. + void respondWith(ScriptState*, const ScriptValue&); + + void responseWasRejected(); + void responseWasFulfilled(const ScriptValue&); + +private: + class ThenFunction; + + RespondWithObserver(ExecutionContext*, int eventID); + + // Sends a response back to the client. The null response means to fallback + // to native. + void sendResponse(PassRefPtr<Response>); + + int m_eventID; + + enum State { Initial, Pending, Done }; + State m_state; +}; + +} // namespace WebCore + +#endif // RespondWithObserver_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.cpp new file mode 100644 index 00000000000..4a95d7da459 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.cpp @@ -0,0 +1,51 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "Response.h" + +#include "bindings/v8/Dictionary.h" +#include "core/fileapi/Blob.h" +#include "modules/serviceworkers/ResponseInit.h" +#include "platform/NotImplemented.h" +#include "public/platform/WebServiceWorkerResponse.h" + +namespace WebCore { + +PassRefPtr<Response> Response::create(Blob* body, const Dictionary& responseInit) +{ + RefPtr<BlobDataHandle> blobDataHandle = body ? body->blobDataHandle() : nullptr; + + // FIXME: Maybe append or override content-length and content-type headers using the blob. The spec will clarify what to do: + // https://github.com/slightlyoff/ServiceWorker/issues/192 + return adoptRef(new Response(blobDataHandle.release(), ResponseInit(responseInit))); +} + +PassRefPtr<HeaderMap> Response::headers() const +{ + // FIXME: Implement. Spec will eventually whitelist allowable headers. + return m_headers; +} + +void Response::populateWebServiceWorkerResponse(blink::WebServiceWorkerResponse& response) +{ + response.setStatus(status()); + response.setStatusText(statusText()); + response.setHeaders(m_headers->headerMap()); + response.setBlobDataHandle(m_blobDataHandle); +} + +Response::Response(PassRefPtr<BlobDataHandle> blobDataHandle, const ResponseInit& responseInit) + : m_status(responseInit.status) + , m_statusText(responseInit.statusText) + , m_headers(responseInit.headers) + , m_blobDataHandle(blobDataHandle) +{ + ScriptWrappable::init(this); + + if (!m_headers) + m_headers = HeaderMap::create(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.h new file mode 100644 index 00000000000..a535e2eaa72 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.h @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef Response_h +#define Response_h + +#include "bindings/v8/Dictionary.h" +#include "bindings/v8/ScriptWrappable.h" +#include "modules/serviceworkers/HeaderMap.h" +#include "platform/blob/BlobData.h" +#include "wtf/RefCounted.h" +#include "wtf/RefPtr.h" +#include "wtf/text/WTFString.h" + +namespace blink { class WebServiceWorkerResponse; } + +namespace WebCore { + +class Blob; +struct ResponseInit; + +class Response FINAL : public ScriptWrappable, public RefCounted<Response> { +public: + static PassRefPtr<Response> create(Blob* body, const Dictionary& responseInit); + ~Response() { }; + + unsigned short status() const { return m_status; } + void setStatus(unsigned short value) { m_status = value; } + + String statusText() const { return m_statusText; } + void setStatusText(const String& value) { m_statusText = value; } + + PassRefPtr<HeaderMap> headers() const; + + void populateWebServiceWorkerResponse(blink::WebServiceWorkerResponse&); + +private: + Response(PassRefPtr<BlobDataHandle>, const ResponseInit&); + unsigned short m_status; + String m_statusText; + RefPtr<HeaderMap> m_headers; + RefPtr<BlobDataHandle> m_blobDataHandle; +}; + +} // namespace WebCore + +#endif // Response_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.idl new file mode 100644 index 00000000000..fb8ecf34369 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/Response.idl @@ -0,0 +1,20 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://fetch.spec.whatwg.org/#response-class +// FIXME: Split this idl/impl into AbstractResponse and Response. +[ + // FIXME: Add ctors for String, Stream, and ArrayBuffer/ArrayBufferView response bodies. + Constructor(Blob body, optional Dictionary responseInitDict), + RuntimeEnabled=ServiceWorker, + Exposed=ServiceWorker +] interface Response { + attribute unsigned short status; + attribute ByteString statusText; + readonly attribute HeaderMap headers; + + // FIXME: Implement the following: + // attribute DOMString url; + // Promise<Blob> toBlob(); +}; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ResponseInit.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ResponseInit.h new file mode 100644 index 00000000000..b82154ed288 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ResponseInit.h @@ -0,0 +1,32 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ResponseInit_h +#define ResponseInit_h + +#include "bindings/v8/Dictionary.h" +#include "modules/serviceworkers/HeaderMap.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +struct ResponseInit { + explicit ResponseInit(const Dictionary& options) + : status(200) + , statusText("OK") + { + options.get("status", status); + // FIXME: Spec uses ByteString for statusText. http://crbug.com/347426 + options.get("statusText", statusText); + options.get("headers", headers); + } + + unsigned short status; + String statusText; + RefPtr<HeaderMap> headers; +}; + +} + +#endif // ResponseInit_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp index 0bbd5048335..1e3163b9e17 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp @@ -31,12 +31,210 @@ #include "config.h" #include "ServiceWorker.h" +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "bindings/v8/ScriptState.h" +#include "core/dom/MessagePort.h" +#include "modules/EventTargetModules.h" +#include "platform/NotImplemented.h" +#include "public/platform/WebMessagePortChannel.h" +#include "public/platform/WebServiceWorkerState.h" +#include "public/platform/WebString.h" +#include <v8.h> namespace WebCore { -ServiceWorker::ServiceWorker(PassOwnPtr<blink::WebServiceWorker> worker) - : m_outerWorker(worker) +class ServiceWorker::ThenFunction FINAL : public ScriptFunction { +public: + static PassOwnPtr<ScriptFunction> create(PassRefPtr<ServiceWorker> observer) + { + ExecutionContext* executionContext = observer->executionContext(); + return adoptPtr(new ThenFunction(toIsolate(executionContext), observer)); + } +private: + ThenFunction(v8::Isolate* isolate, PassRefPtr<ServiceWorker> observer) + : ScriptFunction(isolate) + , m_observer(observer) + { + } + + virtual ScriptValue call(ScriptValue value) OVERRIDE + { + m_observer->onPromiseResolved(); + return value; + } + + RefPtr<ServiceWorker> m_observer; +}; + +const AtomicString& ServiceWorker::interfaceName() const +{ + return EventTargetNames::ServiceWorker; +} + +void ServiceWorker::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionState& exceptionState) +{ + // Disentangle the port in preparation for sending it to the remote context. + OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, exceptionState); + if (exceptionState.hadException()) + return; + + blink::WebString messageString = message->toWireString(); + OwnPtr<blink::WebMessagePortChannelArray> webChannels = MessagePort::toWebMessagePortChannelArray(channels.release()); + m_outerWorker->postMessage(messageString, webChannels.leakPtr()); +} + +bool ServiceWorker::isReady() +{ + return m_proxyState == Ready; +} + +void ServiceWorker::dispatchStateChangeEvent() +{ + ASSERT(isReady()); + this->dispatchEvent(Event::create(EventTypeNames::statechange)); +} + +String ServiceWorker::scope() const +{ + return m_outerWorker->scope().string(); +} + +String ServiceWorker::url() const +{ + return m_outerWorker->url().string(); +} + +const AtomicString& ServiceWorker::state() const +{ + DEFINE_STATIC_LOCAL(AtomicString, unknown, ("unknown", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(AtomicString, parsed, ("parsed", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(AtomicString, installing, ("installing", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(AtomicString, installed, ("installed", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(AtomicString, activating, ("activating", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(AtomicString, active, ("active", AtomicString::ConstructFromLiteral)); + DEFINE_STATIC_LOCAL(AtomicString, deactivated, ("deactivated", AtomicString::ConstructFromLiteral)); + + switch (m_outerWorker->state()) { + case blink::WebServiceWorkerStateUnknown: + // The web platform should never see this internal state + ASSERT_NOT_REACHED(); + return unknown; + case blink::WebServiceWorkerStateParsed: + return parsed; + case blink::WebServiceWorkerStateInstalling: + return installing; + case blink::WebServiceWorkerStateInstalled: + return installed; + case blink::WebServiceWorkerStateActivating: + return activating; + case blink::WebServiceWorkerStateActive: + return active; + case blink::WebServiceWorkerStateDeactivated: + return deactivated; + default: + ASSERT_NOT_REACHED(); + return nullAtom; + } +} + +PassRefPtr<ServiceWorker> ServiceWorker::from(ExecutionContext* executionContext, WebType* worker) +{ + if (!worker) + return PassRefPtr<ServiceWorker>(); + + blink::WebServiceWorkerProxy* proxy = worker->proxy(); + ServiceWorker* existingServiceWorker = proxy ? proxy->unwrap() : 0; + if (existingServiceWorker) { + ASSERT(existingServiceWorker->executionContext() == executionContext); + return existingServiceWorker; + } + + return create(executionContext, adoptPtr(worker)); +} + +PassRefPtr<ServiceWorker> ServiceWorker::from(ScriptPromiseResolverWithContext* resolver, WebType* worker) +{ + RefPtr<ServiceWorker> serviceWorker = ServiceWorker::from(resolver->scriptState()->executionContext(), worker); + ScriptState::Scope scope(resolver->scriptState()); + serviceWorker->waitOnPromise(resolver->promise()); + return serviceWorker; +} + +void ServiceWorker::setProxyState(ProxyState state) +{ + if (m_proxyState == state) + return; + switch (m_proxyState) { + case Initial: + ASSERT(state == RegisterPromisePending || state == ContextStopped); + break; + case RegisterPromisePending: + ASSERT(state == Ready || state == ContextStopped); + break; + case Ready: + ASSERT(state == ContextStopped); + break; + case ContextStopped: + ASSERT_NOT_REACHED(); + break; + } + + ProxyState oldState = m_proxyState; + m_proxyState = state; + if (oldState == Ready || state == Ready) + m_outerWorker->proxyReadyChanged(); +} + +void ServiceWorker::onPromiseResolved() +{ + if (m_proxyState == ContextStopped) + return; + setProxyState(Ready); +} + +void ServiceWorker::waitOnPromise(ScriptPromise promise) +{ + if (promise.isEmpty()) { + // The document was detached during registration. The state doesn't really + // matter since this ServiceWorker will immediately die. + setProxyState(ContextStopped); + return; + } + setProxyState(RegisterPromisePending); + promise.then(ThenFunction::create(this)); +} + +bool ServiceWorker::hasPendingActivity() const +{ + if (AbstractWorker::hasPendingActivity()) + return true; + if (m_proxyState == ContextStopped) + return false; + return m_outerWorker->state() != blink::WebServiceWorkerStateDeactivated; +} + +void ServiceWorker::stop() +{ + setProxyState(ContextStopped); +} + +PassRefPtr<ServiceWorker> ServiceWorker::create(ExecutionContext* executionContext, PassOwnPtr<blink::WebServiceWorker> outerWorker) +{ + RefPtr<ServiceWorker> worker = adoptRef(new ServiceWorker(executionContext, outerWorker)); + worker->suspendIfNeeded(); + return worker.release(); +} + +ServiceWorker::ServiceWorker(ExecutionContext* executionContext, PassOwnPtr<blink::WebServiceWorker> worker) + : AbstractWorker(executionContext) + , WebServiceWorkerProxy(this) + , m_outerWorker(worker) + , m_proxyState(Initial) { + ScriptWrappable::init(this); + ASSERT(m_outerWorker); + m_outerWorker->setProxy(this); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.h index ff1e8491584..ecd0a1befea 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.h +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.h @@ -31,38 +31,71 @@ #ifndef ServiceWorker_h #define ServiceWorker_h +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptWrappable.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "core/workers/AbstractWorker.h" #include "public/platform/WebServiceWorker.h" +#include "public/platform/WebServiceWorkerProxy.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" -namespace blink { -class WebServiceWorker; -} - namespace WebCore { -class ServiceWorker : public RefCounted<ServiceWorker> { +class ScriptState; +class ScriptPromiseResolverWithContext; + +class ServiceWorker + : public AbstractWorker + , public ScriptWrappable + , public blink::WebServiceWorkerProxy { public: - static PassRefPtr<ServiceWorker> create(PassOwnPtr<blink::WebServiceWorker> worker) - { - return adoptRef(new ServiceWorker(worker)); - } + virtual ~ServiceWorker() { } // For CallbackPromiseAdapter typedef blink::WebServiceWorker WebType; - static PassRefPtr<ServiceWorker> from(WebType* worker) - { - return create(adoptPtr(worker)); - } + static PassRefPtr<ServiceWorker> from(ScriptPromiseResolverWithContext*, WebType* worker); + + static PassRefPtr<ServiceWorker> from(ExecutionContext*, WebType*); + + void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionState&); + + String scope() const; + String url() const; + const AtomicString& state() const; + DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange); - ~ServiceWorker() { } + // WebServiceWorkerProxy overrides. + virtual bool isReady() OVERRIDE; + virtual void dispatchStateChangeEvent() OVERRIDE; + + // AbstractWorker overrides. + virtual const AtomicString& interfaceName() const OVERRIDE; private: - explicit ServiceWorker(PassOwnPtr<blink::WebServiceWorker>); + class ThenFunction; + + enum ProxyState { + Initial, + RegisterPromisePending, + Ready, + ContextStopped + }; + + static PassRefPtr<ServiceWorker> create(ExecutionContext*, PassOwnPtr<blink::WebServiceWorker>); + ServiceWorker(ExecutionContext*, PassOwnPtr<blink::WebServiceWorker>); + void setProxyState(ProxyState); + void onPromiseResolved(); + void waitOnPromise(ScriptPromise); + + // ActiveDOMObject overrides. + virtual bool hasPendingActivity() const OVERRIDE; + virtual void stop() OVERRIDE; OwnPtr<blink::WebServiceWorker> m_outerWorker; + ProxyState m_proxyState; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.idl index b58eb9005dc..b9a2bddfd23 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.idl +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.idl @@ -27,8 +27,21 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-interface [ - RuntimeEnabled=ServiceWorker, - NoInterfaceObject -] interface ServiceWorker { + ActiveDOMObject, + RuntimeEnabled=ServiceWorker +] interface ServiceWorker : EventTarget { + + // FIXME: Should inherit this from Worker. + [Custom, RaisesException] void postMessage(SerializedScriptValue message, optional MessagePort[] messagePorts); + + readonly attribute ScalarValueString scope; + readonly attribute ScalarValueString url; + // FIXME: Should be ServiceWorkerState enum, not DOMString. + readonly attribute DOMString state; + attribute EventHandler onstatechange; }; + +ServiceWorker implements AbstractWorker; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp new file mode 100644 index 00000000000..9af10f5fb42 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp @@ -0,0 +1,63 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/serviceworkers/ServiceWorkerClients.h" + +#include "bindings/v8/CallbackPromiseAdapter.h" +#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "modules/serviceworkers/Client.h" +#include "modules/serviceworkers/ServiceWorkerError.h" +#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h" +#include "public/platform/WebServiceWorkerClientsInfo.h" +#include "wtf/RefPtr.h" +#include "wtf/Vector.h" + +namespace WebCore { + +namespace { + + class ClientArray { + public: + typedef blink::WebServiceWorkerClientsInfo WebType; + static Vector<RefPtr<Client> > from(ScriptPromiseResolverWithContext*, WebType* webClientsRaw) + { + OwnPtr<WebType> webClients = adoptPtr(webClientsRaw); + Vector<RefPtr<Client> > clients; + for (size_t i = 0; i < webClients->clientIDs.size(); ++i) { + clients.append(Client::create(webClients->clientIDs[i])); + } + return clients; + } + + private: + WTF_MAKE_NONCOPYABLE(ClientArray); + ClientArray() WTF_DELETED_FUNCTION; + }; + +} // namespace + +PassRefPtr<ServiceWorkerClients> ServiceWorkerClients::create() +{ + return adoptRef(new ServiceWorkerClients()); +} + +ServiceWorkerClients::ServiceWorkerClients() +{ + ScriptWrappable::init(this); +} + +ServiceWorkerClients::~ServiceWorkerClients() +{ +} + +ScriptPromise ServiceWorkerClients::getServiced(ScriptState* scriptState) +{ + RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState); + ServiceWorkerGlobalScopeClient::from(scriptState->executionContext())->getClients(new CallbackPromiseAdapter<ClientArray, ServiceWorkerError>(resolver)); + return resolver->promise(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.h new file mode 100644 index 00000000000..1ba6f02047a --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.h @@ -0,0 +1,33 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ServiceWorkerClients_h +#define ServiceWorkerClients_h + +#include "bindings/v8/ScriptWrappable.h" +#include "public/platform/WebServiceWorkerClientsInfo.h" +#include "wtf/Forward.h" + +namespace WebCore { + +class Client; +class ExecutionContext; +class ScriptState; +class ScriptPromise; + +class ServiceWorkerClients FINAL : public RefCounted<ServiceWorkerClients>, public ScriptWrappable { +public: + static PassRefPtr<ServiceWorkerClients> create(); + ~ServiceWorkerClients(); + + // ServiceWorkerClients.idl + ScriptPromise getServiced(ScriptState*); + +private: + ServiceWorkerClients(); +}; + +} // namespace WebCore + +#endif // ServiceWorkerClients_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.idl new file mode 100644 index 00000000000..1fc9ad0a65d --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.idl @@ -0,0 +1,11 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-clients-interface +[ + Exposed=ServiceWorker, + RuntimeEnabled=ServiceWorker +] interface ServiceWorkerClients { + [CallWith=ScriptState] Promise getServiced(); +}; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp new file mode 100644 index 00000000000..95328969cba --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "config.h" +#include "modules/serviceworkers/ServiceWorkerContainer.h" + +#include "bindings/v8/CallbackPromiseAdapter.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "core/dom/DOMException.h" +#include "core/dom/Document.h" +#include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" +#include "core/dom/MessagePort.h" +#include "core/events/MessageEvent.h" +#include "modules/serviceworkers/RegistrationOptionList.h" +#include "modules/serviceworkers/ServiceWorker.h" +#include "modules/serviceworkers/ServiceWorkerContainerClient.h" +#include "modules/serviceworkers/ServiceWorkerError.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "public/platform/WebServiceWorker.h" +#include "public/platform/WebServiceWorkerProvider.h" +#include "public/platform/WebString.h" +#include "public/platform/WebURL.h" +#include <v8.h> + +using blink::WebServiceWorker; +using blink::WebServiceWorkerProvider; + +namespace WebCore { + +PassRefPtr<ServiceWorkerContainer> ServiceWorkerContainer::create(ExecutionContext* executionContext) +{ + return adoptRef(new ServiceWorkerContainer(executionContext)); +} + +ServiceWorkerContainer::~ServiceWorkerContainer() +{ + ASSERT(!m_provider); +} + +void ServiceWorkerContainer::detachClient() +{ + if (m_provider) { + m_provider->setClient(0); + m_provider = 0; + } +} + +ScriptPromise ServiceWorkerContainer::registerServiceWorker(ScriptState* scriptState, const String& url, const Dictionary& dictionary) +{ + RegistrationOptionList options(dictionary); + ASSERT(RuntimeEnabledFeatures::serviceWorkerEnabled()); + RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState); + ScriptPromise promise = resolver->promise(); + + if (!m_provider) { + resolver->reject(DOMException::create(InvalidStateError, "No associated provider is available")); + return promise; + } + + ExecutionContext* executionContext = scriptState->executionContext(); + RefPtr<SecurityOrigin> documentOrigin = executionContext->securityOrigin(); + KURL patternURL = executionContext->completeURL(options.scope); + patternURL.removeFragmentIdentifier(); + if (!documentOrigin->canRequest(patternURL)) { + resolver->reject(DOMException::create(SecurityError, "Can only register for patterns in the document's origin.")); + return promise; + } + + KURL scriptURL = executionContext->completeURL(url); + scriptURL.removeFragmentIdentifier(); + if (!documentOrigin->canRequest(scriptURL)) { + resolver->reject(DOMException::create(SecurityError, "Script must be in document's origin.")); + return promise; + } + + m_provider->registerServiceWorker(patternURL, scriptURL, new CallbackPromiseAdapter<ServiceWorker, ServiceWorkerError>(resolver)); + return promise; +} + +class UndefinedValue { +public: + typedef WebServiceWorker WebType; + static V8UndefinedType from(ScriptPromiseResolverWithContext* resolver, WebServiceWorker* worker) + { + ASSERT(!worker); // Anything passed here will be leaked. + return V8UndefinedType(); + } + +private: + UndefinedValue(); +}; + +ScriptPromise ServiceWorkerContainer::unregisterServiceWorker(ScriptState* scriptState, const String& pattern) +{ + ASSERT(RuntimeEnabledFeatures::serviceWorkerEnabled()); + RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState); + ScriptPromise promise = resolver->promise(); + + if (!m_provider) { + resolver->reject(DOMException::create(InvalidStateError, "No associated provider is available")); + return promise; + } + + RefPtr<SecurityOrigin> documentOrigin = scriptState->executionContext()->securityOrigin(); + KURL patternURL = scriptState->executionContext()->completeURL(pattern); + patternURL.removeFragmentIdentifier(); + if (!pattern.isEmpty() && !documentOrigin->canRequest(patternURL)) { + resolver->reject(DOMException::create(SecurityError, "Can only unregister for patterns in the document's origin.")); + return promise; + } + + m_provider->unregisterServiceWorker(patternURL, new CallbackPromiseAdapter<UndefinedValue, ServiceWorkerError>(resolver)); + return promise; +} + +ScriptPromise ServiceWorkerContainer::ready(ScriptState* scriptState) +{ + if (m_controller.get()) { + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + resolver->resolve(m_controller.get()); + return promise; + } + // FIXME: Elaborate the implementation when the "waiting" property + // or replace() is implemented. + return ScriptPromise(); +} + +// If the WebServiceWorker is up for adoption (does not have a +// WebServiceWorkerProxy owner), rejects the adoption by deleting the +// WebServiceWorker. +static void deleteIfNoExistingOwner(blink::WebServiceWorker* serviceWorker) +{ + if (serviceWorker && !serviceWorker->proxy()) + delete serviceWorker; +} + +void ServiceWorkerContainer::setActive(blink::WebServiceWorker* serviceWorker) +{ + if (!executionContext()) { + deleteIfNoExistingOwner(serviceWorker); + return; + } + m_active = ServiceWorker::from(executionContext(), serviceWorker); +} + +void ServiceWorkerContainer::setController(blink::WebServiceWorker* serviceWorker) +{ + if (!executionContext()) { + deleteIfNoExistingOwner(serviceWorker); + return; + } + m_controller = ServiceWorker::from(executionContext(), serviceWorker); +} + +void ServiceWorkerContainer::setInstalling(blink::WebServiceWorker* serviceWorker) +{ + if (!executionContext()) { + deleteIfNoExistingOwner(serviceWorker); + return; + } + m_installing = ServiceWorker::from(executionContext(), serviceWorker); +} + +void ServiceWorkerContainer::setWaiting(blink::WebServiceWorker* serviceWorker) +{ + if (!executionContext()) { + deleteIfNoExistingOwner(serviceWorker); + return; + } + m_waiting = ServiceWorker::from(executionContext(), serviceWorker); +} + +void ServiceWorkerContainer::dispatchMessageEvent(const blink::WebString& message, const blink::WebMessagePortChannelArray& webChannels) +{ + if (!executionContext() || !executionContext()->executingWindow()) + return; + + OwnPtr<MessagePortArray> ports = MessagePort::toMessagePortArray(executionContext(), webChannels); + RefPtr<SerializedScriptValue> value = SerializedScriptValue::createFromWire(message); + executionContext()->executingWindow()->dispatchEvent(MessageEvent::create(ports.release(), value)); +} + +ServiceWorkerContainer::ServiceWorkerContainer(ExecutionContext* executionContext) + : ContextLifecycleObserver(executionContext) + , m_provider(0) +{ + ScriptWrappable::init(this); + + if (!executionContext) + return; + + if (ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(executionContext)) { + m_provider = client->provider(); + if (m_provider) + m_provider->setClient(this); + } +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.h new file mode 100644 index 00000000000..b3aa33e0161 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ServiceWorkerContainer_h +#define ServiceWorkerContainer_h + +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptWrappable.h" +#include "core/dom/ContextLifecycleObserver.h" +#include "modules/serviceworkers/ServiceWorker.h" +#include "public/platform/WebServiceWorkerProviderClient.h" +#include "wtf/Forward.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" + +namespace blink { +class WebServiceWorkerProvider; +class WebServiceWorker; +} + +namespace WebCore { + +class Dictionary; +class ExecutionContext; +class ServiceWorker; + +class ServiceWorkerContainer FINAL : + public RefCounted<ServiceWorkerContainer>, + public ScriptWrappable, + public ContextLifecycleObserver, + public blink::WebServiceWorkerProviderClient { +public: + static PassRefPtr<ServiceWorkerContainer> create(ExecutionContext*); + ~ServiceWorkerContainer(); + + void detachClient(); + + PassRefPtrWillBeRawPtr<ServiceWorker> active() { return m_active.get(); } + PassRefPtrWillBeRawPtr<ServiceWorker> controller() { return m_controller.get(); } + PassRefPtrWillBeRawPtr<ServiceWorker> installing() { return m_installing.get(); } + PassRefPtrWillBeRawPtr<ServiceWorker> waiting() { return m_waiting.get(); } + ScriptPromise ready(ScriptState*); + + ScriptPromise registerServiceWorker(ScriptState*, const String& pattern, const Dictionary&); + ScriptPromise unregisterServiceWorker(ScriptState*, const String& scope = String()); + + // WebServiceWorkerProviderClient overrides. + virtual void setActive(blink::WebServiceWorker*) OVERRIDE; + virtual void setController(blink::WebServiceWorker*) OVERRIDE; + virtual void setInstalling(blink::WebServiceWorker*) OVERRIDE; + virtual void setWaiting(blink::WebServiceWorker*) OVERRIDE; + virtual void dispatchMessageEvent(const blink::WebString& message, const blink::WebMessagePortChannelArray&) OVERRIDE; + +private: + explicit ServiceWorkerContainer(ExecutionContext*); + + blink::WebServiceWorkerProvider* m_provider; + RefPtr<ServiceWorker> m_active; + RefPtr<ServiceWorker> m_controller; + RefPtr<ServiceWorker> m_installing; + RefPtr<ServiceWorker> m_waiting; +}; + +} // namespace WebCore + +#endif // ServiceWorkerContainer_h diff --git a/chromium/third_party/WebKit/Source/modules/notifications/WebKitNotification.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.idl index 52899ff5879..9f8a3f6bd2c 100644 --- a/chromium/third_party/WebKit/Source/modules/notifications/WebKitNotification.idl +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.idl @@ -28,20 +28,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-container-interface [ - ActiveDOMObject, - Conditional=LEGACY_NOTIFICATIONS, - NoInterfaceObject, - RuntimeEnabled=Notifications, -] interface WebKitNotification : EventTarget { - void show(); - void cancel(); + RuntimeEnabled=ServiceWorker +] interface ServiceWorkerContainer { + [Unforgeable] readonly attribute ServiceWorker active; + [Unforgeable] readonly attribute ServiceWorker controller; + [Unforgeable] readonly attribute ServiceWorker installing; + [Unforgeable] readonly attribute ServiceWorker waiting; - attribute EventHandler ondisplay; - attribute EventHandler onerror; - attribute EventHandler onclose; - attribute EventHandler onclick; + [CallWith=ScriptState] readonly attribute Promise ready; - attribute DOMString dir; - attribute DOMString replaceId; + [CallWith=ScriptState, ImplementedAs=registerServiceWorker] Promise register(ScalarValueString url, optional Dictionary options); + [CallWith=ScriptState, ImplementedAs=unregisterServiceWorker] Promise unregister(ScalarValueString scope); }; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.cpp new file mode 100644 index 00000000000..e7ec9051817 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.cpp @@ -0,0 +1,61 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "ServiceWorkerContainerClient.h" + +#include "core/dom/Document.h" +#include "core/dom/ExecutionContext.h" +#include "core/frame/LocalFrame.h" +#include "core/loader/FrameLoaderClient.h" +#include "core/workers/WorkerGlobalScope.h" +#include "public/platform/WebServiceWorkerProvider.h" + +namespace WebCore { + +PassOwnPtrWillBeRawPtr<ServiceWorkerContainerClient> ServiceWorkerContainerClient::create(PassOwnPtr<blink::WebServiceWorkerProvider> provider) +{ + return adoptPtrWillBeNoop(new ServiceWorkerContainerClient(provider)); +} + +ServiceWorkerContainerClient::~ServiceWorkerContainerClient() +{ +} + +const char* ServiceWorkerContainerClient::supplementName() +{ + return "ServiceWorkerContainerClient"; +} + +ServiceWorkerContainerClient* ServiceWorkerContainerClient::from(ExecutionContext* context) +{ + if (context->isDocument()) { + Document* document = toDocument(context); + if (!document->frame()) + return 0; + + ServiceWorkerContainerClient* client = static_cast<ServiceWorkerContainerClient*>(DocumentSupplement::from(document, supplementName())); + if (client) + return client; + + // If it's not provided yet, create it lazily. + document->DocumentSupplementable::provideSupplement(ServiceWorkerContainerClient::supplementName(), ServiceWorkerContainerClient::create(document->frame()->loader().client()->createServiceWorkerProvider())); + return static_cast<ServiceWorkerContainerClient*>(DocumentSupplement::from(document, supplementName())); + } + + ASSERT(context->isWorkerGlobalScope()); + return static_cast<ServiceWorkerContainerClient*>(WillBeHeapSupplement<WorkerClients>::from(toWorkerGlobalScope(context)->clients(), supplementName())); +} + +ServiceWorkerContainerClient::ServiceWorkerContainerClient(PassOwnPtr<blink::WebServiceWorkerProvider> provider) + : m_provider(provider) +{ +} + +void provideServiceWorkerContainerClientToWorker(WorkerClients* clients, PassOwnPtr<blink::WebServiceWorkerProvider> provider) +{ + clients->provideSupplement(ServiceWorkerContainerClient::supplementName(), ServiceWorkerContainerClient::create(provider)); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.h new file mode 100644 index 00000000000..457e9dcbdda --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.h @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ServiceWorkerContainerClient_h +#define ServiceWorkerContainerClient_h + +#include "core/dom/DocumentSupplementable.h" +#include "core/workers/WorkerClients.h" +#include "wtf/Forward.h" + +namespace blink { +class WebServiceWorkerProvider; +} + +namespace WebCore { + +class ExecutionContext; + +// This mainly exists to provide access to WebServiceWorkerProvider. +// Owned by Document (or WorkerClients). +class ServiceWorkerContainerClient FINAL : + public NoBaseWillBeGarbageCollectedFinalized<ServiceWorkerContainerClient>, + public DocumentSupplement, + public WillBeHeapSupplement<WorkerClients> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerContainerClient); + WTF_MAKE_NONCOPYABLE(ServiceWorkerContainerClient); +public: + static PassOwnPtrWillBeRawPtr<ServiceWorkerContainerClient> create(PassOwnPtr<blink::WebServiceWorkerProvider>); + virtual ~ServiceWorkerContainerClient(); + + blink::WebServiceWorkerProvider* provider() { return m_provider.get(); } + + static const char* supplementName(); + static ServiceWorkerContainerClient* from(ExecutionContext*); + + virtual void trace(Visitor* visitor) OVERRIDE + { + DocumentSupplement::trace(visitor); + WillBeHeapSupplement<WorkerClients>::trace(visitor); + } + +protected: + explicit ServiceWorkerContainerClient(PassOwnPtr<blink::WebServiceWorkerProvider>); + + OwnPtr<blink::WebServiceWorkerProvider> m_provider; +}; + +void provideServiceWorkerContainerClientToWorker(WorkerClients*, PassOwnPtr<blink::WebServiceWorkerProvider>); + +} // namespace WebCore + +#endif // ServiceWorkerContainerClient_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp index 9c37cfae4f3..93c734d6989 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp @@ -31,18 +31,36 @@ #include "config.h" #include "ServiceWorkerError.h" +#include "core/dom/ExceptionCode.h" + using blink::WebServiceWorkerError; namespace WebCore { -String ServiceWorkerError::errorString(WebServiceWorkerError::ErrorType type) +// static +PassRefPtrWillBeRawPtr<DOMException> ServiceWorkerError::from(ScriptPromiseResolverWithContext*, WebType* webErrorRaw) { - switch (type) { - case WebServiceWorkerError::DisabledError: - return "DisabledError"; - default: - ASSERT_NOT_REACHED(); + OwnPtr<WebType> webError = adoptPtr(webErrorRaw); + switch (webError->errorType) { + case WebServiceWorkerError::ErrorTypeDisabled: + return DOMException::create(NotSupportedError, "Service Worker support is disabled."); + case WebServiceWorkerError::ErrorTypeAbort: + return DOMException::create(AbortError, "The Service Worker operation was aborted."); + case WebServiceWorkerError::ErrorTypeSecurity: + return DOMException::create(SecurityError, "The Service Worker security policy prevented an action."); + case WebServiceWorkerError::ErrorTypeInstall: + // FIXME: Introduce new InstallError type to ExceptionCodes? + return DOMException::create(AbortError, "The Service Worker installation failed."); + case WebServiceWorkerError::ErrorTypeActivate: + // Not currently returned as a promise rejection. + // FIXME: Introduce new ActivateError type to ExceptionCodes? + return DOMException::create(AbortError, "The Service Worker activation failed."); + case WebServiceWorkerError::ErrorTypeNotFound: + return DOMException::create(NotFoundError, "The specified Service Worker resource was not found."); + case WebServiceWorkerError::ErrorTypeUnknown: + return DOMException::create(UnknownError, "An unknown error occurred within Service Worker."); } - return String(); + ASSERT_NOT_REACHED(); + return DOMException::create(UnknownError); } -} +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.h index 276eb134881..b30491dbfcc 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.h +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.h @@ -31,25 +31,22 @@ #ifndef ServiceWorkerError_h #define ServiceWorkerError_h -#include "core/dom/DOMError.h" +#include "core/dom/DOMException.h" +#include "platform/heap/Handle.h" #include "public/platform/WebServiceWorkerError.h" #include "wtf/PassOwnPtr.h" namespace WebCore { +class ScriptPromiseResolverWithContext; + class ServiceWorkerError { public: // For CallbackPromiseAdapter typedef blink::WebServiceWorkerError WebType; - static PassRefPtr<DOMError> from(WebType* webErrorRaw) - { - OwnPtr<WebType> webError = adoptPtr(webErrorRaw); - RefPtr<DOMError> error = DOMError::create(errorString(webError->errorType), webError->message); - return error.release(); - } + static PassRefPtrWillBeRawPtr<DOMException> from(ScriptPromiseResolverWithContext*, WebType* webErrorRaw); private: - static String errorString(blink::WebServiceWorkerError::ErrorType); WTF_MAKE_NONCOPYABLE(ServiceWorkerError); ServiceWorkerError() WTF_DELETED_FUNCTION; }; diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp index 0f2041a2080..b5ea3f7c47f 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp @@ -30,25 +30,43 @@ #include "config.h" #include "ServiceWorkerGlobalScope.h" -#include "bindings/v8/ScriptObject.h" +#include "CachePolyfill.h" +#include "CacheStoragePolyfill.h" +#include "FetchPolyfill.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8ThrowException.h" #include "core/workers/WorkerClients.h" #include "core/workers/WorkerThreadStartupData.h" +#include "modules/EventTargetModules.h" +#include "modules/serviceworkers/FetchManager.h" +#include "modules/serviceworkers/Request.h" +#include "modules/serviceworkers/ServiceWorkerClients.h" +#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h" #include "modules/serviceworkers/ServiceWorkerThread.h" +#include "platform/network/ResourceRequest.h" #include "platform/weborigin/KURL.h" +#include "public/platform/WebURL.h" #include "wtf/CurrentTime.h" namespace WebCore { -PassRefPtr<ServiceWorkerGlobalScope> ServiceWorkerGlobalScope::create(ServiceWorkerThread* thread, PassOwnPtr<WorkerThreadStartupData> startupData) +PassRefPtrWillBeRawPtr<ServiceWorkerGlobalScope> ServiceWorkerGlobalScope::create(ServiceWorkerThread* thread, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData) { - RefPtr<ServiceWorkerGlobalScope> context = adoptRef(new ServiceWorkerGlobalScope(startupData->m_scriptURL, startupData->m_userAgent, thread, monotonicallyIncreasingTime(), startupData->m_workerClients.release())); + RefPtrWillBeRawPtr<ServiceWorkerGlobalScope> context = adoptRefWillBeRefCountedGarbageCollected(new ServiceWorkerGlobalScope(startupData->m_scriptURL, startupData->m_userAgent, thread, monotonicallyIncreasingTime(), startupData->m_workerClients.release())); context->applyContentSecurityPolicyFromString(startupData->m_contentSecurityPolicy, startupData->m_contentSecurityPolicyType); + + context->script()->evaluate(String(fetchPolyfillJs, sizeof(fetchPolyfillJs))); + context->script()->evaluate(String(cachePolyfillJs, sizeof(cachePolyfillJs))); + context->script()->evaluate(String(cacheStoragePolyfillJs, sizeof(cacheStoragePolyfillJs))); + return context.release(); } -ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(const KURL& url, const String& userAgent, ServiceWorkerThread* thread, double timeOrigin, PassOwnPtr<WorkerClients> workerClients) : - WorkerGlobalScope(url, userAgent, thread, timeOrigin, workerClients) +ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(const KURL& url, const String& userAgent, ServiceWorkerThread* thread, double timeOrigin, PassOwnPtrWillBeRawPtr<WorkerClients> workerClients) + : WorkerGlobalScope(url, userAgent, thread, timeOrigin, workerClients) + , m_fetchManager(adoptPtr(new FetchManager(this))) { ScriptWrappable::init(this); } @@ -57,9 +75,47 @@ ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope() { } +void ServiceWorkerGlobalScope::stopFetch() +{ + m_fetchManager.clear(); +} + +String ServiceWorkerGlobalScope::scope(ExecutionContext* context) +{ + return ServiceWorkerGlobalScopeClient::from(context)->scope().string(); +} + +ScriptPromise ServiceWorkerGlobalScope::fetch(ScriptState* scriptState, Request* request) +{ + OwnPtr<ResourceRequest> resourceRequest(request->createResourceRequest()); + return m_fetchManager->fetch(scriptState, resourceRequest.release()); +} + +ScriptPromise ServiceWorkerGlobalScope::fetch(ScriptState* scriptState, const String& urlstring) +{ + KURL url = completeURL(urlstring); + if (!url.isValid()) + return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError("Invalid URL", scriptState->isolate())); + OwnPtr<ResourceRequest> resourceRequest = adoptPtr(new ResourceRequest(url)); + resourceRequest->setHTTPMethod("GET"); + return m_fetchManager->fetch(scriptState, resourceRequest.release()); +} + +PassRefPtr<ServiceWorkerClients> ServiceWorkerGlobalScope::clients() +{ + if (!m_clients) + m_clients = ServiceWorkerClients::create(); + return m_clients; +} + const AtomicString& ServiceWorkerGlobalScope::interfaceName() const { return EventTargetNames::ServiceWorkerGlobalScope; } +void ServiceWorkerGlobalScope::trace(Visitor* visitor) +{ + WorkerGlobalScope::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h index 9876ae3f27d..fca77813cc9 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h @@ -30,22 +30,33 @@ #ifndef ServiceWorkerGlobalScope_h #define ServiceWorkerGlobalScope_h -#include "bindings/v8/ScriptPromiseResolver.h" -#include "core/dom/Promise.h" #include "core/workers/WorkerGlobalScope.h" +#include "platform/heap/Handle.h" #include "wtf/Assertions.h" namespace WebCore { +class FetchManager; +class Request; +class ScriptPromise; +class ScriptState; class ServiceWorkerThread; -struct WorkerThreadStartupData; +class ServiceWorkerClients; +class WorkerThreadStartupData; -class ServiceWorkerGlobalScope : public WorkerGlobalScope { +class ServiceWorkerGlobalScope FINAL : public WorkerGlobalScope { public: - static PassRefPtr<ServiceWorkerGlobalScope> create(ServiceWorkerThread*, PassOwnPtr<WorkerThreadStartupData>); + static PassRefPtrWillBeRawPtr<ServiceWorkerGlobalScope> create(ServiceWorkerThread*, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData>); virtual ~ServiceWorkerGlobalScope(); virtual bool isServiceWorkerGlobalScope() const OVERRIDE { return true; } + virtual void stopFetch() OVERRIDE; + + // ServiceWorkerGlobalScope.idl + PassRefPtr<ServiceWorkerClients> clients(); + String scope(ExecutionContext*); + ScriptPromise fetch(ScriptState*, Request*); + ScriptPromise fetch(ScriptState*, const String&); // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE; @@ -53,10 +64,18 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(install); DEFINE_ATTRIBUTE_EVENT_LISTENER(activate); DEFINE_ATTRIBUTE_EVENT_LISTENER(fetch); + DEFINE_ATTRIBUTE_EVENT_LISTENER(message); + DEFINE_ATTRIBUTE_EVENT_LISTENER(sync); + + virtual void trace(Visitor*) OVERRIDE; private: - ServiceWorkerGlobalScope(const KURL&, const String& userAgent, ServiceWorkerThread*, double timeOrigin, PassOwnPtr<WorkerClients>); + ServiceWorkerGlobalScope(const KURL&, const String& userAgent, ServiceWorkerThread*, double timeOrigin, PassOwnPtrWillBeRawPtr<WorkerClients>); + + RefPtr<ServiceWorkerClients> m_clients; + OwnPtr<FetchManager> m_fetchManager; }; -} + +} // namespace WebCore #endif // ServiceWorkerGlobalScope_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.idl b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.idl index 3db592745d7..07d2dbfde12 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.idl +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.idl @@ -27,12 +27,23 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-interface [ - GlobalContext=ServiceWorkerGlobalScope, + Exposed=ServiceWorker, + Global=Worker&ServiceWorker, RuntimeEnabled=ServiceWorker, ] interface ServiceWorkerGlobalScope : WorkerGlobalScope { - attribute EventHandler oninstall; + + readonly attribute ServiceWorkerClients clients; + [CallWith=ExecutionContext, Unforgeable] readonly attribute ScalarValueString scope; + + [CallWith=ScriptState] Promise fetch(ScalarValueString request); + [CallWith=ScriptState] Promise fetch(Request request); + attribute EventHandler onactivate; attribute EventHandler onfetch; + attribute EventHandler oninstall; + attribute EventHandler onmessage; + attribute EventHandler onsync; }; - diff --git a/chromium/third_party/WebKit/Source/modules/crypto/KeyPair.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp index 6beaf2b2e20..c38ef596e8e 100644 --- a/chromium/third_party/WebKit/Source/modules/crypto/KeyPair.cpp +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,27 +29,26 @@ */ #include "config.h" -#include "modules/crypto/KeyPair.h" +#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h" -#include "modules/crypto/Key.h" -#include "public/platform/WebCryptoKey.h" +#include "core/dom/ExecutionContext.h" +#include "core/workers/WorkerGlobalScope.h" namespace WebCore { -PassRefPtr<KeyPair> KeyPair::create(const blink::WebCryptoKey& publicKey, const blink::WebCryptoKey& privateKey) +const char* ServiceWorkerGlobalScopeClient::supplementName() { - ASSERT(publicKey.type() == blink::WebCryptoKeyTypePublic); - ASSERT(privateKey.type() == blink::WebCryptoKeyTypePrivate); - return adoptRef(new KeyPair(Key::create(publicKey), Key::create(privateKey))); + return "ServiceWorkerGlobalScopeClient"; } -KeyPair::KeyPair(const PassRefPtr<Key>& publicKey, const PassRefPtr<Key>& privateKey) - : m_publicKey(publicKey) - , m_privateKey(privateKey) +ServiceWorkerGlobalScopeClient* ServiceWorkerGlobalScopeClient::from(ExecutionContext* context) { - ASSERT(m_publicKey.get()); - ASSERT(m_privateKey.get()); - ScriptWrappable::init(this); + return static_cast<ServiceWorkerGlobalScopeClient*>(WillBeHeapSupplement<WorkerClients>::from(toWorkerGlobalScope(context)->clients(), supplementName())); +} + +void provideServiceWorkerGlobalScopeClientToWorker(WorkerClients* clients, PassOwnPtrWillBeRawPtr<ServiceWorkerGlobalScopeClient> client) +{ + clients->provideSupplement(ServiceWorkerGlobalScopeClient::supplementName(), client); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h new file mode 100644 index 00000000000..52437daac3c --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ServiceWorkerGlobalScopeClient_h +#define ServiceWorkerGlobalScopeClient_h + +#include "core/dom/MessagePort.h" +#include "core/workers/WorkerClients.h" +#include "public/platform/WebCallbacks.h" +#include "public/platform/WebMessagePortChannel.h" +#include "public/platform/WebServiceWorkerClientsInfo.h" +#include "public/platform/WebServiceWorkerEventResult.h" +#include "wtf/Forward.h" +#include "wtf/Noncopyable.h" + +namespace blink { +class WebURL; +}; + +namespace WebCore { + +class ExecutionContext; +class Response; +class WorkerClients; + +class ServiceWorkerGlobalScopeClient : public WillBeHeapSupplement<WorkerClients> { + WTF_MAKE_NONCOPYABLE(ServiceWorkerGlobalScopeClient); +public: + virtual ~ServiceWorkerGlobalScopeClient() { } + + virtual void getClients(blink::WebServiceWorkerClientsCallbacks*) = 0; + virtual blink::WebURL scope() const = 0; + + virtual void didHandleActivateEvent(int eventID, blink::WebServiceWorkerEventResult) = 0; + virtual void didHandleInstallEvent(int installEventID, blink::WebServiceWorkerEventResult) = 0; + // A null response means no valid response was provided by the service worker, so fallback to native. + virtual void didHandleFetchEvent(int fetchEventID, PassRefPtr<Response> = nullptr) = 0; + virtual void didHandleSyncEvent(int syncEventID) = 0; + virtual void postMessageToClient(int clientID, const blink::WebString& message, PassOwnPtr<blink::WebMessagePortChannelArray>) = 0; + + static const char* supplementName(); + static ServiceWorkerGlobalScopeClient* from(ExecutionContext*); + +protected: + ServiceWorkerGlobalScopeClient() { } +}; + +void provideServiceWorkerGlobalScopeClientToWorker(WorkerClients*, PassOwnPtrWillBeRawPtr<ServiceWorkerGlobalScopeClient>); + +} // namespace WebCore + +#endif // ServiceWorkerGlobalScopeClient_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.cpp index 72d86290707..9aaadaee32a 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.cpp +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.cpp @@ -37,12 +37,12 @@ namespace WebCore { -PassRefPtr<ServiceWorkerThread> ServiceWorkerThread::create(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> startupData) +PassRefPtr<ServiceWorkerThread> ServiceWorkerThread::create(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData) { return adoptRef(new ServiceWorkerThread(workerLoaderProxy, workerReportingProxy, startupData)); } -ServiceWorkerThread::ServiceWorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> startupData) +ServiceWorkerThread::ServiceWorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData) : WorkerThread(workerLoaderProxy, workerReportingProxy, startupData) { } @@ -51,7 +51,7 @@ ServiceWorkerThread::~ServiceWorkerThread() { } -PassRefPtr<WorkerGlobalScope> ServiceWorkerThread::createWorkerGlobalScope(PassOwnPtr<WorkerThreadStartupData> startupData) +PassRefPtrWillBeRawPtr<WorkerGlobalScope> ServiceWorkerThread::createWorkerGlobalScope(PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData) { return ServiceWorkerGlobalScope::create(this, startupData); } diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h index 01beb8d1ba4..8efabdcf160 100644 --- a/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h @@ -30,23 +30,23 @@ #ifndef ServiceWorkerThread_h #define ServiceWorkerThread_h -#include "core/frame/ContentSecurityPolicy.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/workers/WorkerThread.h" namespace WebCore { -struct WorkerThreadStartupData; +class WorkerThreadStartupData; -class ServiceWorkerThread : public WorkerThread { +class ServiceWorkerThread FINAL : public WorkerThread { public: - static PassRefPtr<ServiceWorkerThread> create(WorkerLoaderProxy&, WorkerReportingProxy&, PassOwnPtr<WorkerThreadStartupData>); + static PassRefPtr<ServiceWorkerThread> create(WorkerLoaderProxy&, WorkerReportingProxy&, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData>); virtual ~ServiceWorkerThread(); protected: - virtual PassRefPtr<WorkerGlobalScope> createWorkerGlobalScope(PassOwnPtr<WorkerThreadStartupData>) OVERRIDE; + virtual PassRefPtrWillBeRawPtr<WorkerGlobalScope> createWorkerGlobalScope(PassOwnPtrWillBeRawPtr<WorkerThreadStartupData>) OVERRIDE; private: - ServiceWorkerThread(WorkerLoaderProxy&, WorkerReportingProxy&, PassOwnPtr<WorkerThreadStartupData>); + ServiceWorkerThread(WorkerLoaderProxy&, WorkerReportingProxy&, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData>); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/WaitUntilObserver.cpp b/chromium/third_party/WebKit/Source/modules/serviceworkers/WaitUntilObserver.cpp new file mode 100644 index 00000000000..67770666e83 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/WaitUntilObserver.cpp @@ -0,0 +1,127 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/serviceworkers/WaitUntilObserver.h" + +#include "bindings/v8/ScriptFunction.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptValue.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/ExecutionContext.h" +#include "platform/NotImplemented.h" +#include "public/platform/WebServiceWorkerEventResult.h" +#include "wtf/Assertions.h" +#include "wtf/RefCounted.h" +#include "wtf/RefPtr.h" +#include <v8.h> + +namespace WebCore { + +class WaitUntilObserver::ThenFunction FINAL : public ScriptFunction { +public: + enum ResolveType { + Fulfilled, + Rejected, + }; + + static PassOwnPtr<ScriptFunction> create(PassRefPtr<WaitUntilObserver> observer, ResolveType type) + { + ExecutionContext* executionContext = observer->executionContext(); + return adoptPtr(new ThenFunction(toIsolate(executionContext), observer, type)); + } + +private: + ThenFunction(v8::Isolate* isolate, PassRefPtr<WaitUntilObserver> observer, ResolveType type) + : ScriptFunction(isolate) + , m_observer(observer) + , m_resolveType(type) + { + } + + virtual ScriptValue call(ScriptValue value) OVERRIDE + { + ASSERT(m_observer); + ASSERT(m_resolveType == Fulfilled || m_resolveType == Rejected); + if (m_resolveType == Rejected) + m_observer->reportError(value); + m_observer->decrementPendingActivity(); + m_observer = nullptr; + return value; + } + + RefPtr<WaitUntilObserver> m_observer; + ResolveType m_resolveType; +}; + +PassRefPtr<WaitUntilObserver> WaitUntilObserver::create(ExecutionContext* context, EventType type, int eventID) +{ + return adoptRef(new WaitUntilObserver(context, type, eventID)); +} + +WaitUntilObserver::~WaitUntilObserver() +{ + ASSERT(!m_pendingActivity); +} + +void WaitUntilObserver::willDispatchEvent() +{ + incrementPendingActivity(); +} + +void WaitUntilObserver::didDispatchEvent() +{ + decrementPendingActivity(); +} + +void WaitUntilObserver::waitUntil(ScriptState* scriptState, const ScriptValue& value) +{ + incrementPendingActivity(); + ScriptPromise::cast(scriptState, value).then( + ThenFunction::create(this, ThenFunction::Fulfilled), + ThenFunction::create(this, ThenFunction::Rejected)); +} + +WaitUntilObserver::WaitUntilObserver(ExecutionContext* context, EventType type, int eventID) + : ContextLifecycleObserver(context) + , m_type(type) + , m_eventID(eventID) + , m_pendingActivity(0) + , m_hasError(false) +{ +} + +void WaitUntilObserver::reportError(const ScriptValue& value) +{ + // FIXME: Propagate error message to the client for onerror handling. + notImplemented(); + + m_hasError = true; +} + +void WaitUntilObserver::incrementPendingActivity() +{ + ++m_pendingActivity; +} + +void WaitUntilObserver::decrementPendingActivity() +{ + ASSERT(m_pendingActivity > 0); + if (--m_pendingActivity || !executionContext()) + return; + + ServiceWorkerGlobalScopeClient* client = ServiceWorkerGlobalScopeClient::from(executionContext()); + blink::WebServiceWorkerEventResult result = m_hasError ? blink::WebServiceWorkerEventResultRejected : blink::WebServiceWorkerEventResultCompleted; + switch (m_type) { + case Activate: + client->didHandleActivateEvent(m_eventID, result); + break; + case Install: + client->didHandleInstallEvent(m_eventID, result); + break; + } + observeContext(0); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/WaitUntilObserver.h b/chromium/third_party/WebKit/Source/modules/serviceworkers/WaitUntilObserver.h new file mode 100644 index 00000000000..fb665f8e0fb --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/WaitUntilObserver.h @@ -0,0 +1,59 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WaitUntilObserver_h +#define WaitUntilObserver_h + +#include "core/dom/ContextLifecycleObserver.h" +#include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h" +#include "wtf/Forward.h" +#include "wtf/RefCounted.h" + +namespace WebCore { + +class ExecutionContext; +class ScriptState; +class ScriptValue; + +// Created for each InstallPhaseEvent instance. +class WaitUntilObserver FINAL : + public ContextLifecycleObserver, + public RefCounted<WaitUntilObserver> { +public: + enum EventType { + Activate, + Install + }; + + static PassRefPtr<WaitUntilObserver> create(ExecutionContext*, EventType, int eventID); + + ~WaitUntilObserver(); + + // Must be called before and after dispatching the event. + void willDispatchEvent(); + void didDispatchEvent(); + + // Observes the promise and delays calling the continuation until + // the given promise is resolved or rejected. + void waitUntil(ScriptState*, const ScriptValue&); + +private: + class ThenFunction; + + WaitUntilObserver(ExecutionContext*, EventType, int eventID); + + void reportError(const ScriptValue&); + + void incrementPendingActivity(); + void decrementPendingActivity(); + + EventType m_type; + int m_eventID; + int m_pendingActivity; + bool m_hasError; +}; + +} // namespace WebCore + +#endif // WaitUntilObserver_h diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/cachePolyfill.js b/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/cachePolyfill.js new file mode 100644 index 00000000000..bf2f9245e3e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/cachePolyfill.js @@ -0,0 +1,120 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// A simple, incomplete implementation of the Cache API, intended to facilitate +// end to end serviceworker testing. + +// See https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache-objects + +// FIXME: Support AbstractResponse/OpaqueResponse correctly. +// FIXME: Serialize the cache. +// FIXME: Bind all function references. +(function(global) { + var _castToRequest = function(item) { + if (typeof item === 'string') { + item = new Request({ + url: item, + }); + } + return item; + }; + + var Cache = function() { + // An object containing a property for each HTTP fetch method. Those + // referenced objects contain a property for each URL, which is the + // Response. + this.entriesByMethod = {}; + }; + + // FIXME: Should this be in the spec? + Cache.prototype.keys = function() { + var that = this; + + var flatten = Array.prototype.concat.apply.bind(Array.prototype.concat, []); + + return Promise.resolve(flatten( + Object.keys(this.entriesByMethod).map(function(method) { + return Object.keys(that.entriesByMethod[method]).map(function(url) { + return new Request({method: method, url: url}); + }); + }))); + }; + + // FIXME: Implement this. + // FIXME: Should spec rename each --> forEach? + Cache.prototype.forEach = Promise.reject.bind(Promise, 'Cache.prototype.forEach() not implemented.'); + Cache.prototype.each = Promise.reject.bind(Promise, 'Cache.prototype.each() not implemented.'); + + Cache.prototype.put = function(request, response) { + var that = this; + + return new Promise(function(resolve, reject) { + request = _castToRequest(request); + + if (!that.entriesByMethod.hasOwnProperty(request.method)) { + that.entriesByMethod[request.method] = {}; + } + + var entriesByUrl = that.entriesByMethod[request.method]; + entriesByUrl[request.url] = response; + + resolve(); + }); + }; + + Cache.prototype.add = function(request) { + var that = this; + request = _castToRequest(request); + return new Promise(function (resolve, reject) { + fetch(request).then( + function(response) { + that.put(request, response).then(resolve); + }, + reject); + }); + }; + + // FIXME: Add QueryParams argument. + Cache.prototype.delete = function(request) { + request = _castToRequest(request); + + var that = this; + return new Promise(function(resolve, reject) { + if (that.entriesByMethod.hasOwnProperty(request.method)) { + var entriesByUrl = that.entriesByMethod[request.method]; + delete entriesByUrl[request.url]; + } + resolve(); + }); + }; + + // FIXME: Add QueryParams argument. + Cache.prototype.match = function(request) { + var that = this; + + return new Promise(function(resolve, reject) { + request = _castToRequest(request); + + if (!that.entriesByMethod.hasOwnProperty(request.method)) { + reject('not found'); + return; + } + + var entriesByUrl = that.entriesByMethod[request.method]; + + if (!entriesByUrl.hasOwnProperty(request.url)) { + reject('not found'); + return; + } + + var entry = entriesByUrl[request.url]; + resolve(entry); + }); + }; + + // FIXME: Implement this. + Cache.prototype.matchAll = Promise.reject.bind(Promise, 'Cache.prototype.matchAll not implemented.'); + + global.Cache = global.Cache || Cache; +}(self)); // window or worker global scope. diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/cacheStoragePolyfill.js b/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/cacheStoragePolyfill.js new file mode 100644 index 00000000000..d3b0c5f7197 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/cacheStoragePolyfill.js @@ -0,0 +1,91 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// A simple, incomplete implementation of the CacheStorage API, intended to facilitate +// end to end serviceworker testing. + +// See https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache-storage + +(function(global) { + var CacheStorage = function() { + this.cachesByName = {}; + }; + + CacheStorage.prototype.get = function(key) { + if (this.cachesByName.hasOwnProperty(key)) { + return Promise.resolve(this.cachesByName[key]); + } + return Promise.reject('not found'); + }; + + CacheStorage.prototype.has = function(key) { + return Promise.resolve(this.cachesByName.hasOwnProperty(key)); + }; + + // FIXME: Engage standardization on removing this method from the spec. + CacheStorage.prototype.set = Promise.reject.bind(Promise, 'CacheStorage.prototype.set() not implemented.'); + + // FIXME: Engage standardization on adding this method to the spec. + CacheStorage.prototype.create = function(key) { + this.cachesByName[key] = new Cache(); + + return Promise.resolve(); + }; + + // FIXME: Engage standarization on adding this method to the spec. + CacheStorage.prototype.rename = function(fromKey, toKey) { + if (!this.cachesByName.hasOwnProperty(fromKey)) { + return Promise.reject('not found'); + } + this.cachesByName[toKey] = this.cachesByName[fromKey]; + delete this.cachesByName[fromKey]; + + return Promise.resolve(); + }; + + CacheStorage.prototype.clear = function() { + this.cachesByName = {}; + + return Promise.resolve(); + }; + + CacheStorage.prototype.delete = function(key) { + delete this.cachesByName[key]; + + return Promise.resolve(); + }; + + CacheStorage.prototype.forEach = function(callback, thisArg) { + Object.keys(this.cachesByName).map(function(key) { + thisArg.callback(this.cachesByName[key], key, this); + }); + return Promise.resolve(); + }; + + // FIXME: Implement this. + CacheStorage.prototype.entries = Promise.reject.bind(Promise, 'CacheStorage.prototype.entries() not implemented.'); + + CacheStorage.prototype.keys = function() { + return Promise.resolve(Object.keys(this.cachesByName)); + }; + + CacheStorage.prototype.values = function() { + return Promise.resolve(Object.keys(this.cachesByName).map(function(key) { + return this.cachesByName[key]; + })); + }; + + CacheStorage.prototype.size = function() { + return Promise.resolve(Object.keys(this.cachesByName).length); + }; + + // FIXME: Figure out what should be done with undefined or poorly defined |cacheName| values. + CacheStorage.prototype.match = function(url, cacheName) { + return this.get(cacheName).then(function(cache) { + return cache.match(url); + }); + }; + + global.caches = global.caches || new CacheStorage(); +}(self)); // window or worker global scope. diff --git a/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/fetchPolyfill.js b/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/fetchPolyfill.js new file mode 100644 index 00000000000..22b3bd41025 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/serviceworkers/polyfills/fetchPolyfill.js @@ -0,0 +1,51 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// A simple, incomplete implementation of Fetch, intended to facilitate end +// to end serviceworker testing. + +// See http://fetch.spec.whatwg.org/#fetch-method + +(function (global) { + var _castToRequest = function (item) { + if (typeof item === 'string') { + item = new Request({ + url: item + }); + } + return item; + }; + + // FIXME: Support init argument to fetch. + var fetch = function(request) { + request = _castToRequest(request); + + return new Promise(function(resolve, reject) { + // FIXME: Use extra headers from |request|. + var xhr = new XMLHttpRequest(); + xhr.open(request.method, request.url, true /* async */); + xhr.send(null); + xhr.onreadystatechange = function() { + if (xhr.readyState !== 4) return; + + var response = new Response({ + status: xhr.status, + statusText: xhr.statusText, + // FIXME: Set response.headers. + // FIXME: Set response.method when available. + // FIXME: Set response.url when available. + // FIXME: Set response.body when available. + }); + + if (xhr.status === 200) { + resolve(response); + } else { + reject(response); + } + }; + }); + }; + + global.fetch = global.fetch || fetch; +}(self)); // window or worker global scope diff --git a/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeech.h b/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeech.h new file mode 100644 index 00000000000..03f01d5c617 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeech.h @@ -0,0 +1,7 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO: This is a dummy header file required by the generated binding code. +// This file should be removed after fixing the code generator. + diff --git a/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeechSynthesis.cpp b/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeechSynthesis.cpp index 2e4b06c6cd6..d67d3b64af4 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeechSynthesis.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeechSynthesis.cpp @@ -31,14 +31,14 @@ #include "config.h" #include "modules/speech/DOMWindowSpeechSynthesis.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" #include "wtf/PassRefPtr.h" namespace WebCore { -DOMWindowSpeechSynthesis::DOMWindowSpeechSynthesis(DOMWindow* window) - : DOMWindowProperty(window->frame()) +DOMWindowSpeechSynthesis::DOMWindowSpeechSynthesis(LocalDOMWindow& window) + : DOMWindowProperty(window.frame()) { } @@ -52,20 +52,20 @@ const char* DOMWindowSpeechSynthesis::supplementName() } // static -DOMWindowSpeechSynthesis* DOMWindowSpeechSynthesis::from(DOMWindow* window) +DOMWindowSpeechSynthesis& DOMWindowSpeechSynthesis::from(LocalDOMWindow& window) { - DOMWindowSpeechSynthesis* supplement = static_cast<DOMWindowSpeechSynthesis*>(Supplement<DOMWindow>::from(window, supplementName())); + DOMWindowSpeechSynthesis* supplement = static_cast<DOMWindowSpeechSynthesis*>(WillBeHeapSupplement<LocalDOMWindow>::from(window, supplementName())); if (!supplement) { supplement = new DOMWindowSpeechSynthesis(window); - provideTo(window, supplementName(), adoptPtr(supplement)); + provideTo(window, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } // static -SpeechSynthesis* DOMWindowSpeechSynthesis::speechSynthesis(DOMWindow* window) +SpeechSynthesis* DOMWindowSpeechSynthesis::speechSynthesis(LocalDOMWindow& window) { - return DOMWindowSpeechSynthesis::from(window)->speechSynthesis(); + return DOMWindowSpeechSynthesis::from(window).speechSynthesis(); } SpeechSynthesis* DOMWindowSpeechSynthesis::speechSynthesis() @@ -75,4 +75,10 @@ SpeechSynthesis* DOMWindowSpeechSynthesis::speechSynthesis() return m_speechSynthesis.get(); } +void DOMWindowSpeechSynthesis::trace(Visitor* visitor) +{ + visitor->trace(m_speechSynthesis); + WillBeHeapSupplement<LocalDOMWindow>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeechSynthesis.h b/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeechSynthesis.h index d3afe89301f..865bdb1e7cc 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeechSynthesis.h +++ b/chromium/third_party/WebKit/Source/modules/speech/DOMWindowSpeechSynthesis.h @@ -29,25 +29,29 @@ #include "core/frame/DOMWindowProperty.h" #include "modules/speech/SpeechSynthesis.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { -class DOMWindow; +class LocalDOMWindow; -class DOMWindowSpeechSynthesis : public Supplement<DOMWindow>, public DOMWindowProperty { +class DOMWindowSpeechSynthesis FINAL : public NoBaseWillBeGarbageCollectedFinalized<DOMWindowSpeechSynthesis>, public WillBeHeapSupplement<LocalDOMWindow>, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DOMWindowSpeechSynthesis); public: virtual ~DOMWindowSpeechSynthesis(); - static SpeechSynthesis* speechSynthesis(DOMWindow*); - static DOMWindowSpeechSynthesis* from(DOMWindow*); + static SpeechSynthesis* speechSynthesis(LocalDOMWindow&); + static DOMWindowSpeechSynthesis& from(LocalDOMWindow&); + + void trace(Visitor*); private: - explicit DOMWindowSpeechSynthesis(DOMWindow*); + explicit DOMWindowSpeechSynthesis(LocalDOMWindow&); SpeechSynthesis* speechSynthesis(); static const char* supplementName(); - RefPtr<SpeechSynthesis> m_speechSynthesis; + PersistentWillBeMember<SpeechSynthesis> m_speechSynthesis; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.cpp index 3b0992b047b..c051e1732fd 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.cpp @@ -31,14 +31,14 @@ namespace WebCore { -PassRefPtr<SpeechGrammar> SpeechGrammar::create() +SpeechGrammar* SpeechGrammar::create() { - return adoptRef(new SpeechGrammar); + return new SpeechGrammar; } -PassRefPtr<SpeechGrammar> SpeechGrammar::create(const KURL& src, double weight) +SpeechGrammar* SpeechGrammar::create(const KURL& src, double weight) { - return adoptRef(new SpeechGrammar(src, weight)); + return new SpeechGrammar(src, weight); } void SpeechGrammar::setSrc(ExecutionContext* executionContext, const String& src) diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.h index e7bff2a37af..5a0da9132f3 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.h @@ -27,18 +27,18 @@ #define SpeechGrammar_h #include "bindings/v8/ScriptWrappable.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" -#include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace WebCore { class ExecutionContext; -class SpeechGrammar : public ScriptWrappable, public RefCounted<SpeechGrammar> { +class SpeechGrammar FINAL : public GarbageCollectedFinalized<SpeechGrammar>, public ScriptWrappable { public: - static PassRefPtr<SpeechGrammar> create(); // FIXME: The spec is not clear on what the constructor should look like. - static PassRefPtr<SpeechGrammar> create(const KURL& src, double weight); + static SpeechGrammar* create(); // FIXME: The spec is not clear on what the constructor should look like. + static SpeechGrammar* create(const KURL& src, double weight); const KURL& src(ExecutionContext*) const { return m_src; } const KURL& src() const { return m_src; } @@ -47,6 +47,8 @@ public: double weight() const { return m_weight; } void setWeight(double weight) { m_weight = weight; } + void trace(Visitor*) { } + private: SpeechGrammar(); SpeechGrammar(const KURL& src, double weight); diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.idl index 1b629a4bffb..7b186bf5367 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammar.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject, Constructor ] interface SpeechGrammar { diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.cpp index 6dfe69ee483..d2dbf0fc2ec 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.cpp @@ -31,9 +31,9 @@ namespace WebCore { -PassRefPtr<SpeechGrammarList> SpeechGrammarList::create() +SpeechGrammarList* SpeechGrammarList::create() { - return adoptRef(new SpeechGrammarList); + return new SpeechGrammarList; } SpeechGrammar* SpeechGrammarList::item(unsigned long index) const @@ -61,4 +61,9 @@ SpeechGrammarList::SpeechGrammarList() ScriptWrappable::init(this); } +void SpeechGrammarList::trace(Visitor* visitor) +{ + visitor->trace(m_grammars); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.h index 5f877d9f970..9b6f4499c6b 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.h @@ -28,16 +28,15 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/speech/SpeechGrammar.h" -#include "wtf/RefCounted.h" -#include "wtf/Vector.h" +#include "platform/heap/Handle.h" namespace WebCore { class ExecutionContext; -class SpeechGrammarList : public ScriptWrappable, public RefCounted<SpeechGrammarList> { +class SpeechGrammarList : public GarbageCollectedFinalized<SpeechGrammarList>, public ScriptWrappable { public: - static PassRefPtr<SpeechGrammarList> create(); + static SpeechGrammarList* create(); unsigned long length() const { return m_grammars.size(); } SpeechGrammar* item(unsigned long) const; @@ -45,10 +44,12 @@ public: void addFromUri(ExecutionContext*, const String& src, double weight = 1.0); void addFromString(const String&, double weight = 1.0); + void trace(Visitor*); + private: SpeechGrammarList(); - Vector<RefPtr<SpeechGrammar> > m_grammars; + HeapVector<Member<SpeechGrammar> > m_grammars; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.idl index 9239d9e8e9e..a0dde223ef2 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechGrammarList.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject, Constructor ] interface SpeechGrammarList { diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.cpp index 364332ee890..eb0dcaf0af7 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.cpp @@ -37,11 +37,11 @@ namespace WebCore { -PassRefPtr<SpeechRecognition> SpeechRecognition::create(ExecutionContext* context) +SpeechRecognition* SpeechRecognition::create(ExecutionContext* context) { - RefPtr<SpeechRecognition> speechRecognition(adoptRef(new SpeechRecognition(context))); + SpeechRecognition* speechRecognition = adoptRefCountedGarbageCollectedWillBeNoop(new SpeechRecognition(context)); speechRecognition->suspendIfNeeded(); - return speechRecognition.release(); + return speechRecognition; } void SpeechRecognition::start(ExceptionState& exceptionState) @@ -52,7 +52,6 @@ void SpeechRecognition::start(ExceptionState& exceptionState) return; } - setPendingActivity(this); m_finalResults.clear(); m_controller->start(this, m_grammars.get(), m_lang, m_continuous, m_interimResults, m_maxAlternatives); m_started = true; @@ -106,26 +105,26 @@ void SpeechRecognition::didEndAudio() dispatchEvent(Event::create(EventTypeNames::audioend)); } -void SpeechRecognition::didReceiveResults(const Vector<RefPtr<SpeechRecognitionResult> >& newFinalResults, const Vector<RefPtr<SpeechRecognitionResult> >& currentInterimResults) +void SpeechRecognition::didReceiveResults(const HeapVector<Member<SpeechRecognitionResult> >& newFinalResults, const HeapVector<Member<SpeechRecognitionResult> >& currentInterimResults) { unsigned long resultIndex = m_finalResults.size(); for (size_t i = 0; i < newFinalResults.size(); ++i) m_finalResults.append(newFinalResults[i]); - Vector<RefPtr<SpeechRecognitionResult> > results = m_finalResults; + HeapVector<Member<SpeechRecognitionResult> > results = m_finalResults; for (size_t i = 0; i < currentInterimResults.size(); ++i) results.append(currentInterimResults[i]); dispatchEvent(SpeechRecognitionEvent::createResult(resultIndex, results)); } -void SpeechRecognition::didReceiveNoMatch(PassRefPtr<SpeechRecognitionResult> result) +void SpeechRecognition::didReceiveNoMatch(SpeechRecognitionResult* result) { dispatchEvent(SpeechRecognitionEvent::createNoMatch(result)); } -void SpeechRecognition::didReceiveError(PassRefPtr<SpeechRecognitionError> error) +void SpeechRecognition::didReceiveError(PassRefPtrWillBeRawPtr<SpeechRecognitionError> error) { dispatchEvent(error); m_started = false; @@ -142,7 +141,6 @@ void SpeechRecognition::didEnd() m_stopping = false; if (!m_stoppedByActiveDOMObject) dispatchEvent(Event::create(EventTypeNames::end)); - unsetPendingActivity(this); } const AtomicString& SpeechRecognition::interfaceName() const @@ -162,13 +160,18 @@ void SpeechRecognition::stop() abort(); } +bool SpeechRecognition::hasPendingActivity() const +{ + return m_started; +} + SpeechRecognition::SpeechRecognition(ExecutionContext* context) : ActiveDOMObject(context) , m_grammars(SpeechGrammarList::create()) // FIXME: The spec is not clear on the default value for the grammars attribute. , m_continuous(false) , m_interimResults(false) , m_maxAlternatives(1) - , m_controller(0) + , m_controller(nullptr) , m_stoppedByActiveDOMObject(false) , m_started(false) , m_stopping(false) @@ -189,4 +192,14 @@ SpeechRecognition::~SpeechRecognition() { } +void SpeechRecognition::trace(Visitor* visitor) +{ + visitor->trace(m_grammars); +#if ENABLE(OILPAN) + visitor->trace(m_controller); +#endif + visitor->trace(m_finalResults); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.h index 4b6d0835d69..65dbcdec24c 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.h @@ -28,11 +28,11 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" #include "modules/speech/SpeechGrammarList.h" +#include "modules/speech/SpeechRecognitionResult.h" +#include "platform/heap/Handle.h" #include "wtf/Compiler.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -41,18 +41,17 @@ class ExceptionState; class ExecutionContext; class SpeechRecognitionController; class SpeechRecognitionError; -class SpeechRecognitionResult; -class SpeechRecognitionResultList; -class SpeechRecognition : public RefCounted<SpeechRecognition>, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData { - REFCOUNTED_EVENT_TARGET(SpeechRecognition); +class SpeechRecognition FINAL : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<SpeechRecognition>, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData { + DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<SpeechRecognition>); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(SpeechRecognition); public: - static PassRefPtr<SpeechRecognition> create(ExecutionContext*); - ~SpeechRecognition(); + static SpeechRecognition* create(ExecutionContext*); + virtual ~SpeechRecognition(); // Attributes. - PassRefPtr<SpeechGrammarList> grammars() { return m_grammars; } - void setGrammars(PassRefPtr<SpeechGrammarList> grammars) { m_grammars = grammars; } + SpeechGrammarList* grammars() { return m_grammars; } + void setGrammars(SpeechGrammarList* grammars) { m_grammars = grammars; } String lang() { return m_lang; } void setLang(const String& lang) { m_lang = lang; } bool continuous() { return m_continuous; } @@ -74,9 +73,9 @@ public: void didEndSpeech(); void didEndSound(); void didEndAudio(); - void didReceiveResults(const Vector<RefPtr<SpeechRecognitionResult> >& newFinalResults, const Vector<RefPtr<SpeechRecognitionResult> >& currentInterimResults); - void didReceiveNoMatch(PassRefPtr<SpeechRecognitionResult>); - void didReceiveError(PassRefPtr<SpeechRecognitionError>); + void didReceiveResults(const HeapVector<Member<SpeechRecognitionResult> >& newFinalResults, const HeapVector<Member<SpeechRecognitionResult> >& currentInterimResults); + void didReceiveNoMatch(SpeechRecognitionResult*); + void didReceiveError(PassRefPtrWillBeRawPtr<SpeechRecognitionError>); void didStart(); void didEnd(); @@ -85,6 +84,7 @@ public: virtual ExecutionContext* executionContext() const OVERRIDE; // ActiveDOMObject. + virtual bool hasPendingActivity() const OVERRIDE; virtual void stop() OVERRIDE; DEFINE_ATTRIBUTE_EVENT_LISTENER(audiostart); @@ -99,22 +99,22 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(start); DEFINE_ATTRIBUTE_EVENT_LISTENER(end); -private: - friend class RefCounted<SpeechRecognition>; + virtual void trace(Visitor*) OVERRIDE; +private: explicit SpeechRecognition(ExecutionContext*); - RefPtr<SpeechGrammarList> m_grammars; + Member<SpeechGrammarList> m_grammars; String m_lang; bool m_continuous; bool m_interimResults; unsigned long m_maxAlternatives; - SpeechRecognitionController* m_controller; + RawPtrWillBeMember<SpeechRecognitionController> m_controller; bool m_stoppedByActiveDOMObject; bool m_started; bool m_stopping; - Vector<RefPtr<SpeechRecognitionResult> > m_finalResults; + HeapVector<Member<SpeechRecognitionResult> > m_finalResults; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.idl index dded48ed4b4..712bac61a8b 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognition.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject, ActiveDOMObject, Constructor, diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.cpp index ba38c53bde2..ad99b54b155 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.cpp @@ -29,9 +29,9 @@ namespace WebCore { -PassRefPtr<SpeechRecognitionAlternative> SpeechRecognitionAlternative::create(const String& transcript, double confidence) +SpeechRecognitionAlternative* SpeechRecognitionAlternative::create(const String& transcript, double confidence) { - return adoptRef(new SpeechRecognitionAlternative(transcript, confidence)); + return new SpeechRecognitionAlternative(transcript, confidence); } SpeechRecognitionAlternative::SpeechRecognitionAlternative(const String& transcript, double confidence) diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.h index 464fe9e276e..1cffc074abd 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.h @@ -27,20 +27,22 @@ #define SpeechRecognitionAlternative_h #include "bindings/v8/ScriptWrappable.h" -#include "wtf/RefCounted.h" +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { class ExecutionContext; -class SpeechRecognitionAlternative : public ScriptWrappable, public RefCounted<SpeechRecognitionAlternative> { +class SpeechRecognitionAlternative : public GarbageCollectedFinalized<SpeechRecognitionAlternative>, public ScriptWrappable { public: - static PassRefPtr<SpeechRecognitionAlternative> create(const String&, double); + static SpeechRecognitionAlternative* create(const String&, double); const String& transcript() const { return m_transcript; } double confidence() const { return m_confidence; } + void trace(Visitor*) { } + private: SpeechRecognitionAlternative(const String&, double); diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.idl index 3e120cabb3e..38acdc09dc1 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionAlternative.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject ] interface SpeechRecognitionAlternative { readonly attribute DOMString transcript; diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionClient.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionClient.h index 24c9662a8ed..cd0c2785028 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionClient.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionClient.h @@ -43,7 +43,7 @@ public: virtual ~SpeechRecognitionClient() { } }; -void provideSpeechRecognitionTo(Page*, SpeechRecognitionClient*); +void provideSpeechRecognitionTo(Page&, PassOwnPtr<SpeechRecognitionClient>); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionController.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionController.cpp index 4242ac5a007..189c8d53629 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionController.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionController.cpp @@ -33,7 +33,7 @@ const char* SpeechRecognitionController::supplementName() return "SpeechRecognitionController"; } -SpeechRecognitionController::SpeechRecognitionController(SpeechRecognitionClient* client) +SpeechRecognitionController::SpeechRecognitionController(PassOwnPtr<SpeechRecognitionClient> client) : m_client(client) { } @@ -43,12 +43,12 @@ SpeechRecognitionController::~SpeechRecognitionController() // FIXME: Call m_client->pageDestroyed(); once we have implemented a client. } -PassOwnPtr<SpeechRecognitionController> SpeechRecognitionController::create(SpeechRecognitionClient* client) +PassOwnPtrWillBeRawPtr<SpeechRecognitionController> SpeechRecognitionController::create(PassOwnPtr<SpeechRecognitionClient> client) { - return adoptPtr(new SpeechRecognitionController(client)); + return adoptPtrWillBeNoop(new SpeechRecognitionController(client)); } -void provideSpeechRecognitionTo(Page* page, SpeechRecognitionClient* client) +void provideSpeechRecognitionTo(Page& page, PassOwnPtr<SpeechRecognitionClient> client) { SpeechRecognitionController::provideTo(page, SpeechRecognitionController::supplementName(), SpeechRecognitionController::create(client)); } diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionController.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionController.h index 4e5d50d3a0d..f5512aa91c1 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionController.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionController.h @@ -32,7 +32,8 @@ namespace WebCore { -class SpeechRecognitionController : public Supplement<Page> { +class SpeechRecognitionController FINAL : public NoBaseWillBeGarbageCollectedFinalized<SpeechRecognitionController>, public WillBeHeapSupplement<Page> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(SpeechRecognitionController); public: virtual ~SpeechRecognitionController(); @@ -44,14 +45,16 @@ public: void stop(SpeechRecognition* recognition) { m_client->stop(recognition); } void abort(SpeechRecognition* recognition) { m_client->abort(recognition); } - static PassOwnPtr<SpeechRecognitionController> create(SpeechRecognitionClient*); + static PassOwnPtrWillBeRawPtr<SpeechRecognitionController> create(PassOwnPtr<SpeechRecognitionClient>); static const char* supplementName(); - static SpeechRecognitionController* from(Page* page) { return static_cast<SpeechRecognitionController*>(Supplement<Page>::from(page, supplementName())); } + static SpeechRecognitionController* from(Page* page) { return static_cast<SpeechRecognitionController*>(WillBeHeapSupplement<Page>::from(page, supplementName())); } + + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Page>::trace(visitor); } private: - explicit SpeechRecognitionController(SpeechRecognitionClient*); + explicit SpeechRecognitionController(PassOwnPtr<SpeechRecognitionClient>); - SpeechRecognitionClient* m_client; + OwnPtr<SpeechRecognitionClient> m_client; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp index c1eb2a2d8db..5e4bcee12e3 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp @@ -56,19 +56,19 @@ static String ErrorCodeToString(SpeechRecognitionError::ErrorCode code) return String(); } -PassRefPtr<SpeechRecognitionError> SpeechRecognitionError::create(ErrorCode code, const String& message) +PassRefPtrWillBeRawPtr<SpeechRecognitionError> SpeechRecognitionError::create(ErrorCode code, const String& message) { - return adoptRef(new SpeechRecognitionError(ErrorCodeToString(code), message)); + return adoptRefWillBeNoop(new SpeechRecognitionError(ErrorCodeToString(code), message)); } -PassRefPtr<SpeechRecognitionError> SpeechRecognitionError::create() +PassRefPtrWillBeRawPtr<SpeechRecognitionError> SpeechRecognitionError::create() { - return adoptRef(new SpeechRecognitionError(emptyString(), emptyString())); + return adoptRefWillBeNoop(new SpeechRecognitionError(emptyString(), emptyString())); } -PassRefPtr<SpeechRecognitionError> SpeechRecognitionError::create(const AtomicString& eventName, const SpeechRecognitionErrorInit& initializer) +PassRefPtrWillBeRawPtr<SpeechRecognitionError> SpeechRecognitionError::create(const AtomicString& eventName, const SpeechRecognitionErrorInit& initializer) { - return adoptRef(new SpeechRecognitionError(eventName, initializer)); + return adoptRefWillBeNoop(new SpeechRecognitionError(eventName, initializer)); } SpeechRecognitionError::SpeechRecognitionError(const String& error, const String& message) diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.h index 1eae69e6dda..0572449e7f4 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.h @@ -26,8 +26,7 @@ #ifndef SpeechRecognitionError_h #define SpeechRecognitionError_h -#include "core/events/Event.h" -#include "wtf/RefCounted.h" +#include "modules/EventModules.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -39,7 +38,7 @@ struct SpeechRecognitionErrorInit : public EventInit { String message; }; -class SpeechRecognitionError : public Event { +class SpeechRecognitionError FINAL : public Event { public: enum ErrorCode { // FIXME: This is an unspecified error and Chromium should stop using it. @@ -55,15 +54,20 @@ public: ErrorCodeLanguageNotSupported = 8 }; - static PassRefPtr<SpeechRecognitionError> create(ErrorCode, const String&); - static PassRefPtr<SpeechRecognitionError> create(); - static PassRefPtr<SpeechRecognitionError> create(const AtomicString&, const SpeechRecognitionErrorInit&); + static PassRefPtrWillBeRawPtr<SpeechRecognitionError> create(ErrorCode, const String&); + static PassRefPtrWillBeRawPtr<SpeechRecognitionError> create(); + static PassRefPtrWillBeRawPtr<SpeechRecognitionError> create(const AtomicString&, const SpeechRecognitionErrorInit&); const String& error() { return m_error; } const String& message() { return m_message; } virtual const AtomicString& interfaceName() const OVERRIDE; + virtual void trace(Visitor* visitor) OVERRIDE + { + Event::trace(visitor); + } + private: SpeechRecognitionError(const String&, const String&); SpeechRecognitionError(const AtomicString&, const SpeechRecognitionErrorInit&); diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionEvent.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionEvent.cpp index a34d3a91b52..e6898873810 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionEvent.cpp @@ -34,30 +34,30 @@ SpeechRecognitionEventInit::SpeechRecognitionEventInit() { } -PassRefPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::create() +PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::create() { - return adoptRef(new SpeechRecognitionEvent()); + return adoptRefWillBeNoop(new SpeechRecognitionEvent); } -PassRefPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::create(const AtomicString& eventName, const SpeechRecognitionEventInit& initializer) +PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::create(const AtomicString& eventName, const SpeechRecognitionEventInit& initializer) { - return adoptRef(new SpeechRecognitionEvent(eventName, initializer)); + return adoptRefWillBeNoop(new SpeechRecognitionEvent(eventName, initializer)); } -PassRefPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::createResult(unsigned long resultIndex, const Vector<RefPtr<SpeechRecognitionResult> >& results) +PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::createResult(unsigned long resultIndex, const HeapVector<Member<SpeechRecognitionResult> >& results) { - return adoptRef(new SpeechRecognitionEvent(EventTypeNames::result, resultIndex, SpeechRecognitionResultList::create(results))); + return adoptRefWillBeNoop(new SpeechRecognitionEvent(EventTypeNames::result, resultIndex, SpeechRecognitionResultList::create(results))); } -PassRefPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::createNoMatch(PassRefPtr<SpeechRecognitionResult> result) +PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::createNoMatch(SpeechRecognitionResult* result) { if (result) { - Vector<RefPtr<SpeechRecognitionResult> > results; + HeapVector<Member<SpeechRecognitionResult> > results; results.append(result); - return adoptRef(new SpeechRecognitionEvent(EventTypeNames::nomatch, 0, SpeechRecognitionResultList::create(results))); + return adoptRefWillBeNoop(new SpeechRecognitionEvent(EventTypeNames::nomatch, 0, SpeechRecognitionResultList::create(results))); } - return adoptRef(new SpeechRecognitionEvent(EventTypeNames::nomatch, 0, 0)); + return adoptRefWillBeNoop(new SpeechRecognitionEvent(EventTypeNames::nomatch, 0, nullptr)); } const AtomicString& SpeechRecognitionEvent::interfaceName() const @@ -79,7 +79,7 @@ SpeechRecognitionEvent::SpeechRecognitionEvent(const AtomicString& eventName, co ScriptWrappable::init(this); } -SpeechRecognitionEvent::SpeechRecognitionEvent(const AtomicString& eventName, unsigned long resultIndex, PassRefPtr<SpeechRecognitionResultList> results) +SpeechRecognitionEvent::SpeechRecognitionEvent(const AtomicString& eventName, unsigned long resultIndex, SpeechRecognitionResultList* results) : Event(eventName, /*canBubble=*/false, /*cancelable=*/false) , m_resultIndex(resultIndex) , m_results(results) @@ -89,7 +89,12 @@ SpeechRecognitionEvent::SpeechRecognitionEvent(const AtomicString& eventName, un SpeechRecognitionEvent::~SpeechRecognitionEvent() { - ScriptWrappable::init(this); +} + +void SpeechRecognitionEvent::trace(Visitor* visitor) +{ + visitor->trace(m_results); + Event::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionEvent.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionEvent.h index 532a33299e1..98f0f574848 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionEvent.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionEvent.h @@ -26,30 +26,31 @@ #ifndef SpeechRecognitionEvent_h #define SpeechRecognitionEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "modules/speech/SpeechRecognitionResult.h" #include "modules/speech/SpeechRecognitionResultList.h" -#include "wtf/RefPtr.h" +#include "platform/heap/Handle.h" namespace WebCore { class Document; -struct SpeechRecognitionEventInit : public EventInit { +class SpeechRecognitionEventInit : public EventInit { +public: SpeechRecognitionEventInit(); unsigned long resultIndex; - RefPtr<SpeechRecognitionResultList> results; + Member<SpeechRecognitionResultList> results; }; -class SpeechRecognitionEvent : public Event { +class SpeechRecognitionEvent FINAL : public Event { public: - static PassRefPtr<SpeechRecognitionEvent> create(); - static PassRefPtr<SpeechRecognitionEvent> create(const AtomicString&, const SpeechRecognitionEventInit&); + static PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> create(); + static PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> create(const AtomicString&, const SpeechRecognitionEventInit&); virtual ~SpeechRecognitionEvent(); - static PassRefPtr<SpeechRecognitionEvent> createResult(unsigned long resultIndex, const Vector<RefPtr<SpeechRecognitionResult> >& results); - static PassRefPtr<SpeechRecognitionEvent> createNoMatch(PassRefPtr<SpeechRecognitionResult>); + static PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> createResult(unsigned long resultIndex, const HeapVector<Member<SpeechRecognitionResult> >& results); + static PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> createNoMatch(SpeechRecognitionResult*); unsigned long resultIndex() const { return m_resultIndex; } SpeechRecognitionResultList* results() const { return m_results.get(); } @@ -61,13 +62,15 @@ public: // Event virtual const AtomicString& interfaceName() const OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: SpeechRecognitionEvent(); SpeechRecognitionEvent(const AtomicString&, const SpeechRecognitionEventInit&); - SpeechRecognitionEvent(const AtomicString& eventName, unsigned long resultIndex, PassRefPtr<SpeechRecognitionResultList> results); + SpeechRecognitionEvent(const AtomicString& eventName, unsigned long resultIndex, SpeechRecognitionResultList* results); unsigned long m_resultIndex; - RefPtr<SpeechRecognitionResultList> m_results; + PersistentWillBeMember<SpeechRecognitionResultList> m_results; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.cpp index b4bfe7d7116..92429138685 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.cpp @@ -33,9 +33,9 @@ SpeechRecognitionResult::~SpeechRecognitionResult() { } -PassRefPtr<SpeechRecognitionResult> SpeechRecognitionResult::create(const Vector<RefPtr<SpeechRecognitionAlternative> >& alternatives, bool final) +SpeechRecognitionResult* SpeechRecognitionResult::create(const HeapVector<Member<SpeechRecognitionAlternative> >& alternatives, bool final) { - return adoptRef(new SpeechRecognitionResult(alternatives, final)); + return new SpeechRecognitionResult(alternatives, final); } SpeechRecognitionAlternative* SpeechRecognitionResult::item(unsigned long index) @@ -46,11 +46,16 @@ SpeechRecognitionAlternative* SpeechRecognitionResult::item(unsigned long index) return m_alternatives[index].get(); } -SpeechRecognitionResult::SpeechRecognitionResult(const Vector<RefPtr<SpeechRecognitionAlternative> >& alternatives, bool final) - : m_alternatives(alternatives) - , m_final(final) +SpeechRecognitionResult::SpeechRecognitionResult(const HeapVector<Member<SpeechRecognitionAlternative> >& alternatives, bool final) + : m_final(final) + , m_alternatives(alternatives) { ScriptWrappable::init(this); } +void SpeechRecognitionResult::trace(Visitor* visitor) +{ + visitor->trace(m_alternatives); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.h index 3c33629463f..3d936df2f46 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.h @@ -28,25 +28,26 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/speech/SpeechRecognitionAlternative.h" -#include "wtf/RefCounted.h" -#include "wtf/Vector.h" +#include "platform/heap/Handle.h" namespace WebCore { -class SpeechRecognitionResult : public ScriptWrappable, public RefCounted<SpeechRecognitionResult> { +class SpeechRecognitionResult FINAL : public GarbageCollectedFinalized<SpeechRecognitionResult>, public ScriptWrappable { public: ~SpeechRecognitionResult(); - static PassRefPtr<SpeechRecognitionResult> create(const Vector<RefPtr<SpeechRecognitionAlternative> >&, bool final); + static SpeechRecognitionResult* create(const HeapVector<Member<SpeechRecognitionAlternative> >&, bool final); unsigned long length() { return m_alternatives.size(); } SpeechRecognitionAlternative* item(unsigned long index); bool isFinal() { return m_final; } + void trace(Visitor*); + private: - SpeechRecognitionResult(const Vector<RefPtr<SpeechRecognitionAlternative> >&, bool final); + SpeechRecognitionResult(const HeapVector<Member<SpeechRecognitionAlternative> >&, bool final); - Vector<RefPtr<SpeechRecognitionAlternative> > m_alternatives; bool m_final; + HeapVector<Member<SpeechRecognitionAlternative> > m_alternatives; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.idl index 91d3e907e81..ab0761b693a 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResult.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject ] interface SpeechRecognitionResult { readonly attribute unsigned long length; diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.cpp index 7327bf7f7f3..0a23ebc82f9 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.cpp @@ -29,9 +29,9 @@ namespace WebCore { -PassRefPtr<SpeechRecognitionResultList> SpeechRecognitionResultList::create(const Vector<RefPtr<SpeechRecognitionResult> >& results) +SpeechRecognitionResultList* SpeechRecognitionResultList::create(const HeapVector<Member<SpeechRecognitionResult> >& results) { - return adoptRef(new SpeechRecognitionResultList(results)); + return new SpeechRecognitionResultList(results); } SpeechRecognitionResult* SpeechRecognitionResultList::item(unsigned long index) @@ -42,10 +42,15 @@ SpeechRecognitionResult* SpeechRecognitionResultList::item(unsigned long index) return m_results[index].get(); } -SpeechRecognitionResultList::SpeechRecognitionResultList(const Vector<RefPtr<SpeechRecognitionResult> >& results) +SpeechRecognitionResultList::SpeechRecognitionResultList(const HeapVector<Member<SpeechRecognitionResult> >& results) : m_results(results) { ScriptWrappable::init(this); } +void SpeechRecognitionResultList::trace(Visitor* visitor) +{ + visitor->trace(m_results); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.h index 24ca14720cb..79338dd9b39 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.h @@ -28,22 +28,23 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/speech/SpeechRecognitionResult.h" -#include "wtf/RefCounted.h" -#include "wtf/Vector.h" +#include "platform/heap/Handle.h" namespace WebCore { -class SpeechRecognitionResultList : public ScriptWrappable, public RefCounted<SpeechRecognitionResultList> { +class SpeechRecognitionResultList : public GarbageCollectedFinalized<SpeechRecognitionResultList>, public ScriptWrappable { public: - static PassRefPtr<SpeechRecognitionResultList> create(const Vector<RefPtr<SpeechRecognitionResult> >&); + static SpeechRecognitionResultList* create(const HeapVector<Member<SpeechRecognitionResult> >&); unsigned long length() { return m_results.size(); } SpeechRecognitionResult* item(unsigned long index); + void trace(Visitor*); + private: - explicit SpeechRecognitionResultList(const Vector<RefPtr<SpeechRecognitionResult> >&); + explicit SpeechRecognitionResultList(const HeapVector<Member<SpeechRecognitionResult> >&); - Vector<RefPtr<SpeechRecognitionResult> > m_results; + HeapVector<Member<SpeechRecognitionResult> > m_results; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.idl index c1eadd599a4..e93a5cfc7a2 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechRecognitionResultList.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject ] interface SpeechRecognitionResultList { readonly attribute unsigned long length; diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.cpp index c44a5db7976..39c384d8d93 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.cpp @@ -34,9 +34,9 @@ namespace WebCore { -PassRefPtr<SpeechSynthesis> SpeechSynthesis::create(ExecutionContext* context) +SpeechSynthesis* SpeechSynthesis::create(ExecutionContext* context) { - return adoptRef(new SpeechSynthesis(context)); + return adoptRefCountedGarbageCollectedWillBeNoop(new SpeechSynthesis(context)); } SpeechSynthesis::SpeechSynthesis(ExecutionContext* context) @@ -47,7 +47,7 @@ SpeechSynthesis::SpeechSynthesis(ExecutionContext* context) ScriptWrappable::init(this); } -void SpeechSynthesis::setPlatformSynthesizer(PassOwnPtr<PlatformSpeechSynthesizer> synthesizer) +void SpeechSynthesis::setPlatformSynthesizer(PlatformSpeechSynthesizer* synthesizer) { m_platformSpeechSynthesizer = synthesizer; } @@ -60,20 +60,20 @@ ExecutionContext* SpeechSynthesis::executionContext() const void SpeechSynthesis::voicesDidChange() { m_voiceList.clear(); - if (!executionContext()->activeDOMObjectsAreStopped()) + if (executionContext() && !executionContext()->activeDOMObjectsAreStopped()) dispatchEvent(Event::create(EventTypeNames::voiceschanged)); } -const Vector<RefPtr<SpeechSynthesisVoice> >& SpeechSynthesis::getVoices() +const HeapVector<Member<SpeechSynthesisVoice> >& SpeechSynthesis::getVoices() { if (m_voiceList.size()) return m_voiceList; // If the voiceList is empty, that's the cue to get the voices from the platform again. - const Vector<RefPtr<PlatformSpeechSynthesisVoice> >& platformVoices = m_platformSpeechSynthesizer->voiceList(); + const HeapVector<Member<PlatformSpeechSynthesisVoice> >& platformVoices = m_platformSpeechSynthesizer->voiceList(); size_t voiceCount = platformVoices.size(); for (size_t k = 0; k < voiceCount; k++) - m_voiceList.append(SpeechSynthesisVoice::create(platformVoices[k])); + m_voiceList.append(SpeechSynthesisVoice::create(platformVoices[k].get())); return m_voiceList; } @@ -116,14 +116,16 @@ void SpeechSynthesis::speak(SpeechSynthesisUtterance* utterance, ExceptionState& m_utteranceQueue.append(utterance); - // If the queue was empty, speak this immediately and add it to the queue. + // If the queue was empty, speak this immediately. if (m_utteranceQueue.size() == 1) startSpeakingImmediately(); } void SpeechSynthesis::cancel() { - // Remove all the items from the utterance queue. + // Remove all the items from the utterance queue. The platform + // may still have references to some of these utterances and may + // fire events on them asynchronously. m_utteranceQueue.clear(); m_platformSpeechSynthesizer->cancel(); } @@ -143,7 +145,7 @@ void SpeechSynthesis::resume() void SpeechSynthesis::fireEvent(const AtomicString& type, SpeechSynthesisUtterance* utterance, unsigned long charIndex, const String& name) { - if (!executionContext()->activeDOMObjectsAreStopped()) + if (executionContext() && !executionContext()->activeDOMObjectsAreStopped()) utterance->dispatchEvent(SpeechSynthesisEvent::create(type, charIndex, (currentTime() - utterance->startTime()), name)); } @@ -163,7 +165,6 @@ void SpeechSynthesis::handleSpeakingCompleted(SpeechSynthesisUtterance* utteranc // sent an event on an utterance before it got the message that we // canceled it, and we should always report to the user what actually // happened. - fireEvent(errorOccurred ? EventTypeNames::error : EventTypeNames::end, utterance, 0, String()); // Start the next utterance if we just finished one and one was pending. @@ -171,7 +172,7 @@ void SpeechSynthesis::handleSpeakingCompleted(SpeechSynthesisUtterance* utteranc startSpeakingImmediately(); } -void SpeechSynthesis::boundaryEventOccurred(PassRefPtr<PlatformSpeechSynthesisUtterance> utterance, SpeechBoundary boundary, unsigned charIndex) +void SpeechSynthesis::boundaryEventOccurred(PlatformSpeechSynthesisUtterance* utterance, SpeechBoundary boundary, unsigned charIndex) { DEFINE_STATIC_LOCAL(const String, wordBoundaryString, ("word")); DEFINE_STATIC_LOCAL(const String, sentenceBoundaryString, ("sentence")); @@ -188,33 +189,33 @@ void SpeechSynthesis::boundaryEventOccurred(PassRefPtr<PlatformSpeechSynthesisUt } } -void SpeechSynthesis::didStartSpeaking(PassRefPtr<PlatformSpeechSynthesisUtterance> utterance) +void SpeechSynthesis::didStartSpeaking(PlatformSpeechSynthesisUtterance* utterance) { if (utterance->client()) fireEvent(EventTypeNames::start, static_cast<SpeechSynthesisUtterance*>(utterance->client()), 0, String()); } -void SpeechSynthesis::didPauseSpeaking(PassRefPtr<PlatformSpeechSynthesisUtterance> utterance) +void SpeechSynthesis::didPauseSpeaking(PlatformSpeechSynthesisUtterance* utterance) { m_isPaused = true; if (utterance->client()) fireEvent(EventTypeNames::pause, static_cast<SpeechSynthesisUtterance*>(utterance->client()), 0, String()); } -void SpeechSynthesis::didResumeSpeaking(PassRefPtr<PlatformSpeechSynthesisUtterance> utterance) +void SpeechSynthesis::didResumeSpeaking(PlatformSpeechSynthesisUtterance* utterance) { m_isPaused = false; if (utterance->client()) fireEvent(EventTypeNames::resume, static_cast<SpeechSynthesisUtterance*>(utterance->client()), 0, String()); } -void SpeechSynthesis::didFinishSpeaking(PassRefPtr<PlatformSpeechSynthesisUtterance> utterance) +void SpeechSynthesis::didFinishSpeaking(PlatformSpeechSynthesisUtterance* utterance) { if (utterance->client()) handleSpeakingCompleted(static_cast<SpeechSynthesisUtterance*>(utterance->client()), false); } -void SpeechSynthesis::speakingErrorOccurred(PassRefPtr<PlatformSpeechSynthesisUtterance> utterance) +void SpeechSynthesis::speakingErrorOccurred(PlatformSpeechSynthesisUtterance* utterance) { if (utterance->client()) handleSpeakingCompleted(static_cast<SpeechSynthesisUtterance*>(utterance->client()), true); @@ -229,7 +230,16 @@ SpeechSynthesisUtterance* SpeechSynthesis::currentSpeechUtterance() const const AtomicString& SpeechSynthesis::interfaceName() const { - return EventTargetNames::SpeechSynthesisUtterance; + return EventTargetNames::SpeechSynthesis; +} + +void SpeechSynthesis::trace(Visitor* visitor) +{ + visitor->trace(m_platformSpeechSynthesizer); + visitor->trace(m_voiceList); + visitor->trace(m_utteranceQueue); + PlatformSpeechSynthesizerClient::trace(visitor); + EventTargetWithInlineData::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.h index 8e7c60d7517..6ad91a25e7b 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.h @@ -28,26 +28,23 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ContextLifecycleObserver.h" -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" #include "modules/speech/SpeechSynthesisUtterance.h" #include "modules/speech/SpeechSynthesisVoice.h" +#include "platform/heap/Handle.h" #include "platform/speech/PlatformSpeechSynthesisUtterance.h" #include "platform/speech/PlatformSpeechSynthesizer.h" -#include "wtf/Deque.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" namespace WebCore { class ExceptionState; class PlatformSpeechSynthesizerClient; -class SpeechSynthesisVoice; -class SpeechSynthesis : public PlatformSpeechSynthesizerClient, public ScriptWrappable, public RefCounted<SpeechSynthesis>, public ContextLifecycleObserver, public EventTargetWithInlineData { - REFCOUNTED_EVENT_TARGET(SpeechSynthesis); +class SpeechSynthesis FINAL : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<SpeechSynthesis>, public PlatformSpeechSynthesizerClient, public ScriptWrappable, public ContextLifecycleObserver, public EventTargetWithInlineData { + DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<SpeechSynthesis>); + USING_GARBAGE_COLLECTED_MIXIN(SpeechSynthesis); public: - static PassRefPtr<SpeechSynthesis> create(ExecutionContext*); + static SpeechSynthesis* create(ExecutionContext*); bool pending() const; bool speaking() const; @@ -58,26 +55,28 @@ public: void pause(); void resume(); - const Vector<RefPtr<SpeechSynthesisVoice> >& getVoices(); + const HeapVector<Member<SpeechSynthesisVoice> >& getVoices(); // Used in testing to use a mock platform synthesizer - void setPlatformSynthesizer(PassOwnPtr<PlatformSpeechSynthesizer>); + void setPlatformSynthesizer(PlatformSpeechSynthesizer*); DEFINE_ATTRIBUTE_EVENT_LISTENER(voiceschanged); - virtual ExecutionContext* executionContext() const; + virtual ExecutionContext* executionContext() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: explicit SpeechSynthesis(ExecutionContext*); // PlatformSpeechSynthesizerClient override methods. virtual void voicesDidChange() OVERRIDE; - virtual void didStartSpeaking(PassRefPtr<PlatformSpeechSynthesisUtterance>) OVERRIDE; - virtual void didPauseSpeaking(PassRefPtr<PlatformSpeechSynthesisUtterance>) OVERRIDE; - virtual void didResumeSpeaking(PassRefPtr<PlatformSpeechSynthesisUtterance>) OVERRIDE; - virtual void didFinishSpeaking(PassRefPtr<PlatformSpeechSynthesisUtterance>) OVERRIDE; - virtual void speakingErrorOccurred(PassRefPtr<PlatformSpeechSynthesisUtterance>) OVERRIDE; - virtual void boundaryEventOccurred(PassRefPtr<PlatformSpeechSynthesisUtterance>, SpeechBoundary, unsigned charIndex) OVERRIDE; + virtual void didStartSpeaking(PlatformSpeechSynthesisUtterance*) OVERRIDE; + virtual void didPauseSpeaking(PlatformSpeechSynthesisUtterance*) OVERRIDE; + virtual void didResumeSpeaking(PlatformSpeechSynthesisUtterance*) OVERRIDE; + virtual void didFinishSpeaking(PlatformSpeechSynthesisUtterance*) OVERRIDE; + virtual void speakingErrorOccurred(PlatformSpeechSynthesisUtterance*) OVERRIDE; + virtual void boundaryEventOccurred(PlatformSpeechSynthesisUtterance*, SpeechBoundary, unsigned charIndex) OVERRIDE; void startSpeakingImmediately(); void handleSpeakingCompleted(SpeechSynthesisUtterance*, bool errorOccurred); @@ -86,9 +85,9 @@ private: // Returns the utterance at the front of the queue. SpeechSynthesisUtterance* currentSpeechUtterance() const; - OwnPtr<PlatformSpeechSynthesizer> m_platformSpeechSynthesizer; - Vector<RefPtr<SpeechSynthesisVoice> > m_voiceList; - Deque<RefPtr<SpeechSynthesisUtterance> > m_utteranceQueue; + Member<PlatformSpeechSynthesizer> m_platformSpeechSynthesizer; + HeapVector<Member<SpeechSynthesisVoice> > m_voiceList; + HeapDeque<Member<SpeechSynthesisUtterance> > m_utteranceQueue; bool m_isPaused; // EventTarget diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.idl index a88e4968efe..78222925157 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesis.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject, RuntimeEnabled=SpeechSynthesis ] interface SpeechSynthesis : EventTarget { diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisEvent.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisEvent.cpp index 10a58a2363b..2aea33e5a83 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisEvent.cpp @@ -28,14 +28,14 @@ namespace WebCore { -PassRefPtr<SpeechSynthesisEvent> SpeechSynthesisEvent::create() +PassRefPtrWillBeRawPtr<SpeechSynthesisEvent> SpeechSynthesisEvent::create() { - return adoptRef(new SpeechSynthesisEvent()); + return adoptRefWillBeNoop(new SpeechSynthesisEvent); } -PassRefPtr<SpeechSynthesisEvent> SpeechSynthesisEvent::create(const AtomicString& type, unsigned long charIndex, float elapsedTime, const String& name) +PassRefPtrWillBeRawPtr<SpeechSynthesisEvent> SpeechSynthesisEvent::create(const AtomicString& type, unsigned long charIndex, float elapsedTime, const String& name) { - return adoptRef(new SpeechSynthesisEvent(type, charIndex, elapsedTime, name)); + return adoptRefWillBeNoop(new SpeechSynthesisEvent(type, charIndex, elapsedTime, name)); } SpeechSynthesisEvent::SpeechSynthesisEvent() diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisEvent.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisEvent.h index e03c8aa4aec..0634c55f94c 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisEvent.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisEvent.h @@ -26,21 +26,25 @@ #ifndef SpeechSynthesisEvent_h #define SpeechSynthesisEvent_h -#include "core/events/Event.h" -#include "wtf/PassRefPtr.h" +#include "modules/EventModules.h" namespace WebCore { -class SpeechSynthesisEvent : public Event { +class SpeechSynthesisEvent FINAL : public Event { public: - static PassRefPtr<SpeechSynthesisEvent> create(); - static PassRefPtr<SpeechSynthesisEvent> create(const AtomicString& type, unsigned long charIndex, float elapsedTime, const String& name); + static PassRefPtrWillBeRawPtr<SpeechSynthesisEvent> create(); + static PassRefPtrWillBeRawPtr<SpeechSynthesisEvent> create(const AtomicString& type, unsigned long charIndex, float elapsedTime, const String& name); unsigned long charIndex() const { return m_charIndex; } float elapsedTime() const { return m_elapsedTime; } const String& name() const { return m_name; } - virtual const AtomicString& interfaceName() const { return EventNames::SpeechSynthesisEvent; } + virtual const AtomicString& interfaceName() const OVERRIDE { return EventNames::SpeechSynthesisEvent; } + + virtual void trace(Visitor* visitor) OVERRIDE + { + Event::trace(visitor); + } private: SpeechSynthesisEvent(); diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.cpp index 7031c0d90ce..144342edf72 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.cpp @@ -28,9 +28,9 @@ namespace WebCore { -PassRefPtr<SpeechSynthesisUtterance> SpeechSynthesisUtterance::create(ExecutionContext* context, const String& text) +SpeechSynthesisUtterance* SpeechSynthesisUtterance::create(ExecutionContext* context, const String& text) { - return adoptRef(new SpeechSynthesisUtterance(context, text)); + return adoptRefCountedGarbageCollectedWillBeNoop(new SpeechSynthesisUtterance(context, text)); } SpeechSynthesisUtterance::SpeechSynthesisUtterance(ExecutionContext* context, const String& text) @@ -43,7 +43,6 @@ SpeechSynthesisUtterance::SpeechSynthesisUtterance(ExecutionContext* context, co SpeechSynthesisUtterance::~SpeechSynthesisUtterance() { - m_platformUtterance->setClient(0); } ExecutionContext* SpeechSynthesisUtterance::executionContext() const @@ -71,4 +70,11 @@ void SpeechSynthesisUtterance::setVoice(SpeechSynthesisVoice* voice) m_platformUtterance->setVoice(voice->platformVoice()); } +void SpeechSynthesisUtterance::trace(Visitor* visitor) +{ + visitor->trace(m_platformUtterance); + visitor->trace(m_voice); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.h index 555f335a26d..c1eb9817ae0 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.h @@ -28,20 +28,21 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ContextLifecycleObserver.h" -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" #include "modules/speech/SpeechSynthesisVoice.h" +#include "platform/heap/Handle.h" #include "platform/speech/PlatformSpeechSynthesisUtterance.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" namespace WebCore { -class SpeechSynthesisUtterance : public PlatformSpeechSynthesisUtteranceClient, public ScriptWrappable, public RefCounted<SpeechSynthesisUtterance>, public ContextLifecycleObserver, public EventTargetWithInlineData { - REFCOUNTED_EVENT_TARGET(SpeechSynthesisUtterance); +class SpeechSynthesisUtterance FINAL : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<SpeechSynthesisUtterance>, public PlatformSpeechSynthesisUtteranceClient, public ScriptWrappable, public ContextLifecycleObserver, public EventTargetWithInlineData { + DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<SpeechSynthesisUtterance>); + USING_GARBAGE_COLLECTED_MIXIN(SpeechSynthesisUtterance); public: - static PassRefPtr<SpeechSynthesisUtterance> create(ExecutionContext*, const String&); + static SpeechSynthesisUtterance* create(ExecutionContext*, const String&); - ~SpeechSynthesisUtterance(); + virtual ~SpeechSynthesisUtterance(); const String& text() const { return m_platformUtterance->text(); } void setText(const String& text) { m_platformUtterance->setText(text); } @@ -72,14 +73,16 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(mark); DEFINE_ATTRIBUTE_EVENT_LISTENER(boundary); - virtual ExecutionContext* executionContext() const; + virtual ExecutionContext* executionContext() const OVERRIDE; - PlatformSpeechSynthesisUtterance* platformUtterance() const { return m_platformUtterance.get(); } + PlatformSpeechSynthesisUtterance* platformUtterance() const { return m_platformUtterance; } + + virtual void trace(Visitor*) OVERRIDE; private: SpeechSynthesisUtterance(ExecutionContext*, const String&); - RefPtr<PlatformSpeechSynthesisUtterance> m_platformUtterance; - RefPtr<SpeechSynthesisVoice> m_voice; + Member<PlatformSpeechSynthesisUtterance> m_platformUtterance; + Member<SpeechSynthesisVoice> m_voice; // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.idl index 50a0173c29c..490a03a25c2 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisUtterance.idl @@ -24,7 +24,8 @@ */ [ - Constructor([Default=NullString] optional DOMString text), + GarbageCollected, + Constructor(optional DOMString text = null), ConstructorCallWith=ExecutionContext, RuntimeEnabled=SpeechSynthesis, ] interface SpeechSynthesisUtterance : EventTarget { diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.cpp b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.cpp index 4f6658569a8..83ec578d41c 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.cpp @@ -28,15 +28,20 @@ namespace WebCore { -PassRefPtr<SpeechSynthesisVoice> SpeechSynthesisVoice::create(PassRefPtr<PlatformSpeechSynthesisVoice> voice) +SpeechSynthesisVoice* SpeechSynthesisVoice::create(PlatformSpeechSynthesisVoice* voice) { - return adoptRef(new SpeechSynthesisVoice(voice)); + return new SpeechSynthesisVoice(voice); } -SpeechSynthesisVoice::SpeechSynthesisVoice(PassRefPtr<PlatformSpeechSynthesisVoice> voice) +SpeechSynthesisVoice::SpeechSynthesisVoice(PlatformSpeechSynthesisVoice* voice) : m_platformVoice(voice) { ScriptWrappable::init(this); } +void SpeechSynthesisVoice::trace(Visitor* visitor) +{ + visitor->trace(m_platformVoice); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.h b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.h index 21d17960e50..b3bdb20fc8e 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.h +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.h @@ -27,16 +27,15 @@ #define SpeechSynthesisVoice_h #include "bindings/v8/ScriptWrappable.h" +#include "platform/heap/Handle.h" #include "platform/speech/PlatformSpeechSynthesisVoice.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace WebCore { -class SpeechSynthesisVoice FINAL : public ScriptWrappable, public RefCounted<SpeechSynthesisVoice> { +class SpeechSynthesisVoice FINAL : public GarbageCollectedFinalized<SpeechSynthesisVoice>, public ScriptWrappable { public: - static PassRefPtr<SpeechSynthesisVoice> create(PassRefPtr<PlatformSpeechSynthesisVoice>); + static SpeechSynthesisVoice* create(PlatformSpeechSynthesisVoice*); const String& voiceURI() const { return m_platformVoice->voiceURI(); } const String& name() const { return m_platformVoice->name(); } @@ -44,12 +43,14 @@ public: bool localService() const { return m_platformVoice->localService(); } bool isDefault() const { return m_platformVoice->isDefault(); } - PlatformSpeechSynthesisVoice* platformVoice() const { return m_platformVoice.get(); } + PlatformSpeechSynthesisVoice* platformVoice() const { return m_platformVoice; } + + void trace(Visitor*); private: - explicit SpeechSynthesisVoice(PassRefPtr<PlatformSpeechSynthesisVoice>); + explicit SpeechSynthesisVoice(PlatformSpeechSynthesisVoice*); - RefPtr<PlatformSpeechSynthesisVoice> m_platformVoice; + Member<PlatformSpeechSynthesisVoice> m_platformVoice; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.idl b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.idl index a326a8cde95..05d36a57eb9 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/SpeechSynthesisVoice.idl @@ -24,6 +24,7 @@ */ [ + GarbageCollected, NoInterfaceObject, RuntimeEnabled=SpeechSynthesis ] interface SpeechSynthesisVoice { diff --git a/chromium/third_party/WebKit/Source/modules/speech/WindowSpeech.idl b/chromium/third_party/WebKit/Source/modules/speech/WindowSpeech.idl new file mode 100644 index 00000000000..0d331cc70ca --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/speech/WindowSpeech.idl @@ -0,0 +1,14 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + ImplementedAs=DOMWindowSpeech, + RuntimeEnabled=ScriptedSpeech, +] partial interface Window { + attribute SpeechGrammarConstructor webkitSpeechGrammar; + attribute SpeechGrammarListConstructor webkitSpeechGrammarList; + attribute SpeechRecognitionConstructor webkitSpeechRecognition; + attribute SpeechRecognitionErrorConstructor webkitSpeechRecognitionError; + attribute SpeechRecognitionEventConstructor webkitSpeechRecognitionEvent; +}; diff --git a/chromium/third_party/WebKit/Source/modules/speech/WindowSpeechSynthesis.idl b/chromium/third_party/WebKit/Source/modules/speech/WindowSpeechSynthesis.idl index 833797b4e53..1200a2efe39 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/WindowSpeechSynthesis.idl +++ b/chromium/third_party/WebKit/Source/modules/speech/WindowSpeechSynthesis.idl @@ -24,8 +24,8 @@ */ [ + ImplementedAs=DOMWindowSpeechSynthesis, RuntimeEnabled=SpeechSynthesis, - ImplementedAs=DOMWindowSpeechSynthesis ] partial interface Window { readonly attribute SpeechSynthesis speechSynthesis; }; diff --git a/chromium/third_party/WebKit/Source/modules/speech/testing/InternalsSpeechSynthesis.cpp b/chromium/third_party/WebKit/Source/modules/speech/testing/InternalsSpeechSynthesis.cpp index 45385e47729..eab9dccd4d5 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/testing/InternalsSpeechSynthesis.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/testing/InternalsSpeechSynthesis.cpp @@ -39,11 +39,11 @@ namespace WebCore { -void InternalsSpeechSynthesis::enableMockSpeechSynthesizer(Internals* internals, Document* document) +void InternalsSpeechSynthesis::enableMockSpeechSynthesizer(Internals&, Document* document) { - ASSERT(internals && document && document->domWindow()); + ASSERT(document && document->domWindow()); - SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(document->domWindow()); + SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(*document->domWindow()); if (!synthesis) return; diff --git a/chromium/third_party/WebKit/Source/modules/speech/testing/InternalsSpeechSynthesis.h b/chromium/third_party/WebKit/Source/modules/speech/testing/InternalsSpeechSynthesis.h index 984077eea8c..286899aaa70 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/testing/InternalsSpeechSynthesis.h +++ b/chromium/third_party/WebKit/Source/modules/speech/testing/InternalsSpeechSynthesis.h @@ -38,7 +38,7 @@ class Internals; class InternalsSpeechSynthesis { public: - static void enableMockSpeechSynthesizer(Internals*, Document*); + static void enableMockSpeechSynthesizer(Internals&, Document*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/testing/PlatformSpeechSynthesizerMock.cpp b/chromium/third_party/WebKit/Source/modules/speech/testing/PlatformSpeechSynthesizerMock.cpp index b879c84ac29..a5e36e50636 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/testing/PlatformSpeechSynthesizerMock.cpp +++ b/chromium/third_party/WebKit/Source/modules/speech/testing/PlatformSpeechSynthesizerMock.cpp @@ -31,30 +31,39 @@ namespace WebCore { -PassOwnPtr<PlatformSpeechSynthesizerMock> PlatformSpeechSynthesizerMock::create(PlatformSpeechSynthesizerClient* client) +PlatformSpeechSynthesizerMock* PlatformSpeechSynthesizerMock::create(PlatformSpeechSynthesizerClient* client) { - OwnPtr<PlatformSpeechSynthesizerMock> synthesizer = adoptPtr(new PlatformSpeechSynthesizerMock(client)); + PlatformSpeechSynthesizerMock* synthesizer = new PlatformSpeechSynthesizerMock(client); synthesizer->initializeVoiceList(); client->voicesDidChange(); - return synthesizer.release(); + return synthesizer; } PlatformSpeechSynthesizerMock::PlatformSpeechSynthesizerMock(PlatformSpeechSynthesizerClient* client) : PlatformSpeechSynthesizer(client) , m_speakingFinishedTimer(this, &PlatformSpeechSynthesizerMock::speakingFinished) + , m_speakingErrorOccurredTimer(this, &PlatformSpeechSynthesizerMock::speakingErrorOccurred) { } PlatformSpeechSynthesizerMock::~PlatformSpeechSynthesizerMock() { m_speakingFinishedTimer.stop(); + m_speakingErrorOccurredTimer.stop(); } void PlatformSpeechSynthesizerMock::speakingFinished(Timer<PlatformSpeechSynthesizerMock>*) { ASSERT(m_utterance.get()); client()->didFinishSpeaking(m_utterance); - m_utterance = 0; + m_utterance = nullptr; +} + +void PlatformSpeechSynthesizerMock::speakingErrorOccurred(Timer<PlatformSpeechSynthesizerMock>*) +{ + ASSERT(m_utterance.get()); + client()->speakingErrorOccurred(m_utterance); + m_utterance = nullptr; } void PlatformSpeechSynthesizerMock::initializeVoiceList() @@ -65,7 +74,7 @@ void PlatformSpeechSynthesizerMock::initializeVoiceList() m_voiceList.append(PlatformSpeechSynthesisVoice::create(String("mock.voice.logan"), String("logan"), String("fr-CA"), true, true)); } -void PlatformSpeechSynthesizerMock::speak(PassRefPtr<PlatformSpeechSynthesisUtterance> utterance) +void PlatformSpeechSynthesizerMock::speak(PlatformSpeechSynthesisUtterance* utterance) { ASSERT(!m_utterance); m_utterance = utterance; @@ -76,7 +85,7 @@ void PlatformSpeechSynthesizerMock::speak(PassRefPtr<PlatformSpeechSynthesisUtte client()->boundaryEventOccurred(m_utterance, SpeechSentenceBoundary, m_utterance->text().length()); // Give the fake speech job some time so that pause and other functions have time to be called. - m_speakingFinishedTimer.startOneShot(.1); + m_speakingFinishedTimer.startOneShot(.1, FROM_HERE); } void PlatformSpeechSynthesizerMock::cancel() @@ -85,8 +94,7 @@ void PlatformSpeechSynthesizerMock::cancel() return; m_speakingFinishedTimer.stop(); - client()->speakingErrorOccurred(m_utterance); - m_utterance = 0; + m_speakingErrorOccurredTimer.startOneShot(.1, FROM_HERE); } void PlatformSpeechSynthesizerMock::pause() @@ -99,5 +107,10 @@ void PlatformSpeechSynthesizerMock::resume() client()->didResumeSpeaking(m_utterance); } +void PlatformSpeechSynthesizerMock::trace(Visitor* visitor) +{ + visitor->trace(m_utterance); + PlatformSpeechSynthesizer::trace(visitor); +} } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/speech/testing/PlatformSpeechSynthesizerMock.h b/chromium/third_party/WebKit/Source/modules/speech/testing/PlatformSpeechSynthesizerMock.h index 3378c835b45..ad37336b90b 100644 --- a/chromium/third_party/WebKit/Source/modules/speech/testing/PlatformSpeechSynthesizerMock.h +++ b/chromium/third_party/WebKit/Source/modules/speech/testing/PlatformSpeechSynthesizerMock.h @@ -27,28 +27,32 @@ #define PlatformSpeechSynthesizerMock_h #include "platform/Timer.h" +#include "platform/heap/Handle.h" #include "platform/speech/PlatformSpeechSynthesizer.h" -#include "wtf/PassOwnPtr.h" namespace WebCore { -class PlatformSpeechSynthesizerMock : public PlatformSpeechSynthesizer { +class PlatformSpeechSynthesizerMock FINAL : public PlatformSpeechSynthesizer { public: - static PassOwnPtr<PlatformSpeechSynthesizerMock> create(PlatformSpeechSynthesizerClient*); + static PlatformSpeechSynthesizerMock* create(PlatformSpeechSynthesizerClient*); virtual ~PlatformSpeechSynthesizerMock(); - virtual void speak(PassRefPtr<PlatformSpeechSynthesisUtterance>); - virtual void pause(); - virtual void resume(); - virtual void cancel(); + virtual void speak(PlatformSpeechSynthesisUtterance*) OVERRIDE; + virtual void pause() OVERRIDE; + virtual void resume() OVERRIDE; + virtual void cancel() OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: explicit PlatformSpeechSynthesizerMock(PlatformSpeechSynthesizerClient*); - virtual void initializeVoiceList(); + virtual void initializeVoiceList() OVERRIDE; void speakingFinished(Timer<PlatformSpeechSynthesizerMock>*); + void speakingErrorOccurred(Timer<PlatformSpeechSynthesizerMock>*); Timer<PlatformSpeechSynthesizerMock> m_speakingFinishedTimer; - RefPtr<PlatformSpeechSynthesisUtterance> m_utterance; + Timer<PlatformSpeechSynthesizerMock> m_speakingErrorOccurredTimer; + Member<PlatformSpeechSynthesisUtterance> m_utterance; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp b/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp index 3e2fcff4a6b..6a8b5d31b8c 100644 --- a/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp +++ b/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp @@ -20,8 +20,8 @@ #include "config.h" #include "modules/vibration/NavigatorVibration.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" -#include "core/frame/Frame.h" #include "core/page/PageVisibilityState.h" #include "public/platform/Platform.h" #include "public/platform/WebVibration.h" @@ -31,8 +31,8 @@ namespace WebCore { // Maximum number of entries in a vibration pattern. const unsigned kVibrationPatternLengthMax = 99; -NavigatorVibration::NavigatorVibration(Page* page) - : PageLifecycleObserver(page) +NavigatorVibration::NavigatorVibration(Page& page) + : PageLifecycleObserver(&page) , m_timerStart(this, &NavigatorVibration::timerStartFired) , m_timerStop(this, &NavigatorVibration::timerStopFired) , m_isVibrating(false) @@ -83,7 +83,7 @@ bool NavigatorVibration::vibrate(const VibrationPattern& pattern) return true; } - m_timerStart.startOneShot(0); + m_timerStart.startOneShot(0, FROM_HERE); m_isVibrating = true; return true; } @@ -105,7 +105,7 @@ void NavigatorVibration::timerStartFired(Timer<NavigatorVibration>* timer) if (m_pattern.size()) { m_isVibrating = true; blink::Platform::current()->vibrate(m_pattern[0]); - m_timerStop.startOneShot(m_pattern[0] / 1000.0); + m_timerStop.startOneShot(m_pattern[0] / 1000.0, FROM_HERE); m_pattern.remove(0); } } @@ -118,7 +118,7 @@ void NavigatorVibration::timerStopFired(Timer<NavigatorVibration>* timer) m_isVibrating = false; if (m_pattern.size()) { - m_timerStart.startOneShot(m_pattern[0] / 1000.0); + m_timerStart.startOneShot(m_pattern[0] / 1000.0, FROM_HERE); m_pattern.remove(0); } } @@ -129,40 +129,43 @@ void NavigatorVibration::pageVisibilityChanged() cancelVibration(); } -void NavigatorVibration::didCommitLoad(Frame* frame) +void NavigatorVibration::didCommitLoad(LocalFrame* frame) { // A new load has been committed, which means the current page will be // unloaded. Cancel all running vibrations. cancelVibration(); } -bool NavigatorVibration::vibrate(Navigator* navigator, unsigned time) +bool NavigatorVibration::vibrate(Navigator& navigator, unsigned time) { VibrationPattern pattern; pattern.append(time); return NavigatorVibration::vibrate(navigator, pattern); } -bool NavigatorVibration::vibrate(Navigator* navigator, const VibrationPattern& pattern) +bool NavigatorVibration::vibrate(Navigator& navigator, const VibrationPattern& pattern) { - Page* page = navigator->frame()->page(); + if (!navigator.frame()) + return false; + + Page* page = navigator.frame()->page(); if (!page) return false; if (page->visibilityState() != PageVisibilityStateVisible) return false; - return NavigatorVibration::from(page)->vibrate(pattern); + return NavigatorVibration::from(*page).vibrate(pattern); } -NavigatorVibration* NavigatorVibration::from(Page* page) +NavigatorVibration& NavigatorVibration::from(Page& page) { - NavigatorVibration* navigatorVibration = static_cast<NavigatorVibration*>(Supplement<Page>::from(page, supplementName())); + NavigatorVibration* navigatorVibration = static_cast<NavigatorVibration*>(WillBeHeapSupplement<Page>::from(page, supplementName())); if (!navigatorVibration) { navigatorVibration = new NavigatorVibration(page); - Supplement<Page>::provideTo(page, supplementName(), adoptPtr(navigatorVibration)); + WillBeHeapSupplement<Page>::provideTo(page, supplementName(), adoptPtrWillBeNoop(navigatorVibration)); } - return navigatorVibration; + return *navigatorVibration; } const char* NavigatorVibration::supplementName() diff --git a/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h b/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h index d1243e7b896..42b9454bc16 100644 --- a/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h +++ b/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h @@ -28,12 +28,14 @@ namespace WebCore { -class Frame; +class LocalFrame; class Navigator; -class NavigatorVibration - : public Supplement<Page> +class NavigatorVibration FINAL + : public NoBaseWillBeGarbageCollectedFinalized<NavigatorVibration> + , public WillBeHeapSupplement<Page> , public PageLifecycleObserver { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorVibration); public: typedef Vector<unsigned> VibrationPattern; @@ -46,18 +48,20 @@ public: // Inherited from PageLifecycleObserver virtual void pageVisibilityChanged() OVERRIDE; - virtual void didCommitLoad(Frame*) OVERRIDE; + virtual void didCommitLoad(LocalFrame*) OVERRIDE; - static bool vibrate(Navigator*, unsigned time); - static bool vibrate(Navigator*, const VibrationPattern&); - static NavigatorVibration* from(Page*); + static bool vibrate(Navigator&, unsigned time); + static bool vibrate(Navigator&, const VibrationPattern&); + static NavigatorVibration& from(Page&); bool isVibrating() const { return m_isVibrating; } VibrationPattern pattern() const { return m_pattern; } + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Page>::trace(visitor); } + private: - explicit NavigatorVibration(Page*); + explicit NavigatorVibration(Page&); static const char* supplementName(); Timer<NavigatorVibration> m_timerStart; diff --git a/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.idl b/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.idl index 3307c6a77c1..8ed66244a67 100644 --- a/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.idl +++ b/chromium/third_party/WebKit/Source/modules/vibration/NavigatorVibration.idl @@ -17,12 +17,12 @@ * Boston, MA 02110-1301, USA. */ -[ - RuntimeEnabled=Vibration -] partial interface Navigator { +// http://dev.w3.org/2009/dap/vibration/#idl-def-Navigator + +partial interface Navigator { + // FIXME: should be union type http://crbug.com/240176 // FIXME: The contents of the pattern argument should be clamped. // See https://code.google.com/p/chromium/issues/detail?id=310138 + boolean vibrate([Clamp] unsigned long pattern); boolean vibrate(sequence<unsigned long> pattern); - boolean vibrate([Clamp] unsigned long time); }; - diff --git a/chromium/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp b/chromium/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp index a22bb0117b2..01ce84151d5 100644 --- a/chromium/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp +++ b/chromium/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp @@ -37,16 +37,16 @@ namespace WebCore { -bool InternalsVibration::isVibrating(Internals* internals, Document* document) +bool InternalsVibration::isVibrating(Internals&, Document* document) { - ASSERT(internals && document && document->page()); - return NavigatorVibration::from(document->page())->isVibrating(); + ASSERT(document && document->page()); + return NavigatorVibration::from(*document->page()).isVibrating(); } -Vector<unsigned> InternalsVibration::pendingVibrationPattern(Internals* internals, Document* document) +Vector<unsigned> InternalsVibration::pendingVibrationPattern(Internals&, Document* document) { - ASSERT(internals && document && document->page()); - return NavigatorVibration::from(document->page())->pattern(); + ASSERT(document && document->page()); + return NavigatorVibration::from(*document->page()).pattern(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.h b/chromium/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.h index 4f0cf3e84ca..6b6b622afba 100644 --- a/chromium/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.h +++ b/chromium/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.h @@ -40,8 +40,8 @@ class Internals; class InternalsVibration { public: - static bool isVibrating(Internals*, Document*); - static Vector<unsigned> pendingVibrationPattern(Internals*, Document*); + static bool isVibrating(Internals&, Document*); + static Vector<unsigned> pendingVibrationPattern(Internals&, Document*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp index 83e6dba02ef..53cdd441f57 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp @@ -69,70 +69,47 @@ void AnalyserNode::process(size_t framesToProcess) outputBus->copyFrom(*inputBus); } -void AnalyserNode::reset() -{ - m_analyser.reset(); -} - void AnalyserNode::setFftSize(unsigned size, ExceptionState& exceptionState) { if (!m_analyser.setFftSize(size)) { exceptionState.throwDOMException( IndexSizeError, - ExceptionMessages::failedToSet( - "fftSize", - "AnalyserNode", - "FFT size (" + String::number(size) - + ") must be a power of two between " - + String::number(RealtimeAnalyser::MinFFTSize) + " and " - + String::number(RealtimeAnalyser::MaxFFTSize) + ", inclusive")); + (size < RealtimeAnalyser::MinFFTSize || size > RealtimeAnalyser::MaxFFTSize) ? + ExceptionMessages::indexOutsideRange("FFT size", size, RealtimeAnalyser::MinFFTSize, ExceptionMessages::InclusiveBound, RealtimeAnalyser::MaxFFTSize, ExceptionMessages::InclusiveBound) + : ("The value provided (" + String::number(size) + ") is not a power of two.")); } } -void AnalyserNode::setMinDecibels(float k, ExceptionState& exceptionState) +void AnalyserNode::setMinDecibels(double k, ExceptionState& exceptionState) { - if (k <= maxDecibels()) { + if (k < maxDecibels()) { m_analyser.setMinDecibels(k); } else { exceptionState.throwDOMException( IndexSizeError, - ExceptionMessages::failedToSet( - "minDecibels", - "AnalyserNode", - "minDecibels (" + String::number(k) - + ") must be less than or equal maxDecibels (" + String::number(maxDecibels()) - + ").")); + ExceptionMessages::indexExceedsMaximumBound("minDecibels", k, maxDecibels())); } } -void AnalyserNode::setMaxDecibels(float k, ExceptionState& exceptionState) +void AnalyserNode::setMaxDecibels(double k, ExceptionState& exceptionState) { - if (k >= minDecibels()) { + if (k > minDecibels()) { m_analyser.setMaxDecibels(k); } else { exceptionState.throwDOMException( IndexSizeError, - ExceptionMessages::failedToSet( - "maxDecibels", - "AnalyserNode", - "maxDecibels (" + String::number(k) - + ") must be greater than or equal minDecibels (" + String::number(minDecibels()) - + ").")); + ExceptionMessages::indexExceedsMinimumBound("maxDecibels", k, minDecibels())); } } -void AnalyserNode::setSmoothingTimeConstant(float k, ExceptionState& exceptionState) +void AnalyserNode::setSmoothingTimeConstant(double k, ExceptionState& exceptionState) { if (k >= 0 && k <= 1) { m_analyser.setSmoothingTimeConstant(k); } else { exceptionState.throwDOMException( IndexSizeError, - ExceptionMessages::failedToSet( - "smoothingTimeConstant", - "AnalyserNode", - "smoothing value (" + String::number(k) - + ") must be between 0 and 1, inclusive.")); + ExceptionMessages::indexOutsideRange("smoothing value", k, 0.0, ExceptionMessages::InclusiveBound, 1.0, ExceptionMessages::InclusiveBound)); } } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h index db2dacb7c83..fba97158f67 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h @@ -33,18 +33,17 @@ namespace WebCore { class ExceptionState; -class AnalyserNode : public AudioBasicInspectorNode { +class AnalyserNode FINAL : public AudioBasicInspectorNode { public: - static PassRefPtr<AnalyserNode> create(AudioContext* context, float sampleRate) + static PassRefPtrWillBeRawPtr<AnalyserNode> create(AudioContext* context, float sampleRate) { - return adoptRef(new AnalyserNode(context, sampleRate)); + return adoptRefWillBeNoop(new AnalyserNode(context, sampleRate)); } virtual ~AnalyserNode(); // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); + virtual void process(size_t framesToProcess) OVERRIDE; // Javascript bindings unsigned fftSize() const { return m_analyser.fftSize(); } @@ -52,19 +51,19 @@ public: unsigned frequencyBinCount() const { return m_analyser.frequencyBinCount(); } - void setMinDecibels(float k, ExceptionState&); - float minDecibels() const { return m_analyser.minDecibels(); } + void setMinDecibels(double k, ExceptionState&); + double minDecibels() const { return m_analyser.minDecibels(); } - void setMaxDecibels(float k, ExceptionState&); - float maxDecibels() const { return m_analyser.maxDecibels(); } + void setMaxDecibels(double k, ExceptionState&); + double maxDecibels() const { return m_analyser.maxDecibels(); } - void setSmoothingTimeConstant(float k, ExceptionState&); - float smoothingTimeConstant() const { return m_analyser.smoothingTimeConstant(); } + void setSmoothingTimeConstant(double k, ExceptionState&); + double smoothingTimeConstant() const { return m_analyser.smoothingTimeConstant(); } void getFloatFrequencyData(Float32Array* array) { m_analyser.getFloatFrequencyData(array); } void getByteFrequencyData(Uint8Array* array) { m_analyser.getByteFrequencyData(array); } + void getFloatTimeDomainData(Float32Array* array) { m_analyser.getFloatTimeDomainData(array); } void getByteTimeDomainData(Uint8Array* array) { m_analyser.getByteTimeDomainData(array); } - private: virtual double tailTime() const OVERRIDE { return 0; } virtual double latencyTime() const OVERRIDE { return 0; } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.idl b/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.idl index f3add662997..4de5f299edc 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AnalyserNode.idl @@ -29,11 +29,11 @@ readonly attribute unsigned long frequencyBinCount; // minDecibels / maxDecibels represent the range to scale the FFT analysis data for conversion to unsigned byte values. - [RaisesException=Setter] attribute float minDecibels; - [RaisesException=Setter] attribute float maxDecibels; + [RaisesException=Setter] attribute double minDecibels; + [RaisesException=Setter] attribute double maxDecibels; // A value from 0.0 -> 1.0 where 0.0 represents no time averaging with the last analysis frame. - [RaisesException=Setter] attribute float smoothingTimeConstant; + [RaisesException=Setter] attribute double smoothingTimeConstant; // Copies the current frequency data into the passed array. // If the array has fewer elements than the frequencyBinCount, the excess elements will be dropped. @@ -41,5 +41,6 @@ void getByteFrequencyData(Uint8Array array); // Real-time waveform data + void getFloatTimeDomainData(Float32Array array); void getByteTimeDomainData(Uint8Array array); }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp index f1ea34f4c71..db7cedaaf62 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp @@ -31,6 +31,8 @@ #include "modules/webaudio/AudioBuffer.h" #include "modules/webaudio/AudioBufferCallback.h" #include "platform/Task.h" +#include "platform/audio/AudioBus.h" +#include "platform/audio/AudioFileReader.h" #include "public/platform/Platform.h" #include "wtf/ArrayBuffer.h" #include "wtf/MainThread.h" @@ -63,26 +65,26 @@ void AsyncAudioDecoder::decodeAsync(ArrayBuffer* audioData, float sampleRate, Pa void AsyncAudioDecoder::decode(ArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback) { - // Do the actual decoding and invoke the callback. - RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(audioData->data(), audioData->byteLength(), false, sampleRate); + RefPtr<AudioBus> bus = createBusFromInMemoryAudioFile(audioData->data(), audioData->byteLength(), false, sampleRate); // Decoding is finished, but we need to do the callbacks on the main thread. // The leaked reference to audioBuffer is picked up in notifyComplete. - callOnMainThread(WTF::bind(&AsyncAudioDecoder::notifyComplete, audioData, successCallback, errorCallback, audioBuffer.release().leakRef())); + callOnMainThread(WTF::bind(&AsyncAudioDecoder::notifyComplete, audioData, successCallback, errorCallback, bus.release().leakRef())); } -void AsyncAudioDecoder::notifyComplete(ArrayBuffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, AudioBuffer* audioBuffer) +void AsyncAudioDecoder::notifyComplete(ArrayBuffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, AudioBus* audioBus) { // Adopt references, so everything gets correctly dereffed. RefPtr<ArrayBuffer> audioDataRef = adoptRef(audioData); OwnPtr<AudioBufferCallback> successCallbackPtr = adoptPtr(successCallback); OwnPtr<AudioBufferCallback> errorCallbackPtr = adoptPtr(errorCallback); - RefPtr<AudioBuffer> audioBufferRef = adoptRef(audioBuffer); + RefPtr<AudioBus> audioBusRef = adoptRef(audioBus); - if (audioBuffer && successCallback) - successCallback->handleEvent(audioBuffer); + RefPtrWillBeRawPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioBus(audioBus); + if (audioBuffer.get() && successCallback) + successCallback->handleEvent(audioBuffer.get()); else if (errorCallback) - errorCallback->handleEvent(audioBuffer); + errorCallback->handleEvent(audioBuffer.get()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h b/chromium/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h index a615787bd72..7f774564635 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h @@ -25,6 +25,7 @@ #ifndef AsyncAudioDecoder_h #define AsyncAudioDecoder_h +#include "platform/heap/Handle.h" #include "public/platform/WebThread.h" #include "wtf/Forward.h" #include "wtf/OwnPtr.h" @@ -33,6 +34,7 @@ namespace WebCore { class AudioBuffer; class AudioBufferCallback; +class AudioBus; // AsyncAudioDecoder asynchronously decodes audio file data from an ArrayBuffer in a worker thread. // Upon successful decoding, a completion callback will be invoked with the decoded PCM data in an AudioBuffer. @@ -47,8 +49,9 @@ public: void decodeAsync(ArrayBuffer* audioData, float sampleRate, PassOwnPtr<AudioBufferCallback> successCallback, PassOwnPtr<AudioBufferCallback> errorCallback); private: + PassRefPtrWillBeRawPtr<AudioBuffer> createAudioBufferFromAudioBus(AudioBus*); static void decode(ArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback); - static void notifyComplete(ArrayBuffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, AudioBuffer*); + static void notifyComplete(ArrayBuffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, AudioBus*); OwnPtr<blink::WebThread> m_thread; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.h index 44d03cb103f..1e7cf824eb7 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.h @@ -39,10 +39,10 @@ public: AudioBasicInspectorNode(AudioContext*, float sampleRate, unsigned outputChannelCount); // AudioNode - virtual void pullInputs(size_t framesToProcess); - virtual void connect(AudioNode*, unsigned outputIndex, unsigned inputIndex, ExceptionState&); - virtual void disconnect(unsigned outputIndex, ExceptionState&); - virtual void checkNumberOfChannelsForInput(AudioNodeInput*); + virtual void pullInputs(size_t framesToProcess) OVERRIDE FINAL; + virtual void connect(AudioNode*, unsigned outputIndex, unsigned inputIndex, ExceptionState&) OVERRIDE FINAL; + virtual void disconnect(unsigned outputIndex, ExceptionState&) OVERRIDE FINAL; + virtual void checkNumberOfChannelsForInput(AudioNodeInput*) OVERRIDE FINAL; private: void updatePullStatus(); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorNode.cpp index 6428bae8899..8a5330e2f64 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorNode.cpp @@ -91,12 +91,6 @@ void AudioBasicProcessorNode::pullInputs(size_t framesToProcess) input(0)->pull(output(0)->bus(), framesToProcess); } -void AudioBasicProcessorNode::reset() -{ - if (processor()) - processor()->reset(); -} - // As soon as we know the channel count of our input, we can lazily initialize. // Sometimes this may be called more than once with different channel counts, in which case we must safely // uninitialize and then re-initialize with the new channel count. diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorNode.h index eb94cac2221..ad37fb6e3bd 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorNode.h @@ -42,21 +42,20 @@ public: AudioBasicProcessorNode(AudioContext*, float sampleRate); // AudioNode - virtual void process(size_t framesToProcess); - virtual void pullInputs(size_t framesToProcess); - virtual void reset(); - virtual void initialize(); - virtual void uninitialize(); + virtual void process(size_t framesToProcess) OVERRIDE FINAL; + virtual void pullInputs(size_t framesToProcess) OVERRIDE FINAL; + virtual void initialize() OVERRIDE FINAL; + virtual void uninitialize() OVERRIDE FINAL; // Called in the main thread when the number of channels for the input may have changed. - virtual void checkNumberOfChannelsForInput(AudioNodeInput*); + virtual void checkNumberOfChannelsForInput(AudioNodeInput*) OVERRIDE FINAL; // Returns the number of channels for both the input and the output. unsigned numberOfChannels(); protected: - virtual double tailTime() const OVERRIDE; - virtual double latencyTime() const OVERRIDE; + virtual double tailTime() const OVERRIDE FINAL; + virtual double latencyTime() const OVERRIDE FINAL; AudioProcessor* processor() { return m_processor.get(); } OwnPtr<AudioProcessor> m_processor; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp index b520512e054..d473aae6cc4 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp @@ -32,6 +32,7 @@ #include "modules/webaudio/AudioBuffer.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" #include "platform/audio/AudioBus.h" @@ -42,36 +43,101 @@ namespace WebCore { float AudioBuffer::minAllowedSampleRate() { - return 22050; + // crbug.com/344375 + return 3000; } float AudioBuffer::maxAllowedSampleRate() { - return 96000; + // Windows can support up to this rate. + return 192000; } -PassRefPtr<AudioBuffer> AudioBuffer::create(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) +PassRefPtrWillBeRawPtr<AudioBuffer> AudioBuffer::create(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) { - if (sampleRate < minAllowedSampleRate() || sampleRate > maxAllowedSampleRate() || numberOfChannels > AudioContext::maxNumberOfChannels() || !numberOfFrames) - return 0; + if (sampleRate < minAllowedSampleRate() || sampleRate > maxAllowedSampleRate() || numberOfChannels > AudioContext::maxNumberOfChannels() || !numberOfChannels || !numberOfFrames) + return nullptr; - RefPtr<AudioBuffer> buffer = adoptRef(new AudioBuffer(numberOfChannels, numberOfFrames, sampleRate)); + RefPtrWillBeRawPtr<AudioBuffer> buffer = adoptRefWillBeNoop(new AudioBuffer(numberOfChannels, numberOfFrames, sampleRate)); if (!buffer->createdSuccessfully(numberOfChannels)) - return 0; + return nullptr; return buffer; } -PassRefPtr<AudioBuffer> AudioBuffer::createFromAudioFileData(const void* data, size_t dataSize, bool mixToMono, float sampleRate) +PassRefPtrWillBeRawPtr<AudioBuffer> AudioBuffer::create(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) +{ + if (!numberOfChannels || numberOfChannels > AudioContext::maxNumberOfChannels()) { + exceptionState.throwDOMException( + NotSupportedError, + ExceptionMessages::indexOutsideRange( + "number of channels", + numberOfChannels, + 1u, + ExceptionMessages::InclusiveBound, + AudioContext::maxNumberOfChannels(), + ExceptionMessages::InclusiveBound)); + return nullptr; + } + + if (sampleRate < AudioBuffer::minAllowedSampleRate() || sampleRate > AudioBuffer::maxAllowedSampleRate()) { + exceptionState.throwDOMException( + NotSupportedError, + ExceptionMessages::indexOutsideRange( + "sample rate", + sampleRate, + AudioBuffer::minAllowedSampleRate(), + ExceptionMessages::InclusiveBound, + AudioBuffer::maxAllowedSampleRate(), + ExceptionMessages::InclusiveBound)); + return nullptr; + } + + if (!numberOfFrames) { + exceptionState.throwDOMException( + NotSupportedError, + ExceptionMessages::indexExceedsMinimumBound( + "number of frames", + numberOfFrames, + static_cast<size_t>(0))); + return nullptr; + } + + RefPtrWillBeRawPtr<AudioBuffer> audioBuffer = create(numberOfChannels, numberOfFrames, sampleRate); + + if (!audioBuffer.get()) { + exceptionState.throwDOMException( + NotSupportedError, + "createBuffer(" + + String::number(numberOfChannels) + ", " + + String::number(numberOfFrames) + ", " + + String::number(sampleRate) + + ") failed."); + } + + return audioBuffer; +} + +PassRefPtrWillBeRawPtr<AudioBuffer> AudioBuffer::createFromAudioFileData(const void* data, size_t dataSize, bool mixToMono, float sampleRate) { RefPtr<AudioBus> bus = createBusFromInMemoryAudioFile(data, dataSize, mixToMono, sampleRate); if (bus.get()) { - RefPtr<AudioBuffer> buffer = adoptRef(new AudioBuffer(bus.get())); + RefPtrWillBeRawPtr<AudioBuffer> buffer = adoptRefWillBeNoop(new AudioBuffer(bus.get())); if (buffer->createdSuccessfully(bus->numberOfChannels())) return buffer; } - return 0; + return nullptr; +} + +PassRefPtrWillBeRawPtr<AudioBuffer> AudioBuffer::createFromAudioBus(AudioBus* bus) +{ + if (!bus) + return nullptr; + RefPtrWillBeRawPtr<AudioBuffer> buffer = adoptRefWillBeNoop(new AudioBuffer(bus)); + if (buffer->createdSuccessfully(bus->numberOfChannels())) + return buffer; + return nullptr; } bool AudioBuffer::createdSuccessfully(unsigned desiredNumberOfChannels) const @@ -80,8 +146,7 @@ bool AudioBuffer::createdSuccessfully(unsigned desiredNumberOfChannels) const } AudioBuffer::AudioBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) - : m_gain(1.0) - , m_sampleRate(sampleRate) + : m_sampleRate(sampleRate) , m_length(numberOfFrames) { ScriptWrappable::init(this); @@ -101,8 +166,7 @@ AudioBuffer::AudioBuffer(unsigned numberOfChannels, size_t numberOfFrames, float } AudioBuffer::AudioBuffer(AudioBus* bus) - : m_gain(1.0) - , m_sampleRate(bus->sampleRate()) + : m_sampleRate(bus->sampleRate()) , m_length(bus->length()) { ScriptWrappable::init(this); @@ -122,16 +186,11 @@ AudioBuffer::AudioBuffer(AudioBus* bus) } } -void AudioBuffer::releaseMemory() -{ - m_channels.clear(); -} - PassRefPtr<Float32Array> AudioBuffer::getChannelData(unsigned channelIndex, ExceptionState& exceptionState) { if (channelIndex >= m_channels.size()) { exceptionState.throwDOMException(IndexSizeError, "channel index (" + String::number(channelIndex) + ") exceeds number of channels (" + String::number(m_channels.size()) + ")"); - return 0; + return nullptr; } Float32Array* channelData = m_channels[channelIndex].get(); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.h index 8ffb2aceb11..cd0f87958bb 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.h @@ -41,16 +41,19 @@ namespace WebCore { class AudioBus; class ExceptionState; -class AudioBuffer : public ScriptWrappable, public RefCounted<AudioBuffer> { +class AudioBuffer : public RefCountedWillBeGarbageCollectedFinalized<AudioBuffer>, public ScriptWrappable { public: - static PassRefPtr<AudioBuffer> create(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate); + static PassRefPtrWillBeRawPtr<AudioBuffer> create(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate); + static PassRefPtrWillBeRawPtr<AudioBuffer> create(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&); // Returns 0 if data is not a valid audio file. - static PassRefPtr<AudioBuffer> createFromAudioFileData(const void* data, size_t dataSize, bool mixToMono, float sampleRate); + static PassRefPtrWillBeRawPtr<AudioBuffer> createFromAudioFileData(const void* data, size_t dataSize, bool mixToMono, float sampleRate); + + static PassRefPtrWillBeRawPtr<AudioBuffer> createFromAudioBus(AudioBus*); // Format size_t length() const { return m_length; } - double duration() const { return length() / sampleRate(); } + double duration() const { return length() / static_cast<double>(sampleRate()); } float sampleRate() const { return m_sampleRate; } // Channel data access @@ -59,23 +62,16 @@ public: Float32Array* getChannelData(unsigned channelIndex); void zero(); - // Scalar gain - double gain() const { return m_gain; } - void setGain(double gain) { m_gain = gain; } - - // Because an AudioBuffer has a JavaScript wrapper, which will be garbage collected, it may take awhile for this object to be deleted. - // releaseMemory() can be called when the AudioContext goes away, so we can release the memory earlier than when the garbage collection happens. - // Careful! Only call this when the page unloads, after the AudioContext is no longer processing. - void releaseMemory(); - static float minAllowedSampleRate(); static float maxAllowedSampleRate(); + + void trace(Visitor*) { } + protected: AudioBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate); explicit AudioBuffer(AudioBus*); bool createdSuccessfully(unsigned desiredNumberOfChannels) const; - double m_gain; // scalar gain float m_sampleRate; size_t m_length; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.idl b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.idl index 19f66a5f2a0..7ec7c60bb4c 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBuffer.idl @@ -27,14 +27,13 @@ */ [ + WillBeGarbageCollected, Conditional=WEB_AUDIO ] interface AudioBuffer { readonly attribute long length; // in sample-frames - readonly attribute float duration; // in seconds + readonly attribute double duration; // in seconds readonly attribute float sampleRate; // in sample-frames per second - attribute float gain; // linear gain (default 1.0) - // Channel access readonly attribute unsigned long numberOfChannels; [RaisesException] Float32Array getChannelData(unsigned long channelIndex); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp index 07a63a57bc1..c2dbc32bf24 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp @@ -30,7 +30,6 @@ #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "core/page/PageConsole.h" #include "platform/audio/AudioUtilities.h" #include "modules/webaudio/AudioContext.h" #include "modules/webaudio/AudioNodeOutput.h" @@ -50,14 +49,14 @@ const double DefaultGrainDuration = 0.020; // 20ms // to minimize linear interpolation aliasing. const double MaxRate = 1024; -PassRefPtr<AudioBufferSourceNode> AudioBufferSourceNode::create(AudioContext* context, float sampleRate) +PassRefPtrWillBeRawPtr<AudioBufferSourceNode> AudioBufferSourceNode::create(AudioContext* context, float sampleRate) { - return adoptRef(new AudioBufferSourceNode(context, sampleRate)); + return adoptRefWillBeNoop(new AudioBufferSourceNode(context, sampleRate)); } AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, float sampleRate) : AudioScheduledSourceNode(context, sampleRate) - , m_buffer(0) + , m_buffer(nullptr) , m_isLooping(false) , m_loopStart(0) , m_loopEnd(0) @@ -65,13 +64,11 @@ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, float sample , m_isGrain(false) , m_grainOffset(0.0) , m_grainDuration(DefaultGrainDuration) - , m_lastGain(1.0) , m_pannerNode(0) { ScriptWrappable::init(this); setNodeType(NodeTypeAudioBufferSource); - m_gain = AudioParam::create(context, "gain", 1.0, 0.0, 1.0); m_playbackRate = AudioParam::create(context, "playbackRate", 1.0, 0.0, MaxRate); // Default to mono. A call to setBuffer() will set the number of output channels to that of the buffer. @@ -133,9 +130,6 @@ void AudioBufferSourceNode::process(size_t framesToProcess) return; } - // Apply the gain (in-place) to the output bus. - float totalGain = gain()->value() * m_buffer->gain(); - outputBus->copyWithGainFrom(*outputBus, &m_lastGain, totalGain); outputBus->clearSilentFlag(); } else { // Too bad - the tryLock() failed. We must be in the middle of changing buffers and were already outputting silence anyway. @@ -331,21 +325,9 @@ bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destination } -void AudioBufferSourceNode::reset() -{ - m_virtualReadIndex = 0; - m_lastGain = gain()->value(); -} - void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer, ExceptionState& exceptionState) { ASSERT(isMainThread()); - // FIXME: It does not look like we should throw if the buffer is null as - // the attribute is nullable in the specification. - if (!buffer) { - exceptionState.throwTypeError("buffer cannot be null"); - return; - } // The context must be locked since changing the buffer can re-configure the number of channels that are output. AudioContext::AutoLocker contextLocker(context()); @@ -382,28 +364,18 @@ unsigned AudioBufferSourceNode::numberOfChannels() return output(0)->numberOfChannels(); } -void AudioBufferSourceNode::start(ExceptionState& exceptionState) -{ - startPlaying(false, 0, 0, buffer() ? buffer()->duration() : 0, exceptionState); -} - void AudioBufferSourceNode::start(double when, ExceptionState& exceptionState) { - startPlaying(false, when, 0, buffer() ? buffer()->duration() : 0, exceptionState); + AudioScheduledSourceNode::start(when, exceptionState); } void AudioBufferSourceNode::start(double when, double grainOffset, ExceptionState& exceptionState) { - startPlaying(true, when, grainOffset, buffer() ? buffer()->duration() : 0, exceptionState); + start(when, grainOffset, buffer() ? buffer()->duration() : 0, exceptionState); } void AudioBufferSourceNode::start(double when, double grainOffset, double grainDuration, ExceptionState& exceptionState) { - startPlaying(true, when, grainOffset, grainDuration, exceptionState); -} - -void AudioBufferSourceNode::startPlaying(bool isGrain, double when, double grainOffset, double grainDuration, ExceptionState& exceptionState) -{ ASSERT(isMainThread()); if (m_playbackState != UNSCHEDULED_STATE) { @@ -416,22 +388,20 @@ void AudioBufferSourceNode::startPlaying(bool isGrain, double when, double grain if (!buffer()) return; - if (isGrain) { - // Do sanity checking of grain parameters versus buffer size. - double bufferDuration = buffer()->duration(); + // Do sanity checking of grain parameters versus buffer size. + double bufferDuration = buffer()->duration(); - grainOffset = max(0.0, grainOffset); - grainOffset = min(bufferDuration, grainOffset); - m_grainOffset = grainOffset; + grainOffset = max(0.0, grainOffset); + grainOffset = min(bufferDuration, grainOffset); + m_grainOffset = grainOffset; - double maxDuration = bufferDuration - grainOffset; + double maxDuration = bufferDuration - grainOffset; - grainDuration = max(0.0, grainDuration); - grainDuration = min(maxDuration, grainDuration); - m_grainDuration = grainDuration; - } + grainDuration = max(0.0, grainDuration); + grainDuration = min(maxDuration, grainDuration); + m_grainDuration = grainDuration; - m_isGrain = isGrain; + m_isGrain = true; m_startTime = when; // We call timeToSampleFrame here since at playbackRate == 1 we don't want to go through linear interpolation @@ -443,14 +413,6 @@ void AudioBufferSourceNode::startPlaying(bool isGrain, double when, double grain m_playbackState = SCHEDULED_STATE; } -void AudioBufferSourceNode::noteGrainOn(double when, double grainOffset, double grainDuration, ExceptionState& exceptionState) -{ - // Handle unspecified duration where 0 means the rest of the buffer. - if (!grainDuration && buffer()) - grainDuration = buffer()->duration(); - startPlaying(true, when, grainOffset, grainDuration, exceptionState); -} - double AudioBufferSourceNode::totalPitchRate() { double dopplerRate = 1.0; @@ -513,6 +475,13 @@ void AudioBufferSourceNode::finish() AudioScheduledSourceNode::finish(); } +void AudioBufferSourceNode::trace(Visitor* visitor) +{ + visitor->trace(m_buffer); + visitor->trace(m_playbackRate); + AudioScheduledSourceNode::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h index 9eafdb201b4..cb24a38c09a 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h @@ -42,15 +42,14 @@ class AudioContext; // AudioBufferSourceNode is an AudioNode representing an audio source from an in-memory audio asset represented by an AudioBuffer. // It generally will be used for short sounds which require a high degree of scheduling flexibility (can playback in rhythmically perfect ways). -class AudioBufferSourceNode : public AudioScheduledSourceNode { +class AudioBufferSourceNode FINAL : public AudioScheduledSourceNode { public: - static PassRefPtr<AudioBufferSourceNode> create(AudioContext*, float sampleRate); + static PassRefPtrWillBeRawPtr<AudioBufferSourceNode> create(AudioContext*, float sampleRate); virtual ~AudioBufferSourceNode(); // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); + virtual void process(size_t framesToProcess) OVERRIDE; // setBuffer() is called on the main thread. This is the buffer we use for playback. void setBuffer(AudioBuffer*, ExceptionState&); @@ -61,13 +60,11 @@ public: unsigned numberOfChannels(); // Play-state - void start(ExceptionState&); + void start(ExceptionState& exceptionState) { start(0, exceptionState); } void start(double when, ExceptionState&); void start(double when, double grainOffset, ExceptionState&); void start(double when, double grainOffset, double grainDuration, ExceptionState&); - void noteGrainOn(double when, double grainOffset, double grainDuration, ExceptionState&); - // Note: the attribute was originally exposed as .looping, but to be more consistent in naming with <audio> // and with how it's described in the specification, the proper attribute name is .loop // The old attribute is kept for backwards compatibility. @@ -80,7 +77,6 @@ public: void setLoopStart(double loopStart) { m_loopStart = loopStart; } void setLoopEnd(double loopEnd) { m_loopEnd = loopEnd; } - AudioParam* gain() { return m_gain.get(); } AudioParam* playbackRate() { return m_playbackRate.get(); } // If a panner node is set, then we can incorporate doppler shift into the playback pitch rate. @@ -88,16 +84,16 @@ public: void clearPannerNode(); // If we are no longer playing, propogate silence ahead to downstream nodes. - virtual bool propagatesSilence() const; + virtual bool propagatesSilence() const OVERRIDE; // AudioScheduledSourceNode virtual void finish() OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: AudioBufferSourceNode(AudioContext*, float sampleRate); - void startPlaying(bool isGrain, double when, double grainOffset, double grainDuration, ExceptionState&); - // Returns true on success. bool renderFromBuffer(AudioBus*, unsigned destinationFrameOffset, size_t numberOfFrames); @@ -105,15 +101,14 @@ private: inline bool renderSilenceAndFinishIfNotLooping(AudioBus*, unsigned index, size_t framesToProcess); // m_buffer holds the sample data which this node outputs. - RefPtr<AudioBuffer> m_buffer; + RefPtrWillBeMember<AudioBuffer> m_buffer; // Pointers for the buffer and destination. OwnPtr<const float*[]> m_sourceChannels; OwnPtr<float*[]> m_destinationChannels; - // Used for the "gain" and "playbackRate" attributes. - RefPtr<AudioParam> m_gain; - RefPtr<AudioParam> m_playbackRate; + // Used for the "playbackRate" attributes. + RefPtrWillBeMember<AudioParam> m_playbackRate; // If m_isLooping is false, then this node will be done playing and become inactive after it reaches the end of the sample data in the buffer. // If true, it will wrap around to the start of the buffer each time it reaches the end. @@ -135,9 +130,6 @@ private: // It incorporates the base pitch rate, any sample-rate conversion factor from the buffer, and any doppler shift from an associated panner node. double totalPitchRate(); - // m_lastGain provides continuity when we dynamically adjust the gain. - float m_lastGain; - // We optionally keep track of a panner node which has a doppler shift that is incorporated into // the pitch rate. We manually manage ref-counting because we want to use RefTypeConnection. PannerNode* m_pannerNode; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.idl b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.idl index ab58774ead6..135f1ce1be2 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.idl @@ -24,33 +24,19 @@ // A cached (non-streamed), memory-resident audio source [ - Conditional=WEB_AUDIO + Conditional=WEB_AUDIO, + TypeChecking=Interface|Nullable, ] interface AudioBufferSourceNode : AudioSourceNode { - [StrictTypeChecking, RaisesException=Setter] attribute AudioBuffer buffer; + [RaisesException=Setter] attribute AudioBuffer buffer; - const unsigned short UNSCHEDULED_STATE = 0; - const unsigned short SCHEDULED_STATE = 1; - const unsigned short PLAYING_STATE = 2; - const unsigned short FINISHED_STATE = 3; - - readonly attribute unsigned short playbackState; - - readonly attribute AudioParam gain; readonly attribute AudioParam playbackRate; - attribute boolean loop; // This is the proper attribute name from the specification. - + attribute boolean loop; attribute double loopStart; attribute double loopEnd; - [RaisesException, MeasureAs=WebAudioStart] void start(optional double when, optional double grainOffset, optional double grainDuration); + [RaisesException] void start(optional double when, optional double grainOffset, optional double grainDuration); [RaisesException] void stop(optional double when); - [DeprecateAs=WebAudioLooping, ImplementedAs=loop] attribute boolean looping; // This is an alias for the .loop attribute for backwards compatibility. - - [RaisesException, ImplementedAs=start, MeasureAs=LegacyWebAudio] void noteOn(double when); - [RaisesException, MeasureAs=LegacyWebAudio] void noteGrainOn(double when, double grainOffset, double grainDuration); - [RaisesException, ImplementedAs=stop] void noteOff(double when); - attribute EventHandler onended; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp index 5ae5ffe99f1..a77c9988d43 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp @@ -86,91 +86,67 @@ bool AudioContext::isSampleRateRangeGood(float sampleRate) } // Don't allow more than this number of simultaneous AudioContexts talking to hardware. -const unsigned MaxHardwareContexts = 4; +const unsigned MaxHardwareContexts = 6; unsigned AudioContext::s_hardwareContextCount = 0; -PassRefPtr<AudioContext> AudioContext::create(Document& document, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<AudioContext> AudioContext::create(Document& document, ExceptionState& exceptionState) { ASSERT(isMainThread()); if (s_hardwareContextCount >= MaxHardwareContexts) { exceptionState.throwDOMException( SyntaxError, "number of hardware contexts reached maximum (" + String::number(MaxHardwareContexts) + ")."); - return 0; + return nullptr; } - RefPtr<AudioContext> audioContext(adoptRef(new AudioContext(&document))); + RefPtrWillBeRawPtr<AudioContext> audioContext(adoptRefWillBeThreadSafeRefCountedGarbageCollected(new AudioContext(&document))); audioContext->suspendIfNeeded(); return audioContext.release(); } -PassRefPtr<AudioContext> AudioContext::create(Document& document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) -{ - document.addConsoleMessage(JSMessageSource, WarningMessageLevel, "Deprecated AudioContext constructor: use OfflineAudioContext instead"); - return OfflineAudioContext::create(&document, numberOfChannels, numberOfFrames, sampleRate, exceptionState); -} - // Constructor for rendering to the audio hardware. AudioContext::AudioContext(Document* document) : ActiveDOMObject(document) , m_isStopScheduled(false) + , m_isCleared(false) , m_isInitialized(false) - , m_isAudioThreadFinished(false) - , m_destinationNode(0) + , m_destinationNode(nullptr) , m_isDeletionScheduled(false) , m_automaticPullNodesNeedUpdating(false) , m_connectionCount(0) , m_audioThread(0) , m_graphOwnerThread(UndefinedThreadIdentifier) , m_isOfflineContext(false) - , m_activeSourceCount(0) { - constructCommon(); + ScriptWrappable::init(this); m_destinationNode = DefaultAudioDestinationNode::create(this); - // This sets in motion an asynchronous loading mechanism on another thread. - // We can check m_hrtfDatabaseLoader->isLoaded() to find out whether or not it has been fully loaded. - // It's not that useful to have a callback function for this since the audio thread automatically starts rendering on the graph - // when this has finished (see AudioDestinationNode). - m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate()); + initialize(); } // Constructor for offline (non-realtime) rendering. AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) : ActiveDOMObject(document) , m_isStopScheduled(false) + , m_isCleared(false) , m_isInitialized(false) - , m_isAudioThreadFinished(false) - , m_destinationNode(0) + , m_destinationNode(nullptr) + , m_isDeletionScheduled(false) , m_automaticPullNodesNeedUpdating(false) , m_connectionCount(0) , m_audioThread(0) , m_graphOwnerThread(UndefinedThreadIdentifier) , m_isOfflineContext(true) - , m_activeSourceCount(0) { - constructCommon(); - - m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate); + ScriptWrappable::init(this); // Create a new destination for offline rendering. m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate); - ASSERT(m_renderTarget); - m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTarget.get()); - ASSERT(m_destinationNode); -} + if (m_renderTarget.get()) + m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTarget.get()); -void AudioContext::constructCommon() -{ - ScriptWrappable::init(this); - // According to spec AudioContext must die only after page navigate. - // Lets mark it as ActiveDOMObject with pending activity and unmark it in clear method. - setPendingActivity(this); - - FFTFrame::initialize(); - - m_listener = AudioListener::create(); + initialize(); } AudioContext::~AudioContext() @@ -180,7 +156,6 @@ AudioContext::~AudioContext() #endif // AudioNodes keep a reference to their context, so there should be no way to be in the destructor if there are still AudioNodes around. ASSERT(!m_isInitialized); - ASSERT(m_isStopScheduled); ASSERT(!m_nodesToDelete.size()); ASSERT(!m_referencedNodes.size()); ASSERT(!m_finishedNodes.size()); @@ -190,27 +165,27 @@ AudioContext::~AudioContext() ASSERT(!m_renderingAutomaticPullNodes.size()); } -void AudioContext::lazyInitialize() +void AudioContext::initialize() { - if (!m_isInitialized) { - // Don't allow the context to initialize a second time after it's already been explicitly uninitialized. - ASSERT(!m_isAudioThreadFinished); - if (!m_isAudioThreadFinished) { - if (m_destinationNode.get()) { - m_destinationNode->initialize(); + if (isInitialized()) + return; + + FFTFrame::initialize(); + m_listener = AudioListener::create(); - if (!isOfflineContext()) { - // This starts the audio thread. The destination node's provideInput() method will now be called repeatedly to render audio. - // Each time provideInput() is called, a portion of the audio stream is rendered. Let's call this time period a "render quantum". - // NOTE: for now default AudioContext does not need an explicit startRendering() call from JavaScript. - // We may want to consider requiring it for symmetry with OfflineAudioContext. - m_destinationNode->startRendering(); - ++s_hardwareContextCount; - } + if (m_destinationNode.get()) { + m_destinationNode->initialize(); - } - m_isInitialized = true; + if (!isOfflineContext()) { + // This starts the audio thread. The destination node's provideInput() method will now be called repeatedly to render audio. + // Each time provideInput() is called, a portion of the audio stream is rendered. Let's call this time period a "render quantum". + // NOTE: for now default AudioContext does not need an explicit startRendering() call from JavaScript. + // We may want to consider requiring it for symmetry with OfflineAudioContext. + m_destinationNode->startRendering(); + ++s_hardwareContextCount; } + + m_isInitialized = true; } } @@ -222,28 +197,24 @@ void AudioContext::clear() // Audio thread is dead. Nobody will schedule node deletion action. Let's do it ourselves. do { - deleteMarkedNodes(); - m_nodesToDelete.append(m_nodesMarkedForDeletion); + m_nodesToDelete.appendVector(m_nodesMarkedForDeletion); m_nodesMarkedForDeletion.clear(); + deleteMarkedNodes(); } while (m_nodesToDelete.size()); - // It was set in constructCommon. - unsetPendingActivity(this); + m_isCleared = true; } void AudioContext::uninitialize() { ASSERT(isMainThread()); - if (!m_isInitialized) + if (!isInitialized()) return; // This stops the audio thread and all audio rendering. m_destinationNode->uninitialize(); - // Don't allow the context to initialize a second time after it's already been explicitly uninitialized. - m_isAudioThreadFinished = true; - if (!isOfflineContext()) { ASSERT(s_hardwareContextCount); --s_hardwareContextCount; @@ -255,20 +226,6 @@ void AudioContext::uninitialize() m_isInitialized = false; } -bool AudioContext::isInitialized() const -{ - return m_isInitialized; -} - -bool AudioContext::isRunnable() const -{ - if (!isInitialized()) - return false; - - // Check with the HRTF spatialization system to see if it's finished loading. - return m_hrtfDatabaseLoader->isLoaded(); -} - void AudioContext::stopDispatch(void* userData) { AudioContext* context = reinterpret_cast<AudioContext*>(userData); @@ -294,55 +251,15 @@ void AudioContext::stop() callOnMainThread(stopDispatch, this); } -PassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) +bool AudioContext::hasPendingActivity() const { - RefPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate); - if (!audioBuffer.get()) { - if (numberOfChannels > AudioContext::maxNumberOfChannels()) { - exceptionState.throwDOMException( - NotSupportedError, - "requested number of channels (" + String::number(numberOfChannels) + ") exceeds maximum (" + String::number(AudioContext::maxNumberOfChannels()) + ")"); - } else if (sampleRate < AudioBuffer::minAllowedSampleRate() || sampleRate > AudioBuffer::maxAllowedSampleRate()) { - exceptionState.throwDOMException( - NotSupportedError, - "requested sample rate (" + String::number(sampleRate) - + ") does not lie in the allowed range of " - + String::number(AudioBuffer::minAllowedSampleRate()) - + "-" + String::number(AudioBuffer::maxAllowedSampleRate()) + " Hz"); - } else if (!numberOfFrames) { - exceptionState.throwDOMException( - NotSupportedError, - "number of frames must be greater than 0."); - } else { - exceptionState.throwDOMException( - NotSupportedError, - "unable to create buffer of " + String::number(numberOfChannels) - + " channel(s) of " + String::number(numberOfFrames) - + " frames each."); - } - return 0; - } - - return audioBuffer; + // According to spec AudioContext must die only after page navigates. + return !m_isCleared; } -PassRefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer* arrayBuffer, bool mixToMono, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) { - ASSERT(arrayBuffer); - if (!arrayBuffer) { - exceptionState.throwDOMException( - SyntaxError, - "invalid ArrayBuffer."); - return 0; - } - - RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(arrayBuffer->data(), arrayBuffer->byteLength(), mixToMono, sampleRate()); - if (!audioBuffer.get()) { - exceptionState.throwDOMException( - SyntaxError, - "invalid audio data in ArrayBuffer."); - return 0; - } + RefPtrWillBeRawPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate, exceptionState); return audioBuffer; } @@ -358,11 +275,10 @@ void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassOwnPtr<AudioBuffe m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCallback); } -PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource() +PassRefPtrWillBeRawPtr<AudioBufferSourceNode> AudioContext::createBufferSource() { ASSERT(isMainThread()); - lazyInitialize(); - RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_destinationNode->sampleRate()); + RefPtrWillBeRawPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_destinationNode->sampleRate()); // Because this is an AudioScheduledSourceNode, the context keeps a reference until it has finished playing. // When this happens, AudioScheduledSourceNode::finish() calls AudioContext::notifyNodeFinishedProcessing(). @@ -371,27 +287,25 @@ PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource() return node; } -PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(HTMLMediaElement* mediaElement, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(HTMLMediaElement* mediaElement, ExceptionState& exceptionState) { + ASSERT(isMainThread()); if (!mediaElement) { exceptionState.throwDOMException( InvalidStateError, "invalid HTMLMedialElement."); - return 0; + return nullptr; } - ASSERT(isMainThread()); - lazyInitialize(); - // First check if this media element already has a source node. if (mediaElement->audioSourceNode()) { exceptionState.throwDOMException( InvalidStateError, "invalid HTMLMediaElement."); - return 0; + return nullptr; } - RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::create(this, mediaElement); + RefPtrWillBeRawPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::create(this, mediaElement); mediaElement->setAudioSourceNode(node.get()); @@ -399,33 +313,28 @@ PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H return node; } -PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(MediaStream* mediaStream, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(MediaStream* mediaStream, ExceptionState& exceptionState) { + ASSERT(isMainThread()); if (!mediaStream) { exceptionState.throwDOMException( InvalidStateError, "invalid MediaStream source"); - return 0; + return nullptr; } - ASSERT(isMainThread()); - lazyInitialize(); - - AudioSourceProvider* provider = 0; - MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks(); - RefPtr<MediaStreamTrack> audioTrack; - - // FIXME: get a provider for non-local MediaStreams (like from a remote peer). - for (size_t i = 0; i < audioTracks.size(); ++i) { - audioTrack = audioTracks[i]; - if (audioTrack->component()->audioSourceProvider()) { - provider = audioTrack->component()->audioSourceProvider(); - break; - } + if (audioTracks.isEmpty()) { + exceptionState.throwDOMException( + InvalidStateError, + "MediaStream has no audio track"); + return nullptr; } - RefPtr<MediaStreamAudioSourceNode> node = MediaStreamAudioSourceNode::create(this, mediaStream, audioTrack.get(), provider); + // Use the first audio track in the media stream. + RefPtrWillBeRawPtr<MediaStreamTrack> audioTrack = audioTracks[0]; + OwnPtr<AudioSourceProvider> provider = audioTrack->createWebAudioSource(); + RefPtrWillBeRawPtr<MediaStreamAudioSourceNode> node = MediaStreamAudioSourceNode::create(this, mediaStream, audioTrack.get(), provider.release()); // FIXME: Only stereo streams are supported right now. We should be able to accept multi-channel streams. node->setFormat(2, sampleRate()); @@ -434,36 +343,34 @@ PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med return node; } -PassRefPtr<MediaStreamAudioDestinationNode> AudioContext::createMediaStreamDestination() +PassRefPtrWillBeRawPtr<MediaStreamAudioDestinationNode> AudioContext::createMediaStreamDestination() { - // FIXME: Add support for an optional argument which specifies the number of channels. - // FIXME: The default should probably be stereo instead of mono. - return MediaStreamAudioDestinationNode::create(this, 1); + // Set number of output channels to stereo by default. + return MediaStreamAudioDestinationNode::create(this, 2); } -PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(ExceptionState& exceptionState) { // Set number of input/output channels to stereo by default. return createScriptProcessor(0, 2, 2, exceptionState); } -PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, ExceptionState& exceptionState) { // Set number of input/output channels to stereo by default. return createScriptProcessor(bufferSize, 2, 2, exceptionState); } -PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionState& exceptionState) { // Set number of output channels to stereo by default. return createScriptProcessor(bufferSize, numberOfInputChannels, 2, exceptionState); } -PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionState& exceptionState) { ASSERT(isMainThread()); - lazyInitialize(); - RefPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(this, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels); + RefPtrWillBeRawPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(this, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels); if (!node.get()) { if (!numberOfInputChannels && !numberOfOutputChannels) { @@ -488,90 +395,81 @@ PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe "buffer size (" + String::number(bufferSize) + ") must be a power of two between 256 and 16384."); } - return 0; + return nullptr; } refNode(node.get()); // context keeps reference until we stop making javascript rendering callbacks return node; } -PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter() +PassRefPtrWillBeRawPtr<BiquadFilterNode> AudioContext::createBiquadFilter() { ASSERT(isMainThread()); - lazyInitialize(); return BiquadFilterNode::create(this, m_destinationNode->sampleRate()); } -PassRefPtr<WaveShaperNode> AudioContext::createWaveShaper() +PassRefPtrWillBeRawPtr<WaveShaperNode> AudioContext::createWaveShaper() { ASSERT(isMainThread()); - lazyInitialize(); return WaveShaperNode::create(this); } -PassRefPtr<PannerNode> AudioContext::createPanner() +PassRefPtrWillBeRawPtr<PannerNode> AudioContext::createPanner() { ASSERT(isMainThread()); - lazyInitialize(); return PannerNode::create(this, m_destinationNode->sampleRate()); } -PassRefPtr<ConvolverNode> AudioContext::createConvolver() +PassRefPtrWillBeRawPtr<ConvolverNode> AudioContext::createConvolver() { ASSERT(isMainThread()); - lazyInitialize(); return ConvolverNode::create(this, m_destinationNode->sampleRate()); } -PassRefPtr<DynamicsCompressorNode> AudioContext::createDynamicsCompressor() +PassRefPtrWillBeRawPtr<DynamicsCompressorNode> AudioContext::createDynamicsCompressor() { ASSERT(isMainThread()); - lazyInitialize(); return DynamicsCompressorNode::create(this, m_destinationNode->sampleRate()); } -PassRefPtr<AnalyserNode> AudioContext::createAnalyser() +PassRefPtrWillBeRawPtr<AnalyserNode> AudioContext::createAnalyser() { ASSERT(isMainThread()); - lazyInitialize(); return AnalyserNode::create(this, m_destinationNode->sampleRate()); } -PassRefPtr<GainNode> AudioContext::createGain() +PassRefPtrWillBeRawPtr<GainNode> AudioContext::createGain() { ASSERT(isMainThread()); - lazyInitialize(); return GainNode::create(this, m_destinationNode->sampleRate()); } -PassRefPtr<DelayNode> AudioContext::createDelay(ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<DelayNode> AudioContext::createDelay(ExceptionState& exceptionState) { const double defaultMaxDelayTime = 1; return createDelay(defaultMaxDelayTime, exceptionState); } -PassRefPtr<DelayNode> AudioContext::createDelay(double maxDelayTime, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<DelayNode> AudioContext::createDelay(double maxDelayTime, ExceptionState& exceptionState) { ASSERT(isMainThread()); - lazyInitialize(); - RefPtr<DelayNode> node = DelayNode::create(this, m_destinationNode->sampleRate(), maxDelayTime, exceptionState); + RefPtrWillBeRawPtr<DelayNode> node = DelayNode::create(this, m_destinationNode->sampleRate(), maxDelayTime, exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; return node; } -PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(ExceptionState& exceptionState) { const unsigned ChannelSplitterDefaultNumberOfOutputs = 6; return createChannelSplitter(ChannelSplitterDefaultNumberOfOutputs, exceptionState); } -PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numberOfOutputs, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numberOfOutputs, ExceptionState& exceptionState) { ASSERT(isMainThread()); - lazyInitialize(); - RefPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(this, m_destinationNode->sampleRate(), numberOfOutputs); + RefPtrWillBeRawPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(this, m_destinationNode->sampleRate(), numberOfOutputs); if (!node.get()) { exceptionState.throwDOMException( @@ -579,24 +477,23 @@ PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numbe "number of outputs (" + String::number(numberOfOutputs) + ") must be between 1 and " + String::number(AudioContext::maxNumberOfChannels()) + "."); - return 0; + return nullptr; } return node; } -PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionState& exceptionState) { const unsigned ChannelMergerDefaultNumberOfInputs = 6; return createChannelMerger(ChannelMergerDefaultNumberOfInputs, exceptionState); } -PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfInputs, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfInputs, ExceptionState& exceptionState) { ASSERT(isMainThread()); - lazyInitialize(); - RefPtr<ChannelMergerNode> node = ChannelMergerNode::create(this, m_destinationNode->sampleRate(), numberOfInputs); + RefPtrWillBeRawPtr<ChannelMergerNode> node = ChannelMergerNode::create(this, m_destinationNode->sampleRate(), numberOfInputs); if (!node.get()) { exceptionState.throwDOMException( @@ -604,18 +501,17 @@ PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfI "number of inputs (" + String::number(numberOfInputs) + ") must be between 1 and " + String::number(AudioContext::maxNumberOfChannels()) + "."); - return 0; + return nullptr; } return node; } -PassRefPtr<OscillatorNode> AudioContext::createOscillator() +PassRefPtrWillBeRawPtr<OscillatorNode> AudioContext::createOscillator() { ASSERT(isMainThread()); - lazyInitialize(); - RefPtr<OscillatorNode> node = OscillatorNode::create(this, m_destinationNode->sampleRate()); + RefPtrWillBeRawPtr<OscillatorNode> node = OscillatorNode::create(this, m_destinationNode->sampleRate()); // Because this is an AudioScheduledSourceNode, the context keeps a reference until it has finished playing. // When this happens, AudioScheduledSourceNode::finish() calls AudioContext::notifyNodeFinishedProcessing(). @@ -624,7 +520,7 @@ PassRefPtr<OscillatorNode> AudioContext::createOscillator() return node; } -PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Float32Array* imag, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Float32Array* imag, ExceptionState& exceptionState) { ASSERT(isMainThread()); @@ -632,14 +528,14 @@ PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl exceptionState.throwDOMException( SyntaxError, "invalid real array"); - return 0; + return nullptr; } if (!imag) { exceptionState.throwDOMException( SyntaxError, "invalid imaginary array"); - return 0; + return nullptr; } if (real->length() != imag->length()) { @@ -648,7 +544,7 @@ PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl "length of real array (" + String::number(real->length()) + ") and length of imaginary array (" + String::number(imag->length()) + ") must match."); - return 0; + return nullptr; } if (real->length() > 4096) { @@ -656,7 +552,7 @@ PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl IndexSizeError, "length of real array (" + String::number(real->length()) + ") exceeds allowed maximum of 4096"); - return 0; + return nullptr; } if (imag->length() > 4096) { @@ -664,10 +560,9 @@ PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl IndexSizeError, "length of imaginary array (" + String::number(imag->length()) + ") exceeds allowed maximum of 4096"); - return 0; + return nullptr; } - lazyInitialize(); return PeriodicWave::create(sampleRate(), real, imag); } @@ -680,7 +575,7 @@ void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) void AudioContext::derefFinishedSourceNodes() { ASSERT(isGraphOwner()); - ASSERT(isAudioThread() || isAudioThreadFinished()); + ASSERT(isAudioThread()); for (unsigned i = 0; i < m_finishedNodes.size(); i++) derefNode(m_finishedNodes[i]); @@ -712,7 +607,7 @@ void AudioContext::derefNode(AudioNode* node) void AudioContext::derefUnfinishedSourceNodes() { - ASSERT(isMainThread() && isAudioThreadFinished()); + ASSERT(isMainThread()); for (unsigned i = 0; i < m_referencedNodes.size(); ++i) m_referencedNodes[i]->deref(AudioNode::RefTypeConnection); @@ -743,7 +638,7 @@ bool AudioContext::tryLock(bool& mustReleaseLock) bool isAudioThread = thisThread == audioThread(); // Try to catch cases of using try lock on main thread - it should use regular lock. - ASSERT(isAudioThread || isAudioThreadFinished()); + ASSERT(isAudioThread); if (!isAudioThread) { // In release build treat tryLock() as lock() (since above ASSERT(isAudioThread) never fires) - this is the best we can do. @@ -858,7 +753,7 @@ void AudioContext::markForDeletion(AudioNode* node) { ASSERT(isGraphOwner()); - if (isAudioThreadFinished()) + if (!isInitialized()) m_nodesToDelete.append(node); else m_nodesMarkedForDeletion.append(node); @@ -872,14 +767,14 @@ void AudioContext::markForDeletion(AudioNode* node) void AudioContext::scheduleNodeDeletion() { - bool isGood = m_isInitialized && isGraphOwner(); + bool isGood = isInitialized() && isGraphOwner(); ASSERT(isGood); if (!isGood) return; // Make sure to call deleteMarkedNodes() on main thread. if (m_nodesMarkedForDeletion.size() && !m_isDeletionScheduled) { - m_nodesToDelete.append(m_nodesMarkedForDeletion); + m_nodesToDelete.appendVector(m_nodesMarkedForDeletion); m_nodesMarkedForDeletion.clear(); m_isDeletionScheduled = true; @@ -907,7 +802,7 @@ void AudioContext::deleteMarkedNodes() ASSERT(isMainThread()); // Protect this object from being deleted before we release the mutex locked by AutoLocker. - RefPtr<AudioContext> protect(this); + RefPtrWillBeRawPtr<AudioContext> protect(this); { AutoLocker locker(this); @@ -924,9 +819,14 @@ void AudioContext::deleteMarkedNodes() unsigned numberOfOutputs = node->numberOfOutputs(); for (unsigned i = 0; i < numberOfOutputs; ++i) m_dirtyAudioNodeOutputs.remove(node->output(i)); - +#if ENABLE(OILPAN) + // Finally, clear the keep alive handle that keeps this + // object from being collected. + node->clearKeepAlive(); +#else // Finally, delete it. delete node; +#endif } m_isDeletionScheduled = false; } @@ -955,7 +855,7 @@ void AudioContext::handleDirtyAudioSummingJunctions() { ASSERT(isGraphOwner()); - for (HashSet<AudioSummingJunction*>::iterator i = m_dirtySummingJunctions.begin(); i != m_dirtySummingJunctions.end(); ++i) + for (HashSet<AudioSummingJunction* >::iterator i = m_dirtySummingJunctions.begin(); i != m_dirtySummingJunctions.end(); ++i) (*i)->updateRenderingState(); m_dirtySummingJunctions.clear(); @@ -1051,14 +951,13 @@ void AudioContext::fireCompletionEvent() } } -void AudioContext::incrementActiveSourceCount() -{ - atomicIncrement(&m_activeSourceCount); -} - -void AudioContext::decrementActiveSourceCount() +void AudioContext::trace(Visitor* visitor) { - atomicDecrement(&m_activeSourceCount); + visitor->trace(m_renderTarget); + visitor->trace(m_destinationNode); + visitor->trace(m_listener); + visitor->trace(m_dirtySummingJunctions); + EventTargetWithInlineData::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.h index a6ece93825d..d6c9f8b94dd 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.h @@ -28,11 +28,11 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" #include "core/events/EventListener.h" -#include "core/events/EventTarget.h" -#include "platform/audio/AudioBus.h" -#include "platform/audio/HRTFDatabaseLoader.h" +#include "modules/EventTargetModules.h" #include "modules/webaudio/AsyncAudioDecoder.h" #include "modules/webaudio/AudioDestinationNode.h" +#include "platform/audio/AudioBus.h" +#include "platform/heap/Handle.h" #include "wtf/HashSet.h" #include "wtf/MainThread.h" #include "wtf/OwnPtr.h" @@ -74,43 +74,30 @@ class WaveShaperNode; // AudioContext is the cornerstone of the web audio API and all AudioNodes are created from it. // For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism. -class AudioContext : public ActiveDOMObject, public ScriptWrappable, public ThreadSafeRefCounted<AudioContext>, public EventTargetWithInlineData { - DEFINE_EVENT_TARGET_REFCOUNTING(ThreadSafeRefCounted<AudioContext>); +class AudioContext : public ThreadSafeRefCountedWillBeThreadSafeRefCountedGarbageCollected<AudioContext>, public ActiveDOMObject, public ScriptWrappable, public EventTargetWithInlineData { + DEFINE_EVENT_TARGET_REFCOUNTING(ThreadSafeRefCountedWillBeThreadSafeRefCountedGarbageCollected<AudioContext>); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(AudioContext); public: // Create an AudioContext for rendering to the audio hardware. - static PassRefPtr<AudioContext> create(Document&, ExceptionState&); - - // Deprecated: create an AudioContext for offline (non-realtime) rendering. - static PassRefPtr<AudioContext> create(Document&, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&); + static PassRefPtrWillBeRawPtr<AudioContext> create(Document&, ExceptionState&); virtual ~AudioContext(); - bool isInitialized() const; + virtual void trace(Visitor*) OVERRIDE; + bool isInitialized() const { return m_isInitialized; } bool isOfflineContext() { return m_isOfflineContext; } - // Returns true when initialize() was called AND all asynchronous initialization has completed. - bool isRunnable() const; - - HRTFDatabaseLoader* hrtfDatabaseLoader() const { return m_hrtfDatabaseLoader.get(); } - // Document notification - virtual void stop(); - - Document* document() const; // ASSERTs if document no longer exists. - bool hasDocument(); + virtual void stop() OVERRIDE FINAL; + virtual bool hasPendingActivity() const OVERRIDE; AudioDestinationNode* destination() { return m_destinationNode.get(); } size_t currentSampleFrame() const { return m_destinationNode->currentSampleFrame(); } double currentTime() const { return m_destinationNode->currentTime(); } float sampleRate() const { return m_destinationNode->sampleRate(); } - unsigned long activeSourceCount() const { return static_cast<unsigned long>(m_activeSourceCount); } - void incrementActiveSourceCount(); - void decrementActiveSourceCount(); - - PassRefPtr<AudioBuffer> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&); - PassRefPtr<AudioBuffer> createBuffer(ArrayBuffer*, bool mixToMono, ExceptionState&); + PassRefPtrWillBeRawPtr<AudioBuffer> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&); // Asynchronous audio file data decoding. void decodeAudioData(ArrayBuffer*, PassOwnPtr<AudioBufferCallback>, PassOwnPtr<AudioBufferCallback>, ExceptionState&); @@ -118,29 +105,29 @@ public: AudioListener* listener() { return m_listener.get(); } // The AudioNode create methods are called on the main thread (from JavaScript). - PassRefPtr<AudioBufferSourceNode> createBufferSource(); - PassRefPtr<MediaElementAudioSourceNode> createMediaElementSource(HTMLMediaElement*, ExceptionState&); - PassRefPtr<MediaStreamAudioSourceNode> createMediaStreamSource(MediaStream*, ExceptionState&); - PassRefPtr<MediaStreamAudioDestinationNode> createMediaStreamDestination(); - PassRefPtr<GainNode> createGain(); - PassRefPtr<BiquadFilterNode> createBiquadFilter(); - PassRefPtr<WaveShaperNode> createWaveShaper(); - PassRefPtr<DelayNode> createDelay(ExceptionState&); - PassRefPtr<DelayNode> createDelay(double maxDelayTime, ExceptionState&); - PassRefPtr<PannerNode> createPanner(); - PassRefPtr<ConvolverNode> createConvolver(); - PassRefPtr<DynamicsCompressorNode> createDynamicsCompressor(); - PassRefPtr<AnalyserNode> createAnalyser(); - PassRefPtr<ScriptProcessorNode> createScriptProcessor(ExceptionState&); - PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, ExceptionState&); - PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionState&); - PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionState&); - PassRefPtr<ChannelSplitterNode> createChannelSplitter(ExceptionState&); - PassRefPtr<ChannelSplitterNode> createChannelSplitter(size_t numberOfOutputs, ExceptionState&); - PassRefPtr<ChannelMergerNode> createChannelMerger(ExceptionState&); - PassRefPtr<ChannelMergerNode> createChannelMerger(size_t numberOfInputs, ExceptionState&); - PassRefPtr<OscillatorNode> createOscillator(); - PassRefPtr<PeriodicWave> createPeriodicWave(Float32Array* real, Float32Array* imag, ExceptionState&); + PassRefPtrWillBeRawPtr<AudioBufferSourceNode> createBufferSource(); + PassRefPtrWillBeRawPtr<MediaElementAudioSourceNode> createMediaElementSource(HTMLMediaElement*, ExceptionState&); + PassRefPtrWillBeRawPtr<MediaStreamAudioSourceNode> createMediaStreamSource(MediaStream*, ExceptionState&); + PassRefPtrWillBeRawPtr<MediaStreamAudioDestinationNode> createMediaStreamDestination(); + PassRefPtrWillBeRawPtr<GainNode> createGain(); + PassRefPtrWillBeRawPtr<BiquadFilterNode> createBiquadFilter(); + PassRefPtrWillBeRawPtr<WaveShaperNode> createWaveShaper(); + PassRefPtrWillBeRawPtr<DelayNode> createDelay(ExceptionState&); + PassRefPtrWillBeRawPtr<DelayNode> createDelay(double maxDelayTime, ExceptionState&); + PassRefPtrWillBeRawPtr<PannerNode> createPanner(); + PassRefPtrWillBeRawPtr<ConvolverNode> createConvolver(); + PassRefPtrWillBeRawPtr<DynamicsCompressorNode> createDynamicsCompressor(); + PassRefPtrWillBeRawPtr<AnalyserNode> createAnalyser(); + PassRefPtrWillBeRawPtr<ScriptProcessorNode> createScriptProcessor(ExceptionState&); + PassRefPtrWillBeRawPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, ExceptionState&); + PassRefPtrWillBeRawPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionState&); + PassRefPtrWillBeRawPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionState&); + PassRefPtrWillBeRawPtr<ChannelSplitterNode> createChannelSplitter(ExceptionState&); + PassRefPtrWillBeRawPtr<ChannelSplitterNode> createChannelSplitter(size_t numberOfOutputs, ExceptionState&); + PassRefPtrWillBeRawPtr<ChannelMergerNode> createChannelMerger(ExceptionState&); + PassRefPtrWillBeRawPtr<ChannelMergerNode> createChannelMerger(size_t numberOfInputs, ExceptionState&); + PassRefPtrWillBeRawPtr<OscillatorNode> createOscillator(); + PassRefPtrWillBeRawPtr<PeriodicWave> createPeriodicWave(Float32Array* real, Float32Array* imag, ExceptionState&); // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it. void notifyNodeFinishedProcessing(AudioNode*); @@ -183,9 +170,6 @@ public: ThreadIdentifier audioThread() const { return m_audioThread; } bool isAudioThread() const; - // Returns true only after the audio thread has been started and then shutdown. - bool isAudioThreadFinished() { return m_isAudioThreadFinished; } - // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired. void lock(bool& mustReleaseLock); @@ -234,8 +218,8 @@ public: void removeMarkedSummingJunction(AudioSummingJunction*); // EventTarget - virtual const AtomicString& interfaceName() const OVERRIDE; - virtual ExecutionContext* executionContext() const OVERRIDE; + virtual const AtomicString& interfaceName() const OVERRIDE FINAL; + virtual ExecutionContext* executionContext() const OVERRIDE FINAL; DEFINE_ATTRIBUTE_EVENT_LISTENER(complete); @@ -251,22 +235,21 @@ protected: static bool isSampleRateRangeGood(float sampleRate); private: - void constructCommon(); - - void lazyInitialize(); + void initialize(); void uninitialize(); // ExecutionContext calls stop twice. // We'd like to schedule only one stop action for them. bool m_isStopScheduled; static void stopDispatch(void* userData); + bool m_isCleared; void clear(); void scheduleNodeDeletion(); static void deleteMarkedNodesDispatch(void* userData); + // Set to true when the destination node has been initialized and is ready to process data. bool m_isInitialized; - bool m_isAudioThreadFinished; // The context itself keeps a reference to all source nodes. The source nodes, then reference all nodes they're connected to. // In turn, these nodes reference all nodes they're connected to. All nodes are ultimately connected to the AudioDestinationNode. @@ -279,8 +262,8 @@ private: // Make sure to dereference them here. void derefUnfinishedSourceNodes(); - RefPtr<AudioDestinationNode> m_destinationNode; - RefPtr<AudioListener> m_listener; + RefPtrWillBeMember<AudioDestinationNode> m_destinationNode; + RefPtrWillBeMember<AudioListener> m_listener; // Only accessed in the audio thread. Vector<AudioNode*> m_finishedNodes; @@ -301,7 +284,7 @@ private: bool m_isDeletionScheduled; // Only accessed when the graph lock is held. - HashSet<AudioSummingJunction*> m_dirtySummingJunctions; + HashSet<AudioSummingJunction* > m_dirtySummingJunctions; HashSet<AudioNodeOutput*> m_dirtyAudioNodeOutputs; void handleDirtyAudioSummingJunctions(); void handleDirtyAudioNodeOutputs(); @@ -324,10 +307,7 @@ private: // Only accessed in the audio thread. Vector<AudioNode*> m_deferredFinishDerefList; - // HRTF Database loader - RefPtr<HRTFDatabaseLoader> m_hrtfDatabaseLoader; - - RefPtr<AudioBuffer> m_renderTarget; + RefPtrWillBeMember<AudioBuffer> m_renderTarget; bool m_isOfflineContext; @@ -336,9 +316,6 @@ private: // This is considering 32 is large enough for multiple channels audio. // It is somewhat arbitrary and could be increased if necessary. enum { MaxNumberOfChannels = 32 }; - - // Number of AudioBufferSourceNodes that are active (playing). - int m_activeSourceCount; }; } // WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.idl b/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.idl index 52da1a57277..f5a932a181c 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioContext.idl @@ -24,19 +24,20 @@ */ [ + WillBeGarbageCollected, ActiveDOMObject, Conditional=WEB_AUDIO, Constructor, - Constructor(unsigned long numberOfChannels, unsigned long numberOfFrames, float sampleRate), ConstructorCallWith=Document, NoInterfaceObject, RaisesException=Constructor, ] interface AudioContext : EventTarget { + // All rendered audio ultimately connects to destination, which represents the audio hardware. readonly attribute AudioDestinationNode destination; // All scheduled times are relative to this time in seconds. - readonly attribute float currentTime; + readonly attribute double currentTime; // All AudioNodes in the context run at this sample-rate (sample-frames per second). readonly attribute float sampleRate; @@ -44,11 +45,7 @@ // All panning is relative to this listener. readonly attribute AudioListener listener; - // Number of AudioBufferSourceNodes that are currently playing. - readonly attribute unsigned long activeSourceCount; - [RaisesException] AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long numberOfFrames, float sampleRate); - [RaisesException] AudioBuffer createBuffer(ArrayBuffer? buffer, boolean mixToMono); // Asynchronous audio file data decoding. [RaisesException] void decodeAudioData(ArrayBuffer audioData, AudioBufferCallback successCallback, optional AudioBufferCallback errorCallback); @@ -82,10 +79,4 @@ // void prepareOfflineBufferRendering(unsigned long numberOfChannels, unsigned long numberOfFrames, float sampleRate); attribute EventHandler oncomplete; void startRendering(); - - [MeasureAs=LegacyWebAudio, ImplementedAs=createGain] GainNode createGainNode(); - [MeasureAs=LegacyWebAudio, ImplementedAs=createDelay, RaisesException] DelayNode createDelayNode(optional double maxDelayTime); - - [MeasureAs=LegacyWebAudio, ImplementedAs=createScriptProcessor, RaisesException] ScriptProcessorNode createJavaScriptNode(unsigned long bufferSize, optional unsigned long numberOfInputChannels, optional unsigned long numberOfOutputChannels); - }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp index 68a6d7285e1..807c1d7a8ff 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp @@ -60,7 +60,7 @@ void AudioDestinationNode::render(AudioBus* sourceBus, AudioBus* destinationBus, context()->setAudioThread(currentThread()); - if (!context()->isRunnable()) { + if (!context()->isInitialized()) { destinationBus->zero(); return; } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h index 801d7fd656d..182648732f8 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h @@ -42,29 +42,23 @@ public: virtual ~AudioDestinationNode(); // AudioNode - virtual void process(size_t) { }; // we're pulled by hardware so this is never called - virtual void reset() { m_currentSampleFrame = 0; }; + virtual void process(size_t) OVERRIDE FINAL { } // we're pulled by hardware so this is never called // The audio hardware calls render() to get the next render quantum of audio into destinationBus. // It will optionally give us local/live audio input in sourceBus (if it's not 0). - virtual void render(AudioBus* sourceBus, AudioBus* destinationBus, size_t numberOfFrames); + virtual void render(AudioBus* sourceBus, AudioBus* destinationBus, size_t numberOfFrames) OVERRIDE FINAL; size_t currentSampleFrame() const { return m_currentSampleFrame; } double currentTime() const { return currentSampleFrame() / static_cast<double>(sampleRate()); } virtual unsigned long maxChannelCount() const { return 0; } - // Enable local/live input for the specified device. - virtual void enableInput(const String& inputDeviceId) = 0; - virtual void startRendering() = 0; - AudioSourceProvider* localAudioInputProvider() { return &m_localAudioInputProvider; } - protected: // LocalAudioInputProvider allows us to expose an AudioSourceProvider for local/live audio input. // If there is local/live audio input, we call set() with the audio input data every render quantum. - class LocalAudioInputProvider : public AudioSourceProvider { + class LocalAudioInputProvider FINAL : public AudioSourceProvider { public: LocalAudioInputProvider() : m_sourceBus(AudioBus::create(2, AudioNode::ProcessingSizeInFrames)) // FIXME: handle non-stereo local input. @@ -78,7 +72,7 @@ protected: } // AudioSourceProvider. - virtual void provideInput(AudioBus* destinationBus, size_t numberOfFrames) + virtual void provideInput(AudioBus* destinationBus, size_t numberOfFrames) OVERRIDE { bool isGood = destinationBus && destinationBus->length() == numberOfFrames && m_sourceBus->length() == numberOfFrames; ASSERT(isGood); @@ -90,8 +84,8 @@ protected: RefPtr<AudioBus> m_sourceBus; }; - virtual double tailTime() const OVERRIDE { return 0; } - virtual double latencyTime() const OVERRIDE { return 0; } + virtual double tailTime() const OVERRIDE FINAL { return 0; } + virtual double latencyTime() const OVERRIDE FINAL { return 0; } // Counts the number of sample-frames processed by the destination. size_t m_currentSampleFrame; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp index e13794597bb..94466c9a19f 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp @@ -32,6 +32,7 @@ #include "modules/webaudio/AudioListener.h" +#include "modules/webaudio/PannerNode.h" #include "platform/audio/AudioBus.h" namespace WebCore { @@ -47,6 +48,101 @@ AudioListener::AudioListener() ScriptWrappable::init(this); } +AudioListener::~AudioListener() +{ + m_panners.clear(); +} + +void AudioListener::addPanner(PannerNode* panner) +{ + if (!panner) + return; + + m_panners.append(panner); +} + +void AudioListener::removePanner(PannerNode* panner) +{ + for (unsigned i = 0; i < m_panners.size(); ++i) { + if (panner == m_panners[i]) { + m_panners.remove(i); + break; + } + } +} + +void AudioListener::markPannersAsDirty(unsigned type) +{ + for (unsigned i = 0; i < m_panners.size(); ++i) + m_panners[i]->markPannerAsDirty(type); +} + +void AudioListener::setPosition(const FloatPoint3D &position) +{ + if (m_position == position) + return; + + // This synchronizes with panner's process(). + MutexLocker listenerLocker(m_listenerLock); + m_position = position; + markPannersAsDirty(PannerNode::AzimuthElevationDirty | PannerNode::DistanceConeGainDirty | PannerNode::DopplerRateDirty); +} + +void AudioListener::setOrientation(const FloatPoint3D &orientation) +{ + if (m_orientation == orientation) + return; + + // This synchronizes with panner's process(). + MutexLocker listenerLocker(m_listenerLock); + m_orientation = orientation; + markPannersAsDirty(PannerNode::AzimuthElevationDirty); +} + +void AudioListener::setUpVector(const FloatPoint3D &upVector) +{ + if (m_upVector == upVector) + return; + + // This synchronizes with panner's process(). + MutexLocker listenerLocker(m_listenerLock); + m_upVector = upVector; + markPannersAsDirty(PannerNode::AzimuthElevationDirty); +} + +void AudioListener::setVelocity(const FloatPoint3D &velocity) +{ + if (m_velocity == velocity) + return; + + // This synchronizes with panner's process(). + MutexLocker listenerLocker(m_listenerLock); + m_velocity = velocity; + markPannersAsDirty(PannerNode::DopplerRateDirty); +} + +void AudioListener::setDopplerFactor(double dopplerFactor) +{ + if (m_dopplerFactor == dopplerFactor) + return; + + // This synchronizes with panner's process(). + MutexLocker listenerLocker(m_listenerLock); + m_dopplerFactor = dopplerFactor; + markPannersAsDirty(PannerNode::DopplerRateDirty); +} + +void AudioListener::setSpeedOfSound(double speedOfSound) +{ + if (m_speedOfSound == speedOfSound) + return; + + // This synchronizes with panner's process(). + MutexLocker listenerLocker(m_listenerLock); + m_speedOfSound = speedOfSound; + markPannersAsDirty(PannerNode::DopplerRateDirty); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.h index dcd68dd42ba..214db390b70 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.h @@ -31,63 +31,78 @@ #include "bindings/v8/ScriptWrappable.h" #include "platform/geometry/FloatPoint3D.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" +#include "wtf/Vector.h" namespace WebCore { +class PannerNode; + // AudioListener maintains the state of the listener in the audio scene as defined in the OpenAL specification. -class AudioListener : public ScriptWrappable, public RefCounted<AudioListener> { +class AudioListener : public RefCountedWillBeGarbageCollectedFinalized<AudioListener>, public ScriptWrappable { public: - static PassRefPtr<AudioListener> create() + static PassRefPtrWillBeRawPtr<AudioListener> create() { - return adoptRef(new AudioListener()); + return adoptRefWillBeNoop(new AudioListener()); } + virtual ~AudioListener(); // Position void setPosition(float x, float y, float z) { setPosition(FloatPoint3D(x, y, z)); } - void setPosition(const FloatPoint3D &position) { m_position = position; } const FloatPoint3D& position() const { return m_position; } - // Orientation + // Orientation and Up-vector void setOrientation(float x, float y, float z, float upX, float upY, float upZ) { setOrientation(FloatPoint3D(x, y, z)); setUpVector(FloatPoint3D(upX, upY, upZ)); } - void setOrientation(const FloatPoint3D &orientation) { m_orientation = orientation; } const FloatPoint3D& orientation() const { return m_orientation; } - - // Up-vector - void setUpVector(const FloatPoint3D &upVector) { m_upVector = upVector; } const FloatPoint3D& upVector() const { return m_upVector; } // Velocity void setVelocity(float x, float y, float z) { setVelocity(FloatPoint3D(x, y, z)); } - void setVelocity(const FloatPoint3D &velocity) { m_velocity = velocity; } const FloatPoint3D& velocity() const { return m_velocity; } // Doppler factor - void setDopplerFactor(double dopplerFactor) { m_dopplerFactor = dopplerFactor; } + void setDopplerFactor(double); double dopplerFactor() const { return m_dopplerFactor; } // Speed of sound - void setSpeedOfSound(double speedOfSound) { m_speedOfSound = speedOfSound; } + void setSpeedOfSound(double); double speedOfSound() const { return m_speedOfSound; } + Mutex& listenerLock() { return m_listenerLock; } + void addPanner(PannerNode*); + void removePanner(PannerNode*); + + void trace(Visitor*) { } + private: AudioListener(); - // Position / Orientation + void setPosition(const FloatPoint3D&); + void setOrientation(const FloatPoint3D&); + void setUpVector(const FloatPoint3D&); + void setVelocity(const FloatPoint3D&); + + void markPannersAsDirty(unsigned); + FloatPoint3D m_position; FloatPoint3D m_orientation; FloatPoint3D m_upVector; - FloatPoint3D m_velocity; - double m_dopplerFactor; double m_speedOfSound; + + // Synchronize a panner's process() with setting of the state of the listener. + mutable Mutex m_listenerLock; + + // List for pannerNodes in context. + Vector<PannerNode*> m_panners; }; } // WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.idl b/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.idl index 0011fe0f560..b9668f513fa 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioListener.idl @@ -27,6 +27,7 @@ */ [ + WillBeGarbageCollected, Conditional=WEB_AUDIO ] interface AudioListener { attribute float dopplerFactor; // same as OpenAL (default 1.0) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp index 7e4b075f998..e48936c7335 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp @@ -48,6 +48,9 @@ AudioNode::AudioNode(AudioContext* context, float sampleRate) , m_nodeType(NodeTypeUnknown) , m_context(context) , m_sampleRate(sampleRate) +#if ENABLE(OILPAN) + , m_keepAlive(adoptPtr(new Persistent<AudioNode>(this))) +#endif , m_lastProcessingTime(-1) , m_lastNonSilentTime(-1) , m_normalRefCount(1) // start out with normal refCount == 1 (like WTF::RefCounted class) @@ -139,12 +142,6 @@ void AudioNode::setNodeType(NodeType type) #endif } -void AudioNode::lazyInitialize() -{ - if (!isInitialized()) - initialize(); -} - void AudioNode::addInput(PassOwnPtr<AudioNodeInput> input) { m_inputs.append(input); @@ -309,9 +306,7 @@ void AudioNode::setChannelCountMode(const String& mode, ExceptionState& exceptio } else if (mode == "explicit") { m_channelCountMode = Explicit; } else { - exceptionState.throwDOMException( - InvalidStateError, - "invalid mode '" + mode + "'; must be 'max', 'clamped-max', or 'explicit'."); + ASSERT_NOT_REACHED(); } if (m_channelCountMode != oldMode) @@ -340,9 +335,7 @@ void AudioNode::setChannelInterpretation(const String& interpretation, Exception } else if (interpretation == "discrete") { m_channelInterpretation = AudioBus::Discrete; } else { - exceptionState.throwDOMException( - InvalidStateError, - "invalid interpretation '" + interpretation + "'; must be 'speakers' or 'discrete'."); + ASSERT_NOT_REACHED(); } } @@ -478,6 +471,9 @@ void AudioNode::disableOutputsIfNecessary() void AudioNode::ref(RefType refType) { +#if ENABLE(OILPAN) + ASSERT(m_keepAlive); +#endif switch (refType) { case RefTypeNormal: atomicIncrement(&m_normalRefCount); @@ -531,7 +527,7 @@ void AudioNode::deref(RefType refType) // Once AudioContext::uninitialize() is called there's no more chances for deleteMarkedNodes() to get called, so we call here. // We can't call in AudioContext::~AudioContext() since it will never be called as long as any AudioNode is alive // because AudioNodes keep a reference to the context. - if (context()->isAudioThreadFinished()) + if (!context()->isInitialized()) context()->deleteMarkedNodes(); } @@ -592,6 +588,25 @@ void AudioNode::printNodeCounts() #endif // DEBUG_AUDIONODE_REFERENCES +void AudioNode::trace(Visitor* visitor) +{ + visitor->trace(m_context); + EventTargetWithInlineData::trace(visitor); +} + +#if ENABLE(OILPAN) +void AudioNode::clearKeepAlive() +{ + // It is safe to drop the self-persistent when the ref count + // of a AudioNode reaches zero. At that point, the + // AudioNode node is removed from the AudioContext and + // it cannot be reattached. Therefore, the reference count + // will not go above zero again. + ASSERT(m_keepAlive); + m_keepAlive = nullptr; +} +#endif + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.h index 61fc047bdd5..fb63c918e40 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.h @@ -26,7 +26,7 @@ #define AudioNode_h #include "bindings/v8/ScriptWrappable.h" -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" #include "platform/audio/AudioBus.h" #include "wtf/Forward.h" #include "wtf/OwnPtr.h" @@ -50,7 +50,9 @@ class ExceptionState; // An AudioDestinationNode has one input and no outputs and represents the final destination to the audio hardware. // Most processing nodes such as filters will have one input and one output, although multiple inputs and outputs are possible. -class AudioNode : public ScriptWrappable, public EventTargetWithInlineData { +// AudioNode has its own ref-counting mechanism that use RefTypes so we cannot use RefCountedGarbageCollected. +class AudioNode : public NoBaseWillBeGarbageCollectedFinalized<AudioNode>, public ScriptWrappable, public EventTargetWithInlineData { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(AudioNode); public: enum { ProcessingSizeInFrames = 128 }; @@ -109,17 +111,12 @@ public: // Called from context's audio thread. virtual void process(size_t framesToProcess) = 0; - // Resets DSP processing state (clears delay lines, filter memory, etc.) - // Called from context's audio thread. - virtual void reset() = 0; - // No significant resources should be allocated until initialize() is called. // Processing may not occur until a node is initialized. virtual void initialize(); virtual void uninitialize(); bool isInitialized() const { return m_isInitialized; } - void lazyInitialize(); unsigned numberOfInputs() const { return m_inputs.size(); } unsigned numberOfOutputs() const { return m_outputs.size(); } @@ -181,8 +178,14 @@ public: AudioBus::ChannelInterpretation internalChannelInterpretation() const { return m_channelInterpretation; } // EventTarget - virtual const AtomicString& interfaceName() const OVERRIDE; - virtual ExecutionContext* executionContext() const OVERRIDE; + virtual const AtomicString& interfaceName() const OVERRIDE FINAL; + virtual ExecutionContext* executionContext() const OVERRIDE FINAL; + + virtual void trace(Visitor*) OVERRIDE; + +#if ENABLE(OILPAN) + void clearKeepAlive(); +#endif protected: // Inputs and outputs must be created before the AudioNode is initialized. @@ -200,11 +203,23 @@ protected: private: volatile bool m_isInitialized; NodeType m_nodeType; - RefPtr<AudioContext> m_context; + RefPtrWillBeMember<AudioContext> m_context; float m_sampleRate; Vector<OwnPtr<AudioNodeInput> > m_inputs; Vector<OwnPtr<AudioNodeOutput> > m_outputs; +#if ENABLE(OILPAN) + // AudioNodes are in the oilpan heap but they are still reference counted at + // the same time. This is because we are not allowed to stop the audio + // thread and thus the audio thread cannot allocate objects in the oilpan + // heap. + // The m_keepAlive handle is used to keep a persistent reference to this + // AudioNode while someone has a reference to this AudioNode through a + // RefPtr. + GC_PLUGIN_IGNORE("http://crbug.com/353083") + OwnPtr<Persistent<AudioNode> > m_keepAlive; +#endif + double m_lastProcessingTime; double m_lastNonSilentTime; @@ -220,8 +235,10 @@ private: static int s_nodeCount[NodeTypeEnd]; #endif - virtual void refEventTarget() OVERRIDE { ref(); } - virtual void derefEventTarget() OVERRIDE { deref(); } +#if !ENABLE(OILPAN) + virtual void refEventTarget() OVERRIDE FINAL { ref(); } + virtual void derefEventTarget() OVERRIDE FINAL { deref(); } +#endif protected: unsigned m_channelCount; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.idl b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.idl index 35d98ccf302..4ed4d40b0db 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNode.idl @@ -22,23 +22,32 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum ChannelCountMode { + "max", + "clamped-max", + "explicit" +}; + +enum ChannelInterpretation { + "speakers", + "discrete" +}; + +// http://webaudio.github.io/web-audio-api/#idl-def-AudioNode + [ Conditional=WEB_AUDIO, Custom=Wrap, + WillBeGarbageCollected, ] interface AudioNode : EventTarget { - readonly attribute AudioContext context; - readonly attribute unsigned long numberOfInputs; - readonly attribute unsigned long numberOfOutputs; - - [RaisesException=Setter] attribute unsigned long channelCount; - - [RaisesException=Setter] attribute DOMString channelCountMode; - - [RaisesException=Setter] attribute DOMString channelInterpretation; - + // FIXME: AudioNode argument should not be nullable [RaisesException] void connect(AudioNode? destination, [Default=Undefined] optional unsigned long output, [Default=Undefined] optional unsigned long input); - - [RaisesException] void connect(AudioParam? destination, [Default=Undefined] optional unsigned long output); - + [RaisesException] void connect(AudioParam destination, [Default=Undefined] optional unsigned long output); [RaisesException] void disconnect([Default=Undefined] optional unsigned long output); + readonly attribute AudioContext context; + readonly attribute unsigned long numberOfInputs; + readonly attribute unsigned long numberOfOutputs; + [RaisesException=Setter] attribute unsigned long channelCount; + [RaisesException=Setter] attribute ChannelCountMode channelCountMode; + [RaisesException=Setter] attribute ChannelInterpretation channelInterpretation; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeInput.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeInput.h index 9f171a26ecf..8952863d554 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeInput.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeInput.h @@ -40,7 +40,7 @@ class AudioNodeOutput; // In the case of multiple connections, the input will act as a unity-gain summing junction, mixing all the outputs. // The number of channels of the input's bus is the maximum of the number of channels of all its connections. -class AudioNodeInput : public AudioSummingJunction { +class AudioNodeInput FINAL : public AudioSummingJunction { public: explicit AudioNodeInput(AudioNode*); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp index 9902699bb95..ef7a7ab2a01 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp @@ -146,11 +146,6 @@ unsigned AudioNodeOutput::renderingFanOutCount() const return m_renderingFanOutCount; } -unsigned AudioNodeOutput::renderingParamFanOutCount() const -{ - return m_renderingParamFanOutCount; -} - void AudioNodeOutput::addInput(AudioNodeInput* input) { ASSERT(context()->isGraphOwner()); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.h index 14e9272a306..31f9637ecc7 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.h @@ -62,10 +62,6 @@ public: // Unlike fanOutCount() it will not change during the course of a render quantum. unsigned renderingFanOutCount() const; - // renderingParamFanOutCount() is the number of AudioParams that we're connected to during rendering. - // Unlike paramFanOutCount() it will not change during the course of a render quantum. - unsigned renderingParamFanOutCount() const; - // Must be called with the context's graph lock. void disconnectAll(); @@ -144,8 +140,7 @@ private: unsigned m_renderingFanOutCount; unsigned m_renderingParamFanOutCount; - HashSet<RefPtr<AudioParam> > m_params; - typedef HashSet<RefPtr<AudioParam> >::iterator ParamsIterator; + WillBePersistentHeapHashSet<RefPtrWillBeMember<AudioParam> > m_params; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp index 8ff48e2ed9e..a356c93bd54 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp @@ -84,7 +84,7 @@ bool AudioParam::smooth() m_smoothedValue = m_value; else { // Dezipper - exponential approach. - m_smoothedValue += (m_value - m_smoothedValue) * m_smoothingConstant; + m_smoothedValue += (m_value - m_smoothedValue) * DefaultSmoothingConstant; // If we get close enough then snap to actual value. if (fabs(m_smoothedValue - m_value) < SnapThreshold) // FIXME: the threshold needs to be adjustable depending on range - but this is OK general purpose value. @@ -96,7 +96,7 @@ bool AudioParam::smooth() float AudioParam::finalValue() { - float value; + float value = m_value; calculateFinalValues(&value, 1, false); return value; } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.h index b6c30cbaeb8..ed25afabf79 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.h @@ -43,14 +43,14 @@ namespace WebCore { class AudioNodeOutput; -class AudioParam : public RefCounted<AudioParam>, public ScriptWrappable, public AudioSummingJunction { +class AudioParam FINAL : public RefCountedWillBeGarbageCollectedFinalized<AudioParam>, public ScriptWrappable, public AudioSummingJunction { public: static const double DefaultSmoothingConstant; static const double SnapThreshold; - static PassRefPtr<AudioParam> create(AudioContext* context, const String& name, double defaultValue, double minValue, double maxValue, unsigned units = 0) + static PassRefPtrWillBeRawPtr<AudioParam> create(AudioContext* context, const String& name, double defaultValue, double minValue, double maxValue, unsigned units = 0) { - return adoptRef(new AudioParam(context, name, defaultValue, minValue, maxValue, units)); + return adoptRefWillBeNoop(new AudioParam(context, name, defaultValue, minValue, maxValue, units)); } // AudioSummingJunction @@ -83,12 +83,11 @@ public: bool smooth(); void resetSmoothedValue() { m_smoothedValue = m_value; } - void setSmoothingConstant(double k) { m_smoothingConstant = k; } // Parameter automation. void setValueAtTime(float value, double time) { m_timeline.setValueAtTime(value, time); } void linearRampToValueAtTime(float value, double time) { m_timeline.linearRampToValueAtTime(value, time); } - void exponentialRampToValueAtTime(float value, double time) { m_timeline.exponentialRampToValueAtTime(value, time); } + void exponentialRampToValueAtTime(float value, double time, ExceptionState& es) { m_timeline.exponentialRampToValueAtTime(value, time, es); } void setTargetAtTime(float target, double time, double timeConstant) { m_timeline.setTargetAtTime(target, time, timeConstant); } void setValueCurveAtTime(Float32Array* curve, double time, double duration) { m_timeline.setValueCurveAtTime(curve, time, duration); } void cancelScheduledValues(double startTime) { m_timeline.cancelScheduledValues(startTime); } @@ -103,6 +102,8 @@ public: void connect(AudioNodeOutput*); void disconnect(AudioNodeOutput*); + void trace(Visitor*) { } + protected: AudioParam(AudioContext* context, const String& name, double defaultValue, double minValue, double maxValue, unsigned units = 0) : AudioSummingJunction(context) @@ -113,7 +114,6 @@ protected: , m_maxValue(maxValue) , m_units(units) , m_smoothedValue(defaultValue) - , m_smoothingConstant(DefaultSmoothingConstant) { ScriptWrappable::init(this); } @@ -132,7 +132,6 @@ private: // Smoothing (de-zippering) double m_smoothedValue; - double m_smoothingConstant; AudioParamTimeline m_timeline; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.idl b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.idl index bb903874f3b..2d55ad31792 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParam.idl @@ -27,6 +27,7 @@ */ [ + WillBeGarbageCollected, Conditional=WEB_AUDIO ] interface AudioParam { attribute float value; @@ -42,7 +43,7 @@ // Parameter automation. void setValueAtTime(float value, double time); void linearRampToValueAtTime(float value, double time); - void exponentialRampToValueAtTime(float value, double time); + [RaisesException] void exponentialRampToValueAtTime(float value, double time); // Exponentially approach the target with a rate having the given time constant. void setTargetAtTime(float target, double time, double timeConstant); @@ -54,6 +55,4 @@ // Cancels all scheduled parameter changes with times greater than or equal to startTime. void cancelScheduledValues(double startTime); - [MeasureAs=LegacyWebAudio, ImplementedAs=setTargetAtTime] void setTargetValueAtTime(float targetValue, double time, double timeConstant); - }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp index 51d5293244a..eb107c04c1a 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp @@ -29,6 +29,8 @@ #include "modules/webaudio/AudioParamTimeline.h" +#include "bindings/v8/ExceptionState.h" +#include "core/dom/ExceptionCode.h" #include "platform/audio/AudioUtilities.h" #include "platform/FloatConversion.h" #include "wtf/MathExtras.h" @@ -40,22 +42,30 @@ namespace WebCore { void AudioParamTimeline::setValueAtTime(float value, double time) { - insertEvent(ParamEvent(ParamEvent::SetValue, value, time, 0, 0, 0)); + insertEvent(ParamEvent(ParamEvent::SetValue, value, time, 0, 0, nullptr)); } void AudioParamTimeline::linearRampToValueAtTime(float value, double time) { - insertEvent(ParamEvent(ParamEvent::LinearRampToValue, value, time, 0, 0, 0)); + insertEvent(ParamEvent(ParamEvent::LinearRampToValue, value, time, 0, 0, nullptr)); } -void AudioParamTimeline::exponentialRampToValueAtTime(float value, double time) +void AudioParamTimeline::exponentialRampToValueAtTime(float value, double time, ExceptionState& exceptionState) { - insertEvent(ParamEvent(ParamEvent::ExponentialRampToValue, value, time, 0, 0, 0)); + ASSERT(isMainThread()); + if (value <= 0) { + exceptionState.throwDOMException( + InvalidStateError, + "Target value for exponential ramp must be positive: " + String::number(value)); + return; + } + + insertEvent(ParamEvent(ParamEvent::ExponentialRampToValue, value, time, 0, 0, nullptr)); } void AudioParamTimeline::setTargetAtTime(float target, double time, double timeConstant) { - insertEvent(ParamEvent(ParamEvent::SetTarget, target, time, timeConstant, 0, 0)); + insertEvent(ParamEvent(ParamEvent::SetTarget, target, time, timeConstant, 0, nullptr)); } void AudioParamTimeline::setValueCurveAtTime(Float32Array* curve, double time, double duration) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h index 335a9ac2116..350d3bcb89f 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h @@ -46,7 +46,7 @@ public: void setValueAtTime(float value, double time); void linearRampToValueAtTime(float value, double time); - void exponentialRampToValueAtTime(float value, double time); + void exponentialRampToValueAtTime(float value, double time, ExceptionState&); void setTargetAtTime(float target, double time, double timeConstant); void setValueCurveAtTime(Float32Array* curve, double time, double duration); void cancelScheduledValues(double startTime); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.cpp index ac8eb99bcbc..112994af876 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.cpp @@ -28,18 +28,16 @@ #include "modules/webaudio/AudioProcessingEvent.h" -#include "core/events/ThreadLocalEventNames.h" - namespace WebCore { -PassRefPtr<AudioProcessingEvent> AudioProcessingEvent::create() +PassRefPtrWillBeRawPtr<AudioProcessingEvent> AudioProcessingEvent::create() { - return adoptRef(new AudioProcessingEvent); + return adoptRefWillBeNoop(new AudioProcessingEvent); } -PassRefPtr<AudioProcessingEvent> AudioProcessingEvent::create(PassRefPtr<AudioBuffer> inputBuffer, PassRefPtr<AudioBuffer> outputBuffer) +PassRefPtrWillBeRawPtr<AudioProcessingEvent> AudioProcessingEvent::create(PassRefPtrWillBeRawPtr<AudioBuffer> inputBuffer, PassRefPtrWillBeRawPtr<AudioBuffer> outputBuffer, double playbackTime) { - return adoptRef(new AudioProcessingEvent(inputBuffer, outputBuffer)); + return adoptRefWillBeNoop(new AudioProcessingEvent(inputBuffer, outputBuffer, playbackTime)); } AudioProcessingEvent::AudioProcessingEvent() @@ -47,10 +45,11 @@ AudioProcessingEvent::AudioProcessingEvent() ScriptWrappable::init(this); } -AudioProcessingEvent::AudioProcessingEvent(PassRefPtr<AudioBuffer> inputBuffer, PassRefPtr<AudioBuffer> outputBuffer) +AudioProcessingEvent::AudioProcessingEvent(PassRefPtrWillBeRawPtr<AudioBuffer> inputBuffer, PassRefPtrWillBeRawPtr<AudioBuffer> outputBuffer, double playbackTime) : Event(EventTypeNames::audioprocess, true, false) , m_inputBuffer(inputBuffer) , m_outputBuffer(outputBuffer) + , m_playbackTime(playbackTime) { ScriptWrappable::init(this); } @@ -64,6 +63,13 @@ const AtomicString& AudioProcessingEvent::interfaceName() const return EventNames::AudioProcessingEvent; } +void AudioProcessingEvent::trace(Visitor* visitor) +{ + visitor->trace(m_inputBuffer); + visitor->trace(m_outputBuffer); + Event::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.h index de2d78332f5..e938fe75748 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.h @@ -25,7 +25,7 @@ #ifndef AudioProcessingEvent_h #define AudioProcessingEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "modules/webaudio/AudioBuffer.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" @@ -34,24 +34,28 @@ namespace WebCore { class AudioBuffer; -class AudioProcessingEvent : public Event { +class AudioProcessingEvent FINAL : public Event { public: - static PassRefPtr<AudioProcessingEvent> create(); - static PassRefPtr<AudioProcessingEvent> create(PassRefPtr<AudioBuffer> inputBuffer, PassRefPtr<AudioBuffer> outputBuffer); + static PassRefPtrWillBeRawPtr<AudioProcessingEvent> create(); + static PassRefPtrWillBeRawPtr<AudioProcessingEvent> create(PassRefPtrWillBeRawPtr<AudioBuffer> inputBuffer, PassRefPtrWillBeRawPtr<AudioBuffer> outputBuffer, double playbackTime); virtual ~AudioProcessingEvent(); AudioBuffer* inputBuffer() { return m_inputBuffer.get(); } AudioBuffer* outputBuffer() { return m_outputBuffer.get(); } + double playbackTime() const { return m_playbackTime; } - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: AudioProcessingEvent(); - AudioProcessingEvent(PassRefPtr<AudioBuffer> inputBuffer, PassRefPtr<AudioBuffer> outputBuffer); + AudioProcessingEvent(PassRefPtrWillBeRawPtr<AudioBuffer> inputBuffer, PassRefPtrWillBeRawPtr<AudioBuffer> outputBuffer, double playbackTime); - RefPtr<AudioBuffer> m_inputBuffer; - RefPtr<AudioBuffer> m_outputBuffer; + RefPtrWillBeMember<AudioBuffer> m_inputBuffer; + RefPtrWillBeMember<AudioBuffer> m_outputBuffer; + double m_playbackTime; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.idl b/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.idl index ed8f90a0a3a..2b812825dd0 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioProcessingEvent.idl @@ -25,6 +25,7 @@ [ Conditional=WEB_AUDIO ] interface AudioProcessingEvent : Event { + readonly attribute double playbackTime; readonly attribute AudioBuffer inputBuffer; readonly attribute AudioBuffer outputBuffer; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp index f53e18cf44e..e96f2c89ff9 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp @@ -30,9 +30,9 @@ #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "core/events/Event.h" -#include "platform/audio/AudioUtilities.h" +#include "modules/EventModules.h" #include "modules/webaudio/AudioContext.h" +#include "platform/audio/AudioUtilities.h" #include <algorithm> #include "wtf/MathExtras.h" @@ -48,7 +48,6 @@ AudioScheduledSourceNode::AudioScheduledSourceNode(AudioContext* context, float , m_startTime(0) , m_endTime(UnknownTime) , m_hasEndedListener(false) - , m_stopCalled(false) { } @@ -91,7 +90,6 @@ void AudioScheduledSourceNode::updateSchedulingInfo(size_t quantumFrameSize, if (m_playbackState == SCHEDULED_STATE) { // Increment the active source count only if we're transitioning from SCHEDULED_STATE to PLAYING_STATE. m_playbackState = PLAYING_STATE; - context()->incrementActiveSourceCount(); } quantumFrameOffset = startFrame > quantumStartFrame ? startFrame - quantumStartFrame : 0; @@ -137,7 +135,6 @@ void AudioScheduledSourceNode::updateSchedulingInfo(size_t quantumFrameSize, return; } - void AudioScheduledSourceNode::start(double when, ExceptionState& exceptionState) { ASSERT(isMainThread()); @@ -157,28 +154,23 @@ void AudioScheduledSourceNode::stop(double when, ExceptionState& exceptionState) { ASSERT(isMainThread()); - if (m_stopCalled) { - exceptionState.throwDOMException( - InvalidStateError, - "cannot call stop more than once."); - } else if (m_playbackState == UNSCHEDULED_STATE) { + if (m_playbackState == UNSCHEDULED_STATE) { exceptionState.throwDOMException( InvalidStateError, "cannot call stop without calling start first."); } else { - // This can only happen from the SCHEDULED_STATE or PLAYING_STATE. The UNSCHEDULED_STATE is - // handled above, and the FINISHED_STATE is only reachable after stop() has been called, and - // hence m_stopCalled is true. But that case is handled above. + // stop() can be called more than once, with the last call to stop taking effect, unless the + // source has already stopped due to earlier calls to stop. No exceptions are thrown in any + // case. when = max(0.0, when); m_endTime = when; - m_stopCalled = true; } } -void AudioScheduledSourceNode::setOnended(PassRefPtr<EventListener> listener, DOMWrapperWorld* isolatedWorld) +void AudioScheduledSourceNode::setOnended(PassRefPtr<EventListener> listener) { m_hasEndedListener = listener; - setAttributeEventListener(EventTypeNames::ended, listener, isolatedWorld); + setAttributeEventListener(EventTypeNames::ended, listener); } void AudioScheduledSourceNode::finish() @@ -187,7 +179,6 @@ void AudioScheduledSourceNode::finish() // Let the context dereference this AudioNode. context()->notifyNodeFinishedProcessing(this); m_playbackState = FINISHED_STATE; - context()->decrementActiveSourceCount(); } if (m_hasEndedListener) { @@ -211,8 +202,8 @@ AudioScheduledSourceNode::NotifyEndedTask::NotifyEndedTask(PassRefPtr<AudioSched void AudioScheduledSourceNode::NotifyEndedTask::notifyEnded() { - RefPtr<Event> event = Event::create(EventTypeNames::ended); - event->setTarget(m_scheduledNode); + RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::ended); + event->setTarget(m_scheduledNode.get()); m_scheduledNode->dispatchEvent(event.get()); } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h index e89cd76bf0d..3942ecd3589 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h @@ -40,7 +40,7 @@ public: // These are the possible states an AudioScheduledSourceNode can be in: // // UNSCHEDULED_STATE - Initial playback state. Created, but not yet scheduled. - // SCHEDULED_STATE - Scheduled to play (via noteOn() or noteGrainOn()), but not yet playing. + // SCHEDULED_STATE - Scheduled to play (via start()), but not yet playing. // PLAYING_STATE - Generating sound. // FINISHED_STATE - Finished generating sound. // @@ -77,8 +77,8 @@ public: bool isPlayingOrScheduled() const { return m_playbackState == PLAYING_STATE || m_playbackState == SCHEDULED_STATE; } bool hasFinished() const { return m_playbackState == FINISHED_STATE; } - EventListener* onended(DOMWrapperWorld* isolatedWorld) { return getAttributeEventListener(EventTypeNames::ended, isolatedWorld); } - void setOnended(PassRefPtr<EventListener>, DOMWrapperWorld* isolatedWorld = 0); + EventListener* onended() { return getAttributeEventListener(EventTypeNames::ended); } + void setOnended(PassRefPtr<EventListener>); protected: // Get frame information for the current time quantum. @@ -109,7 +109,6 @@ protected: double m_endTime; // in seconds bool m_hasEndedListener; - bool m_stopCalled; static const double UnknownTime; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioSourceNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioSourceNode.h index b0883e10c5a..a8105b39993 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioSourceNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioSourceNode.h @@ -41,8 +41,8 @@ public: ScriptWrappable::init(this); } protected: - virtual double tailTime() const OVERRIDE { return 0; } - virtual double latencyTime() const OVERRIDE { return 0; } + virtual double tailTime() const OVERRIDE FINAL { return 0; } + virtual double latencyTime() const OVERRIDE FINAL { return 0; } }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/AudioSummingJunction.h b/chromium/third_party/WebKit/Source/modules/webaudio/AudioSummingJunction.h index a2e789f04b2..ca21fe6cb02 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/AudioSummingJunction.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/AudioSummingJunction.h @@ -26,6 +26,7 @@ #define AudioSummingJunction_h #include "platform/audio/AudioBus.h" +#include "platform/heap/Handle.h" #include "wtf/HashSet.h" #include "wtf/Vector.h" @@ -54,23 +55,18 @@ public: // Rendering code accesses its version of the current connections here. unsigned numberOfRenderingConnections() const { return m_renderingOutputs.size(); } AudioNodeOutput* renderingOutput(unsigned i) { return m_renderingOutputs[i]; } - const AudioNodeOutput* renderingOutput(unsigned i) const { return m_renderingOutputs[i]; } bool isConnected() const { return numberOfRenderingConnections() > 0; } virtual bool canUpdateState() = 0; virtual void didUpdate() = 0; protected: - RefPtr<AudioContext> m_context; + RefPtrWillBePersistent<AudioContext> m_context; // m_outputs contains the AudioNodeOutputs representing current connections which are not disabled. // The rendering code should never use this directly, but instead uses m_renderingOutputs. HashSet<AudioNodeOutput*> m_outputs; - // numberOfConnections() should never be called from the audio rendering thread. - // Instead numberOfRenderingConnections() and renderingOutput() should be used. - unsigned numberOfConnections() const { return m_outputs.size(); } - // m_renderingOutputs is a copy of m_outputs which will never be modified during the graph rendering on the audio thread. // This is the list which is used by the rendering code. // Whenever m_outputs is modified, the context is told so it can later update m_renderingOutputs from m_outputs at a safe time. diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp index 5136ae118cd..45b663be10b 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp @@ -40,73 +40,73 @@ namespace WebCore { // settings of the Biquad. static const double MaxBiquadDelayTime = 0.2; -void BiquadDSPKernel::updateCoefficientsIfNecessary(bool useSmoothing, bool forceUpdate) +void BiquadDSPKernel::updateCoefficientsIfNecessary() { - if (forceUpdate || biquadProcessor()->filterCoefficientsDirty()) { - double value1; - double value2; + if (biquadProcessor()->filterCoefficientsDirty()) { + double cutoffFrequency; + double Q; double gain; double detune; // in Cents if (biquadProcessor()->hasSampleAccurateValues()) { - value1 = biquadProcessor()->parameter1()->finalValue(); - value2 = biquadProcessor()->parameter2()->finalValue(); + cutoffFrequency = biquadProcessor()->parameter1()->finalValue(); + Q = biquadProcessor()->parameter2()->finalValue(); gain = biquadProcessor()->parameter3()->finalValue(); detune = biquadProcessor()->parameter4()->finalValue(); - } else if (useSmoothing) { - value1 = biquadProcessor()->parameter1()->smoothedValue(); - value2 = biquadProcessor()->parameter2()->smoothedValue(); + } else { + cutoffFrequency = biquadProcessor()->parameter1()->smoothedValue(); + Q = biquadProcessor()->parameter2()->smoothedValue(); gain = biquadProcessor()->parameter3()->smoothedValue(); detune = biquadProcessor()->parameter4()->smoothedValue(); - } else { - value1 = biquadProcessor()->parameter1()->value(); - value2 = biquadProcessor()->parameter2()->value(); - gain = biquadProcessor()->parameter3()->value(); - detune = biquadProcessor()->parameter4()->value(); } - // Convert from Hertz to normalized frequency 0 -> 1. - double nyquist = this->nyquist(); - double normalizedFrequency = value1 / nyquist; + updateCoefficients(cutoffFrequency, Q, gain, detune); + } +} - // Offset frequency by detune. - if (detune) - normalizedFrequency *= pow(2, detune / 1200); +void BiquadDSPKernel::updateCoefficients(double cutoffFrequency, double Q, double gain, double detune) +{ + // Convert from Hertz to normalized frequency 0 -> 1. + double nyquist = this->nyquist(); + double normalizedFrequency = cutoffFrequency / nyquist; - // Configure the biquad with the new filter parameters for the appropriate type of filter. - switch (biquadProcessor()->type()) { - case BiquadProcessor::LowPass: - m_biquad.setLowpassParams(normalizedFrequency, value2); - break; + // Offset frequency by detune. + if (detune) + normalizedFrequency *= pow(2, detune / 1200); - case BiquadProcessor::HighPass: - m_biquad.setHighpassParams(normalizedFrequency, value2); - break; + // Configure the biquad with the new filter parameters for the appropriate type of filter. + switch (biquadProcessor()->type()) { + case BiquadProcessor::LowPass: + m_biquad.setLowpassParams(normalizedFrequency, Q); + break; - case BiquadProcessor::BandPass: - m_biquad.setBandpassParams(normalizedFrequency, value2); - break; + case BiquadProcessor::HighPass: + m_biquad.setHighpassParams(normalizedFrequency, Q); + break; - case BiquadProcessor::LowShelf: - m_biquad.setLowShelfParams(normalizedFrequency, gain); - break; + case BiquadProcessor::BandPass: + m_biquad.setBandpassParams(normalizedFrequency, Q); + break; - case BiquadProcessor::HighShelf: - m_biquad.setHighShelfParams(normalizedFrequency, gain); - break; + case BiquadProcessor::LowShelf: + m_biquad.setLowShelfParams(normalizedFrequency, gain); + break; - case BiquadProcessor::Peaking: - m_biquad.setPeakingParams(normalizedFrequency, value2, gain); - break; + case BiquadProcessor::HighShelf: + m_biquad.setHighShelfParams(normalizedFrequency, gain); + break; - case BiquadProcessor::Notch: - m_biquad.setNotchParams(normalizedFrequency, value2); - break; + case BiquadProcessor::Peaking: + m_biquad.setPeakingParams(normalizedFrequency, Q, gain); + break; - case BiquadProcessor::Allpass: - m_biquad.setAllpassParams(normalizedFrequency, value2); - break; - } + case BiquadProcessor::Notch: + m_biquad.setNotchParams(normalizedFrequency, Q); + break; + + case BiquadProcessor::Allpass: + m_biquad.setAllpassParams(normalizedFrequency, Q); + break; } } @@ -118,7 +118,14 @@ void BiquadDSPKernel::process(const float* source, float* destination, size_t fr // FIXME: as an optimization, implement a way that a Biquad object can simply copy its internal filter coefficients from another Biquad object. // Then re-factor this code to only run for the first BiquadDSPKernel of each BiquadProcessor. - updateCoefficientsIfNecessary(true, false); + + // The audio thread can't block on this lock; skip updating the coefficients for this block if + // necessary. We'll get them the next time around. + { + MutexTryLocker tryLocker(m_processLock); + if (tryLocker.locked()) + updateCoefficientsIfNecessary(); + } m_biquad.process(source, destination, framesToProcess); } @@ -142,12 +149,33 @@ void BiquadDSPKernel::getFrequencyResponse(int nFrequencies, for (int k = 0; k < nFrequencies; ++k) frequency[k] = narrowPrecisionToFloat(frequencyHz[k] / nyquist); - // We want to get the final values of the coefficients and compute - // the response from that instead of some intermediate smoothed - // set. Forcefully update the coefficients even if they are not - // dirty. + double cutoffFrequency; + double Q; + double gain; + double detune; // in Cents + + { + // Get a copy of the current biquad filter coefficients so we can update the biquad with + // these values. We need to synchronize with process() to prevent process() from updating + // the filter coefficients while we're trying to access them. The process will update it + // next time around. + // + // The BiquadDSPKernel object here (along with it's Biquad object) is for querying the + // frequency response and is NOT the same as the one in process() which is used for + // performing the actual filtering. This one is is created in + // BiquadProcessor::getFrequencyResponse for this purpose. Both, however, point to the same + // BiquadProcessor object. + // + // FIXME: Simplify this: crbug.com/390266 + MutexLocker processLocker(m_processLock); + + cutoffFrequency = biquadProcessor()->parameter1()->value(); + Q = biquadProcessor()->parameter2()->value(); + gain = biquadProcessor()->parameter3()->value(); + detune = biquadProcessor()->parameter4()->value(); + } - updateCoefficientsIfNecessary(false, true); + updateCoefficients(cutoffFrequency, Q, gain, detune); m_biquad.getFrequencyResponse(nFrequencies, frequency.data(), magResponse, phaseResponse); } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h index c2e8ac8cbb5..d0b12b332f0 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h @@ -35,7 +35,7 @@ class BiquadProcessor; // BiquadDSPKernel is an AudioDSPKernel and is responsible for filtering one channel of a BiquadProcessor using a Biquad object. -class BiquadDSPKernel : public AudioDSPKernel { +class BiquadDSPKernel FINAL : public AudioDSPKernel { public: explicit BiquadDSPKernel(BiquadProcessor* processor) : AudioDSPKernel(processor) @@ -43,8 +43,8 @@ public: } // AudioDSPKernel - virtual void process(const float* source, float* dest, size_t framesToProcess); - virtual void reset() { m_biquad.reset(); } + virtual void process(const float* source, float* dest, size_t framesToProcess) OVERRIDE; + virtual void reset() OVERRIDE { m_biquad.reset(); } // Get the magnitude and phase response of the filter at the given // set of frequencies (in Hz). The phase response is in radians. @@ -62,12 +62,13 @@ protected: // To prevent audio glitches when parameters are changed, // dezippering is used to slowly change the parameters. - // |useSmoothing| implies that we want to update using the - // smoothed values. Otherwise the final target values are - // used. If |forceUpdate| is true, we update the coefficients even - // if they are not dirty. (Used when computing the frequency - // response.) - void updateCoefficientsIfNecessary(bool useSmoothing, bool forceUpdate); + void updateCoefficientsIfNecessary(); + // Update the biquad cofficients with the given parameters + void updateCoefficients(double frequency, double Q, double gain, double detune); + +private: + // Synchronize process() with getting and setting the filter coefficients. + mutable Mutex m_processLock; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.cpp index 1aa8f4a910a..7069d1f3f04 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.cpp @@ -82,8 +82,6 @@ void BiquadFilterNode::setType(const String& type) setType(BiquadProcessor::Notch); else if (type == "allpass") setType(BiquadProcessor::Allpass); - else - ASSERT_NOT_REACHED(); } bool BiquadFilterNode::setType(unsigned type) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.h index 0ba4681c304..94bd76e90d2 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.h @@ -32,7 +32,7 @@ namespace WebCore { class AudioParam; -class BiquadFilterNode : public AudioBasicProcessorNode { +class BiquadFilterNode FINAL : public AudioBasicProcessorNode { public: // These must be defined as in the .idl file and must match those in the BiquadProcessor class. enum { @@ -46,13 +46,12 @@ public: ALLPASS = 7 }; - static PassRefPtr<BiquadFilterNode> create(AudioContext* context, float sampleRate) + static PassRefPtrWillBeRawPtr<BiquadFilterNode> create(AudioContext* context, float sampleRate) { - return adoptRef(new BiquadFilterNode(context, sampleRate)); + return adoptRefWillBeNoop(new BiquadFilterNode(context, sampleRate)); } String type() const; - bool setType(unsigned); // Returns true on success. void setType(const String&); AudioParam* frequency() { return biquadProcessor()->parameter1(); } @@ -70,6 +69,7 @@ private: BiquadFilterNode(AudioContext*, float sampleRate); BiquadProcessor* biquadProcessor() { return static_cast<BiquadProcessor*>(processor()); } + bool setType(unsigned); // Returns true on success. }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.idl b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.idl index 2422dfb1a98..9783ab2a22b 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.idl @@ -22,20 +22,21 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum BiquadFilterType { + "lowpass", + "highpass", + "bandpass", + "lowshelf", + "highshelf", + "peaking", + "notch", + "allpass" +}; + [ Conditional=WEB_AUDIO ] interface BiquadFilterNode : AudioNode { - // Filter type. - const unsigned short LOWPASS = 0; - const unsigned short HIGHPASS = 1; - const unsigned short BANDPASS = 2; - const unsigned short LOWSHELF = 3; - const unsigned short HIGHSHELF = 4; - const unsigned short PEAKING = 5; - const unsigned short NOTCH = 6; - const unsigned short ALLPASS = 7; - - [Custom=Setter] attribute DOMString type; + attribute BiquadFilterType type; readonly attribute AudioParam frequency; // in Hertz readonly attribute AudioParam detune; // in Cents diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadProcessor.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadProcessor.cpp index 2655abeb215..f2410ce928d 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadProcessor.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadProcessor.cpp @@ -35,10 +35,10 @@ namespace WebCore { BiquadProcessor::BiquadProcessor(AudioContext* context, float sampleRate, size_t numberOfChannels, bool autoInitialize) : AudioDSPKernelProcessor(sampleRate, numberOfChannels) , m_type(LowPass) - , m_parameter1(0) - , m_parameter2(0) - , m_parameter3(0) - , m_parameter4(0) + , m_parameter1(nullptr) + , m_parameter2(nullptr) + , m_parameter3(nullptr) + , m_parameter4(nullptr) , m_filterCoefficientsDirty(true) , m_hasSampleAccurateValues(false) { diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadProcessor.h b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadProcessor.h index 6c3e3307094..7647586c36e 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/BiquadProcessor.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/BiquadProcessor.h @@ -36,7 +36,7 @@ namespace WebCore { // BiquadProcessor is an AudioDSPKernelProcessor which uses Biquad objects to implement several common filters. -class BiquadProcessor : public AudioDSPKernelProcessor { +class BiquadProcessor FINAL : public AudioDSPKernelProcessor { public: enum FilterType { LowPass = 0, @@ -53,9 +53,9 @@ public: virtual ~BiquadProcessor(); - virtual PassOwnPtr<AudioDSPKernel> createKernel(); + virtual PassOwnPtr<AudioDSPKernel> createKernel() OVERRIDE; - virtual void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess); + virtual void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess) OVERRIDE; // Get the magnitude and phase response of the filter at the given // set of frequencies (in Hz). The phase response is in radians. @@ -80,10 +80,10 @@ public: private: FilterType m_type; - RefPtr<AudioParam> m_parameter1; - RefPtr<AudioParam> m_parameter2; - RefPtr<AudioParam> m_parameter3; - RefPtr<AudioParam> m_parameter4; + RefPtrWillBePersistent<AudioParam> m_parameter1; + RefPtrWillBePersistent<AudioParam> m_parameter2; + RefPtrWillBePersistent<AudioParam> m_parameter3; + RefPtrWillBePersistent<AudioParam> m_parameter4; // so DSP kernels know when to re-compute coefficients bool m_filterCoefficientsDirty; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.cpp index 43b86b4d389..96befdeb438 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.cpp @@ -40,12 +40,12 @@ const unsigned DefaultNumberOfOutputChannels = 1; namespace WebCore { -PassRefPtr<ChannelMergerNode> ChannelMergerNode::create(AudioContext* context, float sampleRate, unsigned numberOfInputs) +PassRefPtrWillBeRawPtr<ChannelMergerNode> ChannelMergerNode::create(AudioContext* context, float sampleRate, unsigned numberOfInputs) { if (!numberOfInputs || numberOfInputs > AudioContext::maxNumberOfChannels()) - return 0; + return nullptr; - return adoptRef(new ChannelMergerNode(context, sampleRate, numberOfInputs)); + return adoptRefWillBeNoop(new ChannelMergerNode(context, sampleRate, numberOfInputs)); } ChannelMergerNode::ChannelMergerNode(AudioContext* context, float sampleRate, unsigned numberOfInputs) @@ -76,29 +76,33 @@ void ChannelMergerNode::process(size_t framesToProcess) // Merge all the channels from all the inputs into one output. unsigned outputChannelIndex = 0; + unsigned maxAllowedOutputChannels = output->numberOfChannels(); + for (unsigned i = 0; i < numberOfInputs(); ++i) { AudioNodeInput* input = this->input(i); if (input->isConnected()) { unsigned numberOfInputChannels = input->bus()->numberOfChannels(); - // Merge channels from this particular input. + // Merge channels from this particular input, but be careful not to exceed the number of + // output channels. (This can happen if there are many inputs with each input + // containing many channels.) for (unsigned j = 0; j < numberOfInputChannels; ++j) { - AudioChannel* inputChannel = input->bus()->channel(j); - AudioChannel* outputChannel = output->bus()->channel(outputChannelIndex); - outputChannel->copyFrom(inputChannel); + if (outputChannelIndex < maxAllowedOutputChannels) { + AudioChannel* inputChannel = input->bus()->channel(j); + AudioChannel* outputChannel = output->bus()->channel(outputChannelIndex); + outputChannel->copyFrom(inputChannel); - ++outputChannelIndex; + ++outputChannelIndex; + } } } + if (outputChannelIndex >= maxAllowedOutputChannels) + break; } ASSERT(outputChannelIndex == output->numberOfChannels()); } -void ChannelMergerNode::reset() -{ -} - // Any time a connection or disconnection happens on any of our inputs, we potentially need to change the // number of channels of our output. void ChannelMergerNode::checkNumberOfChannelsForInput(AudioNodeInput* input) @@ -113,6 +117,9 @@ void ChannelMergerNode::checkNumberOfChannelsForInput(AudioNodeInput* input) numberOfOutputChannels += input->numberOfChannels(); } + // If the actual number of channels exceeds the max allowed, just drop the excess. + numberOfOutputChannels = std::min(numberOfOutputChannels, AudioContext::maxNumberOfChannels()); + // Set the correct number of channels on the output AudioNodeOutput* output = this->output(0); ASSERT(output); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h index a15b6fa5122..ea62eff3175 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h @@ -36,16 +36,15 @@ namespace WebCore { class AudioContext; -class ChannelMergerNode : public AudioNode { +class ChannelMergerNode FINAL : public AudioNode { public: - static PassRefPtr<ChannelMergerNode> create(AudioContext*, float sampleRate, unsigned numberOfInputs); + static PassRefPtrWillBeRawPtr<ChannelMergerNode> create(AudioContext*, float sampleRate, unsigned numberOfInputs); // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); + virtual void process(size_t framesToProcess) OVERRIDE; // Called in the audio thread (pre-rendering task) when the number of channels for an input may have changed. - virtual void checkNumberOfChannelsForInput(AudioNodeInput*); + virtual void checkNumberOfChannelsForInput(AudioNodeInput*) OVERRIDE; private: unsigned m_desiredNumberOfOutputChannels; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.cpp index 4009ba49373..18a5e1a6848 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.cpp @@ -34,12 +34,12 @@ namespace WebCore { -PassRefPtr<ChannelSplitterNode> ChannelSplitterNode::create(AudioContext* context, float sampleRate, unsigned numberOfOutputs) +PassRefPtrWillBeRawPtr<ChannelSplitterNode> ChannelSplitterNode::create(AudioContext* context, float sampleRate, unsigned numberOfOutputs) { if (!numberOfOutputs || numberOfOutputs > AudioContext::maxNumberOfChannels()) - return 0; + return nullptr; - return adoptRef(new ChannelSplitterNode(context, sampleRate, numberOfOutputs)); + return adoptRefWillBeNoop(new ChannelSplitterNode(context, sampleRate, numberOfOutputs)); } ChannelSplitterNode::ChannelSplitterNode(AudioContext* context, float sampleRate, unsigned numberOfOutputs) @@ -79,10 +79,6 @@ void ChannelSplitterNode::process(size_t framesToProcess) } } -void ChannelSplitterNode::reset() -{ -} - } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h index c3c4a668e6a..32bdbd78833 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h @@ -32,13 +32,12 @@ namespace WebCore { class AudioContext; -class ChannelSplitterNode : public AudioNode { +class ChannelSplitterNode FINAL : public AudioNode { public: - static PassRefPtr<ChannelSplitterNode> create(AudioContext*, float sampleRate, unsigned numberOfOutputs); + static PassRefPtrWillBeRawPtr<ChannelSplitterNode> create(AudioContext*, float sampleRate, unsigned numberOfOutputs); // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); + virtual void process(size_t framesToProcess) OVERRIDE; private: virtual double tailTime() const OVERRIDE { return 0; } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp index cef9bca9c78..a0eac4de379 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp @@ -28,6 +28,8 @@ #include "modules/webaudio/ConvolverNode.h" +#include "bindings/v8/ExceptionState.h" +#include "core/dom/ExceptionCode.h" #include "platform/audio/Reverb.h" #include "modules/webaudio/AudioBuffer.h" #include "modules/webaudio/AudioContext.h" @@ -90,13 +92,6 @@ void ConvolverNode::process(size_t framesToProcess) } } -void ConvolverNode::reset() -{ - MutexLocker locker(m_processLock); - if (m_reverb.get()) - m_reverb->reset(); -} - void ConvolverNode::initialize() { if (isInitialized()) @@ -114,13 +109,21 @@ void ConvolverNode::uninitialize() AudioNode::uninitialize(); } -void ConvolverNode::setBuffer(AudioBuffer* buffer) +void ConvolverNode::setBuffer(AudioBuffer* buffer, ExceptionState& exceptionState) { ASSERT(isMainThread()); if (!buffer) return; + if (buffer->sampleRate() != context()->sampleRate()) { + exceptionState.throwDOMException( + NotSupportedError, + "The buffer sample rate of " + String::number(buffer->sampleRate()) + + " does not match the context rate of " + String::number(context()->sampleRate()) + + " Hz."); + } + unsigned numberOfChannels = buffer->numberOfChannels(); size_t bufferLength = buffer->length(); @@ -176,6 +179,12 @@ double ConvolverNode::latencyTime() const return std::numeric_limits<double>::infinity(); } +void ConvolverNode::trace(Visitor* visitor) +{ + visitor->trace(m_buffer); + AudioNode::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h index e5e33e62691..02ad70b3a8f 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h @@ -33,30 +33,32 @@ namespace WebCore { class AudioBuffer; +class ExceptionState; class Reverb; -class ConvolverNode : public AudioNode { +class ConvolverNode FINAL : public AudioNode { public: - static PassRefPtr<ConvolverNode> create(AudioContext* context, float sampleRate) + static PassRefPtrWillBeRawPtr<ConvolverNode> create(AudioContext* context, float sampleRate) { - return adoptRef(new ConvolverNode(context, sampleRate)); + return adoptRefWillBeNoop(new ConvolverNode(context, sampleRate)); } virtual ~ConvolverNode(); // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); - virtual void initialize(); - virtual void uninitialize(); + virtual void process(size_t framesToProcess) OVERRIDE; + virtual void initialize() OVERRIDE; + virtual void uninitialize() OVERRIDE; // Impulse responses - void setBuffer(AudioBuffer*); + void setBuffer(AudioBuffer*, ExceptionState&); AudioBuffer* buffer(); bool normalize() const { return m_normalize; } void setNormalize(bool normalize) { m_normalize = normalize; } + virtual void trace(Visitor*) OVERRIDE; + private: ConvolverNode(AudioContext*, float sampleRate); @@ -64,7 +66,7 @@ private: virtual double latencyTime() const OVERRIDE; OwnPtr<Reverb> m_reverb; - RefPtr<AudioBuffer> m_buffer; + RefPtrWillBeMember<AudioBuffer> m_buffer; // This synchronizes dynamic changes to the convolution impulse response with process(). mutable Mutex m_processLock; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.idl b/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.idl index f0339170133..fe0544b33eb 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ConvolverNode.idl @@ -26,6 +26,6 @@ [ Conditional=WEB_AUDIO ] interface ConvolverNode : AudioNode { - attribute AudioBuffer buffer; + [RaisesException=Setter] attribute AudioBuffer buffer; attribute boolean normalize; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DOMWindowWebAudio.h b/chromium/third_party/WebKit/Source/modules/webaudio/DOMWindowWebAudio.h new file mode 100644 index 00000000000..03f01d5c617 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DOMWindowWebAudio.h @@ -0,0 +1,7 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO: This is a dummy header file required by the generated binding code. +// This file should be removed after fixing the code generator. + diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.cpp index a6b93bf28d8..50f1df3254d 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.cpp @@ -34,8 +34,6 @@ #include "platform/Logging.h" #include "wtf/MainThread.h" -const unsigned EnabledInputChannels = 2; - namespace WebCore { DefaultAudioDestinationNode::DefaultAudioDestinationNode(AudioContext* context) @@ -83,22 +81,6 @@ void DefaultAudioDestinationNode::createDestination() m_destination = AudioDestination::create(*this, m_inputDeviceId, m_numberOfInputChannels, channelCount(), hardwareSampleRate); } -void DefaultAudioDestinationNode::enableInput(const String& inputDeviceId) -{ - ASSERT(isMainThread()); - if (m_numberOfInputChannels != EnabledInputChannels) { - m_numberOfInputChannels = EnabledInputChannels; - m_inputDeviceId = inputDeviceId; - - if (isInitialized()) { - // Re-create destination. - m_destination->stop(); - createDestination(); - m_destination->start(); - } - } -} - void DefaultAudioDestinationNode::startRendering() { ASSERT(isInitialized()); @@ -122,12 +104,7 @@ void DefaultAudioDestinationNode::setChannelCount(unsigned long channelCount, Ex if (!maxChannelCount() || channelCount > maxChannelCount()) { exceptionState.throwDOMException( IndexSizeError, - ExceptionMessages::failedToSet( - "channelCount", - "AudioDestinationNode", - "channel count (" + String::number(channelCount) - + ") must be between 1 and " - + String::number(maxChannelCount()) + ".")); + ExceptionMessages::indexOutsideRange<unsigned>("channel count", channelCount, 1, ExceptionMessages::InclusiveBound, maxChannelCount(), ExceptionMessages::InclusiveBound)); return; } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h index 8c0506d221e..409d31c4c50 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h @@ -34,11 +34,11 @@ namespace WebCore { class AudioContext; class ExceptionState; -class DefaultAudioDestinationNode : public AudioDestinationNode { +class DefaultAudioDestinationNode FINAL : public AudioDestinationNode { public: - static PassRefPtr<DefaultAudioDestinationNode> create(AudioContext* context) + static PassRefPtrWillBeRawPtr<DefaultAudioDestinationNode> create(AudioContext* context) { - return adoptRef(new DefaultAudioDestinationNode(context)); + return adoptRefWillBeNoop(new DefaultAudioDestinationNode(context)); } virtual ~DefaultAudioDestinationNode(); @@ -49,7 +49,6 @@ public: virtual void setChannelCount(unsigned long, ExceptionState&) OVERRIDE; // AudioDestinationNode - virtual void enableInput(const String& inputDeviceId) OVERRIDE; virtual void startRendering() OVERRIDE; virtual unsigned long maxChannelCount() const OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DelayDSPKernel.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/DelayDSPKernel.cpp index 05b8cc566fd..2301325f95b 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DelayDSPKernel.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DelayDSPKernel.cpp @@ -29,6 +29,7 @@ #include "modules/webaudio/DelayDSPKernel.h" #include "platform/audio/AudioUtilities.h" +#include "wtf/MathExtras.h" #include <algorithm> using namespace std; @@ -45,8 +46,8 @@ DelayDSPKernel::DelayDSPKernel(DelayProcessor* processor) return; m_maxDelayTime = processor->maxDelayTime(); - ASSERT(m_maxDelayTime >= 0); - if (m_maxDelayTime < 0) + ASSERT(m_maxDelayTime >= 0 && !std::isnan(m_maxDelayTime)); + if (m_maxDelayTime < 0 || std::isnan(m_maxDelayTime)) return; m_buffer.allocate(bufferLengthForDelay(m_maxDelayTime, processor->sampleRate())); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DelayDSPKernel.h b/chromium/third_party/WebKit/Source/modules/webaudio/DelayDSPKernel.h index 320350ebb5c..a0fbd661015 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DelayDSPKernel.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DelayDSPKernel.h @@ -32,7 +32,7 @@ namespace WebCore { class DelayProcessor; -class DelayDSPKernel : public AudioDelayDSPKernel { +class DelayDSPKernel FINAL : public AudioDelayDSPKernel { public: explicit DelayDSPKernel(DelayProcessor*); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DelayNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/DelayNode.cpp index 7a8817ee82e..55c6337635e 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DelayNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DelayNode.cpp @@ -31,6 +31,7 @@ #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" +#include "wtf/MathExtras.h" namespace WebCore { @@ -40,7 +41,7 @@ DelayNode::DelayNode(AudioContext* context, float sampleRate, double maxDelayTim : AudioBasicProcessorNode(context, sampleRate) { ScriptWrappable::init(this); - if (maxDelayTime <= 0 || maxDelayTime >= maximumAllowedDelayTime) { + if (maxDelayTime <= 0 || maxDelayTime >= maximumAllowedDelayTime || std::isnan(maxDelayTime)) { exceptionState.throwDOMException( NotSupportedError, "max delay time (" + String::number(maxDelayTime) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DelayNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/DelayNode.h index 14ee7e4deab..8324d73d2e9 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DelayNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DelayNode.h @@ -34,11 +34,11 @@ namespace WebCore { class AudioParam; class ExceptionState; -class DelayNode : public AudioBasicProcessorNode { +class DelayNode FINAL : public AudioBasicProcessorNode { public: - static PassRefPtr<DelayNode> create(AudioContext* context, float sampleRate, double maxDelayTime, ExceptionState& exceptionState) + static PassRefPtrWillBeRawPtr<DelayNode> create(AudioContext* context, float sampleRate, double maxDelayTime, ExceptionState& exceptionState) { - return adoptRef(new DelayNode(context, sampleRate, maxDelayTime, exceptionState)); + return adoptRefWillBeNoop(new DelayNode(context, sampleRate, maxDelayTime, exceptionState)); } AudioParam* delayTime(); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DelayProcessor.h b/chromium/third_party/WebKit/Source/modules/webaudio/DelayProcessor.h index 779aa7682e6..63b8af26cb7 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DelayProcessor.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DelayProcessor.h @@ -34,19 +34,19 @@ namespace WebCore { class AudioDSPKernel; -class DelayProcessor : public AudioDSPKernelProcessor { +class DelayProcessor FINAL : public AudioDSPKernelProcessor { public: DelayProcessor(AudioContext*, float sampleRate, unsigned numberOfChannels, double maxDelayTime); virtual ~DelayProcessor(); - virtual PassOwnPtr<AudioDSPKernel> createKernel(); + virtual PassOwnPtr<AudioDSPKernel> createKernel() OVERRIDE; AudioParam* delayTime() const { return m_delayTime.get(); } double maxDelayTime() { return m_maxDelayTime; } private: - RefPtr<AudioParam> m_delayTime; + RefPtrWillBePersistent<AudioParam> m_delayTime; double m_maxDelayTime; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp index 6700897e469..476e8db5dab 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp @@ -85,11 +85,6 @@ void DynamicsCompressorNode::process(size_t framesToProcess) m_reduction->setValue(reduction); } -void DynamicsCompressorNode::reset() -{ - m_dynamicsCompressor->reset(); -} - void DynamicsCompressorNode::initialize() { if (isInitialized()) @@ -118,6 +113,17 @@ double DynamicsCompressorNode::latencyTime() const return m_dynamicsCompressor->latencyTime(); } +void DynamicsCompressorNode::trace(Visitor* visitor) +{ + visitor->trace(m_threshold); + visitor->trace(m_knee); + visitor->trace(m_ratio); + visitor->trace(m_reduction); + visitor->trace(m_attack); + visitor->trace(m_release); + AudioNode::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h index 413c0b08e26..068c6696fdb 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h @@ -33,20 +33,19 @@ namespace WebCore { class DynamicsCompressor; -class DynamicsCompressorNode : public AudioNode { +class DynamicsCompressorNode FINAL : public AudioNode { public: - static PassRefPtr<DynamicsCompressorNode> create(AudioContext* context, float sampleRate) + static PassRefPtrWillBeRawPtr<DynamicsCompressorNode> create(AudioContext* context, float sampleRate) { - return adoptRef(new DynamicsCompressorNode(context, sampleRate)); + return adoptRefWillBeNoop(new DynamicsCompressorNode(context, sampleRate)); } virtual ~DynamicsCompressorNode(); // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); - virtual void initialize(); - virtual void uninitialize(); + virtual void process(size_t framesToProcess) OVERRIDE; + virtual void initialize() OVERRIDE; + virtual void uninitialize() OVERRIDE; // Static compression curve parameters. AudioParam* threshold() { return m_threshold.get(); } @@ -58,6 +57,8 @@ public: // Amount by which the compressor is currently compressing the signal in decibels. AudioParam* reduction() { return m_reduction.get(); } + virtual void trace(Visitor*) OVERRIDE; + private: virtual double tailTime() const OVERRIDE; virtual double latencyTime() const OVERRIDE; @@ -65,12 +66,12 @@ private: DynamicsCompressorNode(AudioContext*, float sampleRate); OwnPtr<DynamicsCompressor> m_dynamicsCompressor; - RefPtr<AudioParam> m_threshold; - RefPtr<AudioParam> m_knee; - RefPtr<AudioParam> m_ratio; - RefPtr<AudioParam> m_reduction; - RefPtr<AudioParam> m_attack; - RefPtr<AudioParam> m_release; + RefPtrWillBeMember<AudioParam> m_threshold; + RefPtrWillBeMember<AudioParam> m_knee; + RefPtrWillBeMember<AudioParam> m_ratio; + RefPtrWillBeMember<AudioParam> m_reduction; + RefPtrWillBeMember<AudioParam> m_attack; + RefPtrWillBeMember<AudioParam> m_release; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/GainNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/GainNode.cpp index 22a4c8377bc..03156476ef3 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/GainNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/GainNode.cpp @@ -79,12 +79,6 @@ void GainNode::process(size_t framesToProcess) } } -void GainNode::reset() -{ - // Snap directly to desired gain. - m_lastGain = gain()->value(); -} - // FIXME: this can go away when we do mixing with gain directly in summing junction of AudioNodeInput // // As soon as we know the channel count of our input, we can lazily initialize. @@ -114,6 +108,12 @@ void GainNode::checkNumberOfChannelsForInput(AudioNodeInput* input) AudioNode::checkNumberOfChannelsForInput(input); } +void GainNode::trace(Visitor* visitor) +{ + visitor->trace(m_gain); + AudioNode::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/GainNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/GainNode.h index 361f581a040..a0886b918e8 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/GainNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/GainNode.h @@ -37,23 +37,24 @@ class AudioContext; // GainNode is an AudioNode with one input and one output which applies a gain (volume) change to the audio signal. // De-zippering (smoothing) is applied when the gain value is changed dynamically. -class GainNode : public AudioNode { +class GainNode FINAL : public AudioNode { public: - static PassRefPtr<GainNode> create(AudioContext* context, float sampleRate) + static PassRefPtrWillBeRawPtr<GainNode> create(AudioContext* context, float sampleRate) { - return adoptRef(new GainNode(context, sampleRate)); + return adoptRefWillBeNoop(new GainNode(context, sampleRate)); } // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); + virtual void process(size_t framesToProcess) OVERRIDE; // Called in the main thread when the number of channels for the input may have changed. - virtual void checkNumberOfChannelsForInput(AudioNodeInput*); + virtual void checkNumberOfChannelsForInput(AudioNodeInput*) OVERRIDE; // JavaScript interface AudioParam* gain() { return m_gain.get(); } + virtual void trace(Visitor*) OVERRIDE; + private: virtual double tailTime() const OVERRIDE { return 0; } virtual double latencyTime() const OVERRIDE { return 0; } @@ -61,7 +62,7 @@ private: GainNode(AudioContext*, float sampleRate); float m_lastGain; // for de-zippering - RefPtr<AudioParam> m_gain; + RefPtrWillBeMember<AudioParam> m_gain; AudioFloatArray m_sampleAccurateGainValues; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp index 50b574ab9cd..ac3f7443b93 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp @@ -28,6 +28,7 @@ #include "modules/webaudio/MediaElementAudioSourceNode.h" +#include "core/html/HTMLMediaElement.h" #include "modules/webaudio/AudioContext.h" #include "modules/webaudio/AudioNodeOutput.h" #include "platform/Logging.h" @@ -40,9 +41,9 @@ const unsigned maxSampleRate = 192000; namespace WebCore { -PassRefPtr<MediaElementAudioSourceNode> MediaElementAudioSourceNode::create(AudioContext* context, HTMLMediaElement* mediaElement) +PassRefPtrWillBeRawPtr<MediaElementAudioSourceNode> MediaElementAudioSourceNode::create(AudioContext* context, HTMLMediaElement* mediaElement) { - return adoptRef(new MediaElementAudioSourceNode(context, mediaElement)); + return adoptRefWillBeNoop(new MediaElementAudioSourceNode(context, mediaElement)); } MediaElementAudioSourceNode::MediaElementAudioSourceNode(AudioContext* context, HTMLMediaElement* mediaElement) @@ -62,7 +63,9 @@ MediaElementAudioSourceNode::MediaElementAudioSourceNode(AudioContext* context, MediaElementAudioSourceNode::~MediaElementAudioSourceNode() { +#if !ENABLE(OILPAN) m_mediaElement->setAudioSourceNode(0); +#endif uninitialize(); } @@ -135,10 +138,6 @@ void MediaElementAudioSourceNode::process(size_t numberOfFrames) } } -void MediaElementAudioSourceNode::reset() -{ -} - void MediaElementAudioSourceNode::lock() { ref(); @@ -151,6 +150,13 @@ void MediaElementAudioSourceNode::unlock() deref(); } +void MediaElementAudioSourceNode::trace(Visitor* visitor) +{ + visitor->trace(m_mediaElement); + AudioSourceNode::trace(visitor); + AudioSourceProviderClient::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h index 27ae39272e3..c5888027f3c 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h @@ -27,7 +27,6 @@ #if ENABLE(WEB_AUDIO) -#include "core/html/HTMLMediaElement.h" #include "platform/audio/AudioSourceProviderClient.h" #include "platform/audio/MultiChannelResampler.h" #include "modules/webaudio/AudioSourceNode.h" @@ -38,24 +37,27 @@ namespace WebCore { class AudioContext; +class HTMLMediaElement; -class MediaElementAudioSourceNode : public AudioSourceNode, public AudioSourceProviderClient { +class MediaElementAudioSourceNode FINAL : public AudioSourceNode, public AudioSourceProviderClient { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaElementAudioSourceNode); public: - static PassRefPtr<MediaElementAudioSourceNode> create(AudioContext*, HTMLMediaElement*); + static PassRefPtrWillBeRawPtr<MediaElementAudioSourceNode> create(AudioContext*, HTMLMediaElement*); virtual ~MediaElementAudioSourceNode(); HTMLMediaElement* mediaElement() { return m_mediaElement.get(); } // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); + virtual void process(size_t framesToProcess) OVERRIDE; // AudioSourceProviderClient - virtual void setFormat(size_t numberOfChannels, float sampleRate); + virtual void setFormat(size_t numberOfChannels, float sampleRate) OVERRIDE; - void lock(); - void unlock(); + virtual void lock() OVERRIDE; + virtual void unlock() OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: MediaElementAudioSourceNode(AudioContext*, HTMLMediaElement*); @@ -63,7 +65,7 @@ private: // As an audio source, we will never propagate silence. virtual bool propagatesSilence() const OVERRIDE { return false; } - RefPtr<HTMLMediaElement> m_mediaElement; + RefPtrWillBeMember<HTMLMediaElement> m_mediaElement; Mutex m_processLock; unsigned m_sourceNumberOfChannels; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp index 34d883a0d42..0e26912194d 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp @@ -28,18 +28,18 @@ #include "modules/webaudio/MediaStreamAudioDestinationNode.h" -#include "core/platform/mediastream/MediaStreamCenter.h" -#include "core/platform/mediastream/RTCPeerConnectionHandler.h" #include "modules/webaudio/AudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "platform/UUID.h" +#include "platform/mediastream/MediaStreamCenter.h" +#include "public/platform/WebRTCPeerConnectionHandler.h" #include "wtf/Locker.h" namespace WebCore { -PassRefPtr<MediaStreamAudioDestinationNode> MediaStreamAudioDestinationNode::create(AudioContext* context, size_t numberOfChannels) +PassRefPtrWillBeRawPtr<MediaStreamAudioDestinationNode> MediaStreamAudioDestinationNode::create(AudioContext* context, size_t numberOfChannels) { - return adoptRef(new MediaStreamAudioDestinationNode(context, numberOfChannels)); + return adoptRefWillBeNoop(new MediaStreamAudioDestinationNode(context, numberOfChannels)); } MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(AudioContext* context, size_t numberOfChannels) @@ -54,18 +54,13 @@ MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(AudioContext* c audioSources.append(m_source); MediaStreamSourceVector videoSources; m_stream = MediaStream::create(context->executionContext(), MediaStreamDescriptor::create(audioSources, videoSources)); - MediaStreamCenter::instance().didCreateMediaStream(m_stream->descriptor()); + MediaStreamCenter::instance().didCreateMediaStreamAndTracks(m_stream->descriptor()); m_source->setAudioFormat(numberOfChannels, context->sampleRate()); initialize(); } -MediaStreamSource* MediaStreamAudioDestinationNode::mediaStreamSource() -{ - return m_source.get(); -} - MediaStreamAudioDestinationNode::~MediaStreamAudioDestinationNode() { uninitialize(); @@ -77,10 +72,6 @@ void MediaStreamAudioDestinationNode::process(size_t numberOfFrames) m_source->consumeAudio(m_mixBus.get(), numberOfFrames); } -void MediaStreamAudioDestinationNode::reset() -{ -} - } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h index 7ac3862f7c0..ef8f39340d8 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h @@ -37,19 +37,16 @@ namespace WebCore { class AudioContext; -class MediaStreamAudioDestinationNode : public AudioBasicInspectorNode { +class MediaStreamAudioDestinationNode FINAL : public AudioBasicInspectorNode { public: - static PassRefPtr<MediaStreamAudioDestinationNode> create(AudioContext*, size_t numberOfChannels); + static PassRefPtrWillBeRawPtr<MediaStreamAudioDestinationNode> create(AudioContext*, size_t numberOfChannels); virtual ~MediaStreamAudioDestinationNode(); MediaStream* stream() { return m_stream.get(); } // AudioNode. - virtual void process(size_t framesToProcess); - virtual void reset(); - - MediaStreamSource* mediaStreamSource(); + virtual void process(size_t framesToProcess) OVERRIDE; private: MediaStreamAudioDestinationNode(AudioContext*, size_t numberOfChannels); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp index 58b91678423..2664e68c5e9 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp @@ -35,12 +35,12 @@ namespace WebCore { -PassRefPtr<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::create(AudioContext* context, MediaStream* mediaStream, MediaStreamTrack* audioTrack, AudioSourceProvider* audioSourceProvider) +PassRefPtrWillBeRawPtr<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::create(AudioContext* context, MediaStream* mediaStream, MediaStreamTrack* audioTrack, PassOwnPtr<AudioSourceProvider> audioSourceProvider) { - return adoptRef(new MediaStreamAudioSourceNode(context, mediaStream, audioTrack, audioSourceProvider)); + return adoptRefWillBeNoop(new MediaStreamAudioSourceNode(context, mediaStream, audioTrack, audioSourceProvider)); } -MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* context, MediaStream* mediaStream, MediaStreamTrack* audioTrack, AudioSourceProvider* audioSourceProvider) +MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* context, MediaStream* mediaStream, MediaStreamTrack* audioTrack, PassOwnPtr<AudioSourceProvider> audioSourceProvider) : AudioSourceNode(context, context->sampleRate()) , m_mediaStream(mediaStream) , m_audioTrack(audioTrack) @@ -113,8 +113,12 @@ void MediaStreamAudioSourceNode::process(size_t numberOfFrames) } } -void MediaStreamAudioSourceNode::reset() +void MediaStreamAudioSourceNode::trace(Visitor* visitor) { + visitor->trace(m_mediaStream); + visitor->trace(m_audioTrack); + AudioSourceNode::trace(visitor); + AudioSourceProviderClient::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h index 625690bc5e1..42f3f43f2fd 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h @@ -39,32 +39,34 @@ namespace WebCore { class AudioContext; -class MediaStreamAudioSourceNode : public AudioSourceNode, public AudioSourceProviderClient { +class MediaStreamAudioSourceNode FINAL : public AudioSourceNode, public AudioSourceProviderClient { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MediaStreamAudioSourceNode); public: - static PassRefPtr<MediaStreamAudioSourceNode> create(AudioContext*, MediaStream*, MediaStreamTrack*, AudioSourceProvider*); + static PassRefPtrWillBeRawPtr<MediaStreamAudioSourceNode> create(AudioContext*, MediaStream*, MediaStreamTrack*, PassOwnPtr<AudioSourceProvider>); virtual ~MediaStreamAudioSourceNode(); MediaStream* mediaStream() { return m_mediaStream.get(); } // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); + virtual void process(size_t framesToProcess) OVERRIDE; // AudioSourceProviderClient - virtual void setFormat(size_t numberOfChannels, float sampleRate); + virtual void setFormat(size_t numberOfChannels, float sampleRate) OVERRIDE; - AudioSourceProvider* audioSourceProvider() const { return m_audioSourceProvider; } + AudioSourceProvider* audioSourceProvider() const { return m_audioSourceProvider.get(); } + + virtual void trace(Visitor*) OVERRIDE; private: - MediaStreamAudioSourceNode(AudioContext*, MediaStream*, MediaStreamTrack*, AudioSourceProvider*); + MediaStreamAudioSourceNode(AudioContext*, MediaStream*, MediaStreamTrack*, PassOwnPtr<AudioSourceProvider>); // As an audio source, we will never propagate silence. virtual bool propagatesSilence() const OVERRIDE { return false; } - RefPtr<MediaStream> m_mediaStream; - RefPtr<MediaStreamTrack> m_audioTrack; - AudioSourceProvider* m_audioSourceProvider; + RefPtrWillBeMember<MediaStream> m_mediaStream; + RefPtrWillBeMember<MediaStreamTrack> m_audioTrack; + OwnPtr<AudioSourceProvider> m_audioSourceProvider; Mutex m_processLock; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OWNERS b/chromium/third_party/WebKit/Source/modules/webaudio/OWNERS index d591a3eaa09..3cd6baeb1da 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OWNERS @@ -1 +1,2 @@ kbr@chromium.org +rtoy@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.cpp index 45f73e94e73..a2a72d1e27b 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.cpp @@ -28,18 +28,16 @@ #include "modules/webaudio/OfflineAudioCompletionEvent.h" -#include "core/events/ThreadLocalEventNames.h" - namespace WebCore { -PassRefPtr<OfflineAudioCompletionEvent> OfflineAudioCompletionEvent::create() +PassRefPtrWillBeRawPtr<OfflineAudioCompletionEvent> OfflineAudioCompletionEvent::create() { - return adoptRef(new OfflineAudioCompletionEvent); + return adoptRefWillBeNoop(new OfflineAudioCompletionEvent); } -PassRefPtr<OfflineAudioCompletionEvent> OfflineAudioCompletionEvent::create(PassRefPtr<AudioBuffer> renderedBuffer) +PassRefPtrWillBeRawPtr<OfflineAudioCompletionEvent> OfflineAudioCompletionEvent::create(PassRefPtrWillBeRawPtr<AudioBuffer> renderedBuffer) { - return adoptRef(new OfflineAudioCompletionEvent(renderedBuffer)); + return adoptRefWillBeNoop(new OfflineAudioCompletionEvent(renderedBuffer)); } OfflineAudioCompletionEvent::OfflineAudioCompletionEvent() @@ -47,7 +45,7 @@ OfflineAudioCompletionEvent::OfflineAudioCompletionEvent() ScriptWrappable::init(this); } -OfflineAudioCompletionEvent::OfflineAudioCompletionEvent(PassRefPtr<AudioBuffer> renderedBuffer) +OfflineAudioCompletionEvent::OfflineAudioCompletionEvent(PassRefPtrWillBeRawPtr<AudioBuffer> renderedBuffer) : Event(EventTypeNames::complete, true, false) , m_renderedBuffer(renderedBuffer) { @@ -63,6 +61,12 @@ const AtomicString& OfflineAudioCompletionEvent::interfaceName() const return EventNames::OfflineAudioCompletionEvent; } +void OfflineAudioCompletionEvent::trace(Visitor* visitor) +{ + visitor->trace(m_renderedBuffer); + Event::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.h b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.h index c994c628a71..da5b8582a1d 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioCompletionEvent.h @@ -25,7 +25,7 @@ #ifndef OfflineAudioCompletionEvent_h #define OfflineAudioCompletionEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "modules/webaudio/AudioBuffer.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" @@ -34,22 +34,24 @@ namespace WebCore { class AudioBuffer; -class OfflineAudioCompletionEvent : public Event { +class OfflineAudioCompletionEvent FINAL : public Event { public: - static PassRefPtr<OfflineAudioCompletionEvent> create(); - static PassRefPtr<OfflineAudioCompletionEvent> create(PassRefPtr<AudioBuffer> renderedBuffer); + static PassRefPtrWillBeRawPtr<OfflineAudioCompletionEvent> create(); + static PassRefPtrWillBeRawPtr<OfflineAudioCompletionEvent> create(PassRefPtrWillBeRawPtr<AudioBuffer> renderedBuffer); virtual ~OfflineAudioCompletionEvent(); AudioBuffer* renderedBuffer() { return m_renderedBuffer.get(); } - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: OfflineAudioCompletionEvent(); - explicit OfflineAudioCompletionEvent(PassRefPtr<AudioBuffer> renderedBuffer); + explicit OfflineAudioCompletionEvent(PassRefPtrWillBeRawPtr<AudioBuffer> renderedBuffer); - RefPtr<AudioBuffer> m_renderedBuffer; + RefPtrWillBeMember<AudioBuffer> m_renderedBuffer; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp index 4cf7947dfe1..bed82c16d9a 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp @@ -36,34 +36,52 @@ namespace WebCore { -PassRefPtr<OfflineAudioContext> OfflineAudioContext::create(ExecutionContext* context, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<OfflineAudioContext> OfflineAudioContext::create(ExecutionContext* context, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) { // FIXME: add support for workers. if (!context || !context->isDocument()) { exceptionState.throwDOMException( NotSupportedError, "Workers are not supported."); - return 0; + return nullptr; } Document* document = toDocument(context); if (!numberOfFrames) { exceptionState.throwDOMException(SyntaxError, "number of frames cannot be zero."); - return 0; + return nullptr; } - if (numberOfChannels > 10) { - exceptionState.throwDOMException(SyntaxError, "number of channels (" + String::number(numberOfChannels) + ") exceeds maximum (10)."); - return 0; + if (numberOfChannels > AudioContext::maxNumberOfChannels()) { + exceptionState.throwDOMException( + IndexSizeError, + ExceptionMessages::indexOutsideRange<unsigned>( + "number of channels", + numberOfChannels, + 0, + ExceptionMessages::InclusiveBound, + AudioContext::maxNumberOfChannels(), + ExceptionMessages::InclusiveBound)); + return nullptr; } if (!isSampleRateRangeGood(sampleRate)) { exceptionState.throwDOMException(SyntaxError, "sample rate (" + String::number(sampleRate) + ") must be in the range 44100-96000 Hz."); - return 0; + return nullptr; + } + + RefPtrWillBeRawPtr<OfflineAudioContext> audioContext(adoptRefWillBeThreadSafeRefCountedGarbageCollected(new OfflineAudioContext(document, numberOfChannels, numberOfFrames, sampleRate))); + + if (!audioContext->destination()) { + exceptionState.throwDOMException( + NotSupportedError, + "OfflineAudioContext(" + String::number(numberOfChannels) + + ", " + String::number(numberOfFrames) + + ", " + String::number(sampleRate) + + ")"); } - RefPtr<OfflineAudioContext> audioContext(adoptRef(new OfflineAudioContext(document, numberOfChannels, numberOfFrames, sampleRate))); audioContext->suspendIfNeeded(); return audioContext.release(); } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h index 4cd6928da3e..6434069a4c9 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h @@ -31,9 +31,9 @@ namespace WebCore { class ExceptionState; -class OfflineAudioContext : public AudioContext { +class OfflineAudioContext FINAL : public AudioContext { public: - static PassRefPtr<OfflineAudioContext> create(ExecutionContext*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&); + static PassRefPtrWillBeRawPtr<OfflineAudioContext> create(ExecutionContext*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&); virtual ~OfflineAudioContext(); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl index 5f5f8ac3ee4..5d5ec0c357d 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl @@ -23,6 +23,7 @@ */ [ + WillBeGarbageCollected, Conditional=WEB_AUDIO, Constructor(unsigned long numberOfChannels, unsigned long numberOfFrames, float sampleRate), ConstructorCallWith=ExecutionContext, diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp index 055458216a6..4bf2fc0a5bb 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp @@ -96,6 +96,11 @@ void OfflineAudioDestinationNode::offlineRender() if (!m_renderBus.get()) return; + bool isAudioContextInitialized = context()->isInitialized(); + ASSERT(isAudioContextInitialized); + if (!isAudioContextInitialized) + return; + bool channelsMatch = m_renderBus->numberOfChannels() == m_renderTarget->numberOfChannels(); ASSERT(channelsMatch); if (!channelsMatch) @@ -106,15 +111,6 @@ void OfflineAudioDestinationNode::offlineRender() if (!isRenderBusAllocated) return; - // Synchronize with HRTFDatabaseLoader. - // The database must be loaded before we can proceed. - HRTFDatabaseLoader* loader = context()->hrtfDatabaseLoader(); - ASSERT(loader); - if (!loader) - return; - - loader->waitForLoaderThreadCompletion(); - // Break up the render target into smaller "render quantize" sized pieces. // Render until we're finished. size_t framesToProcess = m_renderTarget->length(); @@ -157,6 +153,12 @@ void OfflineAudioDestinationNode::notifyComplete() context()->fireCompletionEvent(); } +void OfflineAudioDestinationNode::trace(Visitor* visitor) +{ + visitor->trace(m_renderTarget); + AudioDestinationNode::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h index a2f2a615417..c2ee3ddb26a 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h @@ -36,11 +36,11 @@ namespace WebCore { class AudioBus; class AudioContext; -class OfflineAudioDestinationNode : public AudioDestinationNode { +class OfflineAudioDestinationNode FINAL : public AudioDestinationNode { public: - static PassRefPtr<OfflineAudioDestinationNode> create(AudioContext* context, AudioBuffer* renderTarget) + static PassRefPtrWillBeRawPtr<OfflineAudioDestinationNode> create(AudioContext* context, AudioBuffer* renderTarget) { - return adoptRef(new OfflineAudioDestinationNode(context, renderTarget)); + return adoptRefWillBeNoop(new OfflineAudioDestinationNode(context, renderTarget)); } virtual ~OfflineAudioDestinationNode(); @@ -50,10 +50,11 @@ public: virtual void uninitialize() OVERRIDE; // AudioDestinationNode - virtual void enableInput(const String&) OVERRIDE { } virtual void startRendering() OVERRIDE; - virtual float sampleRate() const { return m_renderTarget->sampleRate(); } + virtual float sampleRate() const OVERRIDE { return m_renderTarget->sampleRate(); } + + virtual void trace(Visitor*) OVERRIDE; private: class OfflineRenderingTask; @@ -62,7 +63,7 @@ private: OfflineAudioDestinationNode(AudioContext*, AudioBuffer* renderTarget); // This AudioNode renders into this AudioBuffer. - RefPtr<AudioBuffer> m_renderTarget; + RefPtrWillBeMember<AudioBuffer> m_renderTarget; // Temporary AudioBus for each render quantum. RefPtr<AudioBus> m_renderBus; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.cpp index 9790a2eef25..7a6be3d0ed4 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.cpp @@ -43,9 +43,9 @@ namespace WebCore { using namespace VectorMath; -PassRefPtr<OscillatorNode> OscillatorNode::create(AudioContext* context, float sampleRate) +PassRefPtrWillBeRawPtr<OscillatorNode> OscillatorNode::create(AudioContext* context, float sampleRate) { - return adoptRef(new OscillatorNode(context, sampleRate)); + return adoptRefWillBeNoop(new OscillatorNode(context, sampleRate)); } OscillatorNode::OscillatorNode(AudioContext* context, float sampleRate) @@ -107,8 +107,6 @@ void OscillatorNode::setType(const String& type) setType(SAWTOOTH); else if (type == "triangle") setType(TRIANGLE); - else - ASSERT_NOT_REACHED(); } bool OscillatorNode::setType(unsigned type) @@ -118,22 +116,22 @@ bool OscillatorNode::setType(unsigned type) switch (type) { case SINE: { - DEFINE_STATIC_REF(PeriodicWave, periodicWaveSine, (PeriodicWave::createSine(sampleRate))); + DEFINE_STATIC_REF_WILL_BE_PERSISTENT(PeriodicWave, periodicWaveSine, (PeriodicWave::createSine(sampleRate))); periodicWave = periodicWaveSine; break; } case SQUARE: { - DEFINE_STATIC_REF(PeriodicWave, periodicWaveSquare, (PeriodicWave::createSquare(sampleRate))); + DEFINE_STATIC_REF_WILL_BE_PERSISTENT(PeriodicWave, periodicWaveSquare, (PeriodicWave::createSquare(sampleRate))); periodicWave = periodicWaveSquare; break; } case SAWTOOTH: { - DEFINE_STATIC_REF(PeriodicWave, periodicWaveSawtooth, (PeriodicWave::createSawtooth(sampleRate))); + DEFINE_STATIC_REF_WILL_BE_PERSISTENT(PeriodicWave, periodicWaveSawtooth, (PeriodicWave::createSawtooth(sampleRate))); periodicWave = periodicWaveSawtooth; break; } case TRIANGLE: { - DEFINE_STATIC_REF(PeriodicWave, periodicWaveTriangle, (PeriodicWave::createTriangle(sampleRate))); + DEFINE_STATIC_REF_WILL_BE_PERSISTENT(PeriodicWave, periodicWaveTriangle, (PeriodicWave::createTriangle(sampleRate))); periodicWave = periodicWaveTriangle; break; } @@ -328,11 +326,6 @@ void OscillatorNode::process(size_t framesToProcess) outputBus->clearSilentFlag(); } -void OscillatorNode::reset() -{ - m_virtualReadIndex = 0; -} - void OscillatorNode::setPeriodicWave(PeriodicWave* periodicWave) { ASSERT(isMainThread()); @@ -348,6 +341,14 @@ bool OscillatorNode::propagatesSilence() const return !isPlayingOrScheduled() || hasFinished() || !m_periodicWave.get(); } +void OscillatorNode::trace(Visitor* visitor) +{ + visitor->trace(m_frequency); + visitor->trace(m_detune); + visitor->trace(m_periodicWave); + AudioScheduledSourceNode::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.h index a4d25390644..be18d7d94ff 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.h @@ -40,7 +40,7 @@ class PeriodicWave; // OscillatorNode is an audio generator of periodic waveforms. -class OscillatorNode : public AudioScheduledSourceNode { +class OscillatorNode FINAL : public AudioScheduledSourceNode { public: // The waveform type. // These must be defined as in the .idl file. @@ -52,17 +52,15 @@ public: CUSTOM = 4 }; - static PassRefPtr<OscillatorNode> create(AudioContext*, float sampleRate); + static PassRefPtrWillBeRawPtr<OscillatorNode> create(AudioContext*, float sampleRate); virtual ~OscillatorNode(); // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); + virtual void process(size_t framesToProcess) OVERRIDE; String type() const; - bool setType(unsigned); // Returns true on success. void setType(const String&); AudioParam* frequency() { return m_frequency.get(); } @@ -70,9 +68,13 @@ public: void setPeriodicWave(PeriodicWave*); + virtual void trace(Visitor*) OVERRIDE; + private: OscillatorNode(AudioContext*, float sampleRate); + bool setType(unsigned); // Returns true on success. + // Returns true if there are sample-accurate timeline parameter changes. bool calculateSampleAccuratePhaseIncrements(size_t framesToProcess); @@ -82,10 +84,10 @@ private: unsigned short m_type; // Frequency value in Hertz. - RefPtr<AudioParam> m_frequency; + RefPtrWillBeMember<AudioParam> m_frequency; // Detune value (deviating from the frequency) in Cents. - RefPtr<AudioParam> m_detune; + RefPtrWillBeMember<AudioParam> m_detune; bool m_firstRender; @@ -100,7 +102,7 @@ private: AudioFloatArray m_phaseIncrements; AudioFloatArray m_detuneValues; - RefPtr<PeriodicWave> m_periodicWave; + RefPtrWillBeMember<PeriodicWave> m_periodicWave; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.idl b/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.idl index 7cbe29dbd30..823d20ed521 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/OscillatorNode.idl @@ -22,27 +22,20 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum OscillatorType { + "sine", + "square", + "sawtooth", + "triangle", + "custom" +}; + // OscillatorNode is an audio generator of periodic waveforms. [ Conditional=WEB_AUDIO ] interface OscillatorNode : AudioSourceNode { - // Type constants. - const unsigned short SINE = 0; - const unsigned short SQUARE = 1; - const unsigned short SAWTOOTH = 2; - const unsigned short TRIANGLE = 3; - const unsigned short CUSTOM = 4; - - [Custom=Setter] attribute DOMString type; - - // Playback state constants. - const unsigned short UNSCHEDULED_STATE = 0; - const unsigned short SCHEDULED_STATE = 1; - const unsigned short PLAYING_STATE = 2; - const unsigned short FINISHED_STATE = 3; - - readonly attribute unsigned short playbackState; + attribute OscillatorType type; readonly attribute AudioParam frequency; // in Hertz readonly attribute AudioParam detune; // in Cents diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp index fcebe1273dc..029c73cf16c 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp @@ -49,9 +49,24 @@ static void fixNANs(double &x) PannerNode::PannerNode(AudioContext* context, float sampleRate) : AudioNode(context, sampleRate) , m_panningModel(Panner::PanningModelHRTF) + , m_distanceModel(DistanceEffect::ModelInverse) + , m_position(0, 0, 0) + , m_orientation(1, 0, 0) + , m_velocity(0, 0, 0) + , m_isAzimuthElevationDirty(true) + , m_isDistanceConeGainDirty(true) + , m_isDopplerRateDirty(true) , m_lastGain(-1.0) + , m_cachedAzimuth(0) + , m_cachedElevation(0) + , m_cachedDistanceConeGain(1.0f) + , m_cachedDopplerRate(1) , m_connectionCount(0) { + // Load the HRTF database asynchronously so we don't block the Javascript thread while creating the HRTF database. + // The HRTF panner will return zeroes until the database is loaded. + m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(context->sampleRate()); + ScriptWrappable::init(this); addInput(adoptPtr(new AudioNodeInput(this))); addOutput(adoptPtr(new AudioNodeOutput(this, 2))); @@ -61,13 +76,6 @@ PannerNode::PannerNode(AudioContext* context, float sampleRate) m_channelCountMode = ClampedMax; m_channelInterpretation = AudioBus::Speakers; - m_distanceGain = AudioParam::create(context, "distanceGain", 1.0, 0.0, 1.0); - m_coneGain = AudioParam::create(context, "coneGain", 1.0, 0.0, 1.0); - - m_position = FloatPoint3D(0, 0, 0); - m_orientation = FloatPoint3D(1, 0, 0); - m_velocity = FloatPoint3D(0, 0, 0); - setNodeType(NodeTypePanner); initialize(); @@ -85,8 +93,12 @@ void PannerNode::pullInputs(size_t framesToProcess) if (m_connectionCount != context()->connectionCount()) { m_connectionCount = context()->connectionCount(); - // Recursively go through all nodes connected to us. - notifyAudioSourcesConnectedToNode(this); + // A map for keeping track if we have visited a node or not. This prevents feedback loops + // from recursing infinitely. See crbug.com/331446. + HashMap<AudioNode*, bool> visitedNodes; + + // Recursively go through all nodes connected to us + notifyAudioSourcesConnectedToNode(this, visitedNodes); } AudioNode::pullInputs(framesToProcess); @@ -102,23 +114,35 @@ void PannerNode::process(size_t framesToProcess) } AudioBus* source = input(0)->bus(); - if (!source) { destination->zero(); return; } // The audio thread can't block on this lock, so we call tryLock() instead. - MutexTryLocker tryLocker(m_pannerLock); - if (tryLocker.locked()) { + MutexTryLocker tryLocker(m_processLock); + MutexTryLocker tryListenerLocker(listener()->listenerLock()); + + if (tryLocker.locked() && tryListenerLocker.locked()) { + // HRTFDatabase should be loaded before proceeding for offline audio context when the panning model is HRTF. + if (m_panningModel == Panner::PanningModelHRTF && !m_hrtfDatabaseLoader->isLoaded()) { + if (context()->isOfflineContext()) { + m_hrtfDatabaseLoader->waitForLoaderThreadCompletion(); + } else { + destination->zero(); + return; + } + } + // Apply the panning effect. double azimuth; double elevation; - getAzimuthElevation(&azimuth, &elevation); + azimuthElevation(&azimuth, &elevation); + m_panner->pan(azimuth, elevation, source, destination, framesToProcess); // Get the distance and cone gain. - double totalGain = distanceConeGain(); + float totalGain = distanceConeGain(); // Snap to desired gain at the beginning. if (m_lastGain == -1.0) @@ -127,24 +151,19 @@ void PannerNode::process(size_t framesToProcess) // Apply gain in-place with de-zippering. destination->copyWithGainFrom(*destination, &m_lastGain, totalGain); } else { - // Too bad - The tryLock() failed. We must be in the middle of changing the panner. + // Too bad - The tryLock() failed. + // We must be in the middle of changing the properties of the panner or the listener. destination->zero(); } } -void PannerNode::reset() -{ - m_lastGain = -1.0; // force to snap to initial gain - if (m_panner.get()) - m_panner->reset(); -} - void PannerNode::initialize() { if (isInitialized()) return; - m_panner = Panner::create(m_panningModel, sampleRate(), context()->hrtfDatabaseLoader()); + m_panner = Panner::create(m_panningModel, sampleRate(), m_hrtfDatabaseLoader.get()); + listener()->addPanner(this); AudioNode::initialize(); } @@ -155,6 +174,8 @@ void PannerNode::uninitialize() return; m_panner.clear(); + listener()->removePanner(this); + AudioNode::uninitialize(); } @@ -166,12 +187,10 @@ AudioListener* PannerNode::listener() String PannerNode::panningModel() const { switch (m_panningModel) { - case EQUALPOWER: + case Panner::PanningModelEqualPower: return "equalpower"; - case HRTF: + case Panner::PanningModelHRTF: return "HRTF"; - case SOUNDFIELD: - return "soundfield"; default: ASSERT_NOT_REACHED(); return "HRTF"; @@ -181,34 +200,26 @@ String PannerNode::panningModel() const void PannerNode::setPanningModel(const String& model) { if (model == "equalpower") - setPanningModel(EQUALPOWER); + setPanningModel(Panner::PanningModelEqualPower); else if (model == "HRTF") - setPanningModel(HRTF); - else if (model == "soundfield") - setPanningModel(SOUNDFIELD); - else - ASSERT_NOT_REACHED(); + setPanningModel(Panner::PanningModelHRTF); } bool PannerNode::setPanningModel(unsigned model) { switch (model) { - case EQUALPOWER: - case HRTF: + case Panner::PanningModelEqualPower: + case Panner::PanningModelHRTF: if (!m_panner.get() || model != m_panningModel) { // This synchronizes with process(). - MutexLocker processLocker(m_pannerLock); - - OwnPtr<Panner> newPanner = Panner::create(model, sampleRate(), context()->hrtfDatabaseLoader()); + MutexLocker processLocker(m_processLock); + OwnPtr<Panner> newPanner = Panner::create(model, sampleRate(), m_hrtfDatabaseLoader.get()); m_panner = newPanner.release(); m_panningModel = model; } break; - case SOUNDFIELD: - // FIXME: Implement sound field model. See // https://bugs.webkit.org/show_bug.cgi?id=77367. - context()->executionContext()->addConsoleMessage(JSMessageSource, WarningMessageLevel, "'soundfield' panning model not implemented."); - break; default: + ASSERT_NOT_REACHED(); return false; } @@ -238,8 +249,6 @@ void PannerNode::setDistanceModel(const String& model) setDistanceModel(DistanceEffect::ModelInverse); else if (model == "exponential") setDistanceModel(DistanceEffect::ModelExponential); - else - ASSERT_NOT_REACHED(); } bool PannerNode::setDistanceModel(unsigned model) @@ -248,32 +257,135 @@ bool PannerNode::setDistanceModel(unsigned model) case DistanceEffect::ModelLinear: case DistanceEffect::ModelInverse: case DistanceEffect::ModelExponential: - m_distanceEffect.setModel(static_cast<DistanceEffect::ModelType>(model), true); + if (model != m_distanceModel) { + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_distanceEffect.setModel(static_cast<DistanceEffect::ModelType>(model), true); + m_distanceModel = model; + } break; default: + ASSERT_NOT_REACHED(); return false; } return true; } -void PannerNode::getAzimuthElevation(double* outAzimuth, double* outElevation) +void PannerNode::setRefDistance(double distance) +{ + if (refDistance() == distance) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_distanceEffect.setRefDistance(distance); + markPannerAsDirty(PannerNode::DistanceConeGainDirty); +} + +void PannerNode::setMaxDistance(double distance) +{ + if (maxDistance() == distance) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_distanceEffect.setMaxDistance(distance); + markPannerAsDirty(PannerNode::DistanceConeGainDirty); +} + +void PannerNode::setRolloffFactor(double factor) +{ + if (rolloffFactor() == factor) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_distanceEffect.setRolloffFactor(factor); + markPannerAsDirty(PannerNode::DistanceConeGainDirty); +} + +void PannerNode::setConeInnerAngle(double angle) +{ + if (coneInnerAngle() == angle) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_coneEffect.setInnerAngle(angle); + markPannerAsDirty(PannerNode::DistanceConeGainDirty); +} + +void PannerNode::setConeOuterAngle(double angle) { - // FIXME: we should cache azimuth and elevation (if possible), so we only re-calculate if a change has been made. + if (coneOuterAngle() == angle) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_coneEffect.setOuterAngle(angle); + markPannerAsDirty(PannerNode::DistanceConeGainDirty); +} +void PannerNode::setConeOuterGain(double angle) +{ + if (coneOuterGain() == angle) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_coneEffect.setOuterGain(angle); + markPannerAsDirty(PannerNode::DistanceConeGainDirty); +} + +void PannerNode::setPosition(float x, float y, float z) +{ + FloatPoint3D position = FloatPoint3D(x, y, z); + + if (m_position == position) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_position = position; + markPannerAsDirty(PannerNode::AzimuthElevationDirty | PannerNode::DistanceConeGainDirty | PannerNode::DopplerRateDirty); +} + +void PannerNode::setOrientation(float x, float y, float z) +{ + FloatPoint3D orientation = FloatPoint3D(x, y, z); + + if (m_orientation == orientation) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_orientation = orientation; + markPannerAsDirty(PannerNode::DistanceConeGainDirty); +} + +void PannerNode::setVelocity(float x, float y, float z) +{ + FloatPoint3D velocity = FloatPoint3D(x, y, z); + + if (m_velocity == velocity) + return; + + // This synchronizes with process(). + MutexLocker processLocker(m_processLock); + m_velocity = velocity; + markPannerAsDirty(PannerNode::DopplerRateDirty); +} + +void PannerNode::calculateAzimuthElevation(double* outAzimuth, double* outElevation) +{ double azimuth = 0.0; // Calculate the source-listener vector FloatPoint3D listenerPosition = listener()->position(); FloatPoint3D sourceListener = m_position - listenerPosition; - if (sourceListener.isZero()) { - // degenerate case if source and listener are at the same point - *outAzimuth = 0.0; - *outElevation = 0.0; - return; - } - + // normalize() does nothing if the length of |sourceListener| is zero. sourceListener.normalize(); // Align axes @@ -321,11 +433,9 @@ void PannerNode::getAzimuthElevation(double* outAzimuth, double* outElevation) *outElevation = elevation; } -float PannerNode::dopplerRate() +double PannerNode::calculateDopplerRate() { double dopplerShift = 1.0; - - // FIXME: optimize for case when neither source nor listener has changed... double dopplerFactor = listener()->dopplerFactor(); if (dopplerFactor > 0.0) { @@ -345,48 +455,97 @@ float PannerNode::dopplerRate() double sourceListenerMagnitude = sourceToListener.length(); - double listenerProjection = sourceToListener.dot(listenerVelocity) / sourceListenerMagnitude; - double sourceProjection = sourceToListener.dot(sourceVelocity) / sourceListenerMagnitude; + if (!sourceListenerMagnitude) { + // Source and listener are at the same position. Skip the computation of the doppler + // shift, and just return the cached value. + dopplerShift = m_cachedDopplerRate; + } else { + double listenerProjection = sourceToListener.dot(listenerVelocity) / sourceListenerMagnitude; + double sourceProjection = sourceToListener.dot(sourceVelocity) / sourceListenerMagnitude; + + listenerProjection = -listenerProjection; + sourceProjection = -sourceProjection; + + double scaledSpeedOfSound = speedOfSound / dopplerFactor; + listenerProjection = min(listenerProjection, scaledSpeedOfSound); + sourceProjection = min(sourceProjection, scaledSpeedOfSound); + + dopplerShift = ((speedOfSound - dopplerFactor * listenerProjection) / (speedOfSound - dopplerFactor * sourceProjection)); + fixNANs(dopplerShift); // avoid illegal values + + // Limit the pitch shifting to 4 octaves up and 3 octaves down. + if (dopplerShift > 16.0) + dopplerShift = 16.0; + else if (dopplerShift < 0.125) + dopplerShift = 0.125; + } + } + } - listenerProjection = -listenerProjection; - sourceProjection = -sourceProjection; + return dopplerShift; +} - double scaledSpeedOfSound = speedOfSound / dopplerFactor; - listenerProjection = min(listenerProjection, scaledSpeedOfSound); - sourceProjection = min(sourceProjection, scaledSpeedOfSound); +float PannerNode::calculateDistanceConeGain() +{ + FloatPoint3D listenerPosition = listener()->position(); - dopplerShift = ((speedOfSound - dopplerFactor * listenerProjection) / (speedOfSound - dopplerFactor * sourceProjection)); - fixNANs(dopplerShift); // avoid illegal values + double listenerDistance = m_position.distanceTo(listenerPosition); + double distanceGain = m_distanceEffect.gain(listenerDistance); + double coneGain = m_coneEffect.gain(m_position, m_orientation, listenerPosition); - // Limit the pitch shifting to 4 octaves up and 3 octaves down. - if (dopplerShift > 16.0) - dopplerShift = 16.0; - else if (dopplerShift < 0.125) - dopplerShift = 0.125; - } + return float(distanceGain * coneGain); +} + +void PannerNode::azimuthElevation(double* outAzimuth, double* outElevation) +{ + ASSERT(context()->isAudioThread()); + + if (isAzimuthElevationDirty()) { + calculateAzimuthElevation(&m_cachedAzimuth, &m_cachedElevation); + m_isAzimuthElevationDirty = false; } - return static_cast<float>(dopplerShift); + *outAzimuth = m_cachedAzimuth; + *outElevation = m_cachedElevation; +} + +double PannerNode::dopplerRate() +{ + ASSERT(context()->isAudioThread()); + + if (isDopplerRateDirty()) { + m_cachedDopplerRate = calculateDopplerRate(); + m_isDopplerRateDirty = false; + } + + return m_cachedDopplerRate; } float PannerNode::distanceConeGain() { - FloatPoint3D listenerPosition = listener()->position(); + ASSERT(context()->isAudioThread()); - double listenerDistance = m_position.distanceTo(listenerPosition); - double distanceGain = m_distanceEffect.gain(listenerDistance); + if (isDistanceConeGainDirty()) { + m_cachedDistanceConeGain = calculateDistanceConeGain(); + m_isDistanceConeGainDirty = false; + } - m_distanceGain->setValue(static_cast<float>(distanceGain)); + return m_cachedDistanceConeGain; +} - // FIXME: could optimize by caching coneGain - double coneGain = m_coneEffect.gain(m_position, m_orientation, listenerPosition); +void PannerNode::markPannerAsDirty(unsigned dirty) +{ + if (dirty & PannerNode::AzimuthElevationDirty) + m_isAzimuthElevationDirty = true; - m_coneGain->setValue(static_cast<float>(coneGain)); + if (dirty & PannerNode::DistanceConeGainDirty) + m_isDistanceConeGainDirty = true; - return float(distanceGain * coneGain); + if (dirty & PannerNode::DopplerRateDirty) + m_isDopplerRateDirty = true; } -void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node) +void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<AudioNode*, bool>& visitedNodes) { ASSERT(node); if (!node) @@ -405,7 +564,14 @@ void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node) for (unsigned j = 0; j < input->numberOfRenderingConnections(); ++j) { AudioNodeOutput* connectedOutput = input->renderingOutput(j); AudioNode* connectedNode = connectedOutput->node(); - notifyAudioSourcesConnectedToNode(connectedNode); // recurse + HashMap<AudioNode*, bool>::iterator iterator = visitedNodes.find(connectedNode); + + // If we've seen this node already, we don't need to process it again. Otherwise, + // mark it as visited and recurse through the node looking for sources. + if (iterator == visitedNodes.end()) { + visitedNodes.set(connectedNode, true); + notifyAudioSourcesConnectedToNode(connectedNode, visitedNodes); // recurse + } } } } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.h index 358eccabea2..840982b387f 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.h @@ -28,11 +28,12 @@ #include "platform/audio/AudioBus.h" #include "platform/audio/Cone.h" #include "platform/audio/Distance.h" +#include "platform/audio/HRTFDatabaseLoader.h" #include "platform/audio/Panner.h" #include "modules/webaudio/AudioListener.h" #include "modules/webaudio/AudioNode.h" -#include "modules/webaudio/AudioParam.h" #include "platform/geometry/FloatPoint3D.h" +#include "wtf/HashMap.h" #include "wtf/OwnPtr.h" namespace WebCore { @@ -44,87 +45,64 @@ namespace WebCore { // A cone effect will attenuate the gain as the orientation moves away from the listener. // All of these effects follow the OpenAL specification very closely. -class PannerNode : public AudioNode { +class PannerNode FINAL : public AudioNode { public: - // These must be defined as in the .idl file and must match those in the Panner class. + // These enums are used to distinguish what cached values of panner are dirty. enum { - EQUALPOWER = 0, - HRTF = 1, - SOUNDFIELD = 2, + AzimuthElevationDirty = 0x1, + DistanceConeGainDirty = 0x2, + DopplerRateDirty = 0x4, }; - // These must be defined as in the .idl file and must match those - // in the DistanceEffect class. - enum { - LINEAR_DISTANCE = 0, - INVERSE_DISTANCE = 1, - EXPONENTIAL_DISTANCE = 2, - }; - - static PassRefPtr<PannerNode> create(AudioContext* context, float sampleRate) + static PassRefPtrWillBeRawPtr<PannerNode> create(AudioContext* context, float sampleRate) { - return adoptRef(new PannerNode(context, sampleRate)); + return adoptRefWillBeNoop(new PannerNode(context, sampleRate)); } virtual ~PannerNode(); // AudioNode - virtual void process(size_t framesToProcess); - virtual void pullInputs(size_t framesToProcess); - virtual void reset(); - virtual void initialize(); - virtual void uninitialize(); - - // Listener - AudioListener* listener(); + virtual void process(size_t framesToProcess) OVERRIDE; + virtual void pullInputs(size_t framesToProcess) OVERRIDE; + virtual void initialize() OVERRIDE; + virtual void uninitialize() OVERRIDE; // Panning model String panningModel() const; - bool setPanningModel(unsigned); // Returns true on success. void setPanningModel(const String&); - // Position - FloatPoint3D position() const { return m_position; } - void setPosition(float x, float y, float z) { m_position = FloatPoint3D(x, y, z); } - - // Orientation - FloatPoint3D orientation() const { return m_position; } - void setOrientation(float x, float y, float z) { m_orientation = FloatPoint3D(x, y, z); } - - // Velocity - FloatPoint3D velocity() const { return m_velocity; } - void setVelocity(float x, float y, float z) { m_velocity = FloatPoint3D(x, y, z); } + // Position, orientation and velocity + void setPosition(float x, float y, float z); + void setOrientation(float x, float y, float z); + void setVelocity(float x, float y, float z); // Distance parameters String distanceModel() const; - bool setDistanceModel(unsigned); // Returns true on success. void setDistanceModel(const String&); double refDistance() { return m_distanceEffect.refDistance(); } - void setRefDistance(double refDistance) { m_distanceEffect.setRefDistance(refDistance); } + void setRefDistance(double); double maxDistance() { return m_distanceEffect.maxDistance(); } - void setMaxDistance(double maxDistance) { m_distanceEffect.setMaxDistance(maxDistance); } + void setMaxDistance(double); double rolloffFactor() { return m_distanceEffect.rolloffFactor(); } - void setRolloffFactor(double rolloffFactor) { m_distanceEffect.setRolloffFactor(rolloffFactor); } + void setRolloffFactor(double); // Sound cones - angles in degrees double coneInnerAngle() const { return m_coneEffect.innerAngle(); } - void setConeInnerAngle(double angle) { m_coneEffect.setInnerAngle(angle); } + void setConeInnerAngle(double); double coneOuterAngle() const { return m_coneEffect.outerAngle(); } - void setConeOuterAngle(double angle) { m_coneEffect.setOuterAngle(angle); } + void setConeOuterAngle(double); double coneOuterGain() const { return m_coneEffect.outerGain(); } - void setConeOuterGain(double angle) { m_coneEffect.setOuterGain(angle); } + void setConeOuterGain(double); - void getAzimuthElevation(double* outAzimuth, double* outElevation); - float dopplerRate(); + void markPannerAsDirty(unsigned); - // Accessors for dynamically calculated gain values. - AudioParam* distanceGain() { return m_distanceGain.get(); } - AudioParam* coneGain() { return m_coneGain.get(); } + // It must be called on audio thread, currently called only process() in AudioBufferSourceNode. + double dopplerRate(); virtual double tailTime() const OVERRIDE { return m_panner ? m_panner->tailTime() : 0; } virtual double latencyTime() const OVERRIDE { return m_panner ? m_panner->latencyTime() : 0; } @@ -132,31 +110,58 @@ public: private: PannerNode(AudioContext*, float sampleRate); - // Returns the combined distance and cone gain attenuation. + // AudioContext's listener + AudioListener* listener(); + + bool setPanningModel(unsigned); // Returns true on success. + bool setDistanceModel(unsigned); // Returns true on success. + + void calculateAzimuthElevation(double* outAzimuth, double* outElevation); + float calculateDistanceConeGain(); // Returns the combined distance and cone gain attenuation. + double calculateDopplerRate(); + + void azimuthElevation(double* outAzimuth, double* outElevation); float distanceConeGain(); + bool isAzimuthElevationDirty() const { return m_isAzimuthElevationDirty; } + bool isDistanceConeGainDirty() const { return m_isDistanceConeGainDirty; } + bool isDopplerRateDirty() const { return m_isDopplerRateDirty; } + // Notifies any AudioBufferSourceNodes connected to us either directly or indirectly about our existence. // This is in order to handle the pitch change necessary for the doppler shift. - void notifyAudioSourcesConnectedToNode(AudioNode*); + void notifyAudioSourcesConnectedToNode(AudioNode*, HashMap<AudioNode*, bool> &visitedNodes); OwnPtr<Panner> m_panner; unsigned m_panningModel; + unsigned m_distanceModel; + // Current source location information FloatPoint3D m_position; FloatPoint3D m_orientation; FloatPoint3D m_velocity; + bool m_isAzimuthElevationDirty; + bool m_isDistanceConeGainDirty; + bool m_isDopplerRateDirty; + // Gain - RefPtr<AudioParam> m_distanceGain; - RefPtr<AudioParam> m_coneGain; DistanceEffect m_distanceEffect; ConeEffect m_coneEffect; float m_lastGain; + // Cached values + double m_cachedAzimuth; + double m_cachedElevation; + float m_cachedDistanceConeGain; + double m_cachedDopplerRate; + + RefPtr<HRTFDatabaseLoader> m_hrtfDatabaseLoader; + + // AudioContext's connection count unsigned m_connectionCount; - // Synchronize process() and setPanningModel() which can change the panner. - mutable Mutex m_pannerLock; + // Synchronize process() with setting of the panning model, source's location information, listener, distance parameters and sound cones. + mutable Mutex m_processLock; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.idl b/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.idl index 455740817ba..cbd1fc8f797 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/PannerNode.idl @@ -22,22 +22,23 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum PanningModelType { + "equalpower", + "HRTF" +}; + +enum DistanceModelType { + "linear", + "inverse", + "exponential" +}; + [ NoInterfaceObject, Conditional=WEB_AUDIO ] interface PannerNode : AudioNode { - // Panning model - const unsigned short EQUALPOWER = 0; - const unsigned short HRTF = 1; - const unsigned short SOUNDFIELD = 2; - - // Distance model - const unsigned short LINEAR_DISTANCE = 0; - const unsigned short INVERSE_DISTANCE = 1; - const unsigned short EXPONENTIAL_DISTANCE = 2; - // Default model for stereo is HRTF - [Custom=Setter] attribute DOMString panningModel; + attribute PanningModelType panningModel; // Uses a 3D cartesian coordinate system void setPosition(float x, float y, float z); @@ -45,7 +46,7 @@ void setVelocity(float x, float y, float z); // Distance model - [Custom=Setter] attribute DOMString distanceModel; + attribute DistanceModelType distanceModel; attribute double refDistance; attribute double maxDistance; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp index 28b7a24dc19..3724e5fce51 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp @@ -45,43 +45,43 @@ namespace WebCore { using namespace VectorMath; -PassRefPtr<PeriodicWave> PeriodicWave::create(float sampleRate, Float32Array* real, Float32Array* imag) +PassRefPtrWillBeRawPtr<PeriodicWave> PeriodicWave::create(float sampleRate, Float32Array* real, Float32Array* imag) { bool isGood = real && imag && real->length() == imag->length(); ASSERT(isGood); if (isGood) { - RefPtr<PeriodicWave> periodicWave = adoptRef(new PeriodicWave(sampleRate)); + RefPtrWillBeRawPtr<PeriodicWave> periodicWave = adoptRefWillBeNoop(new PeriodicWave(sampleRate)); size_t numberOfComponents = real->length(); periodicWave->createBandLimitedTables(real->data(), imag->data(), numberOfComponents); return periodicWave; } - return 0; + return nullptr; } -PassRefPtr<PeriodicWave> PeriodicWave::createSine(float sampleRate) +PassRefPtrWillBeRawPtr<PeriodicWave> PeriodicWave::createSine(float sampleRate) { - RefPtr<PeriodicWave> periodicWave = adoptRef(new PeriodicWave(sampleRate)); + RefPtrWillBeRawPtr<PeriodicWave> periodicWave = adoptRefWillBeNoop(new PeriodicWave(sampleRate)); periodicWave->generateBasicWaveform(OscillatorNode::SINE); return periodicWave; } -PassRefPtr<PeriodicWave> PeriodicWave::createSquare(float sampleRate) +PassRefPtrWillBeRawPtr<PeriodicWave> PeriodicWave::createSquare(float sampleRate) { - RefPtr<PeriodicWave> periodicWave = adoptRef(new PeriodicWave(sampleRate)); + RefPtrWillBeRawPtr<PeriodicWave> periodicWave = adoptRefWillBeNoop(new PeriodicWave(sampleRate)); periodicWave->generateBasicWaveform(OscillatorNode::SQUARE); return periodicWave; } -PassRefPtr<PeriodicWave> PeriodicWave::createSawtooth(float sampleRate) +PassRefPtrWillBeRawPtr<PeriodicWave> PeriodicWave::createSawtooth(float sampleRate) { - RefPtr<PeriodicWave> periodicWave = adoptRef(new PeriodicWave(sampleRate)); + RefPtrWillBeRawPtr<PeriodicWave> periodicWave = adoptRefWillBeNoop(new PeriodicWave(sampleRate)); periodicWave->generateBasicWaveform(OscillatorNode::SAWTOOTH); return periodicWave; } -PassRefPtr<PeriodicWave> PeriodicWave::createTriangle(float sampleRate) +PassRefPtrWillBeRawPtr<PeriodicWave> PeriodicWave::createTriangle(float sampleRate) { - RefPtr<PeriodicWave> periodicWave = adoptRef(new PeriodicWave(sampleRate)); + RefPtrWillBeRawPtr<PeriodicWave> periodicWave = adoptRefWillBeNoop(new PeriodicWave(sampleRate)); periodicWave->generateBasicWaveform(OscillatorNode::TRIANGLE); return periodicWave; } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.h b/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.h index d10b3e2c90f..1e62820f3ff 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.h @@ -40,15 +40,15 @@ namespace WebCore { -class PeriodicWave : public ScriptWrappable, public RefCounted<PeriodicWave> { +class PeriodicWave : public RefCountedWillBeGarbageCollectedFinalized<PeriodicWave>, public ScriptWrappable { public: - static PassRefPtr<PeriodicWave> createSine(float sampleRate); - static PassRefPtr<PeriodicWave> createSquare(float sampleRate); - static PassRefPtr<PeriodicWave> createSawtooth(float sampleRate); - static PassRefPtr<PeriodicWave> createTriangle(float sampleRate); + static PassRefPtrWillBeRawPtr<PeriodicWave> createSine(float sampleRate); + static PassRefPtrWillBeRawPtr<PeriodicWave> createSquare(float sampleRate); + static PassRefPtrWillBeRawPtr<PeriodicWave> createSawtooth(float sampleRate); + static PassRefPtrWillBeRawPtr<PeriodicWave> createTriangle(float sampleRate); // Creates an arbitrary periodic wave given the frequency components (Fourier coefficients). - static PassRefPtr<PeriodicWave> create(float sampleRate, Float32Array* real, Float32Array* imag); + static PassRefPtrWillBeRawPtr<PeriodicWave> create(float sampleRate, Float32Array* real, Float32Array* imag); // Returns pointers to the lower and higher wave data for the pitch range containing // the given fundamental frequency. These two tables are in adjacent "pitch" ranges @@ -62,7 +62,8 @@ public: float rateScale() const { return m_rateScale; } unsigned periodicWaveSize() const { return m_periodicWaveSize; } - float sampleRate() const { return m_sampleRate; } + + void trace(Visitor*) { } private: explicit PeriodicWave(float sampleRate); @@ -81,8 +82,6 @@ private: float m_rateScale; - unsigned numberOfRanges() const { return m_numberOfRanges; } - // Maximum possible number of partials (before culling). unsigned maxNumberOfPartials() const; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.idl b/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.idl index 40a04b127b0..3dccbc7b665 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/PeriodicWave.idl @@ -24,6 +24,7 @@ // PeriodicWave represents a periodic audio waveform given by its Fourier coefficients. [ + WillBeGarbageCollected, Conditional=WEB_AUDIO ] interface PeriodicWave { diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/RealtimeAnalyser.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/RealtimeAnalyser.cpp index d470a267079..b768a243917 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/RealtimeAnalyser.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/RealtimeAnalyser.cpp @@ -30,7 +30,6 @@ #include "platform/audio/AudioBus.h" #include "platform/audio/AudioUtilities.h" -#include "platform/audio/FFTFrame.h" #include "platform/audio/VectorMath.h" #include <algorithm> @@ -67,13 +66,6 @@ RealtimeAnalyser::RealtimeAnalyser() m_analysisFrame = adoptPtr(new FFTFrame(DefaultFFTSize)); } -void RealtimeAnalyser::reset() -{ - m_writeIndex = 0; - m_inputBuffer.zero(); - m_magnitudeBuffer.zero(); -} - bool RealtimeAnalyser::setFftSize(size_t size) { ASSERT(isMainThread()); @@ -145,7 +137,7 @@ void applyWindow(float* p, size_t n) for (unsigned i = 0; i < n; ++i) { double x = static_cast<double>(i) / static_cast<double>(n); - double window = a0 - a1 * cos(2 * piDouble * x) + a2 * cos(4 * piDouble * x); + double window = a0 - a1 * cos(twoPiDouble * x) + a2 * cos(twoPiDouble * 2.0 * x); p[i] *= float(window); } } @@ -185,7 +177,7 @@ void RealtimeAnalyser::doFFTAnalysis() imagP[0] = 0; // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FFT scaling factor). - const double magnitudeScale = 1.0 / DefaultFFTSize; + const double magnitudeScale = 1.0 / fftSize; // A value of 0 does no averaging with the previous result. Larger values produce slower, but smoother changes. double k = m_smoothingTimeConstant; @@ -264,6 +256,35 @@ void RealtimeAnalyser::getByteFrequencyData(Uint8Array* destinationArray) } } +void RealtimeAnalyser::getFloatTimeDomainData(Float32Array* destinationArray) +{ + ASSERT(isMainThread()); + + if (!destinationArray) + return; + + unsigned fftSize = this->fftSize(); + size_t len = min(fftSize, destinationArray->length()); + if (len > 0) { + bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_inputBuffer.size() > fftSize; + ASSERT(isInputBufferGood); + if (!isInputBufferGood) + return; + + float* inputBuffer = m_inputBuffer.data(); + float* destination = destinationArray->data(); + + unsigned writeIndex = m_writeIndex; + + for (unsigned i = 0; i < len; ++i) { + // Buffer access is protected due to modulo operation. + float value = inputBuffer[(i + writeIndex - fftSize + InputBufferSize) % InputBufferSize]; + + destination[i] = value; + } + } +} + void RealtimeAnalyser::getByteTimeDomainData(Uint8Array* destinationArray) { ASSERT(isMainThread()); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/RealtimeAnalyser.h b/chromium/third_party/WebKit/Source/modules/webaudio/RealtimeAnalyser.h index 5ce798f0703..87e7fda037a 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/RealtimeAnalyser.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/RealtimeAnalyser.h @@ -26,6 +26,7 @@ #define RealtimeAnalyser_h #include "platform/audio/AudioArray.h" +#include "platform/audio/FFTFrame.h" #include "wtf/Forward.h" #include "wtf/Noncopyable.h" #include "wtf/OwnPtr.h" @@ -33,31 +34,29 @@ namespace WebCore { class AudioBus; -class FFTFrame; class RealtimeAnalyser FINAL { WTF_MAKE_NONCOPYABLE(RealtimeAnalyser); public: RealtimeAnalyser(); - void reset(); - size_t fftSize() const { return m_fftSize; } bool setFftSize(size_t); unsigned frequencyBinCount() const { return m_fftSize / 2; } - void setMinDecibels(float k) { m_minDecibels = k; } - float minDecibels() const { return static_cast<float>(m_minDecibels); } + void setMinDecibels(double k) { m_minDecibels = k; } + double minDecibels() const { return m_minDecibels; } - void setMaxDecibels(float k) { m_maxDecibels = k; } - float maxDecibels() const { return static_cast<float>(m_maxDecibels); } + void setMaxDecibels(double k) { m_maxDecibels = k; } + double maxDecibels() const { return m_maxDecibels; } - void setSmoothingTimeConstant(float k) { m_smoothingTimeConstant = k; } - float smoothingTimeConstant() const { return static_cast<float>(m_smoothingTimeConstant); } + void setSmoothingTimeConstant(double k) { m_smoothingTimeConstant = k; } + double smoothingTimeConstant() const { return m_smoothingTimeConstant; } void getFloatFrequencyData(Float32Array*); void getByteFrequencyData(Uint8Array*); + void getFloatTimeDomainData(Float32Array*); void getByteTimeDomainData(Uint8Array*); // The audio thread writes input data here. diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp index d3f14c884f2..dbbcfdd595f 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp @@ -56,7 +56,7 @@ static size_t chooseBufferSize() return bufferSize; } -PassRefPtr<ScriptProcessorNode> ScriptProcessorNode::create(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels) +PassRefPtrWillBeRawPtr<ScriptProcessorNode> ScriptProcessorNode::create(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels) { // Check for valid buffer size. switch (bufferSize) { @@ -72,19 +72,19 @@ PassRefPtr<ScriptProcessorNode> ScriptProcessorNode::create(AudioContext* contex case 16384: break; default: - return 0; + return nullptr; } if (!numberOfInputChannels && !numberOfOutputChannels) - return 0; + return nullptr; if (numberOfInputChannels > AudioContext::maxNumberOfChannels()) - return 0; + return nullptr; if (numberOfOutputChannels > AudioContext::maxNumberOfChannels()) - return 0; + return nullptr; - return adoptRef(new ScriptProcessorNode(context, sampleRate, bufferSize, numberOfInputChannels, numberOfOutputChannels)); + return adoptRefWillBeNoop(new ScriptProcessorNode(context, sampleRate, bufferSize, numberOfInputChannels, numberOfOutputChannels)); } ScriptProcessorNode::ScriptProcessorNode(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels) @@ -93,7 +93,6 @@ ScriptProcessorNode::ScriptProcessorNode(AudioContext* context, float sampleRate , m_doubleBufferIndexForEvent(0) , m_bufferSize(bufferSize) , m_bufferReadWriteIndex(0) - , m_isRequestOutstanding(false) , m_numberOfInputChannels(numberOfInputChannels) , m_numberOfOutputChannels(numberOfOutputChannels) , m_internalInputBus(AudioBus::create(numberOfInputChannels, AudioNode::ProcessingSizeInFrames, false)) @@ -128,8 +127,8 @@ void ScriptProcessorNode::initialize() // Create double buffers on both the input and output sides. // These AudioBuffers will be directly accessed in the main thread by JavaScript. for (unsigned i = 0; i < 2; ++i) { - RefPtr<AudioBuffer> inputBuffer = m_numberOfInputChannels ? AudioBuffer::create(m_numberOfInputChannels, bufferSize(), sampleRate) : 0; - RefPtr<AudioBuffer> outputBuffer = m_numberOfOutputChannels ? AudioBuffer::create(m_numberOfOutputChannels, bufferSize(), sampleRate) : 0; + RefPtrWillBeRawPtr<AudioBuffer> inputBuffer = m_numberOfInputChannels ? AudioBuffer::create(m_numberOfInputChannels, bufferSize(), sampleRate) : nullptr; + RefPtrWillBeRawPtr<AudioBuffer> outputBuffer = m_numberOfOutputChannels ? AudioBuffer::create(m_numberOfOutputChannels, bufferSize(), sampleRate) : nullptr; m_inputBuffers.append(inputBuffer); m_outputBuffers.append(outputBuffer); @@ -214,7 +213,9 @@ void ScriptProcessorNode::process(size_t framesToProcess) if (!m_bufferReadWriteIndex) { // Avoid building up requests on the main thread to fire process events when they're not being handled. // This could be a problem if the main thread is very busy doing other things and is being held up handling previous requests. - if (m_isRequestOutstanding) { + // The audio thread can't block on this lock, so we call tryLock() instead. + MutexTryLocker tryLocker(m_processEventLock); + if (!tryLocker.locked()) { // We're late in handling the previous request. The main thread must be very busy. // The best we can do is clear out the buffer ourself here. outputBuffer->zero(); @@ -224,7 +225,6 @@ void ScriptProcessorNode::process(size_t framesToProcess) // Fire the event on the main thread, not this one (which is the realtime audio thread). m_doubleBufferIndexForEvent = m_doubleBufferIndex; - m_isRequestOutstanding = true; callOnMainThread(fireProcessEventDispatch, this); } @@ -247,7 +247,7 @@ void ScriptProcessorNode::fireProcessEventDispatch(void* userData) void ScriptProcessorNode::fireProcessEvent() { - ASSERT(isMainThread() && m_isRequestOutstanding); + ASSERT(isMainThread()); bool isIndexGood = m_doubleBufferIndexForEvent < 2; ASSERT(isIndexGood); @@ -262,22 +262,15 @@ void ScriptProcessorNode::fireProcessEvent() // Avoid firing the event if the document has already gone away. if (context()->executionContext()) { - // Let the audio thread know we've gotten to the point where it's OK for it to make another request. - m_isRequestOutstanding = false; + // This synchronizes with process(). + MutexLocker processLocker(m_processEventLock); - // Call the JavaScript event handler which will do the audio processing. - dispatchEvent(AudioProcessingEvent::create(inputBuffer, outputBuffer)); - } -} - -void ScriptProcessorNode::reset() -{ - m_bufferReadWriteIndex = 0; - m_doubleBufferIndex = 0; + // Calculate a playbackTime with the buffersize which needs to be processed each time onaudioprocess is called. + // The outputBuffer being passed to JS will be played after exhuasting previous outputBuffer by double-buffering. + double playbackTime = (context()->currentSampleFrame() + m_bufferSize) / static_cast<double>(context()->sampleRate()); - for (unsigned i = 0; i < 2; ++i) { - m_inputBuffers[i]->zero(); - m_outputBuffers[i]->zero(); + // Call the JavaScript event handler which will do the audio processing. + dispatchEvent(AudioProcessingEvent::create(inputBuffer, outputBuffer, playbackTime)); } } @@ -291,6 +284,13 @@ double ScriptProcessorNode::latencyTime() const return std::numeric_limits<double>::infinity(); } +void ScriptProcessorNode::trace(Visitor* visitor) +{ + visitor->trace(m_inputBuffers); + visitor->trace(m_outputBuffers); + AudioNode::trace(visitor); +} + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h index 3e1aa7a5535..edbe7423101 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h @@ -44,26 +44,26 @@ class AudioProcessingEvent; // The "onaudioprocess" attribute is an event listener which will get called periodically with an AudioProcessingEvent which has // AudioBuffers for each input and output. -class ScriptProcessorNode : public AudioNode { +class ScriptProcessorNode FINAL : public AudioNode { public: // bufferSize must be one of the following values: 256, 512, 1024, 2048, 4096, 8192, 16384. // This value controls how frequently the onaudioprocess event handler is called and how many sample-frames need to be processed each call. // Lower numbers for bufferSize will result in a lower (better) latency. Higher numbers will be necessary to avoid audio breakup and glitches. // The value chosen must carefully balance between latency and audio quality. - static PassRefPtr<ScriptProcessorNode> create(AudioContext*, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels); + static PassRefPtrWillBeRawPtr<ScriptProcessorNode> create(AudioContext*, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels); virtual ~ScriptProcessorNode(); // AudioNode - virtual void process(size_t framesToProcess); - virtual void reset(); - virtual void initialize(); - virtual void uninitialize(); + virtual void process(size_t framesToProcess) OVERRIDE; + virtual void initialize() OVERRIDE; + virtual void uninitialize() OVERRIDE; size_t bufferSize() const { return m_bufferSize; } DEFINE_ATTRIBUTE_EVENT_LISTENER(audioprocess); + void trace(Visitor*); private: virtual double tailTime() const OVERRIDE; @@ -79,17 +79,19 @@ private: void swapBuffers() { m_doubleBufferIndex = 1 - m_doubleBufferIndex; } unsigned m_doubleBufferIndex; unsigned m_doubleBufferIndexForEvent; - Vector<RefPtr<AudioBuffer> > m_inputBuffers; - Vector<RefPtr<AudioBuffer> > m_outputBuffers; + WillBeHeapVector<RefPtrWillBeMember<AudioBuffer> > m_inputBuffers; + WillBeHeapVector<RefPtrWillBeMember<AudioBuffer> > m_outputBuffers; size_t m_bufferSize; unsigned m_bufferReadWriteIndex; - volatile bool m_isRequestOutstanding; unsigned m_numberOfInputChannels; unsigned m_numberOfOutputChannels; RefPtr<AudioBus> m_internalInputBus; + + // Synchronize process() with fireProcessEvent(). + mutable Mutex m_processEventLock; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.cpp index 6134abe7571..e2339c43b29 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.cpp @@ -100,24 +100,30 @@ void WaveShaperDSPKernel::processCurve(const float* source, float* destination, for (unsigned i = 0; i < framesToProcess; ++i) { const float input = source[i]; - // Calculate a virtual index based on input -1 -> +1 with 0 being at the center of the curve data. - // Then linearly interpolate between the two points in the curve. - double virtualIndex = 0.5 * (input + 1) * curveLength; - int index1 = static_cast<int>(virtualIndex); - int index2 = index1 + 1; - double interpolationFactor = virtualIndex - index1; - - // Clip index to the input range of the curve. - // This takes care of input outside of nominal range -1 -> +1 - index1 = max(index1, 0); - index1 = min(index1, curveLength - 1); - index2 = max(index2, 0); - index2 = min(index2, curveLength - 1); - - double value1 = curveData[index1]; - double value2 = curveData[index2]; - - double output = (1.0 - interpolationFactor) * value1 + interpolationFactor * value2; + // Calculate a virtual index based on input -1 -> +1 with -1 being curve[0], +1 being + // curve[curveLength - 1], and 0 being at the center of the curve data. Then linearly + // interpolate between the two points in the curve. + double virtualIndex = 0.5 * (input + 1) * (curveLength - 1); + double output; + + if (virtualIndex < 0) { + // input < -1, so use curve[0] + output = curveData[0]; + } else if (virtualIndex >= curveLength - 1) { + // input >= 1, so use last curve value + output = curveData[curveLength - 1]; + } else { + // The general case where -1 <= input < 1, where 0 <= virtualIndex < curveLength - 1, + // so interpolate between the nearest samples on the curve. + unsigned index1 = static_cast<unsigned>(virtualIndex); + unsigned index2 = index1 + 1; + double interpolationFactor = virtualIndex - index1; + + double value1 = curveData[index1]; + double value2 = curveData[index2]; + + output = (1.0 - interpolationFactor) * value1 + interpolationFactor * value2; + } destination[i] = output; } } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.h b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.h index 78d7bfe85c4..54017a18c8f 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.h @@ -38,13 +38,13 @@ class WaveShaperProcessor; // WaveShaperDSPKernel is an AudioDSPKernel and is responsible for non-linear distortion on one channel. -class WaveShaperDSPKernel : public AudioDSPKernel { +class WaveShaperDSPKernel FINAL : public AudioDSPKernel { public: explicit WaveShaperDSPKernel(WaveShaperProcessor*); // AudioDSPKernel - virtual void process(const float* source, float* dest, size_t framesToProcess); - virtual void reset(); + virtual void process(const float* source, float* dest, size_t framesToProcess) OVERRIDE; + virtual void reset() OVERRIDE; virtual double tailTime() const OVERRIDE { return 0; } virtual double latencyTime() const OVERRIDE; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.cpp b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.cpp index 3e84aaa304b..0474826663e 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.cpp +++ b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.cpp @@ -72,12 +72,7 @@ void WaveShaperNode::setOversample(const String& type, ExceptionState& exception } else if (type == "4x") { waveShaperProcessor()->setOversample(WaveShaperProcessor::OverSample4x); } else { - exceptionState.throwDOMException( - InvalidStateError, - ExceptionMessages::failedToSet( - "oversample", - "WaveShaperNode", - "invalid oversample '" + type + "': must be 'none', '2x', or '4x'.")); + ASSERT_NOT_REACHED(); } } diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.h b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.h index 8855630bb4d..159a39fb012 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.h @@ -34,11 +34,11 @@ namespace WebCore { class ExceptionState; -class WaveShaperNode : public AudioBasicProcessorNode { +class WaveShaperNode FINAL : public AudioBasicProcessorNode { public: - static PassRefPtr<WaveShaperNode> create(AudioContext* context) + static PassRefPtrWillBeRawPtr<WaveShaperNode> create(AudioContext* context) { - return adoptRef(new WaveShaperNode(context)); + return adoptRefWillBeNoop(new WaveShaperNode(context)); } // setCurve() is called on the main thread. @@ -48,8 +48,6 @@ public: void setOversample(const String& , ExceptionState&); String oversample() const; - double latency() const { return latencyTime(); } - private: explicit WaveShaperNode(AudioContext*); diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.idl b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.idl index e1ee72b6326..e17ad17ee4a 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.idl +++ b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.idl @@ -22,9 +22,15 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum OverSampleType { + "none", + "2x", + "4x" +}; + [ Conditional=WEB_AUDIO ] interface WaveShaperNode : AudioNode { attribute Float32Array curve; - [RaisesException=Setter] attribute DOMString oversample; + [RaisesException=Setter] attribute OverSampleType oversample; }; diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperProcessor.h b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperProcessor.h index 79c826496ff..e69f0a616d0 100644 --- a/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperProcessor.h +++ b/chromium/third_party/WebKit/Source/modules/webaudio/WaveShaperProcessor.h @@ -36,7 +36,7 @@ namespace WebCore { // WaveShaperProcessor is an AudioDSPKernelProcessor which uses WaveShaperDSPKernel objects to implement non-linear distortion effects. -class WaveShaperProcessor : public AudioDSPKernelProcessor { +class WaveShaperProcessor FINAL : public AudioDSPKernelProcessor { public: enum OverSampleType { OverSampleNone, @@ -48,9 +48,9 @@ public: virtual ~WaveShaperProcessor(); - virtual PassOwnPtr<AudioDSPKernel> createKernel(); + virtual PassOwnPtr<AudioDSPKernel> createKernel() OVERRIDE; - virtual void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess); + virtual void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess) OVERRIDE; void setCurve(Float32Array*); Float32Array* curve() { return m_curve.get(); } @@ -63,9 +63,6 @@ private: RefPtr<Float32Array> m_curve; OverSampleType m_oversample; - - // This synchronizes process() with setCurve(). - mutable Mutex m_processLock; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webaudio/WindowWebAudio.idl b/chromium/third_party/WebKit/Source/modules/webaudio/WindowWebAudio.idl new file mode 100644 index 00000000000..75788e12b42 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/webaudio/WindowWebAudio.idl @@ -0,0 +1,12 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + ImplementedAs=DOMWindowWebAudio, +] partial interface Window { + [Conditional=WEB_AUDIO, RuntimeEnabled=WebAudio] attribute AudioContextConstructor AudioContext; + [Conditional=WEB_AUDIO, RuntimeEnabled=WebAudio] attribute OfflineAudioContextConstructor OfflineAudioContext; + [Conditional=WEB_AUDIO, RuntimeEnabled=WebAudio] attribute AudioContextConstructor webkitAudioContext; + [Conditional=WEB_AUDIO, RuntimeEnabled=WebAudio] attribute OfflineAudioContextConstructor webkitOfflineAudioContext; +}; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractDatabaseServer.h b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractDatabaseServer.h index ee3a8435545..d2fb1dce2f6 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractDatabaseServer.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractDatabaseServer.h @@ -28,6 +28,7 @@ #include "modules/webdatabase/DatabaseBasicTypes.h" #include "modules/webdatabase/DatabaseError.h" +#include "platform/heap/Handle.h" #include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" @@ -41,7 +42,7 @@ class SecurityOrigin; class AbstractDatabaseServer { public: virtual String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist = true) = 0; - virtual PassRefPtr<DatabaseBackendBase> openDatabase(RefPtr<DatabaseContext>&, DatabaseType, + virtual PassRefPtrWillBeRawPtr<DatabaseBackendBase> openDatabase(DatabaseContext*, DatabaseType, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError&, String& errorMessage) = 0; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLStatement.h b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLStatement.h index 1fb99128c35..9ddcda69988 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLStatement.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLStatement.h @@ -26,15 +26,16 @@ #ifndef AbstractSQLStatement_h #define AbstractSQLStatement_h -#include "wtf/ThreadSafeRefCounted.h" +#include "platform/heap/Handle.h" namespace WebCore { class AbstractSQLStatementBackend; -class AbstractSQLStatement { +class AbstractSQLStatement : public NoBaseWillBeGarbageCollectedFinalized<AbstractSQLStatement> { public: virtual ~AbstractSQLStatement() { } + virtual void trace(Visitor*) { } virtual void setBackend(AbstractSQLStatementBackend*) = 0; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLStatementBackend.h b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLStatementBackend.h index 11a8c531d67..1e55220f5ac 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLStatementBackend.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLStatementBackend.h @@ -28,16 +28,18 @@ #include "modules/webdatabase/SQLError.h" #include "modules/webdatabase/SQLResultSet.h" +#include "platform/heap/Handle.h" #include "wtf/ThreadSafeRefCounted.h" namespace WebCore { -class AbstractSQLStatementBackend : public ThreadSafeRefCounted<AbstractSQLStatementBackend> { +class AbstractSQLStatementBackend : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<AbstractSQLStatementBackend> { public: virtual ~AbstractSQLStatementBackend() { } + virtual void trace(Visitor*) { } - virtual PassRefPtr<SQLError> sqlError() const = 0; - virtual PassRefPtr<SQLResultSet> sqlResultSet() const = 0; + virtual SQLErrorData* sqlError() const = 0; + virtual SQLResultSet* sqlResultSet() const = 0; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLTransaction.h b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLTransaction.h index ba8e9997e5d..d32fe67f726 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLTransaction.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLTransaction.h @@ -27,15 +27,17 @@ #define AbstractSQLTransaction_h #include "modules/webdatabase/SQLTransactionState.h" +#include "platform/heap/Handle.h" #include "wtf/ThreadSafeRefCounted.h" namespace WebCore { class AbstractSQLTransactionBackend; -class AbstractSQLTransaction : public ThreadSafeRefCounted<AbstractSQLTransaction> { +class AbstractSQLTransaction : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<AbstractSQLTransaction> { public: virtual ~AbstractSQLTransaction() { } + virtual void trace(Visitor*) { } virtual void requestTransitToState(SQLTransactionState) = 0; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLTransactionBackend.h b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLTransactionBackend.h index f21f1cd3514..e72ac8ebf76 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLTransactionBackend.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/AbstractSQLTransactionBackend.h @@ -30,6 +30,7 @@ #include "modules/webdatabase/AbstractSQLStatement.h" #include "modules/webdatabase/SQLError.h" #include "modules/webdatabase/SQLTransactionState.h" +#include "platform/heap/Handle.h" #include "wtf/PassOwnPtr.h" #include "wtf/ThreadSafeRefCounted.h" #include "wtf/Vector.h" @@ -37,17 +38,18 @@ namespace WebCore { -class AbstractSQLTransactionBackend : public ThreadSafeRefCounted<AbstractSQLTransactionBackend> { +class AbstractSQLTransactionBackend : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<AbstractSQLTransactionBackend> { public: virtual ~AbstractSQLTransactionBackend() { } + virtual void trace(Visitor*) { } virtual void requestTransitToState(SQLTransactionState) = 0; - virtual PassRefPtr<SQLError> transactionError() = 0; + virtual SQLErrorData* transactionError() = 0; virtual AbstractSQLStatement* currentStatement() = 0; virtual void setShouldRetryCurrentStatement(bool) = 0; - virtual void executeSQL(PassOwnPtr<AbstractSQLStatement>, const String& statement, + virtual void executeSQL(PassOwnPtrWillBeRawPtr<AbstractSQLStatement>, const String& statement, const Vector<SQLValue>& arguments, int permissions) = 0; }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/ChangeVersionWrapper.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/ChangeVersionWrapper.cpp index 370efa09c20..b9320126b45 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/ChangeVersionWrapper.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/ChangeVersionWrapper.cpp @@ -51,14 +51,14 @@ bool ChangeVersionWrapper::performPreflight(SQLTransactionBackend* transaction) if (!database->getVersionFromDatabase(actualVersion)) { int sqliteError = database->sqliteDatabase().lastError(); database->reportChangeVersionResult(1, SQLError::UNKNOWN_ERR, sqliteError); - m_sqlError = SQLError::create(SQLError::UNKNOWN_ERR, "unable to read the current version", - sqliteError, database->sqliteDatabase().lastErrorMsg()); + m_sqlError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unable to read the current version", + sqliteError, database->sqliteDatabase().lastErrorMsg()); return false; } if (actualVersion != m_oldVersion) { database->reportChangeVersionResult(2, SQLError::VERSION_ERR, 0); - m_sqlError = SQLError::create(SQLError::VERSION_ERR, "current version of the database and `oldVersion` argument do not match"); + m_sqlError = SQLErrorData::create(SQLError::VERSION_ERR, "current version of the database and `oldVersion` argument do not match"); return false; } @@ -74,8 +74,8 @@ bool ChangeVersionWrapper::performPostflight(SQLTransactionBackend* transaction) if (!database->setVersionInDatabase(m_newVersion)) { int sqliteError = database->sqliteDatabase().lastError(); database->reportChangeVersionResult(3, SQLError::UNKNOWN_ERR, sqliteError); - m_sqlError = SQLError::create(SQLError::UNKNOWN_ERR, "unable to set new version in database", - sqliteError, database->sqliteDatabase().lastErrorMsg()); + m_sqlError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unable to set new version in database", + sqliteError, database->sqliteDatabase().lastErrorMsg()); return false; } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/ChangeVersionWrapper.h b/chromium/third_party/WebKit/Source/modules/webdatabase/ChangeVersionWrapper.h index 7ac025ecc67..0cbc7607458 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/ChangeVersionWrapper.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/ChangeVersionWrapper.h @@ -29,27 +29,29 @@ #define ChangeVersionWrapper_h #include "modules/webdatabase/SQLTransactionBackend.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" namespace WebCore { -class SQLError; +class SQLErrorData; -class ChangeVersionWrapper : public SQLTransactionWrapper { +class ChangeVersionWrapper FINAL : public SQLTransactionWrapper { public: - static PassRefPtr<ChangeVersionWrapper> create(const String& oldVersion, const String& newVersion) { return adoptRef(new ChangeVersionWrapper(oldVersion, newVersion)); } + static PassRefPtrWillBeRawPtr<ChangeVersionWrapper> create(const String& oldVersion, const String& newVersion) { return adoptRefWillBeNoop(new ChangeVersionWrapper(oldVersion, newVersion)); } - virtual bool performPreflight(SQLTransactionBackend*); - virtual bool performPostflight(SQLTransactionBackend*); - virtual SQLError* sqlError() const { return m_sqlError.get(); } - virtual void handleCommitFailedAfterPostflight(SQLTransactionBackend*); + virtual void trace(Visitor* visitor) OVERRIDE { SQLTransactionWrapper::trace(visitor); } + virtual bool performPreflight(SQLTransactionBackend*) OVERRIDE; + virtual bool performPostflight(SQLTransactionBackend*) OVERRIDE; + virtual SQLErrorData* sqlError() const OVERRIDE { return m_sqlError.get(); } + virtual void handleCommitFailedAfterPostflight(SQLTransactionBackend*) OVERRIDE; private: ChangeVersionWrapper(const String& oldVersion, const String& newVersion); String m_oldVersion; String m_newVersion; - RefPtr<SQLError> m_sqlError; + OwnPtr<SQLErrorData> m_sqlError; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DOMWindowWebDatabase.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DOMWindowWebDatabase.cpp index e5871988f62..9c5ff3462ba 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DOMWindowWebDatabase.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DOMWindowWebDatabase.cpp @@ -28,29 +28,29 @@ #include "modules/webdatabase/DOMWindowWebDatabase.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "modules/webdatabase/Database.h" #include "modules/webdatabase/DatabaseCallback.h" #include "modules/webdatabase/DatabaseManager.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/weborigin/SecurityOrigin.h" namespace WebCore { -PassRefPtr<Database> DOMWindowWebDatabase::openDatabase(DOMWindow* window, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<Database> DOMWindowWebDatabase::openDatabase(LocalDOMWindow& window, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState& exceptionState) { - if (!window->isCurrentlyDisplayedInFrame()) - return 0; + if (!window.isCurrentlyDisplayedInFrame()) + return nullptr; - RefPtr<Database> database = 0; + RefPtrWillBeRawPtr<Database> database = nullptr; DatabaseManager& dbManager = DatabaseManager::manager(); DatabaseError error = DatabaseError::None; - if (RuntimeEnabledFeatures::databaseEnabled() && window->document()->securityOrigin()->canAccessDatabase()) { + if (RuntimeEnabledFeatures::databaseEnabled() && window.document()->securityOrigin()->canAccessDatabase()) { String errorMessage; - database = dbManager.openDatabase(window->document(), name, version, displayName, estimatedSize, creationCallback, error, errorMessage); + database = dbManager.openDatabase(window.document(), name, version, displayName, estimatedSize, creationCallback, error, errorMessage); ASSERT(database || error != DatabaseError::None); if (error != DatabaseError::None) DatabaseManager::throwExceptionForDatabaseError(error, errorMessage, exceptionState); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DOMWindowWebDatabase.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DOMWindowWebDatabase.h index 048bbc2d984..ce0833a594f 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DOMWindowWebDatabase.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DOMWindowWebDatabase.h @@ -27,6 +27,7 @@ #ifndef DOMWindowWebDatabase_h #define DOMWindowWebDatabase_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" @@ -34,15 +35,15 @@ namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class Database; class DatabaseCallback; class ExceptionState; -class Frame; +class LocalFrame; class DOMWindowWebDatabase { public: - static PassRefPtr<Database> openDatabase(DOMWindow*, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState&); + static PassRefPtrWillBeRawPtr<Database> openDatabase(LocalDOMWindow&, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState&); private: DOMWindowWebDatabase() { }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/Database.cpp index b730139881c..db25a0f61e6 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/Database.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/Database.cpp @@ -57,7 +57,7 @@ namespace WebCore { -PassRefPtr<Database> Database::create(ExecutionContext*, PassRefPtr<DatabaseBackendBase> backend) +PassRefPtrWillBeRawPtr<Database> Database::create(ExecutionContext*, PassRefPtrWillBeRawPtr<DatabaseBackendBase> backend) { // FIXME: Currently, we're only simulating the backend by return the // frontend database as its own the backend. When we split the 2 apart, @@ -66,10 +66,10 @@ PassRefPtr<Database> Database::create(ExecutionContext*, PassRefPtr<DatabaseBack return static_cast<Database*>(backend.get()); } -Database::Database(PassRefPtr<DatabaseContext> databaseContext, +Database::Database(DatabaseContext* databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) - : DatabaseBase(databaseContext->executionContext()) - , DatabaseBackend(databaseContext, name, expectedVersion, displayName, estimatedSize) + : DatabaseBackend(databaseContext, name, expectedVersion, displayName, estimatedSize) + , DatabaseBase(databaseContext->executionContext()) , m_databaseContext(DatabaseBackend::databaseContext()) { ScriptWrappable::init(this); @@ -79,40 +79,14 @@ Database::Database(PassRefPtr<DatabaseContext> databaseContext, ASSERT(m_databaseContext->databaseThread()); } -class DerefContextTask : public ExecutionContextTask { -public: - static PassOwnPtr<DerefContextTask> create(PassRefPtr<ExecutionContext> context) - { - return adoptPtr(new DerefContextTask(context)); - } - - virtual void performTask(ExecutionContext* context) - { - ASSERT_UNUSED(context, context == m_context); - m_context.clear(); - } - - virtual bool isCleanupTask() const { return true; } - -private: - DerefContextTask(PassRefPtr<ExecutionContext> context) - : m_context(context) - { - } - - RefPtr<ExecutionContext> m_context; -}; - Database::~Database() { - // The reference to the ExecutionContext needs to be cleared on the JavaScript thread. If we're on that thread already, we can just let the RefPtr's destruction do the dereffing. - if (!m_executionContext->isContextThread()) { - // Grab a pointer to the script execution here because we're releasing it when we pass it to - // DerefContextTask::create. - ExecutionContext* executionContext = m_executionContext.get(); +} - executionContext->postTask(DerefContextTask::create(m_executionContext.release())); - } +void Database::trace(Visitor* visitor) +{ + visitor->trace(m_databaseContext); + DatabaseBackend::trace(visitor); } Database* Database::from(DatabaseBackend* backend) @@ -120,7 +94,7 @@ Database* Database::from(DatabaseBackend* backend) return static_cast<Database*>(backend->m_frontend); } -PassRefPtr<DatabaseBackend> Database::backend() +PassRefPtrWillBeRawPtr<DatabaseBackend> Database::backend() { return this; } @@ -132,7 +106,7 @@ String Database::version() const void Database::closeImmediately() { - ASSERT(m_executionContext->isContextThread()); + ASSERT(executionContext()->isContextThread()); DatabaseThread* databaseThread = databaseContext()->databaseThread(); if (databaseThread && !databaseThread->terminationRequested() && opened()) { logErrorMessage("forcibly closing database"); @@ -156,8 +130,9 @@ void Database::readTransaction(PassOwnPtr<SQLTransactionCallback> callback, Pass runTransaction(callback, errorCallback, successCallback, true); } -static void callTransactionErrorCallback(ExecutionContext*, PassOwnPtr<SQLTransactionErrorCallback> callback, PassRefPtr<SQLError> error) +static void callTransactionErrorCallback(ExecutionContext*, PassOwnPtr<SQLTransactionErrorCallback> callback, PassOwnPtr<SQLErrorData> errorData) { + RefPtrWillBeRawPtr<SQLError> error = SQLError::create(*errorData); callback->handleEvent(error.get()); } @@ -167,45 +142,47 @@ void Database::runTransaction(PassOwnPtr<SQLTransactionCallback> callback, PassO // FIXME: Rather than passing errorCallback to SQLTransaction and then sometimes firing it ourselves, // this code should probably be pushed down into DatabaseBackend so that we only create the SQLTransaction // if we're actually going to run it. -#if !ASSERT_DISABLED +#if ASSERT_ENABLED SQLTransactionErrorCallback* originalErrorCallback = errorCallback.get(); #endif - RefPtr<SQLTransaction> transaction = SQLTransaction::create(this, callback, successCallback, errorCallback, readOnly); - RefPtr<SQLTransactionBackend> transactionBackend = backend()->runTransaction(transaction, readOnly, changeVersionData); + RefPtrWillBeRawPtr<SQLTransaction> transaction = SQLTransaction::create(this, callback, successCallback, errorCallback, readOnly); + RefPtrWillBeRawPtr<SQLTransactionBackend> transactionBackend = backend()->runTransaction(transaction, readOnly, changeVersionData); if (!transactionBackend) { OwnPtr<SQLTransactionErrorCallback> callback = transaction->releaseErrorCallback(); ASSERT(callback == originalErrorCallback); if (callback) { - RefPtr<SQLError> error = SQLError::create(SQLError::UNKNOWN_ERR, "database has been closed"); + OwnPtr<SQLErrorData> error = SQLErrorData::create(SQLError::UNKNOWN_ERR, "database has been closed"); executionContext()->postTask(createCallbackTask(&callTransactionErrorCallback, callback.release(), error.release())); } } } -class DeliverPendingCallbackTask : public ExecutionContextTask { +// This object is constructed in a database thread, and destructed in the +// context thread. +class DeliverPendingCallbackTask FINAL : public ExecutionContextTask { public: - static PassOwnPtr<DeliverPendingCallbackTask> create(PassRefPtr<SQLTransaction> transaction) + static PassOwnPtr<DeliverPendingCallbackTask> create(PassRefPtrWillBeRawPtr<SQLTransaction> transaction) { return adoptPtr(new DeliverPendingCallbackTask(transaction)); } - virtual void performTask(ExecutionContext*) + virtual void performTask(ExecutionContext*) OVERRIDE { m_transaction->performPendingCallback(); } private: - DeliverPendingCallbackTask(PassRefPtr<SQLTransaction> transaction) + DeliverPendingCallbackTask(PassRefPtrWillBeRawPtr<SQLTransaction> transaction) : m_transaction(transaction) { } - RefPtr<SQLTransaction> m_transaction; + RefPtrWillBeCrossThreadPersistent<SQLTransaction> m_transaction; }; void Database::scheduleTransactionCallback(SQLTransaction* transaction) { - m_executionContext->postTask(DeliverPendingCallbackTask::create(transaction)); + executionContext()->postTask(DeliverPendingCallbackTask::create(transaction)); } Vector<String> Database::performGetTableNames() @@ -242,7 +219,7 @@ Vector<String> Database::tableNames() // FIXME: Not using isolatedCopy on these strings looks ok since threads take strict turns // in dealing with them. However, if the code changes, this may not be true anymore. Vector<String> result; - DatabaseTaskSynchronizer synchronizer; + TaskSynchronizer synchronizer; if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer)) return result; @@ -255,7 +232,7 @@ Vector<String> Database::tableNames() SecurityOrigin* Database::securityOrigin() const { - if (m_executionContext->isContextThread()) + if (executionContext()->isContextThread()) return m_contextThreadSecurityOrigin.get(); if (databaseContext()->databaseThread()->isDatabaseThread()) return m_databaseThreadSecurityOrigin.get(); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/Database.h b/chromium/third_party/WebKit/Source/modules/webdatabase/Database.h index 454cdec6b2e..68b33f2b344 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/Database.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/Database.h @@ -48,12 +48,13 @@ class SQLTransactionCallback; class SQLTransactionErrorCallback; class VoidCallback; -class Database : public DatabaseBase, public DatabaseBackend, public ScriptWrappable { +class Database FINAL : public DatabaseBackend, public DatabaseBase, public ScriptWrappable { public: virtual ~Database(); + virtual void trace(Visitor*) OVERRIDE; // Direct support for the DOM API - virtual String version() const; + virtual String version() const OVERRIDE; void changeVersion(const String& oldVersion, const String& newVersion, PassOwnPtr<SQLTransactionCallback>, PassOwnPtr<SQLTransactionErrorCallback>, PassOwnPtr<VoidCallback> successCallback); void transaction(PassOwnPtr<SQLTransactionCallback>, PassOwnPtr<SQLTransactionErrorCallback>, PassOwnPtr<VoidCallback> successCallback); void readTransaction(PassOwnPtr<SQLTransactionCallback>, PassOwnPtr<SQLTransactionErrorCallback>, PassOwnPtr<VoidCallback> successCallback); @@ -64,17 +65,17 @@ public: Vector<String> tableNames(); - virtual SecurityOrigin* securityOrigin() const; + virtual SecurityOrigin* securityOrigin() const OVERRIDE; - virtual void closeImmediately(); + virtual void closeImmediately() OVERRIDE; void scheduleTransactionCallback(SQLTransaction*); private: - Database(PassRefPtr<DatabaseContext>, const String& name, + Database(DatabaseContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); - PassRefPtr<DatabaseBackend> backend(); - static PassRefPtr<Database> create(ExecutionContext*, PassRefPtr<DatabaseBackendBase>); + PassRefPtrWillBeRawPtr<DatabaseBackend> backend(); + static PassRefPtrWillBeRawPtr<Database> create(ExecutionContext*, PassRefPtrWillBeRawPtr<DatabaseBackendBase>); void runTransaction(PassOwnPtr<SQLTransactionCallback>, PassOwnPtr<SQLTransactionErrorCallback>, PassOwnPtr<VoidCallback> successCallback, bool readOnly, const ChangeVersionData* = 0); @@ -85,7 +86,7 @@ private: void reportCommitTransactionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); RefPtr<SecurityOrigin> m_databaseThreadSecurityOrigin; - RefPtr<DatabaseContext> m_databaseContext; + RefPtrWillBeMember<DatabaseContext> m_databaseContext; friend class DatabaseManager; friend class DatabaseServer; // FIXME: remove this when the backend has been split out. diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/Database.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/Database.idl index 5dcd6920dfd..e809806193a 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/Database.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/Database.idl @@ -27,6 +27,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface Database { readonly attribute DOMString version; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp index 4af63af9799..c4577491a7e 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp @@ -33,9 +33,9 @@ namespace WebCore { -PassRefPtr<DatabaseAuthorizer> DatabaseAuthorizer::create(const String& databaseInfoTableName) +PassRefPtrWillBeRawPtr<DatabaseAuthorizer> DatabaseAuthorizer::create(const String& databaseInfoTableName) { - return adoptRef(new DatabaseAuthorizer(databaseInfoTableName)); + return adoptRefWillBeNoop(new DatabaseAuthorizer(databaseInfoTableName)); } DatabaseAuthorizer::DatabaseAuthorizer(const String& databaseInfoTableName) @@ -395,11 +395,6 @@ bool DatabaseAuthorizer::allowWrite() return !(m_securityEnabled && (m_permissions & ReadOnlyMask || m_permissions & NoAccessMask)); } -void DatabaseAuthorizer::setReadOnly() -{ - m_permissions |= ReadOnlyMask; -} - void DatabaseAuthorizer::setPermissions(int permissions) { m_permissions = permissions; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h index 5202c95999e..44ffbd4424a 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h @@ -28,6 +28,7 @@ #ifndef DatabaseAuthorizer_h #define DatabaseAuthorizer_h +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/HashSet.h" #include "wtf/ThreadSafeRefCounted.h" @@ -37,10 +38,9 @@ namespace WebCore { extern const int SQLAuthAllow; -extern const int SQLAuthIgnore; extern const int SQLAuthDeny; -class DatabaseAuthorizer : public ThreadSafeRefCounted<DatabaseAuthorizer> { +class DatabaseAuthorizer : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<DatabaseAuthorizer> { public: enum Permissions { @@ -49,7 +49,8 @@ public: NoAccessMask = 1 << 2 }; - static PassRefPtr<DatabaseAuthorizer> create(const String& databaseInfoTableName); + static PassRefPtrWillBeRawPtr<DatabaseAuthorizer> create(const String& databaseInfoTableName); + void trace(Visitor*) { } int createTable(const String& tableName); int createTempTable(const String& tableName); @@ -93,7 +94,6 @@ public: void disable(); void enable(); - void setReadOnly(); void setPermissions(int permissions); void reset(); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackend.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackend.cpp index b85c826a1d3..7e18fe47e70 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackend.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackend.cpp @@ -40,16 +40,22 @@ namespace WebCore { -DatabaseBackend::DatabaseBackend(PassRefPtr<DatabaseContext> databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) +DatabaseBackend::DatabaseBackend(DatabaseContext* databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) : DatabaseBackendBase(databaseContext, name, expectedVersion, displayName, estimatedSize, DatabaseType::Async) , m_transactionInProgress(false) , m_isTransactionQueueEnabled(true) { } +void DatabaseBackend::trace(Visitor* visitor) +{ + visitor->trace(m_transactionQueue); + DatabaseBackendBase::trace(visitor); +} + bool DatabaseBackend::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) { - DatabaseTaskSynchronizer synchronizer; + TaskSynchronizer synchronizer; if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer)) return false; @@ -85,7 +91,7 @@ void DatabaseBackend::close() // Clean up transactions that have not been scheduled yet: // Transaction phase 1 cleanup. See comment on "What happens if a // transaction is interrupted?" at the top of SQLTransactionBackend.cpp. - RefPtr<SQLTransactionBackend> transaction; + RefPtrWillBeRawPtr<SQLTransactionBackend> transaction = nullptr; while (!m_transactionQueue.isEmpty()) { transaction = m_transactionQueue.takeFirst(); transaction->notifyDatabaseThreadIsShuttingDown(); @@ -99,18 +105,18 @@ void DatabaseBackend::close() databaseContext()->databaseThread()->recordDatabaseClosed(this); } -PassRefPtr<SQLTransactionBackend> DatabaseBackend::runTransaction(PassRefPtr<SQLTransaction> transaction, +PassRefPtrWillBeRawPtr<SQLTransactionBackend> DatabaseBackend::runTransaction(PassRefPtrWillBeRawPtr<SQLTransaction> transaction, bool readOnly, const ChangeVersionData* data) { MutexLocker locker(m_transactionInProgressMutex); if (!m_isTransactionQueueEnabled) - return 0; + return nullptr; - RefPtr<SQLTransactionWrapper> wrapper; + RefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper = nullptr; if (data) wrapper = ChangeVersionWrapper::create(data->oldVersion(), data->newVersion()); - RefPtr<SQLTransactionBackend> transactionBackend = SQLTransactionBackend::create(this, transaction, wrapper, readOnly); + RefPtrWillBeRawPtr<SQLTransactionBackend> transactionBackend = SQLTransactionBackend::create(this, transaction, wrapper.release(), readOnly); m_transactionQueue.append(transactionBackend); if (!m_transactionInProgress) scheduleTransaction(); @@ -128,7 +134,7 @@ void DatabaseBackend::inProgressTransactionCompleted() void DatabaseBackend::scheduleTransaction() { ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller. - RefPtr<SQLTransactionBackend> transaction; + RefPtrWillBeRawPtr<SQLTransactionBackend> transaction = nullptr; if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty()) transaction = m_transactionQueue.takeFirst(); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackend.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackend.h index 303975a61b1..b0fcdaf5399 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackend.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackend.h @@ -48,12 +48,13 @@ class SQLTransactionCoordinator; class DatabaseBackend : public DatabaseBackendBase { public: - DatabaseBackend(PassRefPtr<DatabaseContext>, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); + DatabaseBackend(DatabaseContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); + virtual void trace(Visitor*) OVERRIDE; - virtual bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); + virtual bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage) OVERRIDE FINAL; void close(); - PassRefPtr<SQLTransactionBackend> runTransaction(PassRefPtr<SQLTransaction>, bool readOnly, const ChangeVersionData*); + PassRefPtrWillBeRawPtr<SQLTransactionBackend> runTransaction(PassRefPtrWillBeRawPtr<SQLTransaction>, bool readOnly, const ChangeVersionData*); void scheduleTransactionStep(SQLTransactionBackend*); void inProgressTransactionCompleted(); @@ -66,11 +67,11 @@ private: class DatabaseTransactionTask; class DatabaseTableNamesTask; - virtual bool performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); + virtual bool performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage) OVERRIDE FINAL; void scheduleTransaction(); - Deque<RefPtr<SQLTransactionBackend> > m_transactionQueue; + Deque<RefPtrWillBeMember<SQLTransactionBackend> > m_transactionQueue; Mutex m_transactionInProgressMutex; bool m_transactionInProgress; bool m_isTransactionQueueEnabled; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendBase.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendBase.cpp index c8b0d89993f..c5e5f9b7e7d 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendBase.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendBase.cpp @@ -31,6 +31,7 @@ #include "modules/webdatabase/DatabaseBackendBase.h" #include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" #include "platform/Logging.h" #include "modules/webdatabase/DatabaseAuthorizer.h" #include "modules/webdatabase/DatabaseBase.h" @@ -199,7 +200,7 @@ const char* DatabaseBackendBase::databaseInfoTableName() return infoTableName; } -DatabaseBackendBase::DatabaseBackendBase(PassRefPtr<DatabaseContext> databaseContext, const String& name, +DatabaseBackendBase::DatabaseBackendBase(DatabaseContext* databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, DatabaseType databaseType) : m_databaseContext(databaseContext) , m_name(name.isolatedCopy()) @@ -219,7 +220,7 @@ DatabaseBackendBase::DatabaseBackendBase(PassRefPtr<DatabaseContext> databaseCon m_name = ""; { - MutexLocker locker(guidMutex()); + SafePointAwareMutexLocker locker(guidMutex()); m_guid = guidForOriginAndName(securityOrigin()->toString(), name); HashSet<DatabaseBackendBase*>* hashSet = guidToDatabaseMap().get(m_guid); if (!hashSet) { @@ -247,6 +248,13 @@ DatabaseBackendBase::~DatabaseBackendBase() ASSERT(!m_opened); } +void DatabaseBackendBase::trace(Visitor* visitor) +{ + visitor->trace(m_databaseContext); + visitor->trace(m_sqliteDatabase); + visitor->trace(m_databaseAuthorizer); +} + void DatabaseBackendBase::closeDatabase() { if (!m_opened) @@ -254,10 +262,11 @@ void DatabaseBackendBase::closeDatabase() m_sqliteDatabase.close(); m_opened = false; + databaseContext()->didCloseDatabase(*this); // See comment at the top this file regarding calling removeOpenDatabase(). DatabaseTracker::tracker().removeOpenDatabase(this); { - MutexLocker locker(guidMutex()); + SafePointAwareMutexLocker locker(guidMutex()); HashSet<DatabaseBackendBase*>* hashSet = guidToDatabaseMap().get(m_guid); ASSERT(hashSet); @@ -320,7 +329,7 @@ bool DatabaseBackendBase::performOpenAndVerify(bool shouldSetVersionInNewDatabas String currentVersion; { - MutexLocker locker(guidMutex()); + SafePointAwareMutexLocker locker(guidMutex()); GuidVersionMap::iterator entry = guidToVersionMap().find(m_guid); if (entry != guidToVersionMap().end()) { @@ -406,8 +415,9 @@ bool DatabaseBackendBase::performOpenAndVerify(bool shouldSetVersionInNewDatabas } ASSERT(m_databaseAuthorizer); - m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer); + m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer.get()); + databaseContext()->didOpenDatabase(*this); // See comment at the top this file regarding calling addOpenDatabase(). DatabaseTracker::tracker().addOpenDatabase(this); m_opened = true; @@ -451,11 +461,6 @@ String DatabaseBackendBase::fileName() const return m_filename.isolatedCopy(); } -DatabaseDetails DatabaseBackendBase::details() const -{ - return DatabaseDetails(stringIdentifier(), displayName(), estimatedSize(), 0); -} - bool DatabaseBackendBase::getVersionFromDatabase(String& version, bool shouldCacheVersion) { String query(String("SELECT value FROM ") + infoTableName + " WHERE key = '" + versionKey + "';"); @@ -501,14 +506,14 @@ void DatabaseBackendBase::setExpectedVersion(const String& version) String DatabaseBackendBase::getCachedVersion() const { - MutexLocker locker(guidMutex()); + SafePointAwareMutexLocker locker(guidMutex()); return guidToVersionMap().get(m_guid).isolatedCopy(); } void DatabaseBackendBase::setCachedVersion(const String& actualVersion) { // Update the in memory database version map. - MutexLocker locker(guidMutex()); + SafePointAwareMutexLocker locker(guidMutex()); updateGuidVersionMap(m_guid, actualVersion); } @@ -532,12 +537,6 @@ void DatabaseBackendBase::enableAuthorizer() m_databaseAuthorizer->enable(); } -void DatabaseBackendBase::setAuthorizerReadOnly() -{ - ASSERT(m_databaseAuthorizer); - m_databaseAuthorizer->setReadOnly(); -} - void DatabaseBackendBase::setAuthorizerPermissions(int permissions) { ASSERT(m_databaseAuthorizer); @@ -587,7 +586,7 @@ void DatabaseBackendBase::incrementalVacuumIfNeeded() int result = m_sqliteDatabase.runIncrementalVacuumCommand(); reportVacuumDatabaseResult(result); if (result != SQLResultOk) - m_frontend->logErrorMessage(formatErrorMessage("error vacuuming database", result, m_sqliteDatabase.lastErrorMsg())); + logErrorMessage(formatErrorMessage("error vacuuming database", result, m_sqliteDatabase.lastErrorMsg())); } } @@ -663,5 +662,14 @@ void DatabaseBackendBase::reportVacuumDatabaseResult(int sqliteErrorCode) } } +void DatabaseBackendBase::logErrorMessage(const String& message) +{ + executionContext()->addConsoleMessage(StorageMessageSource, ErrorMessageLevel, message); +} + +ExecutionContext* DatabaseBackendBase::executionContext() const +{ + return databaseContext()->executionContext(); +} } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendBase.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendBase.h index b8743100818..db1ec138d18 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendBase.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendBase.h @@ -32,8 +32,8 @@ #include "modules/webdatabase/sqlite/SQLiteDatabase.h" #include "modules/webdatabase/DatabaseBasicTypes.h" -#include "modules/webdatabase/DatabaseDetails.h" #include "modules/webdatabase/DatabaseError.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/RefPtr.h" #include "wtf/ThreadSafeRefCounted.h" @@ -48,11 +48,13 @@ namespace WebCore { class DatabaseAuthorizer; class DatabaseContext; class DatabaseBase; +class ExecutionContext; class SecurityOrigin; -class DatabaseBackendBase : public ThreadSafeRefCounted<DatabaseBackendBase> { +class DatabaseBackendBase : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<DatabaseBackendBase> { public: virtual ~DatabaseBackendBase(); + virtual void trace(Visitor*); virtual String version() const; @@ -65,7 +67,6 @@ public: virtual String displayName() const; virtual unsigned long estimatedSize() const; virtual String fileName() const; - virtual DatabaseDetails details() const; SQLiteDatabase& sqliteDatabase() { return m_sqliteDatabase; } unsigned long long maximumSize() const; @@ -75,7 +76,6 @@ public: void disableAuthorizer(); void enableAuthorizer(); - void setAuthorizerReadOnly(); void setAuthorizerPermissions(int permissions); bool lastActionChangedDatabase(); bool lastActionWasInsert(); @@ -86,6 +86,7 @@ public: virtual void closeImmediately() = 0; DatabaseContext* databaseContext() const { return m_databaseContext.get(); } + ExecutionContext* executionContext() const; void setFrontend(DatabaseBase* frontend) { m_frontend = frontend; } protected: @@ -95,7 +96,7 @@ protected: friend class SQLTransactionBackend; friend class SQLTransactionBackendSync; - DatabaseBackendBase(PassRefPtr<DatabaseContext>, const String& name, const String& expectedVersion, + DatabaseBackendBase(DatabaseContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, DatabaseType); void closeDatabase(); @@ -117,11 +118,11 @@ protected: void reportCommitTransactionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); void reportExecuteStatementResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); void reportVacuumDatabaseResult(int sqliteErrorCode); - + void logErrorMessage(const String&); static const char* databaseInfoTableName(); RefPtr<SecurityOrigin> m_contextThreadSecurityOrigin; - RefPtr<DatabaseContext> m_databaseContext; // Associated with m_executionContext. + RefPtrWillBeMember<DatabaseContext> m_databaseContext; // Associated with m_executionContext. String m_name; String m_expectedVersion; @@ -143,7 +144,7 @@ private: SQLiteDatabase m_sqliteDatabase; - RefPtr<DatabaseAuthorizer> m_databaseAuthorizer; + RefPtrWillBeMember<DatabaseAuthorizer> m_databaseAuthorizer; friend class DatabaseServer; }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendSync.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendSync.cpp index eba34c2593e..0e9c8ee211e 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendSync.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendSync.cpp @@ -31,23 +31,31 @@ namespace WebCore { -DatabaseBackendSync::DatabaseBackendSync(PassRefPtr<DatabaseContext> databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) +DatabaseBackendSync::DatabaseBackendSync(DatabaseContext* databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) : DatabaseBackendBase(databaseContext, name, expectedVersion, displayName, estimatedSize, DatabaseType::Sync) { } DatabaseBackendSync::~DatabaseBackendSync() { +#if !ENABLE(OILPAN) // SQLite is "multi-thread safe", but each database handle can only be used // on a single thread at a time. // // For DatabaseBackendSync, we open the SQLite database on the script context // thread. And hence we should also close it on that same thread. This means // that the SQLite database need to be closed here in the destructor. - - ASSERT(m_databaseContext->isContextThread()); - if (opened()) + if (opened()) { + ASSERT(m_databaseContext->isContextThread()); closeDatabase(); + } +#endif + ASSERT(!opened()); +} + +void DatabaseBackendSync::trace(Visitor* visitor) +{ + DatabaseBackendBase::trace(visitor); } bool DatabaseBackendSync::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendSync.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendSync.h index e32635e8757..68502fcc0b6 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendSync.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBackendSync.h @@ -42,11 +42,12 @@ class DatabaseServer; class DatabaseBackendSync : public DatabaseBackendBase { public: virtual ~DatabaseBackendSync(); + virtual void trace(Visitor*) OVERRIDE; - virtual bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); + virtual bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage) OVERRIDE FINAL; protected: - DatabaseBackendSync(PassRefPtr<DatabaseContext>, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); + DatabaseBackendSync(DatabaseContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); friend class DatabaseServer; }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBase.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBase.cpp index 8798b27d558..3d60132a81d 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBase.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBase.cpp @@ -32,19 +32,8 @@ namespace WebCore { DatabaseBase::DatabaseBase(ExecutionContext* executionContext) - : m_executionContext(executionContext) { - ASSERT(m_executionContext->isContextThread()); -} - -ExecutionContext* DatabaseBase::executionContext() const -{ - return m_executionContext.get(); -} - -void DatabaseBase::logErrorMessage(const String& message) -{ - m_executionContext->addConsoleMessage(StorageMessageSource, ErrorMessageLevel, message); + ASSERT_UNUSED(executionContext, executionContext->isContextThread()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBase.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBase.h index d2d1e3e4374..fc6aed64210 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBase.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseBase.h @@ -26,21 +26,13 @@ #ifndef DatabaseBase_h #define DatabaseBase_h -#include "wtf/text/WTFString.h" - namespace WebCore { class ExecutionContext; class DatabaseBase { -public: - ExecutionContext* executionContext() const; - void logErrorMessage(const String& message); - protected: DatabaseBase(ExecutionContext*); - - RefPtr<ExecutionContext> m_executionContext; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp index ef4c9e88d18..be3434855f6 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp @@ -32,17 +32,24 @@ #include "DatabaseClient.h" #include "core/dom/Document.h" +#include "core/inspector/InspectorController.h" #include "core/workers/WorkerGlobalScope.h" +#include "modules/webdatabase/Database.h" +#include "modules/webdatabase/InspectorDatabaseAgent.h" namespace WebCore { +DatabaseClient::DatabaseClient() + : m_inspectorAgent(0) +{ } + DatabaseClient* DatabaseClient::from(ExecutionContext* context) { if (context->isDocument()) { - return static_cast<DatabaseClient*>(Supplement<Page>::from(toDocument(context)->page(), supplementName())); + return static_cast<DatabaseClient*>(WillBeHeapSupplement<Page>::from(toDocument(context)->page(), supplementName())); } ASSERT(context->isWorkerGlobalScope()); - return static_cast<DatabaseClient*>(Supplement<WorkerClients>::from(toWorkerGlobalScope(context)->clients(), supplementName())); + return static_cast<DatabaseClient*>(WillBeHeapSupplement<WorkerClients>::from(toWorkerGlobalScope(context)->clients(), supplementName())); } const char* DatabaseClient::supplementName() @@ -50,12 +57,28 @@ const char* DatabaseClient::supplementName() return "DatabaseClient"; } -void provideDatabaseClientTo(Page* page, PassOwnPtr<DatabaseClient> client) +void DatabaseClient::didOpenDatabase(PassRefPtrWillBeRawPtr<Database> database, const String& domain, const String& name, const String& version) +{ + if (m_inspectorAgent) + m_inspectorAgent->didOpenDatabase(database, domain, name, version); +} + +void DatabaseClient::createInspectorAgentFor(Page* page) +{ + ASSERT(!m_inspectorAgent); + OwnPtr<InspectorDatabaseAgent> inspectorAgent = InspectorDatabaseAgent::create(); + m_inspectorAgent = inspectorAgent.get(); + page->inspectorController().registerModuleAgent(inspectorAgent.release()); +} + +void provideDatabaseClientTo(Page& page, PassOwnPtrWillBeRawPtr<DatabaseClient> client) { - page->provideSupplement(DatabaseClient::supplementName(), client); + DatabaseClient* clientPtr = client.get(); + page.provideSupplement(DatabaseClient::supplementName(), client); + clientPtr->createInspectorAgentFor(&page); } -void provideDatabaseClientToWorker(WorkerClients* workerClients, PassOwnPtr<DatabaseClient> client) +void provideDatabaseClientToWorker(WorkerClients* workerClients, PassOwnPtrWillBeRawPtr<DatabaseClient> client) { workerClients->provideSupplement(DatabaseClient::supplementName(), client); } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.h index 4f080b3aab5..5eb2bae7157 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.h @@ -33,27 +33,38 @@ #include "core/page/Page.h" #include "core/workers/WorkerClients.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" namespace WebCore { +class Database; class ExecutionContext; +class InspectorDatabaseAgent; class WorkerClients; -class DatabaseClient : public Supplement<Page>, public Supplement<WorkerClients> { +class GC_PLUGIN_IGNORE("http://crbug.com/367712") DatabaseClient; +class DatabaseClient : public WillBeHeapSupplement<Page>, public WillBeHeapSupplement<WorkerClients> { WTF_MAKE_NONCOPYABLE(DatabaseClient); public: - DatabaseClient() { } + DatabaseClient(); virtual ~DatabaseClient() { } virtual bool allowDatabase(ExecutionContext*, const String& name, const String& displayName, unsigned long estimatedSize) = 0; + void didOpenDatabase(PassRefPtrWillBeRawPtr<Database>, const String& domain, const String& name, const String& version); + static DatabaseClient* from(ExecutionContext*); static const char* supplementName(); + + void createInspectorAgentFor(Page*); + +private: + InspectorDatabaseAgent* m_inspectorAgent; }; -void provideDatabaseClientTo(Page*, PassOwnPtr<DatabaseClient>); -void provideDatabaseClientToWorker(WorkerClients*, PassOwnPtr<DatabaseClient>); +void provideDatabaseClientTo(Page&, PassOwnPtrWillBeRawPtr<DatabaseClient>); +void provideDatabaseClientToWorker(WorkerClients*, PassOwnPtrWillBeRawPtr<DatabaseClient>); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseContext.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseContext.cpp index c5cbaf6c965..a9828bc84b9 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseContext.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseContext.cpp @@ -87,17 +87,16 @@ namespace WebCore { // The RefPtrs in the Databases and ExecutionContext will ensure that the // DatabaseContext will outlive both regardless of which of the 2 destructs first. -PassRefPtr<DatabaseContext> DatabaseContext::create(ExecutionContext* context) +PassRefPtrWillBeRawPtr<DatabaseContext> DatabaseContext::create(ExecutionContext* context) { - RefPtr<DatabaseContext> self = adoptRef(new DatabaseContext(context)); - self->ref(); // Is deref()-ed on contextDestroyed(). + RefPtrWillBeRawPtr<DatabaseContext> self = adoptRefWillBeNoop(new DatabaseContext(context)); + DatabaseManager::manager().registerDatabaseContext(self.get()); return self.release(); } DatabaseContext::DatabaseContext(ExecutionContext* context) : ActiveDOMObject(context) , m_hasOpenDatabases(false) - , m_isRegistered(true) // will register on construction below. , m_hasRequestedTermination(false) { // ActiveDOMObject expects this to be called to set internal flags. @@ -106,20 +105,23 @@ DatabaseContext::DatabaseContext(ExecutionContext* context) // For debug accounting only. We must do this before we register the // instance. The assertions assume this. DatabaseManager::manager().didConstructDatabaseContext(); - - DatabaseManager::manager().registerDatabaseContext(this); + if (context->isWorkerGlobalScope()) + toWorkerGlobalScope(context)->registerTerminationObserver(this); } DatabaseContext::~DatabaseContext() { - stopDatabases(); - ASSERT(!m_databaseThread || m_databaseThread->terminationRequested()); - // For debug accounting only. We must call this last. The assertions assume // this. DatabaseManager::manager().didDestructDatabaseContext(); } +void DatabaseContext::trace(Visitor* visitor) +{ + visitor->trace(m_databaseThread); + visitor->trace(m_openSyncDatabases); +} + // This is called if the associated ExecutionContext is destructing while // we're still associated with it. That's our cue to disassociate and shutdown. // To do this, we stop the database and let everything shutdown naturally @@ -127,12 +129,20 @@ DatabaseContext::~DatabaseContext() // It is not safe to just delete the context here. void DatabaseContext::contextDestroyed() { + RefPtrWillBeRawPtr<DatabaseContext> protector(this); stopDatabases(); + if (executionContext()->isWorkerGlobalScope()) + toWorkerGlobalScope(executionContext())->unregisterTerminationObserver(this); + DatabaseManager::manager().unregisterDatabaseContext(this); ActiveDOMObject::contextDestroyed(); - deref(); // paired with the ref() call on create(). } -// stop() is from stopActiveDOMObjects() which indicates that the owner Frame +void DatabaseContext::wasRequestedToTerminate() +{ + DatabaseManager::manager().interruptAllDatabasesForContext(this); +} + +// stop() is from stopActiveDOMObjects() which indicates that the owner LocalFrame // or WorkerThread is shutting down. Initiate the orderly shutdown by stopping // the associated databases. void DatabaseContext::stop() @@ -140,10 +150,9 @@ void DatabaseContext::stop() stopDatabases(); } -PassRefPtr<DatabaseContext> DatabaseContext::backend() +DatabaseContext* DatabaseContext::backend() { - DatabaseContext* backend = static_cast<DatabaseContext*>(this); - return backend; + return this; } DatabaseThread* DatabaseContext::databaseThread() @@ -164,12 +173,59 @@ DatabaseThread* DatabaseContext::databaseThread() return m_databaseThread.get(); } -bool DatabaseContext::stopDatabases(DatabaseTaskSynchronizer* cleanupSync) +void DatabaseContext::didOpenDatabase(DatabaseBackendBase& database) { - if (m_isRegistered) { - DatabaseManager::manager().unregisterDatabaseContext(this); - m_isRegistered = false; - } + if (!database.isSyncDatabase()) + return; + ASSERT(isContextThread()); +#if ENABLE(OILPAN) + m_openSyncDatabases.add(&database, adoptPtr(new DatabaseCloser(database))); +#else + m_openSyncDatabases.add(&database); +#endif +} + +void DatabaseContext::didCloseDatabase(DatabaseBackendBase& database) +{ +#if !ENABLE(OILPAN) + if (!database.isSyncDatabase()) + return; + ASSERT(isContextThread()); + m_openSyncDatabases.remove(&database); +#endif +} + +#if ENABLE(OILPAN) +DatabaseContext::DatabaseCloser::~DatabaseCloser() +{ + m_database.closeImmediately(); +} +#endif + +void DatabaseContext::stopSyncDatabases() +{ + // SQLite is "multi-thread safe", but each database handle can only be used + // on a single thread at a time. + // + // For DatabaseBackendSync, we open the SQLite database on the script + // context thread. And hence we should also close it on that same + // thread. This means that the SQLite database need to be closed here in the + // destructor. + ASSERT(isContextThread()); +#if ENABLE(OILPAN) + m_openSyncDatabases.clear(); +#else + Vector<DatabaseBackendBase*> syncDatabases; + copyToVector(m_openSyncDatabases, syncDatabases); + m_openSyncDatabases.clear(); + for (size_t i = 0; i < syncDatabases.size(); ++i) + syncDatabases[i]->closeImmediately(); +#endif +} + +void DatabaseContext::stopDatabases() +{ + stopSyncDatabases(); // Though we initiate termination of the DatabaseThread here in // stopDatabases(), we can't clear the m_databaseThread ref till we get to @@ -182,11 +238,11 @@ bool DatabaseContext::stopDatabases(DatabaseTaskSynchronizer* cleanupSync) // DatabaseThread. if (m_databaseThread && !m_hasRequestedTermination) { - m_databaseThread->requestTermination(cleanupSync); + TaskSynchronizer sync; + m_databaseThread->requestTermination(&sync); m_hasRequestedTermination = true; - return true; + sync.waitForTaskCompletion(); } - return false; } bool DatabaseContext::allowDatabaseAccess() const diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseContext.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseContext.h index e1a66cb921c..62e7a595df2 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseContext.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseContext.h @@ -29,38 +29,45 @@ #define DatabaseContext_h #include "core/dom/ActiveDOMObject.h" +#include "core/workers/WorkerGlobalScope.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/ThreadSafeRefCounted.h" namespace WebCore { class Database; +class DatabaseBackendBase; class DatabaseContext; -class DatabaseTaskSynchronizer; +class TaskSynchronizer; class DatabaseThread; class ExecutionContext; class SecurityOrigin; -class DatabaseContext : public ThreadSafeRefCounted<DatabaseContext>, public ActiveDOMObject { +class DatabaseContext FINAL + : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<DatabaseContext> + , public ActiveDOMObject + , private WorkerGlobalScope::TerminationObserver { public: friend class DatabaseManager; - static PassRefPtr<DatabaseContext> create(ExecutionContext*); + static PassRefPtrWillBeRawPtr<DatabaseContext> create(ExecutionContext*); virtual ~DatabaseContext(); + void trace(Visitor*); // For life-cycle management (inherited from ActiveDOMObject): - virtual void contextDestroyed(); - virtual void stop(); + virtual void contextDestroyed() OVERRIDE; + virtual void stop() OVERRIDE; - PassRefPtr<DatabaseContext> backend(); + DatabaseContext* backend(); DatabaseThread* databaseThread(); void setHasOpenDatabases() { m_hasOpenDatabases = true; } - bool hasOpenDatabases() { return m_hasOpenDatabases; } - - // When the database cleanup is done, cleanupSync will be signalled. - bool stopDatabases(DatabaseTaskSynchronizer*); + void didOpenDatabase(DatabaseBackendBase&); + void didCloseDatabase(DatabaseBackendBase&); + // Blocks the caller thread until cleanup tasks are completed. + void stopDatabases(); bool allowDatabaseAccess() const; @@ -70,11 +77,26 @@ public: private: explicit DatabaseContext(ExecutionContext*); - void stopDatabases() { stopDatabases(0); } - - RefPtr<DatabaseThread> m_databaseThread; + virtual void wasRequestedToTerminate() OVERRIDE; + void stopSyncDatabases(); + + RefPtrWillBeMember<DatabaseThread> m_databaseThread; +#if ENABLE(OILPAN) + class DatabaseCloser { + public: + explicit DatabaseCloser(DatabaseBackendBase& database) : m_database(database) { } + ~DatabaseCloser(); + + private: + DatabaseBackendBase& m_database; + }; + HeapHashMap<WeakMember<DatabaseBackendBase>, OwnPtr<DatabaseCloser> > m_openSyncDatabases; +#else + // The contents of m_openSyncDatabases are raw pointers. It's safe because + // DatabaseBackendSync is always closed before destruction. + HashSet<DatabaseBackendBase*> m_openSyncDatabases; +#endif bool m_hasOpenDatabases; // This never changes back to false, even after the database thread is closed. - bool m_isRegistered; bool m_hasRequestedTermination; }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseManager.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseManager.cpp index c8ed236b30c..fbadafa8f07 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseManager.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseManager.cpp @@ -31,7 +31,6 @@ #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContextTask.h" -#include "core/inspector/InspectorDatabaseInstrumentation.h" #include "platform/Logging.h" #include "modules/webdatabase/AbstractDatabaseServer.h" #include "modules/webdatabase/Database.h" @@ -39,8 +38,8 @@ #include "modules/webdatabase/DatabaseBackendBase.h" #include "modules/webdatabase/DatabaseBackendSync.h" #include "modules/webdatabase/DatabaseCallback.h" +#include "modules/webdatabase/DatabaseClient.h" #include "modules/webdatabase/DatabaseContext.h" -#include "modules/webdatabase/DatabaseDetails.h" #include "modules/webdatabase/DatabaseServer.h" #include "modules/webdatabase/DatabaseSync.h" #include "modules/webdatabase/DatabaseTask.h" @@ -50,17 +49,12 @@ namespace WebCore { DatabaseManager& DatabaseManager::manager() { - static DatabaseManager* dbManager = 0; - // FIXME: The following is vulnerable to a race between threads. Need to - // implement a thread safe on-first-use static initializer. - if (!dbManager) - dbManager = new DatabaseManager(); - + AtomicallyInitializedStatic(DatabaseManager*, dbManager = new DatabaseManager); return *dbManager; } DatabaseManager::DatabaseManager() -#if !ASSERT_DISABLED +#if ASSERT_ENABLED : m_databaseContextRegisteredCount(0) , m_databaseContextInstanceCount(0) #endif @@ -69,66 +63,68 @@ DatabaseManager::DatabaseManager() ASSERT(m_server); // We should always have a server to work with. } -class DatabaseCreationCallbackTask : public ExecutionContextTask { +DatabaseManager::~DatabaseManager() +{ +} + +class DatabaseCreationCallbackTask FINAL : public ExecutionContextTask { public: - static PassOwnPtr<DatabaseCreationCallbackTask> create(PassRefPtr<Database> database, PassOwnPtr<DatabaseCallback> creationCallback) + static PassOwnPtr<DatabaseCreationCallbackTask> create(PassRefPtrWillBeRawPtr<Database> database, PassOwnPtr<DatabaseCallback> creationCallback) { return adoptPtr(new DatabaseCreationCallbackTask(database, creationCallback)); } - virtual void performTask(ExecutionContext*) + virtual void performTask(ExecutionContext*) OVERRIDE { m_creationCallback->handleEvent(m_database.get()); } private: - DatabaseCreationCallbackTask(PassRefPtr<Database> database, PassOwnPtr<DatabaseCallback> callback) + DatabaseCreationCallbackTask(PassRefPtrWillBeRawPtr<Database> database, PassOwnPtr<DatabaseCallback> callback) : m_database(database) , m_creationCallback(callback) { } - RefPtr<Database> m_database; + RefPtrWillBePersistent<Database> m_database; OwnPtr<DatabaseCallback> m_creationCallback; }; -PassRefPtr<DatabaseContext> DatabaseManager::existingDatabaseContextFor(ExecutionContext* context) +DatabaseContext* DatabaseManager::existingDatabaseContextFor(ExecutionContext* context) { MutexLocker locker(m_contextMapLock); ASSERT(m_databaseContextRegisteredCount >= 0); ASSERT(m_databaseContextInstanceCount >= 0); ASSERT(m_databaseContextRegisteredCount <= m_databaseContextInstanceCount); - - RefPtr<DatabaseContext> databaseContext = adoptRef(m_contextMap.get(context)); - if (databaseContext) { - // If we're instantiating a new DatabaseContext, the new instance would - // carry a new refCount of 1. The client expects this and will simply - // adoptRef the databaseContext without ref'ing it. - // However, instead of instantiating a new instance, we're reusing - // an existing one that corresponds to the specified ExecutionContext. - // Hence, that new refCount need to be attributed to the reused instance - // to ensure that the refCount is accurate when the client adopts the ref. - // We do this by ref'ing the reused databaseContext before returning it. - databaseContext->ref(); - } - return databaseContext.release(); +#if ENABLE(OILPAN) + const Persistent<DatabaseContext>* databaseContext = m_contextMap.get(context); + return databaseContext ? databaseContext->get() : 0; +#else + return m_contextMap.get(context); +#endif } -PassRefPtr<DatabaseContext> DatabaseManager::databaseContextFor(ExecutionContext* context) +DatabaseContext* DatabaseManager::databaseContextFor(ExecutionContext* context) { - RefPtr<DatabaseContext> databaseContext = existingDatabaseContextFor(context); - if (!databaseContext) - databaseContext = DatabaseContext::create(context); - return databaseContext.release(); + if (DatabaseContext* databaseContext = existingDatabaseContextFor(context)) + return databaseContext; + // We don't need to hold a reference returned by DatabaseContext::create + // because DatabaseContext::create calls registerDatabaseContext, and the + // DatabaseManager holds a reference. + return DatabaseContext::create(context).get(); } void DatabaseManager::registerDatabaseContext(DatabaseContext* databaseContext) { MutexLocker locker(m_contextMapLock); ExecutionContext* context = databaseContext->executionContext(); +#if ENABLE(OILPAN) + m_contextMap.set(context, adoptPtr(new Persistent<DatabaseContext>(databaseContext))); +#else m_contextMap.set(context, databaseContext); -#if !ASSERT_DISABLED +#endif +#if ASSERT_ENABLED m_databaseContextRegisteredCount++; #endif } @@ -138,13 +134,13 @@ void DatabaseManager::unregisterDatabaseContext(DatabaseContext* databaseContext MutexLocker locker(m_contextMapLock); ExecutionContext* context = databaseContext->executionContext(); ASSERT(m_contextMap.get(context)); -#if !ASSERT_DISABLED +#if ASSERT_ENABLED m_databaseContextRegisteredCount--; #endif m_contextMap.remove(context); } -#if !ASSERT_DISABLED +#if ASSERT_ENABLED void DatabaseManager::didConstructDatabaseContext() { MutexLocker lock(m_contextMapLock); @@ -181,16 +177,14 @@ static void logOpenDatabaseError(ExecutionContext* context, const String& name) context->securityOrigin()->toString().ascii().data()); } -PassRefPtr<DatabaseBackendBase> DatabaseManager::openDatabaseBackend(ExecutionContext* context, +PassRefPtrWillBeRawPtr<DatabaseBackendBase> DatabaseManager::openDatabaseBackend(ExecutionContext* context, DatabaseType type, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) { ASSERT(error == DatabaseError::None); - RefPtr<DatabaseContext> databaseContext = databaseContextFor(context); - RefPtr<DatabaseContext> backendContext = databaseContext->backend(); - - RefPtr<DatabaseBackendBase> backend = m_server->openDatabase(backendContext, type, name, expectedVersion, + RefPtrWillBeRawPtr<DatabaseBackendBase> backend = m_server->openDatabase( + databaseContextFor(context)->backend(), type, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage); if (!backend) { @@ -199,11 +193,11 @@ PassRefPtr<DatabaseBackendBase> DatabaseManager::openDatabaseBackend(ExecutionCo switch (error) { case DatabaseError::GenericSecurityError: logOpenDatabaseError(context, name); - return 0; + return nullptr; case DatabaseError::InvalidDatabaseState: logErrorMessage(context, errorMessage); - return 0; + return nullptr; default: ASSERT_NOT_REACHED(); @@ -213,7 +207,7 @@ PassRefPtr<DatabaseBackendBase> DatabaseManager::openDatabaseBackend(ExecutionCo return backend.release(); } -PassRefPtr<Database> DatabaseManager::openDatabase(ExecutionContext* context, +PassRefPtrWillBeRawPtr<Database> DatabaseManager::openDatabase(ExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, DatabaseError& error, String& errorMessage) @@ -221,27 +215,26 @@ PassRefPtr<Database> DatabaseManager::openDatabase(ExecutionContext* context, ASSERT(error == DatabaseError::None); bool setVersionInNewDatabase = !creationCallback; - RefPtr<DatabaseBackendBase> backend = openDatabaseBackend(context, DatabaseType::Async, name, + RefPtrWillBeRawPtr<DatabaseBackendBase> backend = openDatabaseBackend(context, DatabaseType::Async, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage); if (!backend) - return 0; + return nullptr; - RefPtr<Database> database = Database::create(context, backend); + RefPtrWillBeRawPtr<Database> database = Database::create(context, backend); - RefPtr<DatabaseContext> databaseContext = databaseContextFor(context); - databaseContext->setHasOpenDatabases(); - InspectorInstrumentation::didOpenDatabase(context, database, context->securityOrigin()->host(), name, expectedVersion); + databaseContextFor(context)->setHasOpenDatabases(); + DatabaseClient::from(context)->didOpenDatabase(database, context->securityOrigin()->host(), name, expectedVersion); if (backend->isNew() && creationCallback.get()) { WTF_LOG(StorageAPI, "Scheduling DatabaseCreationCallbackTask for database %p\n", database.get()); - database->m_executionContext->postTask(DatabaseCreationCallbackTask::create(database, creationCallback)); + database->executionContext()->postTask(DatabaseCreationCallbackTask::create(database, creationCallback)); } ASSERT(database); return database.release(); } -PassRefPtr<DatabaseSync> DatabaseManager::openDatabaseSync(ExecutionContext* context, +PassRefPtrWillBeRawPtr<DatabaseSync> DatabaseManager::openDatabaseSync(ExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, DatabaseError& error, String& errorMessage) @@ -250,12 +243,12 @@ PassRefPtr<DatabaseSync> DatabaseManager::openDatabaseSync(ExecutionContext* con ASSERT(error == DatabaseError::None); bool setVersionInNewDatabase = !creationCallback; - RefPtr<DatabaseBackendBase> backend = openDatabaseBackend(context, DatabaseType::Sync, name, + RefPtrWillBeRawPtr<DatabaseBackendBase> backend = openDatabaseBackend(context, DatabaseType::Sync, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage); if (!backend) - return 0; + return nullptr; - RefPtr<DatabaseSync> database = DatabaseSync::create(context, backend); + RefPtrWillBeRawPtr<DatabaseSync> database = DatabaseSync::create(context, backend); if (backend->isNew() && creationCallback.get()) { WTF_LOG(StorageAPI, "Invoking the creation callback for database %p\n", database.get()); @@ -266,22 +259,6 @@ PassRefPtr<DatabaseSync> DatabaseManager::openDatabaseSync(ExecutionContext* con return database.release(); } -bool DatabaseManager::hasOpenDatabases(ExecutionContext* context) -{ - RefPtr<DatabaseContext> databaseContext = existingDatabaseContextFor(context); - if (!databaseContext) - return false; - return databaseContext->hasOpenDatabases(); -} - -void DatabaseManager::stopDatabases(ExecutionContext* context, DatabaseTaskSynchronizer* synchronizer) -{ - RefPtr<DatabaseContext> databaseContext = existingDatabaseContextFor(context); - if (!databaseContext || !databaseContext->stopDatabases(synchronizer)) - if (synchronizer) - synchronizer->taskCompleted(); -} - String DatabaseManager::fullPathForDatabase(SecurityOrigin* origin, const String& name, bool createIfDoesNotExist) { return m_server->fullPathForDatabase(origin, name, createIfDoesNotExist); @@ -292,11 +269,9 @@ void DatabaseManager::closeDatabasesImmediately(const String& originIdentifier, m_server->closeDatabasesImmediately(originIdentifier, name); } -void DatabaseManager::interruptAllDatabasesForContext(ExecutionContext* context) +void DatabaseManager::interruptAllDatabasesForContext(DatabaseContext* databaseContext) { - RefPtr<DatabaseContext> databaseContext = existingDatabaseContextFor(context); - if (databaseContext) - m_server->interruptAllDatabasesForContext(databaseContext->backend().get()); + m_server->interruptAllDatabasesForContext(databaseContext->backend()); } void DatabaseManager::logErrorMessage(ExecutionContext* context, const String& message) diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseManager.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseManager.h index 4210534fb78..6902a44d504 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseManager.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseManager.h @@ -28,6 +28,7 @@ #include "modules/webdatabase/DatabaseBasicTypes.h" #include "modules/webdatabase/DatabaseError.h" +#include "platform/heap/Handle.h" #include "wtf/Assertions.h" #include "wtf/HashMap.h" #include "wtf/PassRefPtr.h" @@ -42,7 +43,7 @@ class DatabaseBackendBase; class DatabaseCallback; class DatabaseContext; class DatabaseSync; -class DatabaseTaskSynchronizer; +class TaskSynchronizer; class ExceptionState; class SecurityOrigin; class ExecutionContext; @@ -54,16 +55,12 @@ class DatabaseManager { public: static DatabaseManager& manager(); - // This gets a DatabaseContext for the specified ExecutionContext. - // If one doesn't already exist, it will create a new one. - PassRefPtr<DatabaseContext> databaseContextFor(ExecutionContext*); - // These 2 methods are for DatabaseContext (un)registration, and should only // be called by the DatabaseContext constructor and destructor. void registerDatabaseContext(DatabaseContext*); void unregisterDatabaseContext(DatabaseContext*); -#if !ASSERT_DISABLED +#if ASSERT_ENABLED void didConstructDatabaseContext(); void didDestructDatabaseContext(); #else @@ -73,27 +70,27 @@ public: static void throwExceptionForDatabaseError(DatabaseError, const String& errorMessage, ExceptionState&); - PassRefPtr<Database> openDatabase(ExecutionContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback>, DatabaseError&, String& errorMessage); - PassRefPtr<DatabaseSync> openDatabaseSync(ExecutionContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback>, DatabaseError&, String& errorMessage); - - bool hasOpenDatabases(ExecutionContext*); - void stopDatabases(ExecutionContext*, DatabaseTaskSynchronizer*); + PassRefPtrWillBeRawPtr<Database> openDatabase(ExecutionContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback>, DatabaseError&, String& errorMessage); + PassRefPtrWillBeRawPtr<DatabaseSync> openDatabaseSync(ExecutionContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback>, DatabaseError&, String& errorMessage); String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist = true); void closeDatabasesImmediately(const String& originIdentifier, const String& name); - void interruptAllDatabasesForContext(ExecutionContext*); + void interruptAllDatabasesForContext(DatabaseContext*); private: DatabaseManager(); - ~DatabaseManager() { } + ~DatabaseManager(); + // This gets a DatabaseContext for the specified ExecutionContext. + // If one doesn't already exist, it will create a new one. + DatabaseContext* databaseContextFor(ExecutionContext*); // This gets a DatabaseContext for the specified ExecutionContext if // it already exist previously. Otherwise, it returns 0. - PassRefPtr<DatabaseContext> existingDatabaseContextFor(ExecutionContext*); + DatabaseContext* existingDatabaseContextFor(ExecutionContext*); - PassRefPtr<DatabaseBackendBase> openDatabaseBackend(ExecutionContext*, + PassRefPtrWillBeRawPtr<DatabaseBackendBase> openDatabaseBackend(ExecutionContext*, DatabaseType, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); @@ -102,9 +99,14 @@ private: AbstractDatabaseServer* m_server; // Access to the following fields require locking m_contextMapLock: - typedef HashMap<ExecutionContext*, DatabaseContext*> ContextMap; +#if ENABLE(OILPAN) + // We can't use PersistentHeapHashMap because multiple threads update the map. + typedef HashMap<ExecutionContext*, OwnPtr<Persistent<DatabaseContext> > > ContextMap; +#else + typedef HashMap<ExecutionContext*, RefPtr<DatabaseContext> > ContextMap; +#endif ContextMap m_contextMap; -#if !ASSERT_DISABLED +#if ASSERT_ENABLED int m_databaseContextRegisteredCount; int m_databaseContextInstanceCount; #endif diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseObserver.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseObserver.h deleted file mode 100644 index 91e9b53991d..00000000000 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseObserver.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DatabaseObserver_h -#define DatabaseObserver_h - -#include "wtf/Forward.h" - -namespace WebCore { - -class DatabaseBackendBase; -class ExecutionContext; - -// FIXME: Deprecate this entire class. -// The implementation of this class is in the WebKit API (Chromium source tree) -// in WebKit/chromium/src/DatabaseObserver.cpp. -class DatabaseObserver { -public: - static void databaseOpened(DatabaseBackendBase*); - static void databaseModified(DatabaseBackendBase*); - static void databaseClosed(DatabaseBackendBase*); - - static void reportOpenDatabaseResult(DatabaseBackendBase*, int callsite, int webSqlErrorCode, int sqliteErrorCode); - static void reportChangeVersionResult(DatabaseBackendBase*, int callsite, int webSqlErrorCode, int sqliteErrorCode); - static void reportStartTransactionResult(DatabaseBackendBase*, int callsite, int webSqlErrorCode, int sqliteErrorCode); - static void reportCommitTransactionResult(DatabaseBackendBase*, int callsite, int webSqlErrorCode, int sqliteErrorCode); - static void reportExecuteStatementResult(DatabaseBackendBase*, int callsite, int webSqlErrorCode, int sqliteErrorCode); - static void reportVacuumDatabaseResult(DatabaseBackendBase*, int sqliteErrorCode); -}; - -} - -#endif // DatabaseObserver_h diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseServer.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseServer.cpp index 7ff2a8e5bef..c62af0e4170 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseServer.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseServer.cpp @@ -50,31 +50,31 @@ void DatabaseServer::interruptAllDatabasesForContext(const DatabaseContext* cont DatabaseTracker::tracker().interruptAllDatabasesForContext(context); } -PassRefPtr<DatabaseBackendBase> DatabaseServer::openDatabase(RefPtr<DatabaseContext>& backendContext, +PassRefPtrWillBeRawPtr<DatabaseBackendBase> DatabaseServer::openDatabase(DatabaseContext* backendContext, DatabaseType type, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError &error, String& errorMessage) { - RefPtr<DatabaseBackendBase> database; - if (DatabaseTracker::tracker().canEstablishDatabase(backendContext.get(), name, displayName, estimatedSize, error)) + RefPtrWillBeRawPtr<DatabaseBackendBase> database = nullptr; + if (DatabaseTracker::tracker().canEstablishDatabase(backendContext, name, displayName, estimatedSize, error)) database = createDatabase(backendContext, type, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase, error, errorMessage); return database.release(); } -PassRefPtr<DatabaseBackendBase> DatabaseServer::createDatabase(RefPtr<DatabaseContext>& backendContext, +PassRefPtrWillBeRawPtr<DatabaseBackendBase> DatabaseServer::createDatabase(DatabaseContext* backendContext, DatabaseType type, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage) { - RefPtr<DatabaseBackendBase> database; + RefPtrWillBeRawPtr<DatabaseBackendBase> database = nullptr; switch (type) { case DatabaseType::Async: - database = adoptRef(new Database(backendContext, name, expectedVersion, displayName, estimatedSize)); + database = adoptRefWillBeNoop(new Database(backendContext, name, expectedVersion, displayName, estimatedSize)); break; case DatabaseType::Sync: - database = adoptRef(new DatabaseSync(backendContext, name, expectedVersion, displayName, estimatedSize)); + database = adoptRefWillBeNoop(new DatabaseSync(backendContext, name, expectedVersion, displayName, estimatedSize)); } if (!database->openAndVerifyVersion(setVersionInNewDatabase, error, errorMessage)) - return 0; + return nullptr; return database.release(); } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseServer.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseServer.h index 30b758f8207..815fb9de4ab 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseServer.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseServer.h @@ -27,26 +27,27 @@ #define DatabaseServer_h #include "modules/webdatabase/AbstractDatabaseServer.h" +#include "platform/heap/Handle.h" namespace WebCore { -class DatabaseServer: public AbstractDatabaseServer { +class DatabaseServer FINAL : public AbstractDatabaseServer { public: - DatabaseServer() { }; + DatabaseServer() { } virtual ~DatabaseServer() { } - virtual String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist); + virtual String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist) OVERRIDE; - virtual PassRefPtr<DatabaseBackendBase> openDatabase(RefPtr<DatabaseContext>&, DatabaseType, + virtual PassRefPtrWillBeRawPtr<DatabaseBackendBase> openDatabase(DatabaseContext*, DatabaseType, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, - bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); + bool setVersionInNewDatabase, DatabaseError&, String& errorMessage) OVERRIDE; - virtual void closeDatabasesImmediately(const String& originIdentifier, const String& name); + virtual void closeDatabasesImmediately(const String& originIdentifier, const String& name) OVERRIDE; - virtual void interruptAllDatabasesForContext(const DatabaseContext*); + virtual void interruptAllDatabasesForContext(const DatabaseContext*) OVERRIDE; protected: - virtual PassRefPtr<DatabaseBackendBase> createDatabase(RefPtr<DatabaseContext>&, DatabaseType, + PassRefPtrWillBeRawPtr<DatabaseBackendBase> createDatabase(DatabaseContext*, DatabaseType, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.cpp index 348e4d13060..0b249873461 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.cpp @@ -48,15 +48,15 @@ namespace WebCore { -PassRefPtr<DatabaseSync> DatabaseSync::create(ExecutionContext*, PassRefPtr<DatabaseBackendBase> backend) +PassRefPtrWillBeRawPtr<DatabaseSync> DatabaseSync::create(ExecutionContext*, PassRefPtrWillBeRawPtr<DatabaseBackendBase> backend) { return static_cast<DatabaseSync*>(backend.get()); } -DatabaseSync::DatabaseSync(PassRefPtr<DatabaseContext> databaseContext, +DatabaseSync::DatabaseSync(DatabaseContext* databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) - : DatabaseBase(databaseContext->executionContext()) - , DatabaseBackendSync(databaseContext, name, expectedVersion, displayName, estimatedSize) + : DatabaseBackendSync(databaseContext, name, expectedVersion, displayName, estimatedSize) + , DatabaseBase(databaseContext->executionContext()) { ScriptWrappable::init(this); setFrontend(this); @@ -64,26 +64,27 @@ DatabaseSync::DatabaseSync(PassRefPtr<DatabaseContext> databaseContext, DatabaseSync::~DatabaseSync() { - ASSERT(m_executionContext->isContextThread()); + if (executionContext()) + ASSERT(executionContext()->isContextThread()); } -PassRefPtr<DatabaseBackendSync> DatabaseSync::backend() +void DatabaseSync::trace(Visitor* visitor) { - return this; + DatabaseBackendSync::trace(visitor); } void DatabaseSync::changeVersion(const String& oldVersion, const String& newVersion, PassOwnPtr<SQLTransactionSyncCallback> changeVersionCallback, ExceptionState& exceptionState) { - ASSERT(m_executionContext->isContextThread()); + ASSERT(executionContext()->isContextThread()); if (sqliteDatabase().transactionInProgress()) { reportChangeVersionResult(1, SQLError::DATABASE_ERR, 0); setLastErrorMessage("unable to changeVersion from within a transaction"); - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Unable to change version from within a transaction."); return; } - RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, changeVersionCallback, false); + RefPtrWillBeRawPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, changeVersionCallback, false); transaction->begin(exceptionState); if (exceptionState.hadException()) { ASSERT(!lastErrorMessage().isEmpty()); @@ -142,40 +143,40 @@ void DatabaseSync::readTransaction(PassOwnPtr<SQLTransactionSyncCallback> callba runTransaction(callback, true, exceptionState); } -void DatabaseSync::rollbackTransaction(PassRefPtr<SQLTransactionSync> transaction) +void DatabaseSync::rollbackTransaction(SQLTransactionSync& transaction) { ASSERT(!lastErrorMessage().isEmpty()); - transaction->rollback(); + transaction.rollback(); setLastErrorMessage(""); return; } void DatabaseSync::runTransaction(PassOwnPtr<SQLTransactionSyncCallback> callback, bool readOnly, ExceptionState& exceptionState) { - ASSERT(m_executionContext->isContextThread()); + ASSERT(executionContext()->isContextThread()); if (sqliteDatabase().transactionInProgress()) { setLastErrorMessage("unable to start a transaction from within a transaction"); - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Unable to start a transaction from within a transaction."); return; } - RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, callback, readOnly); + RefPtrWillBeRawPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, callback, readOnly); transaction->begin(exceptionState); if (exceptionState.hadException()) { - rollbackTransaction(transaction); + rollbackTransaction(*transaction); return; } transaction->execute(exceptionState); if (exceptionState.hadException()) { - rollbackTransaction(transaction); + rollbackTransaction(*transaction); return; } transaction->commit(exceptionState); if (exceptionState.hadException()) { - rollbackTransaction(transaction); + rollbackTransaction(*transaction); return; } @@ -184,7 +185,7 @@ void DatabaseSync::runTransaction(PassOwnPtr<SQLTransactionSyncCallback> callbac void DatabaseSync::closeImmediately() { - ASSERT(m_executionContext->isContextThread()); + ASSERT(executionContext()->isContextThread()); if (!opened()) return; @@ -193,4 +194,18 @@ void DatabaseSync::closeImmediately() closeDatabase(); } +void DatabaseSync::observeTransaction(SQLTransactionSync& transaction) +{ +#if ENABLE(OILPAN) + m_observers.add(&transaction, adoptPtr(new TransactionObserver(transaction))); +#endif +} + +#if ENABLE(OILPAN) +DatabaseSync::TransactionObserver::~TransactionObserver() +{ + m_transaction.rollbackIfInProgress(); +} +#endif + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.h index 64551d24df6..663c4154cc6 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.h @@ -35,6 +35,7 @@ #include "modules/webdatabase/DatabaseBackendSync.h" #include "modules/webdatabase/DatabaseBase.h" #include "modules/webdatabase/DatabaseBasicTypes.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/text/WTFString.h" @@ -51,35 +52,50 @@ class SQLTransactionSyncCallback; class SecurityOrigin; // Instances of this class should be created and used only on the worker's context thread. -class DatabaseSync : public DatabaseBase, public DatabaseBackendSync, public ScriptWrappable { +class DatabaseSync FINAL : public DatabaseBackendSync, public DatabaseBase, public ScriptWrappable { public: virtual ~DatabaseSync(); + virtual void trace(Visitor*) OVERRIDE; void changeVersion(const String& oldVersion, const String& newVersion, PassOwnPtr<SQLTransactionSyncCallback>, ExceptionState&); void transaction(PassOwnPtr<SQLTransactionSyncCallback>, ExceptionState&); void readTransaction(PassOwnPtr<SQLTransactionSyncCallback>, ExceptionState&); - virtual void closeImmediately(); + virtual void closeImmediately() OVERRIDE; + void observeTransaction(SQLTransactionSync&); const String& lastErrorMessage() const { return m_lastErrorMessage; } void setLastErrorMessage(const String& message) { m_lastErrorMessage = message; } - void setLastErrorMessage(const char* message, int sqliteCode) - { - setLastErrorMessage(String::format("%s (%d)", message, sqliteCode)); - } void setLastErrorMessage(const char* message, int sqliteCode, const char* sqliteMessage) { setLastErrorMessage(String::format("%s (%d, %s)", message, sqliteCode, sqliteMessage)); } private: - DatabaseSync(PassRefPtr<DatabaseContext>, const String& name, + DatabaseSync(DatabaseContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); - PassRefPtr<DatabaseBackendSync> backend(); - static PassRefPtr<DatabaseSync> create(ExecutionContext*, PassRefPtr<DatabaseBackendBase>); + static PassRefPtrWillBeRawPtr<DatabaseSync> create(ExecutionContext*, PassRefPtrWillBeRawPtr<DatabaseBackendBase>); void runTransaction(PassOwnPtr<SQLTransactionSyncCallback>, bool readOnly, ExceptionState&); - void rollbackTransaction(PassRefPtr<SQLTransactionSync>); + void rollbackTransaction(SQLTransactionSync&); +#if ENABLE(OILPAN) + class TransactionObserver { + public: + explicit TransactionObserver(SQLTransactionSync& transaction) : m_transaction(transaction) { } + ~TransactionObserver(); + + private: + SQLTransactionSync& m_transaction; + }; + + // Need a Persistent field because a HeapHashMap entry should be removed + // just after a SQLTransactionSync becomes untraceable. If this field was a + // Member<>, we could not assume the destruction order of DatabaseSync, + // SQLTransactionSync, and the field. We can not make the field static + // because multiple worker threads create SQLTransactionSync. + GC_PLUGIN_IGNORE("http://crbug.com/353083") + PersistentHeapHashMap<WeakMember<SQLTransactionSync>, OwnPtr<TransactionObserver> > m_observers; +#endif String m_lastErrorMessage; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.idl index eaaf30f14ea..a558400bf7e 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseSync.idl @@ -29,6 +29,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface DatabaseSync { readonly attribute DOMString version; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTask.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTask.cpp index 7591c386538..83d5efff929 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTask.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTask.cpp @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "config.h" #include "modules/webdatabase/DatabaseTask.h" @@ -35,31 +36,7 @@ namespace WebCore { -DatabaseTaskSynchronizer::DatabaseTaskSynchronizer() - : m_taskCompleted(false) -#ifndef NDEBUG - , m_hasCheckedForTermination(false) -#endif -{ -} - -void DatabaseTaskSynchronizer::waitForTaskCompletion() -{ - m_synchronousMutex.lock(); - while (!m_taskCompleted) - m_synchronousCondition.wait(m_synchronousMutex); - m_synchronousMutex.unlock(); -} - -void DatabaseTaskSynchronizer::taskCompleted() -{ - m_synchronousMutex.lock(); - m_taskCompleted = true; - m_synchronousCondition.signal(); - m_synchronousMutex.unlock(); -} - -DatabaseTask::DatabaseTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer) +DatabaseTask::DatabaseTask(DatabaseBackend* database, TaskSynchronizer* synchronizer) : m_database(database) , m_synchronizer(synchronizer) #if !LOG_DISABLED @@ -106,7 +83,7 @@ void DatabaseTask::run() // *** DatabaseOpenTask *** // Opens the database file and verifies the version matches the expected version. -DatabaseBackend::DatabaseOpenTask::DatabaseOpenTask(DatabaseBackend* database, bool setVersionInNewDatabase, DatabaseTaskSynchronizer* synchronizer, DatabaseError& error, String& errorMessage, bool& success) +DatabaseBackend::DatabaseOpenTask::DatabaseOpenTask(DatabaseBackend* database, bool setVersionInNewDatabase, TaskSynchronizer* synchronizer, DatabaseError& error, String& errorMessage, bool& success) : DatabaseTask(database, synchronizer) , m_setVersionInNewDatabase(setVersionInNewDatabase) , m_error(error) @@ -134,7 +111,7 @@ const char* DatabaseBackend::DatabaseOpenTask::debugTaskName() const // *** DatabaseCloseTask *** // Closes the database. -DatabaseBackend::DatabaseCloseTask::DatabaseCloseTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer) +DatabaseBackend::DatabaseCloseTask::DatabaseCloseTask(DatabaseBackend* database, TaskSynchronizer* synchronizer) : DatabaseTask(database, synchronizer) { } @@ -154,7 +131,7 @@ const char* DatabaseBackend::DatabaseCloseTask::debugTaskName() const // *** DatabaseTransactionTask *** // Starts a transaction that will report its results via a callback. -DatabaseBackend::DatabaseTransactionTask::DatabaseTransactionTask(PassRefPtr<SQLTransactionBackend> transaction) +DatabaseBackend::DatabaseTransactionTask::DatabaseTransactionTask(PassRefPtrWillBeRawPtr<SQLTransactionBackend> transaction) : DatabaseTask(Database::from(transaction->database()), 0) , m_transaction(transaction) { @@ -192,7 +169,7 @@ const char* DatabaseBackend::DatabaseTransactionTask::debugTaskName() const // *** DatabaseTableNamesTask *** // Retrieves a list of all tables in the database - for WebInspector support. -DatabaseBackend::DatabaseTableNamesTask::DatabaseTableNamesTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer, Vector<String>& names) +DatabaseBackend::DatabaseTableNamesTask::DatabaseTableNamesTask(DatabaseBackend* database, TaskSynchronizer* synchronizer, Vector<String>& names) : DatabaseTask(database, synchronizer) , m_tableNames(names) { diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTask.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTask.h index a12fb3535f9..dc8c4a1e436 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTask.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTask.h @@ -25,6 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef DatabaseTask_h #define DatabaseTask_h @@ -33,6 +34,8 @@ #include "modules/webdatabase/DatabaseError.h" #include "modules/webdatabase/SQLTransactionBackend.h" #include "platform/Task.h" +#include "platform/TaskSynchronizer.h" +#include "platform/heap/Handle.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" @@ -43,39 +46,12 @@ namespace WebCore { -// Can be used to wait until DatabaseTask is completed. -// Has to be passed into DatabaseTask::create to be associated with the task. -class DatabaseTaskSynchronizer { - WTF_MAKE_NONCOPYABLE(DatabaseTaskSynchronizer); -public: - DatabaseTaskSynchronizer(); - - // Called from main thread to wait until task is completed. - void waitForTaskCompletion(); - - // Called by the task. - void taskCompleted(); - -#ifndef NDEBUG - bool hasCheckedForTermination() const { return m_hasCheckedForTermination; } - void setHasCheckedForTermination() { m_hasCheckedForTermination = true; } -#endif - -private: - bool m_taskCompleted; - Mutex m_synchronousMutex; - ThreadCondition m_synchronousCondition; -#ifndef NDEBUG - bool m_hasCheckedForTermination; -#endif -}; - class DatabaseTask : public blink::WebThread::Task { WTF_MAKE_NONCOPYABLE(DatabaseTask); WTF_MAKE_FAST_ALLOCATED; public: virtual ~DatabaseTask(); - virtual void run() OVERRIDE; + virtual void run() OVERRIDE FINAL; DatabaseBackend* database() const { return m_database.get(); } #ifndef NDEBUG @@ -84,14 +60,14 @@ public: #endif protected: - DatabaseTask(DatabaseBackend*, DatabaseTaskSynchronizer*); + DatabaseTask(DatabaseBackend*, TaskSynchronizer*); private: virtual void doPerformTask() = 0; virtual void taskCancelled() { } - RefPtr<DatabaseBackend> m_database; - DatabaseTaskSynchronizer* m_synchronizer; + RefPtrWillBeCrossThreadPersistent<DatabaseBackend> m_database; + TaskSynchronizer* m_synchronizer; #if !LOG_DISABLED virtual const char* debugTaskName() const = 0; @@ -99,19 +75,19 @@ private: #endif }; -class DatabaseBackend::DatabaseOpenTask : public DatabaseTask { +class DatabaseBackend::DatabaseOpenTask FINAL : public DatabaseTask { public: - static PassOwnPtr<DatabaseOpenTask> create(DatabaseBackend* db, bool setVersionInNewDatabase, DatabaseTaskSynchronizer* synchronizer, DatabaseError& error, String& errorMessage, bool& success) + static PassOwnPtr<DatabaseOpenTask> create(DatabaseBackend* db, bool setVersionInNewDatabase, TaskSynchronizer* synchronizer, DatabaseError& error, String& errorMessage, bool& success) { return adoptPtr(new DatabaseOpenTask(db, setVersionInNewDatabase, synchronizer, error, errorMessage, success)); } private: - DatabaseOpenTask(DatabaseBackend*, bool setVersionInNewDatabase, DatabaseTaskSynchronizer*, DatabaseError&, String& errorMessage, bool& success); + DatabaseOpenTask(DatabaseBackend*, bool setVersionInNewDatabase, TaskSynchronizer*, DatabaseError&, String& errorMessage, bool& success); - virtual void doPerformTask(); + virtual void doPerformTask() OVERRIDE; #if !LOG_DISABLED - virtual const char* debugTaskName() const; + virtual const char* debugTaskName() const OVERRIDE; #endif bool m_setVersionInNewDatabase; @@ -120,28 +96,28 @@ private: bool& m_success; }; -class DatabaseBackend::DatabaseCloseTask : public DatabaseTask { +class DatabaseBackend::DatabaseCloseTask FINAL : public DatabaseTask { public: - static PassOwnPtr<DatabaseCloseTask> create(DatabaseBackend* db, DatabaseTaskSynchronizer* synchronizer) + static PassOwnPtr<DatabaseCloseTask> create(DatabaseBackend* db, TaskSynchronizer* synchronizer) { return adoptPtr(new DatabaseCloseTask(db, synchronizer)); } private: - DatabaseCloseTask(DatabaseBackend*, DatabaseTaskSynchronizer*); + DatabaseCloseTask(DatabaseBackend*, TaskSynchronizer*); - virtual void doPerformTask(); + virtual void doPerformTask() OVERRIDE; #if !LOG_DISABLED - virtual const char* debugTaskName() const; + virtual const char* debugTaskName() const OVERRIDE; #endif }; -class DatabaseBackend::DatabaseTransactionTask : public DatabaseTask { +class DatabaseBackend::DatabaseTransactionTask FINAL : public DatabaseTask { public: virtual ~DatabaseTransactionTask(); // Transaction task is never synchronous, so no 'synchronizer' parameter. - static PassOwnPtr<DatabaseTransactionTask> create(PassRefPtr<SQLTransactionBackend> transaction) + static PassOwnPtr<DatabaseTransactionTask> create(PassRefPtrWillBeRawPtr<SQLTransactionBackend> transaction) { return adoptPtr(new DatabaseTransactionTask(transaction)); } @@ -149,30 +125,30 @@ public: SQLTransactionBackend* transaction() const { return m_transaction.get(); } private: - explicit DatabaseTransactionTask(PassRefPtr<SQLTransactionBackend>); + explicit DatabaseTransactionTask(PassRefPtrWillBeRawPtr<SQLTransactionBackend>); - virtual void doPerformTask(); - virtual void taskCancelled(); + virtual void doPerformTask() OVERRIDE; + virtual void taskCancelled() OVERRIDE; #if !LOG_DISABLED - virtual const char* debugTaskName() const; + virtual const char* debugTaskName() const OVERRIDE; #endif - RefPtr<SQLTransactionBackend> m_transaction; + RefPtrWillBeCrossThreadPersistent<SQLTransactionBackend> m_transaction; }; -class DatabaseBackend::DatabaseTableNamesTask : public DatabaseTask { +class DatabaseBackend::DatabaseTableNamesTask FINAL : public DatabaseTask { public: - static PassOwnPtr<DatabaseTableNamesTask> create(DatabaseBackend* db, DatabaseTaskSynchronizer* synchronizer, Vector<String>& names) + static PassOwnPtr<DatabaseTableNamesTask> create(DatabaseBackend* db, TaskSynchronizer* synchronizer, Vector<String>& names) { return adoptPtr(new DatabaseTableNamesTask(db, synchronizer, names)); } private: - DatabaseTableNamesTask(DatabaseBackend*, DatabaseTaskSynchronizer*, Vector<String>& names); + DatabaseTableNamesTask(DatabaseBackend*, TaskSynchronizer*, Vector<String>& names); - virtual void doPerformTask(); + virtual void doPerformTask() OVERRIDE; #if !LOG_DISABLED - virtual const char* debugTaskName() const; + virtual const char* debugTaskName() const OVERRIDE; #endif Vector<String>& m_tableNames; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp index 97338704125..b1a70a13b9d 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp @@ -34,14 +34,15 @@ #include "modules/webdatabase/SQLTransactionClient.h" #include "modules/webdatabase/SQLTransactionCoordinator.h" #include "platform/Logging.h" +#include "platform/heap/glue/MessageLoopInterruptor.h" +#include "platform/heap/glue/PendingGCRunner.h" #include "public/platform/Platform.h" -#include "wtf/AutodrainedPool.h" namespace WebCore { DatabaseThread::DatabaseThread() : m_transactionClient(adoptPtr(new SQLTransactionClient())) - , m_transactionCoordinator(adoptPtr(new SQLTransactionCoordinator())) + , m_transactionCoordinator(adoptPtrWillBeNoop(new SQLTransactionCoordinator())) , m_cleanupSync(0) , m_terminationRequested(false) { @@ -49,20 +50,42 @@ DatabaseThread::DatabaseThread() DatabaseThread::~DatabaseThread() { - if (!m_terminationRequested) - requestTermination(0); + ASSERT(m_openDatabaseSet.isEmpty()); + // Oilpan: The database thread must have finished its cleanup tasks before + // the following clear(). Otherwise, WebThread destructor blocks the caller + // thread, and causes a deadlock with ThreadState cleanup. + // DatabaseContext::stop() asks the database thread to close all of + // databases, and wait until GC heap cleanup of the database thread. So we + // can safely destruct WebThread here. m_thread.clear(); } +void DatabaseThread::trace(Visitor* visitor) +{ + visitor->trace(m_openDatabaseSet); + visitor->trace(m_transactionCoordinator); +} + void DatabaseThread::start() { if (m_thread) return; m_thread = adoptPtr(blink::Platform::current()->createThread("WebCore: Database")); + m_thread->postTask(new Task(WTF::bind(&DatabaseThread::setupDatabaseThread, this))); +} + +void DatabaseThread::setupDatabaseThread() +{ + m_pendingGCRunner = adoptPtr(new PendingGCRunner); + m_messageLoopInterruptor = adoptPtr(new MessageLoopInterruptor(m_thread.get())); + m_thread->addTaskObserver(m_pendingGCRunner.get()); + ThreadState::attach(); + ThreadState::current()->addInterruptor(m_messageLoopInterruptor.get()); } -void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync) +void DatabaseThread::requestTermination(TaskSynchronizer *cleanupSync) { + MutexLocker lock(m_terminationRequestedMutex); ASSERT(!m_terminationRequested); m_terminationRequested = true; m_cleanupSync = cleanupSync; @@ -70,13 +93,14 @@ void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync) m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThread, this))); } -bool DatabaseThread::terminationRequested(DatabaseTaskSynchronizer* taskSynchronizer) const +bool DatabaseThread::terminationRequested(TaskSynchronizer* taskSynchronizer) const { #ifndef NDEBUG if (taskSynchronizer) taskSynchronizer->setHasCheckedForTermination(); #endif + MutexLocker lock(m_terminationRequestedMutex); return m_terminationRequested; } @@ -91,15 +115,26 @@ void DatabaseThread::cleanupDatabaseThread() // inconsistent or locked state. if (m_openDatabaseSet.size() > 0) { // As the call to close will modify the original set, we must take a copy to iterate over. - DatabaseSet openSetCopy; + WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> > openSetCopy; openSetCopy.swap(m_openDatabaseSet); - DatabaseSet::iterator end = openSetCopy.end(); - for (DatabaseSet::iterator it = openSetCopy.begin(); it != end; ++it) - (*it).get()->close(); + WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> >::iterator end = openSetCopy.end(); + for (WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> >::iterator it = openSetCopy.begin(); it != end; ++it) + (*it)->close(); } + m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThreadCompleted, this))); +} + +void DatabaseThread::cleanupDatabaseThreadCompleted() +{ + ThreadState::current()->removeInterruptor(m_messageLoopInterruptor.get()); + ThreadState::detach(); + // We need to unregister PendingGCRunner before finising this task to avoid + // PendingGCRunner::didProcessTask accesses dead ThreadState. + m_thread->removeTaskObserver(m_pendingGCRunner.get()); + if (m_cleanupSync) // Someone wanted to know when we were done cleaning up. - m_thread->postTask(new Task(WTF::bind(&DatabaseTaskSynchronizer::taskCompleted, m_cleanupSync))); + m_cleanupSync->taskCompleted(); } void DatabaseThread::recordDatabaseOpen(DatabaseBackend* database) @@ -122,6 +157,7 @@ bool DatabaseThread::isDatabaseOpen(DatabaseBackend* database) { ASSERT(isDatabaseThread()); ASSERT(database); + MutexLocker lock(m_terminationRequestedMutex); return !m_terminationRequested && m_openDatabaseSet.contains(database); } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.h index 53623eca907..c08dca5f4fd 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.h @@ -28,6 +28,7 @@ #ifndef DatabaseThread_h #define DatabaseThread_h +#include "platform/heap/Handle.h" #include "public/platform/WebThread.h" #include "wtf/Deque.h" #include "wtf/HashMap.h" @@ -37,24 +38,28 @@ #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" #include "wtf/ThreadSafeRefCounted.h" +#include "wtf/ThreadingPrimitives.h" namespace WebCore { class DatabaseBackend; class DatabaseTask; -class DatabaseTaskSynchronizer; class Document; +class MessageLoopInterruptor; +class PendingGCRunner; class SQLTransactionClient; class SQLTransactionCoordinator; +class TaskSynchronizer; -class DatabaseThread : public ThreadSafeRefCounted<DatabaseThread> { +class DatabaseThread : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<DatabaseThread> { public: - static PassRefPtr<DatabaseThread> create() { return adoptRef(new DatabaseThread); } + static PassRefPtrWillBeRawPtr<DatabaseThread> create() { return adoptRefWillBeNoop(new DatabaseThread); } ~DatabaseThread(); + void trace(Visitor*); void start(); - void requestTermination(DatabaseTaskSynchronizer* cleanupSync); - bool terminationRequested(DatabaseTaskSynchronizer* taskSynchronizer = 0) const; + void requestTermination(TaskSynchronizer* cleanupSync); + bool terminationRequested(TaskSynchronizer* = 0) const; void scheduleTask(PassOwnPtr<DatabaseTask>); @@ -70,18 +75,25 @@ public: private: DatabaseThread(); + void setupDatabaseThread(); void cleanupDatabaseThread(); + void cleanupDatabaseThreadCompleted(); OwnPtr<blink::WebThread> m_thread; // This set keeps track of the open databases that have been used on this thread. - typedef HashSet<RefPtr<DatabaseBackend> > DatabaseSet; - DatabaseSet m_openDatabaseSet; + // This must be updated in the database thread though it is constructed and + // destructed in the context thread. + WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> > m_openDatabaseSet; OwnPtr<SQLTransactionClient> m_transactionClient; - OwnPtr<SQLTransactionCoordinator> m_transactionCoordinator; - DatabaseTaskSynchronizer* m_cleanupSync; + OwnPtrWillBeMember<SQLTransactionCoordinator> m_transactionCoordinator; + TaskSynchronizer* m_cleanupSync; + + mutable Mutex m_terminationRequestedMutex; bool m_terminationRequested; + OwnPtr<PendingGCRunner> m_pendingGCRunner; + OwnPtr<MessageLoopInterruptor> m_messageLoopInterruptor; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp index e6f2b1b1b52..1bfa4b3a5a6 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp @@ -105,30 +105,30 @@ void DatabaseTracker::addOpenDatabase(DatabaseBackendBase* database) databaseSet->add(database); } -class NotifyDatabaseObserverOnCloseTask : public ExecutionContextTask { +class NotifyDatabaseObserverOnCloseTask FINAL : public ExecutionContextTask { public: - static PassOwnPtr<NotifyDatabaseObserverOnCloseTask> create(PassRefPtr<DatabaseBackendBase> database) + static PassOwnPtr<NotifyDatabaseObserverOnCloseTask> create(PassRefPtrWillBeRawPtr<DatabaseBackendBase> database) { return adoptPtr(new NotifyDatabaseObserverOnCloseTask(database)); } - virtual void performTask(ExecutionContext* context) + virtual void performTask(ExecutionContext*) OVERRIDE { databaseClosed(m_database.get()); } - virtual bool isCleanupTask() const + virtual bool isCleanupTask() const OVERRIDE { return true; } private: - NotifyDatabaseObserverOnCloseTask(PassRefPtr<DatabaseBackendBase> database) + explicit NotifyDatabaseObserverOnCloseTask(PassRefPtrWillBeRawPtr<DatabaseBackendBase> database) : m_database(database) { } - RefPtr<DatabaseBackendBase> m_database; + RefPtrWillBeCrossThreadPersistent<DatabaseBackendBase> m_database; }; void DatabaseTracker::removeOpenDatabase(DatabaseBackendBase* database) @@ -219,14 +219,14 @@ void DatabaseTracker::interruptAllDatabasesForContext(const DatabaseContext* con } } -class DatabaseTracker::CloseOneDatabaseImmediatelyTask : public ExecutionContextTask { +class DatabaseTracker::CloseOneDatabaseImmediatelyTask FINAL : public ExecutionContextTask { public: static PassOwnPtr<CloseOneDatabaseImmediatelyTask> create(const String& originIdentifier, const String& name, DatabaseBackendBase* database) { return adoptPtr(new CloseOneDatabaseImmediatelyTask(originIdentifier, name, database)); } - virtual void performTask(ExecutionContext* context) + virtual void performTask(ExecutionContext*) OVERRIDE { DatabaseTracker::tracker().closeOneDatabaseImmediately(m_originIdentifier, m_name, m_database); } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.h b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.h index c7f09591ef0..f1ad4491054 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.h @@ -59,7 +59,6 @@ public: void addOpenDatabase(DatabaseBackendBase*); void removeOpenDatabase(DatabaseBackendBase*); - void getOpenDatabases(SecurityOrigin*, const String& name, HashSet<RefPtr<DatabaseBackendBase> >* databases); unsigned long long getMaxSizeForDatabase(const DatabaseBackendBase*); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.cpp new file mode 100644 index 00000000000..7fb02271a83 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/webdatabase/InspectorDatabaseAgent.h" + +#include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/frame/LocalFrame.h" +#include "core/html/VoidCallback.h" +#include "core/inspector/InspectorState.h" +#include "core/loader/DocumentLoader.h" +#include "core/page/Page.h" +#include "modules/webdatabase/Database.h" +#include "modules/webdatabase/InspectorDatabaseResource.h" +#include "modules/webdatabase/SQLError.h" +#include "modules/webdatabase/SQLResultSet.h" +#include "modules/webdatabase/SQLResultSetRowList.h" +#include "modules/webdatabase/SQLStatementCallback.h" +#include "modules/webdatabase/SQLStatementErrorCallback.h" +#include "modules/webdatabase/SQLTransaction.h" +#include "modules/webdatabase/SQLTransactionCallback.h" +#include "modules/webdatabase/SQLTransactionErrorCallback.h" +#include "modules/webdatabase/sqlite/SQLValue.h" +#include "platform/JSONValues.h" +#include "wtf/Vector.h" + +typedef WebCore::InspectorBackendDispatcher::DatabaseCommandHandler::ExecuteSQLCallback ExecuteSQLCallback; + +namespace WebCore { + +namespace DatabaseAgentState { +static const char databaseAgentEnabled[] = "databaseAgentEnabled"; +}; + +namespace { + +void reportTransactionFailed(ExecuteSQLCallback* requestCallback, SQLError* error) +{ + RefPtr<TypeBuilder::Database::Error> errorObject = TypeBuilder::Database::Error::create() + .setMessage(error->message()) + .setCode(error->code()); + requestCallback->sendSuccess(nullptr, nullptr, errorObject.release()); +} + +class StatementCallback FINAL : public SQLStatementCallback { +public: + static PassOwnPtr<StatementCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback) + { + return adoptPtr(new StatementCallback(requestCallback)); + } + + virtual ~StatementCallback() { } + + virtual bool handleEvent(SQLTransaction*, SQLResultSet* resultSet) OVERRIDE + { + SQLResultSetRowList* rowList = resultSet->rows(); + + RefPtr<TypeBuilder::Array<String> > columnNames = TypeBuilder::Array<String>::create(); + const Vector<String>& columns = rowList->columnNames(); + for (size_t i = 0; i < columns.size(); ++i) + columnNames->addItem(columns[i]); + + RefPtr<TypeBuilder::Array<JSONValue> > values = TypeBuilder::Array<JSONValue>::create(); + const Vector<SQLValue>& data = rowList->values(); + for (size_t i = 0; i < data.size(); ++i) { + const SQLValue& value = rowList->values()[i]; + switch (value.type()) { + case SQLValue::StringValue: values->addItem(JSONString::create(value.string())); break; + case SQLValue::NumberValue: values->addItem(JSONBasicValue::create(value.number())); break; + case SQLValue::NullValue: values->addItem(JSONValue::null()); break; + } + } + m_requestCallback->sendSuccess(columnNames.release(), values.release(), nullptr); + return true; + } + +private: + StatementCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) + : m_requestCallback(requestCallback) { } + RefPtr<ExecuteSQLCallback> m_requestCallback; +}; + +class StatementErrorCallback FINAL : public SQLStatementErrorCallback { +public: + static PassOwnPtr<StatementErrorCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback) + { + return adoptPtr(new StatementErrorCallback(requestCallback)); + } + + virtual ~StatementErrorCallback() { } + + virtual bool handleEvent(SQLTransaction*, SQLError* error) OVERRIDE + { + reportTransactionFailed(m_requestCallback.get(), error); + return true; + } + +private: + StatementErrorCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) + : m_requestCallback(requestCallback) { } + RefPtr<ExecuteSQLCallback> m_requestCallback; +}; + +class TransactionCallback FINAL : public SQLTransactionCallback { +public: + static PassOwnPtr<TransactionCallback> create(const String& sqlStatement, PassRefPtr<ExecuteSQLCallback> requestCallback) + { + return adoptPtr(new TransactionCallback(sqlStatement, requestCallback)); + } + + virtual ~TransactionCallback() { } + + virtual bool handleEvent(SQLTransaction* transaction) OVERRIDE + { + if (!m_requestCallback->isActive()) + return true; + + Vector<SQLValue> sqlValues; + OwnPtr<SQLStatementCallback> callback(StatementCallback::create(m_requestCallback.get())); + OwnPtr<SQLStatementErrorCallback> errorCallback(StatementErrorCallback::create(m_requestCallback.get())); + transaction->executeSQL(m_sqlStatement, sqlValues, callback.release(), errorCallback.release(), IGNORE_EXCEPTION); + return true; + } +private: + TransactionCallback(const String& sqlStatement, PassRefPtr<ExecuteSQLCallback> requestCallback) + : m_sqlStatement(sqlStatement) + , m_requestCallback(requestCallback) { } + String m_sqlStatement; + RefPtr<ExecuteSQLCallback> m_requestCallback; +}; + +class TransactionErrorCallback FINAL : public SQLTransactionErrorCallback { +public: + static PassOwnPtr<TransactionErrorCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback) + { + return adoptPtr(new TransactionErrorCallback(requestCallback)); + } + + virtual ~TransactionErrorCallback() { } + + virtual bool handleEvent(SQLError* error) OVERRIDE + { + reportTransactionFailed(m_requestCallback.get(), error); + return true; + } +private: + TransactionErrorCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) + : m_requestCallback(requestCallback) { } + RefPtr<ExecuteSQLCallback> m_requestCallback; +}; + +class TransactionSuccessCallback FINAL : public VoidCallback { +public: + static PassOwnPtr<TransactionSuccessCallback> create() + { + return adoptPtr(new TransactionSuccessCallback()); + } + + virtual ~TransactionSuccessCallback() { } + + virtual void handleEvent() OVERRIDE { } + +private: + TransactionSuccessCallback() { } +}; + +} // namespace + +void InspectorDatabaseAgent::didOpenDatabase(PassRefPtrWillBeRawPtr<Database> database, const String& domain, const String& name, const String& version) +{ + if (InspectorDatabaseResource* resource = findByFileName(database->fileName())) { + resource->setDatabase(database); + return; + } + + RefPtrWillBeRawPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::create(database, domain, name, version); + m_resources.set(resource->id(), resource); + // Resources are only bound while visible. + if (m_frontend && m_enabled) + resource->bind(m_frontend); +} + +void InspectorDatabaseAgent::didCommitLoadForMainFrame() +{ + m_resources.clear(); +} + +InspectorDatabaseAgent::InspectorDatabaseAgent() + : InspectorBaseAgent<InspectorDatabaseAgent>("Database") + , m_frontend(0) + , m_enabled(false) +{ +} + +InspectorDatabaseAgent::~InspectorDatabaseAgent() +{ +} + +void InspectorDatabaseAgent::setFrontend(InspectorFrontend* frontend) +{ + m_frontend = frontend->database(); +} + +void InspectorDatabaseAgent::clearFrontend() +{ + m_frontend = 0; + disable(0); +} + +void InspectorDatabaseAgent::enable(ErrorString*) +{ + if (m_enabled) + return; + m_enabled = true; + m_state->setBoolean(DatabaseAgentState::databaseAgentEnabled, m_enabled); + + DatabaseResourcesHeapMap::iterator databasesEnd = m_resources.end(); + for (DatabaseResourcesHeapMap::iterator it = m_resources.begin(); it != databasesEnd; ++it) + it->value->bind(m_frontend); +} + +void InspectorDatabaseAgent::disable(ErrorString*) +{ + if (!m_enabled) + return; + m_enabled = false; + m_state->setBoolean(DatabaseAgentState::databaseAgentEnabled, m_enabled); +} + +void InspectorDatabaseAgent::restore() +{ + m_enabled = m_state->getBoolean(DatabaseAgentState::databaseAgentEnabled); +} + +void InspectorDatabaseAgent::getDatabaseTableNames(ErrorString* error, const String& databaseId, RefPtr<TypeBuilder::Array<String> >& names) +{ + if (!m_enabled) { + *error = "Database agent is not enabled"; + return; + } + + names = TypeBuilder::Array<String>::create(); + + Database* database = databaseForId(databaseId); + if (database) { + Vector<String> tableNames = database->tableNames(); + unsigned length = tableNames.size(); + for (unsigned i = 0; i < length; ++i) + names->addItem(tableNames[i]); + } +} + +void InspectorDatabaseAgent::executeSQL(ErrorString*, const String& databaseId, const String& query, PassRefPtr<ExecuteSQLCallback> prpRequestCallback) +{ + RefPtr<ExecuteSQLCallback> requestCallback = prpRequestCallback; + + if (!m_enabled) { + requestCallback->sendFailure("Database agent is not enabled"); + return; + } + + Database* database = databaseForId(databaseId); + if (!database) { + requestCallback->sendFailure("Database not found"); + return; + } + + OwnPtr<SQLTransactionCallback> callback(TransactionCallback::create(query, requestCallback.get())); + OwnPtr<SQLTransactionErrorCallback> errorCallback(TransactionErrorCallback::create(requestCallback.get())); + OwnPtr<VoidCallback> successCallback(TransactionSuccessCallback::create()); + database->transaction(callback.release(), errorCallback.release(), successCallback.release()); +} + +InspectorDatabaseResource* InspectorDatabaseAgent::findByFileName(const String& fileName) +{ + for (DatabaseResourcesHeapMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) { + if (it->value->database()->fileName() == fileName) + return it->value.get(); + } + return 0; +} + +Database* InspectorDatabaseAgent::databaseForId(const String& databaseId) +{ + DatabaseResourcesHeapMap::iterator it = m_resources.find(databaseId); + if (it == m_resources.end()) + return 0; + return it->value->database(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.h b/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.h new file mode 100644 index 00000000000..28cdb72c5bb --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseAgent.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef InspectorDatabaseAgent_h +#define InspectorDatabaseAgent_h + +#include "InspectorFrontend.h" +#include "core/inspector/InspectorBaseAgent.h" +#include "platform/heap/Handle.h" +#include "wtf/HashMap.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class Database; +class DocumentLoader; +class LocalFrame; +class InspectorDatabaseResource; +class InspectorFrontend; +class InstrumentingAgents; + +typedef String ErrorString; + +class InspectorDatabaseAgent FINAL : public InspectorBaseAgent<InspectorDatabaseAgent>, public InspectorBackendDispatcher::DatabaseCommandHandler { +public: + static PassOwnPtr<InspectorDatabaseAgent> create() + { + return adoptPtr(new InspectorDatabaseAgent()); + } + virtual ~InspectorDatabaseAgent(); + + virtual void setFrontend(InspectorFrontend*) OVERRIDE; + virtual void clearFrontend() OVERRIDE; + virtual void restore() OVERRIDE; + + virtual void didCommitLoadForMainFrame() OVERRIDE; + + // Called from the front-end. + virtual void enable(ErrorString*) OVERRIDE; + virtual void disable(ErrorString*) OVERRIDE; + virtual void getDatabaseTableNames(ErrorString*, const String& databaseId, RefPtr<TypeBuilder::Array<String> >& names) OVERRIDE; + virtual void executeSQL(ErrorString*, const String& databaseId, const String& query, PassRefPtr<ExecuteSQLCallback>) OVERRIDE; + + void didOpenDatabase(PassRefPtrWillBeRawPtr<Database>, const String& domain, const String& name, const String& version); +private: + explicit InspectorDatabaseAgent(); + + Database* databaseForId(const String& databaseId); + InspectorDatabaseResource* findByFileName(const String& fileName); + + InspectorFrontend::Database* m_frontend; + typedef WillBePersistentHeapHashMap<String, RefPtrWillBeMember<InspectorDatabaseResource> > DatabaseResourcesHeapMap; + DatabaseResourcesHeapMap m_resources; + bool m_enabled; +}; + +} // namespace WebCore + +#endif // !defined(InspectorDatabaseAgent_h) diff --git a/chromium/third_party/WebKit/Source/modules/indexeddb/chromium/IDBFactoryBackendInterfaceChromium.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseResource.cpp index 29e234f7d85..c44d6c565ec 100644 --- a/chromium/third_party/WebKit/Source/modules/indexeddb/chromium/IDBFactoryBackendInterfaceChromium.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseResource.cpp @@ -1,5 +1,7 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> + * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,24 +27,44 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "config.h" -#include "modules/indexeddb/chromium/IDBFactoryBackendInterfaceChromium.h" + +#include "modules/webdatabase/InspectorDatabaseResource.h" + +#include "modules/webdatabase/Database.h" namespace WebCore { -static IDBFactoryBackendInterfaceCreate* s_idbFactoryBackendInterfaceCreateFunction = 0; +static int nextUnusedId = 1; + +PassRefPtrWillBeRawPtr<InspectorDatabaseResource> InspectorDatabaseResource::create(PassRefPtrWillBeRawPtr<Database> database, const String& domain, const String& name, const String& version) +{ + return adoptRefWillBeNoop(new InspectorDatabaseResource(database, domain, name, version)); +} + +InspectorDatabaseResource::InspectorDatabaseResource(PassRefPtrWillBeRawPtr<Database> database, const String& domain, const String& name, const String& version) + : m_database(database) + , m_id(String::number(nextUnusedId++)) + , m_domain(domain) + , m_name(name) + , m_version(version) +{ +} -void setIDBFactoryBackendInterfaceCreateFunction(IDBFactoryBackendInterfaceCreate idbFactoryBackendInterfaceCreateFunction) +void InspectorDatabaseResource::trace(Visitor* visitor) { - s_idbFactoryBackendInterfaceCreateFunction = idbFactoryBackendInterfaceCreateFunction; + visitor->trace(m_database); } -PassRefPtr<IDBFactoryBackendInterface> IDBFactoryBackendInterface::create() +void InspectorDatabaseResource::bind(InspectorFrontend::Database* frontend) { - ASSERT(s_idbFactoryBackendInterfaceCreateFunction); - // There's no reason why we need to allocate a new proxy each time, but - // there's also no strong reason not to. - return s_idbFactoryBackendInterfaceCreateFunction(); + RefPtr<TypeBuilder::Database::Database> jsonObject = TypeBuilder::Database::Database::create() + .setId(m_id) + .setDomain(m_domain) + .setName(m_name) + .setVersion(m_version); + frontend->addDatabase(jsonObject); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseDetails.h b/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseResource.h index 162053b836a..d5705ca2c17 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/DatabaseDetails.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/InspectorDatabaseResource.h @@ -1,5 +1,7 @@ /* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> + * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,54 +28,40 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DatabaseDetails_h -#define DatabaseDetails_h +#ifndef InspectorDatabaseResource_h +#define InspectorDatabaseResource_h -#include "wtf/Threading.h" +#include "InspectorFrontend.h" +#include "platform/heap/Handle.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" +#include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" namespace WebCore { +class Database; +class InspectorFrontend; -class DatabaseDetails { +class InspectorDatabaseResource : public RefCountedWillBeGarbageCollectedFinalized<InspectorDatabaseResource> { public: - DatabaseDetails() - : m_expectedUsage(0) - , m_currentUsage(0) - { -#ifndef NDEBUG - m_thread = currentThread(); -#endif - } + static PassRefPtrWillBeRawPtr<InspectorDatabaseResource> create(PassRefPtrWillBeRawPtr<Database>, const String& domain, const String& name, const String& version); + void trace(Visitor*); - DatabaseDetails(const String& databaseName, const String& displayName, unsigned long long expectedUsage, unsigned long long currentUsage) - : m_name(databaseName) - , m_displayName(displayName) - , m_expectedUsage(expectedUsage) - , m_currentUsage(currentUsage) - { -#ifndef NDEBUG - m_thread = currentThread(); -#endif - } - - const String& name() const { return m_name; } - const String& displayName() const { return m_displayName; } - uint64_t expectedUsage() const { return m_expectedUsage; } - uint64_t currentUsage() const { return m_currentUsage; } -#ifndef NDEBUG - ThreadIdentifier thread() const { return m_thread; } -#endif + void bind(InspectorFrontend::Database*); + Database* database() { return m_database.get(); } + void setDatabase(PassRefPtrWillBeRawPtr<Database> database) { m_database = database; } + String id() const { return m_id; } private: + InspectorDatabaseResource(PassRefPtrWillBeRawPtr<Database>, const String& domain, const String& name, const String& version); + + RefPtrWillBeMember<Database> m_database; + String m_id; + String m_domain; String m_name; - String m_displayName; - uint64_t m_expectedUsage; - uint64_t m_currentUsage; -#ifndef NDEBUG - ThreadIdentifier m_thread; -#endif + String m_version; }; } // namespace WebCore -#endif // DatabaseDetails_h +#endif // InspectorDatabaseResource_h diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp index e6fa44b3b59..2ee2b44153a 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/QuotaTracker.cpp @@ -70,7 +70,7 @@ void QuotaTracker::updateDatabaseSize( unsigned long long databaseSize) { MutexLocker lockData(m_dataGuard); - HashMap<String, SizeMap>::iterator it = m_databaseSizes.add(originIdentifier, SizeMap()).iterator; + HashMap<String, SizeMap>::ValueType* it = m_databaseSizes.add(originIdentifier, SizeMap()).storedValue; it->value.set(databaseName, databaseSize); } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLCallbackWrapper.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLCallbackWrapper.h index e630b0af976..53d43b6a2f7 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLCallbackWrapper.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLCallbackWrapper.h @@ -40,7 +40,9 @@ namespace WebCore { // - by destructing the enclosing wrapper - on any thread // - by calling clear() - on any thread // - by unwrapping and then dereferencing normally - on context thread only +// Oilpan: ~T must be thread-independent. template<typename T> class SQLCallbackWrapper { + DISALLOW_ALLOCATION(); public: SQLCallbackWrapper(PassOwnPtr<T> callback, ExecutionContext* executionContext) : m_callback(callback) @@ -54,8 +56,18 @@ public: clear(); } + void trace(Visitor* visitor) { visitor->trace(m_executionContext); } + void clear() { +#if ENABLE(OILPAN) + // It's safe to call ~T in non-context-thread. + // Implementation classes of ExecutionContext are on-heap. Their + // destructors are called in their owner threads. + MutexLocker locker(m_mutex); + m_callback.clear(); + m_executionContext.clear(); +#else ExecutionContext* context; OwnPtr<T> callback; { @@ -73,6 +85,7 @@ public: callback = m_callback.release(); } context->postTask(SafeReleaseTask::create(callback.release())); +#endif } PassOwnPtr<T> unwrap() @@ -87,6 +100,7 @@ public: bool hasCallback() const { return m_callback; } private: +#if !ENABLE(OILPAN) class SafeReleaseTask : public ExecutionContextTask { public: static PassOwnPtr<SafeReleaseTask> create(PassOwnPtr<T> callbackToRelease) @@ -111,10 +125,11 @@ private: OwnPtr<T> m_callbackToRelease; }; +#endif Mutex m_mutex; OwnPtr<T> m_callback; - RefPtr<ExecutionContext> m_executionContext; + RefPtrWillBeMember<ExecutionContext> m_executionContext; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.cpp index 110040e3be4..5d327556ea1 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.cpp @@ -34,7 +34,6 @@ namespace WebCore { const char SQLError::quotaExceededErrorMessage[] = "Quota was exceeded."; -const char SQLError::syntaxErrorMessage[] = "Invalid or unauthorized statement; or the number of arguments did not match the number of ? placeholders."; const char SQLError::unknownErrorMessage[] = "The operation failed for reasons unrelated to the database."; const char SQLError::versionErrorMessage[] = "The actual database version did not match the expected version."; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.h index aed31d9b573..911fd3aee00 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.h @@ -35,21 +35,41 @@ namespace WebCore { -class SQLError : public ThreadSafeRefCounted<SQLError>, public ScriptWrappable { +class SQLErrorData { public: - static PassRefPtr<SQLError> create(unsigned code, const String& message) { return adoptRef(new SQLError(code, message)); } - static PassRefPtr<SQLError> create(unsigned code, const char* message, int sqliteCode) + static PassOwnPtr<SQLErrorData> create(unsigned code, const String& message) { - return create(code, String::format("%s (%d)", message, sqliteCode)); + return adoptPtr(new SQLErrorData(code, message)); } - static PassRefPtr<SQLError> create(unsigned code, const char* message, int sqliteCode, const char* sqliteMessage) + + static PassOwnPtr<SQLErrorData> create(unsigned code, const char* message, int sqliteCode, const char* sqliteMessage) { return create(code, String::format("%s (%d %s)", message, sqliteCode, sqliteMessage)); } + static PassOwnPtr<SQLErrorData> create(const SQLErrorData& data) + { + return create(data.code(), data.message()); + } + unsigned code() const { return m_code; } String message() const { return m_message.isolatedCopy(); } +private: + SQLErrorData(unsigned code, const String& message) : m_code(code), m_message(message.isolatedCopy()) { } + + unsigned m_code; + String m_message; +}; + +class SQLError : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<SQLError>, public ScriptWrappable { +public: + static PassRefPtrWillBeRawPtr<SQLError> create(const SQLErrorData& data) { return adoptRefWillBeNoop(new SQLError(data)); } + void trace(Visitor*) { } + + unsigned code() const { return m_data.code(); } + String message() const { return m_data.message(); } + enum SQLErrorCode { UNKNOWN_ERR = 0, DATABASE_ERR = 1, @@ -62,18 +82,16 @@ public: }; static const char quotaExceededErrorMessage[]; - static const char syntaxErrorMessage[]; static const char unknownErrorMessage[]; static const char versionErrorMessage[]; private: - SQLError(unsigned code, const String& message) : m_code(code), m_message(message.isolatedCopy()) + explicit SQLError(const SQLErrorData& data) : m_data(data) { ScriptWrappable::init(this); } - unsigned m_code; - String m_message; + const SQLErrorData m_data; }; } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.idl index daaed712dc1..b084c977a86 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLError.idl @@ -27,6 +27,7 @@ */ [ + WillBeGarbageCollected, NoInterfaceObject ] interface SQLError { readonly attribute unsigned long code; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.cpp index 77c70c70ac8..bcd07fb170a 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.cpp @@ -31,18 +31,25 @@ #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" +#include "platform/heap/Handle.h" namespace WebCore { SQLResultSet::SQLResultSet() : m_rows(SQLResultSetRowList::create()) , m_insertId(0) - , m_insertIdSet(false) , m_rowsAffected(0) + , m_insertIdSet(false) + , m_isValid(false) { ScriptWrappable::init(this); } +void SQLResultSet::trace(Visitor* visitor) +{ + visitor->trace(m_rows); +} + int64_t SQLResultSet::insertId(ExceptionState& exceptionState) const { // 4.11.4 - Return the id of the last row inserted as a result of the query @@ -50,7 +57,7 @@ int64_t SQLResultSet::insertId(ExceptionState& exceptionState) const if (m_insertIdSet) return m_insertId; - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, "The query didn't result in any rows being added."); return -1; } @@ -75,6 +82,7 @@ void SQLResultSet::setInsertId(int64_t id) void SQLResultSet::setRowsAffected(int count) { m_rowsAffected = count; + m_isValid = true; } } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.h index 3c5a9747454..79b9c49c177 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.h @@ -38,9 +38,10 @@ namespace WebCore { class ExceptionState; -class SQLResultSet : public ThreadSafeRefCounted<SQLResultSet>, public ScriptWrappable { +class SQLResultSet : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<SQLResultSet>, public ScriptWrappable { public: - static PassRefPtr<SQLResultSet> create() { return adoptRef(new SQLResultSet); } + static PassRefPtrWillBeRawPtr<SQLResultSet> create() { return adoptRefWillBeNoop(new SQLResultSet); } + void trace(Visitor*); SQLResultSetRowList* rows() const; @@ -50,14 +51,16 @@ public: // For internal (non-JS) use void setInsertId(int64_t); void setRowsAffected(int); + bool isValid() { return m_isValid; } private: SQLResultSet(); - RefPtr<SQLResultSetRowList> m_rows; + RefPtrWillBeMember<SQLResultSetRowList> m_rows; int64_t m_insertId; - bool m_insertIdSet; int m_rowsAffected; + bool m_insertIdSet; + bool m_isValid; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.idl index 94526873151..8b61f249112 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSet.idl @@ -27,7 +27,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + WillBeGarbageCollected, ] interface SQLResultSet { readonly attribute SQLResultSetRowList rows; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSetRowList.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSetRowList.h index 74565aec240..ea0a3af7309 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSetRowList.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSetRowList.h @@ -31,14 +31,16 @@ #include "bindings/v8/ScriptWrappable.h" #include "modules/webdatabase/sqlite/SQLValue.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class SQLResultSetRowList : public RefCounted<SQLResultSetRowList>, public ScriptWrappable { +class SQLResultSetRowList : public RefCountedWillBeGarbageCollectedFinalized<SQLResultSetRowList>, public ScriptWrappable { public: - static PassRefPtr<SQLResultSetRowList> create() { return adoptRef(new SQLResultSetRowList); } + static PassRefPtrWillBeRawPtr<SQLResultSetRowList> create() { return adoptRefWillBeNoop(new SQLResultSetRowList); } + void trace(Visitor*) { } const Vector<String>& columnNames() const { return m_columns; } const Vector<SQLValue>& values() const { return m_result; } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSetRowList.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSetRowList.idl index 05dd04b12d5..14fd5cccab4 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSetRowList.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLResultSetRowList.idl @@ -27,8 +27,9 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + WillBeGarbageCollected, ] interface SQLResultSetRowList { readonly attribute unsigned long length; - [Custom] any item(unsigned long index); + [Custom] object item(unsigned long index); }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatement.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatement.cpp index 0d77191d5ff..0847f439392 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatement.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatement.cpp @@ -42,10 +42,10 @@ namespace WebCore { -PassOwnPtr<SQLStatement> SQLStatement::create(Database* database, +PassOwnPtrWillBeRawPtr<SQLStatement> SQLStatement::create(Database* database, PassOwnPtr<SQLStatementCallback> callback, PassOwnPtr<SQLStatementErrorCallback> errorCallback) { - return adoptPtr(new SQLStatement(database, callback, errorCallback)); + return adoptPtrWillBeNoop(new SQLStatement(database, callback, errorCallback)); } SQLStatement::SQLStatement(Database* database, PassOwnPtr<SQLStatementCallback> callback, @@ -55,6 +55,14 @@ SQLStatement::SQLStatement(Database* database, PassOwnPtr<SQLStatementCallback> { } +void SQLStatement::trace(Visitor* visitor) +{ + visitor->trace(m_backend); + visitor->trace(m_statementCallbackWrapper); + visitor->trace(m_statementErrorCallbackWrapper); + AbstractSQLStatement::trace(visitor); +} + void SQLStatement::setBackend(AbstractSQLStatementBackend* backend) { m_backend = backend; @@ -79,15 +87,17 @@ bool SQLStatement::performCallback(SQLTransaction* transaction) OwnPtr<SQLStatementCallback> callback = m_statementCallbackWrapper.unwrap(); OwnPtr<SQLStatementErrorCallback> errorCallback = m_statementErrorCallbackWrapper.unwrap(); - RefPtr<SQLError> error = m_backend->sqlError(); + SQLErrorData* error = m_backend->sqlError(); // Call the appropriate statement callback and track if it resulted in an error, // because then we need to jump to the transaction error callback. if (error) { - if (errorCallback) - callbackError = errorCallback->handleEvent(transaction, error.get()); + if (errorCallback) { + RefPtrWillBeRawPtr<SQLError> sqlError = SQLError::create(*error); + callbackError = errorCallback->handleEvent(transaction, sqlError.get()); + } } else if (callback) { - RefPtr<SQLResultSet> resultSet = m_backend->sqlResultSet(); + RefPtrWillBeRawPtr<SQLResultSet> resultSet = m_backend->sqlResultSet(); callbackError = !callback->handleEvent(transaction, resultSet.get()); } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatement.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatement.h index 89c8f79c243..f997c71f727 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatement.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatement.h @@ -45,17 +45,18 @@ class SQLStatementCallback; class SQLStatementErrorCallback; class SQLTransaction; -class SQLStatement : public AbstractSQLStatement { +class SQLStatement FINAL : public AbstractSQLStatement { public: - static PassOwnPtr<SQLStatement> create(Database*, + static PassOwnPtrWillBeRawPtr<SQLStatement> create(Database*, PassOwnPtr<SQLStatementCallback>, PassOwnPtr<SQLStatementErrorCallback>); + virtual void trace(Visitor*) OVERRIDE; bool performCallback(SQLTransaction*); - virtual void setBackend(AbstractSQLStatementBackend*); + virtual void setBackend(AbstractSQLStatementBackend*) OVERRIDE; - virtual bool hasCallback(); - virtual bool hasErrorCallback(); + virtual bool hasCallback() OVERRIDE; + virtual bool hasErrorCallback() OVERRIDE; private: SQLStatement(Database*, PassOwnPtr<SQLStatementCallback>, PassOwnPtr<SQLStatementErrorCallback>); @@ -63,7 +64,7 @@ private: // The AbstractSQLStatementBackend owns the SQLStatement. Hence, the backend is // guaranteed to be outlive the SQLStatement, and it is safe for us to refer // to the backend using a raw pointer here. - AbstractSQLStatementBackend* m_backend; + RawPtrWillBeMember<AbstractSQLStatementBackend> m_backend; SQLCallbackWrapper<SQLStatementCallback> m_statementCallbackWrapper; SQLCallbackWrapper<SQLStatementErrorCallback> m_statementErrorCallbackWrapper; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementBackend.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementBackend.cpp index 266be180365..239f404fa5f 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementBackend.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementBackend.cpp @@ -71,42 +71,50 @@ namespace WebCore { -PassRefPtr<SQLStatementBackend> SQLStatementBackend::create(PassOwnPtr<AbstractSQLStatement> frontend, +PassRefPtrWillBeRawPtr<SQLStatementBackend> SQLStatementBackend::create(PassOwnPtrWillBeRawPtr<AbstractSQLStatement> frontend, const String& statement, const Vector<SQLValue>& arguments, int permissions) { - return adoptRef(new SQLStatementBackend(frontend, statement, arguments, permissions)); + return adoptRefWillBeNoop(new SQLStatementBackend(frontend, statement, arguments, permissions)); } -SQLStatementBackend::SQLStatementBackend(PassOwnPtr<AbstractSQLStatement> frontend, +SQLStatementBackend::SQLStatementBackend(PassOwnPtrWillBeRawPtr<AbstractSQLStatement> frontend, const String& statement, const Vector<SQLValue>& arguments, int permissions) : m_frontend(frontend) , m_statement(statement.isolatedCopy()) , m_arguments(arguments) , m_hasCallback(m_frontend->hasCallback()) , m_hasErrorCallback(m_frontend->hasErrorCallback()) + , m_resultSet(SQLResultSet::create()) , m_permissions(permissions) { m_frontend->setBackend(this); } +void SQLStatementBackend::trace(Visitor* visitor) +{ + visitor->trace(m_frontend); + visitor->trace(m_resultSet); + AbstractSQLStatementBackend::trace(visitor); +} + AbstractSQLStatement* SQLStatementBackend::frontend() { return m_frontend.get(); } -PassRefPtr<SQLError> SQLStatementBackend::sqlError() const +SQLErrorData* SQLStatementBackend::sqlError() const { - return m_error; + return m_error.get(); } -PassRefPtr<SQLResultSet> SQLStatementBackend::sqlResultSet() const +SQLResultSet* SQLStatementBackend::sqlResultSet() const { - return m_resultSet; + return m_resultSet->isValid() ? m_resultSet.get() : 0; } bool SQLStatementBackend::execute(DatabaseBackend* db) { - ASSERT(!m_resultSet); + ASSERT(!m_resultSet->isValid()); // If we're re-running this statement after a quota violation, we need to clear that error now clearFailureDueToQuota(); @@ -126,9 +134,9 @@ bool SQLStatementBackend::execute(DatabaseBackend* db) if (result != SQLResultOk) { WTF_LOG(StorageAPI, "Unable to verify correctness of statement %s - error %i (%s)", m_statement.ascii().data(), result, database->lastErrorMsg()); if (result == SQLResultInterrupt) - m_error = SQLError::create(SQLError::DATABASE_ERR, "could not prepare statement", result, "interrupted"); + m_error = SQLErrorData::create(SQLError::DATABASE_ERR, "could not prepare statement", result, "interrupted"); else - m_error = SQLError::create(SQLError::SYNTAX_ERR, "could not prepare statement", result, database->lastErrorMsg()); + m_error = SQLErrorData::create(SQLError::SYNTAX_ERR, "could not prepare statement", result, database->lastErrorMsg()); db->reportExecuteStatementResult(1, m_error->code(), result); return false; } @@ -137,7 +145,7 @@ bool SQLStatementBackend::execute(DatabaseBackend* db) // If this is the case, they might be trying to do something fishy or malicious if (statement.bindParameterCount() != m_arguments.size()) { WTF_LOG(StorageAPI, "Bind parameter count doesn't match number of question marks"); - m_error = SQLError::create(db->isInterrupted() ? SQLError::DATABASE_ERR : SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count"); + m_error = SQLErrorData::create(db->isInterrupted() ? SQLError::DATABASE_ERR : SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count"); db->reportExecuteStatementResult(2, m_error->code(), 0); return false; } @@ -152,18 +160,16 @@ bool SQLStatementBackend::execute(DatabaseBackend* db) if (result != SQLResultOk) { WTF_LOG(StorageAPI, "Failed to bind value index %i to statement for query '%s'", i + 1, m_statement.ascii().data()); db->reportExecuteStatementResult(3, SQLError::DATABASE_ERR, result); - m_error = SQLError::create(SQLError::DATABASE_ERR, "could not bind value", result, database->lastErrorMsg()); + m_error = SQLErrorData::create(SQLError::DATABASE_ERR, "could not bind value", result, database->lastErrorMsg()); return false; } } - RefPtr<SQLResultSet> resultSet = SQLResultSet::create(); - // Step so we can fetch the column names. result = statement.step(); if (result == SQLResultRow) { int columnCount = statement.columnCount(); - SQLResultSetRowList* rows = resultSet->rows(); + SQLResultSetRowList* rows = m_resultSet->rows(); for (int i = 0; i < columnCount; i++) rows->addColumn(statement.getColumnName(i)); @@ -177,55 +183,54 @@ bool SQLStatementBackend::execute(DatabaseBackend* db) if (result != SQLResultDone) { db->reportExecuteStatementResult(4, SQLError::DATABASE_ERR, result); - m_error = SQLError::create(SQLError::DATABASE_ERR, "could not iterate results", result, database->lastErrorMsg()); + m_error = SQLErrorData::create(SQLError::DATABASE_ERR, "could not iterate results", result, database->lastErrorMsg()); return false; } } else if (result == SQLResultDone) { // Didn't find anything, or was an insert if (db->lastActionWasInsert()) - resultSet->setInsertId(database->lastInsertRowID()); + m_resultSet->setInsertId(database->lastInsertRowID()); } else if (result == SQLResultFull) { // Return the Quota error - the delegate will be asked for more space and this statement might be re-run setFailureDueToQuota(db); return false; } else if (result == SQLResultConstraint) { db->reportExecuteStatementResult(6, SQLError::CONSTRAINT_ERR, result); - m_error = SQLError::create(SQLError::CONSTRAINT_ERR, "could not execute statement due to a constaint failure", result, database->lastErrorMsg()); + m_error = SQLErrorData::create(SQLError::CONSTRAINT_ERR, "could not execute statement due to a constaint failure", result, database->lastErrorMsg()); return false; } else { db->reportExecuteStatementResult(5, SQLError::DATABASE_ERR, result); - m_error = SQLError::create(SQLError::DATABASE_ERR, "could not execute statement", result, database->lastErrorMsg()); + m_error = SQLErrorData::create(SQLError::DATABASE_ERR, "could not execute statement", result, database->lastErrorMsg()); return false; } // FIXME: If the spec allows triggers, and we want to be "accurate" in a different way, we'd use // sqlite3_total_changes() here instead of sqlite3_changed, because that includes rows modified from within a trigger // For now, this seems sufficient - resultSet->setRowsAffected(database->lastChanges()); + m_resultSet->setRowsAffected(database->lastChanges()); - m_resultSet = resultSet; db->reportExecuteStatementResult(0, -1, 0); // OK return true; } void SQLStatementBackend::setVersionMismatchedError(DatabaseBackend* database) { - ASSERT(!m_error && !m_resultSet); + ASSERT(!m_error && !m_resultSet->isValid()); database->reportExecuteStatementResult(7, SQLError::VERSION_ERR, 0); - m_error = SQLError::create(SQLError::VERSION_ERR, "current version of the database and `oldVersion` argument do not match"); + m_error = SQLErrorData::create(SQLError::VERSION_ERR, "current version of the database and `oldVersion` argument do not match"); } void SQLStatementBackend::setFailureDueToQuota(DatabaseBackend* database) { - ASSERT(!m_error && !m_resultSet); + ASSERT(!m_error && !m_resultSet->isValid()); database->reportExecuteStatementResult(8, SQLError::QUOTA_ERR, 0); - m_error = SQLError::create(SQLError::QUOTA_ERR, "there was not enough remaining storage space, or the storage quota was reached and the user declined to allow more space"); + m_error = SQLErrorData::create(SQLError::QUOTA_ERR, "there was not enough remaining storage space, or the storage quota was reached and the user declined to allow more space"); } void SQLStatementBackend::clearFailureDueToQuota() { if (lastExecutionFailedDueToQuota()) - m_error = 0; + m_error = nullptr; } bool SQLStatementBackend::lastExecutionFailedDueToQuota() const diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementBackend.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementBackend.h index ae6d32d7ce2..b77f61cb7b6 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementBackend.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementBackend.h @@ -39,13 +39,14 @@ namespace WebCore { class AbstractSQLStatement; class DatabaseBackend; -class SQLError; +class SQLErrorData; class SQLTransactionBackend; -class SQLStatementBackend : public AbstractSQLStatementBackend { +class SQLStatementBackend FINAL : public AbstractSQLStatementBackend { public: - static PassRefPtr<SQLStatementBackend> create(PassOwnPtr<AbstractSQLStatement>, + static PassRefPtrWillBeRawPtr<SQLStatementBackend> create(PassOwnPtrWillBeRawPtr<AbstractSQLStatement>, const String& sqlStatement, const Vector<SQLValue>& arguments, int permissions); + virtual void trace(Visitor*) OVERRIDE; bool execute(DatabaseBackend*); bool lastExecutionFailedDueToQuota() const; @@ -56,24 +57,24 @@ public: void setVersionMismatchedError(DatabaseBackend*); AbstractSQLStatement* frontend(); - virtual PassRefPtr<SQLError> sqlError() const; - virtual PassRefPtr<SQLResultSet> sqlResultSet() const; + virtual SQLErrorData* sqlError() const OVERRIDE; + virtual SQLResultSet* sqlResultSet() const OVERRIDE; private: - SQLStatementBackend(PassOwnPtr<AbstractSQLStatement>, const String& statement, + SQLStatementBackend(PassOwnPtrWillBeRawPtr<AbstractSQLStatement>, const String& statement, const Vector<SQLValue>& arguments, int permissions); void setFailureDueToQuota(DatabaseBackend*); void clearFailureDueToQuota(); - OwnPtr<AbstractSQLStatement> m_frontend; + OwnPtrWillBeMember<AbstractSQLStatement> m_frontend; String m_statement; Vector<SQLValue> m_arguments; bool m_hasCallback; bool m_hasErrorCallback; - RefPtr<SQLError> m_error; - RefPtr<SQLResultSet> m_resultSet; + OwnPtr<SQLErrorData> m_error; + RefPtrWillBeMember<SQLResultSet> m_resultSet; int m_permissions; }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementSync.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementSync.cpp index f231bfb5aa3..612668848a1 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementSync.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementSync.cpp @@ -50,7 +50,7 @@ SQLStatementSync::SQLStatementSync(const String& statement, const Vector<SQLValu ASSERT(!m_statement.isEmpty()); } -PassRefPtr<SQLResultSet> SQLStatementSync::execute(DatabaseSync* db, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<SQLResultSet> SQLStatementSync::execute(DatabaseSync* db, ExceptionState& exceptionState) { db->setAuthorizerPermissions(m_permissions); @@ -60,20 +60,20 @@ PassRefPtr<SQLResultSet> SQLStatementSync::execute(DatabaseSync* db, ExceptionSt int result = statement.prepare(); if (result != SQLResultOk) { if (result == SQLResultInterrupt) - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Connection to the database interrupted."); else - exceptionState.throwDOMException(SyntaxError, SQLError::syntaxErrorMessage); + exceptionState.throwDOMException(SyntaxError, "Could not prepare statement."); db->setLastErrorMessage("could not prepare statement", result, database->lastErrorMsg()); - return 0; + return nullptr; } if (statement.bindParameterCount() != m_arguments.size()) { if (db->isInterrupted()) - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Connection to the database interrupted."); else - exceptionState.throwDOMException(SyntaxError, SQLError::syntaxErrorMessage); + exceptionState.throwDOMException(SyntaxError, "Number of '?'s in statement string (" + String::number(statement.bindParameterCount()) + ") does not match the arguments provided (" + String::number(m_arguments.size()) + ")."); db->setLastErrorMessage("number of '?'s in statement string does not match argument count"); - return 0; + return nullptr; } for (unsigned i = 0; i < m_arguments.size(); ++i) { @@ -81,17 +81,17 @@ PassRefPtr<SQLResultSet> SQLStatementSync::execute(DatabaseSync* db, ExceptionSt if (result == SQLResultFull) { exceptionState.throwDOMException(QuotaExceededError, SQLError::quotaExceededErrorMessage); db->setLastErrorMessage("there was not enough remaining storage space"); - return 0; + return nullptr; } if (result != SQLResultOk) { - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Could not bind value."); db->setLastErrorMessage("could not bind value", result, database->lastErrorMsg()); - return 0; + return nullptr; } } - RefPtr<SQLResultSet> resultSet = SQLResultSet::create(); + RefPtrWillBeRawPtr<SQLResultSet> resultSet = SQLResultSet::create(); // Step so we can fetch the column names. result = statement.step(); @@ -110,9 +110,9 @@ PassRefPtr<SQLResultSet> SQLStatementSync::execute(DatabaseSync* db, ExceptionSt } while (result == SQLResultRow); if (result != SQLResultDone) { - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Could not iterate results."); db->setLastErrorMessage("could not iterate results", result, database->lastErrorMsg()); - return 0; + return nullptr; } } else if (result == SQLResultDone) { // Didn't find anything, or was an insert. @@ -122,15 +122,15 @@ PassRefPtr<SQLResultSet> SQLStatementSync::execute(DatabaseSync* db, ExceptionSt // Quota error, the delegate will be asked for more space and this statement might be re-run. exceptionState.throwDOMException(QuotaExceededError, SQLError::quotaExceededErrorMessage); db->setLastErrorMessage("there was not enough remaining storage space"); - return 0; + return nullptr; } else if (result == SQLResultConstraint) { exceptionState.throwDOMException(ConstraintError, "A constraint was violated."); db->setLastErrorMessage("statement failed due to a constraint failure"); - return 0; + return nullptr; } else { - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Could not execute statement."); db->setLastErrorMessage("could not execute statement", result, database->lastErrorMsg()); - return 0; + return nullptr; } resultSet->setRowsAffected(database->lastChanges()); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementSync.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementSync.h index d8922125e00..b3a42f46232 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementSync.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLStatementSync.h @@ -33,6 +33,7 @@ #include "modules/webdatabase/sqlite/SQLValue.h" #include "modules/webdatabase/DatabaseBasicTypes.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/Vector.h" #include "wtf/text/WTFString.h" @@ -47,7 +48,7 @@ class SQLStatementSync { public: SQLStatementSync(const String& statement, const Vector<SQLValue>& arguments, int permissions); - PassRefPtr<SQLResultSet> execute(DatabaseSync*, ExceptionState&); + PassRefPtrWillBeRawPtr<SQLResultSet> execute(DatabaseSync*, ExceptionState&); private: String m_statement; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp index 03547a1b231..d27871e6458 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.cpp @@ -48,11 +48,11 @@ namespace WebCore { -PassRefPtr<SQLTransaction> SQLTransaction::create(Database* db, PassOwnPtr<SQLTransactionCallback> callback, +PassRefPtrWillBeRawPtr<SQLTransaction> SQLTransaction::create(Database* db, PassOwnPtr<SQLTransactionCallback> callback, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<SQLTransactionErrorCallback> errorCallback, bool readOnly) { - return adoptRef(new SQLTransaction(db, callback, successCallback, errorCallback, readOnly)); + return adoptRefWillBeNoop(new SQLTransaction(db, callback, successCallback, errorCallback, readOnly)); } SQLTransaction::SQLTransaction(Database* db, PassOwnPtr<SQLTransactionCallback> callback, @@ -69,6 +69,16 @@ SQLTransaction::SQLTransaction(Database* db, PassOwnPtr<SQLTransactionCallback> ScriptWrappable::init(this); } +void SQLTransaction::trace(Visitor* visitor) +{ + visitor->trace(m_database); + visitor->trace(m_backend); + visitor->trace(m_callbackWrapper); + visitor->trace(m_successCallbackWrapper); + visitor->trace(m_errorCallbackWrapper); + AbstractSQLTransaction::trace(visitor); +} + bool SQLTransaction::hasCallback() const { return m_callbackWrapper.hasCallback(); @@ -151,7 +161,7 @@ SQLTransactionState SQLTransaction::deliverTransactionCallback() SQLTransactionState nextState = SQLTransactionState::RunStatements; if (shouldDeliverErrorCallback) { m_database->reportStartTransactionResult(5, SQLError::UNKNOWN_ERR, 0); - m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "the SQLTransactionCallback was null or threw an exception"); + m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "the SQLTransactionCallback was null or threw an exception"); nextState = SQLTransactionState::DeliverTransactionErrorCallback; } m_database->reportStartTransactionResult(0, -1, 0); // OK @@ -168,13 +178,15 @@ SQLTransactionState SQLTransaction::deliverTransactionErrorCallback() // must be waiting in the idle state waiting for this state to finish. // Hence, it's thread safe to fetch the backend transactionError without // a lock. - if (!m_transactionError) - m_transactionError = m_backend->transactionError(); - + if (!m_transactionError) { + ASSERT(m_backend->transactionError()); + m_transactionError = SQLErrorData::create(*m_backend->transactionError()); + } ASSERT(m_transactionError); - errorCallback->handleEvent(m_transactionError.get()); + RefPtrWillBeRawPtr<SQLError> error = SQLError::create(*m_transactionError); + errorCallback->handleEvent(error.get()); - m_transactionError = 0; + m_transactionError = nullptr; } clearCallbackWrappers(); @@ -199,7 +211,7 @@ SQLTransactionState SQLTransaction::deliverStatementCallback() if (result) { m_database->reportCommitTransactionResult(2, SQLError::UNKNOWN_ERR, 0); - m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "the statement callback raised an exception or statement error callback did not return false"); + m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "the statement callback raised an exception or statement error callback did not return false"); return nextStateForTransactionError(); } return SQLTransactionState::RunStatements; @@ -253,8 +265,13 @@ void SQLTransaction::performPendingCallback() void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, PassOwnPtr<SQLStatementCallback> callback, PassOwnPtr<SQLStatementErrorCallback> callbackError, ExceptionState& exceptionState) { - if (!m_executeSqlAllowed || !m_database->opened()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + if (!m_executeSqlAllowed) { + exceptionState.throwDOMException(InvalidStateError, "SQL execution is disallowed."); + return; + } + + if (!m_database->opened()) { + exceptionState.throwDOMException(InvalidStateError, "The database has not been opened."); return; } @@ -264,7 +281,7 @@ void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValu else if (m_readOnly) permissions |= DatabaseAuthorizer::ReadOnlyMask; - OwnPtr<SQLStatement> statement = SQLStatement::create(m_database.get(), callback, callbackError); + OwnPtrWillBeRawPtr<SQLStatement> statement = SQLStatement::create(m_database.get(), callback, callbackError); m_backend->executeSQL(statement.release(), sqlStatement, arguments, permissions); } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.h index 0a4513bb319..0efe3c4e115 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.h @@ -34,6 +34,7 @@ #include "modules/webdatabase/SQLCallbackWrapper.h" #include "modules/webdatabase/SQLStatement.h" #include "modules/webdatabase/SQLTransactionStateMachine.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" @@ -42,7 +43,7 @@ namespace WebCore { class AbstractSQLTransactionBackend; class Database; class ExceptionState; -class SQLError; +class SQLErrorData; class SQLStatementCallback; class SQLStatementErrorCallback; class SQLTransactionCallback; @@ -50,11 +51,12 @@ class SQLTransactionErrorCallback; class SQLValue; class VoidCallback; -class SQLTransaction : public SQLTransactionStateMachine<SQLTransaction>, public AbstractSQLTransaction, public ScriptWrappable { +class SQLTransaction FINAL : public AbstractSQLTransaction, public SQLTransactionStateMachine<SQLTransaction>, public ScriptWrappable { public: - static PassRefPtr<SQLTransaction> create(Database*, PassOwnPtr<SQLTransactionCallback>, + static PassRefPtrWillBeRawPtr<SQLTransaction> create(Database*, PassOwnPtr<SQLTransactionCallback>, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<SQLTransactionErrorCallback>, bool readOnly); + virtual void trace(Visitor*) OVERRIDE; void performPendingCallback(); @@ -95,14 +97,14 @@ private: SQLTransactionState nextStateForTransactionError(); - RefPtr<Database> m_database; - RefPtr<AbstractSQLTransactionBackend> m_backend; + RefPtrWillBeMember<Database> m_database; + RefPtrWillBeMember<AbstractSQLTransactionBackend> m_backend; SQLCallbackWrapper<SQLTransactionCallback> m_callbackWrapper; SQLCallbackWrapper<VoidCallback> m_successCallbackWrapper; SQLCallbackWrapper<SQLTransactionErrorCallback> m_errorCallbackWrapper; bool m_executeSqlAllowed; - RefPtr<SQLError> m_transactionError; + OwnPtr<SQLErrorData> m_transactionError; bool m_readOnly; }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.idl index d506b75983b..cc8b2bb2180 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransaction.idl @@ -27,10 +27,11 @@ */ [ - NoInterfaceObject + WillBeGarbageCollected, + NoInterfaceObject, ] interface SQLTransaction { [Custom] void executeSql(DOMString sqlStatement, - ObjectArray arguments, + object[] arguments, optional SQLStatementCallback callback, optional SQLStatementErrorCallback errorCallback); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackend.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackend.cpp index 0bac058be62..3caab8f110d 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackend.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackend.cpp @@ -340,14 +340,18 @@ namespace WebCore { -PassRefPtr<SQLTransactionBackend> SQLTransactionBackend::create(DatabaseBackend* db, - PassRefPtr<AbstractSQLTransaction> frontend, PassRefPtr<SQLTransactionWrapper> wrapper, bool readOnly) +PassRefPtrWillBeRawPtr<SQLTransactionBackend> SQLTransactionBackend::create(DatabaseBackend* db, + PassRefPtrWillBeRawPtr<AbstractSQLTransaction> frontend, + PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper, + bool readOnly) { - return adoptRef(new SQLTransactionBackend(db, frontend, wrapper, readOnly)); + return adoptRefWillBeNoop(new SQLTransactionBackend(db, frontend, wrapper, readOnly)); } SQLTransactionBackend::SQLTransactionBackend(DatabaseBackend* db, - PassRefPtr<AbstractSQLTransaction> frontend, PassRefPtr<SQLTransactionWrapper> wrapper, bool readOnly) + PassRefPtrWillBeRawPtr<AbstractSQLTransaction> frontend, + PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper, + bool readOnly) : m_frontend(frontend) , m_database(db) , m_wrapper(wrapper) @@ -370,11 +374,21 @@ SQLTransactionBackend::~SQLTransactionBackend() ASSERT(!m_sqliteTransaction); } +void SQLTransactionBackend::trace(Visitor* visitor) +{ + visitor->trace(m_frontend); + visitor->trace(m_currentStatementBackend); + visitor->trace(m_database); + visitor->trace(m_wrapper); + visitor->trace(m_statementQueue); + AbstractSQLTransactionBackend::trace(visitor); +} + void SQLTransactionBackend::doCleanup() { if (!m_frontend) return; - m_frontend = 0; // Break the reference cycle. See comment about the life-cycle above. + m_frontend = nullptr; // Break the reference cycle. See comment about the life-cycle above. ASSERT(database()->databaseContext()->databaseThread()->isDatabaseThread()); @@ -417,7 +431,7 @@ void SQLTransactionBackend::doCleanup() // SQLTransactionBackend is guaranteed to not destruct until the frontend // is also destructing. - m_wrapper = 0; + m_wrapper = nullptr; } AbstractSQLStatement* SQLTransactionBackend::currentStatement() @@ -425,9 +439,9 @@ AbstractSQLStatement* SQLTransactionBackend::currentStatement() return m_currentStatementBackend->frontend(); } -PassRefPtr<SQLError> SQLTransactionBackend::transactionError() +SQLErrorData* SQLTransactionBackend::transactionError() { - return m_transactionError; + return m_transactionError.get(); } void SQLTransactionBackend::setShouldRetryCurrentStatement(bool shouldRetry) @@ -460,7 +474,7 @@ SQLTransactionBackend::StateFunction SQLTransactionBackend::stateFunctionFor(SQL return stateFunctions[static_cast<int>(state)]; } -void SQLTransactionBackend::enqueueStatementBackend(PassRefPtr<SQLStatementBackend> statementBackend) +void SQLTransactionBackend::enqueueStatementBackend(PassRefPtrWillBeRawPtr<SQLStatementBackend> statementBackend) { MutexLocker locker(m_statementMutex); m_statementQueue.append(statementBackend); @@ -512,12 +526,10 @@ void SQLTransactionBackend::performNextStep() runStateMachine(); } -void SQLTransactionBackend::executeSQL(PassOwnPtr<AbstractSQLStatement> statement, +void SQLTransactionBackend::executeSQL(PassOwnPtrWillBeRawPtr<AbstractSQLStatement> statement, const String& sqlStatement, const Vector<SQLValue>& arguments, int permissions) { - RefPtr<SQLStatementBackend> statementBackend; - statementBackend = SQLStatementBackend::create(statement, sqlStatement, arguments, permissions); - enqueueStatementBackend(statementBackend); + enqueueStatementBackend(SQLStatementBackend::create(statement, sqlStatement, arguments, permissions)); } void SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown() @@ -567,7 +579,7 @@ SQLTransactionState SQLTransactionBackend::openTransactionAndPreflight() if (!m_sqliteTransaction->inProgress()) { ASSERT(!m_database->sqliteDatabase().transactionInProgress()); m_database->reportStartTransactionResult(2, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError()); - m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to begin transaction", + m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to begin transaction", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); m_sqliteTransaction.clear(); return nextStateForTransactionError(); @@ -579,7 +591,7 @@ SQLTransactionState SQLTransactionBackend::openTransactionAndPreflight() String actualVersion; if (!m_database->getActualVersionForTransaction(actualVersion)) { m_database->reportStartTransactionResult(3, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError()); - m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to read version", + m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to read version", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); m_database->disableAuthorizer(); m_sqliteTransaction.clear(); @@ -593,10 +605,11 @@ SQLTransactionState SQLTransactionBackend::openTransactionAndPreflight() m_database->disableAuthorizer(); m_sqliteTransaction.clear(); m_database->enableAuthorizer(); - m_transactionError = m_wrapper->sqlError(); - if (!m_transactionError) { + if (m_wrapper->sqlError()) { + m_transactionError = SQLErrorData::create(*m_wrapper->sqlError()); + } else { m_database->reportStartTransactionResult(4, SQLError::UNKNOWN_ERR, 0); - m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction preflight"); + m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction preflight"); } return nextStateForTransactionError(); } @@ -645,7 +658,7 @@ SQLTransactionState SQLTransactionBackend::runStatements() void SQLTransactionBackend::getNextStatement() { - m_currentStatementBackend = 0; + m_currentStatementBackend = nullptr; MutexLocker locker(m_statementMutex); if (!m_statementQueue.isEmpty()) @@ -693,10 +706,11 @@ SQLTransactionState SQLTransactionBackend::nextStateForCurrentStatementError() if (m_currentStatementBackend->hasStatementErrorCallback() && !m_sqliteTransaction->wasRolledBackBySqlite()) return SQLTransactionState::DeliverStatementCallback; - m_transactionError = m_currentStatementBackend->sqlError(); - if (!m_transactionError) { + if (m_currentStatementBackend->sqlError()) { + m_transactionError = SQLErrorData::create(*m_currentStatementBackend->sqlError()); + } else { m_database->reportCommitTransactionResult(1, SQLError::DATABASE_ERR, 0); - m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "the statement failed to execute"); + m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "the statement failed to execute"); } return nextStateForTransactionError(); } @@ -707,10 +721,11 @@ SQLTransactionState SQLTransactionBackend::postflightAndCommit() // Spec 4.3.2.7: Perform postflight steps, jumping to the error callback if they fail. if (m_wrapper && !m_wrapper->performPostflight(this)) { - m_transactionError = m_wrapper->sqlError(); - if (!m_transactionError) { + if (m_wrapper->sqlError()) { + m_transactionError = SQLErrorData::create(*m_wrapper->sqlError()); + } else { m_database->reportCommitTransactionResult(3, SQLError::UNKNOWN_ERR, 0); - m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight"); + m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight"); } return nextStateForTransactionError(); } @@ -727,7 +742,7 @@ SQLTransactionState SQLTransactionBackend::postflightAndCommit() if (m_wrapper) m_wrapper->handleCommitFailedAfterPostflight(this); m_database->reportCommitTransactionResult(4, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError()); - m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "unable to commit transaction", + m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to commit transaction", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); return nextStateForTransactionError(); } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackend.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackend.h index 6c902f1139e..0e1ce415cfd 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackend.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackend.h @@ -32,6 +32,7 @@ #include "modules/webdatabase/AbstractSQLTransactionBackend.h" #include "modules/webdatabase/DatabaseBasicTypes.h" #include "modules/webdatabase/SQLTransactionStateMachine.h" +#include "platform/heap/Handle.h" #include "wtf/Deque.h" #include "wtf/Forward.h" #include "wtf/ThreadingPrimitives.h" @@ -41,27 +42,29 @@ namespace WebCore { class AbstractSQLTransaction; class DatabaseBackend; -class SQLError; +class SQLErrorData; class SQLiteTransaction; class SQLStatementBackend; class SQLTransactionBackend; class SQLValue; -class SQLTransactionWrapper : public ThreadSafeRefCounted<SQLTransactionWrapper> { +class SQLTransactionWrapper : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<SQLTransactionWrapper> { public: virtual ~SQLTransactionWrapper() { } + virtual void trace(Visitor*) { } virtual bool performPreflight(SQLTransactionBackend*) = 0; virtual bool performPostflight(SQLTransactionBackend*) = 0; - virtual SQLError* sqlError() const = 0; + virtual SQLErrorData* sqlError() const = 0; virtual void handleCommitFailedAfterPostflight(SQLTransactionBackend*) = 0; }; -class SQLTransactionBackend : public SQLTransactionStateMachine<SQLTransactionBackend>, public AbstractSQLTransactionBackend { +class SQLTransactionBackend FINAL : public AbstractSQLTransactionBackend, public SQLTransactionStateMachine<SQLTransactionBackend> { public: - static PassRefPtr<SQLTransactionBackend> create(DatabaseBackend*, - PassRefPtr<AbstractSQLTransaction>, PassRefPtr<SQLTransactionWrapper>, bool readOnly); + static PassRefPtrWillBeRawPtr<SQLTransactionBackend> create(DatabaseBackend*, + PassRefPtrWillBeRawPtr<AbstractSQLTransaction>, PassRefPtrWillBeRawPtr<SQLTransactionWrapper>, bool readOnly); virtual ~SQLTransactionBackend(); + virtual void trace(Visitor*) OVERRIDE; void lockAcquired(); void performNextStep(); @@ -71,20 +74,20 @@ public: void notifyDatabaseThreadIsShuttingDown(); private: - SQLTransactionBackend(DatabaseBackend*, PassRefPtr<AbstractSQLTransaction>, - PassRefPtr<SQLTransactionWrapper>, bool readOnly); + SQLTransactionBackend(DatabaseBackend*, PassRefPtrWillBeRawPtr<AbstractSQLTransaction>, + PassRefPtrWillBeRawPtr<SQLTransactionWrapper>, bool readOnly); // APIs called from the frontend published via AbstractSQLTransactionBackend: virtual void requestTransitToState(SQLTransactionState) OVERRIDE; - virtual PassRefPtr<SQLError> transactionError() OVERRIDE; + virtual SQLErrorData* transactionError() OVERRIDE; virtual AbstractSQLStatement* currentStatement() OVERRIDE; virtual void setShouldRetryCurrentStatement(bool) OVERRIDE; - virtual void executeSQL(PassOwnPtr<AbstractSQLStatement>, const String& statement, + virtual void executeSQL(PassOwnPtrWillBeRawPtr<AbstractSQLStatement>, const String& statement, const Vector<SQLValue>& arguments, int permissions) OVERRIDE; void doCleanup(); - void enqueueStatementBackend(PassRefPtr<SQLStatementBackend>); + void enqueueStatementBackend(PassRefPtrWillBeRawPtr<SQLStatementBackend>); // State Machine functions: virtual StateFunction stateFunctionFor(SQLTransactionState) OVERRIDE; @@ -107,12 +110,12 @@ private: void getNextStatement(); - RefPtr<AbstractSQLTransaction> m_frontend; // Has a reference cycle, and will break in doCleanup(). - RefPtr<SQLStatementBackend> m_currentStatementBackend; + RefPtrWillBeMember<AbstractSQLTransaction> m_frontend; // Has a reference cycle, and will break in doCleanup(). + RefPtrWillBeMember<SQLStatementBackend> m_currentStatementBackend; - RefPtr<DatabaseBackend> m_database; - RefPtr<SQLTransactionWrapper> m_wrapper; - RefPtr<SQLError> m_transactionError; + RefPtrWillBeMember<DatabaseBackend> m_database; + RefPtrWillBeMember<SQLTransactionWrapper> m_wrapper; + OwnPtr<SQLErrorData> m_transactionError; bool m_hasCallback; bool m_hasSuccessCallback; @@ -124,7 +127,7 @@ private: bool m_hasVersionMismatch; Mutex m_statementMutex; - Deque<RefPtr<SQLStatementBackend> > m_statementQueue; + Deque<RefPtrWillBeMember<SQLStatementBackend> > m_statementQueue; OwnPtr<SQLiteTransaction> m_sqliteTransaction; }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackendSync.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackendSync.cpp index 8ea31554029..4b1fd6d6b60 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackendSync.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackendSync.cpp @@ -62,14 +62,28 @@ SQLTransactionBackendSync::SQLTransactionBackendSync(DatabaseSync* db, PassOwnPt ASSERT(m_database->executionContext()->isContextThread()); } -SQLTransactionBackendSync::~SQLTransactionBackendSync() +void SQLTransactionBackendSync::rollbackIfInProgress() { - ASSERT(m_database->executionContext()->isContextThread()); + ASSERT(!m_database->executionContext() || m_database->executionContext()->isContextThread()); if (m_sqliteTransaction && m_sqliteTransaction->inProgress()) rollback(); } -PassRefPtr<SQLResultSet> SQLTransactionBackendSync::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, ExceptionState& exceptionState) +SQLTransactionBackendSync::~SQLTransactionBackendSync() +{ +#if ENABLE(OILPAN) + ASSERT(!m_sqliteTransaction || !m_sqliteTransaction->inProgress()); +#else + rollbackIfInProgress(); +#endif +} + +void SQLTransactionBackendSync::trace(Visitor* visitor) +{ + visitor->trace(m_database); +} + +PassRefPtrWillBeRawPtr<SQLResultSet> SQLTransactionBackendSync::executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, ExceptionState& exceptionState) { ASSERT(m_database->executionContext()->isContextThread()); @@ -78,17 +92,17 @@ PassRefPtr<SQLResultSet> SQLTransactionBackendSync::executeSQL(const String& sql if (!m_database->opened()) { m_database->setLastErrorMessage("cannot executeSQL because the database is not open"); exceptionState.throwDOMException(UnknownError, SQLError::unknownErrorMessage); - return 0; + return nullptr; } if (m_hasVersionMismatch) { m_database->setLastErrorMessage("cannot executeSQL because there is a version mismatch"); exceptionState.throwDOMException(VersionError, SQLError::versionErrorMessage); - return 0; + return nullptr; } if (sqlStatement.isEmpty()) - return 0; + return nullptr; int permissions = DatabaseAuthorizer::ReadWriteMask; if (!m_database->databaseContext()->allowDatabaseAccess()) @@ -100,13 +114,13 @@ PassRefPtr<SQLResultSet> SQLTransactionBackendSync::executeSQL(const String& sql m_database->resetAuthorizer(); bool retryStatement = true; - RefPtr<SQLResultSet> resultSet; + RefPtrWillBeRawPtr<SQLResultSet> resultSet; while (retryStatement) { retryStatement = false; resultSet = statement.execute(m_database.get(), exceptionState); if (!resultSet) { if (m_sqliteTransaction->wasRolledBackBySqlite()) - return 0; + return nullptr; if (exceptionState.code() == QuotaExceededError) { if (m_transactionClient->didExceedQuota(database())) { @@ -114,7 +128,7 @@ PassRefPtr<SQLResultSet> SQLTransactionBackendSync::executeSQL(const String& sql retryStatement = true; } else { m_database->setLastErrorMessage("there was not enough remaining storage space"); - return 0; + return nullptr; } } } @@ -157,7 +171,7 @@ void SQLTransactionBackendSync::begin(ExceptionState& exceptionState) m_database->setLastErrorMessage("unable to begin transaction", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); m_sqliteTransaction.clear(); - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Unable to begin transaction."); return; } @@ -170,7 +184,7 @@ void SQLTransactionBackendSync::begin(ExceptionState& exceptionState) m_database->setLastErrorMessage("unable to read version", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); rollback(); - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Unable to read version."); return; } m_hasVersionMismatch = !m_database->expectedVersion().isEmpty() && (m_database->expectedVersion() != actualVersion); @@ -212,7 +226,7 @@ void SQLTransactionBackendSync::commit(ExceptionState& exceptionState) m_database->reportCommitTransactionResult(2, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError()); m_database->setLastErrorMessage("unable to commit transaction", m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); - exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); + exceptionState.throwDOMException(SQLDatabaseError, "Unable to commit transaction."); return; } @@ -229,9 +243,10 @@ void SQLTransactionBackendSync::commit(ExceptionState& exceptionState) m_database->reportCommitTransactionResult(0, -1, 0); // OK } +// This can be called during GC. Do not allocate new on-heap objects. void SQLTransactionBackendSync::rollback() { - ASSERT(m_database->executionContext()->isContextThread()); + ASSERT(!m_database->executionContext() || m_database->executionContext()->isContextThread()); m_database->disableAuthorizer(); if (m_sqliteTransaction) { m_sqliteTransaction->rollback(); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackendSync.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackendSync.h index 43b1d787280..2365a780205 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackendSync.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionBackendSync.h @@ -33,6 +33,7 @@ #define SQLTransactionBackendSync_h #include "modules/webdatabase/DatabaseBasicTypes.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/RefCounted.h" #include "wtf/Vector.h" @@ -49,24 +50,25 @@ class SQLiteTransaction; class ExceptionState; // Instances of this class should be created and used only on the worker's context thread. -class SQLTransactionBackendSync : public RefCounted<SQLTransactionBackendSync> { +class SQLTransactionBackendSync : public RefCountedWillBeGarbageCollectedFinalized<SQLTransactionBackendSync> { public: ~SQLTransactionBackendSync(); + void trace(Visitor*); - PassRefPtr<SQLResultSet> executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, ExceptionState&); + PassRefPtrWillBeRawPtr<SQLResultSet> executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, ExceptionState&); DatabaseSync* database() { return m_database.get(); } - bool isReadOnly() const { return m_readOnly; } void begin(ExceptionState&); void execute(ExceptionState&); void commit(ExceptionState&); void rollback(); + void rollbackIfInProgress(); private: SQLTransactionBackendSync(DatabaseSync*, PassOwnPtr<SQLTransactionSyncCallback>, bool readOnly); - RefPtr<DatabaseSync> m_database; + RefPtrWillBeMember<DatabaseSync> m_database; OwnPtr<SQLTransactionSyncCallback> m_callback; bool m_readOnly; bool m_hasVersionMismatch; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionClient.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionClient.cpp index 4300fc4cf16..80f734a7140 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionClient.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionClient.cpp @@ -55,7 +55,7 @@ void SQLTransactionClient::didCommitWriteTransaction(DatabaseBackendBase* databa { ExecutionContext* executionContext = database->databaseContext()->executionContext(); if (!executionContext->isContextThread()) { - executionContext->postTask(bind(&databaseModified, PassRefPtr<DatabaseBackendBase>(database))); + executionContext->postTask(bind(&databaseModified, PassRefPtrWillBeRawPtr<DatabaseBackendBase>(database))); return; } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCoordinator.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCoordinator.cpp index 7d9cfdf69ba..75b59a8796a 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCoordinator.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCoordinator.cpp @@ -49,12 +49,17 @@ SQLTransactionCoordinator::SQLTransactionCoordinator() { } +void SQLTransactionCoordinator::trace(Visitor* visitor) +{ + visitor->trace(m_coordinationInfoMap); +} + void SQLTransactionCoordinator::processPendingTransactions(CoordinationInfo& info) { if (info.activeWriteTransaction || info.pendingTransactions.isEmpty()) return; - RefPtr<SQLTransactionBackend> firstPendingTransaction = info.pendingTransactions.first(); + RefPtrWillBeRawPtr<SQLTransactionBackend> firstPendingTransaction = info.pendingTransactions.first(); if (firstPendingTransaction->isReadOnly()) { do { firstPendingTransaction = info.pendingTransactions.takeFirst(); @@ -74,15 +79,18 @@ void SQLTransactionCoordinator::acquireLock(SQLTransactionBackend* transaction) String dbIdentifier = getDatabaseIdentifier(transaction); - CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier); + CoordinationInfoHeapMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier); if (coordinationInfoIterator == m_coordinationInfoMap.end()) { // No pending transactions for this DB - coordinationInfoIterator = m_coordinationInfoMap.add(dbIdentifier, CoordinationInfo()).iterator; + CoordinationInfo& info = m_coordinationInfoMap.add(dbIdentifier, CoordinationInfo()).storedValue->value; + info.pendingTransactions.append(transaction); + processPendingTransactions(info); + } else { + CoordinationInfo& info = coordinationInfoIterator->value; + info.pendingTransactions.append(transaction); + processPendingTransactions(info); } - CoordinationInfo& info = coordinationInfoIterator->value; - info.pendingTransactions.append(transaction); - processPendingTransactions(info); } void SQLTransactionCoordinator::releaseLock(SQLTransactionBackend* transaction) @@ -92,7 +100,7 @@ void SQLTransactionCoordinator::releaseLock(SQLTransactionBackend* transaction) String dbIdentifier = getDatabaseIdentifier(transaction); - CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier); + CoordinationInfoHeapMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier); ASSERT_WITH_SECURITY_IMPLICATION(coordinationInfoIterator != m_coordinationInfoMap.end()); CoordinationInfo& info = coordinationInfoIterator->value; @@ -101,7 +109,7 @@ void SQLTransactionCoordinator::releaseLock(SQLTransactionBackend* transaction) info.activeReadTransactions.remove(transaction); } else { ASSERT(info.activeWriteTransaction == transaction); - info.activeWriteTransaction = 0; + info.activeWriteTransaction = nullptr; } processPendingTransactions(info); @@ -114,7 +122,7 @@ void SQLTransactionCoordinator::shutdown() m_isShuttingDown = true; // Notify all transactions in progress that the database thread is shutting down - for (CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.begin(); + for (CoordinationInfoHeapMap::iterator coordinationInfoIterator = m_coordinationInfoMap.begin(); coordinationInfoIterator != m_coordinationInfoMap.end(); ++coordinationInfoIterator) { CoordinationInfo& info = coordinationInfoIterator->value; @@ -123,7 +131,7 @@ void SQLTransactionCoordinator::shutdown() // transaction is interrupted?" at the top of SQLTransactionBackend.cpp. if (info.activeWriteTransaction) info.activeWriteTransaction->notifyDatabaseThreadIsShuttingDown(); - for (HashSet<RefPtr<SQLTransactionBackend> >::iterator activeReadTransactionsIterator = + for (WillBeHeapHashSet<RefPtrWillBeMember<SQLTransactionBackend> >::iterator activeReadTransactionsIterator = info.activeReadTransactions.begin(); activeReadTransactionsIterator != info.activeReadTransactions.end(); ++activeReadTransactionsIterator) { @@ -134,7 +142,7 @@ void SQLTransactionCoordinator::shutdown() // Transaction phase 3 cleanup. See comment on "What happens if a // transaction is interrupted?" at the top of SQLTransactionBackend.cpp. while (!info.pendingTransactions.isEmpty()) { - RefPtr<SQLTransactionBackend> transaction = info.pendingTransactions.first(); + RefPtrWillBeRawPtr<SQLTransactionBackend> transaction = info.pendingTransactions.first(); transaction->notifyDatabaseThreadIsShuttingDown(); } } diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCoordinator.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCoordinator.h index 93ba4cda0aa..d5ef36209b4 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCoordinator.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionCoordinator.h @@ -32,6 +32,7 @@ #ifndef SQLTransactionCoordinator_h #define SQLTransactionCoordinator_h +#include "platform/heap/Handle.h" #include "wtf/Deque.h" #include "wtf/HashMap.h" #include "wtf/HashSet.h" @@ -42,23 +43,33 @@ namespace WebCore { class SQLTransactionBackend; -class SQLTransactionCoordinator { - WTF_MAKE_NONCOPYABLE(SQLTransactionCoordinator); WTF_MAKE_FAST_ALLOCATED; +class SQLTransactionCoordinator : public NoBaseWillBeGarbageCollected<SQLTransactionCoordinator> { + WTF_MAKE_NONCOPYABLE(SQLTransactionCoordinator); + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: SQLTransactionCoordinator(); + void trace(Visitor*); void acquireLock(SQLTransactionBackend*); void releaseLock(SQLTransactionBackend*); void shutdown(); private: - typedef Deque<RefPtr<SQLTransactionBackend> > TransactionsQueue; + typedef Deque<RefPtrWillBeMember<SQLTransactionBackend> > TransactionsQueue; struct CoordinationInfo { TransactionsQueue pendingTransactions; - HashSet<RefPtr<SQLTransactionBackend> > activeReadTransactions; - RefPtr<SQLTransactionBackend> activeWriteTransaction; + WillBeHeapHashSet<RefPtrWillBeMember<SQLTransactionBackend> > activeReadTransactions; + RefPtrWillBeMember<SQLTransactionBackend> activeWriteTransaction; + + void trace(Visitor* visitor) + { + visitor->trace(pendingTransactions); + visitor->trace(activeReadTransactions); + visitor->trace(activeWriteTransaction); + } + ALLOW_ONLY_INLINE_ALLOCATION(); }; // Maps database names to information about pending transactions - typedef HashMap<String, CoordinationInfo> CoordinationInfoMap; - CoordinationInfoMap m_coordinationInfoMap; + typedef WillBeHeapHashMap<String, CoordinationInfo> CoordinationInfoHeapMap; + CoordinationInfoHeapMap m_coordinationInfoMap; bool m_isShuttingDown; void processPendingTransactions(CoordinationInfo&); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.cpp index 677d6c5d3f2..64125beabc5 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.cpp @@ -38,9 +38,9 @@ namespace WebCore { -PassRefPtr<SQLTransactionSync> SQLTransactionSync::create(DatabaseSync* db, PassOwnPtr<SQLTransactionSyncCallback> callback, bool readOnly) +PassRefPtrWillBeRawPtr<SQLTransactionSync> SQLTransactionSync::create(DatabaseSync* db, PassOwnPtr<SQLTransactionSyncCallback> callback, bool readOnly) { - return adoptRef(new SQLTransactionSync(db, callback, readOnly)); + return adoptRefWillBeNoop(new SQLTransactionSync(db, callback, readOnly)); } SQLTransactionSync::SQLTransactionSync(DatabaseSync* db, PassOwnPtr<SQLTransactionSyncCallback> callback, bool readOnly) @@ -48,6 +48,7 @@ SQLTransactionSync::SQLTransactionSync(DatabaseSync* db, PassOwnPtr<SQLTransacti { ASSERT(m_database->executionContext()->isContextThread()); ScriptWrappable::init(this); + db->observeTransaction(*this); } SQLTransactionSync* SQLTransactionSync::from(SQLTransactionBackendSync* backend) diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.h b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.h index 62aa5d57060..a77e5e472b3 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.h @@ -38,9 +38,9 @@ namespace WebCore { // Instances of this class should be created and used only on the worker's context thread. -class SQLTransactionSync : public SQLTransactionBackendSync, public ScriptWrappable { +class SQLTransactionSync FINAL : public SQLTransactionBackendSync, public ScriptWrappable { public: - static PassRefPtr<SQLTransactionSync> create(DatabaseSync*, PassOwnPtr<SQLTransactionSyncCallback>, bool readOnly = false); + static PassRefPtrWillBeRawPtr<SQLTransactionSync> create(DatabaseSync*, PassOwnPtr<SQLTransactionSyncCallback>, bool readOnly = false); static SQLTransactionSync* from(SQLTransactionBackendSync*); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.idl index 732dba36bb5..7cbb0e65ceb 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/SQLTransactionSync.idl @@ -29,7 +29,8 @@ */ [ - NoInterfaceObject + WillBeGarbageCollected, + NoInterfaceObject, ] interface SQLTransactionSync { - [Custom] SQLResultSet executeSql(DOMString sqlStatement, ObjectArray arguments); + [RaisesException, Custom] SQLResultSet executeSql(DOMString sqlStatement, object[] arguments); }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/WindowWebDatabase.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/WindowWebDatabase.idl index 5441c1f8602..0d18b0e96b5 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/WindowWebDatabase.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/WindowWebDatabase.idl @@ -25,8 +25,8 @@ */ [ - ImplementedAs=DOMWindowWebDatabase + ImplementedAs=DOMWindowWebDatabase, + RuntimeEnabled=Database, ] partial interface Window { - [RuntimeEnabled=Database, MeasureAs=OpenWebDatabase, PerWorldBindings, ActivityLogging=ForIsolatedWorlds, RaisesException] Database openDatabase(DOMString name, DOMString version, DOMString displayName, unsigned long estimatedSize, optional DatabaseCallback creationCallback); + [MeasureAs=OpenWebDatabase, LogActivity, RaisesException] Database openDatabase(DOMString name, DOMString version, DOMString displayName, unsigned long estimatedSize, optional DatabaseCallback creationCallback); }; - diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.cpp index d710340e8e2..345d1e3f9b8 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.cpp @@ -29,7 +29,6 @@ #include "modules/webdatabase/WorkerGlobalScopeWebDatabase.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" @@ -38,18 +37,19 @@ #include "modules/webdatabase/DatabaseCallback.h" #include "modules/webdatabase/DatabaseManager.h" #include "modules/webdatabase/DatabaseSync.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/weborigin/SecurityOrigin.h" namespace WebCore { -PassRefPtr<Database> WorkerGlobalScopeWebDatabase::openDatabase(WorkerGlobalScope* context, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<Database> WorkerGlobalScopeWebDatabase::openDatabase(WorkerGlobalScope& context, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState& exceptionState) { DatabaseManager& dbManager = DatabaseManager::manager(); - RefPtr<Database> database; + RefPtrWillBeRawPtr<Database> database = nullptr; DatabaseError error = DatabaseError::None; - if (RuntimeEnabledFeatures::databaseEnabled() && context->securityOrigin()->canAccessDatabase()) { + if (RuntimeEnabledFeatures::databaseEnabled() && context.securityOrigin()->canAccessDatabase()) { String errorMessage; - database = dbManager.openDatabase(context, name, version, displayName, estimatedSize, creationCallback, error, errorMessage); + database = dbManager.openDatabase(&context, name, version, displayName, estimatedSize, creationCallback, error, errorMessage); ASSERT(database || error != DatabaseError::None); if (error != DatabaseError::None) DatabaseManager::throwExceptionForDatabaseError(error, errorMessage, exceptionState); @@ -60,14 +60,14 @@ PassRefPtr<Database> WorkerGlobalScopeWebDatabase::openDatabase(WorkerGlobalScop return database.release(); } -PassRefPtr<DatabaseSync> WorkerGlobalScopeWebDatabase::openDatabaseSync(WorkerGlobalScope* context, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<DatabaseSync> WorkerGlobalScopeWebDatabase::openDatabaseSync(WorkerGlobalScope& context, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState& exceptionState) { DatabaseManager& dbManager = DatabaseManager::manager(); - RefPtr<DatabaseSync> database; + RefPtrWillBeRawPtr<DatabaseSync> database = nullptr; DatabaseError error = DatabaseError::None; - if (RuntimeEnabledFeatures::databaseEnabled() && context->securityOrigin()->canAccessDatabase()) { + if (RuntimeEnabledFeatures::databaseEnabled() && context.securityOrigin()->canAccessDatabase()) { String errorMessage; - database = dbManager.openDatabaseSync(context, name, version, displayName, estimatedSize, creationCallback, error, errorMessage); + database = dbManager.openDatabaseSync(&context, name, version, displayName, estimatedSize, creationCallback, error, errorMessage); ASSERT(database || error != DatabaseError::None); if (error != DatabaseError::None) DatabaseManager::throwExceptionForDatabaseError(error, errorMessage, exceptionState); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.h b/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.h index d3b41239f9f..f0cec067598 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.h @@ -27,6 +27,7 @@ #ifndef WorkerGlobalScopeWebDatabase_h #define WorkerGlobalScopeWebDatabase_h +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -42,8 +43,8 @@ class WorkerGlobalScope; class WorkerGlobalScopeWebDatabase { public: - static PassRefPtr<Database> openDatabase(WorkerGlobalScope*, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState&); - static PassRefPtr<DatabaseSync> openDatabaseSync(WorkerGlobalScope*, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState&); + static PassRefPtrWillBeRawPtr<Database> openDatabase(WorkerGlobalScope&, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState&); + static PassRefPtrWillBeRawPtr<DatabaseSync> openDatabaseSync(WorkerGlobalScope&, const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassOwnPtr<DatabaseCallback> creationCallback, ExceptionState&); private: WorkerGlobalScopeWebDatabase() { }; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.idl b/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.idl index 095c320190a..49fe6a2d48e 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.idl +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/WorkerGlobalScopeWebDatabase.idl @@ -24,9 +24,10 @@ * */ -partial interface WorkerGlobalScope { - [RuntimeEnabled=Database, RaisesException] Database openDatabase(DOMString name, DOMString version, DOMString displayName, unsigned long estimatedSize, optional DatabaseCallback creationCallback); +[ + RuntimeEnabled=Database, +] partial interface WorkerGlobalScope { + [RaisesException, MeasureAs=OpenWebDatabaseInWorker] Database openDatabase(DOMString name, DOMString version, DOMString displayName, unsigned long estimatedSize, optional DatabaseCallback creationCallback); - [RuntimeEnabled=Database, RaisesException] DatabaseSync openDatabaseSync(DOMString name, DOMString version, DOMString displayName, unsigned long estimatedSize, optional DatabaseCallback creationCallback); + [RaisesException, MeasureAs=OpenWebDatabaseSyncInWorker] DatabaseSync openDatabaseSync(DOMString name, DOMString version, DOMString displayName, unsigned long estimatedSize, optional DatabaseCallback creationCallback); }; - diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteAuthorizer.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteAuthorizer.cpp index 37db87ffb26..f9605ee2b93 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteAuthorizer.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteAuthorizer.cpp @@ -34,7 +34,6 @@ namespace WebCore { const int SQLAuthAllow = SQLITE_OK; -const int SQLAuthIgnore = SQLITE_IGNORE; const int SQLAuthDeny = SQLITE_DENY; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteDatabase.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteDatabase.cpp index fad616d3a9d..4f1caacdc97 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteDatabase.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteDatabase.cpp @@ -36,10 +36,8 @@ namespace WebCore { const int SQLResultDone = SQLITE_DONE; -const int SQLResultError = SQLITE_ERROR; const int SQLResultOk = SQLITE_OK; const int SQLResultRow = SQLITE_ROW; -const int SQLResultSchema = SQLITE_SCHEMA; const int SQLResultFull = SQLITE_FULL; const int SQLResultInterrupt = SQLITE_INTERRUPT; const int SQLResultConstraint = SQLITE_CONSTRAINT; @@ -136,29 +134,6 @@ bool SQLiteDatabase::isInterrupted() return m_interrupted; } -void SQLiteDatabase::setFullsync(bool fsync) -{ - if (fsync) - executeCommand("PRAGMA fullfsync = 1;"); - else - executeCommand("PRAGMA fullfsync = 0;"); -} - -int64_t SQLiteDatabase::maximumSize() -{ - int64_t maxPageCount = 0; - - { - MutexLocker locker(m_authorizerLock); - enableAuthorizer(false); - SQLiteStatement statement(*this, "PRAGMA max_page_count"); - maxPageCount = statement.getColumnInt64(0); - enableAuthorizer(true); - } - - return maxPageCount * pageSize(); -} - void SQLiteDatabase::setMaximumSize(int64_t size) { if (size < 0) @@ -233,11 +208,6 @@ int64_t SQLiteDatabase::totalSize() return pageCount * pageSize(); } -void SQLiteDatabase::setSynchronous(SynchronousPragma sync) -{ - executeCommand("PRAGMA synchronous = " + String::number(sync)); -} - void SQLiteDatabase::setBusyTimeout(int ms) { if (m_db) @@ -246,24 +216,11 @@ void SQLiteDatabase::setBusyTimeout(int ms) WTF_LOG(SQLDatabase, "BusyTimeout set on non-open database"); } -void SQLiteDatabase::setBusyHandler(int(*handler)(void*, int)) -{ - if (m_db) - sqlite3_busy_handler(m_db, handler, NULL); - else - WTF_LOG(SQLDatabase, "Busy handler set on non-open database"); -} - bool SQLiteDatabase::executeCommand(const String& sql) { return SQLiteStatement(*this, sql).executeCommand(); } -bool SQLiteDatabase::returnsAtLeastOneResult(const String& sql) -{ - return SQLiteStatement(*this, sql).returnsAtLeastOneResult(); -} - bool SQLiteDatabase::tableExists(const String& tablename) { if (!isOpen()) @@ -276,23 +233,6 @@ bool SQLiteDatabase::tableExists(const String& tablename) return sql.step() == SQLITE_ROW; } -void SQLiteDatabase::clearAllTables() -{ - String query = "SELECT name FROM sqlite_master WHERE type='table';"; - Vector<String> tables; - if (!SQLiteStatement(*this, query).returnTextResults(0, tables)) { - WTF_LOG(SQLDatabase, "Unable to retrieve list of tables from database"); - return; - } - - for (Vector<String>::iterator table = tables.begin(); table != tables.end(); ++table ) { - if (*table == "sqlite_sequence") - continue; - if (!executeCommand("DROP TABLE " + *table)) - WTF_LOG(SQLDatabase, "Unable to drop table %s", (*table).ascii().data()); - } -} - int SQLiteDatabase::runVacuumCommand() { if (!executeCommand("VACUUM;")) @@ -347,18 +287,6 @@ const char* SQLiteDatabase::lastErrorMsg() return m_openErrorMessage.isNull() ? notOpenErrorMessage : m_openErrorMessage.data(); } -#ifndef NDEBUG -void SQLiteDatabase::disableThreadingChecks() -{ - // This doesn't guarantee that SQList was compiled with -DTHREADSAFE, or that you haven't turned off the mutexes. -#if SQLITE_VERSION_NUMBER >= 3003001 - m_sharable = true; -#else - ASSERT(0); // Your SQLite doesn't support sharing handles across threads. -#endif -} -#endif - int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const char* parameter1, const char* parameter2, const char* /*databaseName*/, const char* /*trigger_or_view*/) { DatabaseAuthorizer* auth = static_cast<DatabaseAuthorizer*>(userData); @@ -435,7 +363,7 @@ int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const cha } } -void SQLiteDatabase::setAuthorizer(PassRefPtr<DatabaseAuthorizer> auth) +void SQLiteDatabase::setAuthorizer(DatabaseAuthorizer* auth) { if (!m_db) { WTF_LOG_ERROR("Attempt to set an authorizer on a non-open SQL database"); @@ -493,4 +421,9 @@ bool SQLiteDatabase::turnOnIncrementalAutoVacuum() } } +void SQLiteDatabase::trace(Visitor* visitor) +{ + visitor->trace(m_authorizer); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteDatabase.h b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteDatabase.h index e2d52ee0b93..ad8ae589070 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteDatabase.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteDatabase.h @@ -27,6 +27,7 @@ #ifndef SQLiteDatabase_h #define SQLiteDatabase_h +#include "platform/heap/Handle.h" #include "wtf/Threading.h" #include "wtf/ThreadingPrimitives.h" #include "wtf/text/CString.h" @@ -45,15 +46,14 @@ class SQLiteStatement; class SQLiteTransaction; extern const int SQLResultDone; -extern const int SQLResultError; extern const int SQLResultOk; extern const int SQLResultRow; -extern const int SQLResultSchema; extern const int SQLResultFull; extern const int SQLResultInterrupt; extern const int SQLResultConstraint; class SQLiteDatabase { + DISALLOW_ALLOCATION(); WTF_MAKE_NONCOPYABLE(SQLiteDatabase); friend class SQLiteTransaction; public: @@ -69,10 +69,8 @@ public: void updateLastChangesCount(); bool executeCommand(const String&); - bool returnsAtLeastOneResult(const String&); bool tableExists(const String&); - void clearAllTables(); int runVacuumCommand(); int runIncrementalVacuumCommand(); @@ -82,28 +80,17 @@ public: int lastChanges(); void setBusyTimeout(int ms); - void setBusyHandler(int(*)(void*, int)); - void setFullsync(bool); - - // Gets/sets the maximum size in bytes + // Sets the maximum size in bytes // Depending on per-database attributes, the size will only be settable in units that are the page size of the database, which is established at creation // These chunks will never be anything other than 512, 1024, 2048, 4096, 8192, 16384, or 32768 bytes in size. // setMaximumSize() will round the size down to the next smallest chunk if the passed size doesn't align. - int64_t maximumSize(); void setMaximumSize(int64_t); // Gets the number of unused bytes in the database file. int64_t freeSpaceSize(); int64_t totalSize(); - // The SQLite SYNCHRONOUS pragma can be either FULL, NORMAL, or OFF - // FULL - Any writing calls to the DB block until the data is actually on the disk surface - // NORMAL - SQLite pauses at some critical moments when writing, but much less than FULL - // OFF - Calls return immediately after the data has been passed to disk - enum SynchronousPragma { SyncOff = 0, SyncNormal = 1, SyncFull = 2 }; - void setSynchronous(SynchronousPragma); - int lastError(); const char* lastErrorMsg(); @@ -112,7 +99,7 @@ public: return m_db; } - void setAuthorizer(PassRefPtr<DatabaseAuthorizer>); + void setAuthorizer(DatabaseAuthorizer*); Mutex& databaseMutex() { return m_lockingMutex; } bool isAutoCommitOn() const; @@ -129,13 +116,7 @@ public: enum AutoVacuumPragma { AutoVacuumNone = 0, AutoVacuumFull = 1, AutoVacuumIncremental = 2 }; bool turnOnIncrementalAutoVacuum(); - // Set this flag to allow access from multiple threads. Not all multi-threaded accesses are safe! - // See http://www.sqlite.org/cvstrac/wiki?p=MultiThreading for more info. -#ifndef NDEBUG - void disableThreadingChecks(); -#else - void disableThreadingChecks() {} -#endif + void trace(Visitor*); private: static int authorizerFunction(void*, int, const char*, const char*, const char*, const char*); @@ -151,7 +132,7 @@ private: bool m_sharable; Mutex m_authorizerLock; - RefPtr<DatabaseAuthorizer> m_authorizer; + RefPtrWillBeMember<DatabaseAuthorizer> m_authorizer; Mutex m_lockingMutex; ThreadIdentifier m_openingThread; diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystem.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystem.cpp index 8e5dd11e5c9..0cad5901728 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystem.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystem.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "modules/webdatabase/sqlite/SQLiteFileSystem.h" +#include "platform/heap/Handle.h" #include <sqlite3.h> -#include "public/platform/Platform.h" #include "wtf/text/CString.h" // SQLiteFileSystem::registerSQLiteVFS() is implemented in the @@ -45,56 +45,11 @@ SQLiteFileSystem::SQLiteFileSystem() int SQLiteFileSystem::openDatabase(const String& filename, sqlite3** database, bool forWebSQLDatabase) { + ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); if (!forWebSQLDatabase) return sqlite3_open(filename.utf8().data(), database); return sqlite3_open_v2(filename.utf8().data(), database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "chromium_vfs"); } -String SQLiteFileSystem::getFileNameForNewDatabase( - const String&, const String& dbName, const String &originIdentifier, SQLiteDatabase*) -{ - // Not used by Chromium's DatabaseTracker implementation - ASSERT_NOT_REACHED(); - return String(); -} - -String SQLiteFileSystem::appendDatabaseFileNameToPath(const String&, const String& fileName) -{ - // Not used by Chromium's DatabaseTracker implementation - ASSERT_NOT_REACHED(); - return String(); -} - -bool SQLiteFileSystem::ensureDatabaseDirectoryExists(const String&) -{ - // Not used by Chromium's DatabaseTracker implementation - ASSERT_NOT_REACHED(); - return false; -} - -bool SQLiteFileSystem::ensureDatabaseFileExists(const String&, bool) -{ - // Not used by Chromium's DatabaseTracker implementation - ASSERT_NOT_REACHED(); - return false; -} - -bool SQLiteFileSystem::deleteEmptyDatabaseDirectory(const String&) -{ - // Not used by Chromium's DatabaseTracker implementation - ASSERT_NOT_REACHED(); - return false; -} - -bool SQLiteFileSystem::deleteDatabaseFile(const String& fileName) -{ - return (blink::Platform::current()->databaseDeleteFile(fileName, false) == SQLITE_OK); -} - -long long SQLiteFileSystem::getDatabaseFileSize(const String& fileName) -{ - return blink::Platform::current()->databaseGetFileSize(fileName); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystem.h b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystem.h index f3b1b596bd8..0f2024c6877 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystem.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteFileSystem.h @@ -57,56 +57,6 @@ public: // using a custom VFS. static int openDatabase(const String& filename, sqlite3** database, bool forWebSQLDatabase); - // Returns the file name for a database. - // - // dbDir - The directory where all databases are stored. - // dbName - The name of the database. - // originIdentifier - The origin that wants to use this database. - // db - A database with a number generator used to create unique file names. - static String getFileNameForNewDatabase(const String& dbDir, const String& dbName, - const String& originIdentifier, SQLiteDatabase* db); - - // Creates an absolute file path given a directory and a file name. - // - // path - The directory. - // fileName - The file name. - static String appendDatabaseFileNameToPath(const String& path, const String& fileName); - - // Makes sure the given directory exists, by creating all missing directories - // on the given path. - // - // path - The directory. - static bool ensureDatabaseDirectoryExists(const String& path); - - // If 'checkPathOnly' is false, then this method only checks if the given file exists. - // If 'checkPathOnly' is true, then this method makes sure all directories on the - // given path exist by creating the missing ones, and does not check if the file - // itself exists. - // - // Sometimes we expect a DB file to exist; other times, we're OK with creating a new - // DB file, but we want to make sure that the directory in which we want to put the - // new DB file exists. This method covers both cases. - // - // fileName - The file name. - // checkPathOnly - If true, we only make sure that the given directory exists. - // If false, we only check if the file exists. - static bool ensureDatabaseFileExists(const String& fileName, bool checkPathOnly); - - // Deletes an empty database directory. - // - // path - The directory. - static bool deleteEmptyDatabaseDirectory(const String& path); - - // Deletes a database file. - // - // fileName - The file name. - static bool deleteDatabaseFile(const String& fileName); - - // Returns the size of the database file. - // - // fileName - The file name. - static long long getDatabaseFileSize(const String& fileName); - private: // do not instantiate this class SQLiteFileSystem(); diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteStatement.cpp b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteStatement.cpp index acff15291da..3ae9f8156db 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteStatement.cpp +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteStatement.cpp @@ -59,25 +59,25 @@ int SQLiteStatement::prepare() { ASSERT(!m_isPrepared); + CString query = m_query.stripWhiteSpace().utf8(); + + ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); MutexLocker databaseLock(m_database.databaseMutex()); if (m_database.isInterrupted()) return SQLITE_INTERRUPT; - CString query = m_query.stripWhiteSpace().utf8(); - WTF_LOG(SQLDatabase, "SQL - prepare - %s", query.data()); // Pass the length of the string including the null character to sqlite3_prepare_v2; // this lets SQLite avoid an extra string copy. size_t lengthIncludingNullCharacter = query.length() + 1; - const char* tail; + const char* tail = 0; int error = sqlite3_prepare_v2(m_database.sqlite3Handle(), query.data(), lengthIncludingNullCharacter, &m_statement, &tail); if (error != SQLITE_OK) WTF_LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, query.data(), sqlite3_errmsg(m_database.sqlite3Handle())); - - if (tail && *tail) + else if (tail && *tail) error = SQLITE_ERROR; #ifndef NDEBUG @@ -88,6 +88,7 @@ int SQLiteStatement::prepare() int SQLiteStatement::step() { + ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); MutexLocker databaseLock(m_database.databaseMutex()); if (m_database.isInterrupted()) return SQLITE_INTERRUPT; @@ -123,15 +124,6 @@ int SQLiteStatement::finalize() return result; } -int SQLiteStatement::reset() -{ - ASSERT(m_isPrepared); - if (!m_statement) - return SQLITE_OK; - WTF_LOG(SQLDatabase, "SQL - reset - %s", m_query.ascii().data()); - return sqlite3_reset(m_statement); -} - bool SQLiteStatement::executeCommand() { if (!m_statement && prepare() != SQLITE_OK) @@ -145,41 +137,6 @@ bool SQLiteStatement::executeCommand() return true; } -bool SQLiteStatement::returnsAtLeastOneResult() -{ - if (!m_statement && prepare() != SQLITE_OK) - return false; - ASSERT(m_isPrepared); - if (step() != SQLITE_ROW) { - finalize(); - return false; - } - finalize(); - return true; - -} - -int SQLiteStatement::bindBlob(int index, const void* blob, int size) -{ - ASSERT(m_isPrepared); - ASSERT(index > 0); - ASSERT(static_cast<unsigned>(index) <= bindParameterCount()); - ASSERT(blob); - ASSERT(size >= 0); - - if (!m_statement) - return SQLITE_ERROR; - - return sqlite3_bind_blob(m_statement, index, blob, size, SQLITE_TRANSIENT); -} - -int SQLiteStatement::bindBlob(int index, const String& text) -{ - // SQLite treats uses zero pointers to represent null strings, which means we need to make sure to map null WTFStrings to zero pointers. - ASSERT(!String().charactersWithNullTermination().data()); - return bindBlob(index, text.charactersWithNullTermination().data(), text.length() * sizeof(UChar)); -} - int SQLiteStatement::bindText(int index, const String& text) { ASSERT(m_isPrepared); @@ -191,24 +148,6 @@ int SQLiteStatement::bindText(int index, const String& text) return sqlite3_bind_text16(m_statement, index, text.charactersWithNullTermination().data(), sizeof(UChar) * text.length(), SQLITE_TRANSIENT); } -int SQLiteStatement::bindInt(int index, int integer) -{ - ASSERT(m_isPrepared); - ASSERT(index > 0); - ASSERT(static_cast<unsigned>(index) <= bindParameterCount()); - - return sqlite3_bind_int(m_statement, index, integer); -} - -int SQLiteStatement::bindInt64(int index, int64_t integer) -{ - ASSERT(m_isPrepared); - ASSERT(index > 0); - ASSERT(static_cast<unsigned>(index) <= bindParameterCount()); - - return sqlite3_bind_int64(m_statement, index, integer); -} - int SQLiteStatement::bindDouble(int index, double number) { ASSERT(m_isPrepared); @@ -258,29 +197,6 @@ int SQLiteStatement::columnCount() return sqlite3_data_count(m_statement); } -bool SQLiteStatement::isColumnNull(int col) -{ - ASSERT(col >= 0); - if (!m_statement) - if (prepareAndStep() != SQLITE_ROW) - return false; - if (columnCount() <= col) - return false; - - return sqlite3_column_type(m_statement, col) == SQLITE_NULL; -} - -bool SQLiteStatement::isColumnDeclaredAsBlob(int col) -{ - ASSERT(col >= 0); - if (!m_statement) { - if (prepare() != SQLITE_OK) - return false; - } - - return equalIgnoringCase(String("BLOB"), String(reinterpret_cast<const UChar*>(sqlite3_column_decltype16(m_statement, col)))); -} - String SQLiteStatement::getColumnName(int col) { ASSERT(col >= 0); @@ -335,17 +251,6 @@ String SQLiteStatement::getColumnText(int col) return StringImpl::create8BitIfPossible(string, sqlite3_column_bytes16(m_statement, col) / sizeof(UChar)); } -double SQLiteStatement::getColumnDouble(int col) -{ - ASSERT(col >= 0); - if (!m_statement) - if (prepareAndStep() != SQLITE_ROW) - return 0.0; - if (columnCount() <= col) - return 0.0; - return sqlite3_column_double(m_statement, col); -} - int SQLiteStatement::getColumnInt(int col) { ASSERT(col >= 0); @@ -368,167 +273,4 @@ int64_t SQLiteStatement::getColumnInt64(int col) return sqlite3_column_int64(m_statement, col); } -String SQLiteStatement::getColumnBlobAsString(int col) -{ - ASSERT(col >= 0); - - if (!m_statement && prepareAndStep() != SQLITE_ROW) - return String(); - - if (columnCount() <= col) - return String(); - - const void* blob = sqlite3_column_blob(m_statement, col); - if (!blob) - return String(); - - int size = sqlite3_column_bytes(m_statement, col); - if (size < 0) - return String(); - - ASSERT(!(size % sizeof(UChar))); - return String(static_cast<const UChar*>(blob), size / sizeof(UChar)); -} - -void SQLiteStatement::getColumnBlobAsVector(int col, Vector<char>& result) -{ - ASSERT(col >= 0); - - if (!m_statement && prepareAndStep() != SQLITE_ROW) { - result.clear(); - return; - } - - if (columnCount() <= col) { - result.clear(); - return; - } - - const void* blob = sqlite3_column_blob(m_statement, col); - if (!blob) { - result.clear(); - return; - } - - int size = sqlite3_column_bytes(m_statement, col); - result.resize((size_t)size); - for (int i = 0; i < size; ++i) - result[i] = (static_cast<const unsigned char*>(blob))[i]; -} - -const void* SQLiteStatement::getColumnBlob(int col, int& size) -{ - ASSERT(col >= 0); - - size = 0; - - if (finalize() != SQLITE_OK) - WTF_LOG(SQLDatabase, "Finalize failed"); - if (prepare() != SQLITE_OK) { - WTF_LOG(SQLDatabase, "Prepare failed"); - return 0; - } - if (step() != SQLITE_ROW) { - WTF_LOG(SQLDatabase, "Step wasn't a row"); - return 0; - } - - if (columnCount() <= col) - return 0; - - const void* blob = sqlite3_column_blob(m_statement, col); - if (!blob) - return 0; - - size = sqlite3_column_bytes(m_statement, col); - return blob; -} - -bool SQLiteStatement::returnTextResults(int col, Vector<String>& v) -{ - ASSERT(col >= 0); - - v.clear(); - - if (m_statement) - finalize(); - if (prepare() != SQLITE_OK) - return false; - - while (step() == SQLITE_ROW) - v.append(getColumnText(col)); - bool result = true; - if (m_database.lastError() != SQLITE_DONE) { - result = false; - WTF_LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data()); - } - finalize(); - return result; -} - -bool SQLiteStatement::returnIntResults(int col, Vector<int>& v) -{ - v.clear(); - - if (m_statement) - finalize(); - if (prepare() != SQLITE_OK) - return false; - - while (step() == SQLITE_ROW) - v.append(getColumnInt(col)); - bool result = true; - if (m_database.lastError() != SQLITE_DONE) { - result = false; - WTF_LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data()); - } - finalize(); - return result; -} - -bool SQLiteStatement::returnInt64Results(int col, Vector<int64_t>& v) -{ - v.clear(); - - if (m_statement) - finalize(); - if (prepare() != SQLITE_OK) - return false; - - while (step() == SQLITE_ROW) - v.append(getColumnInt64(col)); - bool result = true; - if (m_database.lastError() != SQLITE_DONE) { - result = false; - WTF_LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data()); - } - finalize(); - return result; -} - -bool SQLiteStatement::returnDoubleResults(int col, Vector<double>& v) -{ - v.clear(); - - if (m_statement) - finalize(); - if (prepare() != SQLITE_OK) - return false; - - while (step() == SQLITE_ROW) - v.append(getColumnDouble(col)); - bool result = true; - if (m_database.lastError() != SQLITE_DONE) { - result = false; - WTF_LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data()); - } - finalize(); - return result; -} - -bool SQLiteStatement::isExpired() -{ - return !m_statement || sqlite3_expired(m_statement); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteStatement.h b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteStatement.h index 14ef4b2edeb..4fec5ccf5f6 100644 --- a/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteStatement.h +++ b/chromium/third_party/WebKit/Source/modules/webdatabase/sqlite/SQLiteStatement.h @@ -41,11 +41,7 @@ public: ~SQLiteStatement(); int prepare(); - int bindBlob(int index, const void* blob, int size); - int bindBlob(int index, const String&); int bindText(int index, const String&); - int bindInt(int index, int); - int bindInt64(int index, int64_t); int bindDouble(int index, double); int bindNull(int index); int bindValue(int index, const SQLValue&); @@ -53,7 +49,6 @@ public: int step(); int finalize(); - int reset(); int prepareAndStep() { if (int error = prepare()) return error; return step(); } @@ -62,37 +57,15 @@ public: // returns false otherwise bool executeCommand(); - // prepares, steps, and finalizes. - // returns true is step() returns SQLITE_ROW - // returns false otherwise - bool returnsAtLeastOneResult(); - - bool isExpired(); - // Returns -1 on last-step failing. Otherwise, returns number of rows // returned in the last step() int columnCount(); - bool isColumnNull(int col); - bool isColumnDeclaredAsBlob(int col); String getColumnName(int col); SQLValue getColumnValue(int col); String getColumnText(int col); - double getColumnDouble(int col); int getColumnInt(int col); int64_t getColumnInt64(int col); - const void* getColumnBlob(int col, int& size); - String getColumnBlobAsString(int col); - void getColumnBlobAsVector(int col, Vector<char>&); - - bool returnTextResults(int col, Vector<String>&); - bool returnIntResults(int col, Vector<int>&); - bool returnInt64Results(int col, Vector<int64_t>&); - bool returnDoubleResults(int col, Vector<double>&); - - SQLiteDatabase* database() { return &m_database; } - - const String& query() const { return m_query; } private: SQLiteDatabase& m_database; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.cpp index 5a572fb276a..b7e5bf70702 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.cpp +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.cpp @@ -31,154 +31,102 @@ #include "config.h" #include "modules/webmidi/MIDIAccess.h" -#include "core/dom/DOMError.h" #include "core/dom/Document.h" #include "core/loader/DocumentLoadTiming.h" #include "core/loader/DocumentLoader.h" -#include "modules/webmidi/MIDIAccessPromise.h" +#include "modules/webmidi/MIDIAccessInitializer.h" #include "modules/webmidi/MIDIConnectionEvent.h" #include "modules/webmidi/MIDIController.h" +#include "modules/webmidi/MIDIOptions.h" #include "modules/webmidi/MIDIPort.h" +#include "platform/AsyncMethodRunner.h" +#include <v8.h> namespace WebCore { -PassRefPtr<MIDIAccess> MIDIAccess::create(ExecutionContext* context, MIDIAccessPromise* promise) -{ - RefPtr<MIDIAccess> midiAccess(adoptRef(new MIDIAccess(context, promise))); - midiAccess->suspendIfNeeded(); - midiAccess->startRequest(); - return midiAccess.release(); -} - -MIDIAccess::~MIDIAccess() -{ - stop(); -} - -MIDIAccess::MIDIAccess(ExecutionContext* context, MIDIAccessPromise* promise) - : ActiveDOMObject(context) - , m_promise(promise) - , m_hasAccess(false) - , m_sysExEnabled(false) - , m_requesting(false) +MIDIAccess::MIDIAccess(PassOwnPtr<MIDIAccessor> accessor, bool sysexEnabled, const Vector<MIDIAccessInitializer::PortDescriptor>& ports, ExecutionContext* executionContext) + : ActiveDOMObject(executionContext) + , m_accessor(accessor) + , m_sysexEnabled(sysexEnabled) { ScriptWrappable::init(this); - m_accessor = MIDIAccessor::create(this); + m_accessor->setClient(this); + for (size_t i = 0; i < ports.size(); ++i) { + const MIDIAccessInitializer::PortDescriptor& port = ports[i]; + if (port.type == MIDIPort::MIDIPortTypeInput) { + m_inputs.append(MIDIInput::create(this, port.id, port.manufacturer, port.name, port.version)); + } else { + m_outputs.append(MIDIOutput::create(this, m_outputs.size(), port.id, port.manufacturer, port.name, port.version)); + } + } } -void MIDIAccess::setSysExEnabled(bool enable) +MIDIAccess::~MIDIAccess() { - m_requesting = false; - m_sysExEnabled = enable; - if (enable) - m_accessor->startSession(); - else - permissionDenied(); } void MIDIAccess::didAddInputPort(const String& id, const String& manufacturer, const String& name, const String& version) { ASSERT(isMainThread()); - - m_inputs.append(MIDIInput::create(this, executionContext(), id, manufacturer, name, version)); + m_inputs.append(MIDIInput::create(this, id, manufacturer, name, version)); } void MIDIAccess::didAddOutputPort(const String& id, const String& manufacturer, const String& name, const String& version) { ASSERT(isMainThread()); - unsigned portIndex = m_outputs.size(); - m_outputs.append(MIDIOutput::create(this, portIndex, executionContext(), id, manufacturer, name, version)); -} - -void MIDIAccess::didStartSession(bool success) -{ - ASSERT(isMainThread()); - - m_hasAccess = success; - if (success) - m_promise->fulfill(); - else - m_promise->reject(DOMError::create("InvalidStateError")); + m_outputs.append(MIDIOutput::create(this, portIndex, id, manufacturer, name, version)); } void MIDIAccess::didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp) { ASSERT(isMainThread()); + if (portIndex >= m_inputs.size()) + return; - if (m_hasAccess && portIndex < m_inputs.size()) { - // Convert from time in seconds which is based on the time coordinate system of monotonicallyIncreasingTime() - // into time in milliseconds (a DOMHighResTimeStamp) according to the same time coordinate system as performance.now(). - // This is how timestamps are defined in the Web MIDI spec. - Document* document = toDocument(executionContext()); - ASSERT(document); + // Convert from time in seconds which is based on the time coordinate system of monotonicallyIncreasingTime() + // into time in milliseconds (a DOMHighResTimeStamp) according to the same time coordinate system as performance.now(). + // This is how timestamps are defined in the Web MIDI spec. + Document* document = toDocument(executionContext()); + ASSERT(document); - double timeStampInMilliseconds = 1000 * document->loader()->timing()->monotonicTimeToZeroBasedDocumentTime(timeStamp); + double timeStampInMilliseconds = 1000 * document->loader()->timing()->monotonicTimeToZeroBasedDocumentTime(timeStamp); - m_inputs[portIndex]->didReceiveMIDIData(portIndex, data, length, timeStampInMilliseconds); - } + m_inputs[portIndex]->didReceiveMIDIData(portIndex, data, length, timeStampInMilliseconds); } void MIDIAccess::sendMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStampInMilliseconds) { - if (m_hasAccess && portIndex < m_outputs.size() && data && length > 1) { - // Convert from a time in milliseconds (a DOMHighResTimeStamp) according to the same time coordinate system as performance.now() - // into a time in seconds which is based on the time coordinate system of monotonicallyIncreasingTime(). - double timeStamp; - - if (!timeStampInMilliseconds) { - // We treat a value of 0 (which is the default value) as special, meaning "now". - // We need to translate it exactly to 0 seconds. - timeStamp = 0; - } else { - Document* document = toDocument(executionContext()); - ASSERT(document); - double documentStartTime = document->loader()->timing()->referenceMonotonicTime(); - timeStamp = documentStartTime + 0.001 * timeStampInMilliseconds; - } - - m_accessor->sendMIDIData(portIndex, data, length, timeStamp); + if (!data || !length || portIndex >= m_outputs.size()) + return; + // Convert from a time in milliseconds (a DOMHighResTimeStamp) according to the same time coordinate system as performance.now() + // into a time in seconds which is based on the time coordinate system of monotonicallyIncreasingTime(). + double timeStamp; + + if (!timeStampInMilliseconds) { + // We treat a value of 0 (which is the default value) as special, meaning "now". + // We need to translate it exactly to 0 seconds. + timeStamp = 0; + } else { + Document* document = toDocument(executionContext()); + ASSERT(document); + double documentStartTime = document->loader()->timing()->referenceMonotonicTime(); + timeStamp = documentStartTime + 0.001 * timeStampInMilliseconds; } + + m_accessor->sendMIDIData(portIndex, data, length, timeStamp); } void MIDIAccess::stop() { - m_hasAccess = false; - if (!m_requesting) - return; - m_requesting = false; - Document* document = toDocument(executionContext()); - ASSERT(document); - MIDIController* controller = MIDIController::from(document->page()); - ASSERT(controller); - controller->cancelSysExPermissionRequest(this); - m_accessor.clear(); } -void MIDIAccess::startRequest() +void MIDIAccess::trace(Visitor* visitor) { - if (!m_promise->options()->sysex) { - m_accessor->startSession(); - return; - } - Document* document = toDocument(executionContext()); - ASSERT(document); - MIDIController* controller = MIDIController::from(document->page()); - if (controller) { - m_requesting = true; - controller->requestSysExPermission(this); - } else { - permissionDenied(); - } -} - -void MIDIAccess::permissionDenied() -{ - ASSERT(isMainThread()); - - m_hasAccess = false; - m_promise->reject(DOMError::create("SecurityError")); + visitor->trace(m_inputs); + visitor->trace(m_outputs); + EventTargetWithInlineData::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.h index 9f6aaaf0c85..b543ec989f5 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.h @@ -31,13 +31,16 @@ #ifndef MIDIAccess_h #define MIDIAccess_h +#include "bindings/v8/ScriptPromise.h" #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" +#include "modules/webmidi/MIDIAccessInitializer.h" #include "modules/webmidi/MIDIAccessor.h" #include "modules/webmidi/MIDIAccessorClient.h" #include "modules/webmidi/MIDIInput.h" #include "modules/webmidi/MIDIOutput.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/Vector.h" @@ -45,13 +48,19 @@ namespace WebCore { class ExecutionContext; -class MIDIAccessPromise; +struct MIDIOptions; -class MIDIAccess : public RefCounted<MIDIAccess>, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData, public MIDIAccessorClient { +class MIDIAccess FINAL : public RefCountedWillBeRefCountedGarbageCollected<MIDIAccess>, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData, public MIDIAccessorClient { REFCOUNTED_EVENT_TARGET(MIDIAccess); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MIDIAccess); public: + static PassRefPtrWillBeRawPtr<MIDIAccess> create(PassOwnPtr<MIDIAccessor> accessor, bool sysexEnabled, const Vector<MIDIAccessInitializer::PortDescriptor>& ports, ExecutionContext* executionContext) + { + RefPtrWillBeRawPtr<MIDIAccess> access = adoptRefWillBeRefCountedGarbageCollected(new MIDIAccess(accessor, sysexEnabled, ports, executionContext)); + access->suspendIfNeeded(); + return access; + } virtual ~MIDIAccess(); - static PassRefPtr<MIDIAccess> create(ExecutionContext*, MIDIAccessPromise*); MIDIInputVector inputs() const { return m_inputs; } MIDIOutputVector outputs() const { return m_outputs; } @@ -59,39 +68,38 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(connect); DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect); - void setSysExEnabled(bool); - bool sysExEnabled() const { return m_sysExEnabled; } + bool sysexEnabled() const { return m_sysexEnabled; } // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE { return EventTargetNames::MIDIAccess; } virtual ExecutionContext* executionContext() const OVERRIDE { return ActiveDOMObject::executionContext(); } // ActiveDOMObject - virtual void stop(); + virtual void stop() OVERRIDE; // MIDIAccessorClient virtual void didAddInputPort(const String& id, const String& manufacturer, const String& name, const String& version) OVERRIDE; virtual void didAddOutputPort(const String& id, const String& manufacturer, const String& name, const String& version) OVERRIDE; - virtual void didStartSession(bool success) OVERRIDE; + virtual void didStartSession(bool success, const String& error, const String& message) OVERRIDE + { + // This method is for MIDIAccess initialization: MIDIAccessInitializer + // has the implementation. + ASSERT_NOT_REACHED(); + } virtual void didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp) OVERRIDE; // |timeStampInMilliseconds| is in the same time coordinate system as performance.now(). void sendMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStampInMilliseconds); -private: - MIDIAccess(ExecutionContext*, MIDIAccessPromise*); + virtual void trace(Visitor*) OVERRIDE; - void startRequest(); - virtual void permissionDenied(); +private: + MIDIAccess(PassOwnPtr<MIDIAccessor>, bool sysexEnabled, const Vector<MIDIAccessInitializer::PortDescriptor>&, ExecutionContext*); + OwnPtr<MIDIAccessor> m_accessor; + bool m_sysexEnabled; MIDIInputVector m_inputs; MIDIOutputVector m_outputs; - MIDIAccessPromise* m_promise; - - OwnPtr<MIDIAccessor> m_accessor; - bool m_hasAccess; - bool m_sysExEnabled; - bool m_requesting; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.idl b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.idl index a20b6bc692f..5ffcfac784d 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.idl +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccess.idl @@ -35,6 +35,8 @@ sequence<MIDIInput> inputs(); sequence<MIDIOutput> outputs(); + readonly attribute boolean sysexEnabled; + attribute EventHandler onconnect; attribute EventHandler ondisconnect; }; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessInitializer.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessInitializer.cpp new file mode 100644 index 00000000000..5a53ba83417 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessInitializer.cpp @@ -0,0 +1,98 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "modules/webmidi/MIDIAccessInitializer.h" + +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "core/dom/DOMError.h" +#include "core/dom/Document.h" +#include "core/frame/Navigator.h" +#include "modules/webmidi/MIDIAccess.h" +#include "modules/webmidi/MIDIController.h" +#include "modules/webmidi/MIDIOptions.h" +#include "modules/webmidi/MIDIPort.h" + +namespace WebCore { + +MIDIAccessInitializer::MIDIAccessInitializer(ScriptState* scriptState, const MIDIOptions& options) + : ScriptPromiseResolverWithContext(scriptState) + , m_options(options) + , m_sysexEnabled(false) +{ +} + +MIDIAccessInitializer::~MIDIAccessInitializer() +{ + // It is safe to cancel a request which is already finished or canceld. + Document* document = toDocument(executionContext()); + ASSERT(document); + MIDIController* controller = MIDIController::from(document->frame()); + if (controller) + controller->cancelSysexPermissionRequest(this); +} + +ScriptPromise MIDIAccessInitializer::start() +{ + ScriptPromise promise = this->promise(); + m_accessor = MIDIAccessor::create(this); + + if (!m_options.sysex) { + m_accessor->startSession(); + return promise; + } + Document* document = toDocument(executionContext()); + ASSERT(document); + MIDIController* controller = MIDIController::from(document->frame()); + if (controller) { + controller->requestSysexPermission(this); + } else { + reject(DOMError::create("SecurityError")); + } + return promise; +} + +void MIDIAccessInitializer::didAddInputPort(const String& id, const String& manufacturer, const String& name, const String& version) +{ + ASSERT(m_accessor); + m_portDescriptors.append(PortDescriptor(id, manufacturer, name, MIDIPort::MIDIPortTypeInput, version)); +} + +void MIDIAccessInitializer::didAddOutputPort(const String& id, const String& manufacturer, const String& name, const String& version) +{ + ASSERT(m_accessor); + m_portDescriptors.append(PortDescriptor(id, manufacturer, name, MIDIPort::MIDIPortTypeOutput, version)); +} + +void MIDIAccessInitializer::didStartSession(bool success, const String& error, const String& message) +{ + ASSERT(m_accessor); + if (success) { + resolve(MIDIAccess::create(m_accessor.release(), m_sysexEnabled, m_portDescriptors, executionContext())); + } else { + reject(DOMError::create(error, message)); + } +} + +void MIDIAccessInitializer::setSysexEnabled(bool enable) +{ + m_sysexEnabled = enable; + if (enable) + m_accessor->startSession(); + else + reject(DOMError::create("SecurityError")); +} + +SecurityOrigin* MIDIAccessInitializer::securityOrigin() const +{ + return executionContext()->securityOrigin(); +} + +ExecutionContext* MIDIAccessInitializer::executionContext() const +{ + return scriptState()->executionContext(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessInitializer.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessInitializer.h new file mode 100644 index 00000000000..6f3f605228f --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessInitializer.h @@ -0,0 +1,76 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MIDIAccessInitializer_h +#define MIDIAccessInitializer_h + +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" +#include "modules/webmidi/MIDIAccessor.h" +#include "modules/webmidi/MIDIAccessorClient.h" +#include "modules/webmidi/MIDIOptions.h" +#include "modules/webmidi/MIDIPort.h" +#include "wtf/OwnPtr.h" +#include "wtf/RawPtr.h" +#include "wtf/Vector.h" + +namespace WebCore { + +class MIDIAccess; +class Navigator; +class ScriptState; + +class MIDIAccessInitializer : public ScriptPromiseResolverWithContext, public MIDIAccessorClient { +public: + struct PortDescriptor { + String id; + String manufacturer; + String name; + MIDIPort::MIDIPortTypeCode type; + String version; + + PortDescriptor(const String& id, const String& manufacturer, const String& name, MIDIPort::MIDIPortTypeCode type, const String& version) + : id(id) + , manufacturer(manufacturer) + , name(name) + , type(type) + , version(version) { } + }; + + static ScriptPromise start(ScriptState* scriptState, const MIDIOptions& options) + { + RefPtr<MIDIAccessInitializer> p = adoptRef(new MIDIAccessInitializer(scriptState, options)); + p->keepAliveWhilePending(); + p->suspendIfNeeded(); + return p->start(); + } + + virtual ~MIDIAccessInitializer(); + + // MIDIAccessorClient + virtual void didAddInputPort(const String& id, const String& manufacturer, const String& name, const String& version) OVERRIDE; + virtual void didAddOutputPort(const String& id, const String& manufacturer, const String& name, const String& version) OVERRIDE; + virtual void didStartSession(bool success, const String& error, const String& message) OVERRIDE; + virtual void didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp) OVERRIDE { } + + void setSysexEnabled(bool value); + SecurityOrigin* securityOrigin() const; + +private: + ScriptPromise start(); + + MIDIAccessInitializer(ScriptState*, const MIDIOptions&); + + ExecutionContext* executionContext() const; + + OwnPtr<MIDIAccessor> m_accessor; + MIDIOptions m_options; + bool m_sysexEnabled; + Vector<PortDescriptor> m_portDescriptors; +}; + +} // namespace WebCore + + +#endif // MIDIAccessInitializer_h diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessPromise.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessPromise.cpp deleted file mode 100644 index 7ae06b3faae..00000000000 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessPromise.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "modules/webmidi/MIDIAccessPromise.h" - -#include "core/dom/DOMError.h" -#include "modules/webmidi/MIDIAccess.h" -#include "modules/webmidi/MIDIErrorCallback.h" -#include "modules/webmidi/MIDISuccessCallback.h" - -namespace WebCore { - -PassRefPtr<MIDIAccessPromise> MIDIAccessPromise::create(ExecutionContext* context, const Dictionary& options) -{ - RefPtr<MIDIAccessPromise> midiAccessPromise(adoptRef(new MIDIAccessPromise(context, options))); - midiAccessPromise->suspendIfNeeded(); - return midiAccessPromise.release(); -} - -MIDIAccessPromise::MIDIAccessPromise(ExecutionContext* context, const Dictionary& options) - : ActiveDOMObject(context) - , m_state(Pending) - , m_options(adoptPtr(new MIDIOptions(options))) -{ - ScriptWrappable::init(this); -} - -MIDIAccessPromise::~MIDIAccessPromise() -{ - stop(); -} - -bool MIDIAccessPromise::hasPendingActivity() const -{ - return !!m_access && m_state != Accepted && m_state != Rejected; -} - -void MIDIAccessPromise::stop() -{ - m_state = Invoked; - if (!!m_access) - m_access->stop(); - clear(); -} - -void MIDIAccessPromise::fulfill() -{ - if (m_state == Pending) { - if (m_successCallback) { - m_state = Invoked; - ASSERT(m_access); - m_successCallback->handleEvent(m_access.get(), m_options->sysex); - clear(); - } else { - m_state = Accepted; - } - } -} - -void MIDIAccessPromise::reject(PassRefPtr<DOMError> error) -{ - if (m_state == Pending) { - if (m_errorCallback) { - m_state = Invoked; - m_errorCallback->handleEvent(error.get()); - clear(); - } else { - m_state = Rejected; - m_error = error; - } - } -} - -void MIDIAccessPromise::then(PassOwnPtr<MIDISuccessCallback> successCallback, PassOwnPtr<MIDIErrorCallback> errorCallback) -{ - // Lazily request access. - if (!m_access) - m_access = MIDIAccess::create(executionContext(), this); - - switch (m_state) { - case Accepted: - m_state = Invoked; - successCallback->handleEvent(m_access.get(), m_options->sysex); - clear(); - break; - case Rejected: - m_state = Invoked; - errorCallback->handleEvent(m_error.get()); - clear(); - break; - case Pending: - m_successCallback = successCallback; - m_errorCallback = errorCallback; - break; - case Invoked: - break; - default: - ASSERT_NOT_REACHED(); - } -} - -void MIDIAccessPromise::clear() -{ - ASSERT(m_state == Invoked); - m_access.clear(); - m_error.clear(); - m_options.clear(); - m_successCallback.clear(); - m_errorCallback.clear(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessPromise.idl b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessPromise.idl deleted file mode 100644 index 2a4b37a8195..00000000000 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessPromise.idl +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// FIXME: Once Promise is implemented, remove this interface and use it. -// See also, http://crbug.com/243345 -[ - NoInterfaceObject, - ActiveDOMObject -] interface MIDIAccessPromise { - // Supports only then() method tentatively. But it never returns Promise. - void then(MIDISuccessCallback successCallback, MIDIErrorCallback errorCallback); -}; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessor.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessor.cpp index 478c73cbde2..e9a94b0419c 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessor.cpp +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessor.cpp @@ -75,9 +75,9 @@ void MIDIAccessor::didAddOutputPort(const WebString& id, const WebString& manufa m_client->didAddOutputPort(id, manufacturer, name, version); } -void MIDIAccessor::didStartSession(bool success) +void MIDIAccessor::didStartSession(bool success, const WebString& error, const WebString& message) { - m_client->didStartSession(success); + m_client->didStartSession(success, error, message); } void MIDIAccessor::didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp) diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessor.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessor.h index 78290b6a88f..d45870e3a94 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessor.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessor.h @@ -40,7 +40,7 @@ namespace WebCore { class MIDIAccessorClient; -class MIDIAccessor : public blink::WebMIDIAccessorClient { +class MIDIAccessor FINAL : public blink::WebMIDIAccessorClient { public: static PassOwnPtr<MIDIAccessor> create(MIDIAccessorClient*); @@ -48,11 +48,15 @@ public: void startSession(); void sendMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp); + // MIDIAccessInitializer and MIDIAccess are both MIDIAccessClient. + // MIDIAccessInitializer is the first client and MIDIAccess takes over it + // once the initialization successfully finishes. + void setClient(MIDIAccessorClient* client) { m_client = client; } // blink::WebMIDIAccessorClient virtual void didAddInputPort(const blink::WebString& id, const blink::WebString& manufacturer, const blink::WebString& name, const blink::WebString& version) OVERRIDE; virtual void didAddOutputPort(const blink::WebString& id, const blink::WebString& manufacturer, const blink::WebString& name, const blink::WebString& version) OVERRIDE; - virtual void didStartSession(bool success) OVERRIDE; + virtual void didStartSession(bool success, const blink::WebString& error, const blink::WebString& message) OVERRIDE; virtual void didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp) OVERRIDE; private: diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessorClient.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessorClient.h index 450b8f60c0a..198374ffec0 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessorClient.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIAccessorClient.h @@ -40,7 +40,7 @@ public: virtual void didAddInputPort(const String& id, const String& manufacturer, const String& name, const String& version) = 0; virtual void didAddOutputPort(const String& id, const String& manufacturer, const String& name, const String& version) = 0; - virtual void didStartSession(bool success) = 0; + virtual void didStartSession(bool success, const String& error, const String& message) = 0; virtual void didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp) = 0; }; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClient.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClient.h index 5c797c4fb22..32daafe833e 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClient.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClient.h @@ -31,23 +31,22 @@ #ifndef MIDIClient_h #define MIDIClient_h -#include "wtf/PassRefPtr.h" +#include "platform/heap/Handle.h" namespace WebCore { -class MIDIAccess; -class Page; +class LocalFrame; +class MIDIAccessInitializer; class MIDIClient { public: - virtual void requestSysExPermission(PassRefPtr<MIDIAccess>) = 0; - virtual void cancelSysExPermissionRequest(MIDIAccess*) = 0; + virtual void requestSysexPermission(MIDIAccessInitializer*) = 0; + virtual void cancelSysexPermissionRequest(MIDIAccessInitializer*) = 0; -protected: virtual ~MIDIClient() { } }; -void provideMIDITo(Page*, MIDIClient*); +void provideMIDITo(LocalFrame&, PassOwnPtr<MIDIClient>); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClientMock.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClientMock.cpp index 800cf50fbb6..5b9f3976856 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClientMock.cpp +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClientMock.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "modules/webmidi/MIDIClientMock.h" -#include "modules/webmidi/MIDIAccess.h" +#include "modules/webmidi/MIDIAccessInitializer.h" namespace WebCore { @@ -44,7 +44,7 @@ MIDIClientMock::~MIDIClientMock() { } -void MIDIClientMock::setSysExPermission(bool allowed) +void MIDIClientMock::setSysexPermission(bool allowed) { m_allowed = allowed; } @@ -54,12 +54,12 @@ void MIDIClientMock::resetMock() m_allowed = false; } -void MIDIClientMock::requestSysExPermission(PassRefPtr<MIDIAccess> access) +void MIDIClientMock::requestSysexPermission(MIDIAccessInitializer* initializer) { - access->setSysExEnabled(m_allowed); + initializer->setSysexEnabled(m_allowed); } -void MIDIClientMock::cancelSysExPermissionRequest(MIDIAccess*) +void MIDIClientMock::cancelSysexPermissionRequest(MIDIAccessInitializer*) { } diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClientMock.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClientMock.h index 095b6b6e345..fedb2c280f8 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClientMock.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIClientMock.h @@ -32,21 +32,22 @@ #define MIDIClientMock_h #include "modules/webmidi/MIDIClient.h" +#include "platform/heap/Handle.h" namespace WebCore { // FIXME: This belongs in Source/testing/runner, not compiled into shipping Blink! -class MIDIClientMock : public MIDIClient { +class MIDIClientMock FINAL : public MIDIClient { public: MIDIClientMock(); virtual ~MIDIClientMock(); - void setSysExPermission(bool); + void setSysexPermission(bool); void resetMock(); // MIDIClient - virtual void requestSysExPermission(PassRefPtr<MIDIAccess>) OVERRIDE; - virtual void cancelSysExPermissionRequest(MIDIAccess*) OVERRIDE; + virtual void requestSysexPermission(MIDIAccessInitializer*) OVERRIDE; + virtual void cancelSysexPermissionRequest(MIDIAccessInitializer*) OVERRIDE; private: bool m_allowed; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIConnectionEvent.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIConnectionEvent.cpp new file mode 100644 index 00000000000..cd4692a0d3e --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIConnectionEvent.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "modules/webmidi/MIDIConnectionEvent.h" + +namespace WebCore { + +MIDIConnectionEvent::MIDIConnectionEvent() +{ + ScriptWrappable::init(this); +} + +MIDIConnectionEvent::MIDIConnectionEvent(const AtomicString& type, PassRefPtrWillBeRawPtr<MIDIPort> port) + : Event(type, false, false) + , m_port(port) +{ + ScriptWrappable::init(this); +} + +MIDIConnectionEvent::MIDIConnectionEvent(const AtomicString& type, const MIDIConnectionEventInit& initializer) + : Event(type, initializer) + , m_port(initializer.port) +{ + ScriptWrappable::init(this); +} + +PassRefPtrWillBeRawPtr<MIDIConnectionEvent> MIDIConnectionEvent::create() +{ + return adoptRefWillBeNoop(new MIDIConnectionEvent()); +} + +PassRefPtrWillBeRawPtr<MIDIConnectionEvent> MIDIConnectionEvent::create(const AtomicString& type, PassRefPtrWillBeRawPtr<MIDIPort> port) +{ + return adoptRefWillBeNoop(new MIDIConnectionEvent(type, port)); +} + +PassRefPtrWillBeRawPtr<MIDIConnectionEvent> MIDIConnectionEvent::create(const AtomicString& type, const MIDIConnectionEventInit& initializer) +{ + return adoptRefWillBeNoop(new MIDIConnectionEvent(type, initializer)); +} + +void MIDIConnectionEvent::trace(Visitor* visitor) +{ + visitor->trace(m_port); + Event::trace(visitor); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIConnectionEvent.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIConnectionEvent.h index 3579a70e57a..aad2888783e 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIConnectionEvent.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIConnectionEvent.h @@ -31,62 +31,38 @@ #ifndef MIDIConnectionEvent_h #define MIDIConnectionEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "modules/webmidi/MIDIPort.h" namespace WebCore { struct MIDIConnectionEventInit : public EventInit { MIDIConnectionEventInit() - : port(0) + : port(nullptr) { - }; + } - RefPtr<MIDIPort> port; + RefPtrWillBeMember<MIDIPort> port; }; -class MIDIConnectionEvent : public Event { +class MIDIConnectionEvent FINAL : public Event { public: - static PassRefPtr<MIDIConnectionEvent> create() - { - return adoptRef(new MIDIConnectionEvent()); - } - - static PassRefPtr<MIDIConnectionEvent> create(const AtomicString& type, PassRefPtr<MIDIPort> port) - { - return adoptRef(new MIDIConnectionEvent(type, port)); - } - - static PassRefPtr<MIDIConnectionEvent> create(const AtomicString& type, const MIDIConnectionEventInit& initializer) - { - return adoptRef(new MIDIConnectionEvent(type, initializer)); - } + static PassRefPtrWillBeRawPtr<MIDIConnectionEvent> create(); + static PassRefPtrWillBeRawPtr<MIDIConnectionEvent> create(const AtomicString&, PassRefPtrWillBeRawPtr<MIDIPort>); + static PassRefPtrWillBeRawPtr<MIDIConnectionEvent> create(const AtomicString&, const MIDIConnectionEventInit&); - RefPtr<MIDIPort> port() { return m_port; } + PassRefPtrWillBeRawPtr<MIDIPort> port() { return m_port; } virtual const AtomicString& interfaceName() const OVERRIDE { return EventNames::MIDIConnectionEvent; } -private: - MIDIConnectionEvent() - { - ScriptWrappable::init(this); - } + virtual void trace(Visitor*) OVERRIDE; - MIDIConnectionEvent(const AtomicString& type, PassRefPtr<MIDIPort> port) - : Event(type, false, false) - , m_port(port) - { - ScriptWrappable::init(this); - } - - MIDIConnectionEvent(const AtomicString& type, const MIDIConnectionEventInit& initializer) - : Event(type, initializer) - , m_port(initializer.port) - { - ScriptWrappable::init(this); - } +private: + MIDIConnectionEvent(); + MIDIConnectionEvent(const AtomicString&, PassRefPtrWillBeRawPtr<MIDIPort>); + MIDIConnectionEvent(const AtomicString&, const MIDIConnectionEventInit&); - RefPtr<MIDIPort> m_port; + RefPtrWillBeMember<MIDIPort> m_port; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIController.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIController.cpp index ab0f6177446..45d44da5bf8 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIController.cpp +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIController.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "modules/webmidi/MIDIController.h" -#include "modules/webmidi/MIDIAccess.h" +#include "modules/webmidi/MIDIAccessInitializer.h" #include "modules/webmidi/MIDIClient.h" namespace WebCore { @@ -41,34 +41,34 @@ const char* MIDIController::supplementName() return "MIDIController"; } -MIDIController::MIDIController(MIDIClient* client) +MIDIController::MIDIController(PassOwnPtr<MIDIClient> client) : m_client(client) { - ASSERT(client); + ASSERT(m_client); } MIDIController::~MIDIController() { } -PassOwnPtr<MIDIController> MIDIController::create(MIDIClient* client) +PassOwnPtrWillBeRawPtr<MIDIController> MIDIController::create(PassOwnPtr<MIDIClient> client) { - return adoptPtr(new MIDIController(client)); + return adoptPtrWillBeNoop(new MIDIController(client)); } -void MIDIController::requestSysExPermission(PassRefPtr<MIDIAccess> access) +void MIDIController::requestSysexPermission(MIDIAccessInitializer* initializer) { - m_client->requestSysExPermission(access); + m_client->requestSysexPermission(initializer); } -void MIDIController::cancelSysExPermissionRequest(MIDIAccess* access) +void MIDIController::cancelSysexPermissionRequest(MIDIAccessInitializer* initializer) { - m_client->cancelSysExPermissionRequest(access); + m_client->cancelSysexPermissionRequest(initializer); } -void provideMIDITo(Page* page, MIDIClient* client) +void provideMIDITo(LocalFrame& frame, PassOwnPtr<MIDIClient> client) { - MIDIController::provideTo(page, MIDIController::supplementName(), MIDIController::create(client)); + MIDIController::provideTo(frame, MIDIController::supplementName(), MIDIController::create(client)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIController.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIController.h index c947f18b1a5..2aff8a39254 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIController.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIController.h @@ -31,30 +31,33 @@ #ifndef MIDIController_h #define MIDIController_h -#include "core/page/Page.h" -#include "wtf/RefPtr.h" +#include "core/frame/LocalFrame.h" +#include "platform/heap/Handle.h" namespace WebCore { -class MIDIAccess; +class MIDIAccessInitializer; class MIDIClient; -class MIDIController : public Supplement<Page> { +class MIDIController FINAL : public NoBaseWillBeGarbageCollectedFinalized<MIDIController>, public WillBeHeapSupplement<LocalFrame> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MIDIController); public: - ~MIDIController(); + virtual ~MIDIController(); - void requestSysExPermission(PassRefPtr<MIDIAccess>); - void cancelSysExPermissionRequest(MIDIAccess*); + void requestSysexPermission(MIDIAccessInitializer*); + void cancelSysexPermissionRequest(MIDIAccessInitializer*); - static PassOwnPtr<MIDIController> create(MIDIClient*); + static PassOwnPtrWillBeRawPtr<MIDIController> create(PassOwnPtr<MIDIClient>); static const char* supplementName(); - static MIDIController* from(Page* page) { return static_cast<MIDIController*>(Supplement<Page>::from(page, supplementName())); } + static MIDIController* from(LocalFrame* frame) { return static_cast<MIDIController*>(WillBeHeapSupplement<LocalFrame>::from(frame, supplementName())); } + + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<LocalFrame>::trace(visitor); } protected: - explicit MIDIController(MIDIClient*); + explicit MIDIController(PassOwnPtr<MIDIClient>); private: - MIDIClient* m_client; + OwnPtr<MIDIClient> m_client; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.cpp index 748b844e226..10ed596fd29 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.cpp +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.cpp @@ -33,20 +33,19 @@ #include "modules/webmidi/MIDIAccess.h" #include "modules/webmidi/MIDIMessageEvent.h" +#include "platform/heap/Handle.h" namespace WebCore { -PassRefPtr<MIDIInput> MIDIInput::create(MIDIAccess* access, ExecutionContext* context, const String& id, const String& manufacturer, const String& name, const String& version) +PassRefPtrWillBeRawPtr<MIDIInput> MIDIInput::create(MIDIAccess* access, const String& id, const String& manufacturer, const String& name, const String& version) { ASSERT(access); - RefPtr<MIDIInput> input = adoptRef(new MIDIInput(access, context, id, manufacturer, name, version)); - input->suspendIfNeeded(); + RefPtrWillBeRawPtr<MIDIInput> input = adoptRefWillBeRefCountedGarbageCollected(new MIDIInput(access, id, manufacturer, name, version)); return input.release(); } -MIDIInput::MIDIInput(MIDIAccess* access, ExecutionContext* context, const String& id, const String& manufacturer, const String& name, const String& version) - : MIDIPort(context, id, manufacturer, name, MIDIPortTypeInput, version) - , m_access(access) +MIDIInput::MIDIInput(MIDIAccess* access, const String& id, const String& manufacturer, const String& name, const String& version) + : MIDIPort(access, id, manufacturer, name, MIDIPortTypeInput, version) { ScriptWrappable::init(this); } @@ -58,13 +57,18 @@ void MIDIInput::didReceiveMIDIData(unsigned portIndex, const unsigned char* data if (!length) return; - // Drop SysEx message here when the client does not request it. Note that this is not a security check but an - // automatic filtering for clients that do not want SysEx message. Also note that SysEx message will never be sent - // unless the current process has an explicit permission to handle SysEx message. - if (data[0] == 0xf0 && !m_access->sysExEnabled()) + // Drop sysex message here when the client does not request it. Note that this is not a security check but an + // automatic filtering for clients that do not want sysex message. Also note that sysex message will never be sent + // unless the current process has an explicit permission to handle sysex message. + if (data[0] == 0xf0 && !midiAccess()->sysexEnabled()) return; RefPtr<Uint8Array> array = Uint8Array::create(data, length); dispatchEvent(MIDIMessageEvent::create(timeStamp, array)); } +void MIDIInput::trace(Visitor* visitor) +{ + MIDIPort::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.h index 39f7efdd9fc..7901214af23 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.h @@ -31,17 +31,16 @@ #ifndef MIDIInput_h #define MIDIInput_h -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" #include "modules/webmidi/MIDIPort.h" namespace WebCore { class MIDIAccess; -class ExecutionContext; -class MIDIInput : public MIDIPort { +class MIDIInput FINAL : public MIDIPort { public: - static PassRefPtr<MIDIInput> create(MIDIAccess*, ExecutionContext*, const String& id, const String& manufacturer, const String& name, const String& version); + static PassRefPtrWillBeRawPtr<MIDIInput> create(MIDIAccess*, const String& id, const String& manufacturer, const String& name, const String& version); virtual ~MIDIInput() { } DEFINE_ATTRIBUTE_EVENT_LISTENER(midimessage); @@ -52,15 +51,13 @@ public: // |timeStamp| is a DOMHighResTimeStamp in the time coordinate system of performance.now(). void didReceiveMIDIData(unsigned portIndex, const unsigned char* data, size_t length, double timeStamp); - MIDIAccess* midiAccess() const { return m_access; } + virtual void trace(Visitor*) OVERRIDE; private: - MIDIInput(MIDIAccess*, ExecutionContext*, const String& id, const String& manufacturer, const String& name, const String& version); - - MIDIAccess* m_access; + MIDIInput(MIDIAccess*, const String& id, const String& manufacturer, const String& name, const String& version); }; -typedef Vector<RefPtr<MIDIInput> > MIDIInputVector; +typedef WillBeHeapVector<RefPtrWillBeMember<MIDIInput> > MIDIInputVector; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.idl b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.idl index 7f3db641fd8..4986c54630d 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.idl +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIInput.idl @@ -29,9 +29,8 @@ */ [ - ActiveDOMObject, - Custom=Wrap, NoInterfaceObject, + SetWrapperReferenceTo(MIDIAccess midiAccess), ] interface MIDIInput : MIDIPort { attribute EventHandler onmidimessage; }; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIMessageEvent.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIMessageEvent.h index 8c173ce6707..b4517e0c39b 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIMessageEvent.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIMessageEvent.h @@ -31,7 +31,7 @@ #ifndef MIDIMessageEvent_h #define MIDIMessageEvent_h -#include "core/events/Event.h" +#include "modules/EventModules.h" #include "wtf/Uint8Array.h" namespace WebCore { @@ -46,21 +46,21 @@ struct MIDIMessageEventInit : public EventInit { RefPtr<Uint8Array> data; }; -class MIDIMessageEvent : public Event { +class MIDIMessageEvent FINAL : public Event { public: - static PassRefPtr<MIDIMessageEvent> create() + static PassRefPtrWillBeRawPtr<MIDIMessageEvent> create() { - return adoptRef(new MIDIMessageEvent()); + return adoptRefWillBeNoop(new MIDIMessageEvent()); } - static PassRefPtr<MIDIMessageEvent> create(double receivedTime, PassRefPtr<Uint8Array> data) + static PassRefPtrWillBeRawPtr<MIDIMessageEvent> create(double receivedTime, PassRefPtr<Uint8Array> data) { - return adoptRef(new MIDIMessageEvent(receivedTime, data)); + return adoptRefWillBeNoop(new MIDIMessageEvent(receivedTime, data)); } - static PassRefPtr<MIDIMessageEvent> create(const AtomicString& type, const MIDIMessageEventInit& initializer) + static PassRefPtrWillBeRawPtr<MIDIMessageEvent> create(const AtomicString& type, const MIDIMessageEventInit& initializer) { - return adoptRef(new MIDIMessageEvent(type, initializer)); + return adoptRefWillBeNoop(new MIDIMessageEvent(type, initializer)); } double receivedTime() { return m_receivedTime; } @@ -68,6 +68,8 @@ public: virtual const AtomicString& interfaceName() const OVERRIDE { return EventNames::MIDIMessageEvent; } + virtual void trace(Visitor* visitor) OVERRIDE { Event::trace(visitor); } + private: MIDIMessageEvent() : m_receivedTime(0) diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.cpp index 44b3d77e780..268e9667a68 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.cpp +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.cpp @@ -33,21 +33,154 @@ #include "bindings/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" +#include "core/dom/ExecutionContext.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/timing/Performance.h" #include "modules/webmidi/MIDIAccess.h" namespace WebCore { -PassRefPtr<MIDIOutput> MIDIOutput::create(MIDIAccess* access, unsigned portIndex, ExecutionContext* context, const String& id, const String& manufacturer, const String& name, const String& version) +namespace { + +double now(ExecutionContext* context) +{ + LocalDOMWindow* window = context ? context->executingWindow() : 0; + Performance* performance = window ? &window->performance() : 0; + return performance ? performance->now() : 0.0; +} + +class MessageValidator { +public: + static bool validate(Uint8Array* array, ExceptionState& exceptionState, bool sysexEnabled) + { + MessageValidator validator(array); + return validator.process(exceptionState, sysexEnabled); + } +private: + MessageValidator(Uint8Array* array) + : m_data(array->data()) + , m_length(array->length()) + , m_offset(0) { } + + bool process(ExceptionState& exceptionState, bool sysexEnabled) + { + while (!isEndOfData() && acceptRealTimeMessages()) { + if (!isStatusByte()) { + exceptionState.throwTypeError("Running status is not allowed " + getPositionString()); + return false; + } + if (isEndOfSysex()) { + exceptionState.throwTypeError("Unexpected end of system exclusive message " + getPositionString()); + return false; + } + if (isReservedStatusByte()) { + exceptionState.throwTypeError("Reserved status is not allowed " + getPositionString()); + return false; + } + if (isSysex()) { + if (!sysexEnabled) { + exceptionState.throwDOMException(InvalidAccessError, "System exclusive message is not allowed " + getPositionString()); + return false; + } + if (!acceptCurrentSysex()) { + if (isEndOfData()) + exceptionState.throwTypeError("System exclusive message is not ended by end of system exclusive message."); + else + exceptionState.throwTypeError("System exclusive message contains a status byte " + getPositionString()); + return false; + } + } else { + if (!acceptCurrentMessage()) { + if (isEndOfData()) + exceptionState.throwTypeError("Message is incomplete."); + else + exceptionState.throwTypeError("Unexpected status byte at index " + getPositionString()); + return false; + } + } + } + return true; + } + +private: + bool isEndOfData() { return m_offset >= m_length; } + bool isSysex() { return m_data[m_offset] == 0xf0; } + bool isSystemMessage() { return m_data[m_offset] >= 0xf0; } + bool isEndOfSysex() { return m_data[m_offset] == 0xf7; } + bool isRealTimeMessage() { return m_data[m_offset] >= 0xf8; } + bool isStatusByte() { return m_data[m_offset] & 0x80; } + bool isReservedStatusByte() { return m_data[m_offset] == 0xf4 || m_data[m_offset] == 0xf5 || m_data[m_offset] == 0xf9 || m_data[m_offset] == 0xfd; } + + bool acceptRealTimeMessages() + { + for (; !isEndOfData(); m_offset++) { + if (isRealTimeMessage() && !isReservedStatusByte()) + continue; + return true; + } + return false; + } + + bool acceptCurrentSysex() + { + ASSERT(isSysex()); + for (m_offset++; !isEndOfData(); m_offset++) { + if (isReservedStatusByte()) + return false; + if (isRealTimeMessage()) + continue; + if (isEndOfSysex()) { + m_offset++; + return true; + } + if (isStatusByte()) + return false; + } + return false; + } + + bool acceptCurrentMessage() + { + ASSERT(isStatusByte()); + ASSERT(!isSysex()); + ASSERT(!isReservedStatusByte()); + ASSERT(!isRealTimeMessage()); + static const int channelMessageLength[7] = { 3, 3, 3, 3, 2, 2, 3 }; // for 0x8*, 0x9*, ..., 0xe* + static const int systemMessageLength[7] = { 2, 3, 2, 0, 0, 1, 0 }; // for 0xf1, 0xf2, ..., 0xf7 + size_t length = isSystemMessage() ? systemMessageLength[m_data[m_offset] - 0xf1] : channelMessageLength[(m_data[m_offset] >> 4) - 8]; + size_t count = 1; + for (m_offset++; !isEndOfData(); m_offset++) { + if (isReservedStatusByte()) + return false; + if (isRealTimeMessage()) + continue; + if (isStatusByte()) + return false; + if (++count == length) { + m_offset++; + return true; + } + } + return false; + } + + String getPositionString() { return "at index " + String::number(m_offset) + " (" + String::number(m_data[m_offset]) + ")."; } + + const unsigned char* m_data; + const size_t m_length; + size_t m_offset; +}; + +} // namespace + +PassRefPtrWillBeRawPtr<MIDIOutput> MIDIOutput::create(MIDIAccess* access, unsigned portIndex, const String& id, const String& manufacturer, const String& name, const String& version) { ASSERT(access); - RefPtr<MIDIOutput> output = adoptRef(new MIDIOutput(access, portIndex, context, id, manufacturer, name, version)); - output->suspendIfNeeded(); - return output.release(); + return adoptRefWillBeRefCountedGarbageCollected(new MIDIOutput(access, portIndex, id, manufacturer, name, version)); } -MIDIOutput::MIDIOutput(MIDIAccess* access, unsigned portIndex, ExecutionContext* context, const String& id, const String& manufacturer, const String& name, const String& version) - : MIDIPort(context, id, manufacturer, name, MIDIPortTypeOutput, version) - , m_access(access) +MIDIOutput::MIDIOutput(MIDIAccess* access, unsigned portIndex, const String& id, const String& manufacturer, const String& name, const String& version) + : MIDIPort(access, id, manufacturer, name, MIDIPortTypeOutput, version) , m_portIndex(portIndex) { ScriptWrappable::init(this); @@ -59,29 +192,26 @@ MIDIOutput::~MIDIOutput() void MIDIOutput::send(Uint8Array* array, double timestamp, ExceptionState& exceptionState) { - if (!array) - return; + if (timestamp == 0.0) + timestamp = now(executionContext()); - const unsigned char* data = array->data(); - size_t length = array->length(); - - // Filter out System Exclusive messages if we're not allowed. - // FIXME: implement more extensive filtering. - if (length > 0 && data[0] >= 0xf0 && !m_access->sysExEnabled()) { - exceptionState.throwSecurityError("permission to send system exclusive messages is denied."); + if (!array) return; - } - m_access->sendMIDIData(m_portIndex, data, length, timestamp); + if (MessageValidator::validate(array, exceptionState, midiAccess()->sysexEnabled())) + midiAccess()->sendMIDIData(m_portIndex, array->data(), array->length(), timestamp); } void MIDIOutput::send(Vector<unsigned> unsignedData, double timestamp, ExceptionState& exceptionState) { + if (timestamp == 0.0) + timestamp = now(executionContext()); + RefPtr<Uint8Array> array = Uint8Array::create(unsignedData.size()); for (size_t i = 0; i < unsignedData.size(); ++i) { if (unsignedData[i] > 0xff) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); + exceptionState.throwTypeError("The value at index " + String::number(i) + " (" + String::number(unsignedData[i]) + ") is greater than 0xFF."); return; } unsigned char value = unsignedData[i] & 0xff; @@ -93,12 +223,17 @@ void MIDIOutput::send(Vector<unsigned> unsignedData, double timestamp, Exception void MIDIOutput::send(Uint8Array* data, ExceptionState& exceptionState) { - send(data, 0, exceptionState); + send(data, 0.0, exceptionState); } void MIDIOutput::send(Vector<unsigned> unsignedData, ExceptionState& exceptionState) { - send(unsignedData, 0, exceptionState); + send(unsignedData, 0.0, exceptionState); +} + +void MIDIOutput::trace(Visitor* visitor) +{ + MIDIPort::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.h index 9f23c88adfb..4d1d996613f 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.h @@ -39,11 +39,10 @@ namespace WebCore { class ExceptionState; class MIDIAccess; -class ExecutionContext; -class MIDIOutput : public MIDIPort { +class MIDIOutput FINAL : public MIDIPort { public: - static PassRefPtr<MIDIOutput> create(MIDIAccess*, unsigned portIndex, ExecutionContext*, const String& id, const String& manufacturer, const String& name, const String& version); + static PassRefPtrWillBeRawPtr<MIDIOutput> create(MIDIAccess*, unsigned portIndex, const String& id, const String& manufacturer, const String& name, const String& version); virtual ~MIDIOutput(); void send(Uint8Array*, double timestamp, ExceptionState&); @@ -53,16 +52,15 @@ public: void send(Uint8Array*, ExceptionState&); void send(Vector<unsigned>, ExceptionState&); - MIDIAccess* midiAccess() const { return m_access; } + virtual void trace(Visitor*) OVERRIDE; private: - MIDIOutput(MIDIAccess*, unsigned portIndex, ExecutionContext*, const String& id, const String& manufacturer, const String& name, const String& version); + MIDIOutput(MIDIAccess*, unsigned portIndex, const String& id, const String& manufacturer, const String& name, const String& version); - MIDIAccess* m_access; unsigned m_portIndex; }; -typedef Vector<RefPtr<MIDIOutput> > MIDIOutputVector; +typedef WillBeHeapVector<RefPtrWillBeMember<MIDIOutput> > MIDIOutputVector; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.idl b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.idl index 726ed6465da..a41bcfb390c 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.idl +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIOutput.idl @@ -28,10 +28,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.w3.org/TR/webmidi/#idl-def-MIDIOutput +// http://cwilso.github.io/web-midi-api/#idl-def-MIDIOutput + [ - ActiveDOMObject, - Custom=Wrap, NoInterfaceObject, + SetWrapperReferenceTo(MIDIAccess midiAccess), ] interface MIDIOutput : MIDIPort { [RaisesException] void send(Uint8Array data, optional double timestamp); [RaisesException] void send(sequence<unsigned long> data, optional double timestamp); diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.cpp index 0e550401672..9525d24e839 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.cpp +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.cpp @@ -31,25 +31,23 @@ #include "config.h" #include "modules/webmidi/MIDIPort.h" +#include "modules/webmidi/MIDIAccess.h" + namespace WebCore { -MIDIPort::MIDIPort(ExecutionContext* context, const String& id, const String& manufacturer, const String& name, MIDIPortTypeCode type, const String& version) - : ActiveDOMObject(context) - , m_id(id) +MIDIPort::MIDIPort(MIDIAccess* access, const String& id, const String& manufacturer, const String& name, MIDIPortTypeCode type, const String& version) + : m_id(id) , m_manufacturer(manufacturer) , m_name(name) , m_type(type) , m_version(version) + , m_access(access) { + ASSERT(access); ASSERT(type == MIDIPortTypeInput || type == MIDIPortTypeOutput); ScriptWrappable::init(this); } -MIDIPort::~MIDIPort() -{ - stop(); -} - String MIDIPort::type() const { switch (m_type) { @@ -63,4 +61,15 @@ String MIDIPort::type() const return emptyString(); } +ExecutionContext* MIDIPort::executionContext() const +{ + return m_access->executionContext(); +} + +void MIDIPort::trace(Visitor* visitor) +{ + visitor->trace(m_access); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.h b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.h index e5f83abaf69..96d3085e5ec 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.h @@ -32,23 +32,26 @@ #define MIDIPort_h #include "bindings/v8/ScriptWrappable.h" -#include "core/dom/ActiveDOMObject.h" -#include "core/events/EventTarget.h" +#include "modules/EventTargetModules.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/Vector.h" namespace WebCore { -class MIDIPort : public RefCounted<MIDIPort>, public ScriptWrappable, public ActiveDOMObject, public EventTargetWithInlineData { +class MIDIAccess; + +class MIDIPort : public RefCountedWillBeRefCountedGarbageCollected<MIDIPort>, public ScriptWrappable, public EventTargetWithInlineData { REFCOUNTED_EVENT_TARGET(MIDIPort); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MIDIPort); public: enum MIDIPortTypeCode { MIDIPortTypeInput, MIDIPortTypeOutput }; - virtual ~MIDIPort(); + virtual ~MIDIPort() { } String id() const { return m_id; } String manufacturer() const { return m_manufacturer; } @@ -56,14 +59,18 @@ public: String type() const; String version() const { return m_version; } + MIDIAccess* midiAccess() const { return m_access; } + + virtual void trace(Visitor*) OVERRIDE; + DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect); // EventTarget virtual const AtomicString& interfaceName() const OVERRIDE { return EventTargetNames::MIDIPort; } - virtual ExecutionContext* executionContext() const OVERRIDE { return ActiveDOMObject::executionContext(); } + virtual ExecutionContext* executionContext() const OVERRIDE FINAL; protected: - MIDIPort(ExecutionContext*, const String& id, const String& manufacturer, const String& name, MIDIPortTypeCode, const String& version); + MIDIPort(MIDIAccess*, const String& id, const String& manufacturer, const String& name, MIDIPortTypeCode, const String& version); private: String m_id; @@ -71,10 +78,9 @@ private: String m_name; MIDIPortTypeCode m_type; String m_version; + RawPtrWillBeMember<MIDIAccess> m_access; }; -typedef Vector<RefPtr<MIDIPort> > MIDIPortVector; - } // namespace WebCore #endif // MIDIPort_h diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.idl b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.idl index 944cacb6834..3ca858a76e0 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.idl +++ b/chromium/third_party/WebKit/Source/modules/webmidi/MIDIPort.idl @@ -35,7 +35,6 @@ enum MIDIPortType { [ NoInterfaceObject, - ActiveDOMObject ] interface MIDIPort : EventTarget { readonly attribute DOMString id; readonly attribute DOMString manufacturer; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.cpp b/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.cpp index 87f7b25d31e..b668dcc6d45 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.cpp +++ b/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.cpp @@ -31,15 +31,18 @@ #include "config.h" #include "modules/webmidi/NavigatorWebMIDI.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolver.h" +#include "core/dom/DOMError.h" #include "core/dom/Document.h" -#include "core/dom/ExecutionContext.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" -#include "modules/webmidi/MIDIAccessPromise.h" +#include "modules/webmidi/MIDIAccessInitializer.h" +#include "modules/webmidi/MIDIOptions.h" namespace WebCore { -NavigatorWebMIDI::NavigatorWebMIDI(Frame* frame) +NavigatorWebMIDI::NavigatorWebMIDI(LocalFrame* frame) : DOMWindowProperty(frame) { } @@ -53,30 +56,32 @@ const char* NavigatorWebMIDI::supplementName() return "NavigatorWebMIDI"; } -NavigatorWebMIDI* NavigatorWebMIDI::from(Navigator* navigator) +NavigatorWebMIDI& NavigatorWebMIDI::from(Navigator& navigator) { - NavigatorWebMIDI* supplement = static_cast<NavigatorWebMIDI*>(Supplement<Navigator>::from(navigator, supplementName())); + NavigatorWebMIDI* supplement = static_cast<NavigatorWebMIDI*>(WillBeHeapSupplement<Navigator>::from(navigator, supplementName())); if (!supplement) { - supplement = new NavigatorWebMIDI(navigator->frame()); - provideTo(navigator, supplementName(), adoptPtr(supplement)); + supplement = new NavigatorWebMIDI(navigator.frame()); + provideTo(navigator, supplementName(), adoptPtrWillBeNoop(supplement)); } - return supplement; + return *supplement; } -PassRefPtr<MIDIAccessPromise> NavigatorWebMIDI::requestMIDIAccess(Navigator* navigator, const Dictionary& options) +ScriptPromise NavigatorWebMIDI::requestMIDIAccess(ScriptState* scriptState, Navigator& navigator, const Dictionary& options) { - return NavigatorWebMIDI::from(navigator)->requestMIDIAccess(options); + return NavigatorWebMIDI::from(navigator).requestMIDIAccess(scriptState, options); } -PassRefPtr<MIDIAccessPromise> NavigatorWebMIDI::requestMIDIAccess(const Dictionary& options) +ScriptPromise NavigatorWebMIDI::requestMIDIAccess(ScriptState* scriptState, const Dictionary& options) { - if (!frame()) - return 0; - - ExecutionContext* context = frame()->document(); - ASSERT(context); + if (!frame() || frame()->document()->activeDOMObjectsAreStopped()) { + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + // FIXME: Currently this rejection does not work because the context is stopped. + resolver->reject(DOMError::create("AbortError")); + return promise; + } - return MIDIAccessPromise::create(context, options); + return MIDIAccessInitializer::start(scriptState, MIDIOptions(options)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.h b/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.h index 1b6e73bc191..4e21441851a 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.h +++ b/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.h @@ -31,25 +31,29 @@ #ifndef NavigatorWebMIDI_h #define NavigatorWebMIDI_h +#include "bindings/v8/ScriptPromise.h" #include "core/frame/DOMWindowProperty.h" #include "modules/webmidi/MIDIOptions.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" namespace WebCore { -class MIDIAccessPromise; class Navigator; -class NavigatorWebMIDI : public Supplement<Navigator>, public DOMWindowProperty { +class NavigatorWebMIDI FINAL : public NoBaseWillBeGarbageCollectedFinalized<NavigatorWebMIDI>, public WillBeHeapSupplement<Navigator>, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(NavigatorWebMIDI); public: virtual ~NavigatorWebMIDI(); - static NavigatorWebMIDI* from(Navigator*); + static NavigatorWebMIDI& from(Navigator&); - static PassRefPtr<MIDIAccessPromise> requestMIDIAccess(Navigator*, const Dictionary&); - PassRefPtr<MIDIAccessPromise> requestMIDIAccess(const Dictionary&); + static ScriptPromise requestMIDIAccess(ScriptState*, Navigator&, const Dictionary&); + ScriptPromise requestMIDIAccess(ScriptState*, const Dictionary&); + + virtual void trace(Visitor* visitor) OVERRIDE { WillBeHeapSupplement<Navigator>::trace(visitor); } private: - NavigatorWebMIDI(Frame*); + NavigatorWebMIDI(LocalFrame*); static const char* supplementName(); }; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.idl b/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.idl index e8ad27d70b0..6a275d5b26f 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.idl +++ b/chromium/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.idl @@ -28,6 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -partial interface Navigator { - [RuntimeEnabled=WebMIDI] MIDIAccessPromise requestMIDIAccess(optional Dictionary options); +[ + RuntimeEnabled=WebMIDI, +] partial interface Navigator { + [CallWith=ScriptState] Promise requestMIDIAccess(optional Dictionary options); }; diff --git a/chromium/third_party/WebKit/Source/modules/webmidi/OWNERS b/chromium/third_party/WebKit/Source/modules/webmidi/OWNERS index 88c0a7fa556..eed18af1fc9 100644 --- a/chromium/third_party/WebKit/Source/modules/webmidi/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/webmidi/OWNERS @@ -1,2 +1,3 @@ kouhei@chromium.org toyoshim@chromium.org +yhirano@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/websockets/CloseEvent.h b/chromium/third_party/WebKit/Source/modules/websockets/CloseEvent.h index 3b710d9123e..c23eef8c454 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/CloseEvent.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/CloseEvent.h @@ -31,8 +31,7 @@ #ifndef CloseEvent_h #define CloseEvent_h -#include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" +#include "modules/EventModules.h" namespace WebCore { @@ -48,21 +47,21 @@ struct CloseEventInit : public EventInit { String reason; }; -class CloseEvent : public Event { +class CloseEvent FINAL : public Event { public: - static PassRefPtr<CloseEvent> create() + static PassRefPtrWillBeRawPtr<CloseEvent> create() { - return adoptRef(new CloseEvent()); + return adoptRefWillBeNoop(new CloseEvent()); } - static PassRefPtr<CloseEvent> create(bool wasClean, unsigned short code, const String& reason) + static PassRefPtrWillBeRawPtr<CloseEvent> create(bool wasClean, unsigned short code, const String& reason) { - return adoptRef(new CloseEvent(wasClean, code, reason)); + return adoptRefWillBeNoop(new CloseEvent(wasClean, code, reason)); } - static PassRefPtr<CloseEvent> create(const AtomicString& type, const CloseEventInit& initializer) + static PassRefPtrWillBeRawPtr<CloseEvent> create(const AtomicString& type, const CloseEventInit& initializer) { - return adoptRef(new CloseEvent(type, initializer)); + return adoptRefWillBeNoop(new CloseEvent(type, initializer)); } bool wasClean() const { return m_wasClean; } @@ -72,6 +71,8 @@ public: // Event function. virtual const AtomicString& interfaceName() const OVERRIDE { return EventNames::CloseEvent; } + virtual void trace(Visitor* visitor) OVERRIDE { Event::trace(visitor); } + private: CloseEvent() : Event(EventTypeNames::close, false, false) diff --git a/chromium/third_party/WebKit/Source/modules/websockets/MainThreadWebSocketChannel.cpp b/chromium/third_party/WebKit/Source/modules/websockets/MainThreadWebSocketChannel.cpp index 96e20c227ea..8bb864a6b39 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/MainThreadWebSocketChannel.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/MainThreadWebSocketChannel.cpp @@ -36,12 +36,13 @@ #include "core/dom/ExecutionContext.h" #include "core/fileapi/Blob.h" #include "core/fileapi/FileReaderLoader.h" +#include "core/frame/LocalFrame.h" #include "core/inspector/InspectorInstrumentation.h" -#include "core/loader/CookieJar.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" +#include "core/loader/MixedContentChecker.h" #include "core/loader/UniqueIdentifier.h" -#include "core/frame/Frame.h" #include "core/page/Page.h" #include "modules/websockets/WebSocketChannelClient.h" #include "platform/Logging.h" @@ -71,11 +72,11 @@ MainThreadWebSocketChannel::MainThreadWebSocketChannel(Document* document, WebSo , m_closingTimer(this, &MainThreadWebSocketChannel::closingTimerFired) , m_state(ChannelIdle) , m_shouldDiscardReceivedData(false) - , m_unhandledBufferedAmount(0) , m_identifier(0) , m_hasContinuousFrame(false) , m_closeEventCode(CloseEventCodeAbnormalClosure) , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) + , m_numConsumedBytesInCurrentFrame(0) , m_blobLoaderStatus(BlobLoaderNotStarted) , m_sourceURLAtConstruction(sourceURL) , m_lineNumberAtConstruction(lineNumber) @@ -88,47 +89,45 @@ MainThreadWebSocketChannel::~MainThreadWebSocketChannel() { } -void MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol) +bool MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol) { WTF_LOG(Network, "MainThreadWebSocketChannel %p connect()", this); ASSERT(!m_handle); ASSERT(!m_suspended); + + if (m_document->frame() && !m_document->frame()->loader().mixedContentChecker()->canConnectInsecureWebSocket(m_document->securityOrigin(), url)) + return false; + if (MixedContentChecker::isMixedContent(m_document->securityOrigin(), url)) { + String message = "Connecting to a non-secure WebSocket server from a secure origin is deprecated."; + m_document->addConsoleMessage(JSMessageSource, WarningMessageLevel, message); + } + m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document)); m_handshake->reset(); m_handshake->addExtensionProcessor(m_perMessageDeflate.createExtensionProcessor()); m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor()); - if (m_identifier) + if (m_identifier) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketCreate", "data", InspectorWebSocketCreateEvent::data(m_document, m_identifier, url, protocol)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, url, protocol); + } ref(); - m_handle = SocketStreamHandle::create(m_handshake->url(), this); -} -String MainThreadWebSocketChannel::subprotocol() -{ - WTF_LOG(Network, "MainThreadWebSocketChannel %p subprotocol()", this); - if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) - return ""; - String serverProtocol = m_handshake->serverWebSocketProtocol(); - if (serverProtocol.isNull()) - return ""; - return serverProtocol; -} + m_handle = SocketStreamHandle::create(this); + ASSERT(m_handle); + if (m_document->frame()) { + m_document->frame()->loader().client()->dispatchWillOpenSocketStream(m_handle.get()); + } + m_handle->connect(m_handshake->url()); -String MainThreadWebSocketChannel::extensions() -{ - WTF_LOG(Network, "MainThreadWebSocketChannel %p extensions()", this); - if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) - return ""; - String extensions = m_handshake->acceptedExtensions(); - if (extensions.isNull()) - return ""; - return extensions; + return true; } WebSocketChannel::SendResult MainThreadWebSocketChannel::send(const String& message) { WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending String '%s'", this, message.utf8().data()); - CString utf8 = message.utf8(String::StrictConversionReplacingUnpairedSurrogatesWithFFFD); + CString utf8 = message.utf8(StrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD); enqueueTextFrame(utf8); processOutgoingFrameQueue(); // m_channel->send() may happen later, thus it's not always possible to know whether @@ -153,20 +152,12 @@ WebSocketChannel::SendResult MainThreadWebSocketChannel::send(PassRefPtr<BlobDat return WebSocketChannel::SendSuccess; } -bool MainThreadWebSocketChannel::send(const char* data, int length) +WebSocketChannel::SendResult MainThreadWebSocketChannel::send(PassOwnPtr<Vector<char> > data) { - WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending char* data=%p length=%d", this, data, length); - enqueueRawFrame(WebSocketFrame::OpCodeBinary, data, length); + WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending Vector %p", this, data.get()); + enqueueVector(WebSocketFrame::OpCodeBinary, data); processOutgoingFrameQueue(); - return true; -} - -unsigned long MainThreadWebSocketChannel::bufferedAmount() const -{ - WTF_LOG(Network, "MainThreadWebSocketChannel %p bufferedAmount()", this); - ASSERT(m_handle); - ASSERT(!m_suspended); - return m_handle->bufferedAmount(); + return WebSocketChannel::SendSuccess; } void MainThreadWebSocketChannel::close(int code, const String& reason) @@ -177,7 +168,14 @@ void MainThreadWebSocketChannel::close(int code, const String& reason) return; startClosingHandshake(code, reason); if (!m_closingTimer.isActive()) - m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime); + m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime, FROM_HERE); +} + +void MainThreadWebSocketChannel::clearDocument() +{ + if (m_handshake) + m_handshake->clearDocument(); + m_document = 0; } void MainThreadWebSocketChannel::disconnectHandle() @@ -188,6 +186,14 @@ void MainThreadWebSocketChannel::disconnectHandle() m_handle->disconnect(); } +void MainThreadWebSocketChannel::callDidReceiveMessageError() +{ + if (!m_client || m_didFailOfClientAlreadyRun) + return; + m_didFailOfClientAlreadyRun = true; + m_client->didReceiveMessageError(); +} + void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber) { WTF_LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reason.utf8().data()); @@ -198,7 +204,7 @@ void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level, } // Hybi-10 specification explicitly states we must not continue to handle incoming data // once the WebSocket connection is failed (section 7.1.7). - RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. + RefPtrWillBeRawPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. m_shouldDiscardReceivedData = true; if (!m_buffer.isEmpty()) skipBuffer(m_buffer.size()); // Save memory. @@ -206,11 +212,9 @@ void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level, m_perMessageDeflate.didFail(); m_hasContinuousFrame = false; m_continuousFrameData.clear(); - if (!m_didFailOfClientAlreadyRun) { - m_didFailOfClientAlreadyRun = true; - if (m_client) - m_client->didReceiveMessageError(); - } + + callDidReceiveMessageError(); + if (m_state != ChannelClosed) disconnectHandle(); // Will call didCloseSocketStream(). } @@ -218,12 +222,16 @@ void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level, void MainThreadWebSocketChannel::disconnect() { WTF_LOG(Network, "MainThreadWebSocketChannel %p disconnect()", this); - if (m_identifier && m_document) + if (m_identifier && m_document) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketDestroy", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); - if (m_handshake) - m_handshake->clearExecutionContext(); + } + + clearDocument(); + m_client = 0; - m_document = 0; disconnectHandle(); } @@ -236,15 +244,7 @@ void MainThreadWebSocketChannel::resume() { m_suspended = false; if ((!m_buffer.isEmpty() || (m_state == ChannelClosed)) && m_client && !m_resumeTimer.isActive()) - m_resumeTimer.startOneShot(0); -} - -void MainThreadWebSocketChannel::willOpenSocketStream(SocketStreamHandle* handle) -{ - WTF_LOG(Network, "MainThreadWebSocketChannel %p willOpenSocketStream()", this); - ASSERT(handle); - if (m_document->frame()) - m_document->frame()->loader().client()->dispatchWillOpenSocketStream(handle); + m_resumeTimer.startOneShot(0, FROM_HERE); } void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) @@ -253,8 +253,12 @@ void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) ASSERT(handle == m_handle); if (!m_document) return; - if (m_identifier) - InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, *m_handshake->clientHandshakeRequest()); + if (m_identifier) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketSendHandshakeRequest", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. + InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, m_handshake->clientHandshakeRequest().get()); + } CString handshakeMessage = m_handshake->clientHandshakeMessage(); if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) failAsError("Failed to send WebSocket handshake."); @@ -263,8 +267,12 @@ void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle) { WTF_LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this); - if (m_identifier && m_document) + if (m_identifier && m_document) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketDestroy", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); + } ASSERT_UNUSED(handle, handle == m_handle || !m_handle); // Show error message on JS console if this is unexpected connection close @@ -280,13 +288,12 @@ void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle if (m_outgoingFrameQueueStatus != OutgoingFrameQueueClosed) abortOutgoingFrameQueue(); if (m_handle) { - m_unhandledBufferedAmount = m_handle->bufferedAmount(); WebSocketChannelClient* client = m_client; m_client = 0; - m_document = 0; - m_handle = 0; + clearDocument(); + m_handle = nullptr; if (client) - client->didClose(m_unhandledBufferedAmount, m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete, m_closeEventCode, m_closeEventReason); + client->didClose(m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete, m_closeEventCode, m_closeEventReason); } deref(); } @@ -294,7 +301,7 @@ void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle void MainThreadWebSocketChannel::didReceiveSocketStreamData(SocketStreamHandle* handle, const char* data, int len) { WTF_LOG(Network, "MainThreadWebSocketChannel %p didReceiveSocketStreamData() Received %d bytes", this, len); - RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. + RefPtrWillBeRawPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. ASSERT(handle == m_handle); if (!m_document) return; @@ -317,10 +324,35 @@ void MainThreadWebSocketChannel::didReceiveSocketStreamData(SocketStreamHandle* processBuffer(); } -void MainThreadWebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, size_t bufferedAmount) +void MainThreadWebSocketChannel::didConsumeBufferedAmount(SocketStreamHandle*, size_t consumed) { - if (m_client) - m_client->didUpdateBufferedAmount(bufferedAmount); + if (m_framingOverheadQueue.isEmpty()) { + // Ignore the handshake consumption. + return; + } + if (!m_client || m_state == ChannelClosed) + return; + size_t remain = consumed; + while (remain > 0) { + ASSERT(!m_framingOverheadQueue.isEmpty()); + const FramingOverhead& frame = m_framingOverheadQueue.first(); + + ASSERT(m_numConsumedBytesInCurrentFrame <= frame.frameDataSize()); + size_t consumedInThisFrame = std::min(remain, frame.frameDataSize() - m_numConsumedBytesInCurrentFrame); + remain -= consumedInThisFrame; + m_numConsumedBytesInCurrentFrame += consumedInThisFrame; + + if (m_numConsumedBytesInCurrentFrame == frame.frameDataSize()) { + if (m_client && WebSocketFrame::isNonControlOpCode(frame.opcode())) { + // FIXME: As |consumed| is the number of possibly compressed + // bytes, we can't determine the number of consumed original + // bytes in the middle of a frame. + m_client->didConsumeBufferedAmount(frame.originalPayloadLength()); + } + m_framingOverheadQueue.takeFirst(); + m_numConsumedBytesInCurrentFrame = 0; + } + } } void MainThreadWebSocketChannel::didFailSocketStream(SocketStreamHandle* handle, const SocketStreamError& error) @@ -340,11 +372,12 @@ void MainThreadWebSocketChannel::didFailSocketStream(SocketStreamHandle* handle, if (failingURL.isNull()) failingURL = m_handshake->url().string(); WTF_LOG(Network, "Error Message: '%s', FailURL: '%s'", message.utf8().data(), failingURL.utf8().data()); - RefPtr<WebSocketChannel> protect(this); - if (m_client && (m_state != ChannelClosing && m_state != ChannelClosed) && !m_didFailOfClientAlreadyRun) { - m_didFailOfClientAlreadyRun = true; - m_client->didReceiveMessageError(); - } + + RefPtrWillBeRawPtr<WebSocketChannel> protect(this); + + if (m_state != ChannelClosing && m_state != ChannelClosed) + callDidReceiveMessageError(); + if (m_state != ChannelClosed) disconnectHandle(); } @@ -425,31 +458,29 @@ bool MainThreadWebSocketChannel::processOneItemFromBuffer() return false; } - RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. + RefPtrWillBeRawPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. if (m_handshake->mode() == WebSocketHandshake::Incomplete) { int headerLength = m_handshake->readServerHandshake(m_buffer.data(), m_buffer.size()); if (headerLength <= 0) return false; if (m_handshake->mode() == WebSocketHandshake::Connected) { - if (m_identifier) - InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(m_document, m_identifier, m_handshake->serverHandshakeResponse()); + if (m_identifier) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketReceiveHandshakeResponse", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. + InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(m_document, m_identifier, 0, &m_handshake->serverHandshakeResponse()); + } if (m_deflateFramer.enabled() && m_document) { const String message = "WebSocket extension \"x-webkit-deflate-frame\" is deprecated"; m_document->addConsoleMessage(JSMessageSource, WarningMessageLevel, message, m_sourceURLAtConstruction, m_lineNumberAtConstruction); } - if (!m_handshake->serverSetCookie().isEmpty()) { - if (cookiesEnabled(m_document)) { - // Exception (for sandboxed documents) ignored. - m_document->setCookie(m_handshake->serverSetCookie(), IGNORE_EXCEPTION); - } - } - // FIXME: handle set-cookie2. WTF_LOG(Network, "MainThreadWebSocketChannel %p Connected", this); skipBuffer(headerLength); - m_client->didConnect(); + String subprotocol = m_handshake->serverWebSocketProtocol(); + String extensions = m_handshake->acceptedExtensions(); + m_client->didConnect(subprotocol.isNull() ? "" : subprotocol, extensions.isNull() ? "" : extensions); WTF_LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m_buffer", this, static_cast<unsigned long>(m_buffer.size())); return !m_buffer.isEmpty(); } @@ -470,7 +501,7 @@ void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChann { ASSERT_UNUSED(timer, timer == &m_resumeTimer); - RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. + RefPtrWillBeRawPtr<MainThreadWebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference. processBuffer(); if (!m_suspended && m_client && (m_state == ChannelClosed) && m_handle) didCloseSocketStream(m_handle.get()); @@ -567,11 +598,11 @@ bool MainThreadWebSocketChannel::processFrame() // A new data frame is received before the previous continuous frame finishes. // Note that control frames are allowed to come in the middle of continuous frames. if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuation && !WebSocketFrame::isControlOpCode(frame.opCode)) { - failAsError("Received new data frame but previous continuous frame is unfinished."); + failAsError("Received start of new message but previous message is unfinished."); return false; } - InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame); + InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame.opCode, frame.masked, frame.payload, frame.payloadLength); switch (frame.opCode) { case WebSocketFrame::OpCodeContinuation: @@ -601,8 +632,9 @@ bool MainThreadWebSocketChannel::processFrame() failAsError("Could not decode a text frame as UTF-8."); else m_client->didReceiveMessage(message); - } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) + } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) { m_client->didReceiveBinaryData(continuousFrameData.release()); + } } break; @@ -643,9 +675,9 @@ bool MainThreadWebSocketChannel::processFrame() break; case WebSocketFrame::OpCodeClose: - if (!frame.payloadLength) + if (!frame.payloadLength) { m_closeEventCode = CloseEventCodeNoStatusRcvd; - else if (frame.payloadLength == 1) { + } else if (frame.payloadLength == 1) { m_closeEventCode = CloseEventCodeAbnormalClosure; failAsError("Received a broken close frame containing an invalid size body."); return false; @@ -695,6 +727,7 @@ bool MainThreadWebSocketChannel::processFrame() void MainThreadWebSocketChannel::enqueueTextFrame(const CString& string) { ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); + OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); frame->opCode = WebSocketFrame::OpCodeText; frame->frameType = QueuedFrameTypeString; @@ -705,6 +738,7 @@ void MainThreadWebSocketChannel::enqueueTextFrame(const CString& string) void MainThreadWebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) { ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); + OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); frame->opCode = opCode; frame->frameType = QueuedFrameTypeVector; @@ -714,9 +748,21 @@ void MainThreadWebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, m_outgoingFrameQueue.append(frame.release()); } +void MainThreadWebSocketChannel::enqueueVector(WebSocketFrame::OpCode opCode, PassOwnPtr<Vector<char> > data) +{ + ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); + + OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); + frame->opCode = opCode; + frame->frameType = QueuedFrameTypeVector; + frame->vectorData.swap(*data); + m_outgoingFrameQueue.append(frame.release()); +} + void MainThreadWebSocketChannel::enqueueBlobFrame(WebSocketFrame::OpCode opCode, PassRefPtr<BlobDataHandle> blobData) { ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); + OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); frame->opCode = opCode; frame->frameType = QueuedFrameTypeBlob; @@ -800,7 +846,7 @@ bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const ASSERT(!m_suspended); WebSocketFrame frame(opCode, data, dataLength, WebSocketFrame::Final | WebSocketFrame::Masked); - InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, frame); + InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, frame.opCode, frame.masked, frame.payload, frame.payloadLength); OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); if (!deflateResult->succeeded()) { @@ -815,6 +861,7 @@ bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const Vector<char> frameData; frame.makeFrameData(frameData); + m_framingOverheadQueue.append(FramingOverhead(opCode, frameData.size(), dataLength)); m_perMessageDeflate.resetDeflateBuffer(); return m_handle->send(frameData.data(), frameData.size()); diff --git a/chromium/third_party/WebKit/Source/modules/websockets/MainThreadWebSocketChannel.h b/chromium/third_party/WebKit/Source/modules/websockets/MainThreadWebSocketChannel.h index 5a4532c7e1c..729792e3f46 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/MainThreadWebSocketChannel.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/MainThreadWebSocketChannel.h @@ -44,7 +44,6 @@ #include "wtf/Deque.h" #include "wtf/Forward.h" #include "wtf/PassOwnPtr.h" -#include "wtf/RefCounted.h" #include "wtf/Vector.h" #include "wtf/text/CString.h" @@ -57,63 +56,76 @@ class SocketStreamHandle; class SocketStreamError; class WebSocketChannelClient; -class MainThreadWebSocketChannel : public RefCounted<MainThreadWebSocketChannel>, public SocketStreamHandleClient, public WebSocketChannel, public FileReaderLoaderClient { - WTF_MAKE_FAST_ALLOCATED; +class MainThreadWebSocketChannel FINAL : public WebSocketChannel, public SocketStreamHandleClient, public FileReaderLoaderClient { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: // You can specify the source file and the line number information // explicitly by passing the last parameter. // In the usual case, they are set automatically and you don't have to // pass it. - static PassRefPtr<MainThreadWebSocketChannel> create(Document* document, WebSocketChannelClient* client, const String& sourceURL = String(), unsigned lineNumber = 0) { return adoptRef(new MainThreadWebSocketChannel(document, client, sourceURL, lineNumber)); } + static PassRefPtrWillBeRawPtr<MainThreadWebSocketChannel> create(Document* document, WebSocketChannelClient* client, const String& sourceURL = String(), unsigned lineNumber = 0) + { + return adoptRefWillBeRefCountedGarbageCollected(new MainThreadWebSocketChannel(document, client, sourceURL, lineNumber)); + } virtual ~MainThreadWebSocketChannel(); - bool send(const char* data, int length); - // WebSocketChannel functions. - virtual void connect(const KURL&, const String& protocol) OVERRIDE; - virtual String subprotocol() OVERRIDE; - virtual String extensions() OVERRIDE; + virtual bool connect(const KURL&, const String& protocol) OVERRIDE; virtual WebSocketChannel::SendResult send(const String& message) OVERRIDE; virtual WebSocketChannel::SendResult send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength) OVERRIDE; virtual WebSocketChannel::SendResult send(PassRefPtr<BlobDataHandle>) OVERRIDE; - virtual unsigned long bufferedAmount() const OVERRIDE; + virtual WebSocketChannel::SendResult send(PassOwnPtr<Vector<char> > data) OVERRIDE; // Start closing handshake. Use the CloseEventCodeNotSpecified for the code // argument to omit payload. virtual void close(int code, const String& reason) OVERRIDE; virtual void fail(const String& reason, MessageLevel, const String&, unsigned lineNumber) OVERRIDE; - using WebSocketChannel::fail; virtual void disconnect() OVERRIDE; virtual void suspend() OVERRIDE; virtual void resume() OVERRIDE; // SocketStreamHandleClient functions. - virtual void willOpenSocketStream(SocketStreamHandle*) OVERRIDE; virtual void didOpenSocketStream(SocketStreamHandle*) OVERRIDE; virtual void didCloseSocketStream(SocketStreamHandle*) OVERRIDE; virtual void didReceiveSocketStreamData(SocketStreamHandle*, const char*, int) OVERRIDE; - virtual void didUpdateBufferedAmount(SocketStreamHandle*, size_t bufferedAmount) OVERRIDE; + virtual void didConsumeBufferedAmount(SocketStreamHandle*, size_t consumed) OVERRIDE; virtual void didFailSocketStream(SocketStreamHandle*, const SocketStreamError&) OVERRIDE; // FileReaderLoaderClient functions. - virtual void didStartLoading(); - virtual void didReceiveData(); - virtual void didFinishLoading(); - virtual void didFail(FileError::ErrorCode); - - using RefCounted<MainThreadWebSocketChannel>::ref; - using RefCounted<MainThreadWebSocketChannel>::deref; - -protected: - // WebSocketChannel functions. - virtual void refWebSocketChannel() OVERRIDE { ref(); } - virtual void derefWebSocketChannel() OVERRIDE { deref(); } + virtual void didStartLoading() OVERRIDE; + virtual void didReceiveData() OVERRIDE; + virtual void didFinishLoading() OVERRIDE; + virtual void didFail(FileError::ErrorCode) OVERRIDE; private: MainThreadWebSocketChannel(Document*, WebSocketChannelClient*, const String&, unsigned); + class FramingOverhead { + public: + FramingOverhead(WebSocketFrame::OpCode opcode, size_t frameDataSize, size_t originalPayloadLength) + : m_opcode(opcode) + , m_frameDataSize(frameDataSize) + , m_originalPayloadLength(originalPayloadLength) + { + } + + WebSocketFrame::OpCode opcode() const { return m_opcode; } + size_t frameDataSize() const { return m_frameDataSize; } + size_t originalPayloadLength() const { return m_originalPayloadLength; } + + private: + WebSocketFrame::OpCode m_opcode; + size_t m_frameDataSize; + size_t m_originalPayloadLength; + }; + + void clearDocument(); + void disconnectHandle(); + // Calls didReceiveMessageError() on m_client if we haven't yet. + void callDidReceiveMessageError(); + bool appendToBuffer(const char* data, size_t len); void skipBuffer(size_t len); // Repeats parsing data from m_buffer until instructed to stop. @@ -150,6 +162,7 @@ private: }; void enqueueTextFrame(const CString&); void enqueueRawFrame(WebSocketFrame::OpCode, const char* data, size_t dataLength); + void enqueueVector(WebSocketFrame::OpCode, PassOwnPtr<Vector<char> >); void enqueueBlobFrame(WebSocketFrame::OpCode, PassRefPtr<BlobDataHandle>); void failAsError(const String& reason) { fail(reason, ErrorMessageLevel, m_sourceURLAtConstruction, m_lineNumberAtConstruction); } @@ -201,7 +214,6 @@ private: Timer<MainThreadWebSocketChannel> m_closingTimer; ChannelState m_state; bool m_shouldDiscardReceivedData; - unsigned long m_unhandledBufferedAmount; unsigned long m_identifier; // m_identifier == 0 means that we could not obtain a valid identifier. @@ -214,6 +226,10 @@ private: Deque<OwnPtr<QueuedFrame> > m_outgoingFrameQueue; OutgoingFrameQueueStatus m_outgoingFrameQueueStatus; + Deque<FramingOverhead> m_framingOverheadQueue; + // The number of bytes that are already consumed (i.e. sent) in the + // current frame. + size_t m_numConsumedBytesInCurrentFrame; // FIXME: Load two or more Blobs simultaneously for better performance. OwnPtr<FileReaderLoader> m_blobLoader; diff --git a/chromium/third_party/WebKit/Source/modules/websockets/NewWebSocketChannelImpl.cpp b/chromium/third_party/WebKit/Source/modules/websockets/NewWebSocketChannelImpl.cpp index d3a016f5017..6d74ff666b6 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/NewWebSocketChannelImpl.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/NewWebSocketChannelImpl.cpp @@ -35,12 +35,20 @@ #include "core/dom/ExecutionContext.h" #include "core/fileapi/FileReaderLoader.h" #include "core/fileapi/FileReaderLoaderClient.h" +#include "core/frame/LocalFrame.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" +#include "core/loader/FrameLoader.h" +#include "core/loader/FrameLoaderClient.h" +#include "core/loader/MixedContentChecker.h" #include "core/loader/UniqueIdentifier.h" #include "modules/websockets/WebSocketChannelClient.h" +#include "modules/websockets/WebSocketFrame.h" #include "platform/Logging.h" +#include "platform/network/WebSocketHandshakeRequest.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" +#include "public/platform/WebSerializedOrigin.h" #include "public/platform/WebSocketHandshakeRequestInfo.h" #include "public/platform/WebSocketHandshakeResponseInfo.h" #include "public/platform/WebString.h" @@ -51,7 +59,7 @@ using blink::WebSocketHandle; namespace WebCore { -class NewWebSocketChannelImpl::BlobLoader : public FileReaderLoaderClient { +class NewWebSocketChannelImpl::BlobLoader FINAL : public NoBaseWillBeGarbageCollectedFinalized<NewWebSocketChannelImpl::BlobLoader>, public FileReaderLoaderClient { public: BlobLoader(PassRefPtr<BlobDataHandle>, NewWebSocketChannelImpl*); virtual ~BlobLoader() { } @@ -64,8 +72,13 @@ public: virtual void didFinishLoading() OVERRIDE; virtual void didFail(FileError::ErrorCode) OVERRIDE; + void trace(Visitor* visitor) + { + visitor->trace(m_channel); + } + private: - NewWebSocketChannelImpl* m_channel; + RawPtrWillBeMember<NewWebSocketChannelImpl> m_channel; FileReaderLoader m_loader; }; @@ -102,7 +115,6 @@ NewWebSocketChannelImpl::NewWebSocketChannelImpl(ExecutionContext* context, WebS , m_identifier(0) , m_sendingQuota(0) , m_receivedDataSizeForFlowControl(receivedDataSizeForFlowControlHighWaterMark * 2) // initial quota - , m_bufferedAmount(0) , m_sentSizeOfTopMessage(0) , m_sourceURLAtConstruction(sourceURL) , m_lineNumberAtConstruction(lineNumber) @@ -116,11 +128,19 @@ NewWebSocketChannelImpl::~NewWebSocketChannelImpl() abortAsyncOperations(); } -void NewWebSocketChannelImpl::connect(const KURL& url, const String& protocol) +bool NewWebSocketChannelImpl::connect(const KURL& url, const String& protocol) { WTF_LOG(Network, "NewWebSocketChannelImpl %p connect()", this); if (!m_handle) - return; + return false; + + if (executionContext()->isDocument() && document()->frame() && !document()->frame()->loader().mixedContentChecker()->canConnectInsecureWebSocket(document()->securityOrigin(), url)) + return false; + if (MixedContentChecker::isMixedContent(document()->securityOrigin(), url)) { + String message = "Connecting to a non-secure WebSocket server from a secure origin is deprecated."; + document()->addConsoleMessage(JSMessageSource, WarningMessageLevel, message); + } + m_url = url; Vector<String> protocols; // Avoid placing an empty token in the Vector when the protocol string is @@ -134,23 +154,19 @@ void NewWebSocketChannelImpl::connect(const KURL& url, const String& protocol) for (size_t i = 0; i < protocols.size(); ++i) { webProtocols[i] = protocols[i]; } - String origin = executionContext()->securityOrigin()->toString(); - m_handle->connect(url, webProtocols, origin, this); - flowControlIfNecessary(); - if (m_identifier) - InspectorInstrumentation::didCreateWebSocket(document(), m_identifier, url, protocol); -} -String NewWebSocketChannelImpl::subprotocol() -{ - WTF_LOG(Network, "NewWebSocketChannelImpl %p subprotocol()", this); - return m_subprotocol; -} + if (executionContext()->isDocument() && document()->frame()) + document()->frame()->loader().client()->dispatchWillOpenWebSocket(m_handle.get()); + m_handle->connect(url, webProtocols, *executionContext()->securityOrigin(), this); -String NewWebSocketChannelImpl::extensions() -{ - WTF_LOG(Network, "NewWebSocketChannelImpl %p extensions()", this); - return m_extensions; + flowControlIfNecessary(); + if (m_identifier) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketCreate", "data", InspectorWebSocketCreateEvent::data(document(), m_identifier, url, protocol)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. + InspectorInstrumentation::didCreateWebSocket(document(), m_identifier, url, protocol); + } + return true; } WebSocketChannel::SendResult NewWebSocketChannelImpl::send(const String& message) @@ -160,10 +176,9 @@ WebSocketChannel::SendResult NewWebSocketChannelImpl::send(const String& message // FIXME: Change the inspector API to show the entire message instead // of individual frames. CString data = message.utf8(); - WebSocketFrame frame(WebSocketFrame::OpCodeText, data.data(), data.length(), WebSocketFrame::Final | WebSocketFrame::Masked); - InspectorInstrumentation::didSendWebSocketFrame(document(), m_identifier, frame); + InspectorInstrumentation::didSendWebSocketFrame(document(), m_identifier, WebSocketFrame::OpCodeText, true, data.data(), data.length()); } - m_messages.append(Message(message)); + m_messages.append(adoptPtr(new Message(message))); sendInternal(); return SendSuccess; } @@ -177,10 +192,9 @@ WebSocketChannel::SendResult NewWebSocketChannelImpl::send(PassRefPtr<BlobDataHa // FIXME: We can't access the data here. // Since Binary data are not displayed in Inspector, this does not // affect actual behavior. - WebSocketFrame frame(WebSocketFrame::OpCodeBinary, "", 0, WebSocketFrame::Final | WebSocketFrame::Masked); - InspectorInstrumentation::didSendWebSocketFrame(document(), m_identifier, frame); + InspectorInstrumentation::didSendWebSocketFrame(document(), m_identifier, WebSocketFrame::OpCodeBinary, true, "", 0); } - m_messages.append(Message(blobDataHandle)); + m_messages.append(adoptPtr(new Message(blobDataHandle))); sendInternal(); return SendSuccess; } @@ -191,26 +205,35 @@ WebSocketChannel::SendResult NewWebSocketChannelImpl::send(const ArrayBuffer& bu if (m_identifier) { // FIXME: Change the inspector API to show the entire message instead // of individual frames. - WebSocketFrame frame(WebSocketFrame::OpCodeBinary, static_cast<const char*>(buffer.data()) + byteOffset, byteLength, WebSocketFrame::Final | WebSocketFrame::Masked); - InspectorInstrumentation::didSendWebSocketFrame(document(), m_identifier, frame); + InspectorInstrumentation::didSendWebSocketFrame(document(), m_identifier, WebSocketFrame::OpCodeBinary, true, static_cast<const char*>(buffer.data()) + byteOffset, byteLength); } // buffer.slice copies its contents. - m_messages.append(buffer.slice(byteOffset, byteOffset + byteLength)); + // FIXME: Reduce copy by sending the data immediately when we don't need to + // queue the data. + m_messages.append(adoptPtr(new Message(buffer.slice(byteOffset, byteOffset + byteLength)))); sendInternal(); return SendSuccess; } -unsigned long NewWebSocketChannelImpl::bufferedAmount() const +WebSocketChannel::SendResult NewWebSocketChannelImpl::send(PassOwnPtr<Vector<char> > data) { - WTF_LOG(Network, "NewWebSocketChannelImpl %p bufferedAmount()", this); - return m_bufferedAmount; + WTF_LOG(Network, "NewWebSocketChannelImpl %p sendVector(%p, %llu)", this, data.get(), static_cast<unsigned long long>(data->size())); + if (m_identifier) { + // FIXME: Change the inspector API to show the entire message instead + // of individual frames. + InspectorInstrumentation::didSendWebSocketFrame(document(), m_identifier, WebSocketFrame::OpCodeBinary, true, data->data(), data->size()); + } + m_messages.append(adoptPtr(new Message(data))); + sendInternal(); + return SendSuccess; } void NewWebSocketChannelImpl::close(int code, const String& reason) { WTF_LOG(Network, "NewWebSocketChannelImpl %p close(%d, %s)", this, code, reason.utf8().data()); ASSERT(m_handle); - m_handle->close(static_cast<unsigned short>(code), reason); + unsigned short codeToSend = static_cast<unsigned short>(code == CloseEventCodeNotSpecified ? CloseEventCodeNoStatusRcvd : code); + m_handle->close(codeToSend, reason); } void NewWebSocketChannelImpl::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber) @@ -234,8 +257,12 @@ void NewWebSocketChannelImpl::fail(const String& reason, MessageLevel level, con void NewWebSocketChannelImpl::disconnect() { WTF_LOG(Network, "NewWebSocketChannelImpl %p disconnect()", this); - if (m_identifier) + if (m_identifier) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketDestroy", "data", InspectorWebSocketEvent::data(document(), m_identifier)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didCloseWebSocket(document(), m_identifier); + } abortAsyncOperations(); m_handle.clear(); m_client = 0; @@ -254,7 +281,7 @@ void NewWebSocketChannelImpl::resume() NewWebSocketChannelImpl::Message::Message(const String& text) : type(MessageTypeText) - , text(text.utf8(String::StrictConversionReplacingUnpairedSurrogatesWithFFFD)) { } + , text(text.utf8(StrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD)) { } NewWebSocketChannelImpl::Message::Message(PassRefPtr<BlobDataHandle> blobDataHandle) : type(MessageTypeBlob) @@ -264,36 +291,53 @@ NewWebSocketChannelImpl::Message::Message(PassRefPtr<ArrayBuffer> arrayBuffer) : type(MessageTypeArrayBuffer) , arrayBuffer(arrayBuffer) { } +NewWebSocketChannelImpl::Message::Message(PassOwnPtr<Vector<char> > vectorData) + : type(MessageTypeVector) + , vectorData(vectorData) { } + void NewWebSocketChannelImpl::sendInternal() { ASSERT(m_handle); - unsigned long bufferedAmount = m_bufferedAmount; + unsigned long consumedBufferedAmount = 0; while (!m_messages.isEmpty() && m_sendingQuota > 0 && !m_blobLoader) { bool final = false; - const Message& message = m_messages.first(); - switch (message.type) { + Message* message = m_messages.first().get(); + switch (message->type) { case MessageTypeText: { WebSocketHandle::MessageType type = m_sentSizeOfTopMessage ? WebSocketHandle::MessageTypeContinuation : WebSocketHandle::MessageTypeText; - size_t size = std::min(static_cast<size_t>(m_sendingQuota), message.text.length() - m_sentSizeOfTopMessage); - final = (m_sentSizeOfTopMessage + size == message.text.length()); - m_handle->send(final, type, message.text.data() + m_sentSizeOfTopMessage, size); + size_t size = std::min(static_cast<size_t>(m_sendingQuota), message->text.length() - m_sentSizeOfTopMessage); + final = (m_sentSizeOfTopMessage + size == message->text.length()); + m_handle->send(final, type, message->text.data() + m_sentSizeOfTopMessage, size); m_sentSizeOfTopMessage += size; m_sendingQuota -= size; + consumedBufferedAmount += size; break; } case MessageTypeBlob: ASSERT(!m_blobLoader); - m_blobLoader = adoptPtr(new BlobLoader(message.blobDataHandle, this)); + m_blobLoader = adoptPtrWillBeNoop(new BlobLoader(message->blobDataHandle, this)); break; case MessageTypeArrayBuffer: { WebSocketHandle::MessageType type = m_sentSizeOfTopMessage ? WebSocketHandle::MessageTypeContinuation : WebSocketHandle::MessageTypeBinary; - size_t size = std::min(static_cast<size_t>(m_sendingQuota), message.arrayBuffer->byteLength() - m_sentSizeOfTopMessage); - final = (m_sentSizeOfTopMessage + size == message.arrayBuffer->byteLength()); - m_handle->send(final, type, static_cast<const char*>(message.arrayBuffer->data()) + m_sentSizeOfTopMessage, size); + size_t size = std::min(static_cast<size_t>(m_sendingQuota), message->arrayBuffer->byteLength() - m_sentSizeOfTopMessage); + final = (m_sentSizeOfTopMessage + size == message->arrayBuffer->byteLength()); + m_handle->send(final, type, static_cast<const char*>(message->arrayBuffer->data()) + m_sentSizeOfTopMessage, size); + m_sentSizeOfTopMessage += size; + m_sendingQuota -= size; + consumedBufferedAmount += size; + break; + } + case MessageTypeVector: { + WebSocketHandle::MessageType type = + m_sentSizeOfTopMessage ? WebSocketHandle::MessageTypeContinuation : WebSocketHandle::MessageTypeBinary; + size_t size = std::min(static_cast<size_t>(m_sendingQuota), message->vectorData->size() - m_sentSizeOfTopMessage); + final = (m_sentSizeOfTopMessage + size == message->vectorData->size()); + m_handle->send(final, type, message->vectorData->data() + m_sentSizeOfTopMessage, size); m_sentSizeOfTopMessage += size; m_sendingQuota -= size; + consumedBufferedAmount += size; break; } } @@ -302,9 +346,8 @@ void NewWebSocketChannelImpl::sendInternal() m_sentSizeOfTopMessage = 0; } } - if (m_client && m_bufferedAmount != bufferedAmount) { - m_client->didUpdateBufferedAmount(m_bufferedAmount); - } + if (m_client && consumedBufferedAmount > 0) + m_client->didConsumeBufferedAmount(consumedBufferedAmount); } void NewWebSocketChannelImpl::flowControlIfNecessary() @@ -335,7 +378,7 @@ void NewWebSocketChannelImpl::handleDidClose(bool wasClean, unsigned short code, m_client = 0; WebSocketChannelClient::ClosingHandshakeCompletionStatus status = wasClean ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete; - client->didClose(m_bufferedAmount, status, code, reason); + client->didClose(status, code, reason); // client->didClose may delete this object. } @@ -358,23 +401,30 @@ void NewWebSocketChannelImpl::didConnect(WebSocketHandle* handle, bool fail, con // failAsError may delete this object. return; } - m_subprotocol = selectedProtocol; - m_extensions = extensions; - m_client->didConnect(); + m_client->didConnect(selectedProtocol, extensions); } void NewWebSocketChannelImpl::didStartOpeningHandshake(WebSocketHandle* handle, const blink::WebSocketHandshakeRequestInfo& request) { WTF_LOG(Network, "NewWebSocketChannelImpl %p didStartOpeningHandshake(%p)", this, handle); - if (m_identifier) - InspectorInstrumentation::willSendWebSocketHandshakeRequest(document(), m_identifier, request.toCoreRequest()); + if (m_identifier) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketSendHandshakeRequest", "data", InspectorWebSocketEvent::data(document(), m_identifier)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. + InspectorInstrumentation::willSendWebSocketHandshakeRequest(document(), m_identifier, &request.toCoreRequest()); + m_handshakeRequest = WebSocketHandshakeRequest::create(request.toCoreRequest()); + } } void NewWebSocketChannelImpl::didFinishOpeningHandshake(WebSocketHandle* handle, const blink::WebSocketHandshakeResponseInfo& response) { WTF_LOG(Network, "NewWebSocketChannelImpl %p didFinishOpeningHandshake(%p)", this, handle); - if (m_identifier) - InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(document(), m_identifier, response.toCoreResponse()); + if (m_identifier) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketReceiveHandshakeResponse", "data", InspectorWebSocketEvent::data(document(), m_identifier)); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. + InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(document(), m_identifier, m_handshakeRequest.get(), &response.toCoreResponse()); + } + m_handshakeRequest.clear(); } void NewWebSocketChannelImpl::didFail(WebSocketHandle* handle, const blink::WebString& message) @@ -420,10 +470,10 @@ void NewWebSocketChannelImpl::didReceiveData(WebSocketHandle* handle, bool fin, // of individual frames. WebSocketFrame::OpCode opcode = m_receivingMessageTypeIsText ? WebSocketFrame::OpCodeText : WebSocketFrame::OpCodeBinary; WebSocketFrame frame(opcode, m_receivingMessageData.data(), m_receivingMessageData.size(), WebSocketFrame::Final); - InspectorInstrumentation::didReceiveWebSocketFrame(document(), m_identifier, frame); + InspectorInstrumentation::didReceiveWebSocketFrame(document(), m_identifier, frame.opCode, frame.masked, frame.payload, frame.payloadLength); } if (m_receivingMessageTypeIsText) { - String message = String::fromUTF8(m_receivingMessageData.data(), m_receivingMessageData.size()); + String message = m_receivingMessageData.isEmpty() ? emptyString() : String::fromUTF8(m_receivingMessageData.data(), m_receivingMessageData.size()); m_receivingMessageData.clear(); if (message.isNull()) { failAsError("Could not decode a text frame as UTF-8."); @@ -444,6 +494,9 @@ void NewWebSocketChannelImpl::didClose(WebSocketHandle* handle, bool wasClean, u ASSERT(m_handle); m_handle.clear(); if (m_identifier) { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketDestroy", "data", InspectorWebSocketEvent::data(document(), m_identifier)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didCloseWebSocket(document(), m_identifier); m_identifier = 0; } @@ -460,14 +513,21 @@ void NewWebSocketChannelImpl::didReceiveFlowControl(WebSocketHandle* handle, int sendInternal(); } +void NewWebSocketChannelImpl::didStartClosingHandshake(WebSocketHandle* handle) +{ + WTF_LOG(Network, "NewWebSocketChannelImpl %p didStartClosingHandshake(%p)", this, handle); + if (m_client) + m_client->didStartClosingHandshake(); +} + void NewWebSocketChannelImpl::didFinishLoadingBlob(PassRefPtr<ArrayBuffer> buffer) { m_blobLoader.clear(); ASSERT(m_handle); // The loaded blob is always placed on m_messages[0]. - ASSERT(m_messages.size() > 0 && m_messages.first().type == MessageTypeBlob); + ASSERT(m_messages.size() > 0 && m_messages.first()->type == MessageTypeBlob); // We replace it with the loaded blob. - m_messages.first() = Message(buffer); + m_messages.first() = adoptPtr(new Message(buffer)); sendInternal(); } @@ -483,4 +543,10 @@ void NewWebSocketChannelImpl::didFailLoadingBlob(FileError::ErrorCode errorCode) // |this| can be deleted here. } +void NewWebSocketChannelImpl::trace(Visitor* visitor) +{ + visitor->trace(m_blobLoader); + WebSocketChannel::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/NewWebSocketChannelImpl.h b/chromium/third_party/WebKit/Source/modules/websockets/NewWebSocketChannelImpl.h index 94abe4b5baa..555dc6c7051 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/NewWebSocketChannelImpl.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/NewWebSocketChannelImpl.h @@ -43,8 +43,8 @@ #include "wtf/Deque.h" #include "wtf/FastAllocBase.h" #include "wtf/OwnPtr.h" +#include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/Vector.h" #include "wtf/text/CString.h" @@ -60,57 +60,59 @@ class WebSocketHandshakeResponseInfo; namespace WebCore { class Document; +class WebSocketHandshakeRequest; // This class may replace MainThreadWebSocketChannel. -class NewWebSocketChannelImpl : public WebSocketChannel, public RefCounted<NewWebSocketChannelImpl>, public blink::WebSocketHandleClient, public ContextLifecycleObserver { - WTF_MAKE_FAST_ALLOCATED; +class NewWebSocketChannelImpl FINAL : public WebSocketChannel, public blink::WebSocketHandleClient, public ContextLifecycleObserver { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: // You can specify the source file and the line number information // explicitly by passing the last parameter. // In the usual case, they are set automatically and you don't have to // pass it. - static PassRefPtr<NewWebSocketChannelImpl> create(ExecutionContext* context, WebSocketChannelClient* client, const String& sourceURL = String(), unsigned lineNumber = 0) + static PassRefPtrWillBeRawPtr<NewWebSocketChannelImpl> create(ExecutionContext* context, WebSocketChannelClient* client, const String& sourceURL = String(), unsigned lineNumber = 0) { - return adoptRef(new NewWebSocketChannelImpl(context, client, sourceURL, lineNumber)); + return adoptRefWillBeRefCountedGarbageCollected(new NewWebSocketChannelImpl(context, client, sourceURL, lineNumber)); } virtual ~NewWebSocketChannelImpl(); // WebSocketChannel functions. - virtual void connect(const KURL&, const String& protocol) OVERRIDE; - virtual String subprotocol() OVERRIDE; - virtual String extensions() OVERRIDE; + virtual bool connect(const KURL&, const String& protocol) OVERRIDE; virtual WebSocketChannel::SendResult send(const String& message) OVERRIDE; virtual WebSocketChannel::SendResult send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength) OVERRIDE; virtual WebSocketChannel::SendResult send(PassRefPtr<BlobDataHandle>) OVERRIDE; - virtual unsigned long bufferedAmount() const OVERRIDE; + virtual WebSocketChannel::SendResult send(PassOwnPtr<Vector<char> > data) OVERRIDE; // Start closing handshake. Use the CloseEventCodeNotSpecified for the code // argument to omit payload. virtual void close(int code, const String& reason) OVERRIDE; virtual void fail(const String& reason, MessageLevel, const String&, unsigned lineNumber) OVERRIDE; - using WebSocketChannel::fail; virtual void disconnect() OVERRIDE; - using RefCounted<NewWebSocketChannelImpl>::ref; - using RefCounted<NewWebSocketChannelImpl>::deref; - virtual void suspend() OVERRIDE; virtual void resume() OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: enum MessageType { MessageTypeText, MessageTypeBlob, MessageTypeArrayBuffer, + MessageTypeVector, }; struct Message { explicit Message(const String&); explicit Message(PassRefPtr<BlobDataHandle>); explicit Message(PassRefPtr<ArrayBuffer>); + explicit Message(PassOwnPtr<Vector<char> >); + MessageType type; + CString text; RefPtr<BlobDataHandle> blobDataHandle; RefPtr<ArrayBuffer> arrayBuffer; + OwnPtr<Vector<char> > vectorData; }; struct ReceivedMessage { @@ -136,15 +138,12 @@ private: virtual void didReceiveData(blink::WebSocketHandle*, bool fin, blink::WebSocketHandle::MessageType, const char* data, size_t /* size */) OVERRIDE; virtual void didClose(blink::WebSocketHandle*, bool wasClean, unsigned short code, const blink::WebString& reason) OVERRIDE; virtual void didReceiveFlowControl(blink::WebSocketHandle*, int64_t quota) OVERRIDE; + virtual void didStartClosingHandshake(blink::WebSocketHandle*) OVERRIDE; // Methods for BlobLoader. void didFinishLoadingBlob(PassRefPtr<ArrayBuffer>); void didFailLoadingBlob(FileError::ErrorCode); - // WebSocketChannel functions. - virtual void refWebSocketChannel() OVERRIDE { ref(); } - virtual void derefWebSocketChannel() OVERRIDE { deref(); } - // LifecycleObserver functions. // This object must be destroyed before the context. virtual void contextDestroyed() OVERRIDE { ASSERT_NOT_REACHED(); } @@ -159,20 +158,18 @@ private: KURL m_url; // m_identifier > 0 means calling scriptContextExecution() returns a Document. unsigned long m_identifier; - OwnPtr<BlobLoader> m_blobLoader; - Deque<Message> m_messages; + OwnPtrWillBeMember<BlobLoader> m_blobLoader; + Deque<OwnPtr<Message> > m_messages; Vector<char> m_receivingMessageData; bool m_receivingMessageTypeIsText; int64_t m_sendingQuota; int64_t m_receivedDataSizeForFlowControl; - unsigned long m_bufferedAmount; size_t m_sentSizeOfTopMessage; - String m_subprotocol; - String m_extensions; String m_sourceURLAtConstruction; unsigned m_lineNumberAtConstruction; + RefPtr<WebSocketHandshakeRequest> m_handshakeRequest; static const int64_t receivedDataSizeForFlowControlHighWaterMark = 1 << 15; }; diff --git a/chromium/third_party/WebKit/Source/modules/websockets/OWNERS b/chromium/third_party/WebKit/Source/modules/websockets/OWNERS index e332b79af66..c1f23ed7dd1 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/OWNERS +++ b/chromium/third_party/WebKit/Source/modules/websockets/OWNERS @@ -1,5 +1,2 @@ tyoshino@chromium.org yhirano@chromium.org - -# Inactive -yutak@chromium.org diff --git a/chromium/third_party/WebKit/Source/modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp b/chromium/third_party/WebKit/Source/modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp index dc781728bc0..28bf3494ed7 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp @@ -31,117 +31,16 @@ #include "config.h" #include "modules/websockets/ThreadableWebSocketChannelClientWrapper.h" -#include "core/dom/CrossThreadTask.h" -#include "platform/CrossThreadCopier.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefPtr.h" - namespace WebCore { -ThreadableWebSocketChannelClientWrapper::ThreadableWebSocketChannelClientWrapper(ExecutionContext* context, WebSocketChannelClient* client) - : m_context(context) - , m_client(client) - , m_peer(0) - , m_failedWebSocketChannelCreation(false) - , m_syncMethodDone(true) - , m_sendRequestResult(WebSocketChannel::SendFail) - , m_bufferedAmount(0) - , m_suspended(false) -{ -} - -PassRefPtr<ThreadableWebSocketChannelClientWrapper> ThreadableWebSocketChannelClientWrapper::create(ExecutionContext* context, WebSocketChannelClient* client) -{ - return adoptRef(new ThreadableWebSocketChannelClientWrapper(context, client)); -} - -void ThreadableWebSocketChannelClientWrapper::clearSyncMethodDone() -{ - m_syncMethodDone = false; -} - -void ThreadableWebSocketChannelClientWrapper::setSyncMethodDone() -{ - m_syncMethodDone = true; -} - -bool ThreadableWebSocketChannelClientWrapper::syncMethodDone() const -{ - return m_syncMethodDone; -} - -WorkerThreadableWebSocketChannel::Peer* ThreadableWebSocketChannelClientWrapper::peer() const -{ - return m_peer; -} - -void ThreadableWebSocketChannelClientWrapper::didCreateWebSocketChannel(WorkerThreadableWebSocketChannel::Peer* peer) -{ - m_peer = peer; - m_syncMethodDone = true; -} - -void ThreadableWebSocketChannelClientWrapper::clearPeer() -{ - m_peer = 0; -} - -bool ThreadableWebSocketChannelClientWrapper::failedWebSocketChannelCreation() const -{ - return m_failedWebSocketChannelCreation; -} - -void ThreadableWebSocketChannelClientWrapper::setFailedWebSocketChannelCreation() -{ - m_failedWebSocketChannelCreation = true; -} - -String ThreadableWebSocketChannelClientWrapper::subprotocol() const -{ - if (m_subprotocol.isEmpty()) - return emptyString(); - return String(m_subprotocol); -} - -void ThreadableWebSocketChannelClientWrapper::setSubprotocol(const String& subprotocol) -{ - m_subprotocol.clear(); - append(m_subprotocol, subprotocol); -} - -String ThreadableWebSocketChannelClientWrapper::extensions() const -{ - if (m_extensions.isEmpty()) - return emptyString(); - return String(m_extensions); -} - -void ThreadableWebSocketChannelClientWrapper::setExtensions(const String& extensions) -{ - m_extensions.clear(); - append(m_extensions, extensions); -} - -WebSocketChannel::SendResult ThreadableWebSocketChannelClientWrapper::sendRequestResult() const -{ - return m_sendRequestResult; -} - -void ThreadableWebSocketChannelClientWrapper::setSendRequestResult(WebSocketChannel::SendResult sendRequestResult) +ThreadableWebSocketChannelClientWrapper::ThreadableWebSocketChannelClientWrapper(WebSocketChannelClient* client) + : m_client(client) { - m_sendRequestResult = sendRequestResult; - m_syncMethodDone = true; } -unsigned long ThreadableWebSocketChannelClientWrapper::bufferedAmount() const +PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> ThreadableWebSocketChannelClientWrapper::create(WebSocketChannelClient* client) { - return m_bufferedAmount; -} - -void ThreadableWebSocketChannelClientWrapper::setBufferedAmount(unsigned long bufferedAmount) -{ - m_bufferedAmount = bufferedAmount; - m_syncMethodDone = true; + return adoptRefWillBeNoop(new ThreadableWebSocketChannelClientWrapper(client)); } void ThreadableWebSocketChannelClientWrapper::clearClient() @@ -149,135 +48,46 @@ void ThreadableWebSocketChannelClientWrapper::clearClient() m_client = 0; } -void ThreadableWebSocketChannelClientWrapper::didConnect() +void ThreadableWebSocketChannelClientWrapper::didConnect(const String& subprotocol, const String& extensions) { - m_pendingTasks.append(createCallbackTask(&didConnectCallback, this)); - if (!m_suspended) - processPendingTasks(); + if (m_client) + m_client->didConnect(subprotocol, extensions); } void ThreadableWebSocketChannelClientWrapper::didReceiveMessage(const String& message) { - m_pendingTasks.append(createCallbackTask(&didReceiveMessageCallback, this, message)); - if (!m_suspended) - processPendingTasks(); + if (m_client) + m_client->didReceiveMessage(message); } void ThreadableWebSocketChannelClientWrapper::didReceiveBinaryData(PassOwnPtr<Vector<char> > binaryData) { - m_pendingTasks.append(createCallbackTask(&didReceiveBinaryDataCallback, this, binaryData)); - if (!m_suspended) - processPendingTasks(); + if (m_client) + m_client->didReceiveBinaryData(binaryData); } -void ThreadableWebSocketChannelClientWrapper::didUpdateBufferedAmount(unsigned long bufferedAmount) +void ThreadableWebSocketChannelClientWrapper::didConsumeBufferedAmount(unsigned long consumed) { - m_pendingTasks.append(createCallbackTask(&didUpdateBufferedAmountCallback, this, bufferedAmount)); - if (!m_suspended) - processPendingTasks(); + if (m_client) + m_client->didConsumeBufferedAmount(consumed); } void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshake() { - m_pendingTasks.append(createCallbackTask(&didStartClosingHandshakeCallback, this)); - if (!m_suspended) - processPendingTasks(); + if (m_client) + m_client->didStartClosingHandshake(); } -void ThreadableWebSocketChannelClientWrapper::didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) +void ThreadableWebSocketChannelClientWrapper::didClose(WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) { - m_pendingTasks.append(createCallbackTask(&didCloseCallback, this, unhandledBufferedAmount, closingHandshakeCompletion, code, reason)); - if (!m_suspended) - processPendingTasks(); + if (m_client) + m_client->didClose(closingHandshakeCompletion, code, reason); } void ThreadableWebSocketChannelClientWrapper::didReceiveMessageError() { - m_pendingTasks.append(createCallbackTask(&didReceiveMessageErrorCallback, this)); - if (!m_suspended) - processPendingTasks(); -} - -void ThreadableWebSocketChannelClientWrapper::suspend() -{ - m_suspended = true; -} - -void ThreadableWebSocketChannelClientWrapper::resume() -{ - m_suspended = false; - processPendingTasks(); -} - -void ThreadableWebSocketChannelClientWrapper::processPendingTasksCallback(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper) -{ - ASSERT_UNUSED(context, context->isWorkerGlobalScope()); - wrapper->processPendingTasks(); -} - -void ThreadableWebSocketChannelClientWrapper::processPendingTasks() -{ - if (m_suspended) - return; - if (!m_syncMethodDone) { - // When a synchronous operation is in progress (i.e. the execution stack contains - // WorkerThreadableWebSocketChannel::waitForMethodCompletion()), we cannot invoke callbacks in this run loop. - m_context->postTask(createCallbackTask(&ThreadableWebSocketChannelClientWrapper::processPendingTasksCallback, this)); - return; - } - Vector<OwnPtr<ExecutionContextTask> > tasks; - tasks.swap(m_pendingTasks); - for (Vector<OwnPtr<ExecutionContextTask> >::const_iterator iter = tasks.begin(); iter != tasks.end(); ++iter) - (*iter)->performTask(0); -} - -void ThreadableWebSocketChannelClientWrapper::didConnectCallback(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper) -{ - ASSERT_UNUSED(context, !context); - if (wrapper->m_client) - wrapper->m_client->didConnect(); -} - -void ThreadableWebSocketChannelClientWrapper::didReceiveMessageCallback(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, const String& message) -{ - ASSERT_UNUSED(context, !context); - if (wrapper->m_client) - wrapper->m_client->didReceiveMessage(message); -} - -void ThreadableWebSocketChannelClientWrapper::didReceiveBinaryDataCallback(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, PassOwnPtr<Vector<char> > binaryData) -{ - ASSERT_UNUSED(context, !context); - if (wrapper->m_client) - wrapper->m_client->didReceiveBinaryData(binaryData); -} - -void ThreadableWebSocketChannelClientWrapper::didUpdateBufferedAmountCallback(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, unsigned long bufferedAmount) -{ - ASSERT_UNUSED(context, !context); - if (wrapper->m_client) - wrapper->m_client->didUpdateBufferedAmount(bufferedAmount); -} - -void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshakeCallback(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper) -{ - ASSERT_UNUSED(context, !context); - if (wrapper->m_client) - wrapper->m_client->didStartClosingHandshake(); -} - -void ThreadableWebSocketChannelClientWrapper::didCloseCallback(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) -{ - ASSERT_UNUSED(context, !context); - if (wrapper->m_client) - wrapper->m_client->didClose(unhandledBufferedAmount, closingHandshakeCompletion, code, reason); -} - -void ThreadableWebSocketChannelClientWrapper::didReceiveMessageErrorCallback(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper) -{ - ASSERT_UNUSED(context, !context); - if (wrapper->m_client) - wrapper->m_client->didReceiveMessageError(); + if (m_client) + m_client->didReceiveMessageError(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/ThreadableWebSocketChannelClientWrapper.h b/chromium/third_party/WebKit/Source/modules/websockets/ThreadableWebSocketChannelClientWrapper.h index 0458acf1e18..afb7c9f4707 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/ThreadableWebSocketChannelClientWrapper.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/ThreadableWebSocketChannelClientWrapper.h @@ -31,88 +31,35 @@ #ifndef ThreadableWebSocketChannelClientWrapper_h #define ThreadableWebSocketChannelClientWrapper_h -#include "core/dom/ExecutionContext.h" -#include "modules/websockets/WebSocketChannel.h" #include "modules/websockets/WebSocketChannelClient.h" -#include "modules/websockets/WorkerThreadableWebSocketChannel.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" -#include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" -#include "wtf/Threading.h" +#include "wtf/ThreadSafeRefCounted.h" #include "wtf/Vector.h" -#include "wtf/text/WTFString.h" namespace WebCore { -class ExecutionContext; -class WebSocketChannelClient; - -class ThreadableWebSocketChannelClientWrapper : public ThreadSafeRefCounted<ThreadableWebSocketChannelClientWrapper> { +class ThreadableWebSocketChannelClientWrapper : public ThreadSafeRefCountedWillBeGarbageCollected<ThreadableWebSocketChannelClientWrapper> { public: - static PassRefPtr<ThreadableWebSocketChannelClientWrapper> create(ExecutionContext*, WebSocketChannelClient*); - - void clearSyncMethodDone(); - void setSyncMethodDone(); - bool syncMethodDone() const; - - WorkerThreadableWebSocketChannel::Peer* peer() const; - void didCreateWebSocketChannel(WorkerThreadableWebSocketChannel::Peer*); - void clearPeer(); - - bool failedWebSocketChannelCreation() const; - void setFailedWebSocketChannelCreation(); - - // Subprotocol and extensions will be available when didConnect() callback is invoked. - String subprotocol() const; - void setSubprotocol(const String&); - String extensions() const; - void setExtensions(const String&); - - WebSocketChannel::SendResult sendRequestResult() const; - void setSendRequestResult(WebSocketChannel::SendResult); - - unsigned long bufferedAmount() const; - void setBufferedAmount(unsigned long); + static PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> create(WebSocketChannelClient*); void clearClient(); - void didConnect(); + void didConnect(const String& subprotocol, const String& extensions); void didReceiveMessage(const String& message); void didReceiveBinaryData(PassOwnPtr<Vector<char> >); - void didUpdateBufferedAmount(unsigned long bufferedAmount); + void didConsumeBufferedAmount(unsigned long); void didStartClosingHandshake(); - void didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus, unsigned short code, const String& reason); + void didClose(WebSocketChannelClient::ClosingHandshakeCompletionStatus, unsigned short code, const String& reason); void didReceiveMessageError(); - void suspend(); - void resume(); + void trace(Visitor*) { } private: - ThreadableWebSocketChannelClientWrapper(ExecutionContext*, WebSocketChannelClient*); - - void processPendingTasks(); - - static void didConnectCallback(ExecutionContext*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>); - static void didReceiveMessageCallback(ExecutionContext*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>, const String& message); - static void didReceiveBinaryDataCallback(ExecutionContext*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>, PassOwnPtr<Vector<char> >); - static void didUpdateBufferedAmountCallback(ExecutionContext*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>, unsigned long bufferedAmount); - static void didStartClosingHandshakeCallback(ExecutionContext*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>); - static void didCloseCallback(ExecutionContext*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus, unsigned short code, const String& reason); - static void processPendingTasksCallback(ExecutionContext*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>); - static void didReceiveMessageErrorCallback(ExecutionContext*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>); + ThreadableWebSocketChannelClientWrapper(WebSocketChannelClient*); - ExecutionContext* m_context; WebSocketChannelClient* m_client; - WorkerThreadableWebSocketChannel::Peer* m_peer; - bool m_failedWebSocketChannelCreation; - bool m_syncMethodDone; - // ThreadSafeRefCounted must not have String member variables. - Vector<UChar> m_subprotocol; - Vector<UChar> m_extensions; - WebSocketChannel::SendResult m_sendRequestResult; - unsigned long m_bufferedAmount; - bool m_suspended; - Vector<OwnPtr<ExecutionContextTask> > m_pendingTasks; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.cpp index ea8e45aabc1..e5402b742ea 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.cpp @@ -37,21 +37,23 @@ #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "core/events/Event.h" #include "core/events/MessageEvent.h" #include "core/fileapi/Blob.h" #include "core/frame/ConsoleTypes.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/inspector/ScriptCallStack.h" #include "modules/websockets/CloseEvent.h" #include "platform/Logging.h" #include "platform/blob/BlobData.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KnownPorts.h" #include "platform/weborigin/SecurityOrigin.h" +#include "public/platform/Platform.h" #include "wtf/ArrayBuffer.h" #include "wtf/ArrayBufferView.h" +#include "wtf/Assertions.h" #include "wtf/HashSet.h" #include "wtf/PassOwnPtr.h" #include "wtf/StdLibExtras.h" @@ -59,8 +61,6 @@ #include "wtf/text/StringBuilder.h" #include "wtf/text/WTFString.h" -using namespace std; - namespace WebCore { WebSocket::EventQueue::EventQueue(EventTarget* target) @@ -70,7 +70,7 @@ WebSocket::EventQueue::EventQueue(EventTarget* target) WebSocket::EventQueue::~EventQueue() { stop(); } -void WebSocket::EventQueue::dispatch(PassRefPtr<Event> event) +void WebSocket::EventQueue::dispatch(PassRefPtrWillBeRawPtr<Event> event) { switch (m_state) { case Active: @@ -88,8 +88,14 @@ void WebSocket::EventQueue::dispatch(PassRefPtr<Event> event) } } +bool WebSocket::EventQueue::isEmpty() const +{ + return m_events.isEmpty(); +} + void WebSocket::EventQueue::suspend() { + m_resumeTimer.stop(); if (m_state != Active) return; @@ -101,7 +107,7 @@ void WebSocket::EventQueue::resume() if (m_state != Suspended || m_resumeTimer.isActive()) return; - m_resumeTimer.startOneShot(0); + m_resumeTimer.startOneShot(0, FROM_HERE); } void WebSocket::EventQueue::stop() @@ -119,9 +125,9 @@ void WebSocket::EventQueue::dispatchQueuedEvents() if (m_state != Active) return; - RefPtr<EventQueue> protect(this); + RefPtrWillBeRawPtr<EventQueue> protect(this); - Deque<RefPtr<Event> > events; + WillBeHeapDeque<RefPtrWillBeMember<Event> > events; events.swap(m_events); while (!events.isEmpty()) { if (m_state == Stopped || m_state == Suspended) @@ -145,33 +151,38 @@ void WebSocket::EventQueue::resumeTimerFired(Timer<EventQueue>*) dispatchQueuedEvents(); } +void WebSocket::EventQueue::trace(Visitor* visitor) +{ + visitor->trace(m_events); +} + const size_t maxReasonSizeInBytes = 123; -static inline bool isValidProtocolCharacter(UChar character) +static inline bool isValidSubprotocolCharacter(UChar character) { - // Hybi-10 says "(Subprotocol string must consist of) characters in the range U+0021 to U+007E not including - // separator characters as defined in [RFC2616]." const UChar minimumProtocolCharacter = '!'; // U+0021. const UChar maximumProtocolCharacter = '~'; // U+007E. - return character >= minimumProtocolCharacter && character <= maximumProtocolCharacter - && character != '"' && character != '(' && character != ')' && character != ',' && character != '/' + // Set to true if character does not matches "separators" ABNF defined in + // RFC2616. SP and HT are excluded since the range check excludes them. + bool isNotSeparator = character != '"' && character != '(' && character != ')' && character != ',' && character != '/' && !(character >= ':' && character <= '@') // U+003A - U+0040 (':', ';', '<', '=', '>', '?', '@'). && !(character >= '[' && character <= ']') // U+005B - U+005D ('[', '\\', ']'). && character != '{' && character != '}'; + return character >= minimumProtocolCharacter && character <= maximumProtocolCharacter && isNotSeparator; } -static bool isValidProtocolString(const String& protocol) +bool WebSocket::isValidSubprotocolString(const String& protocol) { if (protocol.isEmpty()) return false; for (size_t i = 0; i < protocol.length(); ++i) { - if (!isValidProtocolCharacter(protocol[i])) + if (!isValidSubprotocolCharacter(protocol[i])) return false; } return true; } -static String encodeProtocolString(const String& protocol) +static String encodeSubprotocolString(const String& protocol) { StringBuilder builder; for (size_t i = 0; i < protocol.length(); i++) { @@ -198,8 +209,8 @@ static String joinStrings(const Vector<String>& strings, const char* separator) static unsigned long saturateAdd(unsigned long a, unsigned long b) { - if (numeric_limits<unsigned long>::max() - a < b) - return numeric_limits<unsigned long>::max(); + if (std::numeric_limits<unsigned long>::max() - a < b) + return std::numeric_limits<unsigned long>::max(); return a + b; } @@ -208,7 +219,7 @@ static void setInvalidStateErrorForSendMethod(ExceptionState& exceptionState) exceptionState.throwDOMException(InvalidStateError, "Still in CONNECTING state."); } -const char* WebSocket::subProtocolSeperator() +const char* WebSocket::subprotocolSeperator() { return ", "; } @@ -217,19 +228,20 @@ WebSocket::WebSocket(ExecutionContext* context) : ActiveDOMObject(context) , m_state(CONNECTING) , m_bufferedAmount(0) + , m_consumedBufferedAmount(0) , m_bufferedAmountAfterClose(0) , m_binaryType(BinaryTypeBlob) , m_subprotocol("") , m_extensions("") , m_eventQueue(EventQueue::create(this)) + , m_bufferedAmountConsumeTimer(this, &WebSocket::reflectBufferedAmountConsumption) { ScriptWrappable::init(this); } WebSocket::~WebSocket() { - if (m_channel) - m_channel->disconnect(); + ASSERT(!m_channel); } void WebSocket::logError(const String& message) @@ -237,49 +249,36 @@ void WebSocket::logError(const String& message) executionContext()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message); } -PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String& url, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String& url, ExceptionState& exceptionState) { Vector<String> protocols; return create(context, url, protocols, exceptionState); } -PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String& url, const Vector<String>& protocols, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String& url, const Vector<String>& protocols, ExceptionState& exceptionState) { if (url.isNull()) { exceptionState.throwDOMException(SyntaxError, "Failed to create a WebSocket: the provided URL is invalid."); - return 0; + return nullptr; } - RefPtr<WebSocket> webSocket(adoptRef(new WebSocket(context))); + RefPtrWillBeRawPtr<WebSocket> webSocket(adoptRefWillBeRefCountedGarbageCollected(new WebSocket(context))); webSocket->suspendIfNeeded(); - webSocket->connect(context->completeURL(url), protocols, exceptionState); + webSocket->connect(url, protocols, exceptionState); if (exceptionState.hadException()) - return 0; + return nullptr; return webSocket.release(); } -PassRefPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String& url, const String& protocol, ExceptionState& exceptionState) +PassRefPtrWillBeRawPtr<WebSocket> WebSocket::create(ExecutionContext* context, const String& url, const String& protocol, ExceptionState& exceptionState) { Vector<String> protocols; protocols.append(protocol); return create(context, url, protocols, exceptionState); } -void WebSocket::connect(const String& url, ExceptionState& exceptionState) -{ - Vector<String> protocols; - connect(url, protocols, exceptionState); -} - -void WebSocket::connect(const String& url, const String& protocol, ExceptionState& exceptionState) -{ - Vector<String> protocols; - protocols.append(protocol); - connect(url, protocols, exceptionState); -} - void WebSocket::connect(const String& url, const Vector<String>& protocols, ExceptionState& exceptionState) { WTF_LOG(Network, "WebSocket %p connect() url='%s'", this, url.utf8().data()); @@ -295,6 +294,7 @@ void WebSocket::connect(const String& url, const Vector<String>& protocols, Exce exceptionState.throwDOMException(SyntaxError, "The URL's scheme must be either 'ws' or 'wss'. '" + m_url.protocol() + "' is not allowed."); return; } + if (m_url.hasFragmentIdentifier()) { m_state = CLOSED; exceptionState.throwDOMException(SyntaxError, "The URL contains a fragment identifier ('" + m_url.fragmentIdentifier() + "'). Fragment identifiers are not allowed in WebSocket URLs."); @@ -319,19 +319,13 @@ void WebSocket::connect(const String& url, const Vector<String>& protocols, Exce return; } - m_channel = WebSocketChannel::create(executionContext(), this); + m_channel = createChannel(executionContext(), this); - // FIXME: There is a disagreement about restriction of subprotocols between WebSocket API and hybi-10 protocol - // draft. The former simply says "only characters in the range U+0021 to U+007E are allowed," while the latter - // imposes a stricter rule: "the elements MUST be non-empty strings with characters as defined in [RFC2616], - // and MUST all be unique strings." - // - // Here, we throw SyntaxError if the given protocols do not meet the latter criteria. This behavior does not - // comply with WebSocket API specification, but it seems to be the only reasonable way to handle this conflict. for (size_t i = 0; i < protocols.size(); ++i) { - if (!isValidProtocolString(protocols[i])) { + if (!isValidSubprotocolString(protocols[i])) { m_state = CLOSED; - exceptionState.throwDOMException(SyntaxError, "The subprotocol '" + encodeProtocolString(protocols[i]) + "' is invalid."); + exceptionState.throwDOMException(SyntaxError, "The subprotocol '" + encodeSubprotocolString(protocols[i]) + "' is invalid."); + releaseChannel(); return; } } @@ -339,19 +333,25 @@ void WebSocket::connect(const String& url, const Vector<String>& protocols, Exce for (size_t i = 0; i < protocols.size(); ++i) { if (!visited.add(protocols[i]).isNewEntry) { m_state = CLOSED; - exceptionState.throwDOMException(SyntaxError, "The subprotocol '" + encodeProtocolString(protocols[i]) + "' is duplicated."); + exceptionState.throwDOMException(SyntaxError, "The subprotocol '" + encodeSubprotocolString(protocols[i]) + "' is duplicated."); + releaseChannel(); return; } } String protocolString; if (!protocols.isEmpty()) - protocolString = joinStrings(protocols, subProtocolSeperator()); + protocolString = joinStrings(protocols, subprotocolSeperator()); - m_channel->connect(m_url, protocolString); + if (!m_channel->connect(m_url, protocolString)) { + m_state = CLOSED; + exceptionState.throwSecurityError("An insecure WebSocket connection may not be initiated from a page loaded over HTTPS."); + releaseChannel(); + return; + } } -void WebSocket::handleSendResult(WebSocketChannel::SendResult result, ExceptionState& exceptionState) +void WebSocket::handleSendResult(WebSocketChannel::SendResult result, ExceptionState& exceptionState, WebSocketSendType dataType) { switch (result) { case WebSocketChannel::InvalidMessage: @@ -361,6 +361,7 @@ void WebSocket::handleSendResult(WebSocketChannel::SendResult result, ExceptionS logError("WebSocket send() failed."); return; case WebSocketChannel::SendSuccess: + blink::Platform::current()->histogramEnumeration("WebCore.WebSocket.SendType", dataType, WebSocketSendTypeMax); return; } ASSERT_NOT_REACHED(); @@ -374,6 +375,22 @@ void WebSocket::updateBufferedAmountAfterClose(unsigned long payloadSize) logError("WebSocket is already in CLOSING or CLOSED state."); } +void WebSocket::reflectBufferedAmountConsumption(Timer<WebSocket>*) +{ + ASSERT(m_bufferedAmount >= m_consumedBufferedAmount); + WTF_LOG(Network, "WebSocket %p reflectBufferedAmountConsumption() %lu => %lu", this, m_bufferedAmount, m_bufferedAmount - m_consumedBufferedAmount); + + m_bufferedAmount -= m_consumedBufferedAmount; + m_consumedBufferedAmount = 0; +} + +void WebSocket::releaseChannel() +{ + ASSERT(m_channel); + m_channel->disconnect(); + m_channel = nullptr; +} + void WebSocket::send(const String& message, ExceptionState& exceptionState) { WTF_LOG(Network, "WebSocket %p send() Sending String '%s'", this, message.utf8().data()); @@ -387,7 +404,8 @@ void WebSocket::send(const String& message, ExceptionState& exceptionState) return; } ASSERT(m_channel); - handleSendResult(m_channel->send(message), exceptionState); + m_bufferedAmount += message.utf8().length(); + handleSendResult(m_channel->send(message), exceptionState, WebSocketSendTypeString); } void WebSocket::send(ArrayBuffer* binaryData, ExceptionState& exceptionState) @@ -403,7 +421,8 @@ void WebSocket::send(ArrayBuffer* binaryData, ExceptionState& exceptionState) return; } ASSERT(m_channel); - handleSendResult(m_channel->send(*binaryData, 0, binaryData->byteLength()), exceptionState); + m_bufferedAmount += binaryData->byteLength(); + handleSendResult(m_channel->send(*binaryData, 0, binaryData->byteLength()), exceptionState, WebSocketSendTypeArrayBuffer); } void WebSocket::send(ArrayBufferView* arrayBufferView, ExceptionState& exceptionState) @@ -419,8 +438,9 @@ void WebSocket::send(ArrayBufferView* arrayBufferView, ExceptionState& exception return; } ASSERT(m_channel); + m_bufferedAmount += arrayBufferView->byteLength(); RefPtr<ArrayBuffer> arrayBuffer(arrayBufferView->buffer()); - handleSendResult(m_channel->send(*arrayBuffer, arrayBufferView->byteOffset(), arrayBufferView->byteLength()), exceptionState); + handleSendResult(m_channel->send(*arrayBuffer, arrayBufferView->byteOffset(), arrayBufferView->byteLength()), exceptionState, WebSocketSendTypeArrayBufferView); } void WebSocket::send(Blob* binaryData, ExceptionState& exceptionState) @@ -435,8 +455,9 @@ void WebSocket::send(Blob* binaryData, ExceptionState& exceptionState) updateBufferedAmountAfterClose(static_cast<unsigned long>(binaryData->size())); return; } + m_bufferedAmount += binaryData->size(); ASSERT(m_channel); - handleSendResult(m_channel->send(binaryData->blobDataHandle()), exceptionState); + handleSendResult(m_channel->send(binaryData->blobDataHandle()), exceptionState, WebSocketSendTypeBlob); } void WebSocket::close(unsigned short code, const String& reason, ExceptionState& exceptionState) @@ -464,7 +485,7 @@ void WebSocket::closeInternal(int code, const String& reason, ExceptionState& ex exceptionState.throwDOMException(InvalidAccessError, "The code must be either 1000, or between 3000 and 4999. " + String::number(code) + " is neither."); return; } - CString utf8 = reason.utf8(String::StrictConversionReplacingUnpairedSurrogatesWithFFFD); + CString utf8 = reason.utf8(StrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD); if (utf8.length() > maxReasonSizeInBytes) { exceptionState.throwDOMException(SyntaxError, "The message must not be greater than " + String::number(maxReasonSizeInBytes) + " bytes."); return; @@ -475,7 +496,7 @@ void WebSocket::closeInternal(int code, const String& reason, ExceptionState& ex return; if (m_state == CONNECTING) { m_state = CLOSING; - m_channel->fail("WebSocket is closed before the connection is established.", WarningMessageLevel); + m_channel->fail("WebSocket is closed before the connection is established.", WarningMessageLevel, String(), 0); return; } m_state = CLOSING; @@ -553,7 +574,7 @@ void WebSocket::contextDestroyed() bool WebSocket::hasPendingActivity() const { - return m_state != CLOSED; + return m_channel || !m_eventQueue->isEmpty(); } void WebSocket::suspend() @@ -573,27 +594,21 @@ void WebSocket::resume() void WebSocket::stop() { m_eventQueue->stop(); - - if (!hasPendingActivity()) { - ASSERT(!m_channel); - return; - } if (m_channel) { m_channel->close(WebSocketChannel::CloseEventCodeGoingAway, String()); - m_channel->disconnect(); - m_channel = 0; + releaseChannel(); } m_state = CLOSED; } -void WebSocket::didConnect() +void WebSocket::didConnect(const String& subprotocol, const String& extensions) { WTF_LOG(Network, "WebSocket %p didConnect()", this); if (m_state != CONNECTING) return; m_state = OPEN; - m_subprotocol = m_channel->subprotocol(); - m_extensions = m_channel->extensions(); + m_subprotocol = subprotocol; + m_extensions = extensions; m_eventQueue->dispatch(Event::create(EventTypeNames::open)); } @@ -615,13 +630,20 @@ void WebSocket::didReceiveBinaryData(PassOwnPtr<Vector<char> > binaryData) binaryData->swap(*rawData->mutableData()); OwnPtr<BlobData> blobData = BlobData::create(); blobData->appendData(rawData.release(), 0, BlobDataItem::toEndOfFile); - RefPtr<Blob> blob = Blob::create(BlobDataHandle::create(blobData.release(), size)); + RefPtrWillBeRawPtr<Blob> blob = Blob::create(BlobDataHandle::create(blobData.release(), size)); m_eventQueue->dispatch(MessageEvent::create(blob.release(), SecurityOrigin::create(m_url)->toString())); break; } case BinaryTypeArrayBuffer: - m_eventQueue->dispatch(MessageEvent::create(ArrayBuffer::create(binaryData->data(), binaryData->size()), SecurityOrigin::create(m_url)->toString())); + RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(binaryData->data(), binaryData->size()); + if (!arrayBuffer) { + // Failed to allocate an ArrayBuffer. We need to crash the renderer + // since there's no way defined in the spec to tell this to the + // user. + CRASH(); + } + m_eventQueue->dispatch(MessageEvent::create(arrayBuffer.release(), SecurityOrigin::create(m_url)->toString())); break; } } @@ -629,15 +651,19 @@ void WebSocket::didReceiveBinaryData(PassOwnPtr<Vector<char> > binaryData) void WebSocket::didReceiveMessageError() { WTF_LOG(Network, "WebSocket %p didReceiveMessageError()", this); + m_state = CLOSED; m_eventQueue->dispatch(Event::create(EventTypeNames::error)); } -void WebSocket::didUpdateBufferedAmount(unsigned long bufferedAmount) +void WebSocket::didConsumeBufferedAmount(unsigned long consumed) { - WTF_LOG(Network, "WebSocket %p didUpdateBufferedAmount() New bufferedAmount is %lu", this, bufferedAmount); + ASSERT(m_bufferedAmount >= consumed); + WTF_LOG(Network, "WebSocket %p didConsumeBufferedAmount(%lu)", this, consumed); if (m_state == CLOSED) return; - m_bufferedAmount = bufferedAmount; + m_consumedBufferedAmount += consumed; + if (!m_bufferedAmountConsumeTimer.isActive()) + m_bufferedAmountConsumeTimer.startOneShot(0, FROM_HERE); } void WebSocket::didStartClosingHandshake() @@ -646,33 +672,17 @@ void WebSocket::didStartClosingHandshake() m_state = CLOSING; } -void WebSocket::didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) +void WebSocket::didClose(ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) { WTF_LOG(Network, "WebSocket %p didClose()", this); if (!m_channel) return; - bool wasClean = m_state == CLOSING && !unhandledBufferedAmount && closingHandshakeCompletion == ClosingHandshakeComplete && code != WebSocketChannel::CloseEventCodeAbnormalClosure; - - // hasPendingActivity() returns false when m_state is CLOSED. So, it's - // possible that the wrapper gets garbage-collected during execution of the - // event. We need to keep this object alive to continue the rest of this - // method. Since the event we dispatch below sets "this" to the wrapper - // object, it doesn't get collected, but just to be sure, put a reference - // for protection. - // - // We can move m_channel clean up code before event dispatching, but it - // makes it harder to check correctness. Comparing cost, we now have this - // temporary reference. - RefPtr<WebSocket> protect(this); - + bool hasAllDataConsumed = m_bufferedAmount == m_consumedBufferedAmount; + bool wasClean = m_state == CLOSING && hasAllDataConsumed && closingHandshakeCompletion == ClosingHandshakeComplete && code != WebSocketChannel::CloseEventCodeAbnormalClosure; m_state = CLOSED; - m_bufferedAmount = unhandledBufferedAmount; - m_eventQueue->dispatch(CloseEvent::create(wasClean, code, reason)); - if (m_channel) { - m_channel->disconnect(); - m_channel = 0; - } + m_eventQueue->dispatch(CloseEvent::create(wasClean, code, reason)); + releaseChannel(); } size_t WebSocket::getFramingOverhead(size_t payloadSize) @@ -689,4 +699,11 @@ size_t WebSocket::getFramingOverhead(size_t payloadSize) return overhead; } +void WebSocket::trace(Visitor* visitor) +{ + visitor->trace(m_channel); + visitor->trace(m_eventQueue); + EventTargetWithInlineData::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.h b/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.h index c69fb98f2e6..e96d43f74c6 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.h @@ -34,11 +34,11 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/dom/ActiveDOMObject.h" #include "core/events/EventListener.h" -#include "core/events/EventTarget.h" -#include "core/events/ThreadLocalEventNames.h" +#include "modules/EventTargetModules.h" #include "modules/websockets/WebSocketChannel.h" #include "modules/websockets/WebSocketChannelClient.h" #include "platform/Timer.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" #include "wtf/Deque.h" #include "wtf/Forward.h" @@ -51,16 +51,17 @@ namespace WebCore { class Blob; class ExceptionState; -class WebSocket : public RefCounted<WebSocket>, public ScriptWrappable, public EventTargetWithInlineData, public ActiveDOMObject, public WebSocketChannelClient { +class WebSocket : public RefCountedWillBeRefCountedGarbageCollected<WebSocket>, public ScriptWrappable, public EventTargetWithInlineData, public ActiveDOMObject, public WebSocketChannelClient { REFCOUNTED_EVENT_TARGET(WebSocket); + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WebSocket); public: - static const char* subProtocolSeperator(); + static const char* subprotocolSeperator(); // WebSocket instances must be used with a wrapper since this class's // lifetime management is designed assuming the V8 holds a ref on it while // hasPendingActivity() returns true. - static PassRefPtr<WebSocket> create(ExecutionContext*, const String& url, ExceptionState&); - static PassRefPtr<WebSocket> create(ExecutionContext*, const String& url, const String& protocol, ExceptionState&); - static PassRefPtr<WebSocket> create(ExecutionContext*, const String& url, const Vector<String>& protocols, ExceptionState&); + static PassRefPtrWillBeRawPtr<WebSocket> create(ExecutionContext*, const String& url, ExceptionState&); + static PassRefPtrWillBeRawPtr<WebSocket> create(ExecutionContext*, const String& url, const String& protocol, ExceptionState&); + static PassRefPtrWillBeRawPtr<WebSocket> create(ExecutionContext*, const String& url, const Vector<String>& protocols, ExceptionState&); virtual ~WebSocket(); enum State { @@ -70,8 +71,6 @@ public: CLOSED = 3 }; - void connect(const String& url, ExceptionState&); - void connect(const String& url, const String& protocol, ExceptionState&); void connect(const String& url, const Vector<String>& protocols, ExceptionState&); void send(const String& message, ExceptionState&); @@ -117,29 +116,44 @@ public: virtual void stop() OVERRIDE; // WebSocketChannelClient functions. - virtual void didConnect() OVERRIDE; + virtual void didConnect(const String& subprotocol, const String& extensions) OVERRIDE; virtual void didReceiveMessage(const String& message) OVERRIDE; virtual void didReceiveBinaryData(PassOwnPtr<Vector<char> >) OVERRIDE; virtual void didReceiveMessageError() OVERRIDE; - virtual void didUpdateBufferedAmount(unsigned long bufferedAmount) OVERRIDE; + virtual void didConsumeBufferedAmount(unsigned long) OVERRIDE; virtual void didStartClosingHandshake() OVERRIDE; - virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) OVERRIDE; + virtual void didClose(ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; + + static bool isValidSubprotocolString(const String&); + +protected: + explicit WebSocket(ExecutionContext*); private: - class EventQueue : public RefCounted<EventQueue> { + // FIXME: This should inherit WebCore::EventQueue. + class EventQueue FINAL : public RefCountedWillBeGarbageCollectedFinalized<EventQueue> { public: - static PassRefPtr<EventQueue> create(EventTarget* target) { return adoptRef(new EventQueue(target)); } - virtual ~EventQueue(); + static PassRefPtrWillBeRawPtr<EventQueue> create(EventTarget* target) + { + return adoptRefWillBeNoop(new EventQueue(target)); + } + ~EventQueue(); // Dispatches the event if this queue is active. // Queues the event if this queue is suspended. // Does nothing otherwise. - void dispatch(PassRefPtr<Event> /* event */); + void dispatch(PassRefPtrWillBeRawPtr<Event> /* event */); + + bool isEmpty() const; void suspend(); void resume(); void stop(); + void trace(Visitor*); + private: enum State { Active, @@ -156,11 +170,24 @@ private: State m_state; EventTarget* m_target; - Deque<RefPtr<Event> > m_events; + WillBeHeapDeque<RefPtrWillBeMember<Event> > m_events; Timer<EventQueue> m_resumeTimer; }; - explicit WebSocket(ExecutionContext*); + enum WebSocketSendType { + WebSocketSendTypeString, + WebSocketSendTypeArrayBuffer, + WebSocketSendTypeArrayBufferView, + WebSocketSendTypeBlob, + WebSocketSendTypeMax, + }; + + // This function is virtual for unittests. + // FIXME: Move WebSocketChannel::create here. + virtual PassRefPtrWillBeRawPtr<WebSocketChannel> createChannel(ExecutionContext* context, WebSocketChannelClient* client) + { + return WebSocketChannel::create(context, client); + } // Adds a console message with JSMessageSource and ErrorMessageLevel. void logError(const String& message); @@ -172,30 +199,40 @@ private: size_t getFramingOverhead(size_t payloadSize); - // Checks the result of WebSocketChannel::send() method, and shows console - // message and sets ec appropriately. - void handleSendResult(WebSocketChannel::SendResult, ExceptionState&); + // Checks the result of WebSocketChannel::send() method, and: + // - shows console message + // - sets ExceptionState appropriately + // - reports data for UMA. + void handleSendResult(WebSocketChannel::SendResult, ExceptionState&, WebSocketSendType); // Updates m_bufferedAmountAfterClose given the amount of data passed to // send() method after the state changed to CLOSING or CLOSED. void updateBufferedAmountAfterClose(unsigned long); + void reflectBufferedAmountConsumption(Timer<WebSocket>*); + + void releaseChannel(); enum BinaryType { BinaryTypeBlob, BinaryTypeArrayBuffer }; - RefPtr<WebSocketChannel> m_channel; + RefPtrWillBeMember<WebSocketChannel> m_channel; State m_state; KURL m_url; unsigned long m_bufferedAmount; + // The consumed buffered amount that will be reflected to m_bufferedAmount + // later. It will be cleared once reflected. + unsigned long m_consumedBufferedAmount; unsigned long m_bufferedAmountAfterClose; BinaryType m_binaryType; + // The subprotocol the server selected. String m_subprotocol; String m_extensions; - RefPtr<EventQueue> m_eventQueue; + RefPtrWillBeMember<EventQueue> m_eventQueue; + Timer<WebSocket> m_bufferedAmountConsumeTimer; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.idl b/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.idl index b5a4ca9494b..eeb8cbdb103 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.idl +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocket.idl @@ -29,16 +29,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://dev.w3.org/html5/websockets/#websocket +// http://www.whatwg.org/specs/web-apps/current-work/multipage/network.html#websocket + +// FIXME: use BinaryType in binaryType +enum BinaryType { "blob", "arraybuffer" }; + [ ActiveDOMObject, + // FIXME: should be optional union type http://crbug.com/240176 Constructor(DOMString url), - Constructor(DOMString url, sequence<DOMString> protocols), Constructor(DOMString url, DOMString protocol), + Constructor(DOMString url, sequence<DOMString> protocols), ConstructorCallWith=ExecutionContext, - GlobalContext=Window&WorkerGlobalScope, + Exposed=Window&Worker, RaisesException=Constructor, + WillBeGarbageCollected, ] interface WebSocket : EventTarget { - readonly attribute DOMString URL; // Lowercased .url is the one in the spec, but leaving .URL for compatibility reasons. + [MeasureAs=WebSocketURL] readonly attribute DOMString URL; // Lowercased .url is the one in the spec, but leaving .URL for compatibility reasons. readonly attribute DOMString url; // ready state @@ -47,24 +55,21 @@ const unsigned short CLOSING = 2; const unsigned short CLOSED = 3; readonly attribute unsigned short readyState; - readonly attribute unsigned long bufferedAmount; // networking - attribute EventHandler onopen; - attribute EventHandler onmessage; - attribute EventHandler onerror; - attribute EventHandler onclose; - - [TreatReturnedNullStringAs=Undefined] readonly attribute DOMString protocol; + attribute EventHandler onopen; + attribute EventHandler onerror; + attribute EventHandler onclose; [TreatReturnedNullStringAs=Undefined] readonly attribute DOMString extensions; + [TreatReturnedNullStringAs=Undefined] readonly attribute DOMString protocol; + [RaisesException] void close([Clamp] optional unsigned short code, optional DOMString reason); - attribute DOMString binaryType; - + // messaging + attribute EventHandler onmessage; + attribute DOMString binaryType; + [RaisesException] void send(DOMString data); + [RaisesException] void send(Blob data); [RaisesException] void send(ArrayBuffer data); [RaisesException] void send(ArrayBufferView data); - [RaisesException] void send(Blob data); - [RaisesException] void send(DOMString data); - - [RaisesException] void close([Clamp] optional unsigned short code, optional DOMString reason); }; diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannel.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannel.cpp index a27f64c00d7..ec50f54dff1 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannel.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannel.cpp @@ -36,27 +36,26 @@ #include "core/dom/Document.h" #include "core/dom/ExecutionContext.h" #include "core/inspector/ScriptCallStack.h" -#include "core/frame/Settings.h" #include "core/workers/WorkerGlobalScope.h" #include "core/workers/WorkerRunLoop.h" #include "core/workers/WorkerThread.h" #include "modules/websockets/MainThreadWebSocketChannel.h" +#include "modules/websockets/NewWebSocketChannelImpl.h" #include "modules/websockets/ThreadableWebSocketChannelClientWrapper.h" #include "modules/websockets/WebSocketChannelClient.h" #include "modules/websockets/WorkerThreadableWebSocketChannel.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { -static const char webSocketChannelMode[] = "webSocketChannelMode"; - -PassRefPtr<WebSocketChannel> WebSocketChannel::create(ExecutionContext* context, WebSocketChannelClient* client) +PassRefPtrWillBeRawPtr<WebSocketChannel> WebSocketChannel::create(ExecutionContext* context, WebSocketChannelClient* client) { ASSERT(context); ASSERT(client); String sourceURL; unsigned lineNumber = 0; - RefPtr<ScriptCallStack> callStack = createScriptCallStack(1, true); + RefPtrWillBeRawPtr<ScriptCallStack> callStack = createScriptCallStack(1, true); if (callStack && callStack->size()) { sourceURL = callStack->at(0).sourceURL(); lineNumber = callStack->at(0).lineNumber(); @@ -64,17 +63,12 @@ PassRefPtr<WebSocketChannel> WebSocketChannel::create(ExecutionContext* context, if (context->isWorkerGlobalScope()) { WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); - WorkerRunLoop& runLoop = workerGlobalScope->thread()->runLoop(); - String mode = webSocketChannelMode; - mode.append(String::number(runLoop.createUniqueId())); - return WorkerThreadableWebSocketChannel::create(workerGlobalScope, client, mode, sourceURL, lineNumber); + return WorkerThreadableWebSocketChannel::create(*workerGlobalScope, client, sourceURL, lineNumber); } Document* document = toDocument(context); - Settings* settings = document->settings(); - if (settings && settings->experimentalWebSocketEnabled()) { - // FIXME: Create and return an "experimental" WebSocketChannel instead of a MainThreadWebSocketChannel. - return MainThreadWebSocketChannel::create(document, client, sourceURL, lineNumber); + if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) { + return NewWebSocketChannelImpl::create(document, client, sourceURL, lineNumber); } return MainThreadWebSocketChannel::create(document, client, sourceURL, lineNumber); } diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannel.h b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannel.h index fe63eaa7c19..6d29a69fa56 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannel.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannel.h @@ -32,9 +32,11 @@ #define WebSocketChannel_h #include "core/frame/ConsoleTypes.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/Noncopyable.h" #include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace WebCore { @@ -44,11 +46,14 @@ class KURL; class ExecutionContext; class WebSocketChannelClient; -class WebSocketChannel { +// FIXME: WebSocketChannel needs to be RefCountedGarbageCollected to support manual ref/deref +// in MainThreadWebSocketChannelImpl. We should change it to GarbageCollectedFinalized once +// we remove MainThreadWebSocketChannelImpl. +class WebSocketChannel : public RefCountedWillBeRefCountedGarbageCollected<WebSocketChannel> { WTF_MAKE_NONCOPYABLE(WebSocketChannel); public: WebSocketChannel() { } - static PassRefPtr<WebSocketChannel> create(ExecutionContext*, WebSocketChannelClient*); + static PassRefPtrWillBeRawPtr<WebSocketChannel> create(ExecutionContext*, WebSocketChannelClient*); enum SendResult { SendSuccess, @@ -75,13 +80,14 @@ public: CloseEventCodeMaximumUserDefined = 4999 }; - virtual void connect(const KURL&, const String& protocol) = 0; - virtual String subprotocol() = 0; // Will be available after didConnect() callback is invoked. - virtual String extensions() = 0; // Will be available after didConnect() callback is invoked. + virtual bool connect(const KURL&, const String& protocol) = 0; virtual SendResult send(const String& message) = 0; virtual SendResult send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength) = 0; virtual SendResult send(PassRefPtr<BlobDataHandle>) = 0; - virtual unsigned long bufferedAmount() const = 0; + + // For WorkerThreadableWebSocketChannel. + virtual SendResult send(PassOwnPtr<Vector<char> >) = 0; + virtual void close(int code, const String& reason) = 0; // Log the reason text and close the connection. Will call didClose(). @@ -96,20 +102,15 @@ public: // You can specify String() and 0 for sourceURL and lineNumber // respectively, if you can't / needn't provide the information. virtual void fail(const String& reason, MessageLevel, const String& sourceURL, unsigned lineNumber) = 0; - void fail(const String& reason, MessageLevel level) { fail(reason, level, String(), 0); } virtual void disconnect() = 0; // Will suppress didClose(). virtual void suspend() = 0; virtual void resume() = 0; - void ref() { refWebSocketChannel(); } - void deref() { derefWebSocketChannel(); } - -protected: virtual ~WebSocketChannel() { } - virtual void refWebSocketChannel() = 0; - virtual void derefWebSocketChannel() = 0; + + virtual void trace(Visitor*) { } }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannelClient.h b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannelClient.h index aa942aacb65..ff558c20fa4 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannelClient.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketChannelClient.h @@ -37,24 +37,24 @@ namespace WebCore { - class WebSocketChannelClient { - public: - virtual ~WebSocketChannelClient() { } - virtual void didConnect() { } - virtual void didReceiveMessage(const String&) { } - virtual void didReceiveBinaryData(PassOwnPtr<Vector<char> >) { } - virtual void didReceiveMessageError() { } - virtual void didUpdateBufferedAmount(unsigned long /* bufferedAmount */) { } - virtual void didStartClosingHandshake() { } - enum ClosingHandshakeCompletionStatus { - ClosingHandshakeIncomplete, - ClosingHandshakeComplete - }; - virtual void didClose(unsigned long /* unhandledBufferedAmount */, ClosingHandshakeCompletionStatus, unsigned short /* code */, const String& /* reason */) { } - - protected: - WebSocketChannelClient() { } +class WebSocketChannelClient { +public: + virtual ~WebSocketChannelClient() { } + virtual void didConnect(const String& subprotocol, const String& extensions) { } + virtual void didReceiveMessage(const String&) { } + virtual void didReceiveBinaryData(PassOwnPtr<Vector<char> >) { } + virtual void didReceiveMessageError() { } + virtual void didConsumeBufferedAmount(unsigned long consumed) { } + virtual void didStartClosingHandshake() { } + enum ClosingHandshakeCompletionStatus { + ClosingHandshakeIncomplete, + ClosingHandshakeComplete }; + virtual void didClose(ClosingHandshakeCompletionStatus, unsigned short /* code */, const String& /* reason */) { } + +protected: + WebSocketChannelClient() { } +}; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketDeflateFramer.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketDeflateFramer.cpp index 6a816e18c49..f7f0e1e0802 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketDeflateFramer.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketDeflateFramer.cpp @@ -38,7 +38,7 @@ namespace WebCore { -class WebSocketExtensionDeflateFrame : public WebSocketExtensionProcessor { +class WebSocketExtensionDeflateFrame FINAL : public WebSocketExtensionProcessor { WTF_MAKE_FAST_ALLOCATED; public: static PassOwnPtr<WebSocketExtensionDeflateFrame> create(WebSocketDeflateFramer* framer) diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketDeflater.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketDeflater.cpp index fa98ffbea1e..4937637752a 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketDeflater.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketDeflater.cpp @@ -108,7 +108,7 @@ bool WebSocketDeflater::finish() // Since consecutive calls of deflate with Z_SYNC_FLUSH and no input lead to an error, // we create and return the output for the empty input manually. ASSERT(!m_buffer.size()); - m_buffer.append("\x02\x00", 2); + m_buffer.append("\x00", 1); return true; } while (true) { diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketExtensionDispatcherTest.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketExtensionDispatcherTest.cpp index b5990e10a4f..215fcbe475c 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketExtensionDispatcherTest.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketExtensionDispatcherTest.cpp @@ -38,7 +38,7 @@ namespace { class WebSocketExtensionDispatcherTest; -class MockWebSocketExtensionProcessor : public WebSocketExtensionProcessor { +class MockWebSocketExtensionProcessor FINAL : public WebSocketExtensionProcessor { public: MockWebSocketExtensionProcessor(const String& name, WebSocketExtensionDispatcherTest* test) : WebSocketExtensionProcessor(name) diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp index b0ed328eb15..84d97869282 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.cpp @@ -34,18 +34,17 @@ #include "modules/websockets/WebSocketHandshake.h" #include "core/dom/Document.h" -#include "core/dom/ExecutionContext.h" #include "core/inspector/ScriptCallStack.h" #include "core/loader/CookieJar.h" #include "modules/websockets/WebSocket.h" #include "platform/Cookie.h" +#include "platform/Crypto.h" #include "platform/Logging.h" #include "platform/network/HTTPHeaderMap.h" #include "platform/network/HTTPParsers.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" #include "wtf/CryptographicallyRandomNumber.h" -#include "wtf/SHA1.h" #include "wtf/StdLibExtras.h" #include "wtf/StringExtras.h" #include "wtf/Vector.h" @@ -56,23 +55,11 @@ namespace WebCore { -namespace { - -// FIXME: The spec says that the Sec-WebSocket-Protocol header in a handshake -// response can't be null if the header in a request is not null. -// Some servers are not accustomed to the shutdown, -// so we provide an adhoc white-list for it tentatively. -const char* const missingProtocolWhiteList[] = { - "ica.citrix.com", -}; - String formatHandshakeFailureReason(const String& detail) { return "Error during WebSocket handshake: " + detail; } -} // namespace - static String resourceName(const KURL& url) { StringBuilder name; @@ -104,10 +91,9 @@ static String hostName(const KURL& url, bool secure) static const size_t maxInputSampleSize = 128; static String trimInputSample(const char* p, size_t len) { - String s = String(p, std::min<size_t>(len, maxInputSampleSize)); if (len > maxInputSampleSize) - s.append(horizontalEllipsis); - return s; + return String(p, maxInputSampleSize) + horizontalEllipsis; + return String(p, len); } static String generateSecWebSocketKey() @@ -121,21 +107,24 @@ static String generateSecWebSocketKey() String WebSocketHandshake::getExpectedWebSocketAccept(const String& secWebSocketKey) { static const char webSocketKeyGUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - static const size_t sha1HashSize = 20; // FIXME: This should be defined in SHA1.h. - SHA1 sha1; CString keyData = secWebSocketKey.ascii(); - sha1.addBytes(reinterpret_cast<const uint8_t*>(keyData.data()), keyData.length()); - sha1.addBytes(reinterpret_cast<const uint8_t*>(webSocketKeyGUID), strlen(webSocketKeyGUID)); - Vector<uint8_t, sha1HashSize> hash; - sha1.computeHash(hash); - return base64Encode(reinterpret_cast<const char*>(hash.data()), sha1HashSize); + + StringBuilder digestable; + digestable.append(secWebSocketKey); + digestable.append(webSocketKeyGUID, strlen(webSocketKeyGUID)); + CString digestableCString = digestable.toString().utf8(); + DigestValue digest; + bool digestSuccess = computeDigest(HashAlgorithmSha1, digestableCString.data(), digestableCString.length(), digest); + RELEASE_ASSERT(digestSuccess); + + return base64Encode(reinterpret_cast<const char*>(digest.data()), sha1HashSize); } -WebSocketHandshake::WebSocketHandshake(const KURL& url, const String& protocol, ExecutionContext* context) +WebSocketHandshake::WebSocketHandshake(const KURL& url, const String& protocol, Document* document) : m_url(url) , m_clientProtocol(protocol) , m_secure(m_url.protocolIs("wss")) - , m_context(context) + , m_document(document) , m_mode(Incomplete) { m_secWebSocketKey = generateSecWebSocketKey(); @@ -179,7 +168,7 @@ bool WebSocketHandshake::secure() const String WebSocketHandshake::clientOrigin() const { - return m_context->securityOrigin()->toString(); + return m_document->securityOrigin()->toString(); } String WebSocketHandshake::clientLocation() const @@ -194,6 +183,8 @@ String WebSocketHandshake::clientLocation() const CString WebSocketHandshake::clientHandshakeMessage() const { + ASSERT(m_document); + // Keep the following consistent with clientHandshakeRequest(). StringBuilder builder; @@ -209,15 +200,6 @@ CString WebSocketHandshake::clientHandshakeMessage() const if (!m_clientProtocol.isEmpty()) fields.append("Sec-WebSocket-Protocol: " + m_clientProtocol); - KURL url = httpURLForAuthenticationAndCookies(); - if (m_context->isDocument()) { - Document* document = toDocument(m_context); - String cookie = cookieRequestHeaderFieldValue(document, url); - if (!cookie.isEmpty()) - fields.append("Cookie: " + cookie); - // Set "Cookie2: <cookie>" if cookies 2 exists for url? - } - // Add no-cache headers to avoid compatibility issue. // There are some proxies that rewrite "Connection: upgrade" // to "Connection: close" in the response if a request doesn't contain @@ -231,8 +213,7 @@ CString WebSocketHandshake::clientHandshakeMessage() const if (extensionValue.length()) fields.append("Sec-WebSocket-Extensions: " + extensionValue); - // Add a User-Agent header. - fields.append("User-Agent: " + m_context->userAgent(m_context->url())); + fields.append("User-Agent: " + m_document->userAgent(m_document->url())); // Fields in the handshake are sent by the client in a random order; the // order is not meaningful. Thus, it's ok to send the order we constructed @@ -250,37 +231,36 @@ CString WebSocketHandshake::clientHandshakeMessage() const PassRefPtr<WebSocketHandshakeRequest> WebSocketHandshake::clientHandshakeRequest() const { + ASSERT(m_document); + // Keep the following consistent with clientHandshakeMessage(). // FIXME: do we need to store m_secWebSocketKey1, m_secWebSocketKey2 and // m_key3 in WebSocketHandshakeRequest? - RefPtr<WebSocketHandshakeRequest> request = WebSocketHandshakeRequest::create("GET", m_url); + RefPtr<WebSocketHandshakeRequest> request = WebSocketHandshakeRequest::create(m_url); request->addHeaderField("Upgrade", "websocket"); request->addHeaderField("Connection", "Upgrade"); - request->addHeaderField("Host", hostName(m_url, m_secure)); - request->addHeaderField("Origin", clientOrigin()); + request->addHeaderField("Host", AtomicString(hostName(m_url, m_secure))); + request->addHeaderField("Origin", AtomicString(clientOrigin())); if (!m_clientProtocol.isEmpty()) - request->addHeaderField("Sec-WebSocket-Protocol", m_clientProtocol); + request->addHeaderField("Sec-WebSocket-Protocol", AtomicString(m_clientProtocol)); KURL url = httpURLForAuthenticationAndCookies(); - if (m_context->isDocument()) { - Document* document = toDocument(m_context); - String cookie = cookieRequestHeaderFieldValue(document, url); - if (!cookie.isEmpty()) - request->addHeaderField("Cookie", cookie); - // Set "Cookie2: <cookie>" if cookies 2 exists for url? - } + + String cookie = cookieRequestHeaderFieldValue(m_document, url); + if (!cookie.isEmpty()) + request->addHeaderField("Cookie", AtomicString(cookie)); + // Set "Cookie2: <cookie>" if cookies 2 exists for url? request->addHeaderField("Pragma", "no-cache"); request->addHeaderField("Cache-Control", "no-cache"); - request->addHeaderField("Sec-WebSocket-Key", m_secWebSocketKey); + request->addHeaderField("Sec-WebSocket-Key", AtomicString(m_secWebSocketKey)); request->addHeaderField("Sec-WebSocket-Version", "13"); const String extensionValue = m_extensionDispatcher.createHeaderValue(); if (extensionValue.length()) - request->addHeaderField("Sec-WebSocket-Extensions", extensionValue); + request->addHeaderField("Sec-WebSocket-Extensions", AtomicString(extensionValue)); - // Add a User-Agent header. - request->addHeaderField("User-Agent", m_context->userAgent(m_context->url())); + request->addHeaderField("User-Agent", AtomicString(m_document->userAgent(m_document->url()))); return request.release(); } @@ -291,9 +271,9 @@ void WebSocketHandshake::reset() m_extensionDispatcher.reset(); } -void WebSocketHandshake::clearExecutionContext() +void WebSocketHandshake::clearDocument() { - m_context = 0; + m_document = 0; } int WebSocketHandshake::readServerHandshake(const char* header, size_t len) @@ -353,16 +333,6 @@ const AtomicString& WebSocketHandshake::serverWebSocketProtocol() const return m_response.headerFields().get("sec-websocket-protocol"); } -const AtomicString& WebSocketHandshake::serverSetCookie() const -{ - return m_response.headerFields().get("set-cookie"); -} - -const AtomicString& WebSocketHandshake::serverSetCookie2() const -{ - return m_response.headerFields().get("set-cookie2"); -} - const AtomicString& WebSocketHandshake::serverUpgrade() const { return m_response.headerFields().get("upgrade"); @@ -482,7 +452,7 @@ const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* e bool sawSecWebSocketAcceptHeaderField = false; bool sawSecWebSocketProtocolHeaderField = false; const char* p = start; - for (; p < end; p++) { + while (p < end) { size_t consumedLength = parseHTTPHeader(p, end - p, m_failureReason, name, value); if (!consumedLength) return 0; @@ -520,7 +490,7 @@ const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* e String extensions = m_extensionDispatcher.acceptedExtensions(); if (!extensions.isEmpty()) - m_response.addHeaderField("Sec-WebSocket-Extensions", extensions); + m_response.addHeaderField("Sec-WebSocket-Extensions", AtomicString(extensions)); return p; } @@ -563,26 +533,14 @@ bool WebSocketHandshake::checkResponseHeaders() return false; } Vector<String> result; - m_clientProtocol.split(String(WebSocket::subProtocolSeperator()), result); + m_clientProtocol.split(String(WebSocket::subprotocolSeperator()), result); if (!result.contains(serverWebSocketProtocol)) { m_failureReason = formatHandshakeFailureReason("'Sec-WebSocket-Protocol' header value '" + serverWebSocketProtocol + "' in response does not match any of sent values"); return false; } } else if (!m_clientProtocol.isEmpty()) { - // FIXME: Some servers are not accustomed to this failure, so we provide an adhoc white-list for it tentatively. - Vector<String> protocols; - m_clientProtocol.split(String(WebSocket::subProtocolSeperator()), protocols); - bool match = false; - for (size_t i = 0; i < protocols.size() && !match; ++i) { - for (size_t j = 0; j < WTF_ARRAY_LENGTH(missingProtocolWhiteList) && !match; ++j) { - if (protocols[i] == missingProtocolWhiteList[j]) - match = true; - } - } - if (!match) { - m_failureReason = formatHandshakeFailureReason("Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received"); - return false; - } + m_failureReason = formatHandshakeFailureReason("Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received"); + return false; } return true; } diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.h b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.h index 835aae72c93..2053bba87fb 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketHandshake.h @@ -41,7 +41,7 @@ namespace WebCore { -class ExecutionContext; +class Document; class WebSocketHandshake { WTF_MAKE_NONCOPYABLE(WebSocketHandshake); WTF_MAKE_FAST_ALLOCATED; @@ -52,7 +52,7 @@ public: enum Mode { Incomplete, Normal, Failed, Connected, ModeMax }; - WebSocketHandshake(const KURL&, const String& protocol, ExecutionContext*); + WebSocketHandshake(const KURL&, const String& protocol, Document*); ~WebSocketHandshake(); const KURL& url() const; @@ -67,13 +67,18 @@ public: String clientOrigin() const; String clientLocation() const; + // Builds a WebSocket opening handshake string to send to the server. + // Cookie headers will be added later by the platform code for security + // reason. CString clientHandshakeMessage() const; + // Builds an object representing WebSocket opening handshake to pass to the + // inspector. PassRefPtr<WebSocketHandshakeRequest> clientHandshakeRequest() const; // We're collecting data for histogram in the destructor. Note that calling // this method affects that. void reset(); - void clearExecutionContext(); + void clearDocument(); int readServerHandshake(const char* header, size_t len); Mode mode() const; @@ -81,8 +86,6 @@ public: String failureReason() const; const AtomicString& serverWebSocketProtocol() const; - const AtomicString& serverSetCookie() const; - const AtomicString& serverSetCookie2() const; const AtomicString& serverUpgrade() const; const AtomicString& serverConnection() const; const AtomicString& serverWebSocketAccept() const; @@ -107,7 +110,7 @@ private: KURL m_url; String m_clientProtocol; bool m_secure; - ExecutionContext* m_context; + Document* m_document; Mode m_mode; diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketPerMessageDeflate.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketPerMessageDeflate.cpp index f0852b5d097..5843ebc8c37 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketPerMessageDeflate.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketPerMessageDeflate.cpp @@ -41,7 +41,7 @@ namespace WebCore { -class CompressionMessageExtensionProcessor : public WebSocketExtensionProcessor { +class CompressionMessageExtensionProcessor FINAL : public WebSocketExtensionProcessor { WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(CompressionMessageExtensionProcessor); public: @@ -189,7 +189,7 @@ bool WebSocketPerMessageDeflate::deflate(WebSocketFrame& frame) } if (frame.payloadLength > 0 && !m_deflater->addBytes(frame.payload, frame.payloadLength)) { - m_failureReason = "Failed to inflate a frame"; + m_failureReason = "Failed to deflate a frame"; return false; } if (frame.final && !m_deflater->finish()) { diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketPerMessageDeflateTest.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketPerMessageDeflateTest.cpp index cebd4efda07..d221e7c8ba3 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketPerMessageDeflateTest.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketPerMessageDeflateTest.cpp @@ -188,8 +188,8 @@ TEST(WebSocketPerMessageDeflateTest, TestDeflateEmptyMessages) c.resetDeflateBuffer(); ASSERT_TRUE(c.deflate(f2)); - EXPECT_EQ(2u, f2.payloadLength); - EXPECT_EQ(0, memcmp("\x02\x00", f2.payload, f2.payloadLength)); + EXPECT_EQ(1u, f2.payloadLength); + EXPECT_EQ(0, memcmp("\x00", f2.payload, f2.payloadLength)); EXPECT_TRUE(f2.final); EXPECT_FALSE(f2.compress); @@ -292,6 +292,31 @@ TEST(WebSocketPerMessageDeflateTest, TestInflate) EXPECT_TRUE(f3.final); } +TEST(WebSocketPerMessageDeflateTest, TestInflateMultipleBlocksOverMultipleFrames) +{ + WebSocketPerMessageDeflate c; + c.enable(8, WebSocketDeflater::TakeOverContext); + WebSocketFrame::OpCode opcode = WebSocketFrame::OpCodeText; + WebSocketFrame::OpCode continuation = WebSocketFrame::OpCodeContinuation; + std::string expected = "HelloHello"; + std::string actual; + WebSocketFrame f1(opcode, "\xf2\x48\xcd\xc9\xc9\x07\x00\x00\x00\xff\xff", 11, WebSocketFrame::Compress); + WebSocketFrame f2(continuation, "\xf2\x00\x11\x00\x00", 5, WebSocketFrame::Final); + + ASSERT_TRUE(c.inflate(f1)); + EXPECT_FALSE(f1.compress); + EXPECT_FALSE(f1.final); + actual += std::string(f1.payload, f1.payloadLength); + + c.resetInflateBuffer(); + ASSERT_TRUE(c.inflate(f2)); + EXPECT_FALSE(f2.compress); + EXPECT_TRUE(f2.final); + actual += std::string(f2.payload, f2.payloadLength); + + EXPECT_EQ(expected, actual); +} + TEST(WebSocketPerMessageDeflateTest, TestInflateEmptyFrame) { WebSocketPerMessageDeflate c; diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WebSocketTest.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketTest.cpp new file mode 100644 index 00000000000..f8f1b866ac4 --- /dev/null +++ b/chromium/third_party/WebKit/Source/modules/websockets/WebSocketTest.cpp @@ -0,0 +1,794 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "modules/websockets/WebSocket.h" + +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/ExceptionCode.h" +#include "core/fileapi/Blob.h" +#include "core/frame/ConsoleTypes.h" +#include "core/testing/DummyPageHolder.h" +#include "wtf/ArrayBuffer.h" +#include "wtf/OwnPtr.h" +#include "wtf/Uint8Array.h" +#include "wtf/Vector.h" +#include "wtf/testing/WTFTestHelpers.h" +#include "wtf/text/WTFString.h" +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <v8.h> + +using testing::_; +using testing::AnyNumber; +using testing::InSequence; +using testing::Ref; +using testing::Return; + +namespace WebCore { + +namespace { + +typedef testing::StrictMock<testing::MockFunction<void(int)> > Checkpoint; // NOLINT + +class MockWebSocketChannel : public WebSocketChannel { +public: + static PassRefPtrWillBeRawPtr<MockWebSocketChannel> create() + { + return adoptRefWillBeRefCountedGarbageCollected(new testing::StrictMock<MockWebSocketChannel>()); + } + + virtual ~MockWebSocketChannel() + { + } + + MOCK_METHOD2(connect, bool(const KURL&, const String&)); + MOCK_METHOD1(send, SendResult(const String&)); + MOCK_METHOD3(send, SendResult(const ArrayBuffer&, unsigned, unsigned)); + MOCK_METHOD1(send, SendResult(PassRefPtr<BlobDataHandle>)); + MOCK_METHOD1(send, SendResult(PassOwnPtr<Vector<char> >)); + MOCK_CONST_METHOD0(bufferedAmount, unsigned long()); + MOCK_METHOD2(close, void(int, const String&)); + MOCK_METHOD4(fail, void(const String&, MessageLevel, const String&, unsigned)); + MOCK_METHOD0(disconnect, void()); + MOCK_METHOD0(suspend, void()); + MOCK_METHOD0(resume, void()); + + MockWebSocketChannel() + { + } +}; + +class WebSocketWithMockChannel FINAL : public WebSocket { +public: + static PassRefPtrWillBeRawPtr<WebSocketWithMockChannel> create(ExecutionContext* context) + { + RefPtrWillBeRawPtr<WebSocketWithMockChannel> websocket = adoptRefWillBeRefCountedGarbageCollected(new WebSocketWithMockChannel(context)); + websocket->suspendIfNeeded(); + return websocket.release(); + } + + MockWebSocketChannel* channel() { return m_channel.get(); } + + virtual PassRefPtrWillBeRawPtr<WebSocketChannel> createChannel(ExecutionContext*, WebSocketChannelClient*) OVERRIDE + { + ASSERT(!m_hasCreatedChannel); + m_hasCreatedChannel = true; + return m_channel.get(); + } + + virtual void trace(Visitor* visitor) OVERRIDE + { + visitor->trace(m_channel); + WebSocket::trace(visitor); + } + +private: + WebSocketWithMockChannel(ExecutionContext* context) + : WebSocket(context) + , m_channel(MockWebSocketChannel::create()) + , m_hasCreatedChannel(false) { } + + RefPtrWillBeMember<MockWebSocketChannel> m_channel; + bool m_hasCreatedChannel; +}; + +class WebSocketTestBase { +public: + WebSocketTestBase() + : m_pageHolder(DummyPageHolder::create()) + , m_websocket(WebSocketWithMockChannel::create(&m_pageHolder->document())) + , m_executionScope(v8::Isolate::GetCurrent()) + , m_exceptionState(ExceptionState::ConstructionContext, "property", "interface", m_executionScope.scriptState()->context()->Global(), m_executionScope.isolate()) + { + } + + virtual ~WebSocketTestBase() + { + if (!m_websocket) + return; + // These statements are needed to clear WebSocket::m_channel to + // avoid ASSERTION failure on ~WebSocket. + ASSERT(m_websocket->channel()); + ::testing::Mock::VerifyAndClear(m_websocket->channel()); + EXPECT_CALL(channel(), disconnect()).Times(AnyNumber()); + + m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, ""); + m_websocket.clear(); + Heap::collectAllGarbage(); + } + + MockWebSocketChannel& channel() { return *m_websocket->channel(); } + + OwnPtr<DummyPageHolder> m_pageHolder; + RefPtrWillBePersistent<WebSocketWithMockChannel> m_websocket; + V8TestingScope m_executionScope; + ExceptionState m_exceptionState; +}; + +class WebSocketTest : public WebSocketTestBase, public ::testing::Test { +public: +}; + +TEST_F(WebSocketTest, connectToBadURL) +{ + m_websocket->connect("xxx", Vector<String>(), m_exceptionState); + + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SyntaxError, m_exceptionState.code()); + EXPECT_EQ("The URL 'xxx' is invalid.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, connectToNonWsURL) +{ + m_websocket->connect("http://example.com/", Vector<String>(), m_exceptionState); + + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SyntaxError, m_exceptionState.code()); + EXPECT_EQ("The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, connectToURLHavingFragmentIdentifier) +{ + m_websocket->connect("ws://example.com/#fragment", Vector<String>(), m_exceptionState); + + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SyntaxError, m_exceptionState.code()); + EXPECT_EQ("The URL contains a fragment identifier ('fragment'). Fragment identifiers are not allowed in WebSocket URLs.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, invalidPort) +{ + m_websocket->connect("ws://example.com:7", Vector<String>(), m_exceptionState); + + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SecurityError, m_exceptionState.code()); + EXPECT_EQ("The port 7 is not allowed.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +// FIXME: Add a test for Content Security Policy. + +TEST_F(WebSocketTest, invalidSubprotocols) +{ + Vector<String> subprotocols; + subprotocols.append("@subprotocol-|'\"x\x01\x02\x03x"); + + { + InSequence s; + EXPECT_CALL(channel(), disconnect()); + } + + m_websocket->connect("ws://example.com/", subprotocols, m_exceptionState); + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SyntaxError, m_exceptionState.code()); + EXPECT_EQ("The subprotocol '@subprotocol-|'\"x\\u0001\\u0002\\u0003x' is invalid.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, channelConnectSuccess) +{ + Vector<String> subprotocols; + subprotocols.append("aa"); + subprotocols.append("bb"); + + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/hoge"), String("aa, bb"))).WillOnce(Return(true)); + } + + m_websocket->connect("ws://example.com/hoge", Vector<String>(subprotocols), m_exceptionState); + + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + EXPECT_EQ(KURL(KURL(), "ws://example.com/hoge"), m_websocket->url()); +} + +TEST_F(WebSocketTest, channelConnectFail) +{ + Vector<String> subprotocols; + subprotocols.append("aa"); + subprotocols.append("bb"); + + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String("aa, bb"))).WillOnce(Return(false)); + EXPECT_CALL(channel(), disconnect()); + } + + m_websocket->connect("ws://example.com/", Vector<String>(subprotocols), m_exceptionState); + + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SecurityError, m_exceptionState.code()); + EXPECT_EQ("An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, isValidSubprotocolString) +{ + EXPECT_TRUE(WebSocket::isValidSubprotocolString("Helloworld!!")); + EXPECT_FALSE(WebSocket::isValidSubprotocolString("Hello, world!!")); + EXPECT_FALSE(WebSocket::isValidSubprotocolString(String())); + EXPECT_FALSE(WebSocket::isValidSubprotocolString("")); + + const char validCharacters[] = "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~"; + size_t length = strlen(validCharacters); + for (size_t i = 0; i < length; ++i) { + String s; + s.append(static_cast<UChar>(validCharacters[i])); + EXPECT_TRUE(WebSocket::isValidSubprotocolString(s)); + } + for (size_t i = 0; i < 256; ++i) { + if (std::find(validCharacters, validCharacters + length, static_cast<char>(i)) != validCharacters + length) { + continue; + } + String s; + s.append(static_cast<UChar>(i)); + EXPECT_FALSE(WebSocket::isValidSubprotocolString(s)); + } +} + +TEST_F(WebSocketTest, connectSuccess) +{ + Vector<String> subprotocols; + subprotocols.append("aa"); + subprotocols.append("bb"); + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String("aa, bb"))).WillOnce(Return(true)); + } + m_websocket->connect("ws://example.com/", subprotocols, m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->didConnect("bb", "cc"); + + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); + EXPECT_EQ("bb", m_websocket->protocol()); + EXPECT_EQ("cc", m_websocket->extensions()); +} + +TEST_F(WebSocketTest, didClose) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), disconnect()); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, ""); + + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, maximumReasonSize) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), fail(_, _, _, _)); + } + String reason; + for (size_t i = 0; i < 123; ++i) + reason.append("a"); + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->close(1000, reason, m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, reasonSizeExceeding) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + } + String reason; + for (size_t i = 0; i < 124; ++i) + reason.append("a"); + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->close(1000, reason, m_exceptionState); + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SyntaxError, m_exceptionState.code()); + EXPECT_EQ("The message must not be greater than 123 bytes.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, closeWhenConnecting) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), fail(String("WebSocket is closed before the connection is established."), WarningMessageLevel, String(), 0)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->close(1000, "bye", m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, close) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), close(3005, String("bye"))); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->didConnect("", ""); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); + m_websocket->close(3005, "bye", m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, closeWithoutReason) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), close(3005, String())); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->didConnect("", ""); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); + m_websocket->close(3005, m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, closeWithoutCodeAndReason) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), close(-1, String())); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->didConnect("", ""); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); + m_websocket->close(m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, closeWhenClosing) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), close(-1, String())); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->didConnect("", ""); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); + m_websocket->close(m_exceptionState); + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); + + m_websocket->close(m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, closeWhenClosed) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), close(-1, String())); + EXPECT_CALL(channel(), disconnect()); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->didConnect("", ""); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); + m_websocket->close(m_exceptionState); + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); + + m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeComplete, 1000, String()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); + m_websocket->close(m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendStringWhenConnecting) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->send("hello", m_exceptionState); + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(InvalidStateError, m_exceptionState.code()); + EXPECT_EQ("Still in CONNECTING state.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendStringWhenClosing) +{ + Checkpoint checkpoint; + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), fail(_, _, _, _)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->close(m_exceptionState); + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->send("hello", m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendStringWhenClosed) +{ + Checkpoint checkpoint; + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), disconnect()); + EXPECT_CALL(checkpoint, Call(1)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, ""); + checkpoint.Call(1); + + m_websocket->send("hello", m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendStringSuccess) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::SendSuccess)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->didConnect("", ""); + m_websocket->send("hello", m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendStringFail) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::SendFail)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->didConnect("", ""); + m_websocket->send("hello", m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendStringInvalidMessage) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), send(String("hello"))).WillOnce(Return(WebSocketChannel::InvalidMessage)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->didConnect("", ""); + m_websocket->send("hello", m_exceptionState); + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SyntaxError, m_exceptionState.code()); + EXPECT_EQ("The message contains invalid characters.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendArrayBufferWhenConnecting) +{ + RefPtr<ArrayBufferView> view = Uint8Array::create(8); + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->send(view->buffer().get(), m_exceptionState); + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(InvalidStateError, m_exceptionState.code()); + EXPECT_EQ("Still in CONNECTING state.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendArrayBufferWhenClosing) +{ + RefPtr<ArrayBufferView> view = Uint8Array::create(8); + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), fail(_, _, _, _)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->close(m_exceptionState); + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->send(view->buffer().get(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendArrayBufferWhenClosed) +{ + Checkpoint checkpoint; + RefPtr<ArrayBufferView> view = Uint8Array::create(8); + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), disconnect()); + EXPECT_CALL(checkpoint, Call(1)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->didClose(WebSocketChannelClient::ClosingHandshakeIncomplete, 1006, ""); + checkpoint.Call(1); + + m_websocket->send(view->buffer().get(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSED, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendArrayBufferSuccess) +{ + RefPtr<ArrayBufferView> view = Uint8Array::create(8); + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::SendSuccess)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->didConnect("", ""); + m_websocket->send(view->buffer().get(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendArrayBufferFail) +{ + RefPtr<ArrayBufferView> view = Uint8Array::create(8); + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::SendFail)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->didConnect("", ""); + m_websocket->send(view->buffer().get(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); +} + +TEST_F(WebSocketTest, sendArrayBufferInvalidMessage) +{ + RefPtr<ArrayBufferView> view = Uint8Array::create(8); + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), send(Ref(*view->buffer()), 0, 8)).WillOnce(Return(WebSocketChannel::InvalidMessage)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + + m_websocket->didConnect("", ""); + m_websocket->send(view->buffer().get(), m_exceptionState); + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(SyntaxError, m_exceptionState.code()); + EXPECT_EQ("The message contains invalid characters.", m_exceptionState.message()); + EXPECT_EQ(WebSocket::OPEN, m_websocket->readyState()); +} + +// FIXME: We should have Blob tests here. +// We can't create a Blob because the blob registration cannot be mocked yet. + +// FIXME: We should add tests for bufferedAmount. + +// FIXME: We should add tests for data receiving. + +TEST_F(WebSocketTest, binaryType) +{ + EXPECT_EQ("blob", m_websocket->binaryType()); + + m_websocket->setBinaryType("hoge"); + + EXPECT_EQ("blob", m_websocket->binaryType()); + + m_websocket->setBinaryType("arraybuffer"); + + EXPECT_EQ("arraybuffer", m_websocket->binaryType()); + + m_websocket->setBinaryType("fuga"); + + EXPECT_EQ("arraybuffer", m_websocket->binaryType()); + + m_websocket->setBinaryType("blob"); + + EXPECT_EQ("blob", m_websocket->binaryType()); +} + +// FIXME: We should add tests for suspend / resume. + +class WebSocketValidClosingCodeTest : public WebSocketTestBase, public ::testing::TestWithParam<unsigned short> { +public: +}; + +TEST_P(WebSocketValidClosingCodeTest, test) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + EXPECT_CALL(channel(), fail(_, _, _, _)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->close(GetParam(), "bye", m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CLOSING, m_websocket->readyState()); +} + +INSTANTIATE_TEST_CASE_P(WebSocketValidClosingCode, WebSocketValidClosingCodeTest, ::testing::Values(1000, 3000, 3001, 4998, 4999)); + +class WebSocketInvalidClosingCodeTest : public WebSocketTestBase, public ::testing::TestWithParam<unsigned short> { +public: +}; + +TEST_P(WebSocketInvalidClosingCodeTest, test) +{ + { + InSequence s; + EXPECT_CALL(channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); + } + m_websocket->connect("ws://example.com/", Vector<String>(), m_exceptionState); + + EXPECT_FALSE(m_exceptionState.hadException()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); + + m_websocket->close(GetParam(), "bye", m_exceptionState); + + EXPECT_TRUE(m_exceptionState.hadException()); + EXPECT_EQ(InvalidAccessError, m_exceptionState.code()); + EXPECT_EQ(String::format("The code must be either 1000, or between 3000 and 4999. %d is neither.", GetParam()), m_exceptionState.message()); + EXPECT_EQ(WebSocket::CONNECTING, m_websocket->readyState()); +} + +INSTANTIATE_TEST_CASE_P(WebSocketInvalidClosingCode, WebSocketInvalidClosingCodeTest, ::testing::Values(0, 1, 998, 999, 1001, 2999, 5000, 9999, 65535)); + +} // namespace + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp b/chromium/third_party/WebKit/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp index ae3f539168c..3b51be0378b 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp +++ b/chromium/third_party/WebKit/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp @@ -39,24 +39,84 @@ #include "core/fileapi/Blob.h" #include "core/inspector/ScriptCallFrame.h" #include "core/inspector/ScriptCallStack.h" -#include "core/frame/Settings.h" #include "core/workers/WorkerLoaderProxy.h" #include "core/workers/WorkerRunLoop.h" #include "core/workers/WorkerThread.h" #include "modules/websockets/MainThreadWebSocketChannel.h" +#include "modules/websockets/NewWebSocketChannelImpl.h" #include "modules/websockets/ThreadableWebSocketChannelClientWrapper.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "public/platform/Platform.h" +#include "public/platform/WebWaitableEvent.h" #include "wtf/ArrayBuffer.h" +#include "wtf/Assertions.h" +#include "wtf/Functional.h" #include "wtf/MainThread.h" namespace WebCore { -WorkerThreadableWebSocketChannel::WorkerThreadableWebSocketChannel(WorkerGlobalScope* context, WebSocketChannelClient* client, const String& taskMode, const String& sourceURL, unsigned lineNumber) - : m_workerGlobalScope(context) - , m_workerClientWrapper(ThreadableWebSocketChannelClientWrapper::create(context, client)) - , m_bridge(Bridge::create(m_workerClientWrapper, m_workerGlobalScope, taskMode)) +// Created and destroyed on the worker thread. All setters of this class are +// called on the main thread, while all getters are called on the worker +// thread. signalWorkerThread() must be called before any getters are called. +class ThreadableWebSocketChannelSyncHelper { +public: + static PassOwnPtr<ThreadableWebSocketChannelSyncHelper> create(PassOwnPtr<blink::WebWaitableEvent> event) + { + return adoptPtr(new ThreadableWebSocketChannelSyncHelper(event)); + } + + // All setters are called on the main thread. + void setConnectRequestResult(bool connectRequestResult) + { + m_connectRequestResult = connectRequestResult; + } + void setSendRequestResult(WebSocketChannel::SendResult sendRequestResult) + { + m_sendRequestResult = sendRequestResult; + } + + // All getter are called on the worker thread. + bool connectRequestResult() const + { + return m_connectRequestResult; + } + WebSocketChannel::SendResult sendRequestResult() const + { + return m_sendRequestResult; + } + + // This should be called after all setters are called and before any + // getters are called. + void signalWorkerThread() + { + m_event->signal(); + } + + blink::WebWaitableEvent* event() const + { + return m_event.get(); + } + +private: + ThreadableWebSocketChannelSyncHelper(PassOwnPtr<blink::WebWaitableEvent> event) + : m_event(event) + , m_connectRequestResult(false) + , m_sendRequestResult(WebSocketChannel::SendFail) + { + } + + OwnPtr<blink::WebWaitableEvent> m_event; + bool m_connectRequestResult; + WebSocketChannel::SendResult m_sendRequestResult; +}; + +WorkerThreadableWebSocketChannel::WorkerThreadableWebSocketChannel(WorkerGlobalScope& workerGlobalScope, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) + : m_workerClientWrapper(ThreadableWebSocketChannelClientWrapper::create(client)) + , m_bridge(Bridge::create(m_workerClientWrapper, workerGlobalScope)) , m_sourceURLAtConnection(sourceURL) , m_lineNumberAtConnection(lineNumber) { + ASSERT(m_workerClientWrapper.get()); m_bridge->initialize(sourceURL, lineNumber); } @@ -66,22 +126,11 @@ WorkerThreadableWebSocketChannel::~WorkerThreadableWebSocketChannel() m_bridge->disconnect(); } -void WorkerThreadableWebSocketChannel::connect(const KURL& url, const String& protocol) +bool WorkerThreadableWebSocketChannel::connect(const KURL& url, const String& protocol) { if (m_bridge) - m_bridge->connect(url, protocol); -} - -String WorkerThreadableWebSocketChannel::subprotocol() -{ - ASSERT(m_workerClientWrapper); - return m_workerClientWrapper->subprotocol(); -} - -String WorkerThreadableWebSocketChannel::extensions() -{ - ASSERT(m_workerClientWrapper); - return m_workerClientWrapper->extensions(); + return m_bridge->connect(url, protocol); + return false; } WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::send(const String& message) @@ -105,13 +154,6 @@ WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::send(PassRefPtr<B return m_bridge->send(blobData); } -unsigned long WorkerThreadableWebSocketChannel::bufferedAmount() const -{ - if (!m_bridge) - return 0; - return m_bridge->bufferedAmount(); -} - void WorkerThreadableWebSocketChannel::close(int code, const String& reason) { if (m_bridge) @@ -123,7 +165,7 @@ void WorkerThreadableWebSocketChannel::fail(const String& reason, MessageLevel l if (!m_bridge) return; - RefPtr<ScriptCallStack> callStack = createScriptCallStack(1, true); + RefPtrWillBeRawPtr<ScriptCallStack> callStack = createScriptCallStack(1, true); if (callStack && callStack->size()) { // In order to emulate the ConsoleMessage behavior, // we should ignore the specified url and line number if @@ -145,34 +187,30 @@ void WorkerThreadableWebSocketChannel::disconnect() m_bridge.clear(); } -void WorkerThreadableWebSocketChannel::suspend() +void WorkerThreadableWebSocketChannel::trace(Visitor* visitor) { - m_workerClientWrapper->suspend(); - if (m_bridge) - m_bridge->suspend(); + visitor->trace(m_workerClientWrapper); + WebSocketChannel::trace(visitor); } -void WorkerThreadableWebSocketChannel::resume() -{ - m_workerClientWrapper->resume(); - if (m_bridge) - m_bridge->resume(); -} - -WorkerThreadableWebSocketChannel::Peer::Peer(PassRefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, ExecutionContext* context, const String& taskMode, const String& sourceURL, unsigned lineNumber) +WorkerThreadableWebSocketChannel::Peer::Peer(PassRefPtr<WeakReference<Peer> > reference, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, ExecutionContext* context, const String& sourceURL, unsigned lineNumber, PassOwnPtr<ThreadableWebSocketChannelSyncHelper> syncHelper) : m_workerClientWrapper(clientWrapper) , m_loaderProxy(loaderProxy) - , m_mainWebSocketChannel(0) - , m_taskMode(taskMode) + , m_mainWebSocketChannel(nullptr) + , m_syncHelper(syncHelper) + , m_weakFactory(reference, this) { + ASSERT(isMainThread()); + ASSERT(m_workerClientWrapper.get()); + Document* document = toDocument(context); - Settings* settings = document->settings(); - if (settings && settings->experimentalWebSocketEnabled()) { - // FIXME: Create an "experimental" WebSocketChannel instead of a MainThreadWebSocketChannel. - m_mainWebSocketChannel = MainThreadWebSocketChannel::create(document, this, sourceURL, lineNumber); - } else + if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) { + m_mainWebSocketChannel = NewWebSocketChannelImpl::create(document, this, sourceURL, lineNumber); + } else { m_mainWebSocketChannel = MainThreadWebSocketChannel::create(document, this, sourceURL, lineNumber); - ASSERT(isMainThread()); + } + + m_syncHelper->signalWorkerThread(); } WorkerThreadableWebSocketChannel::Peer::~Peer() @@ -182,60 +220,64 @@ WorkerThreadableWebSocketChannel::Peer::~Peer() m_mainWebSocketChannel->disconnect(); } -void WorkerThreadableWebSocketChannel::Peer::connect(const KURL& url, const String& protocol) +void WorkerThreadableWebSocketChannel::Peer::initialize(ExecutionContext* context, PassRefPtr<WeakReference<Peer> > reference, WorkerLoaderProxy* loaderProxy, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, const String& sourceURLAtConnection, unsigned lineNumberAtConnection, PassOwnPtr<ThreadableWebSocketChannelSyncHelper> syncHelper) { - ASSERT(isMainThread()); - if (!m_mainWebSocketChannel) - return; - m_mainWebSocketChannel->connect(url, protocol); + // The caller must call destroy() to free the peer. + new Peer(reference, clientWrapper, *loaderProxy, context, sourceURLAtConnection, lineNumberAtConnection, syncHelper); } -static void workerGlobalScopeDidSend(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WebSocketChannel::SendResult sendRequestResult) -{ - ASSERT_UNUSED(context, context->isWorkerGlobalScope()); - workerClientWrapper->setSendRequestResult(sendRequestResult); -} - -void WorkerThreadableWebSocketChannel::Peer::send(const String& message) +void WorkerThreadableWebSocketChannel::Peer::destroy() { ASSERT(isMainThread()); - if (!m_mainWebSocketChannel || !m_workerClientWrapper) - return; - WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel->send(message); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidSend, m_workerClientWrapper, sendRequestResult), m_taskMode); + delete this; } -void WorkerThreadableWebSocketChannel::Peer::send(const ArrayBuffer& binaryData) +void WorkerThreadableWebSocketChannel::Peer::connect(const KURL& url, const String& protocol) { ASSERT(isMainThread()); - if (!m_mainWebSocketChannel || !m_workerClientWrapper) - return; - WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel->send(binaryData, 0, binaryData.byteLength()); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidSend, m_workerClientWrapper, sendRequestResult), m_taskMode); + if (!m_mainWebSocketChannel) { + m_syncHelper->setConnectRequestResult(false); + } else { + bool connectRequestResult = m_mainWebSocketChannel->connect(url, protocol); + m_syncHelper->setConnectRequestResult(connectRequestResult); + } + m_syncHelper->signalWorkerThread(); } -void WorkerThreadableWebSocketChannel::Peer::send(PassRefPtr<BlobDataHandle> blobData) +void WorkerThreadableWebSocketChannel::Peer::send(const String& message) { ASSERT(isMainThread()); - if (!m_mainWebSocketChannel || !m_workerClientWrapper) - return; - WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel->send(blobData); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidSend, m_workerClientWrapper, sendRequestResult), m_taskMode); + if (!m_mainWebSocketChannel) { + m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); + } else { + WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel->send(message); + m_syncHelper->setSendRequestResult(sendRequestResult); + } + m_syncHelper->signalWorkerThread(); } -static void workerGlobalScopeDidGetBufferedAmount(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, unsigned long bufferedAmount) +void WorkerThreadableWebSocketChannel::Peer::sendArrayBuffer(PassOwnPtr<Vector<char> > data) { - ASSERT_UNUSED(context, context->isWorkerGlobalScope()); - workerClientWrapper->setBufferedAmount(bufferedAmount); + ASSERT(isMainThread()); + if (!m_mainWebSocketChannel) { + m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); + } else { + WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel->send(data); + m_syncHelper->setSendRequestResult(sendRequestResult); + } + m_syncHelper->signalWorkerThread(); } -void WorkerThreadableWebSocketChannel::Peer::bufferedAmount() +void WorkerThreadableWebSocketChannel::Peer::sendBlob(PassRefPtr<BlobDataHandle> blobData) { ASSERT(isMainThread()); - if (!m_mainWebSocketChannel || !m_workerClientWrapper) - return; - unsigned long bufferedAmount = m_mainWebSocketChannel->bufferedAmount(); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidGetBufferedAmount, m_workerClientWrapper, bufferedAmount), m_taskMode); + if (!m_mainWebSocketChannel) { + m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); + } else { + WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel->send(blobData); + m_syncHelper->setSendRequestResult(sendRequestResult); + } + m_syncHelper->signalWorkerThread(); } void WorkerThreadableWebSocketChannel::Peer::close(int code, const String& reason) @@ -260,40 +302,25 @@ void WorkerThreadableWebSocketChannel::Peer::disconnect() if (!m_mainWebSocketChannel) return; m_mainWebSocketChannel->disconnect(); - m_mainWebSocketChannel = 0; -} - -void WorkerThreadableWebSocketChannel::Peer::suspend() -{ - ASSERT(isMainThread()); - if (!m_mainWebSocketChannel) - return; - m_mainWebSocketChannel->suspend(); + m_mainWebSocketChannel = nullptr; } -void WorkerThreadableWebSocketChannel::Peer::resume() -{ - ASSERT(isMainThread()); - if (!m_mainWebSocketChannel) - return; - m_mainWebSocketChannel->resume(); -} - -static void workerGlobalScopeDidConnect(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, const String& subprotocol, const String& extensions) +static void workerGlobalScopeDidConnect(ExecutionContext* context, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, const String& subprotocol, const String& extensions) { ASSERT_UNUSED(context, context->isWorkerGlobalScope()); - workerClientWrapper->setSubprotocol(subprotocol); - workerClientWrapper->setExtensions(extensions); - workerClientWrapper->didConnect(); + workerClientWrapper->didConnect(subprotocol, extensions); } -void WorkerThreadableWebSocketChannel::Peer::didConnect() +void WorkerThreadableWebSocketChannel::Peer::didConnect(const String& subprotocol, const String& extensions) { ASSERT(isMainThread()); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidConnect, m_workerClientWrapper, m_mainWebSocketChannel->subprotocol(), m_mainWebSocketChannel->extensions()), m_taskMode); + // It is important to seprate task creation from posting + // the task. See the above comment. + OwnPtr<ExecutionContextTask> task = createCallbackTask(&workerGlobalScopeDidConnect, m_workerClientWrapper.get(), subprotocol, extensions); + m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); } -static void workerGlobalScopeDidReceiveMessage(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, const String& message) +static void workerGlobalScopeDidReceiveMessage(ExecutionContext* context, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, const String& message) { ASSERT_UNUSED(context, context->isWorkerGlobalScope()); workerClientWrapper->didReceiveMessage(message); @@ -302,10 +329,13 @@ static void workerGlobalScopeDidReceiveMessage(ExecutionContext* context, PassRe void WorkerThreadableWebSocketChannel::Peer::didReceiveMessage(const String& message) { ASSERT(isMainThread()); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidReceiveMessage, m_workerClientWrapper, message), m_taskMode); + // It is important to seprate task creation from posting + // the task. See the above comment. + OwnPtr<ExecutionContextTask> task = createCallbackTask(&workerGlobalScopeDidReceiveMessage, m_workerClientWrapper.get(), message); + m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); } -static void workerGlobalScopeDidReceiveBinaryData(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, PassOwnPtr<Vector<char> > binaryData) +static void workerGlobalScopeDidReceiveBinaryData(ExecutionContext* context, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, PassOwnPtr<Vector<char> > binaryData) { ASSERT_UNUSED(context, context->isWorkerGlobalScope()); workerClientWrapper->didReceiveBinaryData(binaryData); @@ -314,22 +344,28 @@ static void workerGlobalScopeDidReceiveBinaryData(ExecutionContext* context, Pas void WorkerThreadableWebSocketChannel::Peer::didReceiveBinaryData(PassOwnPtr<Vector<char> > binaryData) { ASSERT(isMainThread()); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidReceiveBinaryData, m_workerClientWrapper, binaryData), m_taskMode); + // It is important to seprate task creation from posting + // the task. See the above comment. + OwnPtr<ExecutionContextTask> task = createCallbackTask(&workerGlobalScopeDidReceiveBinaryData, m_workerClientWrapper.get(), binaryData); + m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); } -static void workerGlobalScopeDidUpdateBufferedAmount(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, unsigned long bufferedAmount) +static void workerGlobalScopeDidConsumeBufferedAmount(ExecutionContext* context, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, unsigned long consumed) { ASSERT_UNUSED(context, context->isWorkerGlobalScope()); - workerClientWrapper->didUpdateBufferedAmount(bufferedAmount); + workerClientWrapper->didConsumeBufferedAmount(consumed); } -void WorkerThreadableWebSocketChannel::Peer::didUpdateBufferedAmount(unsigned long bufferedAmount) +void WorkerThreadableWebSocketChannel::Peer::didConsumeBufferedAmount(unsigned long consumed) { ASSERT(isMainThread()); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidUpdateBufferedAmount, m_workerClientWrapper, bufferedAmount), m_taskMode); + // It is important to seprate task creation from posting + // the task. See the above comment. + OwnPtr<ExecutionContextTask> task = createCallbackTask(&workerGlobalScopeDidConsumeBufferedAmount, m_workerClientWrapper.get(), consumed); + m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); } -static void workerGlobalScopeDidStartClosingHandshake(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper) +static void workerGlobalScopeDidStartClosingHandshake(ExecutionContext* context, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper) { ASSERT_UNUSED(context, context->isWorkerGlobalScope()); workerClientWrapper->didStartClosingHandshake(); @@ -338,23 +374,29 @@ static void workerGlobalScopeDidStartClosingHandshake(ExecutionContext* context, void WorkerThreadableWebSocketChannel::Peer::didStartClosingHandshake() { ASSERT(isMainThread()); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidStartClosingHandshake, m_workerClientWrapper), m_taskMode); + // It is important to seprate task creation from posting + // the task. See the above comment. + OwnPtr<ExecutionContextTask> task = createCallbackTask(&workerGlobalScopeDidStartClosingHandshake, m_workerClientWrapper.get()); + m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); } -static void workerGlobalScopeDidClose(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) +static void workerGlobalScopeDidClose(ExecutionContext* context, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) { ASSERT_UNUSED(context, context->isWorkerGlobalScope()); - workerClientWrapper->didClose(unhandledBufferedAmount, closingHandshakeCompletion, code, reason); + workerClientWrapper->didClose(closingHandshakeCompletion, code, reason); } -void WorkerThreadableWebSocketChannel::Peer::didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) +void WorkerThreadableWebSocketChannel::Peer::didClose(ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason) { ASSERT(isMainThread()); - m_mainWebSocketChannel = 0; - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidClose, m_workerClientWrapper, unhandledBufferedAmount, closingHandshakeCompletion, code, reason), m_taskMode); + m_mainWebSocketChannel = nullptr; + // It is important to seprate task creation from posting + // the task. See the above comment. + OwnPtr<ExecutionContextTask> task = createCallbackTask(&workerGlobalScopeDidClose, m_workerClientWrapper.get(), closingHandshakeCompletion, code, reason); + m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); } -static void workerGlobalScopeDidReceiveMessageError(ExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper) +static void workerGlobalScopeDidReceiveMessageError(ExecutionContext* context, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper) { ASSERT_UNUSED(context, context->isWorkerGlobalScope()); workerClientWrapper->didReceiveMessageError(); @@ -363,15 +405,17 @@ static void workerGlobalScopeDidReceiveMessageError(ExecutionContext* context, P void WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError() { ASSERT(isMainThread()); - m_loaderProxy.postTaskForModeToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidReceiveMessageError, m_workerClientWrapper), m_taskMode); + // It is important to seprate task creation from posting + // the task. See the above comment. + OwnPtr<ExecutionContextTask> task = createCallbackTask(&workerGlobalScopeDidReceiveMessageError, m_workerClientWrapper.get()); + m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); } -WorkerThreadableWebSocketChannel::Bridge::Bridge(PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, PassRefPtr<WorkerGlobalScope> workerGlobalScope, const String& taskMode) +WorkerThreadableWebSocketChannel::Bridge::Bridge(PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WorkerGlobalScope& workerGlobalScope) : m_workerClientWrapper(workerClientWrapper) , m_workerGlobalScope(workerGlobalScope) , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) - , m_taskMode(taskMode) - , m_peer(0) + , m_syncHelper(0) { ASSERT(m_workerClientWrapper.get()); } @@ -381,292 +425,150 @@ WorkerThreadableWebSocketChannel::Bridge::~Bridge() disconnect(); } -class WorkerThreadableWebSocketChannel::WorkerGlobalScopeDidInitializeTask : public ExecutionContextTask { -public: - static PassOwnPtr<ExecutionContextTask> create(WorkerThreadableWebSocketChannel::Peer* peer, WorkerLoaderProxy* loaderProxy, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper) - { - return adoptPtr(new WorkerGlobalScopeDidInitializeTask(peer, loaderProxy, workerClientWrapper)); - } - - virtual ~WorkerGlobalScopeDidInitializeTask() { } - virtual void performTask(ExecutionContext* context) OVERRIDE - { - ASSERT_UNUSED(context, context->isWorkerGlobalScope()); - if (m_workerClientWrapper->failedWebSocketChannelCreation()) { - // If Bridge::initialize() quitted earlier, we need to kick mainThreadDestroy() to delete the peer. - OwnPtr<WorkerThreadableWebSocketChannel::Peer> peer = adoptPtr(m_peer); - m_peer = 0; - m_loaderProxy->postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadDestroy, peer.release())); - } else - m_workerClientWrapper->didCreateWebSocketChannel(m_peer); - } - virtual bool isCleanupTask() const OVERRIDE { return true; } - -private: - WorkerGlobalScopeDidInitializeTask(WorkerThreadableWebSocketChannel::Peer* peer, WorkerLoaderProxy* loaderProxy, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper) - : m_peer(peer) - , m_loaderProxy(loaderProxy) - , m_workerClientWrapper(workerClientWrapper) - { - } - - WorkerThreadableWebSocketChannel::Peer* m_peer; - WorkerLoaderProxy* m_loaderProxy; - RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; -}; - -void WorkerThreadableWebSocketChannel::Bridge::mainThreadInitialize(ExecutionContext* context, WorkerLoaderProxy* loaderProxy, PassRefPtr<ThreadableWebSocketChannelClientWrapper> prpClientWrapper, const String& taskMode, const String& sourceURL, unsigned lineNumber) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - - RefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper = prpClientWrapper; - - Peer* peer = Peer::create(clientWrapper, *loaderProxy, context, taskMode, sourceURL, lineNumber); - bool sent = loaderProxy->postTaskForModeToWorkerGlobalScope( - WorkerThreadableWebSocketChannel::WorkerGlobalScopeDidInitializeTask::create(peer, loaderProxy, clientWrapper), taskMode); - if (!sent) { - clientWrapper->clearPeer(); - delete peer; - } -} - void WorkerThreadableWebSocketChannel::Bridge::initialize(const String& sourceURL, unsigned lineNumber) { - ASSERT(!m_peer); - setMethodNotCompleted(); - RefPtr<Bridge> protect(this); - m_loaderProxy.postTaskToLoader( - createCallbackTask(&Bridge::mainThreadInitialize, AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper, m_taskMode, sourceURL, lineNumber)); - waitForMethodCompletion(); - // m_peer may be null when the nested runloop exited before a peer has created. - m_peer = m_workerClientWrapper->peer(); - if (!m_peer) - m_workerClientWrapper->setFailedWebSocketChannelCreation(); -} + RefPtr<WeakReference<Peer> > reference = WeakReference<Peer>::createUnbound(); + m_peer = WeakPtr<Peer>(reference); -void WorkerThreadableWebSocketChannel::mainThreadConnect(ExecutionContext* context, Peer* peer, const KURL& url, const String& protocol) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); - - peer->connect(url, protocol); -} + OwnPtr<ThreadableWebSocketChannelSyncHelper> syncHelper = ThreadableWebSocketChannelSyncHelper::create(adoptPtr(blink::Platform::current()->createWaitableEvent())); + // This pointer is guaranteed to be valid until we call terminatePeer. + m_syncHelper = syncHelper.get(); -void WorkerThreadableWebSocketChannel::Bridge::connect(const KURL& url, const String& protocol) -{ - ASSERT(m_workerClientWrapper); - if (!m_peer) - return; - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadConnect, AllowCrossThreadAccess(m_peer), url, protocol)); -} - -void WorkerThreadableWebSocketChannel::mainThreadSend(ExecutionContext* context, Peer* peer, const String& message) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); - - peer->send(message); + RefPtr<Bridge> protect(this); + OwnPtr<ExecutionContextTask> task = createCallbackTask(&Peer::initialize, reference.release(), AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper.get(), sourceURL, lineNumber, syncHelper.release()); + if (!waitForMethodCompletion(task.release())) { + // The worker thread has been signalled to shutdown before method completion. + terminatePeer(); + } } -void WorkerThreadableWebSocketChannel::mainThreadSendArrayBuffer(ExecutionContext* context, Peer* peer, PassOwnPtr<Vector<char> > data) +bool WorkerThreadableWebSocketChannel::Bridge::connect(const KURL& url, const String& protocol) { - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); + if (hasTerminatedPeer()) + return false; - RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(data->data(), data->size()); - peer->send(*arrayBuffer); -} + RefPtr<Bridge> protect(this); + // It is important to seprate task creation from calling + // waitForMethodCompletion. See the above comment. + OwnPtr<ExecutionContextTask> task = CallClosureTask::create(bind(&Peer::connect, m_peer, url.copy(), protocol.isolatedCopy())); + if (!waitForMethodCompletion(task.release())) + return false; -void WorkerThreadableWebSocketChannel::mainThreadSendBlob(ExecutionContext* context, Peer* peer, PassRefPtr<BlobDataHandle> data) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); - peer->send(data); + return m_syncHelper->connectRequestResult(); } WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(const String& message) { - if (!m_workerClientWrapper || !m_peer) + if (hasTerminatedPeer()) return WebSocketChannel::SendFail; - setMethodNotCompleted(); - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadSend, AllowCrossThreadAccess(m_peer), message)); + RefPtr<Bridge> protect(this); - waitForMethodCompletion(); - ThreadableWebSocketChannelClientWrapper* clientWrapper = m_workerClientWrapper.get(); - if (!clientWrapper) + // It is important to seprate task creation from calling + // waitForMethodCompletion. See the above comment. + OwnPtr<ExecutionContextTask> task = CallClosureTask::create(bind(&Peer::send, m_peer, message.isolatedCopy())); + if (!waitForMethodCompletion(task.release())) return WebSocketChannel::SendFail; - return clientWrapper->sendRequestResult(); + + return m_syncHelper->sendRequestResult(); } WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(const ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) { - if (!m_workerClientWrapper || !m_peer) + if (hasTerminatedPeer()) return WebSocketChannel::SendFail; + // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied into Vector<char>. OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength)); if (binaryData.byteLength()) memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteOffset, byteLength); - setMethodNotCompleted(); - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadSendArrayBuffer, AllowCrossThreadAccess(m_peer), data.release())); + RefPtr<Bridge> protect(this); - waitForMethodCompletion(); - ThreadableWebSocketChannelClientWrapper* clientWrapper = m_workerClientWrapper.get(); - if (!clientWrapper) + // It is important to seprate task creation from calling + // waitForMethodCompletion. See the above comment. + OwnPtr<ExecutionContextTask> task = CallClosureTask::create(bind(&Peer::sendArrayBuffer, m_peer, data.release())); + if (!waitForMethodCompletion(task.release())) return WebSocketChannel::SendFail; - return clientWrapper->sendRequestResult(); + + return m_syncHelper->sendRequestResult(); } WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(PassRefPtr<BlobDataHandle> data) { - if (!m_workerClientWrapper || !m_peer) + if (hasTerminatedPeer()) return WebSocketChannel::SendFail; - setMethodNotCompleted(); - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadSendBlob, AllowCrossThreadAccess(m_peer), data)); - RefPtr<Bridge> protect(this); - waitForMethodCompletion(); - ThreadableWebSocketChannelClientWrapper* clientWrapper = m_workerClientWrapper.get(); - if (!clientWrapper) - return WebSocketChannel::SendFail; - return clientWrapper->sendRequestResult(); -} -void WorkerThreadableWebSocketChannel::mainThreadBufferedAmount(ExecutionContext* context, Peer* peer) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); - - peer->bufferedAmount(); -} - -unsigned long WorkerThreadableWebSocketChannel::Bridge::bufferedAmount() -{ - if (!m_workerClientWrapper || !m_peer) - return 0; - setMethodNotCompleted(); - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadBufferedAmount, AllowCrossThreadAccess(m_peer))); RefPtr<Bridge> protect(this); - waitForMethodCompletion(); - ThreadableWebSocketChannelClientWrapper* clientWrapper = m_workerClientWrapper.get(); - if (clientWrapper) - return clientWrapper->bufferedAmount(); - return 0; -} - -void WorkerThreadableWebSocketChannel::mainThreadClose(ExecutionContext* context, Peer* peer, int code, const String& reason) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); + // It is important to seprate task creation from calling + // waitForMethodCompletion. See the above comment. + OwnPtr<ExecutionContextTask> task = CallClosureTask::create(bind(&Peer::sendBlob, m_peer, data)); + if (!waitForMethodCompletion(task.release())) + return WebSocketChannel::SendFail; - peer->close(code, reason); + return m_syncHelper->sendRequestResult(); } void WorkerThreadableWebSocketChannel::Bridge::close(int code, const String& reason) { - if (!m_peer) + if (hasTerminatedPeer()) return; - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadClose, AllowCrossThreadAccess(m_peer), code, reason)); -} -void WorkerThreadableWebSocketChannel::mainThreadFail(ExecutionContext* context, Peer* peer, const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); - - peer->fail(reason, level, sourceURL, lineNumber); + // It is important to seprate task creation from calling + // waitForMethodCompletion. See the above comment. + OwnPtr<ExecutionContextTask> task = CallClosureTask::create(bind(&Peer::close, m_peer, code, reason.isolatedCopy())); + m_loaderProxy.postTaskToLoader(task.release()); } void WorkerThreadableWebSocketChannel::Bridge::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber) { - if (!m_peer) + if (hasTerminatedPeer()) return; - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadFail, AllowCrossThreadAccess(m_peer), reason, level, sourceURL, lineNumber)); -} -void WorkerThreadableWebSocketChannel::mainThreadDestroy(ExecutionContext* context, PassOwnPtr<Peer> peer) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT_UNUSED(peer, peer); - - // Peer object will be deleted even if the task does not run in the main thread's cleanup period, because - // the destructor for the task object (created by createCallbackTask()) will automatically delete the peer. + // It is important to seprate task creation from calling + // waitForMethodCompletion. See the above comment. + OwnPtr<ExecutionContextTask> task = CallClosureTask::create(bind(&Peer::fail, m_peer, reason.isolatedCopy(), level, sourceURL.isolatedCopy(), lineNumber)); + m_loaderProxy.postTaskToLoader(task.release()); } void WorkerThreadableWebSocketChannel::Bridge::disconnect() { clearClientWrapper(); - if (m_peer) { - OwnPtr<Peer> peer = adoptPtr(m_peer); - m_peer = 0; - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadDestroy, peer.release())); - } - m_workerGlobalScope = 0; + terminatePeer(); } -void WorkerThreadableWebSocketChannel::mainThreadSuspend(ExecutionContext* context, Peer* peer) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); - - peer->suspend(); -} - -void WorkerThreadableWebSocketChannel::Bridge::suspend() +void WorkerThreadableWebSocketChannel::Bridge::clearClientWrapper() { - if (!m_peer) - return; - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadSuspend, AllowCrossThreadAccess(m_peer))); + m_workerClientWrapper->clearClient(); } -void WorkerThreadableWebSocketChannel::mainThreadResume(ExecutionContext* context, Peer* peer) +// Caller of this function should hold a reference to the bridge, because this function may call WebSocket::didClose() in the end, +// which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference. +bool WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion(PassOwnPtr<ExecutionContextTask> task) { - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - ASSERT(peer); + ASSERT(m_workerGlobalScope); + ASSERT(m_syncHelper); - peer->resume(); -} - -void WorkerThreadableWebSocketChannel::Bridge::resume() -{ - if (!m_peer) - return; - m_loaderProxy.postTaskToLoader(createCallbackTask(&WorkerThreadableWebSocketChannel::mainThreadResume, AllowCrossThreadAccess(m_peer))); -} + m_loaderProxy.postTaskToLoader(task); -void WorkerThreadableWebSocketChannel::Bridge::clearClientWrapper() -{ - m_workerClientWrapper->clearClient(); + // We wait for the syncHelper event even if a shutdown event is fired. + // See https://codereview.chromium.org/267323004/#msg43 for why we need to wait this. + Vector<blink::WebWaitableEvent*> events; + events.append(m_syncHelper->event()); + ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); + blink::Platform::current()->waitMultipleEvents(events); + // This is checking whether a shutdown event is fired or not. + return !m_workerGlobalScope->thread()->runLoop().terminated(); } -void WorkerThreadableWebSocketChannel::Bridge::setMethodNotCompleted() +void WorkerThreadableWebSocketChannel::Bridge::terminatePeer() { - ASSERT(m_workerClientWrapper); - m_workerClientWrapper->clearSyncMethodDone(); -} + OwnPtr<ExecutionContextTask> task = CallClosureTask::create(bind(&Peer::destroy, m_peer)); + m_loaderProxy.postTaskToLoader(task.release()); + // Peer::destroy() deletes m_peer and then m_syncHelper will be released. + // We must not touch m_syncHelper any more. + m_syncHelper = 0; -// Caller of this function should hold a reference to the bridge, because this function may call WebSocket::didClose() in the end, -// which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference. -void WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion() -{ - if (!m_workerGlobalScope) - return; - WorkerRunLoop& runLoop = m_workerGlobalScope->thread()->runLoop(); - MessageQueueWaitResult result = MessageQueueMessageReceived; - ThreadableWebSocketChannelClientWrapper* clientWrapper = m_workerClientWrapper.get(); - while (m_workerGlobalScope && clientWrapper && !clientWrapper->syncMethodDone() && result != MessageQueueTerminated) { - result = runLoop.runInMode(m_workerGlobalScope.get(), m_taskMode); // May cause this bridge to get disconnected, which makes m_workerGlobalScope become null. - clientWrapper = m_workerClientWrapper.get(); - } + // We won't use this any more. + m_workerGlobalScope = nullptr; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/modules/websockets/WorkerThreadableWebSocketChannel.h b/chromium/third_party/WebKit/Source/modules/websockets/WorkerThreadableWebSocketChannel.h index e8d897e3076..8605cab90b2 100644 --- a/chromium/third_party/WebKit/Source/modules/websockets/WorkerThreadableWebSocketChannel.h +++ b/chromium/third_party/WebKit/Source/modules/websockets/WorkerThreadableWebSocketChannel.h @@ -31,115 +31,118 @@ #ifndef WorkerThreadableWebSocketChannel_h #define WorkerThreadableWebSocketChannel_h +#include "core/dom/ExecutionContextTask.h" #include "core/frame/ConsoleTypes.h" #include "core/workers/WorkerGlobalScope.h" #include "modules/websockets/WebSocketChannel.h" #include "modules/websockets/WebSocketChannelClient.h" - +#include "platform/heap/Handle.h" +#include "wtf/Assertions.h" #include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/Threading.h" #include "wtf/Vector.h" +#include "wtf/WeakPtr.h" #include "wtf/text/WTFString.h" +namespace blink { +class WebWaitableEvent; +} + namespace WebCore { class BlobDataHandle; class KURL; class ExecutionContext; class ThreadableWebSocketChannelClientWrapper; +class ThreadableWebSocketChannelSyncHelper; class WorkerGlobalScope; class WorkerLoaderProxy; class WorkerRunLoop; -class WorkerThreadableWebSocketChannel : public RefCounted<WorkerThreadableWebSocketChannel>, public WebSocketChannel { - WTF_MAKE_FAST_ALLOCATED; +class WorkerThreadableWebSocketChannel FINAL : public WebSocketChannel { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassRefPtr<WebSocketChannel> create(WorkerGlobalScope* workerGlobalScope, WebSocketChannelClient* client, const String& taskMode, const String& sourceURL, unsigned lineNumber) + static PassRefPtrWillBeRawPtr<WebSocketChannel> create(WorkerGlobalScope& workerGlobalScope, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) { - return adoptRef(new WorkerThreadableWebSocketChannel(workerGlobalScope, client, taskMode, sourceURL, lineNumber)); + return adoptRefWillBeRefCountedGarbageCollected(new WorkerThreadableWebSocketChannel(workerGlobalScope, client, sourceURL, lineNumber)); } virtual ~WorkerThreadableWebSocketChannel(); // WebSocketChannel functions. - virtual void connect(const KURL&, const String& protocol) OVERRIDE; - virtual String subprotocol() OVERRIDE; - virtual String extensions() OVERRIDE; + virtual bool connect(const KURL&, const String& protocol) OVERRIDE; virtual WebSocketChannel::SendResult send(const String& message) OVERRIDE; virtual WebSocketChannel::SendResult send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength) OVERRIDE; virtual WebSocketChannel::SendResult send(PassRefPtr<BlobDataHandle>) OVERRIDE; - virtual unsigned long bufferedAmount() const OVERRIDE; + virtual WebSocketChannel::SendResult send(PassOwnPtr<Vector<char> >) OVERRIDE + { + ASSERT_NOT_REACHED(); + return WebSocketChannel::SendFail; + } virtual void close(int code, const String& reason) OVERRIDE; virtual void fail(const String& reason, MessageLevel, const String&, unsigned) OVERRIDE; virtual void disconnect() OVERRIDE; // Will suppress didClose(). - virtual void suspend() OVERRIDE; - virtual void resume() OVERRIDE; + virtual void suspend() OVERRIDE { } + virtual void resume() OVERRIDE { } + + virtual void trace(Visitor*) OVERRIDE; - // Generated by the bridge. The Peer and its bridge should have identical - // lifetimes. - class Peer : public WebSocketChannelClient { + // Generated by the bridge. The Peer is destructed by an async call from + // Bridge, and may outlive the bridge. All methods of this class must + // be called on the main thread. + class Peer FINAL : public WebSocketChannelClient { WTF_MAKE_NONCOPYABLE(Peer); WTF_MAKE_FAST_ALLOCATED; public: + virtual ~Peer(); + // sourceURLAtConnection and lineNumberAtConnection parameters may // be shown when the connection fails. - static Peer* create(PassRefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, ExecutionContext* context, const String& taskMode, const String& sourceURLAtConnection, unsigned lineNumberAtConnection) - { - return new Peer(clientWrapper, loaderProxy, context, taskMode, sourceURLAtConnection, lineNumberAtConnection); - } - ~Peer(); + static void initialize(ExecutionContext*, PassRefPtr<WeakReference<Peer> >, WorkerLoaderProxy*, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper>, const String& sourceURLAtConnection, unsigned lineNumberAtConnection, PassOwnPtr<ThreadableWebSocketChannelSyncHelper>); + void destroy(); void connect(const KURL&, const String& protocol); void send(const String& message); - void send(const ArrayBuffer&); - void send(PassRefPtr<BlobDataHandle>); + void sendArrayBuffer(PassOwnPtr<Vector<char> >); + void sendBlob(PassRefPtr<BlobDataHandle>); void bufferedAmount(); void close(int code, const String& reason); void fail(const String& reason, MessageLevel, const String& sourceURL, unsigned lineNumber); void disconnect(); - void suspend(); - void resume(); // WebSocketChannelClient functions. - virtual void didConnect() OVERRIDE; + virtual void didConnect(const String& subprotocol, const String& extensions) OVERRIDE; virtual void didReceiveMessage(const String& message) OVERRIDE; virtual void didReceiveBinaryData(PassOwnPtr<Vector<char> >) OVERRIDE; - virtual void didUpdateBufferedAmount(unsigned long bufferedAmount) OVERRIDE; + virtual void didConsumeBufferedAmount(unsigned long) OVERRIDE; virtual void didStartClosingHandshake() OVERRIDE; - virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) OVERRIDE; + virtual void didClose(ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) OVERRIDE; virtual void didReceiveMessageError() OVERRIDE; private: - Peer(PassRefPtr<ThreadableWebSocketChannelClientWrapper>, WorkerLoaderProxy&, ExecutionContext*, const String& taskMode, const String& sourceURL, unsigned lineNumber); + Peer(PassRefPtr<WeakReference<Peer> >, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper>, WorkerLoaderProxy&, ExecutionContext*, const String& sourceURL, unsigned lineNumber, PassOwnPtr<ThreadableWebSocketChannelSyncHelper>); - RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; + const RefPtrWillBePersistent<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; WorkerLoaderProxy& m_loaderProxy; - RefPtr<WebSocketChannel> m_mainWebSocketChannel; - String m_taskMode; + RefPtrWillBePersistent<WebSocketChannel> m_mainWebSocketChannel; + OwnPtr<ThreadableWebSocketChannelSyncHelper> m_syncHelper; + WeakPtrFactory<Peer> m_weakFactory; }; - using RefCounted<WorkerThreadableWebSocketChannel>::ref; - using RefCounted<WorkerThreadableWebSocketChannel>::deref; - -protected: - // WebSocketChannel functions. - virtual void refWebSocketChannel() OVERRIDE { ref(); } - virtual void derefWebSocketChannel() OVERRIDE { deref(); } - private: // Bridge for Peer. Running on the worker thread. class Bridge : public RefCounted<Bridge> { public: - static PassRefPtr<Bridge> create(PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, PassRefPtr<WorkerGlobalScope> workerGlobalScope, const String& taskMode) + static PassRefPtr<Bridge> create(PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WorkerGlobalScope& workerGlobalScope) { - return adoptRef(new Bridge(workerClientWrapper, workerGlobalScope, taskMode)); + return adoptRef(new Bridge(workerClientWrapper, workerGlobalScope)); } ~Bridge(); // sourceURLAtConnection and lineNumberAtConnection parameters may // be shown when the connection fails. void initialize(const String& sourceURLAtConnection, unsigned lineNumberAtConnection); - void connect(const KURL&, const String& protocol); + bool connect(const KURL&, const String& protocol); WebSocketChannel::SendResult send(const String& message); WebSocketChannel::SendResult send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength); WebSocketChannel::SendResult send(PassRefPtr<BlobDataHandle>); @@ -147,53 +150,32 @@ private: void close(int code, const String& reason); void fail(const String& reason, MessageLevel, const String& sourceURL, unsigned lineNumber); void disconnect(); - void suspend(); - void resume(); - - using RefCounted<Bridge>::ref; - using RefCounted<Bridge>::deref; private: - Bridge(PassRefPtr<ThreadableWebSocketChannelClientWrapper>, PassRefPtr<WorkerGlobalScope>, const String& taskMode); - - static void setWebSocketChannel(ExecutionContext*, Bridge* thisPtr, Peer*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>); + Bridge(PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper>, WorkerGlobalScope&); - // Executed on the main thread to create a Peer for this bridge. - // sourceURL and lineNumber provides the source filename and - // the line number information at the connection initiation - // respectively. They may be shown when the connection fails. - static void mainThreadInitialize(ExecutionContext*, WorkerLoaderProxy*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>, const String& taskMode, const String& sourceURL, unsigned lineNumber); + static void setWebSocketChannel(ExecutionContext*, Bridge* thisPtr, Peer*, PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper>); // Executed on the worker context's thread. void clearClientWrapper(); - void setMethodNotCompleted(); - void waitForMethodCompletion(); + // Returns false if shutdown event is received before method completion. + bool waitForMethodCompletion(PassOwnPtr<ExecutionContextTask>); - RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; - RefPtr<WorkerGlobalScope> m_workerGlobalScope; - WorkerLoaderProxy& m_loaderProxy; - String m_taskMode; - Peer* m_peer; - }; + void terminatePeer(); - WorkerThreadableWebSocketChannel(WorkerGlobalScope*, WebSocketChannelClient*, const String& taskMode, const String& sourceURL, unsigned lineNumber); + bool hasTerminatedPeer() { return !m_syncHelper; } - static void mainThreadConnect(ExecutionContext*, Peer*, const KURL&, const String& protocol); - static void mainThreadSend(ExecutionContext*, Peer*, const String& message); - static void mainThreadSendArrayBuffer(ExecutionContext*, Peer*, PassOwnPtr<Vector<char> >); - static void mainThreadSendBlob(ExecutionContext*, Peer*, PassRefPtr<BlobDataHandle>); - static void mainThreadBufferedAmount(ExecutionContext*, Peer*); - static void mainThreadClose(ExecutionContext*, Peer*, int code, const String& reason); - static void mainThreadFail(ExecutionContext*, Peer*, const String& reason, MessageLevel, const String& sourceURL, unsigned lineNumber); - static void mainThreadDestroy(ExecutionContext*, PassOwnPtr<Peer>); - static void mainThreadSuspend(ExecutionContext*, Peer*); - static void mainThreadResume(ExecutionContext*, Peer*); + const RefPtrWillBePersistent<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; + RefPtrWillBePersistent<WorkerGlobalScope> m_workerGlobalScope; + WorkerLoaderProxy& m_loaderProxy; + ThreadableWebSocketChannelSyncHelper* m_syncHelper; + WeakPtr<Peer> m_peer; + }; - class WorkerGlobalScopeDidInitializeTask; + WorkerThreadableWebSocketChannel(WorkerGlobalScope&, WebSocketChannelClient*, const String& sourceURL, unsigned lineNumber); - RefPtr<WorkerGlobalScope> m_workerGlobalScope; - RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; + const RefPtrWillBeMember<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; RefPtr<Bridge> m_bridge; String m_sourceURLAtConnection; unsigned m_lineNumberAtConnection; |