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();