Import Cobalt 23.master.0.309200
diff --git a/cobalt/browser/on_screen_keyboard_starboard_bridge.cc b/cobalt/browser/on_screen_keyboard_starboard_bridge.cc index 39b998c..969f822 100644 --- a/cobalt/browser/on_screen_keyboard_starboard_bridge.cc +++ b/cobalt/browser/on_screen_keyboard_starboard_bridge.cc
@@ -96,5 +96,34 @@ return SbWindowSetOnScreenKeyboardKeepFocus(sb_window_provider_.Run(), keep_focus); } + +void OnScreenKeyboardStarboardBridge::SetBackgroundColor( + const char* background_color) { + const CobaltExtensionOnScreenKeyboardApi* on_screen_keyboard_extension = + static_cast<const CobaltExtensionOnScreenKeyboardApi*>( + SbSystemGetExtension(kCobaltExtensionOnScreenKeyboardName)); + + if (on_screen_keyboard_extension && + strcmp(on_screen_keyboard_extension->name, + kCobaltExtensionOnScreenKeyboardName) == 0 && + on_screen_keyboard_extension->version >= 1) { + on_screen_keyboard_extension->SetBackgroundColor(sb_window_provider_.Run(), + background_color); + } +} + +void OnScreenKeyboardStarboardBridge::SetDarkTheme(bool dark_theme) { + const CobaltExtensionOnScreenKeyboardApi* on_screen_keyboard_extension = + static_cast<const CobaltExtensionOnScreenKeyboardApi*>( + SbSystemGetExtension(kCobaltExtensionOnScreenKeyboardName)); + + if (on_screen_keyboard_extension && + strcmp(on_screen_keyboard_extension->name, + kCobaltExtensionOnScreenKeyboardName) == 0 && + on_screen_keyboard_extension->version >= 1) { + on_screen_keyboard_extension->SetDarkTheme(sb_window_provider_.Run(), + dark_theme); + } +} } // namespace browser } // namespace cobalt
diff --git a/cobalt/browser/on_screen_keyboard_starboard_bridge.h b/cobalt/browser/on_screen_keyboard_starboard_bridge.h index f73cc11..6ee9a70 100644 --- a/cobalt/browser/on_screen_keyboard_starboard_bridge.h +++ b/cobalt/browser/on_screen_keyboard_starboard_bridge.h
@@ -19,6 +19,7 @@ #include "base/callback.h" #include "cobalt/dom/on_screen_keyboard_bridge.h" +#include "cobalt/extension/on_screen_keyboard.h" #include "starboard/window.h" namespace cobalt { @@ -58,6 +59,10 @@ void SetKeepFocus(bool keep_focus) override; + void SetBackgroundColor(const char* background_color) override; + + void SetDarkTheme(bool dark_theme) override; + private: base::Callback<SbWindow()> sb_window_provider_; };
diff --git a/cobalt/demos/content/BUILD.gn b/cobalt/demos/content/BUILD.gn index 9e6b742..e9f5d09 100644 --- a/cobalt/demos/content/BUILD.gn +++ b/cobalt/demos/content/BUILD.gn
@@ -111,8 +111,6 @@ if (is_internal_build) { sources += [ - "internal/runtime-dump.html", - "javascript-fuzzer/index.html", "media-element-demo/public/assets/ac3.mp4", "media-element-demo/public/assets/dash-audio.mp4", "media-element-demo/public/assets/dash-video-1080p.mp4", @@ -125,86 +123,6 @@ "media-element-demo/public/assets/progressive.mp4", "mtm-demo/README.txt", "mtm-demo/progressive.mp4", - "performance-spike/assets/Roboto-Regular.ttf", - "performance-spike/assets/banner.jpg", - "performance-spike/assets/banner1080.jpg", - "performance-spike/assets/banner1080baked.jpg", - "performance-spike/assets/banner1080withLinearGradient.jpg", - "performance-spike/assets/banner720.jpg", - "performance-spike/assets/banner720baked.jpg", - "performance-spike/assets/icons.ttf", - "performance-spike/css/default.css", - "performance-spike/css/icons-content.css", - "performance-spike/css/icons.css", - "performance-spike/di/injector.js", - "performance-spike/di/mapping.js", - "performance-spike/di/resolver.js", - "performance-spike/index.html", - "performance-spike/namespace.js", - "performance-spike/runtime-dump.html", - "performance-spike/spike/anim/_config.js", - "performance-spike/spike/anim/alignment.js", - "performance-spike/spike/anim/centering.js", - "performance-spike/spike/anim/cssanimations/_config.js", - "performance-spike/spike/anim/cssanimations/animationbuilder.js", - "performance-spike/spike/anim/cssanimations/centering.js", - "performance-spike/spike/anim/cssanimations/rows.js", - "performance-spike/spike/anim/csstransitions/_config.js", - "performance-spike/spike/anim/csstransitions/centering.js", - "performance-spike/spike/anim/csstransitions/rows.js", - "performance-spike/spike/anim/csstransitions/transitionbuilder.js", - "performance-spike/spike/anim/rows.js", - "performance-spike/spike/anim/transformer/_config.js", - "performance-spike/spike/anim/transformer/centering.js", - "performance-spike/spike/anim/transformer/ease.js", - "performance-spike/spike/anim/transformer/rows.js", - "performance-spike/spike/anim/transformer/transformer.js", - "performance-spike/spike/anim/tweens/_config.js", - "performance-spike/spike/anim/tweens/centering.js", - "performance-spike/spike/anim/tweens/rows.js", - "performance-spike/spike/anim/tweens/tweens.js", - "performance-spike/spike/behavior/_config.js", - "performance-spike/spike/behavior/body.js", - "performance-spike/spike/behavior/buttons.js", - "performance-spike/spike/behavior/column.js", - "performance-spike/spike/behavior/content.js", - "performance-spike/spike/behavior/cssfocused.js", - "performance-spike/spike/behavior/factory.js", - "performance-spike/spike/behavior/header.js", - "performance-spike/spike/behavior/headerbuttons.js", - "performance-spike/spike/behavior/item.js", - "performance-spike/spike/behavior/main.js", - "performance-spike/spike/behavior/menu.js", - "performance-spike/spike/behavior/navigate.js", - "performance-spike/spike/behavior/row.js", - "performance-spike/spike/core/_config.js", - "performance-spike/spike/core/environment.js", - "performance-spike/spike/core/experiments.js", - "performance-spike/spike/core/fps.js", - "performance-spike/spike/core/location.js", - "performance-spike/spike/core/math.js", - "performance-spike/spike/core/rollingmean.js", - "performance-spike/spike/core/styles.js", - "performance-spike/spike/core/throttlefactory.js", - "performance-spike/spike/core/ticker.js", - "performance-spike/spike/ctrl/_config.js", - "performance-spike/spike/ctrl/behaviors.js", - "performance-spike/spike/ctrl/factory.js", - "performance-spike/spike/ctrl/focuser.js", - "performance-spike/spike/ctrl/hbox.js", - "performance-spike/spike/ctrl/keyhandler.js", - "performance-spike/spike/ctrl/leaf.js", - "performance-spike/spike/ctrl/vbox.js", - "performance-spike/spike/data/_config.js", - "performance-spike/spike/data/channel_crash_course.js", - "performance-spike/spike/data/menu.js", - "performance-spike/spike/data/menu_content.js", - "performance-spike/spike/data/update.js", - "performance-spike/spike/factory/_config.js", - "performance-spike/spike/factory/itemfactory.js", - "performance-spike/spike/factory/menufactory.js", - "performance-spike/spike/factory/rowfactory.js", - "performance-spike/spike/main.js", "text-encoding-workaround/text-encoding-workaround.html", ] }
diff --git a/cobalt/dom/BUILD.gn b/cobalt/dom/BUILD.gn index 79ed564..ff47acc 100644 --- a/cobalt/dom/BUILD.gn +++ b/cobalt/dom/BUILD.gn
@@ -261,7 +261,6 @@ "screenshot.h", "screenshot_manager.cc", "screenshot_manager.h", - "serialized_algorithm_runner.cc", "serialized_algorithm_runner.h", "serializer.cc", "serializer.h",
diff --git a/cobalt/dom/html_script_element.cc b/cobalt/dom/html_script_element.cc index e003c03..42f7997 100644 --- a/cobalt/dom/html_script_element.cc +++ b/cobalt/dom/html_script_element.cc
@@ -78,6 +78,18 @@ DCHECK(document->html_element_context()->script_runner()); } +std::string HTMLScriptElement::src() const { + auto src = GetAttribute("src"); + if (!src.has_value()) { + return ""; + } + if (!node_document()) { + return src.value(); + } + const GURL& base_url = node_document()->location()->url(); + return base_url.Resolve(src.value()).spec(); +} + base::Optional<std::string> HTMLScriptElement::cross_origin() const { base::Optional<std::string> cross_origin_attribute = GetAttribute("crossOrigin"); @@ -217,7 +229,11 @@ // 1. Let src be the value of the element's src attribute. // 2. If src is the empty string, queue a task to fire a simple event // named error at the element, and abort these steps. - if (HasAttribute("src") && src() == "") { + // + // Need to use the "src" attribute. The |src| property is fully resolved. See + // header file for details. + auto src = GetAttribute("src").value_or(""); + if (HasAttribute("src") && src == "") { LOG(ERROR) << "src attribute of script element is empty."; PreventGarbageCollectionAndPostToDispatchEvent( @@ -230,9 +246,9 @@ // 4. If the previous step failed, queue a task to fire a simple event named // error at the element, and abort these steps. const GURL& base_url = document_->location()->url(); - url_ = base_url.Resolve(src()); + url_ = base_url.Resolve(src); if (!url_.is_valid()) { - LOG(ERROR) << src() << " cannot be resolved based on " << base_url << "."; + LOG(ERROR) << src << " cannot be resolved based on " << base_url << "."; PreventGarbageCollectionAndPostToDispatchEvent( FROM_HERE, base::Tokens::error(), @@ -267,7 +283,7 @@ "bugs, it is recommended to use JavaScript to create a " "script element and load it async. The <script> reference " "appears at: \"" - << inline_script_location_ << "\" and its src is \"" << src() << "\""; + << inline_script_location_ << "\" and its src is \"" << src << "\""; } load_option_ = 2;
diff --git a/cobalt/dom/html_script_element.h b/cobalt/dom/html_script_element.h index 3c9740e..f5537fd 100644 --- a/cobalt/dom/html_script_element.h +++ b/cobalt/dom/html_script_element.h
@@ -42,7 +42,13 @@ // Web API: HTMLScriptElement // - std::string src() const { return GetAttribute("src").value_or(""); } + // If the "src" attribute is a relative URL, the |src| property returns a + // fully resolved URL used the |document.location.href| as the base URL. This + // matches the Chrome implementation of the |src| property. + // See: + // https://source.chromium.org/chromium/chromium/src/+/main:out/Debug/gen/third_party/blink/renderer/bindings/core/v8/v8_html_script_element.cc;l=93;drc=4f7206c7352efba617f4561cd8c95844d9e9814f + // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/dom/element.cc;l=7360;drc=5f6702f8b8f9da8510d2b3ec809e177e6db09e53 + std::string src() const; void set_src(const std::string& value) { SetAttribute("src", value); } std::string type() const { return GetAttribute("type").value_or(""); }
diff --git a/cobalt/dom/media_source.cc b/cobalt/dom/media_source.cc index f9f2c05..1dcc7d3 100644 --- a/cobalt/dom/media_source.cc +++ b/cobalt/dom/media_source.cc
@@ -83,13 +83,14 @@ // If the system has more processors than the specified value, SourceBuffer // append and remove algorithm will be offloaded to a non-web thread to reduce // the load on the web thread. -// The default value is 2. Set to a reasonably high value (say 1024) will -// disable algorithm offloading completely. +// The default value is 1024, which effectively disable offloading by default. +// Setting to a reasonably low value (say 0 or 2) will enable algorithm +// offloading. bool IsAlgorithmOffloadEnabled(script::EnvironmentSettings* settings) { int min_process_count_to_offload = GetMediaSettings(settings) ->GetMinimumProcessorCountToOffloadAlgorithm() - .value_or(2); + .value_or(1024); DCHECK_GE(min_process_count_to_offload, 0); return SbSystemGetNumberOfProcessors() >= min_process_count_to_offload; } @@ -97,10 +98,10 @@ // If this function returns true, SourceBuffer will reduce asynchronous // behaviors. For example, queued events will be dispatached immediately when // possible. -// The default value is true. +// The default value is false. bool IsAsynchronousReductionEnabled(script::EnvironmentSettings* settings) { return GetMediaSettings(settings)->IsAsynchronousReductionEnabled().value_or( - true); + false); } // If the size of a job that is part of an algorithm is less than or equal to @@ -390,9 +391,10 @@ if (algorithm_process_thread_) { LOG(INFO) << "Algorithm offloading enabled."; - offload_algorithm_runner_.reset(new OffloadAlgorithmRunner( - algorithm_process_thread_->message_loop()->task_runner(), - base::MessageLoop::current()->task_runner())); + offload_algorithm_runner_.reset( + new OffloadAlgorithmRunner<SourceBufferAlgorithm>( + algorithm_process_thread_->message_loop()->task_runner(), + base::MessageLoop::current()->task_runner())); } else { LOG(INFO) << "Algorithm offloading disabled."; } @@ -574,7 +576,8 @@ return has_max_video_capabilities_; } -SerializedAlgorithmRunner* MediaSource::GetAlgorithmRunner(int job_size) { +SerializedAlgorithmRunner<SourceBufferAlgorithm>* +MediaSource::GetAlgorithmRunner(int job_size) { if (!offload_algorithm_runner_) { return &default_algorithm_runner_; }
diff --git a/cobalt/dom/media_source.h b/cobalt/dom/media_source.h index bfe0774..65ab2a8 100644 --- a/cobalt/dom/media_source.h +++ b/cobalt/dom/media_source.h
@@ -59,6 +59,7 @@ #include "cobalt/dom/media_source_ready_state.h" #include "cobalt/dom/serialized_algorithm_runner.h" #include "cobalt/dom/source_buffer.h" +#include "cobalt/dom/source_buffer_algorithm.h" #include "cobalt/dom/source_buffer_list.h" #include "cobalt/dom/time_ranges.h" #include "cobalt/dom/video_track.h" @@ -126,7 +127,8 @@ void SetSourceBufferActive(SourceBuffer* source_buffer, bool is_active); HTMLMediaElement* GetMediaElement() const; bool MediaElementHasMaxVideoCapabilities() const; - SerializedAlgorithmRunner* GetAlgorithmRunner(int job_size); + SerializedAlgorithmRunner<SourceBufferAlgorithm>* GetAlgorithmRunner( + int job_size); DEFINE_WRAPPABLE_TYPE(MediaSource); void TraceMembers(script::Tracer* tracer) override; @@ -148,9 +150,10 @@ const int min_size_for_immediate_job_; // The default algorithm runner runs all steps on the web thread. - DefaultAlgorithmRunner default_algorithm_runner_; + DefaultAlgorithmRunner<SourceBufferAlgorithm> default_algorithm_runner_; // The offload algorithm runner offloads some steps to a non-web thread. - std::unique_ptr<OffloadAlgorithmRunner> offload_algorithm_runner_; + std::unique_ptr<OffloadAlgorithmRunner<SourceBufferAlgorithm>> + offload_algorithm_runner_; std::unique_ptr<base::Thread> algorithm_process_thread_; ChunkDemuxer* chunk_demuxer_;
diff --git a/cobalt/dom/on_screen_keyboard.cc b/cobalt/dom/on_screen_keyboard.cc index 54c2242..188aa1e 100644 --- a/cobalt/dom/on_screen_keyboard.cc +++ b/cobalt/dom/on_screen_keyboard.cc
@@ -46,6 +46,14 @@ .second; DCHECK(is_emplaced); bridge_->Show(data_.c_str(), ticket); + + if (background_color_.has_value()) { + bridge_->SetBackgroundColor(background_color_.value().c_str()); + } + if (dark_theme_.has_value()) { + bridge_->SetDarkTheme(dark_theme_.value()); + } + return promise; }
diff --git a/cobalt/dom/on_screen_keyboard.h b/cobalt/dom/on_screen_keyboard.h index 8690c95..ce7d0fa 100644 --- a/cobalt/dom/on_screen_keyboard.h +++ b/cobalt/dom/on_screen_keyboard.h
@@ -99,6 +99,18 @@ void set_keep_focus(bool keep_focus); bool keep_focus() const { return keep_focus_; } + void set_background_color(base::Optional<std::string>& background_color) { + background_color_ = background_color; + } + base::Optional<std::string> background_color() const { + return background_color_; + } + + void set_dark_theme(base::Optional<bool> dark_theme) { + dark_theme_ = dark_theme; + } + base::Optional<bool> dark_theme() const { return dark_theme_; } + // Called by the WebModule to dispatch DOM show, hide, focus, blur and // suggestions updated events. void DispatchHideEvent(int ticket); @@ -135,6 +147,10 @@ bool suggestions_supported_; + base::Optional<std::string> background_color_; + + base::Optional<bool> dark_theme_; + DISALLOW_COPY_AND_ASSIGN(OnScreenKeyboard); }; } // namespace dom
diff --git a/cobalt/dom/on_screen_keyboard.idl b/cobalt/dom/on_screen_keyboard.idl index ebe632c..fe13887 100644 --- a/cobalt/dom/on_screen_keyboard.idl +++ b/cobalt/dom/on_screen_keyboard.idl
@@ -43,4 +43,15 @@ attribute EventHandler onfocus; attribute EventHandler onblur; attribute EventHandler oninput; + + // This attribute overrides the background color of on-screen keyboard. + // The attribute is only fully supported on Apple TV at the moment. + // backgroundColor should be a string of below formats: + // 1. hex color notation #RRGGBB, e.g. "#0000FF". + // 2. rgb color notation rgb(R, G, B), e.g. "rgb(0, 0, 255)". + attribute DOMString? backgroundColor; + + // This attribute overrides the dark theme of on-screen keyboard. + // The attribute is only fully supported on Apple TV at the moment. + attribute boolean? darkTheme; };
diff --git a/cobalt/dom/on_screen_keyboard_bridge.h b/cobalt/dom/on_screen_keyboard_bridge.h index d58c0ad..c5623af 100644 --- a/cobalt/dom/on_screen_keyboard_bridge.h +++ b/cobalt/dom/on_screen_keyboard_bridge.h
@@ -39,6 +39,8 @@ virtual scoped_refptr<DOMRect> BoundingRect() const = 0; virtual void SetKeepFocus(bool keep_focus) = 0; virtual bool IsValidTicket(int ticket) const = 0; + virtual void SetBackgroundColor(const char* background_color) = 0; + virtual void SetDarkTheme(bool dark_theme) = 0; }; } // namespace dom
diff --git a/cobalt/dom/on_screen_keyboard_test.cc b/cobalt/dom/on_screen_keyboard_test.cc index 4ab1e6f..fd616a3 100644 --- a/cobalt/dom/on_screen_keyboard_test.cc +++ b/cobalt/dom/on_screen_keyboard_test.cc
@@ -112,6 +112,10 @@ void SetKeepFocus(bool keep_focus) override { SetKeepFocusMock(keep_focus); } + void SetBackgroundColor(const char* background_color) override {} + + void SetDarkTheme(bool dark_theme) override {} + MOCK_METHOD1(ShowMock, void(std::string)); MOCK_METHOD0(HideMock, void()); MOCK_METHOD0(BlurMock, void()); @@ -604,5 +608,49 @@ EXPECT_TRUE(EvaluateScript(script, NULL)); } +TEST_F(OnScreenKeyboardTest, SetBackgroundColor) { + if (SkipLocale()) return; + + std::string result; + EXPECT_TRUE( + EvaluateScript("window.onScreenKeyboard.backgroundColor;", &result)); + EXPECT_EQ("null", result); + + std::string color_str = "#0000FF"; + EXPECT_TRUE(EvaluateScript("window.onScreenKeyboard.backgroundColor = '" + + color_str + + "';" + "window.onScreenKeyboard.backgroundColor", + &result)); + + EXPECT_EQ(color_str, result); + + color_str = "rgb(0, 0, 100)"; + EXPECT_TRUE(EvaluateScript("window.onScreenKeyboard.backgroundColor = '" + + color_str + + "';" + "window.onScreenKeyboard.backgroundColor", + &result)); + + EXPECT_EQ(color_str, result); +} + +TEST_F(OnScreenKeyboardTest, SetDarkTheme) { + if (SkipLocale()) return; + + std::string result; + EXPECT_TRUE(EvaluateScript("window.onScreenKeyboard.darkTheme;", &result)); + EXPECT_EQ("null", result); + + std::string dark_theme_str = "false"; + EXPECT_TRUE( + EvaluateScript("window.onScreenKeyboard.darkTheme = " + dark_theme_str + + ";" + "window.onScreenKeyboard.darkTheme", + &result)); + + EXPECT_EQ(dark_theme_str, result); +} + } // namespace dom } // namespace cobalt
diff --git a/cobalt/dom/serialized_algorithm_runner.cc b/cobalt/dom/serialized_algorithm_runner.cc deleted file mode 100644 index 07dece0..0000000 --- a/cobalt/dom/serialized_algorithm_runner.cc +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright 2022 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cobalt/dom/serialized_algorithm_runner.h" - -#include "base/message_loop/message_loop.h" - -namespace cobalt { -namespace dom { - -void DefaultAlgorithmRunner::Start(const scoped_refptr<HandleBase>& handle) { - DCHECK(handle); - TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::Start()"); - - if (asynchronous_reduction_enabled_) { - Process(handle); - return; - } - - auto task_runner = base::MessageLoop::current()->task_runner(); - task_runner->PostTask(FROM_HERE, - base::BindOnce(&DefaultAlgorithmRunner::Process, - base::Unretained(this), handle)); -} - -void DefaultAlgorithmRunner::Process(const scoped_refptr<HandleBase>& handle) { - DCHECK(handle); - TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::Process()"); - - auto task_runner = base::MessageLoop::current()->task_runner(); - - bool finished = false; - handle->Process(&finished); - - if (finished) { - handle->Finalize(); - return; - } - task_runner->PostTask(FROM_HERE, - base::BindOnce(&DefaultAlgorithmRunner::Process, - base::Unretained(this), handle)); -} - -OffloadAlgorithmRunner::OffloadAlgorithmRunner( - const scoped_refptr<TaskRunner>& process_task_runner, - const scoped_refptr<TaskRunner>& finalize_task_runner) - : process_task_runner_(process_task_runner), - finalize_task_runner_(finalize_task_runner) { - DCHECK(process_task_runner_); - DCHECK(finalize_task_runner_); - DCHECK_NE(process_task_runner_, finalize_task_runner_); -} - -void OffloadAlgorithmRunner::Start(const scoped_refptr<HandleBase>& handle) { - DCHECK(handle); - - TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::Start()"); - - process_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&OffloadAlgorithmRunner::Process, - base::Unretained(this), handle)); -} - -void OffloadAlgorithmRunner::Process(const scoped_refptr<HandleBase>& handle) { - DCHECK(handle); - DCHECK(process_task_runner_->BelongsToCurrentThread()); - - TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::Process()"); - - bool finished = false; - handle->Process(&finished); - - if (finished) { - finalize_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&HandleBase::Finalize, handle)); - return; - } - process_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&OffloadAlgorithmRunner::Process, - base::Unretained(this), handle)); -} - -} // namespace dom -} // namespace cobalt
diff --git a/cobalt/dom/serialized_algorithm_runner.h b/cobalt/dom/serialized_algorithm_runner.h index d4c2b39..db625ad 100644 --- a/cobalt/dom/serialized_algorithm_runner.h +++ b/cobalt/dom/serialized_algorithm_runner.h
@@ -22,6 +22,7 @@ #include "base/callback.h" #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" #include "base/trace_event/trace_event.h" #include "starboard/common/mutex.h" @@ -53,37 +54,56 @@ // This class will keep calling Process() until |finished| becomes false, and // then call Finalize(). It guarantees that all calls won't be overlapped and // the member functions of the algorithm don't have to synchronize between them. +template <typename SerializedAlgorithm> class SerializedAlgorithmRunner { public: - // Abstract the non-template part of the Handle class, and shouldn't be used - // directly. - class HandleBase : public base::RefCountedThreadSafe<HandleBase> { - public: - virtual ~HandleBase() {} - - virtual void Process(bool* finished) = 0; - virtual void Finalize() = 0; - }; - // A handle object for a running algorithm instance, to allow for aborting and // access the algorithm. - template <typename SerializedAlgorithm> - class Handle : public HandleBase { + class Handle : public base::RefCountedThreadSafe<Handle> { public: - explicit Handle(std::unique_ptr<SerializedAlgorithm> algorithm); - // Abort the algorithm and no more processing will happen on return. It is // possible that Process() has already finished asynchronously, in which // case this function will call Finalize() instead (if it hasn't been called // yet). void Abort(); + void Process(bool* finished); + void FinalizeIfNotAborted(); + SerializedAlgorithm* algorithm() const { return algorithm_.get(); } private: - void Process(bool* finished) override; - void Finalize() override; + friend class SerializedAlgorithmRunner; - // The |mutex_| is necessary as `Abort()` can be called from any thread. + // Provide synchronization only when |synchronization_required| is true. + // This allows bypassing of synchronization for algorithm runners that + // operate on a single thread, where a mutex could be reentrant if acquired + // due to nested calls. + class ScopedLockWhenRequired { + public: + ScopedLockWhenRequired(bool synchronization_required, + const starboard::Mutex& mutex) + : synchronization_required_(synchronization_required), mutex_(mutex) { + if (synchronization_required_) { + mutex_.Acquire(); + } + } + ~ScopedLockWhenRequired() { + if (synchronization_required_) { + mutex_.Release(); + } + } + + private: + const bool synchronization_required_; + const starboard::Mutex& mutex_; + }; + + Handle(bool synchronization_required, + std::unique_ptr<SerializedAlgorithm> algorithm); + + // The |mutex_| is necessary for algorithm runners operate on multiple + // threads as `Abort()` can be called from any thread. + const bool synchronization_required_; starboard::Mutex mutex_; std::unique_ptr<SerializedAlgorithm> algorithm_; bool aborted_ = false; @@ -93,21 +113,32 @@ virtual ~SerializedAlgorithmRunner() {} - virtual void Start(const scoped_refptr<HandleBase>& handle) = 0; + virtual scoped_refptr<Handle> CreateHandle( + std::unique_ptr<SerializedAlgorithm> algorithm) = 0; + virtual void Start(scoped_refptr<Handle> handle) = 0; + + protected: + scoped_refptr<Handle> CreateHandle( + bool synchronization_required, + std::unique_ptr<SerializedAlgorithm> algorithm) { + return new Handle(synchronization_required, std::move(algorithm)); + } }; template <typename SerializedAlgorithm> -SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Handle( +SerializedAlgorithmRunner<SerializedAlgorithm>::Handle::Handle( + bool synchronization_required, std::unique_ptr<SerializedAlgorithm> algorithm) - : algorithm_(std::move(algorithm)) { + : synchronization_required_(synchronization_required), + algorithm_(std::move(algorithm)) { DCHECK(algorithm_); } template <typename SerializedAlgorithm> -void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Abort() { +void SerializedAlgorithmRunner<SerializedAlgorithm>::Handle::Abort() { TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Abort()"); - starboard::ScopedLock scoped_lock(mutex_); + ScopedLockWhenRequired scoped_lock(synchronization_required_, mutex_); DCHECK(!aborted_); // Abort() cannot be called twice. @@ -126,18 +157,19 @@ } template <typename SerializedAlgorithm> -void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Process( +void SerializedAlgorithmRunner<SerializedAlgorithm>::Handle::Process( bool* finished) { TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Process()"); DCHECK(finished); - starboard::ScopedLock scoped_lock(mutex_); + ScopedLockWhenRequired scoped_lock(synchronization_required_, mutex_); DCHECK(!finished_); DCHECK(!finalized_); if (aborted_) { + *finished = true; return; } @@ -147,17 +179,19 @@ } template <typename SerializedAlgorithm> -void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Finalize() { +void SerializedAlgorithmRunner< + SerializedAlgorithm>::Handle::FinalizeIfNotAborted() { TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Finalize()"); - starboard::ScopedLock scoped_lock(mutex_); - DCHECK(finished_); + ScopedLockWhenRequired scoped_lock(synchronization_required_, mutex_); + DCHECK(!finalized_); if (aborted_) { return; } + DCHECK(finished_); DCHECK(algorithm_); algorithm_->Finalize(); @@ -167,14 +201,21 @@ // This class runs algorithm on the task runner associated with the thread where // Start() is called. -class DefaultAlgorithmRunner : public SerializedAlgorithmRunner { +template <typename SerializedAlgorithm> +class DefaultAlgorithmRunner + : public SerializedAlgorithmRunner<SerializedAlgorithm> { public: explicit DefaultAlgorithmRunner(bool asynchronous_reduction_enabled) : asynchronous_reduction_enabled_(asynchronous_reduction_enabled) {} private: - void Start(const scoped_refptr<HandleBase>& handle) override; - void Process(const scoped_refptr<HandleBase>& handle); + typedef + typename SerializedAlgorithmRunner<SerializedAlgorithm>::Handle Handle; + + scoped_refptr<Handle> CreateHandle( + std::unique_ptr<SerializedAlgorithm> algorithm) override; + void Start(scoped_refptr<Handle> handle) override; + void Process(scoped_refptr<Handle> handle); const bool asynchronous_reduction_enabled_; }; @@ -185,7 +226,9 @@ // This class will keep calling the Process() member function of the algorithm // on the process task runner, and then call Finalize() on the finalize task // runner when |finished| becomes true. -class OffloadAlgorithmRunner : public SerializedAlgorithmRunner { +template <typename SerializedAlgorithm> +class OffloadAlgorithmRunner + : public SerializedAlgorithmRunner<SerializedAlgorithm> { public: typedef base::SingleThreadTaskRunner TaskRunner; @@ -193,13 +236,121 @@ const scoped_refptr<TaskRunner>& finalize_task_runner); private: - void Start(const scoped_refptr<HandleBase>& handle) override; - void Process(const scoped_refptr<HandleBase>& handle); + typedef + typename SerializedAlgorithmRunner<SerializedAlgorithm>::Handle Handle; + + scoped_refptr<Handle> CreateHandle( + std::unique_ptr<SerializedAlgorithm> algorithm) override; + void Start(scoped_refptr<Handle> handle) override; + void Process(scoped_refptr<Handle> handle); scoped_refptr<TaskRunner> process_task_runner_; scoped_refptr<TaskRunner> finalize_task_runner_; }; +template <typename SerializedAlgorithm> +scoped_refptr<typename SerializedAlgorithmRunner<SerializedAlgorithm>::Handle> +DefaultAlgorithmRunner<SerializedAlgorithm>::CreateHandle( + std::unique_ptr<SerializedAlgorithm> algorithm) { + TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::CreateHandle()"); + + const bool kSynchronizationRequired = false; + return SerializedAlgorithmRunner<SerializedAlgorithm>::CreateHandle( + kSynchronizationRequired, std::move(algorithm)); +} + +template <typename SerializedAlgorithm> +void DefaultAlgorithmRunner<SerializedAlgorithm>::Start( + scoped_refptr<Handle> handle) { + DCHECK(handle); + TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::Start()"); + + if (asynchronous_reduction_enabled_) { + Process(handle); + return; + } + + auto task_runner = base::MessageLoop::current()->task_runner(); + task_runner->PostTask(FROM_HERE, + base::BindOnce(&DefaultAlgorithmRunner::Process, + base::Unretained(this), handle)); +} + +template <typename SerializedAlgorithm> +void DefaultAlgorithmRunner<SerializedAlgorithm>::Process( + scoped_refptr<Handle> handle) { + DCHECK(handle); + TRACE_EVENT0("cobalt::dom", "DefaultAlgorithmRunner::Process()"); + + auto task_runner = base::MessageLoop::current()->task_runner(); + + bool finished = false; + handle->Process(&finished); + + if (finished) { + handle->FinalizeIfNotAborted(); + return; + } + task_runner->PostTask(FROM_HERE, + base::BindOnce(&DefaultAlgorithmRunner::Process, + base::Unretained(this), handle)); +} + +template <typename SerializedAlgorithm> +OffloadAlgorithmRunner<SerializedAlgorithm>::OffloadAlgorithmRunner( + const scoped_refptr<TaskRunner>& process_task_runner, + const scoped_refptr<TaskRunner>& finalize_task_runner) + : process_task_runner_(process_task_runner), + finalize_task_runner_(finalize_task_runner) { + DCHECK(process_task_runner_); + DCHECK(finalize_task_runner_); + DCHECK_NE(process_task_runner_, finalize_task_runner_); +} + +template <typename SerializedAlgorithm> +scoped_refptr<typename SerializedAlgorithmRunner<SerializedAlgorithm>::Handle> +OffloadAlgorithmRunner<SerializedAlgorithm>::CreateHandle( + std::unique_ptr<SerializedAlgorithm> algorithm) { + TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::CreateHandle()"); + + const bool kSynchronizationRequired = true; + return SerializedAlgorithmRunner<SerializedAlgorithm>::CreateHandle( + kSynchronizationRequired, std::move(algorithm)); +} + +template <typename SerializedAlgorithm> +void OffloadAlgorithmRunner<SerializedAlgorithm>::Start( + scoped_refptr<Handle> handle) { + DCHECK(handle); + + TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::Start()"); + + process_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&OffloadAlgorithmRunner::Process, + base::Unretained(this), handle)); +} + +template <typename SerializedAlgorithm> +void OffloadAlgorithmRunner<SerializedAlgorithm>::Process( + scoped_refptr<Handle> handle) { + DCHECK(handle); + DCHECK(process_task_runner_->BelongsToCurrentThread()); + + TRACE_EVENT0("cobalt::dom", "OffloadAlgorithmRunner::Process()"); + + bool finished = false; + handle->Process(&finished); + + if (finished) { + finalize_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&Handle::FinalizeIfNotAborted, handle)); + return; + } + process_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&OffloadAlgorithmRunner::Process, + base::Unretained(this), handle)); +} + } // namespace dom } // namespace cobalt
diff --git a/cobalt/dom/source_buffer.cc b/cobalt/dom/source_buffer.cc index ffaee80..1f6278b 100644 --- a/cobalt/dom/source_buffer.cc +++ b/cobalt/dom/source_buffer.cc
@@ -387,11 +387,11 @@ base::Unretained(this)), base::Bind(&SourceBuffer::OnAlgorithmFinalized, base::Unretained(this)))); + auto algorithm_runner = + media_source_->GetAlgorithmRunner(std::numeric_limits<int>::max()); active_algorithm_handle_ = - new SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>( - std::move(algorithm)); - media_source_->GetAlgorithmRunner(std::numeric_limits<int>::max()) - ->Start(active_algorithm_handle_); + algorithm_runner->CreateHandle(std::move(algorithm)); + algorithm_runner->Start(active_algorithm_handle_); } void SourceBuffer::set_track_defaults( @@ -482,9 +482,13 @@ } void SourceBuffer::ScheduleAndMaybeDispatchImmediately(base::Token event_name) { + ScheduleEvent(event_name); + // TODO(b/244773734): Re-enable direct event dispatching + /* scoped_refptr<web::Event> event = new web::Event(event_name); event->set_target(this); event_queue_->EnqueueAndMaybeDispatchImmediately(event); + */ } bool SourceBuffer::PrepareAppend(size_t new_data_size, @@ -509,6 +513,7 @@ return false; } + metrics_.StartTracking(); media_source_->OpenIfInEndedState(); double current_time = media_source_->GetMediaElement()->current_time(NULL); @@ -517,9 +522,11 @@ new_data_size + evict_extra_in_bytes_)) { web::DOMException::Raise(web::DOMException::kQuotaExceededErr, exception_state); + metrics_.EndTracking(0); return false; } + metrics_.EndTracking(0); return true; } @@ -528,11 +535,9 @@ script::ExceptionState* exception_state) { TRACE_EVENT1("cobalt::dom", "SourceBuffer::AppendBufferInternal()", "size", size); - metrics_.StartTracking(); if (!PrepareAppend(size, exception_state)) { return; } - metrics_.EndTracking(0); DCHECK(data || size == 0); @@ -562,10 +567,10 @@ base::Bind(&SourceBuffer::OnAlgorithmFinalized, base::Unretained(this)), &metrics_)); + auto algorithm_runner = media_source_->GetAlgorithmRunner(size); active_algorithm_handle_ = - new SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>( - std::move(algorithm)); - media_source_->GetAlgorithmRunner(size)->Start(active_algorithm_handle_); + algorithm_runner->CreateHandle(std::move(algorithm)); + algorithm_runner->Start(active_algorithm_handle_); } void SourceBuffer::OnAlgorithmFinalized() {
diff --git a/cobalt/dom/source_buffer.h b/cobalt/dom/source_buffer.h index 0cf7f28..c7336e6 100644 --- a/cobalt/dom/source_buffer.h +++ b/cobalt/dom/source_buffer.h
@@ -204,7 +204,7 @@ starboard::Mutex timestamp_offset_mutex_; double timestamp_offset_ = 0; - scoped_refptr<SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>> + scoped_refptr<SerializedAlgorithmRunner<SourceBufferAlgorithm>::Handle> active_algorithm_handle_; double append_window_start_ = 0; double append_window_end_ = std::numeric_limits<double>::infinity();
diff --git a/cobalt/extension/on_screen_keyboard.h b/cobalt/extension/on_screen_keyboard.h new file mode 100644 index 0000000..a1d922d --- /dev/null +++ b/cobalt/extension/on_screen_keyboard.h
@@ -0,0 +1,57 @@ +// Copyright 2022 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COBALT_EXTENSION_ON_SCREEN_KEYBOARD_H_ +#define COBALT_EXTENSION_ON_SCREEN_KEYBOARD_H_ + +#include <stdint.h> + +#include "starboard/system.h" +#include "starboard/window.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define kCobaltExtensionOnScreenKeyboardName \ + "dev.cobalt.extension.OnScreenKeyboard" + +typedef struct CobaltExtensionOnScreenKeyboardApi { + // Name should be the string + // |kCobaltExtensionOnScreenKeyboardName|. This helps to validate that + // the extension API is correct. + const char* name; + + // This specifies the version of the API that is implemented. + uint32_t version; + + // The fields below this point were added in version 1 or later. + + // This function overrides the background color of on-screen keyboard. + // The function is only enabled for Apple TV at the moment. + // background_color should be a string of below formats: + // 1. hex color notation #RRGGBB, e.g. "#0000FF". + // 2. rgb color notation rgb(R, G, B), e.g. "rgb(0, 0, 255)". + void (*SetBackgroundColor)(SbWindow window, const char* background_color); + + // This function overrides the dark theme of on-screen keyboard. + // The function is only enabled for Apple TV at the moment. + void (*SetDarkTheme)(SbWindow window, bool dark_theme); +} CobaltExtensionOnScreenKeyboardApi; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // COBALT_EXTENSION_ON_SCREEN_KEYBOARD_H_
diff --git a/cobalt/media_session/media_session_client.cc b/cobalt/media_session/media_session_client.cc index e668cae..c8290cf 100644 --- a/cobalt/media_session/media_session_client.cc +++ b/cobalt/media_session/media_session_client.cc
@@ -331,7 +331,7 @@ ext_image.src = media_image.src().c_str(); if (ext_image.src == nullptr) { // src() is required, but Cobalt IDL parser doesn't enforce it. - // http://cs/cobalt/cobalt/media_session/media_image.idl?l=19 + // See cobalt/media_session/media_image.idl for more info. // https://wicg.github.io/mediasession/#dictdef-mediaimage LOG(ERROR) << "Required src string for MediaImage is missing."; }
diff --git a/starboard/CHANGELOG.md b/starboard/CHANGELOG.md index 69ca601..fddc2c3 100644 --- a/starboard/CHANGELOG.md +++ b/starboard/CHANGELOG.md
@@ -15,6 +15,9 @@ [configuration.h](configuration.h). ## Version 14 +### Require kSbSystemPathStorageDirectory on all platforms. +Path to directory for permanent persistent storage. + ### Add MP3, FLAC, and PCM values to SbMediaAudioCodec. This makes it possible to support these codecs in the future.
diff --git a/starboard/android/apk/app/src/app/AndroidManifest.xml b/starboard/android/apk/app/src/app/AndroidManifest.xml index 42d8bc0..9c4e11a 100644 --- a/starboard/android/apk/app/src/app/AndroidManifest.xml +++ b/starboard/android/apk/app/src/app/AndroidManifest.xml
@@ -32,7 +32,7 @@ <!-- This is needed when targeting API 28+ to use foreground services --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> - <!-- Used for go/cobalt-ifa and AdvertisingIdClient.Info.getId() --> + <!-- https://iabtechlab.com/OTT-IFA, AdvertisingIdClient.Info.getId() --> <uses-permission android:name="com.google.android.gms.permission.AD_ID"/> <application
diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/libraries/services/clientloginfo/ClientLogInfo.java b/starboard/android/apk/app/src/main/java/dev/cobalt/libraries/services/clientloginfo/ClientLogInfo.java index 57c39ad..7628f93 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/libraries/services/clientloginfo/ClientLogInfo.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/libraries/services/clientloginfo/ClientLogInfo.java
@@ -6,10 +6,7 @@ import dev.cobalt.coat.CobaltService; import dev.cobalt.util.Log; -/** - * ClientLogInfo to report Android API support on android devices, read go/coat-api-support for more - * info. - */ +/** ClientLogInfo to report Android API support on android devices. */ public class ClientLogInfo extends CobaltService { public static final String TAG = "ClientLogInfo";
diff --git a/starboard/nplb/system_get_path_test.cc b/starboard/nplb/system_get_path_test.cc index e320737..44f4e00 100644 --- a/starboard/nplb/system_get_path_test.cc +++ b/starboard/nplb/system_get_path_test.cc
@@ -69,6 +69,9 @@ TEST(SbSystemGetPathTest, ReturnsRequiredPaths) { BasicTest(kSbSystemPathContentDirectory, true, true, __LINE__); BasicTest(kSbSystemPathCacheDirectory, true, true, __LINE__); +#if SB_API_VERSION >= 14 + BasicTest(kSbSystemPathStorageDirectory, true, true, __LINE__); +#endif // SB_API_VERSION >= 14 } TEST(SbSystemGetPathTest, FailsGracefullyZeroBufferLength) {
diff --git a/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h b/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h index 3f6e7c0..8a997a8 100644 --- a/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h +++ b/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h
@@ -62,9 +62,6 @@ void Reset() override; private: - void ProcessOneInputBuffer(const scoped_refptr<InputBuffer>& input_buffer, - const ConsumedCB& consumed_cb); - void InitializeAudioDecoder(const SbMediaAudioSampleInfo& audio_sample_info); void TeardownAudioDecoder(); void OnDecoderOutput();