Import Cobalt 23.lts.1.309088
diff --git a/cobalt/bindings/path_generator.py b/cobalt/bindings/path_generator.py
index 192ff59..ee91538 100644
--- a/cobalt/bindings/path_generator.py
+++ b/cobalt/bindings/path_generator.py
@@ -63,22 +63,7 @@
rel_idl_path = os.path.relpath(idl_path, self.interfaces_root)
components = os.path.dirname(rel_idl_path).split(os.sep)
-
- # Check if this IDL's path lies in our interfaces root. If it does not,
- # we treat it as an extension IDL.
- real_interfaces_root = os.path.realpath(self.interfaces_root)
- real_idl_path = os.path.realpath(os.path.dirname(idl_path))
- interfaces_root_is_in_components_path = (
- os.path.commonprefix([real_interfaces_root,
- real_idl_path]) == real_interfaces_root)
-
- if interfaces_root_is_in_components_path:
- return [os.path.basename(self.interfaces_root)] + components
- else:
- # If our IDL path lies outside of the cobalt/ directory, assume it is
- # an externally defined web extension and assign it the 'webapi_extension'
- # namespace.
- return [os.path.basename(self.interfaces_root), 'webapi_extension']
+ return [os.path.basename(self.interfaces_root)] + components
def Namespace(self, interface_name):
"""Get the interface's namespace."""
diff --git a/cobalt/bindings/testing/BUILD.gn b/cobalt/bindings/testing/BUILD.gn
index 523ca00..b97f61c 100644
--- a/cobalt/bindings/testing/BUILD.gn
+++ b/cobalt/bindings/testing/BUILD.gn
@@ -94,6 +94,7 @@
"promise_interface.idl",
"put_forwards_interface.idl",
"sequence_user.idl",
+ "serialize_script_value_interface.idl",
"single_operation_interface.idl",
"static_properties_interface.idl",
"stringifier_anonymous_operation_interface.idl",
@@ -185,6 +186,7 @@
"promise_test.cc",
"put_forwards_test.cc",
"sequence_bindings_test.cc",
+ "serialize_script_value_test.cc",
"stack_trace_test.cc",
"static_properties_bindings_test.cc",
"stringifier_bindings_test.cc",
diff --git a/cobalt/bindings/testing/serialize_script_value_interface.h b/cobalt/bindings/testing/serialize_script_value_interface.h
new file mode 100644
index 0000000..782edb2
--- /dev/null
+++ b/cobalt/bindings/testing/serialize_script_value_interface.h
@@ -0,0 +1,63 @@
+// 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_BINDINGS_TESTING_SERIALIZE_SCRIPT_VALUE_INTERFACE_H_
+#define COBALT_BINDINGS_TESTING_SERIALIZE_SCRIPT_VALUE_INTERFACE_H_
+
+#include <memory>
+#include <utility>
+
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/environment_settings.h"
+#include "cobalt/script/typed_arrays.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/web/context.h"
+#include "cobalt/web/environment_settings.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class SerializeScriptValueInterface : public script::Wrappable {
+ public:
+ SerializeScriptValueInterface() = default;
+
+ size_t serialized_size() { return data_buffer_->size; }
+
+ void SerializeTest(const script::ValueHandleHolder& value) {
+ data_buffer_ = std::move(script::SerializeScriptValue(value));
+ isolate_ = script::GetIsolate(value);
+ }
+
+ const script::ValueHandleHolder* DeserializeTest() {
+ deserialized_.reset(
+ script::DeserializeScriptValue(isolate_, *data_buffer_));
+ return deserialized_.get();
+ }
+
+ DEFINE_WRAPPABLE_TYPE(SerializeScriptValueInterface);
+
+ private:
+ std::unique_ptr<script::DataBuffer> data_buffer_;
+ std::unique_ptr<script::ValueHandleHolder> deserialized_;
+ v8::Isolate* isolate_;
+};
+
+} // namespace testing
+} // namespace bindings
+} // namespace cobalt
+
+#endif // COBALT_BINDINGS_TESTING_SERIALIZE_SCRIPT_VALUE_INTERFACE_H_
diff --git a/starboard/shared/test_webapi_extension/my_new_interface.idl b/cobalt/bindings/testing/serialize_script_value_interface.idl
similarity index 75%
rename from starboard/shared/test_webapi_extension/my_new_interface.idl
rename to cobalt/bindings/testing/serialize_script_value_interface.idl
index 8f49995..9fd6a06 100644
--- a/starboard/shared/test_webapi_extension/my_new_interface.idl
+++ b/cobalt/bindings/testing/serialize_script_value_interface.idl
@@ -1,4 +1,4 @@
-// Copyright 2017 The Cobalt Authors. All Rights Reserved.
+// 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.
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-interface MyNewInterface {
- attribute DOMString foo;
-
- void SetMyNewEnum(MyNewEnum value);
- MyNewEnum GetMyNewEnum();
+[ Constructor ]
+interface SerializeScriptValueInterface {
+ void serializeTest(any value);
+ any deserializeTest();
};
diff --git a/cobalt/bindings/testing/serialize_script_value_test.cc b/cobalt/bindings/testing/serialize_script_value_test.cc
new file mode 100644
index 0000000..96e0dc6
--- /dev/null
+++ b/cobalt/bindings/testing/serialize_script_value_test.cc
@@ -0,0 +1,55 @@
+// 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 "base/strings/string_number_conversions.h"
+#include "cobalt/bindings/testing/bindings_test_base.h"
+#include "cobalt/bindings/testing/serialize_script_value_interface.h"
+
+using ::testing::ContainsRegex;
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class SerializeScriptValueTest
+ : public InterfaceBindingsTest<SerializeScriptValueInterface> {
+ public:
+ void ExpectTrue(const std::string& script) {
+ std::string result;
+ EvaluateScript("`${" + script + "}`", &result);
+ EXPECT_EQ("true", result)
+ << "Expect \"" + script + "\" to evaluate to true.";
+ }
+};
+
+TEST_F(SerializeScriptValueTest, Serialize) {
+ // Stores serialized result that is then used by |deserializeTest()|.
+ EvaluateScript(R"(
+ test.serializeTest({a: ['something'], b: new Uint8Array([42])});
+ )");
+ // Sanity check the serialized size.
+ EXPECT_EQ(32, test_mock().serialized_size());
+ ExpectTrue("!(test.deserializeTest() instanceof Array)");
+ ExpectTrue("test.deserializeTest() instanceof Object");
+ ExpectTrue("test.deserializeTest().a instanceof Array");
+ ExpectTrue("1 === test.deserializeTest().a.length");
+ ExpectTrue("'something' === test.deserializeTest().a[0]");
+ ExpectTrue("test.deserializeTest().b instanceof Uint8Array");
+ ExpectTrue("!(test.deserializeTest().b instanceof Uint16Array)");
+ ExpectTrue("42 === test.deserializeTest().b[0]");
+}
+
+} // namespace testing
+} // namespace bindings
+} // namespace cobalt
diff --git a/cobalt/browser/browser_module.cc b/cobalt/browser/browser_module.cc
index d95d150..b80da96 100644
--- a/cobalt/browser/browser_module.cc
+++ b/cobalt/browser/browser_module.cc
@@ -21,6 +21,7 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
@@ -28,7 +29,6 @@
#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/cobalt_paths.h"
@@ -144,15 +144,6 @@
"activated or not. While activated, input will constantly and randomly be "
"generated and passed directly into the main web module.";
-const char kSetMediaConfigCommand[] = "set_media_config";
-const char kSetMediaConfigCommandShortHelp[] =
- "Sets media module configuration.";
-const char kSetMediaConfigCommandLongHelp[] =
- "This can be called in the form of set_media_config('name=value'), where "
- "name is a string and value is an int. Refer to the implementation of "
- "MediaModule::SetConfiguration() on individual platform for settings "
- "supported on the particular platform.";
-
const char kScreenshotCommand[] = "screenshot";
const char kScreenshotCommandShortHelp[] = "Takes a screenshot.";
const char kScreenshotCommandLongHelp[] =
@@ -268,10 +259,6 @@
kFuzzerToggleCommand,
base::Bind(&BrowserModule::OnFuzzerToggle, base::Unretained(this)),
kFuzzerToggleCommandShortHelp, kFuzzerToggleCommandLongHelp)),
- ALLOW_THIS_IN_INITIALIZER_LIST(set_media_config_command_handler_(
- kSetMediaConfigCommand,
- base::Bind(&BrowserModule::OnSetMediaConfig, base::Unretained(this)),
- kSetMediaConfigCommandShortHelp, kSetMediaConfigCommandLongHelp)),
ALLOW_THIS_IN_INITIALIZER_LIST(screenshot_command_handler_(
kScreenshotCommand,
base::Bind(&OnScreenshotMessage, base::Unretained(this)),
@@ -450,9 +437,10 @@
switch (application_state_) {
case base::kApplicationStateStarted:
Blur(0);
- // Intentional fall-through.
+ FALLTHROUGH;
case base::kApplicationStateBlurred:
Conceal(0);
+ FALLTHROUGH;
case base::kApplicationStateConcealed:
Freeze(0);
break;
@@ -1011,30 +999,6 @@
}
}
-void BrowserModule::OnSetMediaConfig(const std::string& config) {
- if (base::MessageLoop::current() != self_message_loop_) {
- self_message_loop_->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&BrowserModule::OnSetMediaConfig, weak_this_, config));
- return;
- }
-
- std::vector<std::string> tokens = base::SplitString(
- config, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
- int value;
- if (tokens.size() != 2 || !base::StringToInt(tokens[1], &value)) {
- LOG(WARNING) << "Media configuration '" << config << "' is not in the"
- << " form of '<string name>=<int value>'.";
- return;
- }
- if (media_module_->SetConfiguration(tokens[0], value)) {
- LOG(INFO) << "Successfully setting " << tokens[0] << " to " << value;
- } else {
- LOG(WARNING) << "Failed to set " << tokens[0] << " to " << value;
- }
-}
-
void BrowserModule::OnDisableMediaCodecs(const std::string& codecs) {
disabled_media_codecs_ = codecs;
can_play_type_handler_->SetDisabledMediaCodecs(codecs);
@@ -2059,8 +2023,11 @@
scoped_refptr<script::Wrappable> BrowserModule::CreateH5vcc(
script::EnvironmentSettings* settings) {
+ DCHECK(web_module_);
+
h5vcc::H5vcc::Settings h5vcc_settings;
- h5vcc_settings.media_module = media_module_.get();
+ h5vcc_settings.set_media_source_setting_func = base::Bind(
+ &WebModule::SetMediaSourceSetting, base::Unretained(web_module_.get()));
h5vcc_settings.network_module = network_module_;
#if SB_IS(EVERGREEN)
h5vcc_settings.updater_module = updater_module_;
diff --git a/cobalt/browser/browser_module.h b/cobalt/browser/browser_module.h
index b618caa..6730fa2 100644
--- a/cobalt/browser/browser_module.h
+++ b/cobalt/browser/browser_module.h
@@ -355,10 +355,6 @@
// Toggles the input fuzzer on/off. Ignores the parameter.
void OnFuzzerToggle(const std::string&);
- // Use the config in the form of '<string name>=<int value>' to call
- // MediaModule::SetConfiguration().
- void OnSetMediaConfig(const std::string& config);
-
// Sets the disabled media codecs in the debug console and in
// the CanPlayTypeHandler instance.
// Future requests to play videos with these codecs will report that these
@@ -615,10 +611,6 @@
debug::console::ConsoleCommandManager::CommandHandler
fuzzer_toggle_command_handler_;
- // Command handler object for setting media module config.
- debug::console::ConsoleCommandManager::CommandHandler
- set_media_config_command_handler_;
-
// Command handler object for screenshot command from the debug console.
debug::console::ConsoleCommandManager::CommandHandler
screenshot_command_handler_;
diff --git a/cobalt/browser/web_module.cc b/cobalt/browser/web_module.cc
index 8311b31..ecc0f56 100644
--- a/cobalt/browser/web_module.cc
+++ b/cobalt/browser/web_module.cc
@@ -48,6 +48,7 @@
#include "cobalt/dom/keyboard_event.h"
#include "cobalt/dom/keyboard_event_init.h"
#include "cobalt/dom/local_storage_database.h"
+#include "cobalt/dom/media_source_settings.h"
#include "cobalt/dom/mutation_observer_task_manager.h"
#include "cobalt/dom/navigation_type.h"
#include "cobalt/dom/navigator.h"
@@ -215,6 +216,8 @@
void SetSize(cssom::ViewportSize viewport_size);
void UpdateCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
void SetMediaModule(media::MediaModule* media_module);
+ void SetMediaSourceSetting(const std::string& name, int value,
+ bool* succeeded);
void SetImageCacheCapacity(int64_t bytes);
void SetRemoteTypefaceCacheCapacity(int64_t bytes);
@@ -396,6 +399,9 @@
// Object to register and retrieve MediaSource object with a string key.
std::unique_ptr<dom::MediaSource::Registry> media_source_registry_;
+ // Object to hold WebModule wide settings for MediaSource related objects.
+ dom::MediaSourceSettingsImpl media_source_settings_;
+
// The Window object wraps all DOM-related components.
scoped_refptr<dom::Window> window_;
@@ -580,8 +586,8 @@
web_context_->setup_environment_settings(new dom::DOMSettings(
debugger_hooks_, kDOMMaxElementDepth, media_source_registry_.get(),
- data.can_play_type_handler, memory_info, &mutation_observer_task_manager_,
- data.options.dom_settings_options));
+ &media_source_settings_, data.can_play_type_handler, memory_info,
+ &mutation_observer_task_manager_, data.options.dom_settings_options));
DCHECK(web_context_->environment_settings());
// From algorithm to setup up a window environment settings object:
// https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#set-up-a-window-environment-settings-object
@@ -706,7 +712,7 @@
web_context_->global_environment()->SetReportEvalCallback(
base::Bind(&web::CspDelegate::ReportEval,
- base::Unretained(window_->document()->csp_delegate())));
+ base::Unretained(window_->csp_delegate())));
web_context_->global_environment()->SetReportErrorCallback(
base::Bind(&WebModule::Impl::ReportScriptError, base::Unretained(this)));
@@ -1013,12 +1019,10 @@
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(is_running_);
DCHECK(window_);
- DCHECK(window_->document());
- DCHECK(window_->document()->csp_delegate());
+ DCHECK(window_->csp_delegate());
std::string eval_disabled_message;
- bool allow_eval =
- window_->document()->csp_delegate()->AllowEval(&eval_disabled_message);
+ bool allow_eval = window_->csp_delegate()->AllowEval(&eval_disabled_message);
if (allow_eval) {
web_context_->global_environment()->EnableEval();
} else {
@@ -1096,6 +1100,12 @@
window_->set_web_media_player_factory(media_module);
}
+void WebModule::Impl::SetMediaSourceSetting(const std::string& name, int value,
+ bool* succeeded) {
+ DCHECK(succeeded);
+ *succeeded = media_source_settings_.Set(name, value);
+}
+
void WebModule::Impl::SetApplicationState(base::ApplicationState state,
SbTimeMonotonic timestamp) {
window_->SetApplicationState(state, timestamp);
@@ -1576,6 +1586,12 @@
impl_->SetMediaModule(media_module);
}
+bool WebModule::SetMediaSourceSetting(const std::string& name, int value) {
+ bool succeeded = false;
+ SetMediaSourceSettingInternal(name, value, &succeeded);
+ return succeeded;
+}
+
void WebModule::SetImageCacheCapacity(int64_t bytes) {
POST_TO_ENSURE_IMPL_ON_THREAD(SetImageCacheCapacity, bytes);
impl_->SetImageCacheCapacity(bytes);
@@ -1709,5 +1725,12 @@
impl_->SetUnloadEventTimingInfo(start_time, end_time);
}
+void WebModule::SetMediaSourceSettingInternal(const std::string& name,
+ int value, bool* succeeded) {
+ POST_AND_BLOCK_TO_ENSURE_IMPL_ON_THREAD(SetMediaSourceSettingInternal, name,
+ value, succeeded);
+ impl_->SetMediaSourceSetting(name, value, succeeded);
+}
+
} // namespace browser
} // namespace cobalt
diff --git a/cobalt/browser/web_module.h b/cobalt/browser/web_module.h
index b7c21e5..3e442c8 100644
--- a/cobalt/browser/web_module.h
+++ b/cobalt/browser/web_module.h
@@ -338,6 +338,7 @@
void UpdateCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
void SetMediaModule(media::MediaModule* media_module);
+ bool SetMediaSourceSetting(const std::string& name, int value);
void SetImageCacheCapacity(int64_t bytes);
void SetRemoteTypefaceCacheCapacity(int64_t bytes);
@@ -458,10 +459,11 @@
void ClearAllIntervalsAndTimeouts();
- void CancelSynchronousLoads();
-
void GetIsReadyToFreeze(volatile bool* is_ready_to_freeze);
+ void SetMediaSourceSettingInternal(const std::string& name, int value,
+ bool* succeeded);
+
// The message loop this object is running on.
base::MessageLoop* message_loop() const {
DCHECK(web_agent_);
diff --git a/cobalt/build/build_number.py b/cobalt/build/build_number.py
index b0307e3..7ec534e 100644
--- a/cobalt/build/build_number.py
+++ b/cobalt/build/build_number.py
@@ -44,28 +44,15 @@
def GetRevinfo():
"""Get absolute state of all git repos."""
- try:
- repo_root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'
- ]).strip().decode('utf-8')
- except subprocess.CalledProcessError:
- logging.info('Could not get repo root. Trying again in src/')
- try:
- repo_root = subprocess.check_output(
- ['git', '-C', 'src', 'rev-parse',
- '--show-toplevel']).strip().decode('utf-8')
- except subprocess.CalledProcessError as e:
- logging.warning('Failed to get revision information: %s', e)
- return {}
-
# First make sure we can add the cobalt_src repo.
try:
- repos = CheckRevInfo('.', cwd=repo_root)
+ repos = CheckRevInfo('.', cwd=paths.REPOSITORY_ROOT)
except subprocess.CalledProcessError as e:
logging.warning('Failed to get revision information: %s', e)
return {}
for rel_path in _SUBREPO_PATHS:
- path = os.path.join(repo_root, rel_path)
+ path = os.path.join(paths.REPOSITORY_ROOT, rel_path)
try:
repos.update(CheckRevInfo(rel_path, cwd=path))
except subprocess.CalledProcessError as e:
diff --git a/cobalt/debug/backend/debug_module.cc b/cobalt/debug/backend/debug_module.cc
index 982f8f3..56e8b26 100644
--- a/cobalt/debug/backend/debug_module.cc
+++ b/cobalt/debug/backend/debug_module.cc
@@ -123,7 +123,7 @@
script::ScriptDebugger::CreateDebugger(data.global_environment, this);
script_runner_.reset(new DebugScriptRunner(
data.global_environment, script_debugger_.get(),
- data.window ? data.window->document()->csp_delegate() : nullptr));
+ data.window ? data.window->csp_delegate() : nullptr));
debug_dispatcher_.reset(
new DebugDispatcher(script_debugger_.get(), script_runner_.get()));
debug_backend_ = WrapRefCounted(new DebugBackend(
diff --git a/cobalt/demos/content/BUILD.gn b/cobalt/demos/content/BUILD.gn
index e87713e..c23edf1 100644
--- a/cobalt/demos/content/BUILD.gn
+++ b/cobalt/demos/content/BUILD.gn
@@ -133,7 +133,6 @@
"performance-spike/assets/banner720.jpg",
"performance-spike/assets/banner720baked.jpg",
"performance-spike/assets/icons.ttf",
- "performance-spike/assets/profile-alecmce.jpg",
"performance-spike/css/default.css",
"performance-spike/css/icons-content.css",
"performance-spike/css/icons.css",
diff --git a/cobalt/demos/content/watchdog-demo/index.html b/cobalt/demos/content/watchdog-demo/index.html
index 0213470..c5f17f8 100644
--- a/cobalt/demos/content/watchdog-demo/index.html
+++ b/cobalt/demos/content/watchdog-demo/index.html
@@ -59,7 +59,7 @@
let ret = 'void';
if (watchdogFunction == 'register') {
- ret = h5vcc.crashLog.register('test-name', 'test-description', 'started', 5000000, 0, 'none');
+ ret = h5vcc.crashLog.register('test-name', 'test-description', 'started', 3000, 0, 'none');
} else if (watchdogFunction == 'unregister') {
ret = h5vcc.crashLog.unregister('test-name');
} else if (watchdogFunction == 'ping') {
diff --git a/cobalt/dom/BUILD.gn b/cobalt/dom/BUILD.gn
index 74caf14..e16397b 100644
--- a/cobalt/dom/BUILD.gn
+++ b/cobalt/dom/BUILD.gn
@@ -187,6 +187,8 @@
"media_query_list.h",
"media_source.cc",
"media_source.h",
+ "media_source_settings.cc",
+ "media_source_settings.h",
"memory_info.cc",
"memory_info.h",
"mime_type_array.cc",
@@ -259,10 +261,14 @@
"screenshot.h",
"screenshot_manager.cc",
"screenshot_manager.h",
+ "serialized_algorithm_runner.cc",
+ "serialized_algorithm_runner.h",
"serializer.cc",
"serializer.h",
"source_buffer.cc",
"source_buffer.h",
+ "source_buffer_algorithm.cc",
+ "source_buffer_algorithm.h",
"source_buffer_list.cc",
"source_buffer_list.h",
"source_buffer_metrics.cc",
@@ -382,6 +388,7 @@
"local_storage_database_test.cc",
"location_test.cc",
"media_query_list_test.cc",
+ "media_source_settings_test.cc",
"mutation_observer_test.cc",
"named_node_map_test.cc",
"navigator_licenses_test.cc",
diff --git a/cobalt/dom/document.cc b/cobalt/dom/document.cc
index 22323c1..4e665a5 100644
--- a/cobalt/dom/document.cc
+++ b/cobalt/dom/document.cc
@@ -60,8 +60,6 @@
#include "cobalt/dom/wheel_event.h"
#include "cobalt/dom/window.h"
#include "cobalt/script/global_environment.h"
-#include "cobalt/web/csp_delegate.h"
-#include "cobalt/web/csp_delegate_factory.h"
#include "cobalt/web/custom_event.h"
#include "cobalt/web/dom_exception.h"
#include "cobalt/web/message_event.h"
@@ -71,6 +69,17 @@
namespace cobalt {
namespace dom {
+namespace {
+csp::SecurityCallback CreateSecurityCallback(
+ web::CspDelegate* csp_delegate, web::CspDelegate::ResourceType type) {
+ csp::SecurityCallback callback;
+ if (csp_delegate) {
+ callback = base::Bind(&web::CspDelegate::CanLoad,
+ base::Unretained(csp_delegate), type);
+ }
+ return callback;
+}
+} // namespace
Document::Document(HTMLElementContext* html_element_context,
const Options& options)
@@ -113,20 +122,11 @@
SetViewport(*options.viewport_size);
}
- std::unique_ptr<web::CspViolationReporter> violation_reporter(
- new web::CspViolationReporter(this, options.post_sender));
- csp_delegate_ = web::CspDelegateFactory::GetInstance()->Create(
- options.csp_enforcement_mode, std::move(violation_reporter), options.url,
- options.require_csp, options.csp_policy_changed_callback,
- options.csp_insecure_allowed_token);
-
cookie_jar_ = options.cookie_jar;
location_ = new Location(
options.url, options.hashchange_callback, options.navigation_callback,
- base::Bind(&web::CspDelegate::CanLoad,
- base::Unretained(csp_delegate_.get()),
- web::CspDelegate::kLocation),
+ CreateSecurityCallback(csp_delegate(), web::CspDelegate::kLocation),
base::Bind(&Document::SetNavigationType, base::Unretained(this)));
font_cache_.reset(new FontCache(
@@ -138,15 +138,11 @@
if (HasBrowsingContext()) {
if (html_element_context_->remote_typeface_cache()) {
html_element_context_->remote_typeface_cache()->set_security_callback(
- base::Bind(&web::CspDelegate::CanLoad,
- base::Unretained(csp_delegate_.get()),
- web::CspDelegate::kFont));
+ CreateSecurityCallback(csp_delegate(), web::CspDelegate::kFont));
}
-
if (html_element_context_->image_cache()) {
- html_element_context_->image_cache()->set_security_callback(base::Bind(
- &web::CspDelegate::CanLoad, base::Unretained(csp_delegate_.get()),
- web::CspDelegate::kImage));
+ html_element_context_->image_cache()->set_security_callback(
+ CreateSecurityCallback(csp_delegate(), web::CspDelegate::kImage));
}
ready_state_ = kDocumentReadyStateLoading;
@@ -640,7 +636,7 @@
void Document::NotifyUrlChanged(const GURL& url) {
location_->set_url(url);
- csp_delegate_->NotifyUrlChanged(url);
+ csp_delegate()->NotifyUrlChanged(url);
}
void Document::OnFocusChange() {
diff --git a/cobalt/dom/document.h b/cobalt/dom/document.h
index b50a8d9..2fc0246 100644
--- a/cobalt/dom/document.h
+++ b/cobalt/dom/document.h
@@ -55,8 +55,6 @@
#include "cobalt/network_bridge/net_poster.h"
#include "cobalt/script/exception_state.h"
#include "cobalt/script/wrappable.h"
-#include "cobalt/web/csp_delegate.h"
-#include "cobalt/web/csp_delegate_type.h"
#include "cobalt/web/event.h"
#include "starboard/time.h"
#include "url/gurl.h"
@@ -105,15 +103,9 @@
public ApplicationLifecycleState::Observer {
public:
struct Options {
- Options()
- : window(NULL),
- cookie_jar(NULL),
- csp_enforcement_mode(web::kCspEnforcementEnable) {}
+ Options() : window(NULL), cookie_jar(NULL) {}
explicit Options(const GURL& url_value)
- : url(url_value),
- window(NULL),
- cookie_jar(NULL),
- csp_enforcement_mode(web::kCspEnforcementEnable) {}
+ : url(url_value), window(NULL), cookie_jar(NULL) {}
Options(const GURL& url_value, Window* window,
const base::Closure& hashchange_callback,
const scoped_refptr<base::BasicClock>& navigation_start_clock_value,
@@ -121,11 +113,7 @@
const scoped_refptr<cssom::CSSStyleSheet> user_agent_style_sheet,
const base::Optional<cssom::ViewportSize>& viewport_size,
network_bridge::CookieJar* cookie_jar,
- const network_bridge::PostSender& post_sender,
- csp::CSPHeaderPolicy require_csp,
- web::CspEnforcementType csp_enforcement_mode,
- const base::Closure& csp_policy_changed_callback,
- int csp_insecure_allowed_token = 0, int dom_max_element_depth = 0)
+ int dom_max_element_depth = 0)
: url(url_value),
window(window),
hashchange_callback(hashchange_callback),
@@ -134,11 +122,6 @@
user_agent_style_sheet(user_agent_style_sheet),
viewport_size(viewport_size),
cookie_jar(cookie_jar),
- post_sender(post_sender),
- require_csp(require_csp),
- csp_enforcement_mode(csp_enforcement_mode),
- csp_policy_changed_callback(csp_policy_changed_callback),
- csp_insecure_allowed_token(csp_insecure_allowed_token),
dom_max_element_depth(dom_max_element_depth) {}
GURL url;
@@ -149,11 +132,6 @@
scoped_refptr<cssom::CSSStyleSheet> user_agent_style_sheet;
base::Optional<cssom::ViewportSize> viewport_size;
network_bridge::CookieJar* cookie_jar;
- network_bridge::PostSender post_sender;
- csp::CSPHeaderPolicy require_csp;
- web::CspEnforcementType csp_enforcement_mode;
- base::Closure csp_policy_changed_callback;
- int csp_insecure_allowed_token;
int dom_max_element_depth;
};
@@ -386,7 +364,13 @@
return navigation_start_clock_;
}
- web::CspDelegate* csp_delegate() const { return csp_delegate_.get(); }
+ // Virtual for testing.
+ virtual web::CspDelegate* csp_delegate() const {
+ if (window_) {
+ return window_->csp_delegate();
+ }
+ return nullptr;
+ }
// Triggers a synchronous layout.
scoped_refptr<render_tree::Node> DoSynchronousLayoutAndGetRenderTree();
@@ -594,8 +578,6 @@
// Viewport size.
base::Optional<cssom::ViewportSize> viewport_size_;
- // Content Security Policy enforcement for this document.
- std::unique_ptr<web::CspDelegate> csp_delegate_;
network_bridge::CookieJar* cookie_jar_;
// Associated location object.
scoped_refptr<Location> location_;
diff --git a/cobalt/dom/document_test.cc b/cobalt/dom/document_test.cc
index 434fc9b..8909802 100644
--- a/cobalt/dom/document_test.cc
+++ b/cobalt/dom/document_test.cc
@@ -34,6 +34,7 @@
#include "cobalt/dom/location.h"
#include "cobalt/dom/mouse_event.h"
#include "cobalt/dom/node_list.h"
+#include "cobalt/dom/testing/fake_document.h"
#include "cobalt/dom/testing/html_collection_testing.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
#include "cobalt/dom/text.h"
@@ -90,26 +91,30 @@
//////////////////////////////////////////////////////////////////////////
TEST_F(DocumentTest, Create) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
ASSERT_TRUE(document);
EXPECT_EQ(Node::kDocumentNode, document->node_type());
EXPECT_EQ("#document", document->node_name());
GURL url("http://a valid url");
- document = new Document(&html_element_context_, Document::Options(url));
+ document =
+ new testing::FakeDocument(&html_element_context_, Document::Options(url));
EXPECT_EQ(url.spec(), document->url());
EXPECT_EQ(url.spec(), document->document_uri());
EXPECT_EQ(url, document->url_as_gurl());
}
TEST_F(DocumentTest, IsNotXMLDocument) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
EXPECT_FALSE(document->IsXMLDocument());
}
TEST_F(DocumentTest, DocumentElement) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
EXPECT_EQ(NULL, document->document_element().get());
scoped_refptr<Text> text = new Text(document, "test_text");
@@ -121,7 +126,8 @@
}
TEST_F(DocumentTest, CreateElement) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
scoped_refptr<Element> element = document->CreateElement("element");
EXPECT_EQ(Node::kElementNode, element->node_type());
@@ -137,7 +143,8 @@
}
TEST_F(DocumentTest, CreateTextNode) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
scoped_refptr<Text> text = document->CreateTextNode("test_text");
EXPECT_EQ(Node::kTextNode, text->node_type());
@@ -147,7 +154,8 @@
}
TEST_F(DocumentTest, CreateComment) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
scoped_refptr<Comment> comment = document->CreateComment("test_comment");
EXPECT_EQ(Node::kCommentNode, comment->node_type());
@@ -159,7 +167,8 @@
TEST_F(DocumentTest, CreateEventEvent) {
StrictMock<MockExceptionState> exception_state;
scoped_refptr<script::ScriptException> exception;
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
// Create an Event, the name is case insensitive.
scoped_refptr<web::Event> event =
@@ -183,7 +192,8 @@
TEST_F(DocumentTest, CreateEventCustomEvent) {
StrictMock<MockExceptionState> exception_state;
scoped_refptr<script::ScriptException> exception;
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
// Create an Event, the name is case insensitive.
scoped_refptr<web::Event> event =
@@ -196,7 +206,8 @@
TEST_F(DocumentTest, CreateEventUIEvent) {
StrictMock<MockExceptionState> exception_state;
scoped_refptr<script::ScriptException> exception;
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
// Create an Event, the name is case insensitive.
scoped_refptr<web::Event> event =
@@ -214,7 +225,8 @@
TEST_F(DocumentTest, CreateEventKeyboardEvent) {
StrictMock<MockExceptionState> exception_state;
scoped_refptr<script::ScriptException> exception;
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
// Create an Event, the name is case insensitive.
scoped_refptr<web::Event> event =
@@ -232,7 +244,8 @@
TEST_F(DocumentTest, CreateEventMessageEvent) {
StrictMock<MockExceptionState> exception_state;
scoped_refptr<script::ScriptException> exception;
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
// Create an Event, the name is case insensitive.
scoped_refptr<web::Event> event =
@@ -245,7 +258,8 @@
TEST_F(DocumentTest, CreateEventMouseEvent) {
StrictMock<MockExceptionState> exception_state;
scoped_refptr<script::ScriptException> exception;
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
// Create an Event, the name is case insensitive.
scoped_refptr<web::Event> event =
@@ -263,7 +277,8 @@
TEST_F(DocumentTest, CreateEventEventNotSupported) {
StrictMock<MockExceptionState> exception_state;
scoped_refptr<script::ScriptException> exception;
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
EXPECT_CALL(exception_state, SetException(_))
.WillOnce(SaveArg<0>(&exception));
@@ -278,17 +293,20 @@
}
TEST_F(DocumentTest, GetElementsByClassName) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
testing::TestGetElementsByClassName(document);
}
TEST_F(DocumentTest, GetElementsByTagName) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
testing::TestGetElementsByTagName(document);
}
TEST_F(DocumentTest, GetElementById) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
// Construct a tree:
// document
@@ -321,17 +339,20 @@
}
TEST_F(DocumentTest, Implementation) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
EXPECT_TRUE(document->implementation());
}
TEST_F(DocumentTest, Location) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
EXPECT_TRUE(document->location());
}
TEST_F(DocumentTest, StyleSheets) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
scoped_refptr<HTMLElement> element1 =
html_element_context_.html_element_factory()->CreateHTMLElement(
@@ -376,7 +397,8 @@
}
TEST_F(DocumentTest, StyleSheetsAddedToFront) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
scoped_refptr<HTMLElement> element1 =
html_element_context_.html_element_factory()->CreateHTMLElement(
@@ -421,7 +443,8 @@
}
TEST_F(DocumentTest, HtmlElement) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
EXPECT_FALSE(document->html());
scoped_refptr<Node> div =
@@ -435,7 +458,8 @@
}
TEST_F(DocumentTest, HeadElement) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
EXPECT_FALSE(document->head());
scoped_refptr<Node> html =
@@ -453,7 +477,8 @@
}
TEST_F(DocumentTest, BodyElement) {
- scoped_refptr<Document> document = new Document(&html_element_context_);
+ scoped_refptr<Document> document =
+ new testing::FakeDocument(&html_element_context_);
EXPECT_FALSE(document->body());
scoped_refptr<Node> html =
diff --git a/cobalt/dom/dom_settings.cc b/cobalt/dom/dom_settings.cc
index 6c9e66d..d07474b 100644
--- a/cobalt/dom/dom_settings.cc
+++ b/cobalt/dom/dom_settings.cc
@@ -28,6 +28,7 @@
DOMSettings::DOMSettings(
const base::DebuggerHooks& debugger_hooks, const int max_dom_element_depth,
MediaSourceRegistry* media_source_registry,
+ const MediaSourceSettings* media_source_settings,
media::CanPlayTypeHandler* can_play_type_handler,
const media::DecoderBufferMemoryInfo* decoder_buffer_memory_info,
MutationObserverTaskManager* mutation_observer_task_manager,
@@ -36,6 +37,7 @@
max_dom_element_depth_(max_dom_element_depth),
microphone_options_(options.microphone_options),
media_source_registry_(media_source_registry),
+ media_source_settings_(media_source_settings),
can_play_type_handler_(can_play_type_handler),
decoder_buffer_memory_info_(decoder_buffer_memory_info),
mutation_observer_task_manager_(mutation_observer_task_manager) {}
diff --git a/cobalt/dom/dom_settings.h b/cobalt/dom/dom_settings.h
index 8eb437a..33a5c0a 100644
--- a/cobalt/dom/dom_settings.h
+++ b/cobalt/dom/dom_settings.h
@@ -15,8 +15,10 @@
#ifndef COBALT_DOM_DOM_SETTINGS_H_
#define COBALT_DOM_DOM_SETTINGS_H_
+#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "cobalt/base/debugger_hooks.h"
+#include "cobalt/dom/media_source_settings.h"
#include "cobalt/dom/mutation_observer_task_manager.h"
#include "cobalt/media/can_play_type_handler.h"
#include "cobalt/media/decoder_buffer_memory_info.h"
@@ -55,6 +57,7 @@
DOMSettings(const base::DebuggerHooks& debugger_hooks,
const int max_dom_element_depth,
MediaSourceRegistry* media_source_registry,
+ const MediaSourceSettings* media_source_settings,
media::CanPlayTypeHandler* can_play_type_handler,
const media::DecoderBufferMemoryInfo* decoder_buffer_memory_info,
MutationObserverTaskManager* mutation_observer_task_manager,
@@ -71,6 +74,9 @@
MediaSourceRegistry* media_source_registry() const {
return media_source_registry_;
}
+ const MediaSourceSettings* media_source_settings() const {
+ return media_source_settings_;
+ }
void set_decoder_buffer_memory_info(
const media::DecoderBufferMemoryInfo* decoder_buffer_memory_info) {
decoder_buffer_memory_info_ = decoder_buffer_memory_info;
@@ -96,6 +102,7 @@
const int max_dom_element_depth_;
const speech::Microphone::Options microphone_options_;
MediaSourceRegistry* media_source_registry_;
+ const MediaSourceSettings* media_source_settings_;
media::CanPlayTypeHandler* can_play_type_handler_;
const media::DecoderBufferMemoryInfo* decoder_buffer_memory_info_;
MutationObserverTaskManager* mutation_observer_task_manager_;
diff --git a/cobalt/dom/element_test.cc b/cobalt/dom/element_test.cc
index 0128e48..bfdd04d 100644
--- a/cobalt/dom/element_test.cc
+++ b/cobalt/dom/element_test.cc
@@ -31,6 +31,7 @@
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/named_node_map.h"
#include "cobalt/dom/node_list.h"
+#include "cobalt/dom/testing/fake_document.h"
#include "cobalt/dom/testing/html_collection_testing.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
#include "cobalt/dom/text.h"
@@ -70,7 +71,7 @@
NULL, dom_stat_tracker_.get(), "",
base::kApplicationStateStarted, NULL, NULL) {
EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks());
- document_ = new Document(&html_element_context_);
+ document_ = new testing::FakeDocument(&html_element_context_);
xml_document_ = new XMLDocument(&html_element_context_);
}
diff --git a/cobalt/dom/event_queue.cc b/cobalt/dom/event_queue.cc
index 1bd5282..ca851e8 100644
--- a/cobalt/dom/event_queue.cc
+++ b/cobalt/dom/event_queue.cc
@@ -44,6 +44,23 @@
events_.push_back(event);
}
+void EventQueue::EnqueueAndMaybeDispatchImmediately(
+ const scoped_refptr<web::Event>& event) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+
+ bool was_empty = events_.empty();
+
+ Enqueue(event);
+
+ if (was_empty) {
+ // We can only dispatch the event immediately if there aren't any existing
+ // events in the queue, because dom activities (including events) have to
+ // happen in order, and any existing events in the queue may mean that these
+ // events have to be dispatched after other activities not tracked here.
+ DispatchEvents();
+ }
+}
+
void EventQueue::CancelAllEvents() {
DCHECK(message_loop_->BelongsToCurrentThread());
diff --git a/cobalt/dom/event_queue.h b/cobalt/dom/event_queue.h
index 624bd8e..6aad863 100644
--- a/cobalt/dom/event_queue.h
+++ b/cobalt/dom/event_queue.h
@@ -42,7 +42,13 @@
// The EventTarget is guaranteed to be valid during the life time and should
// usually be the owner.
explicit EventQueue(web::EventTarget* event_target);
+
void Enqueue(const scoped_refptr<web::Event>& event);
+ // Try to dispatch the event immediately if there are no existing events in
+ // the queue, otherwise it has the same behavior as Enqueue(), which enqueues
+ // the event and the event will be dispatched after the existing events.
+ void EnqueueAndMaybeDispatchImmediately(
+ const scoped_refptr<web::Event>& event);
void CancelAllEvents();
void TraceMembers(script::Tracer* tracer) override;
diff --git a/cobalt/dom/event_queue_test.cc b/cobalt/dom/event_queue_test.cc
index e8fc35f..be4a970 100644
--- a/cobalt/dom/event_queue_test.cc
+++ b/cobalt/dom/event_queue_test.cc
@@ -90,6 +90,42 @@
base::RunLoop().RunUntilIdle();
}
+TEST_F(EventQueueTest, EnqueueAndMaybeDispatchImmediatelyTest) {
+ scoped_refptr<web::EventTarget> event_target =
+ new web::EventTarget(&environment_settings_);
+ scoped_refptr<web::Event> event = new web::Event(base::Token("event"));
+ std::unique_ptr<MockEventListener> event_listener =
+ MockEventListener::Create();
+ EventQueue event_queue(event_target.get());
+
+ event->set_target(event_target);
+ event_target->AddEventListener(
+ "event", FakeScriptValue<web::EventListener>(event_listener.get()),
+ false);
+
+ {
+ ::testing::InSequence s;
+ ExpectHandleEventCallWithEventAndTarget(event_listener.get(), event,
+ event_target);
+ // The event should be dispatched immediately as the queue is empty, so the
+ // expectation should be set before being enqueued.
+ event_queue.EnqueueAndMaybeDispatchImmediately(event);
+ }
+
+ {
+ ::testing::InSequence s;
+ event_queue.Enqueue(event);
+ // The event won't be dispatched immediately as the queue isn't empty, so
+ // the expectations can be set after being enqueued.
+ event_queue.EnqueueAndMaybeDispatchImmediately(event);
+ ExpectHandleEventCallWithEventAndTarget(event_listener.get(), event,
+ event_target);
+ ExpectHandleEventCallWithEventAndTarget(event_listener.get(), event,
+ event_target);
+ base::RunLoop().RunUntilIdle();
+ }
+}
+
TEST_F(EventQueueTest, CancelAllEventsTest) {
scoped_refptr<web::EventTarget> event_target =
new web::EventTarget(&environment_settings_);
diff --git a/cobalt/dom/html_element_test.cc b/cobalt/dom/html_element_test.cc
index e8936f9..9426a09 100644
--- a/cobalt/dom/html_element_test.cc
+++ b/cobalt/dom/html_element_test.cc
@@ -31,6 +31,7 @@
#include "cobalt/dom/html_div_element.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/named_node_map.h"
+#include "cobalt/dom/testing/fake_document.h"
#include "cobalt/dom/testing/mock_layout_boxes.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
#include "cobalt/dom/testing/stub_window.h"
@@ -86,7 +87,7 @@
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, dom_stat_tracker_.get(),
"", base::kApplicationStateStarted, NULL, NULL),
- document_(new Document(&html_element_context_)) {}
+ document_(new testing::FakeDocument(&html_element_context_)) {}
~HTMLElementTest() override {}
// This creates simple DOM tree with mock layout boxes for all elements except
diff --git a/cobalt/dom/media_source.cc b/cobalt/dom/media_source.cc
index 290996f..f9f2c05 100644
--- a/cobalt/dom/media_source.cc
+++ b/cobalt/dom/media_source.cc
@@ -52,7 +52,9 @@
#include "base/compiler_specific.h"
#include "base/guid.h"
#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/base/tokens.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/web/dom_exception.h"
@@ -63,19 +65,80 @@
namespace cobalt {
namespace dom {
+namespace {
+
using ::media::CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR;
using ::media::CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR;
using ::media::PIPELINE_OK;
using ::media::PipelineStatus;
+auto GetMediaSettings(script::EnvironmentSettings* settings) {
+ DOMSettings* dom_settings =
+ base::polymorphic_downcast<DOMSettings*>(settings);
+ DCHECK(dom_settings);
+ DCHECK(dom_settings->media_source_settings());
+ return dom_settings->media_source_settings();
+}
+
+// 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.
+bool IsAlgorithmOffloadEnabled(script::EnvironmentSettings* settings) {
+ int min_process_count_to_offload =
+ GetMediaSettings(settings)
+ ->GetMinimumProcessorCountToOffloadAlgorithm()
+ .value_or(2);
+ DCHECK_GE(min_process_count_to_offload, 0);
+ return SbSystemGetNumberOfProcessors() >= min_process_count_to_offload;
+}
+
+// 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.
+bool IsAsynchronousReductionEnabled(script::EnvironmentSettings* settings) {
+ return GetMediaSettings(settings)->IsAsynchronousReductionEnabled().value_or(
+ true);
+}
+
+// If the size of a job that is part of an algorithm is less than or equal to
+// the return value of this function, the implementation will run the job
+// immediately instead of scheduling it to run later to reduce latency.
+// NOTE: This only works when IsAsynchronousReductionEnabled() returns true,
+// and it is currently only enabled for buffer append.
+// The default value is 16 KB. Set to 0 will disable immediate job completely.
+int GetMinSizeForImmediateJob(script::EnvironmentSettings* settings) {
+ const int kDefaultMinSize = 16 * 1024;
+ auto min_size =
+ GetMediaSettings(settings)->GetMinSizeForImmediateJob().value_or(
+ kDefaultMinSize);
+ DCHECK_GE(min_size, 0);
+ return min_size;
+}
+
+} // namespace
+
MediaSource::MediaSource(script::EnvironmentSettings* settings)
: web::EventTarget(settings),
+ algorithm_offload_enabled_(IsAlgorithmOffloadEnabled(settings)),
+ asynchronous_reduction_enabled_(IsAsynchronousReductionEnabled(settings)),
+ min_size_for_immediate_job_(GetMinSizeForImmediateJob(settings)),
+ default_algorithm_runner_(asynchronous_reduction_enabled_),
chunk_demuxer_(NULL),
ready_state_(kMediaSourceReadyStateClosed),
ALLOW_THIS_IN_INITIALIZER_LIST(event_queue_(this)),
source_buffers_(new SourceBufferList(settings, &event_queue_)),
active_source_buffers_(new SourceBufferList(settings, &event_queue_)),
- live_seekable_range_(new TimeRanges) {}
+ live_seekable_range_(new TimeRanges) {
+ LOG(INFO) << "Algorithm offloading is "
+ << (algorithm_offload_enabled_ ? "enabled" : "disabled");
+ LOG(INFO) << "Asynchronous reduction is "
+ << (asynchronous_reduction_enabled_ ? "enabled" : "disabled");
+ LOG(INFO) << "Min size of immediate job is set to "
+ << min_size_for_immediate_job_;
+}
MediaSource::~MediaSource() { SetReadyState(kMediaSourceReadyStateClosed); }
@@ -179,8 +242,9 @@
ChunkDemuxer::Status status = chunk_demuxer_->AddId(guid, type);
switch (status) {
case ChunkDemuxer::kOk:
- source_buffer =
- new SourceBuffer(settings, guid, this, chunk_demuxer_, &event_queue_);
+ source_buffer = new SourceBuffer(settings, guid, this,
+ asynchronous_reduction_enabled_,
+ chunk_demuxer_, &event_queue_);
break;
case ChunkDemuxer::kNotSupported:
web::DOMException::Raise(web::DOMException::kNotSupportedErr,
@@ -310,8 +374,28 @@
}
DCHECK(IsClosed());
+ DCHECK(!algorithm_process_thread_);
+
attached_element_ = base::AsWeakPtr(media_element);
has_max_video_capabilities_ = media_element->HasMaxVideoCapabilities();
+
+ if (algorithm_offload_enabled_) {
+ algorithm_process_thread_.reset(new base::Thread("MSEAlgorithm"));
+ if (!algorithm_process_thread_->Start()) {
+ LOG(WARNING) << "Starting algorithm process thread failed, disable"
+ " algorithm offloading";
+ algorithm_process_thread_.reset();
+ }
+ }
+
+ 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()));
+ } else {
+ LOG(INFO) << "Algorithm offloading disabled.";
+ }
return true;
}
@@ -490,6 +574,18 @@
return has_max_video_capabilities_;
}
+SerializedAlgorithmRunner* MediaSource::GetAlgorithmRunner(int job_size) {
+ if (!offload_algorithm_runner_) {
+ return &default_algorithm_runner_;
+ }
+ if (asynchronous_reduction_enabled_ &&
+ job_size <= min_size_for_immediate_job_) {
+ // Append without posting new tasks is only supported on the default runner.
+ return &default_algorithm_runner_;
+ }
+ return offload_algorithm_runner_.get();
+}
+
void MediaSource::TraceMembers(script::Tracer* tracer) {
web::EventTarget::TraceMembers(tracer);
@@ -536,6 +632,12 @@
attached_element_.reset();
ScheduleEvent(base::Tokens::sourceclose());
+
+ if (algorithm_process_thread_) {
+ algorithm_process_thread_->Stop();
+ algorithm_process_thread_.reset();
+ }
+ offload_algorithm_runner_.reset();
}
bool MediaSource::IsUpdating() const {
diff --git a/cobalt/dom/media_source.h b/cobalt/dom/media_source.h
index de7bccb..bfe0774 100644
--- a/cobalt/dom/media_source.h
+++ b/cobalt/dom/media_source.h
@@ -45,16 +45,19 @@
#ifndef COBALT_DOM_MEDIA_SOURCE_H_
#define COBALT_DOM_MEDIA_SOURCE_H_
+#include <memory>
#include <string>
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/threading/thread.h"
#include "cobalt/base/token.h"
#include "cobalt/dom/audio_track.h"
#include "cobalt/dom/event_queue.h"
#include "cobalt/dom/html_media_element.h"
#include "cobalt/dom/media_source_end_of_stream_error.h"
#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_list.h"
#include "cobalt/dom/time_ranges.h"
@@ -123,6 +126,7 @@
void SetSourceBufferActive(SourceBuffer* source_buffer, bool is_active);
HTMLMediaElement* GetMediaElement() const;
bool MediaElementHasMaxVideoCapabilities() const;
+ SerializedAlgorithmRunner* GetAlgorithmRunner(int job_size);
DEFINE_WRAPPABLE_TYPE(MediaSource);
void TraceMembers(script::Tracer* tracer) override;
@@ -132,6 +136,23 @@
bool IsUpdating() const;
void ScheduleEvent(base::Token event_name);
+ // Set to true to offload SourceBuffer buffer append and removal algorithms to
+ // a non-web thread.
+ const bool algorithm_offload_enabled_;
+ // Set to true to reduce asynchronous behaviors. For example, queued events
+ // will be dispatached immediately when possible.
+ const bool asynchronous_reduction_enabled_;
+ // Only used when |asynchronous_reduction_enabled_| is set true, where any
+ // buffer append job smaller than its value will happen immediately instead of
+ // being scheduled asynchronously.
+ const int min_size_for_immediate_job_;
+
+ // The default algorithm runner runs all steps on the web thread.
+ DefaultAlgorithmRunner 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<base::Thread> algorithm_process_thread_;
+
ChunkDemuxer* chunk_demuxer_;
MediaSourceReadyState ready_state_;
EventQueue event_queue_;
diff --git a/cobalt/dom/media_source_settings.cc b/cobalt/dom/media_source_settings.cc
new file mode 100644
index 0000000..a330f83
--- /dev/null
+++ b/cobalt/dom/media_source_settings.cc
@@ -0,0 +1,64 @@
+// 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/media_source_settings.h"
+
+#include <cstring>
+
+#include "base/logging.h"
+
+namespace cobalt {
+namespace dom {
+
+bool MediaSourceSettingsImpl::Set(const std::string& name, int value) {
+ const char kPrefix[] = "MediaSource.";
+ if (name.compare(0, strlen(kPrefix), kPrefix) != 0) {
+ return false;
+ }
+
+ base::AutoLock auto_lock(lock_);
+ if (name == "MediaSource.SourceBufferEvictExtraInBytes") {
+ if (value >= 0) {
+ source_buffer_evict_extra_in_bytes_ = value;
+ LOG(INFO) << name << ": set to " << value;
+ return true;
+ }
+ } else if (name == "MediaSource.MinimumProcessorCountToOffloadAlgorithm") {
+ if (value >= 0) {
+ minimum_processor_count_to_offload_algorithm_ = value;
+ LOG(INFO) << name << ": set to " << value;
+ return true;
+ }
+ } else if (name == "MediaSource.EnableAsynchronousReduction") {
+ if (value == 0 || value == 1) {
+ is_asynchronous_reduction_enabled_ = value != 0;
+ LOG(INFO) << name << ": set to " << value;
+ return true;
+ }
+ } else if (name == "MediaSource.MinSizeForImmediateJob") {
+ if (value >= 0) {
+ min_size_for_immediate_job_ = value;
+ LOG(INFO) << name << ": set to " << value;
+ return true;
+ }
+ } else {
+ LOG(WARNING) << "Ignore unknown setting with name \"" << name << "\"";
+ return false;
+ }
+ LOG(WARNING) << name << ": ignore invalid value " << value;
+ return false;
+}
+
+} // namespace dom
+} // namespace cobalt
diff --git a/cobalt/dom/media_source_settings.h b/cobalt/dom/media_source_settings.h
new file mode 100644
index 0000000..8d1b0be
--- /dev/null
+++ b/cobalt/dom/media_source_settings.h
@@ -0,0 +1,87 @@
+// 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_DOM_MEDIA_SOURCE_SETTINGS_H_
+#define COBALT_DOM_MEDIA_SOURCE_SETTINGS_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "base/synchronization/lock.h"
+
+namespace cobalt {
+namespace dom {
+
+// Holds WebModule wide settings for MediaSource related objects. Their default
+// values are set in MediaSource related implementations, and the default values
+// will be overridden if the return values of the member functions are
+// non-empty.
+// Please refer to where these functions are called for the particular
+// MediaSource behaviors being controlled by them.
+class MediaSourceSettings {
+ public:
+ virtual base::Optional<int> GetSourceBufferEvictExtraInBytes() const = 0;
+ virtual base::Optional<int> GetMinimumProcessorCountToOffloadAlgorithm()
+ const = 0;
+ virtual base::Optional<bool> IsAsynchronousReductionEnabled() const = 0;
+ virtual base::Optional<int> GetMinSizeForImmediateJob() const = 0;
+
+ protected:
+ MediaSourceSettings() = default;
+ ~MediaSourceSettings() = default;
+
+ MediaSourceSettings(const MediaSourceSettings&) = delete;
+ MediaSourceSettings& operator=(const MediaSourceSettings&) = delete;
+};
+
+// Allows setting the values of MediaSource settings via a name and an int
+// value.
+// This class is thread safe.
+class MediaSourceSettingsImpl : public MediaSourceSettings {
+ public:
+ base::Optional<int> GetSourceBufferEvictExtraInBytes() const override {
+ base::AutoLock auto_lock(lock_);
+ return source_buffer_evict_extra_in_bytes_;
+ }
+ base::Optional<int> GetMinimumProcessorCountToOffloadAlgorithm()
+ const override {
+ base::AutoLock auto_lock(lock_);
+ return minimum_processor_count_to_offload_algorithm_;
+ }
+ base::Optional<bool> IsAsynchronousReductionEnabled() const override {
+ base::AutoLock auto_lock(lock_);
+ return is_asynchronous_reduction_enabled_;
+ }
+ base::Optional<int> GetMinSizeForImmediateJob() const override {
+ base::AutoLock auto_lock(lock_);
+ return min_size_for_immediate_job_;
+ }
+
+ // Returns true when the setting associated with `name` is set to `value`.
+ // Returns false when `name` is not associated with any settings, or if
+ // `value` contains an invalid value.
+ bool Set(const std::string& name, int value);
+
+ private:
+ mutable base::Lock lock_;
+ base::Optional<int> source_buffer_evict_extra_in_bytes_;
+ base::Optional<int> minimum_processor_count_to_offload_algorithm_;
+ base::Optional<bool> is_asynchronous_reduction_enabled_;
+ base::Optional<int> min_size_for_immediate_job_;
+};
+
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_MEDIA_SOURCE_SETTINGS_H_
diff --git a/cobalt/dom/media_source_settings_test.cc b/cobalt/dom/media_source_settings_test.cc
new file mode 100644
index 0000000..27d9e9e
--- /dev/null
+++ b/cobalt/dom/media_source_settings_test.cc
@@ -0,0 +1,107 @@
+// 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/media_source_settings.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cobalt {
+namespace dom {
+namespace {
+
+TEST(MediaSourceSettingsImplTest, Empty) {
+ MediaSourceSettingsImpl impl;
+
+ EXPECT_FALSE(impl.GetSourceBufferEvictExtraInBytes());
+ EXPECT_FALSE(impl.GetMinimumProcessorCountToOffloadAlgorithm());
+ EXPECT_FALSE(impl.IsAsynchronousReductionEnabled());
+ EXPECT_FALSE(impl.GetMinSizeForImmediateJob());
+}
+
+TEST(MediaSourceSettingsImplTest, SunnyDay) {
+ MediaSourceSettingsImpl impl;
+
+ ASSERT_TRUE(impl.Set("MediaSource.SourceBufferEvictExtraInBytes", 100));
+ ASSERT_TRUE(
+ impl.Set("MediaSource.MinimumProcessorCountToOffloadAlgorithm", 101));
+ ASSERT_TRUE(impl.Set("MediaSource.EnableAsynchronousReduction", 1));
+ ASSERT_TRUE(impl.Set("MediaSource.MinSizeForImmediateJob", 103));
+
+ EXPECT_EQ(impl.GetSourceBufferEvictExtraInBytes().value(), 100);
+ EXPECT_EQ(impl.GetMinimumProcessorCountToOffloadAlgorithm().value(), 101);
+ EXPECT_TRUE(impl.IsAsynchronousReductionEnabled().value());
+ EXPECT_EQ(impl.GetMinSizeForImmediateJob().value(), 103);
+}
+
+TEST(MediaSourceSettingsImplTest, RainyDay) {
+ MediaSourceSettingsImpl impl;
+
+ ASSERT_FALSE(impl.Set("MediaSource.SourceBufferEvictExtraInBytes", -100));
+ ASSERT_FALSE(
+ impl.Set("MediaSource.MinimumProcessorCountToOffloadAlgorithm", -101));
+ ASSERT_FALSE(impl.Set("MediaSource.EnableAsynchronousReduction", 2));
+ ASSERT_FALSE(impl.Set("MediaSource.MinSizeForImmediateJob", -103));
+
+ EXPECT_FALSE(impl.GetSourceBufferEvictExtraInBytes());
+ EXPECT_FALSE(impl.GetMinimumProcessorCountToOffloadAlgorithm());
+ EXPECT_FALSE(impl.IsAsynchronousReductionEnabled());
+ EXPECT_FALSE(impl.GetMinSizeForImmediateJob());
+}
+
+TEST(MediaSourceSettingsImplTest, ZeroValuesWork) {
+ MediaSourceSettingsImpl impl;
+
+ ASSERT_TRUE(impl.Set("MediaSource.SourceBufferEvictExtraInBytes", 0));
+ ASSERT_TRUE(
+ impl.Set("MediaSource.MinimumProcessorCountToOffloadAlgorithm", 0));
+ ASSERT_TRUE(impl.Set("MediaSource.EnableAsynchronousReduction", 0));
+ ASSERT_TRUE(impl.Set("MediaSource.MinSizeForImmediateJob", 0));
+
+ EXPECT_EQ(impl.GetSourceBufferEvictExtraInBytes().value(), 0);
+ EXPECT_EQ(impl.GetMinimumProcessorCountToOffloadAlgorithm().value(), 0);
+ EXPECT_FALSE(impl.IsAsynchronousReductionEnabled().value());
+ EXPECT_EQ(impl.GetMinSizeForImmediateJob().value(), 0);
+}
+
+TEST(MediaSourceSettingsImplTest, Updatable) {
+ MediaSourceSettingsImpl impl;
+
+ ASSERT_TRUE(impl.Set("MediaSource.SourceBufferEvictExtraInBytes", 0));
+ ASSERT_TRUE(
+ impl.Set("MediaSource.MinimumProcessorCountToOffloadAlgorithm", 0));
+ ASSERT_TRUE(impl.Set("MediaSource.EnableAsynchronousReduction", 0));
+ ASSERT_TRUE(impl.Set("MediaSource.MinSizeForImmediateJob", 0));
+
+ ASSERT_TRUE(impl.Set("MediaSource.SourceBufferEvictExtraInBytes", 1));
+ ASSERT_TRUE(
+ impl.Set("MediaSource.MinimumProcessorCountToOffloadAlgorithm", 1));
+ ASSERT_TRUE(impl.Set("MediaSource.EnableAsynchronousReduction", 1));
+ ASSERT_TRUE(impl.Set("MediaSource.MinSizeForImmediateJob", 1));
+
+ EXPECT_EQ(impl.GetSourceBufferEvictExtraInBytes().value(), 1);
+ EXPECT_EQ(impl.GetMinimumProcessorCountToOffloadAlgorithm().value(), 1);
+ EXPECT_TRUE(impl.IsAsynchronousReductionEnabled().value());
+ EXPECT_EQ(impl.GetMinSizeForImmediateJob().value(), 1);
+}
+
+TEST(MediaSourceSettingsImplTest, InvalidSettingNames) {
+ MediaSourceSettingsImpl impl;
+
+ ASSERT_FALSE(impl.Set("MediaSource.Invalid", 0));
+ ASSERT_FALSE(impl.Set("Invalid.SourceBufferEvictExtraInBytes", 0));
+}
+
+} // namespace
+} // namespace dom
+} // namespace cobalt
diff --git a/cobalt/dom/rule_matching_test.cc b/cobalt/dom/rule_matching_test.cc
index e9573e0..e11362e 100644
--- a/cobalt/dom/rule_matching_test.cc
+++ b/cobalt/dom/rule_matching_test.cc
@@ -32,6 +32,7 @@
#include "cobalt/dom/node.h"
#include "cobalt/dom/node_descendants_iterator.h"
#include "cobalt/dom/node_list.h"
+#include "cobalt/dom/testing/fake_document.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
#include "cobalt/dom/testing/stub_window.h"
#include "cobalt/dom_parser/parser.h"
@@ -58,7 +59,7 @@
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, dom_stat_tracker_.get(), "",
base::kApplicationStateStarted, NULL, NULL),
- document_(new Document(&html_element_context_)),
+ document_(new testing::FakeDocument(&html_element_context_)),
root_(document_->CreateElement("html")->AsHTMLElement()),
head_(document_->CreateElement("head")->AsHTMLElement()),
body_(document_->CreateElement("body")->AsHTMLElement()) {
diff --git a/cobalt/dom/serialized_algorithm_runner.cc b/cobalt/dom/serialized_algorithm_runner.cc
new file mode 100644
index 0000000..07dece0
--- /dev/null
+++ b/cobalt/dom/serialized_algorithm_runner.cc
@@ -0,0 +1,95 @@
+// 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
new file mode 100644
index 0000000..d4c2b39
--- /dev/null
+++ b/cobalt/dom/serialized_algorithm_runner.h
@@ -0,0 +1,206 @@
+// 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_DOM_SERIALIZED_ALGORITHM_RUNNER_H_
+#define COBALT_DOM_SERIALIZED_ALGORITHM_RUNNER_H_
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "base/trace_event/trace_event.h"
+#include "starboard/common/mutex.h"
+
+namespace cobalt {
+namespace dom {
+
+// This class defines a common interface to run algorithms, and an algorithm is
+// any class with the following methods:
+// void Process(bool* finished);
+// void Abort();
+// void Finalize();
+//
+// For example, with a class:
+// class Download {
+// void Process(bool* finished) {
+// // Download some data
+// // *finished = whether download is finished.
+// }
+// void Abort() {
+// // Cancel the download, and neither Process() nor Finalize() will be
+// // called again.
+// }
+// void Finalize() {
+// // Queue an event to notify that the download has finished.
+// }
+// };
+//
+// 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.
+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 {
+ 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();
+ SerializedAlgorithm* algorithm() const { return algorithm_.get(); }
+
+ private:
+ void Process(bool* finished) override;
+ void Finalize() override;
+
+ // The |mutex_| is necessary as `Abort()` can be called from any thread.
+ starboard::Mutex mutex_;
+ std::unique_ptr<SerializedAlgorithm> algorithm_;
+ bool aborted_ = false;
+ bool finished_ = false;
+ bool finalized_ = false;
+ };
+
+ virtual ~SerializedAlgorithmRunner() {}
+
+ virtual void Start(const scoped_refptr<HandleBase>& handle) = 0;
+};
+
+template <typename SerializedAlgorithm>
+SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Handle(
+ std::unique_ptr<SerializedAlgorithm> algorithm)
+ : algorithm_(std::move(algorithm)) {
+ DCHECK(algorithm_);
+}
+
+template <typename SerializedAlgorithm>
+void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Abort() {
+ TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Abort()");
+
+ starboard::ScopedLock scoped_lock(mutex_);
+
+ DCHECK(!aborted_); // Abort() cannot be called twice.
+
+ if (finished_) {
+ // If the algorithm has finished, just call Finalize() to treat it as
+ // finished instead of aborted.
+ if (!finalized_) {
+ algorithm_->Finalize();
+ }
+ } else {
+ algorithm_->Abort();
+ }
+
+ algorithm_.reset();
+ aborted_ = true;
+}
+
+template <typename SerializedAlgorithm>
+void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Process(
+ bool* finished) {
+ TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Process()");
+
+ DCHECK(finished);
+
+ starboard::ScopedLock scoped_lock(mutex_);
+
+ DCHECK(!finished_);
+ DCHECK(!finalized_);
+
+ if (aborted_) {
+ return;
+ }
+
+ DCHECK(algorithm_);
+ algorithm_->Process(&finished_);
+ *finished = finished_;
+}
+
+template <typename SerializedAlgorithm>
+void SerializedAlgorithmRunner::Handle<SerializedAlgorithm>::Finalize() {
+ TRACE_EVENT0("cobalt::dom", "SerializedAlgorithmRunner::Handle::Finalize()");
+ starboard::ScopedLock scoped_lock(mutex_);
+
+ DCHECK(finished_);
+ DCHECK(!finalized_);
+
+ if (aborted_) {
+ return;
+ }
+
+ DCHECK(algorithm_);
+
+ algorithm_->Finalize();
+ algorithm_.reset();
+ finalized_ = true;
+}
+
+// This class runs algorithm on the task runner associated with the thread where
+// Start() is called.
+class DefaultAlgorithmRunner : public SerializedAlgorithmRunner {
+ 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);
+
+ const bool asynchronous_reduction_enabled_;
+};
+
+// This class runs algorithms on two task runners, it can be used to offload
+// processing to another task runner.
+//
+// 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 {
+ public:
+ typedef base::SingleThreadTaskRunner TaskRunner;
+
+ OffloadAlgorithmRunner(const scoped_refptr<TaskRunner>& process_task_runner,
+ const scoped_refptr<TaskRunner>& finalize_task_runner);
+
+ private:
+ void Start(const scoped_refptr<HandleBase>& handle) override;
+ void Process(const scoped_refptr<HandleBase>& handle);
+
+ scoped_refptr<TaskRunner> process_task_runner_;
+ scoped_refptr<TaskRunner> finalize_task_runner_;
+};
+
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_SERIALIZED_ALGORITHM_RUNNER_H_
diff --git a/cobalt/dom/source_buffer.cc b/cobalt/dom/source_buffer.cc
index a8b78e9..f49d151 100644
--- a/cobalt/dom/source_buffer.cc
+++ b/cobalt/dom/source_buffer.cc
@@ -45,9 +45,12 @@
#include "cobalt/dom/source_buffer.h"
#include <algorithm>
+#include <limits>
+#include <utility>
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
@@ -84,26 +87,34 @@
return base::TimeDelta::FromSecondsD(time);
}
+// The return value will be used in `SourceBuffer::EvictCodedFrames()` to allow
+// it to evict extra data from the SourceBuffer, so it can reduce the overall
+// memory used by the underlying Demuxer implementation.
+// The default value is 0, i.e. do not evict extra bytes.
size_t GetEvictExtraInBytes(script::EnvironmentSettings* settings) {
DOMSettings* dom_settings =
base::polymorphic_downcast<DOMSettings*>(settings);
- if (dom_settings && dom_settings->decoder_buffer_memory_info()) {
- return dom_settings->decoder_buffer_memory_info()
- ->GetSourceBufferEvictExtraInBytes();
- }
- return 0;
+ DCHECK(dom_settings);
+ DCHECK(dom_settings->media_source_settings());
+ int bytes = dom_settings->media_source_settings()
+ ->GetSourceBufferEvictExtraInBytes()
+ .value_or(0);
+ DCHECK_GE(bytes, 0);
+ return std::max<int>(bytes, 0);
}
} // namespace
SourceBuffer::SourceBuffer(script::EnvironmentSettings* settings,
const std::string& id, MediaSource* media_source,
+ bool asynchronous_reduction_enabled,
ChunkDemuxer* chunk_demuxer, EventQueue* event_queue)
: web::EventTarget(settings),
id_(id),
+ asynchronous_reduction_enabled_(asynchronous_reduction_enabled),
evict_extra_in_bytes_(GetEvictExtraInBytes(settings)),
- chunk_demuxer_(chunk_demuxer),
media_source_(media_source),
+ chunk_demuxer_(chunk_demuxer),
event_queue_(event_queue),
audio_tracks_(
new AudioTrackList(settings, media_source->GetMediaElement())),
@@ -115,9 +126,11 @@
DCHECK(chunk_demuxer);
DCHECK(event_queue);
+ LOG(INFO) << "Evict extra in bytes is set to " << evict_extra_in_bytes_;
+
chunk_demuxer_->SetTracksWatcher(
id_,
- base::Bind(&SourceBuffer::InitSegmentReceived, base::Unretained(this)));
+ base::Bind(&SourceBuffer::OnInitSegmentReceived, base::Unretained(this)));
chunk_demuxer_->SetParseWarningCallback(
id, base::BindRepeating([](::media::SourceBufferParseWarning warning) {
LOG(WARNING) << "Encountered SourceBufferParseWarning "
@@ -132,7 +145,7 @@
exception_state);
return;
}
- if (updating_) {
+ if (updating()) {
web::DOMException::Raise(web::DOMException::kInvalidStateErr,
exception_state);
return;
@@ -168,6 +181,12 @@
return time_ranges;
}
+double SourceBuffer::timestamp_offset(
+ script::ExceptionState* exception_state) const {
+ starboard::ScopedLock scoped_lock(timestamp_offset_mutex_);
+ return timestamp_offset_;
+}
+
void SourceBuffer::set_timestamp_offset(
double offset, script::ExceptionState* exception_state) {
if (media_source_ == NULL) {
@@ -175,7 +194,7 @@
exception_state);
return;
}
- if (updating_) {
+ if (updating()) {
web::DOMException::Raise(web::DOMException::kInvalidStateErr,
exception_state);
return;
@@ -189,6 +208,9 @@
return;
}
+ // We don't have to acquire |timestamp_offset_mutex_|, as no algorithms are
+ // running asynchronously at this moment, which is guaranteed by the check of
+ // updating() above.
timestamp_offset_ = offset;
chunk_demuxer_->SetGroupStartTimestampIfInSequenceMode(
@@ -202,7 +224,7 @@
exception_state);
return;
}
- if (updating_) {
+ if (updating()) {
web::DOMException::Raise(web::DOMException::kInvalidStateErr,
exception_state);
return;
@@ -223,7 +245,7 @@
exception_state);
return;
}
- if (updating_) {
+ if (updating()) {
web::DOMException::Raise(web::DOMException::kInvalidStateErr,
exception_state);
return;
@@ -274,20 +296,21 @@
return;
}
- if (pending_remove_start_ != -1) {
- DCHECK(updating_);
- web::DOMException::Raise(web::DOMException::kInvalidStateErr,
- exception_state);
- return;
+ if (active_algorithm_handle_) {
+ if (!active_algorithm_handle_->algorithm()->SupportExplicitAbort()) {
+ web::DOMException::Raise(web::DOMException::kInvalidStateErr,
+ exception_state);
+ return;
+ }
+ active_algorithm_handle_->Abort();
+ active_algorithm_handle_ = nullptr;
}
- AbortIfUpdating();
-
base::TimeDelta timestamp_offset = DoubleToTimeDelta(timestamp_offset_);
chunk_demuxer_->ResetParserState(id_, DoubleToTimeDelta(append_window_start_),
DoubleToTimeDelta(append_window_end_),
×tamp_offset);
- timestamp_offset_ = timestamp_offset.InSecondsF();
+ UpdateTimestampOffset(timestamp_offset);
set_append_window_start(0, exception_state);
set_append_window_end(std::numeric_limits<double>::infinity(),
@@ -303,7 +326,7 @@
exception_state);
return;
}
- if (updating_) {
+ if (updating()) {
web::DOMException::Raise(web::DOMException::kInvalidStateErr,
exception_state);
return;
@@ -322,14 +345,25 @@
media_source_->OpenIfInEndedState();
- updating_ = true;
-
ScheduleEvent(base::Tokens::updatestart());
- pending_remove_start_ = start;
- pending_remove_end_ = end;
- remove_timer_.Start(FROM_HERE, base::TimeDelta(), this,
- &SourceBuffer::OnRemoveTimer);
+ DCHECK_GE(start, 0);
+ DCHECK_LT(start, end);
+
+ std::unique_ptr<SourceBufferAlgorithm> algorithm(
+ new SourceBufferRemoveAlgorithm(
+ chunk_demuxer_, id_, DoubleToTimeDelta(start), DoubleToTimeDelta(end),
+ base::Bind(asynchronous_reduction_enabled_
+ ? &SourceBuffer::ScheduleAndMaybeDispatchImmediately
+ : &SourceBuffer::ScheduleEvent,
+ base::Unretained(this)),
+ base::Bind(&SourceBuffer::OnAlgorithmFinalized,
+ base::Unretained(this))));
+ active_algorithm_handle_ =
+ new SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>(
+ std::move(algorithm));
+ media_source_->GetAlgorithmRunner(std::numeric_limits<int>::max())
+ ->Start(active_algorithm_handle_);
}
void SourceBuffer::set_track_defaults(
@@ -340,7 +374,7 @@
exception_state);
return;
}
- if (updating_) {
+ if (updating()) {
web::DOMException::Raise(web::DOMException::kInvalidStateErr,
exception_state);
return;
@@ -354,10 +388,9 @@
return;
}
- if (pending_remove_start_ != -1) {
- CancelRemove();
- } else {
- AbortIfUpdating();
+ if (active_algorithm_handle_) {
+ active_algorithm_handle_->Abort();
+ active_algorithm_handle_ = nullptr;
}
DCHECK(media_source_);
@@ -402,8 +435,15 @@
tracer->Trace(video_tracks_);
}
-void SourceBuffer::InitSegmentReceived(std::unique_ptr<MediaTracks> tracks) {
+void SourceBuffer::OnInitSegmentReceived(std::unique_ptr<MediaTracks> tracks) {
if (!first_initialization_segment_received_) {
+ // This can be called from non-web thread when the append is async.
+ if (!web_task_runner_->BelongsToCurrentThread()) {
+ web_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&SourceBuffer::OnInitSegmentReceived, this,
+ base::Passed(&tracks)));
+ return;
+ }
media_source_->SetSourceBufferActive(this, true);
first_initialization_segment_received_ = true;
}
@@ -417,6 +457,12 @@
event_queue_->Enqueue(event);
}
+void SourceBuffer::ScheduleAndMaybeDispatchImmediately(base::Token event_name) {
+ 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,
script::ExceptionState* exception_state) {
TRACE_EVENT1("cobalt::dom", "SourceBuffer::PrepareAppend()", "new_data_size",
@@ -426,7 +472,7 @@
exception_state);
return false;
}
- if (updating_) {
+ if (updating()) {
web::DOMException::Raise(web::DOMException::kInvalidStateErr,
exception_state);
return false;
@@ -441,7 +487,10 @@
media_source_->OpenIfInEndedState();
- if (!EvictCodedFrames(new_data_size)) {
+ double current_time = media_source_->GetMediaElement()->current_time(NULL);
+ if (!chunk_demuxer_->EvictCodedFrames(
+ id_, base::TimeDelta::FromSecondsD(current_time),
+ new_data_size + evict_extra_in_bytes_)) {
web::DOMException::Raise(web::DOMException::kQuotaExceededErr,
exception_state);
return false;
@@ -450,15 +499,6 @@
return true;
}
-bool SourceBuffer::EvictCodedFrames(size_t new_data_size) {
- DCHECK(media_source_);
- DCHECK(media_source_->GetMediaElement());
- double current_time = media_source_->GetMediaElement()->current_time(NULL);
- return chunk_demuxer_->EvictCodedFrames(
- id_, base::TimeDelta::FromSecondsD(current_time),
- new_data_size + evict_extra_in_bytes_);
-}
-
void SourceBuffer::AppendBufferInternal(
const unsigned char* data, size_t size,
script::ExceptionState* exception_state) {
@@ -471,8 +511,8 @@
metrics_.EndTracking(0);
DCHECK(data || size == 0);
+
if (data) {
- DCHECK_EQ(pending_append_data_offset_, 0u);
if (pending_append_data_capacity_ < size) {
pending_append_data_.reset();
pending_append_data_.reset(new uint8_t[size]);
@@ -480,124 +520,43 @@
}
memcpy(pending_append_data_.get(), data, size);
}
- pending_append_data_size_ = size;
- pending_append_data_offset_ = 0;
-
- updating_ = true;
ScheduleEvent(base::Tokens::updatestart());
- append_timer_.Start(FROM_HERE, base::TimeDelta(), this,
- &SourceBuffer::OnAppendTimer);
+ std::unique_ptr<SourceBufferAlgorithm> algorithm(
+ new SourceBufferAppendAlgorithm(
+ media_source_, chunk_demuxer_, id_, pending_append_data_.get(), size,
+ DoubleToTimeDelta(append_window_start_),
+ DoubleToTimeDelta(append_window_end_),
+ DoubleToTimeDelta(timestamp_offset_),
+ base::Bind(&SourceBuffer::UpdateTimestampOffset,
+ base::Unretained(this)),
+ base::Bind(asynchronous_reduction_enabled_
+ ? &SourceBuffer::ScheduleAndMaybeDispatchImmediately
+ : &SourceBuffer::ScheduleEvent,
+ base::Unretained(this)),
+ base::Bind(&SourceBuffer::OnAlgorithmFinalized,
+ base::Unretained(this)),
+ &metrics_));
+ active_algorithm_handle_ =
+ new SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>(
+ std::move(algorithm));
+ media_source_->GetAlgorithmRunner(size)->Start(active_algorithm_handle_);
}
-void SourceBuffer::OnAppendTimer() {
- TRACE_EVENT0("cobalt::dom", "SourceBuffer::OnAppendTimer()");
- const size_t kMaxAppendSize = 128 * 1024;
+void SourceBuffer::OnAlgorithmFinalized() {
+ DCHECK(active_algorithm_handle_);
+ active_algorithm_handle_ = nullptr;
+}
- DCHECK(updating_);
-
- DCHECK_GE(pending_append_data_size_, pending_append_data_offset_);
- size_t append_size = pending_append_data_size_ - pending_append_data_offset_;
- append_size = std::min(append_size, kMaxAppendSize);
-
- uint8_t dummy;
- const uint8* data_to_append =
- append_size > 0 ? pending_append_data_.get() + pending_append_data_offset_
- : &dummy;
-
- base::TimeDelta timestamp_offset = DoubleToTimeDelta(timestamp_offset_);
- metrics_.StartTracking();
- bool success = chunk_demuxer_->AppendData(
- id_, data_to_append, append_size, DoubleToTimeDelta(append_window_start_),
- DoubleToTimeDelta(append_window_end_), ×tamp_offset);
-
- if (timestamp_offset != DoubleToTimeDelta(timestamp_offset_)) {
+void SourceBuffer::UpdateTimestampOffset(base::TimeDelta timestamp_offset) {
+ starboard::ScopedLock scoped_lock(timestamp_offset_mutex_);
+ // The check avoids overwriting |timestamp_offset_| when there is a small
+ // difference between its float and its int64_t representation .
+ if (DoubleToTimeDelta(timestamp_offset_) != timestamp_offset) {
timestamp_offset_ = timestamp_offset.InSecondsF();
}
-
- if (!success) {
- metrics_.EndTracking(0);
- pending_append_data_size_ = 0;
- pending_append_data_offset_ = 0;
- AppendError();
- } else {
- metrics_.EndTracking(append_size);
- pending_append_data_offset_ += append_size;
-
- if (pending_append_data_offset_ < pending_append_data_size_) {
- append_timer_.Start(FROM_HERE, base::TimeDelta(), this,
- &SourceBuffer::OnAppendTimer);
- return;
- }
-
- updating_ = false;
- pending_append_data_size_ = 0;
- pending_append_data_offset_ = 0;
-
- ScheduleEvent(base::Tokens::update());
- ScheduleEvent(base::Tokens::updateend());
- }
}
-void SourceBuffer::AppendError() {
- base::TimeDelta timestamp_offset = DoubleToTimeDelta(timestamp_offset_);
- chunk_demuxer_->ResetParserState(id_, DoubleToTimeDelta(append_window_start_),
- DoubleToTimeDelta(append_window_end_),
- ×tamp_offset);
- timestamp_offset_ = timestamp_offset.InSecondsF();
-
- updating_ = false;
-
- ScheduleEvent(base::Tokens::error());
- ScheduleEvent(base::Tokens::updateend());
- media_source_->EndOfStreamAlgorithm(kMediaSourceEndOfStreamErrorDecode);
-}
-
-void SourceBuffer::OnRemoveTimer() {
- TRACE_EVENT0("cobalt::dom", "SourceBuffer::OnRemoveTimer()");
- DCHECK(updating_);
- DCHECK_GE(pending_remove_start_, 0);
- DCHECK_LT(pending_remove_start_, pending_remove_end_);
-
- chunk_demuxer_->Remove(id_, DoubleToTimeDelta(pending_remove_start_),
- DoubleToTimeDelta(pending_remove_end_));
-
- updating_ = false;
- pending_remove_start_ = -1;
- pending_remove_end_ = -1;
-
- ScheduleEvent(base::Tokens::update());
- ScheduleEvent(base::Tokens::updateend());
-}
-
-void SourceBuffer::CancelRemove() {
- DCHECK(updating_);
- DCHECK_NE(pending_remove_start_, -1);
- remove_timer_.Stop();
- pending_remove_start_ = -1;
- pending_remove_end_ = -1;
- updating_ = false;
-}
-
-void SourceBuffer::AbortIfUpdating() {
- if (!updating_) {
- return;
- }
-
- DCHECK_EQ(pending_remove_start_, -1);
-
- append_timer_.Stop();
- pending_append_data_size_ = 0;
- pending_append_data_offset_ = 0;
-
- updating_ = false;
-
- ScheduleEvent(base::Tokens::abort());
- ScheduleEvent(base::Tokens::updateend());
-}
-
-void SourceBuffer::RemoveMediaTracks() { NOTREACHED(); }
-
} // namespace dom
} // namespace cobalt
diff --git a/cobalt/dom/source_buffer.h b/cobalt/dom/source_buffer.h
index 9f68856..65bbe48 100644
--- a/cobalt/dom/source_buffer.h
+++ b/cobalt/dom/source_buffer.h
@@ -53,10 +53,13 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
#include "base/timer/timer.h"
#include "cobalt/base/token.h"
#include "cobalt/dom/audio_track_list.h"
#include "cobalt/dom/event_queue.h"
+#include "cobalt/dom/serialized_algorithm_runner.h"
+#include "cobalt/dom/source_buffer_algorithm.h"
#include "cobalt/dom/source_buffer_append_mode.h"
#include "cobalt/dom/source_buffer_metrics.h"
#include "cobalt/dom/time_ranges.h"
@@ -67,6 +70,7 @@
#include "cobalt/script/environment_settings.h"
#include "cobalt/script/exception_state.h"
#include "cobalt/web/event_target.h"
+#include "starboard/common/mutex.h"
#include "third_party/chromium/media/base/media_tracks.h"
#include "third_party/chromium/media/filters/chunk_demuxer.h"
@@ -85,8 +89,8 @@
// Custom, not in any spec.
//
SourceBuffer(script::EnvironmentSettings* settings, const std::string& id,
- MediaSource* media_source, ChunkDemuxer* chunk_demuxer,
- EventQueue* event_queue);
+ MediaSource* media_source, bool asynchronous_reduction_enabled,
+ ChunkDemuxer* chunk_demuxer, EventQueue* event_queue);
// Web API: SourceBuffer
//
@@ -95,12 +99,10 @@
}
void set_mode(SourceBufferAppendMode mode,
script::ExceptionState* exception_state);
- bool updating() const { return updating_; }
+ bool updating() const { return active_algorithm_handle_ != nullptr; }
scoped_refptr<TimeRanges> buffered(
script::ExceptionState* exception_state) const;
- double timestamp_offset(script::ExceptionState* exception_state) const {
- return timestamp_offset_;
- }
+ double timestamp_offset(script::ExceptionState* exception_state) const;
void set_timestamp_offset(double offset,
script::ExceptionState* exception_state);
scoped_refptr<AudioTrackList> audio_tracks() const { return audio_tracks_; }
@@ -140,22 +142,16 @@
private:
typedef ::media::MediaTracks MediaTracks;
- void InitSegmentReceived(std::unique_ptr<MediaTracks> tracks);
+ void OnInitSegmentReceived(std::unique_ptr<MediaTracks> tracks);
void ScheduleEvent(base::Token event_name);
+ void ScheduleAndMaybeDispatchImmediately(base::Token event_name);
bool PrepareAppend(size_t new_data_size,
script::ExceptionState* exception_state);
- bool EvictCodedFrames(size_t new_data_size);
void AppendBufferInternal(const unsigned char* data, size_t size,
script::ExceptionState* exception_state);
- void OnAppendTimer();
- void AppendError();
- void OnRemoveTimer();
-
- void CancelRemove();
- void AbortIfUpdating();
-
- void RemoveMediaTracks();
+ void OnAlgorithmFinalized();
+ void UpdateTimestampOffset(base::TimeDelta timestamp_offset_);
const TrackDefault* GetTrackDefault(
const std::string& track_type,
@@ -167,30 +163,32 @@
const std::string& byte_stream_track_id) const;
const std::string id_;
+ const bool asynchronous_reduction_enabled_;
const size_t evict_extra_in_bytes_;
- ChunkDemuxer* chunk_demuxer_;
+
MediaSource* media_source_;
+ ChunkDemuxer* chunk_demuxer_;
+ scoped_refptr<base::SingleThreadTaskRunner> web_task_runner_ =
+ base::MessageLoop::current()->task_runner();
scoped_refptr<TrackDefaultList> track_defaults_ = new TrackDefaultList(NULL);
EventQueue* event_queue_;
- SourceBufferAppendMode mode_ = kSourceBufferAppendModeSegments;
- bool updating_ = false;
- double timestamp_offset_ = 0;
+ bool first_initialization_segment_received_ = false;
scoped_refptr<AudioTrackList> audio_tracks_;
scoped_refptr<VideoTrackList> video_tracks_;
+
+ SourceBufferAppendMode mode_ = kSourceBufferAppendModeSegments;
+
+ starboard::Mutex timestamp_offset_mutex_;
+ double timestamp_offset_ = 0;
+
+ scoped_refptr<SerializedAlgorithmRunner::Handle<SourceBufferAlgorithm>>
+ active_algorithm_handle_;
double append_window_start_ = 0;
double append_window_end_ = std::numeric_limits<double>::infinity();
- base::OneShotTimer append_timer_;
- bool first_initialization_segment_received_ = false;
std::unique_ptr<uint8_t[]> pending_append_data_;
size_t pending_append_data_capacity_ = 0;
- size_t pending_append_data_size_ = 0;
- size_t pending_append_data_offset_ = 0;
-
- base::OneShotTimer remove_timer_;
- double pending_remove_start_ = -1;
- double pending_remove_end_ = -1;
SourceBufferMetrics metrics_;
};
diff --git a/cobalt/dom/source_buffer_algorithm.cc b/cobalt/dom/source_buffer_algorithm.cc
new file mode 100644
index 0000000..50eec01
--- /dev/null
+++ b/cobalt/dom/source_buffer_algorithm.cc
@@ -0,0 +1,152 @@
+// 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/source_buffer_algorithm.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/trace_event/trace_event.h"
+#include "cobalt/dom/media_source.h"
+
+namespace cobalt {
+namespace dom {
+
+SourceBufferAppendAlgorithm::SourceBufferAppendAlgorithm(
+ MediaSource* media_source, ::media::ChunkDemuxer* chunk_demuxer,
+ const std::string& id, const uint8_t* buffer, size_t size_in_bytes,
+ base::TimeDelta append_window_start, base::TimeDelta append_window_end,
+ base::TimeDelta timestamp_offset,
+ UpdateTimestampOffsetCB&& update_timestamp_offset_cb,
+ ScheduleEventCB&& schedule_event_cb, base::OnceClosure&& finalized_cb,
+ SourceBufferMetrics* metrics)
+ : media_source_(media_source),
+ chunk_demuxer_(chunk_demuxer),
+ id_(id),
+ buffer_(buffer),
+ bytes_remaining_(size_in_bytes),
+ append_window_start_(append_window_start),
+ append_window_end_(append_window_end),
+ timestamp_offset_(timestamp_offset),
+ update_timestamp_offset_cb_(std::move(update_timestamp_offset_cb)),
+ schedule_event_cb_(std::move(schedule_event_cb)),
+ finalized_cb_(std::move(finalized_cb)),
+ metrics_(metrics) {
+ DCHECK(media_source_);
+ DCHECK(chunk_demuxer_);
+ if (bytes_remaining_ > 0) {
+ DCHECK(buffer);
+ }
+ DCHECK(update_timestamp_offset_cb_);
+ DCHECK(schedule_event_cb_);
+ DCHECK(metrics_);
+ TRACE_EVENT1("cobalt::dom", "SourceBufferAppendAlgorithm ctor",
+ "bytes_remaining", bytes_remaining_);
+}
+
+void SourceBufferAppendAlgorithm::Process(bool* finished) {
+ DCHECK(finished);
+ DCHECK(!*finished);
+
+ const size_t kMaxAppendSize = 128 * 1024;
+
+ size_t append_size = std::min(bytes_remaining_, kMaxAppendSize);
+
+ TRACE_EVENT1("cobalt::dom", "SourceBufferAppendAlgorithm::Process()",
+ "append_size", append_size);
+
+ metrics_->StartTracking();
+ succeeded_ = chunk_demuxer_->AppendData(
+ id_, buffer_, append_size, append_window_start_, append_window_end_,
+ ×tamp_offset_);
+ update_timestamp_offset_cb_.Run(timestamp_offset_);
+ metrics_->EndTracking(succeeded_ ? append_size : 0);
+
+ if (succeeded_) {
+ buffer_ += append_size;
+ bytes_remaining_ -= append_size;
+
+ if (bytes_remaining_ == 0) {
+ *finished = true;
+ return;
+ }
+
+ return;
+ }
+
+ chunk_demuxer_->ResetParserState(id_, append_window_start_,
+ append_window_end_, ×tamp_offset_);
+ update_timestamp_offset_cb_.Run(timestamp_offset_);
+ *finished = true;
+}
+
+void SourceBufferAppendAlgorithm::Abort() {
+ TRACE_EVENT0("cobalt::dom", "SourceBufferAppendAlgorithm::Abort()");
+ schedule_event_cb_.Run(base::Tokens::abort());
+ schedule_event_cb_.Run(base::Tokens::updateend());
+}
+
+void SourceBufferAppendAlgorithm::Finalize() {
+ TRACE_EVENT1("cobalt::dom", "SourceBufferAppendAlgorithm::Finalize()",
+ "succeeded", succeeded_);
+ if (succeeded_) {
+ schedule_event_cb_.Run(base::Tokens::update());
+ schedule_event_cb_.Run(base::Tokens::updateend());
+ } else {
+ schedule_event_cb_.Run(base::Tokens::error());
+ schedule_event_cb_.Run(base::Tokens::updateend());
+ media_source_->EndOfStreamAlgorithm(kMediaSourceEndOfStreamErrorDecode);
+ }
+
+ std::move(finalized_cb_).Run();
+}
+
+SourceBufferRemoveAlgorithm::SourceBufferRemoveAlgorithm(
+ ::media::ChunkDemuxer* chunk_demuxer, const std::string& id,
+ base::TimeDelta pending_remove_start, base::TimeDelta pending_remove_end,
+ ScheduleEventCB&& schedule_event_cb, base::OnceClosure&& finalized_cb)
+ : chunk_demuxer_(chunk_demuxer),
+ id_(id),
+ pending_remove_start_(pending_remove_start),
+ pending_remove_end_(pending_remove_end),
+ schedule_event_cb_(std::move(schedule_event_cb)),
+ finalized_cb_(std::move(finalized_cb)) {
+ TRACE_EVENT0("cobalt::dom", "SourceBufferRemoveAlgorithm ctor");
+ DCHECK(chunk_demuxer_);
+ DCHECK(schedule_event_cb_);
+}
+
+void SourceBufferRemoveAlgorithm::Process(bool* finished) {
+ TRACE_EVENT0("cobalt::dom", "SourceBufferRemoveAlgorithm::Process()");
+ chunk_demuxer_->Remove(id_, pending_remove_start_, pending_remove_end_);
+ *finished = true;
+}
+
+void SourceBufferRemoveAlgorithm::Abort() {
+ TRACE_EVENT0("cobalt::dom", "SourceBufferRemoveAlgorithm::Abort()");
+ // SourceBufferRemoveAlgorithm cannot be cancelled explicitly by the web app.
+ // This function will only be called when the SourceBuffer is being removed
+ // from the MediaSource and no events should be fired.
+}
+
+void SourceBufferRemoveAlgorithm::Finalize() {
+ TRACE_EVENT0("cobalt::dom", "SourceBufferRemoveAlgorithm::Finalize()");
+ schedule_event_cb_.Run(base::Tokens::update());
+ schedule_event_cb_.Run(base::Tokens::updateend());
+ std::move(finalized_cb_).Run();
+}
+
+} // namespace dom
+} // namespace cobalt
diff --git a/cobalt/dom/source_buffer_algorithm.h b/cobalt/dom/source_buffer_algorithm.h
new file mode 100644
index 0000000..d9e0f16
--- /dev/null
+++ b/cobalt/dom/source_buffer_algorithm.h
@@ -0,0 +1,119 @@
+// 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_DOM_SOURCE_BUFFER_ALGORITHM_H_
+#define COBALT_DOM_SOURCE_BUFFER_ALGORITHM_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "cobalt/base/tokens.h"
+#include "cobalt/dom/source_buffer_metrics.h"
+#include "third_party/chromium/media/filters/chunk_demuxer.h"
+
+namespace cobalt {
+namespace dom {
+
+class MediaSource; // Necessary to avoid circular inclusion.
+
+// Base class of all SourceBuffer algorithms. Its user should call `Process()`
+// multiple times until |finished| is set to true on return, and then call
+// `Finalize()` exactly once. `Abort()` can be called at any time to abort any
+// processing.
+class SourceBufferAlgorithm {
+ public:
+ typedef base::RepeatingCallback<void(base::TimeDelta)>
+ UpdateTimestampOffsetCB;
+ typedef base::RepeatingCallback<void(base::Token)> ScheduleEventCB;
+
+ virtual ~SourceBufferAlgorithm() {}
+
+ // Returns false to indicate that the algorithm cannot be explicitly aborted
+ // by calling `Abort()` on the Handle. The algorithm may still be aborted
+ // when the SourceBuffer is being removed from the MediaSource.
+ virtual bool SupportExplicitAbort() = 0;
+
+ virtual void Process(bool* finished) = 0;
+ virtual void Abort() = 0;
+ virtual void Finalize() = 0;
+};
+
+// Implements the steps 12 to 18 of SourceBuffer stream append loop algorithm as
+// specified at
+// https://www.w3.org/TR/2016/CR-media-source-20160705/#sourcebuffer-stream-append-loop.
+class SourceBufferAppendAlgorithm : public SourceBufferAlgorithm {
+ public:
+ SourceBufferAppendAlgorithm(
+ MediaSource* media_source, ::media::ChunkDemuxer* chunk_demuxer,
+ const std::string& id, const uint8_t* buffer, size_t size_in_bytes,
+ base::TimeDelta append_window_start, base::TimeDelta append_window_end,
+ base::TimeDelta timestamp_offset,
+ UpdateTimestampOffsetCB&& update_timestamp_offset_cb,
+ ScheduleEventCB&& schedule_event_cb, base::OnceClosure&& finalized_cb,
+ SourceBufferMetrics* metrics);
+
+ private:
+ bool SupportExplicitAbort() override { return true; }
+ void Process(bool* finished) override;
+ void Abort() override;
+ void Finalize() override;
+
+ MediaSource* const media_source_;
+ ::media::ChunkDemuxer* const chunk_demuxer_;
+ const std::string id_;
+ const uint8_t* buffer_;
+ size_t bytes_remaining_;
+ const base::TimeDelta append_window_start_;
+ const base::TimeDelta append_window_end_;
+
+ base::TimeDelta timestamp_offset_;
+ const UpdateTimestampOffsetCB update_timestamp_offset_cb_;
+ const ScheduleEventCB schedule_event_cb_;
+ base::OnceClosure finalized_cb_;
+ SourceBufferMetrics* const metrics_;
+
+ bool succeeded_ = false;
+};
+
+// Implements the steps 6 to 9 of SourceBuffer range removal algorithm as
+// specified at
+// https://www.w3.org/TR/2016/CR-media-source-20160705/#sourcebuffer-range-removal.
+class SourceBufferRemoveAlgorithm : public SourceBufferAlgorithm {
+ public:
+ SourceBufferRemoveAlgorithm(::media::ChunkDemuxer* chunk_demuxer,
+ const std::string& id,
+ base::TimeDelta pending_remove_start,
+ base::TimeDelta pending_remove_end,
+ ScheduleEventCB&& schedule_event_cb,
+ base::OnceClosure&& finalized_cb);
+
+ private:
+ bool SupportExplicitAbort() override { return false; }
+ void Process(bool* finished) override;
+ void Abort() override;
+ void Finalize() override;
+
+ ::media::ChunkDemuxer* const chunk_demuxer_;
+ const std::string id_;
+ const base::TimeDelta pending_remove_start_;
+ const base::TimeDelta pending_remove_end_;
+ const ScheduleEventCB schedule_event_cb_;
+ base::OnceClosure finalized_cb_;
+};
+
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_SOURCE_BUFFER_ALGORITHM_H_
diff --git a/cobalt/dom/testing/BUILD.gn b/cobalt/dom/testing/BUILD.gn
index 49453ae..846388b 100644
--- a/cobalt/dom/testing/BUILD.gn
+++ b/cobalt/dom/testing/BUILD.gn
@@ -17,6 +17,7 @@
has_pedantic_warnings = true
sources = [
+ "fake_document.h",
"html_collection_testing.h",
"mock_layout_boxes.h",
"stub_css_parser.cc",
diff --git a/cobalt/dom/testing/fake_document.h b/cobalt/dom/testing/fake_document.h
new file mode 100644
index 0000000..3ab3d94
--- /dev/null
+++ b/cobalt/dom/testing/fake_document.h
@@ -0,0 +1,70 @@
+// 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_DOM_TESTING_FAKE_DOCUMENT_H_
+#define COBALT_DOM_TESTING_FAKE_DOCUMENT_H_
+
+#include <memory>
+#include <utility>
+
+#include "cobalt/dom/document.h"
+
+#include "cobalt/web/csp_delegate_factory.h"
+
+namespace cobalt {
+namespace dom {
+namespace testing {
+
+class FakeDocument : public dom::Document {
+ public:
+ explicit FakeDocument(dom::HTMLElementContext* html_element_context)
+ : dom::Document(html_element_context) {
+ web::WindowOrWorkerGlobalScope::Options options(
+ base::ApplicationState::kApplicationStateStarted);
+ std::unique_ptr<web::CspViolationReporter> violation_reporter(
+ new web::CspViolationReporter(nullptr, options.post_sender));
+ csp_delegate_ = web::CspDelegateFactory::GetInstance()->Create(
+ options.csp_enforcement_mode, std::move(violation_reporter),
+ environment_settings()->creation_url(), options.require_csp,
+ options.csp_policy_changed_callback,
+ options.csp_insecure_allowed_token);
+ }
+
+ FakeDocument(dom::HTMLElementContext* html_element_context,
+ dom::Document::Options doc_options)
+ : dom::Document(html_element_context, doc_options) {
+ web::WindowOrWorkerGlobalScope::Options options(
+ base::ApplicationState::kApplicationStateStarted);
+ std::unique_ptr<web::CspViolationReporter> violation_reporter(
+ new web::CspViolationReporter(nullptr, options.post_sender));
+ csp_delegate_ = web::CspDelegateFactory::GetInstance()->Create(
+ options.csp_enforcement_mode, std::move(violation_reporter),
+ environment_settings()->creation_url(), options.require_csp,
+ options.csp_policy_changed_callback,
+ options.csp_insecure_allowed_token);
+ }
+
+ web::CspDelegate* csp_delegate() const override {
+ return csp_delegate_.get();
+ }
+
+ private:
+ std::unique_ptr<web::CspDelegate> csp_delegate_;
+};
+
+} // namespace testing
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_TESTING_FAKE_DOCUMENT_H_
diff --git a/cobalt/dom/testing/stub_environment_settings.h b/cobalt/dom/testing/stub_environment_settings.h
index 01d01f3..a70eef3 100644
--- a/cobalt/dom/testing/stub_environment_settings.h
+++ b/cobalt/dom/testing/stub_environment_settings.h
@@ -26,7 +26,7 @@
public:
explicit StubEnvironmentSettings(const Options& options = Options())
: DOMSettings(null_debugger_hooks_, 0, nullptr, nullptr, nullptr, nullptr,
- options) {}
+ nullptr, options) {}
~StubEnvironmentSettings() override {}
private:
diff --git a/cobalt/dom/testing/test_with_javascript.h b/cobalt/dom/testing/test_with_javascript.h
index 58df232..30204af 100644
--- a/cobalt/dom/testing/test_with_javascript.h
+++ b/cobalt/dom/testing/test_with_javascript.h
@@ -50,15 +50,16 @@
Window* window() { return stub_window_->window().get(); }
bool EvaluateScript(const std::string& js_code, std::string* result) {
- DCHECK(global_environment());
- scoped_refptr<script::SourceCode> source_code =
- script::SourceCode::CreateSourceCode(
- js_code, base::SourceLocation(__FILE__, __LINE__, 1));
+ return global_environment()->EvaluateScript(
+ CreateSourceCodeAndPrepareEval(js_code), result);
+ }
- global_environment()->EnableEval();
- global_environment()->SetReportEvalCallback(base::Closure());
- bool succeeded = global_environment()->EvaluateScript(source_code, result);
- return succeeded;
+ bool EvaluateScript(
+ const std::string& js_code,
+ const scoped_refptr<script::Wrappable>& owning_object,
+ base::Optional<script::ValueHandleHolder::Reference>* result = NULL) {
+ return global_environment()->EvaluateScript(
+ CreateSourceCodeAndPrepareEval(js_code), owning_object, result);
}
::testing::StrictMock<script::testing::MockExceptionState>*
@@ -73,6 +74,15 @@
base::EventDispatcher* event_dispatcher() { return &event_dispatcher_; }
private:
+ scoped_refptr<script::SourceCode> CreateSourceCodeAndPrepareEval(
+ const std::string& js_code) {
+ DCHECK(global_environment());
+ global_environment()->EnableEval();
+ global_environment()->SetReportEvalCallback(base::Closure());
+ return script::SourceCode::CreateSourceCode(
+ js_code, base::SourceLocation(__FILE__, __LINE__, 1));
+ }
+
std::unique_ptr<StubWindow> stub_window_;
::testing::StrictMock<script::testing::MockExceptionState> exception_state_;
base::EventDispatcher event_dispatcher_;
diff --git a/cobalt/dom/user_agent_data_test.cc b/cobalt/dom/user_agent_data_test.cc
index dc3c350..376fcda 100644
--- a/cobalt/dom/user_agent_data_test.cc
+++ b/cobalt/dom/user_agent_data_test.cc
@@ -40,7 +40,6 @@
// Inject H5vcc interface to make it also accessible via Window
h5vcc::H5vcc::Settings h5vcc_settings;
- h5vcc_settings.media_module = NULL;
h5vcc_settings.network_module = NULL;
#if SB_IS(EVERGREEN)
h5vcc_settings.updater_module = NULL;
diff --git a/cobalt/dom/window.cc b/cobalt/dom/window.cc
index 89178fe..aca75dc 100644
--- a/cobalt/dom/window.cc
+++ b/cobalt/dom/window.cc
@@ -129,8 +129,12 @@
bool log_tts)
// 'window' object EventTargets require special handling for onerror events,
// see EventTarget constructor for more details.
- : web::WindowOrWorkerGlobalScope(settings, dom_stat_tracker,
- initial_application_state),
+ : web::WindowOrWorkerGlobalScope(
+ settings, dom_stat_tracker,
+ web::WindowOrWorkerGlobalScope::Options(
+ initial_application_state, post_sender, require_csp,
+ csp_enforcement_mode, csp_policy_changed_callback,
+ csp_insecure_allowed_token)),
viewport_size_(view_size),
is_resize_event_pending_(false),
is_reporting_script_error_(false),
@@ -155,9 +159,7 @@
base::Bind(&Window::FireHashChangeEvent, base::Unretained(this)),
performance_->timing()->GetNavigationStartClock(),
navigation_callback, ParseUserAgentStyleSheet(css_parser),
- view_size, cookie_jar, post_sender, require_csp,
- csp_enforcement_mode, csp_policy_changed_callback,
- csp_insecure_allowed_token, dom_max_element_depth)))),
+ view_size, cookie_jar, dom_max_element_depth)))),
document_loader_(nullptr),
history_(new History()),
navigator_(new Navigator(environment_settings(), captions)),
@@ -172,7 +174,6 @@
ALLOW_THIS_IN_INITIALIZER_LIST(
session_storage_(new Storage(this, Storage::kSessionStorage, NULL))),
screen_(new Screen(view_size)),
- preflight_cache_(new loader::CORSPreflightCache()),
ran_animation_frame_callbacks_callback_(
ran_animation_frame_callbacks_callback),
window_close_callback_(window_close_callback),
diff --git a/cobalt/dom/window.h b/cobalt/dom/window.h
index 6485969..033ac82 100644
--- a/cobalt/dom/window.h
+++ b/cobalt/dom/window.h
@@ -45,7 +45,6 @@
#include "cobalt/dom/test_runner.h"
#endif // ENABLE_TEST_RUNNER
#include "cobalt/input/camera_3d.h"
-#include "cobalt/loader/cors_preflight_cache.h"
#include "cobalt/loader/decoder.h"
#include "cobalt/loader/fetcher_factory.h"
#include "cobalt/loader/font/remote_typeface_cache.h"
@@ -361,10 +360,6 @@
void CacheSplashScreen(const std::string& content,
const base::Optional<std::string>& topic);
- const scoped_refptr<loader::CORSPreflightCache> get_preflight_cache() {
- return preflight_cache_;
- }
-
// Custom on screen keyboard.
const scoped_refptr<OnScreenKeyboard>& on_screen_keyboard() const;
void ReleaseOnScreenKeyboard();
@@ -443,9 +438,6 @@
scoped_refptr<Screen> screen_;
- // Global preflight cache.
- scoped_refptr<loader::CORSPreflightCache> preflight_cache_;
-
const base::Closure ran_animation_frame_callbacks_callback_;
const CloseCallback window_close_callback_;
const base::Closure window_minimize_callback_;
diff --git a/cobalt/h5vcc/BUILD.gn b/cobalt/h5vcc/BUILD.gn
index 9c5a145..fd7216f 100644
--- a/cobalt/h5vcc/BUILD.gn
+++ b/cobalt/h5vcc/BUILD.gn
@@ -79,7 +79,6 @@
"//cobalt/cache",
"//cobalt/configuration",
"//cobalt/dom",
- "//cobalt/media",
"//cobalt/network",
"//cobalt/persistent_storage:persistent_settings",
"//cobalt/script",
diff --git a/cobalt/h5vcc/h5vcc.cc b/cobalt/h5vcc/h5vcc.cc
index d3b8198..806f7a1 100644
--- a/cobalt/h5vcc/h5vcc.cc
+++ b/cobalt/h5vcc/h5vcc.cc
@@ -27,12 +27,12 @@
c_val_ = new dom::CValView();
crash_log_ = new H5vccCrashLog();
runtime_ = new H5vccRuntime(settings.event_dispatcher);
- settings_ =
- new H5vccSettings(settings.media_module, settings.network_module,
+ settings_ = new H5vccSettings(
+ settings.set_media_source_setting_func, settings.network_module,
#if SB_IS(EVERGREEN)
- settings.updater_module,
+ settings.updater_module,
#endif
- settings.user_agent_data, settings.global_environment);
+ settings.user_agent_data, settings.global_environment);
#if defined(COBALT_ENABLE_SSO)
sso_ = new H5vccSso();
#endif
diff --git a/cobalt/h5vcc/h5vcc.h b/cobalt/h5vcc/h5vcc.h
index c74b9e6..0dce20d 100644
--- a/cobalt/h5vcc/h5vcc.h
+++ b/cobalt/h5vcc/h5vcc.h
@@ -17,6 +17,7 @@
#include <string>
+#include "base/callback.h"
#include "cobalt/base/event_dispatcher.h"
#include "cobalt/dom/c_val_view.h"
#include "cobalt/dom/mutation_observer_task_manager.h"
@@ -45,8 +46,7 @@
public:
struct Settings {
Settings()
- : media_module(NULL),
- network_module(NULL),
+ : network_module(NULL),
#if SB_IS(EVERGREEN)
updater_module(NULL),
#endif
@@ -55,7 +55,7 @@
user_agent_data(NULL),
global_environment(NULL) {
}
- media::MediaModule* media_module;
+ H5vccSettings::SetMediaSourceSettingFunc set_media_source_setting_func;
network::NetworkModule* network_module;
#if SB_IS(EVERGREEN)
updater::UpdaterModule* updater_module;
diff --git a/cobalt/h5vcc/h5vcc_crash_log.cc b/cobalt/h5vcc/h5vcc_crash_log.cc
index 7a502b4..564feda 100644
--- a/cobalt/h5vcc/h5vcc_crash_log.cc
+++ b/cobalt/h5vcc/h5vcc_crash_log.cc
@@ -161,8 +161,8 @@
default:
replace = watchdog::NONE;
}
- return watchdog->Register(name, description, monitor_state, time_interval,
- time_wait, replace);
+ return watchdog->Register(name, description, monitor_state,
+ time_interval * 1000, time_wait * 1000, replace);
}
return false;
}
diff --git a/cobalt/h5vcc/h5vcc_crash_log.idl b/cobalt/h5vcc/h5vcc_crash_log.idl
index 45f6df3..2bbf4df 100644
--- a/cobalt/h5vcc/h5vcc_crash_log.idl
+++ b/cobalt/h5vcc/h5vcc_crash_log.idl
@@ -34,9 +34,9 @@
// description, information on the Watchdog client.
// watchdog_state, application state to continue monitoring client up to.
// Inclusive.
- // time_interval, maximum number of microseconds allowed between pings
- // before triggering a Watchdog violation. Min value of 1000000.
- // time_wait, number of microseconds to initially wait before Watchdog
+ // time_interval, maximum number of milliseconds allowed between pings
+ // before triggering a Watchdog violation. Min value of 1000.
+ // time_wait, number of milliseconds to initially wait before Watchdog
// violations can be triggered. Reapplies after client resumes from idle
// state due to application state changes.
// watchdog_replace, behavior with previously registered Watchdog clients
@@ -51,12 +51,13 @@
// Returns true if Watchdog client was pinged. Name determines the Watchdog
// client to ping with ping_info which can either be empty or contain relevant
- // metadata. ping_info has a max length of 1024.
+ // metadata. ping_info has a max length of 128.
boolean ping(DOMString name, DOMString ping_info);
// Returns a json string containing the Watchdog violations since the last
- // call. Clears internal cache of Watchdog violations to prevent duplicates.
- // Timestamps are stored as strings due to int size constraints.
+ // call, up to the 200 most recent. Clears internal cache of Watchdog
+ // violations to prevent duplicates. Timestamps are stored as strings due to
+ // int size constraints.
// Example json:
// {
// "test-name":{
@@ -67,18 +68,18 @@
// "pingInfos":[
// {
// "info":"test-ping",
- // "timestampMicroseconds":"1658972623547006"
+ // "timestampMilliseconds":"1658972623547"
// }
// ],
// "registeredClients":[
// "test-name"
// ],
- // "timeIntervalMicroseconds":"5000000",
- // "timeWaitMicroseconds":"0",
- // "timestampLastPingedMicroseconds":"1658972623547006",
- // "timestampRegisteredMicroseconds":"1658972621890834",
- // "timestampViolationMicroseconds":"1658972629489771",
- // "violationDurationMicroseconds":"942764"
+ // "timeIntervalMilliseconds":"5000",
+ // "timeWaitMilliseconds":"0",
+ // "timestampLastPingedMilliseconds":"1658972623547",
+ // "timestampRegisteredMilliseconds":"1658972621890",
+ // "timestampViolationMilliseconds":"1658972629489",
+ // "violationDurationMilliseconds":"942"
// }
// ]
// }
diff --git a/cobalt/h5vcc/h5vcc_settings.cc b/cobalt/h5vcc/h5vcc_settings.cc
index 3417192..1735270 100644
--- a/cobalt/h5vcc/h5vcc_settings.cc
+++ b/cobalt/h5vcc/h5vcc_settings.cc
@@ -19,14 +19,15 @@
namespace cobalt {
namespace h5vcc {
-H5vccSettings::H5vccSettings(media::MediaModule* media_module,
- cobalt::network::NetworkModule* network_module,
+H5vccSettings::H5vccSettings(
+ const SetMediaSourceSettingFunc& set_media_source_setting_func,
+ cobalt::network::NetworkModule* network_module,
#if SB_IS(EVERGREEN)
- cobalt::updater::UpdaterModule* updater_module,
+ cobalt::updater::UpdaterModule* updater_module,
#endif
- web::NavigatorUAData* user_agent_data,
- script::GlobalEnvironment* global_environment)
- : media_module_(media_module),
+ web::NavigatorUAData* user_agent_data,
+ script::GlobalEnvironment* global_environment)
+ : set_media_source_setting_func_(set_media_source_setting_func),
network_module_(network_module),
#if SB_IS(EVERGREEN)
updater_module_(updater_module),
@@ -36,7 +37,6 @@
}
bool H5vccSettings::Set(const std::string& name, int32 value) const {
- const char kMediaPrefix[] = "Media.";
const char kNavigatorUAData[] = "NavigatorUAData";
const char kQUIC[] = "QUIC";
@@ -44,8 +44,9 @@
const char kUpdaterMinFreeSpaceBytes[] = "Updater.MinFreeSpaceBytes";
#endif
- if (name.compare(kMediaPrefix) == 0) {
- return media_module_ ? media_module_->SetConfiguration(name, value) : false;
+ if (set_media_source_setting_func_ &&
+ set_media_source_setting_func_.Run(name, value)) {
+ return true;
}
if (name.compare(kNavigatorUAData) == 0 && value == 1) {
diff --git a/cobalt/h5vcc/h5vcc_settings.h b/cobalt/h5vcc/h5vcc_settings.h
index 2257d6b..a73e59f 100644
--- a/cobalt/h5vcc/h5vcc_settings.h
+++ b/cobalt/h5vcc/h5vcc_settings.h
@@ -17,7 +17,6 @@
#include <string>
-#include "cobalt/media/media_module.h"
#include "cobalt/network/network_module.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/wrappable.h"
@@ -35,13 +34,16 @@
// version to avoid being abused.
class H5vccSettings : public script::Wrappable {
public:
- explicit H5vccSettings(media::MediaModule* media_module,
- cobalt::network::NetworkModule* network_module,
+ typedef base::Callback<bool(const std::string& name, int value)>
+ SetMediaSourceSettingFunc;
+
+ H5vccSettings(const SetMediaSourceSettingFunc& set_media_source_setting_func,
+ cobalt::network::NetworkModule* network_module,
#if SB_IS(EVERGREEN)
- cobalt::updater::UpdaterModule* updater_module,
+ cobalt::updater::UpdaterModule* updater_module,
#endif
- web::NavigatorUAData* user_agent_data,
- script::GlobalEnvironment* global_environment);
+ web::NavigatorUAData* user_agent_data,
+ script::GlobalEnvironment* global_environment);
// Returns true when the setting is set successfully or if the setting has
// already been set to the expected value. Returns false when the setting is
@@ -51,7 +53,7 @@
DEFINE_WRAPPABLE_TYPE(H5vccSettings);
private:
- media::MediaModule* media_module_;
+ const SetMediaSourceSettingFunc set_media_source_setting_func_;
cobalt::network::NetworkModule* network_module_ = nullptr;
#if SB_IS(EVERGREEN)
cobalt::updater::UpdaterModule* updater_module_ = nullptr;
diff --git a/cobalt/h5vcc/h5vcc_storage.cc b/cobalt/h5vcc/h5vcc_storage.cc
index b5c3af0..d734a0e 100644
--- a/cobalt/h5vcc/h5vcc_storage.cc
+++ b/cobalt/h5vcc/h5vcc_storage.cc
@@ -248,12 +248,14 @@
quota.image() + quota.font() + quota.splash() +
quota.uncompiled_js() + quota.compiled_js();
- // TODO(b/235529738): Calculate correct max_quota_size that subtracts
- // non-cache memory used in the kSbSystemPathCacheDirectory.
uint32_t max_quota_size = 24 * 1024 * 1024;
#if SB_API_VERSION >= 14
max_quota_size = kSbMaxSystemPathCacheDirectorySize;
#endif
+ // Assume the non-http-cache memory in kSbSystemPathCacheDirectory
+ // is less than 1 mb and subtract this from the max_quota_size.
+ max_quota_size -= (1 << 20);
+
if (quota_total != max_quota_size) {
return SetQuotaResponse(starboard::FormatString(
"H5vccStorageResourceTypeQuotaDictionary input parameter field values "
@@ -311,12 +313,13 @@
->GetMaxCacheStorageInBytes(disk_cache::kCompiledScript)
.value());
- // TODO(b/235529738): Calculate correct max_quota_size that subtracts
- // non-cache memory used in the kSbSystemPathCacheDirectory.
uint32_t max_quota_size = 24 * 1024 * 1024;
#if SB_API_VERSION >= 14
max_quota_size = kSbMaxSystemPathCacheDirectorySize;
#endif
+ // Assume the non-http-cache memory in kSbSystemPathCacheDirectory
+ // is less than 1 mb and subtract this from the max_quota_size.
+ max_quota_size -= (1 << 20);
quota.set_total(max_quota_size);
diff --git a/cobalt/h5vcc/h5vcc_system.h b/cobalt/h5vcc/h5vcc_system.h
index 6af4279..5b5d086 100644
--- a/cobalt/h5vcc/h5vcc_system.h
+++ b/cobalt/h5vcc/h5vcc_system.h
@@ -21,7 +21,6 @@
#if SB_IS(EVERGREEN)
#include "cobalt/h5vcc/h5vcc_updater.h"
#endif
-#include "cobalt/media/media_module.h"
#include "cobalt/script/wrappable.h"
namespace cobalt {
diff --git a/cobalt/layout_tests/testdata/web-platform-tests/WebCryptoAPI/web_platform_tests.txt b/cobalt/layout_tests/testdata/web-platform-tests/WebCryptoAPI/web_platform_tests.txt
index 3e1afd6..287a65d 100644
--- a/cobalt/layout_tests/testdata/web-platform-tests/WebCryptoAPI/web_platform_tests.txt
+++ b/cobalt/layout_tests/testdata/web-platform-tests/WebCryptoAPI/web_platform_tests.txt
@@ -1,6 +1,7 @@
# WebCrypto API tests.
#
# Only HMAC signing is supported
+sign_verify/hmac.https.worker.html,PASS
sign_verify/test_rsa_pkcs.https.html,DISABLE
sign_verify/test_hmac.https.html,PASS
sign_verify/test_rsa_pss.https.html,DISABLE
diff --git a/cobalt/media/base/sbplayer_pipeline.cc b/cobalt/media/base/sbplayer_pipeline.cc
index 79e9a6a..dc3a212 100644
--- a/cobalt/media/base/sbplayer_pipeline.cc
+++ b/cobalt/media/base/sbplayer_pipeline.cc
@@ -1255,11 +1255,9 @@
SbTime time_ahead_of_playback =
timestamp_of_last_written_audio_ - last_media_time_;
if (time_ahead_of_playback > (kAudioLimit + kMediaTimeCheckInterval)) {
- SbTime delay_time = (time_ahead_of_playback - kAudioLimit) /
- std::max(playback_rate_.value(), 1.0f);
task_runner_->PostDelayedTask(
FROM_HERE, base::Bind(&SbPlayerPipeline::DelayedNeedData, this),
- base::TimeDelta::FromMicroseconds(delay_time));
+ base::TimeDelta::FromMicroseconds(kMediaTimeCheckInterval));
audio_read_delayed_ = true;
return;
}
diff --git a/cobalt/media/base/starboard_player.cc b/cobalt/media/base/starboard_player.cc
index 7c5eb1d..ae7defd 100644
--- a/cobalt/media/base/starboard_player.cc
+++ b/cobalt/media/base/starboard_player.cc
@@ -37,7 +37,7 @@
namespace {
-base::Statistics<SbTime, int, 1024> s_player_presenting_delays_;
+base::Statistics<SbTime, int, 1024> s_startup_latency;
} // namespace
@@ -983,7 +983,6 @@
if (set_drm_system_ready_cb_time_ == -1) {
first_events_str =
starboard::FormatString("%-40s0 us", "SbPlayerCreate() called");
-
} else if (set_drm_system_ready_cb_time_ < player_creation_time_) {
first_events_str = starboard::FormatString(
"%-40s0 us\n%-40s%" PRId64 " us", "set_drm_system_ready_cb called",
@@ -996,9 +995,10 @@
set_drm_system_ready_cb_time_ - player_creation_time_);
}
- SbTime player_initialization_time_delta =
- sb_player_state_initialized_time_ -
+ SbTime first_event_time =
std::max(player_creation_time_, set_drm_system_ready_cb_time_);
+ SbTime player_initialization_time_delta =
+ sb_player_state_initialized_time_ - first_event_time;
SbTime player_preroll_time_delta =
sb_player_state_prerolling_time_ - sb_player_state_initialized_time_;
SbTime first_audio_sample_time_delta = std::max(
@@ -1008,27 +1008,29 @@
SbTime player_presenting_time_delta =
sb_player_state_presenting_time_ -
std::max(first_audio_sample_time_, first_video_sample_time_);
+ SbTime startup_latency = sb_player_state_presenting_time_ - first_event_time;
- s_player_presenting_delays_.AddSample(player_presenting_time_delta, 1);
+ s_startup_latency.AddSample(startup_latency, 1);
// clang-format off
LOG(INFO) << starboard::FormatString(
- "\nSbPlayer startup latencies\n"
+ "\nSbPlayer startup latencies: %" PRId64 " us\n"
" Event name time since last event\n"
" %s\n" // |first_events_str| populated above
" kSbPlayerStateInitialized received %" PRId64 " us\n"
" kSbPlayerStatePrerolling received %" PRId64 " us\n"
" First media sample(s) written [a/v] %" PRId64 "/%" PRId64 " us\n"
" kSbPlayerStatePresenting received %" PRId64 " us\n"
- " kSbPlayerStatePresenting delay statistics (us):\n"
+ " Startup latency statistics (us):\n"
" min: %" PRId64 ", median: %" PRId64 ", average: %" PRId64
", max: %" PRId64,
+ startup_latency,
first_events_str.c_str(), player_initialization_time_delta,
player_preroll_time_delta, first_audio_sample_time_delta,
first_video_sample_time_delta, player_presenting_time_delta,
- s_player_presenting_delays_.min(),
- s_player_presenting_delays_.GetMedian(),
- s_player_presenting_delays_.average(), s_player_presenting_delays_.max());
+ s_startup_latency.min(),
+ s_startup_latency.GetMedian(),
+ s_startup_latency.average(), s_startup_latency.max());
// clang-format on
}
diff --git a/cobalt/media/decoder_buffer_allocator.cc b/cobalt/media/decoder_buffer_allocator.cc
index 6f3a1a1..57b9974 100644
--- a/cobalt/media/decoder_buffer_allocator.cc
+++ b/cobalt/media/decoder_buffer_allocator.cc
@@ -188,10 +188,6 @@
return max_buffer_capacity_;
}
-size_t DecoderBufferAllocator::GetSourceBufferEvictExtraInBytes() const {
- return source_buffer_evict_extra_in_bytes_;
-}
-
void DecoderBufferAllocator::EnsureReuseAllocatorIsCreated() {
mutex_.DCheckAcquired();
diff --git a/cobalt/media/decoder_buffer_allocator.h b/cobalt/media/decoder_buffer_allocator.h
index 2e08a9f..31c3df4 100644
--- a/cobalt/media/decoder_buffer_allocator.h
+++ b/cobalt/media/decoder_buffer_allocator.h
@@ -47,11 +47,6 @@
size_t GetAllocatedMemory() const override;
size_t GetCurrentMemoryCapacity() const override;
size_t GetMaximumMemoryCapacity() const override;
- size_t GetSourceBufferEvictExtraInBytes() const override;
-
- void SetSourceBufferEvictExtraInBytes(size_t evict_extra_in_bytes) {
- source_buffer_evict_extra_in_bytes_ = evict_extra_in_bytes;
- }
private:
void EnsureReuseAllocatorIsCreated();
@@ -66,7 +61,6 @@
std::unique_ptr<nb::BidirectionalFitReuseAllocator> reuse_allocator_;
int max_buffer_capacity_ = 0;
- size_t source_buffer_evict_extra_in_bytes_ = 0;
// Monitor memory allocation and use when |using_memory_pool_| is false
starboard::atomic_int32_t sbmemory_bytes_used_;
diff --git a/cobalt/media/decoder_buffer_memory_info.h b/cobalt/media/decoder_buffer_memory_info.h
index 2e4813b..730b303 100644
--- a/cobalt/media/decoder_buffer_memory_info.h
+++ b/cobalt/media/decoder_buffer_memory_info.h
@@ -28,14 +28,6 @@
virtual size_t GetAllocatedMemory() const = 0;
virtual size_t GetCurrentMemoryCapacity() const = 0;
virtual size_t GetMaximumMemoryCapacity() const = 0;
- // The return value will be used in `SourceBuffer::EvictCodedFrames()` so
- // it will evict extra data from the SourceBuffer, to reduce the overall
- // memory the underlying Demuxer implementation may use.
- // NOTE: This is not the best place to pass such information. Since it is a
- // tentative workaround that will be reverted once we confirm the new
- // DecoderBufferAllocator implementation works in production, adding this
- // here allows us to reduce interfaces passed from media to dom.
- virtual size_t GetSourceBufferEvictExtraInBytes() const = 0;
};
class StubDecoderBufferMemoryInfo : public DecoderBufferMemoryInfo {
@@ -45,7 +37,6 @@
size_t GetAllocatedMemory() const override { return 0; }
size_t GetCurrentMemoryCapacity() const override { return 0; }
size_t GetMaximumMemoryCapacity() const override { return 0; }
- size_t GetSourceBufferEvictExtraInBytes() const override { return 0; }
};
} // namespace media
diff --git a/cobalt/media/media_module.cc b/cobalt/media/media_module.cc
index 7a63e4b..11bcbd7 100644
--- a/cobalt/media/media_module.cc
+++ b/cobalt/media/media_module.cc
@@ -183,14 +183,6 @@
} // namespace
-bool MediaModule::SetConfiguration(const std::string& name, int32 value) {
- if (name == "source_buffer_evict_extra_in_bytes" && value >= 0) {
- decoder_buffer_allocator_.SetSourceBufferEvictExtraInBytes(value);
- return true;
- }
- return false;
-}
-
std::unique_ptr<WebMediaPlayer> MediaModule::CreateWebMediaPlayer(
WebMediaPlayerClient* client) {
TRACK_MEMORY_SCOPE("Media");
diff --git a/cobalt/media/media_module.h b/cobalt/media/media_module.h
index 0a90162..e79db38 100644
--- a/cobalt/media/media_module.h
+++ b/cobalt/media/media_module.h
@@ -61,11 +61,6 @@
system_window_(system_window),
resource_provider_(resource_provider) {}
- // Returns true when the setting is set successfully or if the setting has
- // already been set to the expected value. Returns false when the setting is
- // invalid or not set to the expected value.
- bool SetConfiguration(const std::string& name, int32 value);
-
const DecoderBufferAllocator* GetDecoderBufferAllocator() const {
return &decoder_buffer_allocator_;
}
diff --git a/cobalt/network/url_request_context.cc b/cobalt/network/url_request_context.cc
index 34cc482..eb46dcf 100644
--- a/cobalt/network/url_request_context.cc
+++ b/cobalt/network/url_request_context.cc
@@ -181,14 +181,20 @@
} else {
using_http_cache_ = true;
- // TODO: Set max size of cache in Starboard.
- const int cache_size_mb = 24;
+ int max_cache_bytes = 24 * 1024 * 1024;
+#if SB_API_VERSION >= 14
+ max_cache_bytes = kSbMaxSystemPathCacheDirectorySize;
+#endif
+ // Assume the non-http-cache memory in kSbSystemPathCacheDirectory
+ // is less than 1 mb and subtract this from the max_cache_bytes.
+ max_cache_bytes -= (1 << 20);
+
auto http_cache = std::make_unique<net::HttpCache>(
storage_.http_network_session(),
std::make_unique<net::HttpCache::DefaultBackend>(
net::DISK_CACHE, net::CACHE_BACKEND_COBALT,
base::FilePath(std::string(path.data())),
- /* max_bytes */ 1024 * 1024 * cache_size_mb),
+ /* max_bytes */ max_cache_bytes),
true);
if (persistent_settings != nullptr) {
auto cache_enabled = persistent_settings->GetPersistentSettingAsBool(
diff --git a/cobalt/script/BUILD.gn b/cobalt/script/BUILD.gn
index df196e6..fb5b577 100644
--- a/cobalt/script/BUILD.gn
+++ b/cobalt/script/BUILD.gn
@@ -60,6 +60,8 @@
"//cobalt/base",
"//nb",
"//starboard:starboard_headers_only",
+ "//third_party/v8",
+ "//third_party/v8:v8_libplatform",
"//url",
]
}
@@ -74,6 +76,8 @@
":script",
"//base",
"//cobalt/base",
+ "//third_party/v8",
+ "//third_party/v8:v8_libplatform",
]
}
diff --git a/cobalt/script/fake_global_environment.h b/cobalt/script/fake_global_environment.h
index d1d1cfb..51760fa 100644
--- a/cobalt/script/fake_global_environment.h
+++ b/cobalt/script/fake_global_environment.h
@@ -60,6 +60,10 @@
const scoped_refptr<Wrappable>& impl,
const std::string& local_object_name) override {}
ScriptValueFactory* script_value_factory() { return NULL; }
+ v8::Isolate* isolate() const override { return nullptr; }
+ v8::Local<v8::Context> context() const override {
+ return v8::Local<v8::Context>();
+ }
};
} // namespace script
diff --git a/cobalt/script/global_environment.h b/cobalt/script/global_environment.h
index 8681b94..4e569f3 100644
--- a/cobalt/script/global_environment.h
+++ b/cobalt/script/global_environment.h
@@ -27,6 +27,7 @@
#include "cobalt/script/stack_frame.h"
#include "cobalt/script/value_handle.h"
#include "cobalt/script/wrappable.h"
+#include "v8/include/v8.h"
namespace cobalt {
namespace script {
@@ -138,6 +139,9 @@
// should live longer than any ScriptValueFactory pointer.
virtual ScriptValueFactory* script_value_factory() = 0;
+ virtual v8::Isolate* isolate() const = 0;
+ virtual v8::Local<v8::Context> context() const = 0;
+
class ScopedPreventGarbageCollection {
public:
ScopedPreventGarbageCollection(GlobalEnvironment* global_environment,
diff --git a/cobalt/script/v8c/cobalt_platform.h b/cobalt/script/v8c/cobalt_platform.h
index 7c58d8e..c6d4399 100644
--- a/cobalt/script/v8c/cobalt_platform.h
+++ b/cobalt/script/v8c/cobalt_platform.h
@@ -17,6 +17,8 @@
#include <map>
#include <memory>
+#include <utility>
+#include <vector>
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
@@ -60,7 +62,7 @@
return default_platform_->OnCriticalMemoryPressure(length);
}
- int NumberOfWorkerThreads() {
+ int NumberOfWorkerThreads() override {
return default_platform_->NumberOfWorkerThreads();
}
@@ -68,16 +70,17 @@
v8::Isolate* isolate) override;
std::unique_ptr<v8::JobHandle> PostJob(
- v8::TaskPriority priority, std::unique_ptr<v8::JobTask> job_task) override {
- return v8::platform::NewDefaultJobHandle(
- this, priority, std::move(job_task), NumberOfWorkerThreads());
+ v8::TaskPriority priority,
+ std::unique_ptr<v8::JobTask> job_task) override {
+ return v8::platform::NewDefaultJobHandle(
+ this, priority, std::move(job_task), NumberOfWorkerThreads());
}
void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override {
default_platform_->CallOnWorkerThread(std::move(task));
}
- virtual void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task,
- double delay_in_seconds) {
+ void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task,
+ double delay_in_seconds) override {
default_platform_->CallDelayedOnWorkerThread(std::move(task),
delay_in_seconds);
}
diff --git a/cobalt/script/v8c/v8c_global_environment.h b/cobalt/script/v8c/v8c_global_environment.h
index fd4b772..a422397 100644
--- a/cobalt/script/v8c/v8c_global_environment.h
+++ b/cobalt/script/v8c/v8c_global_environment.h
@@ -102,8 +102,8 @@
ScriptValueFactory* script_value_factory() override;
- v8::Isolate* isolate() const { return isolate_; }
- v8::Local<v8::Context> context() const {
+ v8::Isolate* isolate() const override { return isolate_; }
+ v8::Local<v8::Context> context() const override {
return v8::Local<v8::Context>::New(isolate_, context_);
}
diff --git a/cobalt/script/v8c/v8c_value_handle.cc b/cobalt/script/v8c/v8c_value_handle.cc
index 9e33866..d95d653 100644
--- a/cobalt/script/v8c/v8c_value_handle.cc
+++ b/cobalt/script/v8c/v8c_value_handle.cc
@@ -12,10 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <memory>
#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "base/memory/ref_counted.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/entry_scope.h"
@@ -103,5 +108,54 @@
return v8c::ConvertSimpleObjectToMap(value, exception_state);
}
+v8::Isolate* GetIsolate(const ValueHandleHolder& value) {
+ const script::v8c::V8cValueHandleHolder* v8_value_handle_holder =
+ base::polymorphic_downcast<const script::v8c::V8cValueHandleHolder*>(
+ &value);
+ return v8_value_handle_holder->isolate();
+}
+
+v8::Local<v8::Value> GetV8Value(const ValueHandleHolder& value) {
+ const script::v8c::V8cValueHandleHolder* v8_value_handle_holder =
+ base::polymorphic_downcast<const script::v8c::V8cValueHandleHolder*>(
+ &value);
+ return v8_value_handle_holder->v8_value();
+}
+
+ValueHandleHolder* DeserializeScriptValue(v8::Isolate* isolate,
+ const DataBuffer& data_buffer) {
+ v8::EscapableHandleScope scope(isolate);
+ v8::TryCatch try_catch(isolate);
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+
+ v8::ValueDeserializer deserializer(isolate, data_buffer.ptr.get(),
+ data_buffer.size);
+ v8::Local<v8::Value> value;
+ if (!deserializer.ReadValue(context).ToLocal(&value)) {
+ return nullptr;
+ }
+ script::v8c::V8cExceptionState exception_state(isolate);
+ auto* holder = new script::v8c::V8cValueHandleHolder();
+ FromJSValue(isolate, scope.Escape(value), script::v8c::kNoConversionFlags,
+ &exception_state, holder);
+ return holder;
+}
+
+std::unique_ptr<DataBuffer> SerializeScriptValue(
+ const ValueHandleHolder& value) {
+ v8::Isolate* isolate = GetIsolate(value);
+ script::v8c::EntryScope entry_scope(isolate);
+ v8::Local<v8::Value> v8_value = GetV8Value(value);
+ v8::ValueSerializer serializer(isolate);
+ bool wrote_value;
+ if (!serializer.WriteValue(isolate->GetCurrentContext(), v8_value)
+ .To(&wrote_value) ||
+ !wrote_value) {
+ return nullptr;
+ }
+ std::pair<uint8_t*, size_t> pair = serializer.Release();
+ return std::make_unique<DataBuffer>(std::move(pair.first), pair.second);
+}
+
} // namespace script
} // namespace cobalt
diff --git a/cobalt/script/value_handle.h b/cobalt/script/value_handle.h
index ef3b444..f0c8cce 100644
--- a/cobalt/script/value_handle.h
+++ b/cobalt/script/value_handle.h
@@ -15,11 +15,14 @@
#ifndef COBALT_SCRIPT_VALUE_HANDLE_H_
#define COBALT_SCRIPT_VALUE_HANDLE_H_
+#include <memory>
#include <string>
#include <unordered_map>
+#include "base/memory/ref_counted.h"
#include "cobalt/script/exception_state.h"
#include "cobalt/script/script_value.h"
+#include "v8/include/v8.h"
namespace cobalt {
namespace script {
@@ -35,6 +38,18 @@
typedef ScriptValue<ValueHandle> ValueHandleHolder;
+struct BufferDeleter {
+ void operator()(uint8_t* buffer) { SbMemoryDeallocate(buffer); }
+};
+using DataBufferPtr = std::unique_ptr<uint8_t[], BufferDeleter>;
+
+struct DataBuffer {
+ DataBufferPtr ptr;
+ size_t size;
+
+ DataBuffer(uint8_t* ptr, size_t size) : ptr(DataBufferPtr(ptr)), size(size) {}
+};
+
// Converts a "simple" object to a map of the object's properties. "Simple"
// means that the object's property names are strings and its property values
// must be a boolean, number or string. Note that this is implemented on a per
@@ -47,6 +62,13 @@
std::unordered_map<std::string, std::string> ConvertSimpleObjectToMap(
const ValueHandleHolder& value, ExceptionState* exception_state);
+v8::Isolate* GetIsolate(const ValueHandleHolder& value);
+v8::Local<v8::Value> GetV8Value(const ValueHandleHolder& value);
+ValueHandleHolder* DeserializeScriptValue(v8::Isolate* isolate,
+ const DataBuffer& data_buffer);
+std::unique_ptr<DataBuffer> SerializeScriptValue(
+ const ValueHandleHolder& value);
+
} // namespace script
} // namespace cobalt
diff --git a/cobalt/site/docs/communication.md b/cobalt/site/docs/communication.md
index e96bb45..d8d4d40 100644
--- a/cobalt/site/docs/communication.md
+++ b/cobalt/site/docs/communication.md
@@ -10,7 +10,7 @@
If you have identified a bug in Cobalt common code - meaning that you don't
expect that it is related to a platform or port implementation quirk, then you
-should file a bug on our public issue tracker.
+should file a bug on our public issue tracker.
Additionally, if you have specific feature requests, you can also file them on
our public tracker, but they should be very concrete and well-specified. If
@@ -26,7 +26,7 @@
address (say, your work email address).*
-## Asking Techincal Questions
+## Asking Technical Questions
For programming related technical questions about Starboard or Cobalt, we
encourage you to search through and post questions on [Stack
diff --git a/cobalt/site/docs/development/setup-android.md b/cobalt/site/docs/development/setup-android.md
index ac393b0..2c8bdb5 100644
--- a/cobalt/site/docs/development/setup-android.md
+++ b/cobalt/site/docs/development/setup-android.md
@@ -106,10 +106,10 @@
## Basic Build, Install, and Run (command-line based)
1. Complete the Preliminary Setup above
-1. Generate the cobalt.apk by building the "cobalt_deploy" target
+1. Generate the cobalt.apk by building the "cobalt_install" target
```
- ninja -C out/android-x86_gold cobalt_deploy
+ ninja -C out/android-x86_gold cobalt_install
```
Output can be found in the corresponding `out/android-x86_gold` directory.
diff --git a/cobalt/site/docs/development/setup-docker.md b/cobalt/site/docs/development/setup-docker.md
index afc7065..d7b2beb 100644
--- a/cobalt/site/docs/development/setup-docker.md
+++ b/cobalt/site/docs/development/setup-docker.md
@@ -65,9 +65,9 @@
base os image and version. Defaults to Debian 10. `ubuntu:bionic` and
`ubuntu:xenial` are other tested examples.
-**PLATFORM**: Cobalt build platform, passed to GYP
+**PLATFORM**: Cobalt build platform, passed to GN
-**CONFIG**: Cobalt build config, passed to GYP. Defaults to `debug`
+**CONFIG**: Cobalt build config, passed to GN. Defaults to `debug`
**TARGET**: Build target, passed to `ninja`
@@ -90,4 +90,4 @@
```
and try to build Cobalt with the <a
-href="https://cobalt.googlesource.com/cobalt/+/refs/heads/22.lts.stable/src/README.md#building-and-running-the-code">usual gyp / ninja flow.</a>
+href="https://cobalt.googlesource.com/cobalt/+/refs/heads/22.lts.stable/src/README.md#building-and-running-the-code">usual GN / ninja flow.</a>
diff --git a/cobalt/site/docs/development/setup-linux.md b/cobalt/site/docs/development/setup-linux.md
index b296507..8f570d6 100644
--- a/cobalt/site/docs/development/setup-linux.md
+++ b/cobalt/site/docs/development/setup-linux.md
@@ -31,7 +31,7 @@
$ export NVM_DIR=~/.nvm
$ export NODE_VERSION=12.17.0
- $ curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash
+ $ curl --silent -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
$ . $NVM_DIR/nvm.sh \
&& nvm install --lts \
diff --git a/cobalt/speech/sandbox/speech_sandbox.cc b/cobalt/speech/sandbox/speech_sandbox.cc
index 56f46bd..78e3353 100644
--- a/cobalt/speech/sandbox/speech_sandbox.cc
+++ b/cobalt/speech/sandbox/speech_sandbox.cc
@@ -77,7 +77,7 @@
const dom::DOMSettings::Options& dom_settings_options) {
std::unique_ptr<script::EnvironmentSettings> environment_settings(
new dom::DOMSettings(null_debugger_hooks_, kDOMMaxElementDepth, NULL,
- NULL, NULL, NULL, dom_settings_options));
+ NULL, NULL, NULL, NULL, dom_settings_options));
DCHECK(environment_settings);
speech_recognition_ = new SpeechRecognition(environment_settings.get());
diff --git a/cobalt/test/document_loader.h b/cobalt/test/document_loader.h
index bb6ac15..6e6b7da 100644
--- a/cobalt/test/document_loader.h
+++ b/cobalt/test/document_loader.h
@@ -29,6 +29,7 @@
#include "cobalt/dom/dom_parser.h"
#include "cobalt/dom/dom_stat_tracker.h"
#include "cobalt/dom/html_element_context.h"
+#include "cobalt/dom/testing/fake_document.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
#include "cobalt/dom_parser/parser.h"
#include "cobalt/loader/fetcher_factory.h"
@@ -78,7 +79,7 @@
dom::Document::Options options(url);
options.navigation_start_clock = new base::SystemMonotonicClock();
options.viewport_size = cssom::ViewportSize(1920, 1080);
- document_ = new dom::Document(&html_element_context_, options);
+ document_ = new dom::testing::FakeDocument(&html_element_context_, options);
document_->AddObserver(this);
document_loader_.reset(new loader::Loader(
base::Bind(&loader::FetcherFactory::CreateFetcher,
diff --git a/cobalt/watchdog/watchdog.cc b/cobalt/watchdog/watchdog.cc
index a8dd794..0a46c90 100644
--- a/cobalt/watchdog/watchdog.cc
+++ b/cobalt/watchdog/watchdog.cc
@@ -38,14 +38,14 @@
const char kWatchdogViolationsJson[] = "watchdog.json";
// The frequency in microseconds of monitor loops.
const int64_t kWatchdogMonitorFrequency = 1000000;
-// The maximum number of most recent repeated Watchdog violations.
-const int64_t kWatchdogMaxViolations = 100;
+// The maximum number of Watchdog violations.
+const int kWatchdogMaxViolations = 200;
// The minimum number of microseconds between writes.
const int64_t kWatchdogWriteWaitTime = 300000000;
// The maximum number of most recent ping infos.
-const int64_t kWatchdogMaxPingInfos = 20;
+const int kWatchdogMaxPingInfos = 20;
// The maximum length of each ping info.
-const int64_t kWatchdogMaxPingInfoLength = 1024;
+const int kWatchdogMaxPingInfoLength = 128;
// Persistent setting name and default setting for the boolean that controls
// whether or not Watchdog is enabled. When disabled, Watchdog behaves like a
@@ -162,14 +162,13 @@
SB_CHECK(SbMutexAcquire(&(static_cast<Watchdog*>(context))->mutex_) ==
kSbMutexAcquired);
+ // Shutdown
if (!((static_cast<Watchdog*>(context))->is_monitoring_)) {
SB_CHECK(SbMutexRelease(&(static_cast<Watchdog*>(context))->mutex_));
break;
}
- int64_t current_time = SbTimeToPosix(SbTimeGetNow());
SbTimeMonotonic current_monotonic_time = SbTimeGetMonotonicNow();
- base::Value registered_clients(base::Value::Type::LIST);
// Iterates through client map to monitor all registered clients.
bool watchdog_violation = false;
@@ -196,94 +195,7 @@
if (time_delta > client->time_interval_microseconds &&
time_wait > client->time_wait_microseconds) {
watchdog_violation = true;
-
- // Gets violation dictionary with key client name from violations_map_.
- if (static_cast<Watchdog*>(context)->violations_map_ == nullptr)
- InitializeViolationsMap(context);
- base::Value* violation_dict =
- (static_cast<Watchdog*>(context)->violations_map_)
- ->FindKey(client->name);
-
- // Checks if new unique violation.
- bool new_violation = false;
- if (violation_dict == nullptr) {
- new_violation = true;
- } else {
- // Compares against last_pinged_timestamp_microsecond of last
- // violation.
- base::Value* violations = violation_dict->FindKey("violations");
- int index = violations->GetList().size() - 1;
- std::string timestamp_last_pinged_microseconds =
- violations->GetList()[index]
- .FindKey("timestampLastPingedMicroseconds")
- ->GetString();
- if (timestamp_last_pinged_microseconds !=
- std::to_string(client->time_last_pinged_microseconds))
- new_violation = true;
- }
-
- // New unique violation.
- if (new_violation) {
- // Creates new violation.
- base::Value violation(base::Value::Type::DICTIONARY);
- violation.SetKey("pingInfos", client->ping_infos.Clone());
- violation.SetKey("monitorState",
- base::Value(std::string(GetApplicationStateString(
- client->monitor_state))));
- violation.SetKey(
- "timeIntervalMicroseconds",
- base::Value(std::to_string(client->time_interval_microseconds)));
- violation.SetKey(
- "timeWaitMicroseconds",
- base::Value(std::to_string(client->time_wait_microseconds)));
- violation.SetKey("timestampRegisteredMicroseconds",
- base::Value(std::to_string(
- client->time_registered_microseconds)));
- violation.SetKey("timestampLastPingedMicroseconds",
- base::Value(std::to_string(
- client->time_last_pinged_microseconds)));
- violation.SetKey("timestampViolationMicroseconds",
- base::Value(std::to_string(current_time)));
- violation.SetKey(
- "violationDurationMicroseconds",
- base::Value(std::to_string(time_delta -
- client->time_interval_microseconds)));
- if (registered_clients.GetList().empty()) {
- for (auto& it : static_cast<Watchdog*>(context)->client_map_) {
- registered_clients.GetList().emplace_back(base::Value(it.first));
- }
- }
- violation.SetKey("registeredClients", registered_clients.Clone());
-
- // Adds new violation to violations_map_.
- if (violation_dict == nullptr) {
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("description", base::Value(client->description));
- base::Value list(base::Value::Type::LIST);
- list.GetList().emplace_back(violation.Clone());
- dict.SetKey("violations", list.Clone());
- (static_cast<Watchdog*>(context)->violations_map_)
- ->SetKey(client->name, dict.Clone());
- } else {
- base::Value* violations = violation_dict->FindKey("violations");
- violations->GetList().emplace_back(violation.Clone());
- if (violations->GetList().size() > kWatchdogMaxViolations)
- violations->GetList().erase(violations->GetList().begin());
- }
- // Consecutive non-unique violation.
- } else {
- // Updates consecutive violation in violations_map_.
- base::Value* violations = violation_dict->FindKey("violations");
- int index = violations->GetList().size() - 1;
- int64_t violation_duration =
- std::stoll(violations->GetList()[index]
- .FindKey("violationDurationMicroseconds")
- ->GetString());
- violations->GetList()[index].SetKey(
- "violationDurationMicroseconds",
- base::Value(std::to_string(violation_duration + time_delta)));
- }
- static_cast<Watchdog*>(context)->pending_write_ = true;
+ UpdateViolationsMap(context, client, time_delta);
// Resets time last updated.
client->time_last_updated_monotonic_microseconds =
@@ -300,9 +212,103 @@
return nullptr;
}
+void Watchdog::UpdateViolationsMap(void* context, Client* client,
+ SbTimeMonotonic time_delta) {
+ // Gets violation dictionary with key client name from violations_map_.
+ if (static_cast<Watchdog*>(context)->violations_map_ == nullptr)
+ InitializeViolationsMap(context);
+ base::Value* violation_dict =
+ (static_cast<Watchdog*>(context)->violations_map_)->FindKey(client->name);
+
+ // Checks if new unique violation.
+ bool new_violation = false;
+ if (violation_dict == nullptr) {
+ new_violation = true;
+ } else {
+ // Compares against last_pinged_timestamp_microsecond of last violation.
+ base::Value* violations = violation_dict->FindKey("violations");
+ int last_index = violations->GetList().size() - 1;
+ std::string timestamp_last_pinged_milliseconds =
+ violations->GetList()[last_index]
+ .FindKey("timestampLastPingedMilliseconds")
+ ->GetString();
+ if (timestamp_last_pinged_milliseconds !=
+ std::to_string(client->time_last_pinged_microseconds / 1000))
+ new_violation = true;
+ }
+
+ // New unique violation.
+ if (new_violation) {
+ // Creates new violation.
+ base::Value violation(base::Value::Type::DICTIONARY);
+ violation.SetKey("pingInfos", client->ping_infos.Clone());
+ violation.SetKey("monitorState",
+ base::Value(std::string(
+ GetApplicationStateString(client->monitor_state))));
+ violation.SetKey(
+ "timeIntervalMilliseconds",
+ base::Value(std::to_string(client->time_interval_microseconds / 1000)));
+ violation.SetKey(
+ "timeWaitMilliseconds",
+ base::Value(std::to_string(client->time_wait_microseconds / 1000)));
+ violation.SetKey("timestampRegisteredMilliseconds",
+ base::Value(std::to_string(
+ client->time_registered_microseconds / 1000)));
+ violation.SetKey("timestampLastPingedMilliseconds",
+ base::Value(std::to_string(
+ client->time_last_pinged_microseconds / 1000)));
+ violation.SetKey(
+ "timestampViolationMilliseconds",
+ base::Value(std::to_string(SbTimeToPosix(SbTimeGetNow()) / 1000)));
+ violation.SetKey(
+ "violationDurationMilliseconds",
+ base::Value(std::to_string(
+ (time_delta - client->time_interval_microseconds) / 1000)));
+ base::Value registered_clients(base::Value::Type::LIST);
+ for (auto& it : static_cast<Watchdog*>(context)->client_map_) {
+ registered_clients.GetList().emplace_back(base::Value(it.first));
+ }
+ violation.SetKey("registeredClients", registered_clients.Clone());
+
+ // Adds new violation to violations_map_.
+ if (violation_dict == nullptr) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetKey("description", base::Value(client->description));
+ base::Value list(base::Value::Type::LIST);
+ list.GetList().emplace_back(violation.Clone());
+ dict.SetKey("violations", list.Clone());
+ (static_cast<Watchdog*>(context)->violations_map_)
+ ->SetKey(client->name, dict.Clone());
+ } else {
+ base::Value* violations = violation_dict->FindKey("violations");
+ violations->GetList().emplace_back(violation.Clone());
+ }
+ static_cast<Watchdog*>(context)->violations_count_++;
+ if (static_cast<Watchdog*>(context)->violations_count_ >
+ kWatchdogMaxViolations)
+ EvictWatchdogViolation(context);
+ // Consecutive non-unique violation.
+ } else {
+ // Updates consecutive violation in violations_map_.
+ base::Value* violations = violation_dict->FindKey("violations");
+ int last_index = violations->GetList().size() - 1;
+ int64_t violation_duration =
+ std::stoll(violations->GetList()[last_index]
+ .FindKey("violationDurationMilliseconds")
+ ->GetString());
+ violations->GetList()[last_index].SetKey(
+ "violationDurationMilliseconds",
+ base::Value(std::to_string(violation_duration + (time_delta / 1000))));
+ }
+
+ static_cast<Watchdog*>(context)->pending_write_ = true;
+}
+
void Watchdog::InitializeViolationsMap(void* context) {
// Loads the previous Watchdog violations file containing violations before
// app start, if it exists, to populate violations_map_.
+ static_cast<Watchdog*>(context)->violations_count_ = 0;
+
starboard::ScopedFile read_file(
(static_cast<Watchdog*>(context)->GetWatchdogFilePath()).c_str(),
kSbFileOpenOnly | kSbFileRead);
@@ -314,13 +320,56 @@
static_cast<Watchdog*>(context)->violations_map_ =
base::JSONReader::Read(watchdog_json);
}
+
if (static_cast<Watchdog*>(context)->violations_map_ == nullptr) {
SB_LOG(INFO) << "[Watchdog] No previous violations JSON.";
static_cast<Watchdog*>(context)->violations_map_ =
std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
+ } else {
+ for (const auto& it :
+ (static_cast<Watchdog*>(context)->violations_map_)->DictItems()) {
+ base::Value& violation_dict = it.second;
+ base::Value* violations = violation_dict.FindKey("violations");
+ static_cast<Watchdog*>(context)->violations_count_ +=
+ violations->GetList().size();
+ }
}
}
+void Watchdog::EvictWatchdogViolation(void* context) {
+ // Evicts a violation in violations_map_ prioritizing first the most frequent
+ // violations (largest violations count by client name) and second the oldest
+ // violation.
+ std::string evicted_name = "";
+ int evicted_count = 0;
+ int64_t evicted_timestamp = 0;
+
+ for (const auto& it :
+ (static_cast<Watchdog*>(context)->violations_map_)->DictItems()) {
+ std::string name = it.first;
+ base::Value& violation_dict = it.second;
+ base::Value* violations = violation_dict.FindKey("violations");
+ int count = violations->GetList().size();
+ int64_t timestamp =
+ std::stoll(violations->GetList()[0]
+ .FindKey("timestampViolationMilliseconds")
+ ->GetString());
+
+ if ((evicted_name == "") || (count > evicted_count) ||
+ ((count == evicted_count) && (timestamp < evicted_timestamp))) {
+ evicted_name = name;
+ evicted_count = count;
+ evicted_timestamp = timestamp;
+ }
+ }
+
+ base::Value* violation_dict =
+ (static_cast<Watchdog*>(context)->violations_map_)->FindKey(evicted_name);
+ base::Value* violations = violation_dict->FindKey("violations");
+ violations->GetList().erase(violations->GetList().begin());
+ static_cast<Watchdog*>(context)->violations_count_--;
+}
+
void Watchdog::MaybeWriteWatchdogViolations(void* context) {
if (SbTimeGetMonotonicNow() >
static_cast<Watchdog*>(context)->time_last_written_microseconds_ +
@@ -345,9 +394,9 @@
if (is_disabled_) return true;
// Validates parameters.
- if (time_interval < 1000000 || time_wait < 0) {
+ if (time_interval < kWatchdogMonitorFrequency || time_wait < 0) {
SB_DLOG(ERROR) << "[Watchdog] Unable to Register: " << name;
- if (time_interval < 1000000) {
+ if (time_interval < kWatchdogMonitorFrequency) {
SB_DLOG(ERROR) << "[Watchdog] Time interval less than min: "
<< kWatchdogMonitorFrequency;
} else {
@@ -450,8 +499,8 @@
if (info != "") {
// Creates new ping_info.
base::Value ping_info(base::Value::Type::DICTIONARY);
- ping_info.SetKey("timestampMicroseconds",
- base::Value(std::to_string(current_time)));
+ ping_info.SetKey("timestampMilliseconds",
+ base::Value(std::to_string(current_time / 1000)));
ping_info.SetKey("info", base::Value(info));
client->ping_infos.GetList().emplace_back(ping_info.Clone());
@@ -491,6 +540,7 @@
base::DictionaryValue** dict = nullptr;
violations_map_->GetAsDictionary(dict);
if (dict) (*dict)->Clear();
+ violations_count_ = 0;
}
starboard::SbFileDeleteRecursive(GetWatchdogFilePath().c_str(), true);
SB_LOG(INFO) << "[Watchdog] Reading violations:\n" << watchdog_json;
diff --git a/cobalt/watchdog/watchdog.h b/cobalt/watchdog/watchdog.h
index 7ab5d96..1532f79 100644
--- a/cobalt/watchdog/watchdog.h
+++ b/cobalt/watchdog/watchdog.h
@@ -97,7 +97,10 @@
std::string GetWatchdogFilePath();
void WriteWatchdogViolations();
static void* Monitor(void* context);
+ static void UpdateViolationsMap(void* context, Client* client,
+ SbTimeMonotonic time_delta);
static void InitializeViolationsMap(void* context);
+ static void EvictWatchdogViolation(void* context);
static void MaybeWriteWatchdogViolations(void* context);
static void MaybeTriggerCrash(void* context);
@@ -128,6 +131,8 @@
std::unordered_map<std::string, std::unique_ptr<Client>> client_map_;
// Dictionary of lists of Watchdog violations represented as dictionaries.
std::unique_ptr<base::Value> violations_map_;
+ // Number of violations in violations_map_;
+ int violations_count_;
// Monitor thread.
SbThread watchdog_thread_;
// Flag to stop monitor thread.
diff --git a/cobalt/web/agent.cc b/cobalt/web/agent.cc
index d017e6d..f52e113 100644
--- a/cobalt/web/agent.cc
+++ b/cobalt/web/agent.cc
@@ -18,6 +18,7 @@
#include <memory>
#include <utility>
+#include "base/observer_list.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/loader/fetcher_factory.h"
#include "cobalt/loader/script_loader_factory.h"
@@ -51,6 +52,11 @@
explicit Impl(const Agent::Options& options);
virtual ~Impl();
+ void AddEnvironmentSettingsChangeObserver(
+ EnvironmentSettingsChangeObserver* observer) final;
+ void RemoveEnvironmentSettingsChangeObserver(
+ EnvironmentSettingsChangeObserver* observer) final;
+
// Context
//
void set_message_loop(base::MessageLoop* message_loop) {
@@ -88,6 +94,9 @@
const std::string& name() const final { return name_; };
void setup_environment_settings(
EnvironmentSettings* environment_settings) final {
+ for (auto& observer : environment_settings_change_observers_) {
+ observer.OnEnvironmentSettingsChanged(!!environment_settings);
+ }
environment_settings_.reset(environment_settings);
if (environment_settings_) environment_settings_->set_context(this);
}
@@ -208,6 +217,9 @@
scoped_refptr<worker::ServiceWorkerObject> active_service_worker_;
scoped_refptr<worker::ServiceWorkerRegistrationObject>
containing_service_worker_registration_;
+
+ base::ObserverList<Context::EnvironmentSettingsChangeObserver>::Unchecked
+ environment_settings_change_observers_;
};
Impl::Impl(const Agent::Options& options) : name_(options.name) {
@@ -269,6 +281,7 @@
}
setup_environment_settings(nullptr);
+ environment_settings_change_observers_.Clear();
blob_registry_.reset();
script_runner_.reset();
execution_state_.reset();
@@ -280,6 +293,16 @@
Impl::~Impl() { ShutDownJavaScriptEngine(); }
+void Impl::AddEnvironmentSettingsChangeObserver(
+ Context::EnvironmentSettingsChangeObserver* observer) {
+ environment_settings_change_observers_.AddObserver(observer);
+}
+
+void Impl::RemoveEnvironmentSettingsChangeObserver(
+ Context::EnvironmentSettingsChangeObserver* observer) {
+ environment_settings_change_observers_.RemoveObserver(observer);
+}
+
void Impl::InjectGlobalObjectAttributes(
const Agent::Options::InjectedGlobalObjectAttributes& attributes) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/cobalt/web/context.h b/cobalt/web/context.h
index f48182f..360dbe2 100644
--- a/cobalt/web/context.h
+++ b/cobalt/web/context.h
@@ -44,6 +44,15 @@
class Context {
public:
virtual ~Context() {}
+
+ class EnvironmentSettingsChangeObserver {
+ public:
+ virtual void OnEnvironmentSettingsChanged(bool context_valid) = 0;
+
+ protected:
+ virtual ~EnvironmentSettingsChangeObserver() = default;
+ };
+
virtual base::MessageLoop* message_loop() const = 0;
virtual void ShutDownJavaScriptEngine() = 0;
virtual loader::FetcherFactory* fetcher_factory() const = 0;
@@ -82,6 +91,11 @@
virtual std::string GetUserAgent() const = 0;
virtual std::string GetPreferredLanguage() const = 0;
+ virtual void AddEnvironmentSettingsChangeObserver(
+ EnvironmentSettingsChangeObserver* observer) = 0;
+ virtual void RemoveEnvironmentSettingsChangeObserver(
+ EnvironmentSettingsChangeObserver* observer) = 0;
+
// https://w3c.github.io/ServiceWorker/#dfn-control
virtual bool is_controlled_by(worker::ServiceWorkerObject* worker) const = 0;
diff --git a/cobalt/web/csp_violation_reporter.cc b/cobalt/web/csp_violation_reporter.cc
index 268ac95..2cb1951 100644
--- a/cobalt/web/csp_violation_reporter.cc
+++ b/cobalt/web/csp_violation_reporter.cc
@@ -21,7 +21,6 @@
#include "base/json/json_writer.h"
#include "base/values.h"
#include "cobalt/dom/document.h"
-#include "cobalt/dom/html_element_context.h"
#include "cobalt/network/net_poster.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/web/security_policy_violation_event.h"
@@ -83,12 +82,12 @@
}
void GatherSecurityPolicyViolationEventData(
- const dom::Document* document, const csp::ViolationInfo& violation_info,
+ WindowOrWorkerGlobalScope* global, const csp::ViolationInfo& violation_info,
ViolationEvent* event_data) {
- event_data->document_uri =
- StripUrlForUseInReport(document->url_as_gurl(), document->url_as_gurl());
- event_data->blocked_uri = StripUrlForUseInReport(document->url_as_gurl(),
- violation_info.blocked_url);
+ GURL base_url = global->environment_settings()->base_url();
+ event_data->document_uri = StripUrlForUseInReport(base_url, base_url);
+ event_data->blocked_uri =
+ StripUrlForUseInReport(base_url, violation_info.blocked_url);
// TODO: Implement Document referrer, if needed.
event_data->referrer = "";
event_data->violated_directive = violation_info.directive_text;
@@ -96,14 +95,14 @@
event_data->original_policy = violation_info.header;
script::GlobalEnvironment* global_environment =
- document->html_element_context()->script_runner()->GetGlobalEnvironment();
+ global->environment_settings()->context()->global_environment();
const std::vector<script::StackFrame>& stack_trace =
global_environment->GetStackTrace(1);
if (stack_trace.size() > 0) {
event_data->line_number = stack_trace[0].line_number;
event_data->column_number = stack_trace[0].column_number;
- event_data->source_file = StripUrlForUseInReport(
- document->url_as_gurl(), GURL(stack_trace[0].source_url));
+ event_data->source_file =
+ StripUrlForUseInReport(base_url, GURL(stack_trace[0].source_url));
}
// TODO: Set the status code if the document origin is non-secure.
@@ -113,14 +112,15 @@
} // namespace
CspViolationReporter::CspViolationReporter(
- dom::Document* document, const network_bridge::PostSender& post_sender)
+ web::WindowOrWorkerGlobalScope* global,
+ const network_bridge::PostSender& post_sender)
: post_sender_(post_sender),
message_loop_(base::MessageLoop::current()),
- document_(document) {}
+ global_(global) {}
CspViolationReporter::~CspViolationReporter() {}
-// https://www.w3.org/TR/CSP2/#violation-reports
+// https://www.w3.org/TR/CSP3/#report-violation
void CspViolationReporter::Report(const csp::ViolationInfo& violation_info) {
DCHECK(message_loop_);
if (!message_loop_->task_runner()->BelongsToCurrentThread()) {
@@ -132,14 +132,24 @@
LOG(INFO) << violation_info.console_message;
ViolationEvent violation_data;
- GatherSecurityPolicyViolationEventData(document_, violation_info,
+ GatherSecurityPolicyViolationEventData(global_, violation_info,
&violation_data);
- document_->DispatchEvent(new SecurityPolicyViolationEvent(
- violation_data.document_uri, violation_data.referrer,
- violation_data.blocked_uri, violation_data.violated_directive,
- violation_data.effective_directive, violation_data.original_policy,
- violation_data.source_file, violation_data.status_code,
- violation_data.line_number, violation_data.column_number));
+ if (global_->IsWindow()) {
+ global_->AsWindow()->document()->DispatchEvent(
+ new SecurityPolicyViolationEvent(
+ violation_data.document_uri, violation_data.referrer,
+ violation_data.blocked_uri, violation_data.violated_directive,
+ violation_data.effective_directive, violation_data.original_policy,
+ violation_data.source_file, violation_data.status_code,
+ violation_data.line_number, violation_data.column_number));
+ } else {
+ global_->DispatchEvent(new SecurityPolicyViolationEvent(
+ violation_data.document_uri, violation_data.referrer,
+ violation_data.blocked_uri, violation_data.violated_directive,
+ violation_data.effective_directive, violation_data.original_policy,
+ violation_data.source_file, violation_data.status_code,
+ violation_data.line_number, violation_data.column_number));
+ }
if (violation_info.endpoints.empty() || post_sender_.is_null()) {
return;
@@ -190,7 +200,7 @@
return;
}
violation_reports_sent_.insert(report_hash);
- const GURL& origin_url = document_->url_as_gurl();
+ const GURL& origin_url = global_->environment_settings()->base_url();
for (std::vector<std::string>::const_iterator it = endpoints.begin();
it != endpoints.end(); ++it) {
GURL resolved_endpoint = origin_url.Resolve(*it);
diff --git a/cobalt/web/csp_violation_reporter.h b/cobalt/web/csp_violation_reporter.h
index c7aa1a5..b2b9a98 100644
--- a/cobalt/web/csp_violation_reporter.h
+++ b/cobalt/web/csp_violation_reporter.h
@@ -25,11 +25,8 @@
#include "cobalt/network_bridge/net_poster.h"
namespace cobalt {
-namespace dom {
-class Document;
-} // namespace dom
-
namespace web {
+class WindowOrWorkerGlobalScope;
// Responsible for reporting CSP violations, i.e. posting JSON
// reports to any reporting endpoints described by the policy.
@@ -37,12 +34,12 @@
// and passed in to its constructor. Generally it should not be called directly.
class CspViolationReporter {
public:
- CspViolationReporter(dom::Document* document,
+ CspViolationReporter(WindowOrWorkerGlobalScope* global,
const network_bridge::PostSender& post_sender);
virtual ~CspViolationReporter();
// Used as a callback from ContentSecurityPolicy to dispatch security
- // violation events on the Document and send the reports.
+ // violation events on the Document or Global Object and send the reports.
// Report() can be called from any thread and it will re-post itself
// to the message loop it was created on, which should be the Document's
// message loop.
@@ -63,7 +60,7 @@
// We must send violations on the document's message loop.
base::MessageLoop* message_loop_;
- dom::Document* document_;
+ WindowOrWorkerGlobalScope* global_;
DISALLOW_COPY_AND_ASSIGN(CspViolationReporter);
};
diff --git a/cobalt/web/message_event.cc b/cobalt/web/message_event.cc
index 0f153b6..a6e8888 100644
--- a/cobalt/web/message_event.cc
+++ b/cobalt/web/message_event.cc
@@ -20,15 +20,20 @@
#include "base/basictypes.h"
#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/web/context.h"
#include "cobalt/web/environment_settings.h"
#include "starboard/common/string.h"
+#include "starboard/memory.h"
+#include "v8/include/v8.h"
namespace {
-const char* const kResponseTypes[] = {"text", "blob", "arraybuffer"};
+const char* const kResponseTypes[] = {"text", "blob", "arraybuffer", "any"};
COMPILE_ASSERT(arraysize(kResponseTypes) ==
- cobalt::web::MessageEvent::kResponseTypeCodeMax,
+ cobalt::web::MessageEvent::kResponseTypeMax,
enum_and_array_size_mismatch);
} // namespace
@@ -36,67 +41,73 @@
namespace cobalt {
namespace web {
+// static
std::string MessageEvent::GetResponseTypeAsString(
- const MessageEvent::ResponseTypeCode code) {
- DCHECK_LT(code, kResponseTypeCodeMax);
- if ((code >= kText) && (code < kResponseTypeCodeMax)) {
- return kResponseTypes[code];
- }
- return std::string();
+ const MessageEvent::ResponseType response_type) {
+ DCHECK_GE(response_type, kText);
+ DCHECK_LT(response_type, kResponseTypeMax);
+ return kResponseTypes[response_type];
}
-MessageEvent::ResponseTypeCode MessageEvent::GetResponseTypeCode(
+// static
+MessageEvent::ResponseType MessageEvent::GetResponseType(
base::StringPiece to_match) {
for (std::size_t i = 0; i != arraysize(kResponseTypes); ++i) {
if (strncmp(kResponseTypes[i], to_match.data(), to_match.size()) == 0) {
- return MessageEvent::ResponseTypeCode(i);
+ return MessageEvent::ResponseType(i);
}
}
- return kResponseTypeCodeMax;
+ return kResponseTypeMax;
}
-MessageEvent::ResponseType MessageEvent::data(
+MessageEvent::Response MessageEvent::data(
script::EnvironmentSettings* settings) const {
- const char* data_pointer = NULL;
- int data_length = 0;
- if (data_) {
- data_pointer = data_->data();
- data_length = data_->size();
+ if (!data_ && !data_io_buffer_) {
+ return Response("");
}
- auto* global_environment =
- settings ? base::polymorphic_downcast<web::EnvironmentSettings*>(settings)
- ->context()
- ->global_environment()
- : nullptr;
- script::Handle<script::ArrayBuffer> response_buffer;
- if (response_type_ != kText) {
+ script::GlobalEnvironment* global_environment = nullptr;
+ if (response_type_ == kBlob || response_type_ == kArrayBuffer ||
+ response_type_ == kAny) {
+ DCHECK(settings);
+ global_environment =
+ base::polymorphic_downcast<web::EnvironmentSettings*>(settings)
+ ->context()
+ ->global_environment();
DCHECK(global_environment);
- auto buffer_copy =
- script::ArrayBuffer::New(global_environment, data_pointer, data_length);
- response_buffer = std::move(buffer_copy);
}
switch (response_type_) {
case kText: {
// TODO: Find a way to remove two copies of data here.
- std::string string_response(data_pointer, data_length);
- return ResponseType(string_response);
+ std::string string_response(data_io_buffer_->data(),
+ data_io_buffer_->size());
+ return Response(string_response);
}
- case kBlob: {
- DCHECK(settings);
- scoped_refptr<web::Blob> blob = new web::Blob(settings, response_buffer);
- return ResponseType(blob);
- }
+ case kBlob:
case kArrayBuffer: {
- return ResponseType(response_buffer);
+ auto buffer_copy = script::ArrayBuffer::New(
+ global_environment, data_io_buffer_->data(), data_io_buffer_->size());
+ script::Handle<script::ArrayBuffer> response_buffer =
+ std::move(buffer_copy);
+ if (response_type_ == kBlob) {
+ DCHECK(settings);
+ scoped_refptr<web::Blob> blob =
+ new web::Blob(settings, response_buffer);
+ return Response(blob);
+ }
+ return Response(response_buffer);
}
- case kResponseTypeCodeMax:
+ case kAny: {
+ v8::Isolate* isolate = global_environment->isolate();
+ script::v8c::EntryScope entry_scope(isolate);
+ return Response(script::Handle<script::ValueHandle>(
+ std::move(script::DeserializeScriptValue(isolate, *data_))));
+ }
+ default:
NOTREACHED() << "Invalid response type.";
- return ResponseType();
+ return Response("");
}
-
- return ResponseType();
}
} // namespace web
diff --git a/cobalt/web/message_event.h b/cobalt/web/message_event.h
index 88a838a..b39a198 100644
--- a/cobalt/web/message_event.h
+++ b/cobalt/web/message_event.h
@@ -16,58 +16,63 @@
#ifndef COBALT_WEB_MESSAGE_EVENT_H_
#define COBALT_WEB_MESSAGE_EVENT_H_
+#include <memory>
#include <string>
+#include <utility>
#include "base/memory/ref_counted.h"
#include "base/strings/string_piece.h"
#include "cobalt/base/token.h"
#include "cobalt/script/array_buffer.h"
#include "cobalt/script/union_type.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/script/wrappable.h"
#include "cobalt/web/blob.h"
#include "cobalt/web/event.h"
#include "cobalt/web/message_event_init.h"
#include "net/base/io_buffer.h"
+#include "v8/include/v8.h"
namespace cobalt {
namespace web {
class MessageEvent : public web::Event {
public:
- typedef script::UnionType3<std::string, scoped_refptr<web::Blob>,
- script::Handle<script::ArrayBuffer> >
- ResponseType;
- // These response codes are ordered in the likelihood of being used.
+ typedef script::UnionType4<std::string, scoped_refptr<web::Blob>,
+ script::Handle<script::ArrayBuffer>,
+ script::Handle<script::ValueHandle>>
+ Response;
+ // These response types are ordered in the likelihood of being used.
// Keeping them in expected order will help make code faster.
- enum ResponseTypeCode { kText, kBlob, kArrayBuffer, kResponseTypeCodeMax };
-
- explicit MessageEvent(const std::string& type) : Event(type) {}
- MessageEvent(const std::string& type, const web::MessageEventInit& init_dict)
- : Event(type, init_dict),
- data_(new net::IOBufferWithSize(init_dict.data().size())) {
- init_dict.data().copy(data_->data(), data_->size());
- }
-
- MessageEvent(base::Token type, ResponseTypeCode response_type,
- const scoped_refptr<net::IOBufferWithSize>& data)
- : Event(type), response_type_(response_type), data_(data) {}
+ enum ResponseType { kText, kBlob, kArrayBuffer, kAny, kResponseTypeMax };
// Creates an event with its "initialized flag" unset.
explicit MessageEvent(UninitializedFlag uninitialized_flag)
: Event(uninitialized_flag) {}
- ResponseType data(script::EnvironmentSettings* settings = nullptr) const;
+ explicit MessageEvent(const std::string& type) : Event(type) {}
+ MessageEvent(base::Token type, std::unique_ptr<script::DataBuffer> data)
+ : Event(type), response_type_(kAny), data_(std::move(data)) {}
+ MessageEvent(base::Token type, ResponseType response_type,
+ const scoped_refptr<net::IOBufferWithSize>& data)
+ : Event(type), response_type_(response_type), data_io_buffer_(data) {}
+ MessageEvent(const std::string& type, const web::MessageEventInit& init_dict)
+ : Event(type, init_dict),
+ response_type_(kAny),
+ data_(script::SerializeScriptValue(*(init_dict.data()))) {}
+
+ Response data(script::EnvironmentSettings* settings = nullptr) const;
// These helper functions are custom, and not in any spec.
- static std::string GetResponseTypeAsString(const ResponseTypeCode code);
- // This function returns kResponseTypeCodeMax if no match is found.
- static ResponseTypeCode GetResponseTypeCode(base::StringPiece to_match);
+ static std::string GetResponseTypeAsString(const ResponseType response_type);
+ static MessageEvent::ResponseType GetResponseType(base::StringPiece to_match);
DEFINE_WRAPPABLE_TYPE(MessageEvent)
private:
- ResponseTypeCode response_type_ = kText;
- scoped_refptr<net::IOBufferWithSize> data_;
+ ResponseType response_type_ = kText;
+ scoped_refptr<net::IOBufferWithSize> data_io_buffer_;
+ std::unique_ptr<script::DataBuffer> data_;
};
} // namespace web
diff --git a/cobalt/web/message_event.idl b/cobalt/web/message_event.idl
index 9f722bd..0e15ab7 100644
--- a/cobalt/web/message_event.idl
+++ b/cobalt/web/message_event.idl
@@ -19,5 +19,5 @@
Exposed = (Window,Worker),
Constructor(DOMString type, optional MessageEventInit eventInitDict)
] interface MessageEvent : Event {
- [CallWith = EnvironmentSettings] readonly attribute DOMString data;
+ [CallWith = EnvironmentSettings] readonly attribute any data;
};
diff --git a/cobalt/web/message_event_init.idl b/cobalt/web/message_event_init.idl
index 9de818e..9ccf914 100644
--- a/cobalt/web/message_event_init.idl
+++ b/cobalt/web/message_event_init.idl
@@ -15,5 +15,5 @@
// https://www.w3.org/TR/html50/webappapis.html#erroreventinit
dictionary MessageEventInit : EventInit {
- DOMString data = "";
+ any data = null;
};
diff --git a/cobalt/web/message_event_test.cc b/cobalt/web/message_event_test.cc
index 4feaab2..d8f6d6d 100644
--- a/cobalt/web/message_event_test.cc
+++ b/cobalt/web/message_event_test.cc
@@ -20,6 +20,8 @@
#include "base/bind.h"
#include "base/logging.h"
#include "cobalt/dom/testing/test_with_javascript.h"
+#include "cobalt/script/v8c/entry_scope.h"
+#include "cobalt/script/value_handle.h"
#include "cobalt/web/message_event_init.h"
#include "cobalt/web/testing/gtest_workarounds.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -46,14 +48,17 @@
EXPECT_FALSE(event->IsBeingDispatched());
EXPECT_FALSE(event->propagation_stopped());
EXPECT_FALSE(event->immediate_propagation_stopped());
- MessageEvent::ResponseType event_data = event->data();
+ MessageEvent::Response event_data = event->data();
EXPECT_TRUE(event_data.IsType<std::string>());
EXPECT_EQ("", event_data.AsType<std::string>());
}
-TEST(MessageEventTest, ConstructorWithEventTypeAndDefaultInitDict) {
+TEST_F(MessageEventTestWithJavaScript,
+ ConstructorWithEventTypeAndDefaultInitDict) {
MessageEventInit init;
- init.set_data("data_value");
+ base::Optional<script::ValueHandleHolder::Reference> reference;
+ EvaluateScript("'data_value'", window(), &reference);
+ init.set_data(&(reference->referenced_value()));
scoped_refptr<MessageEvent> event = new MessageEvent("mytestevent", init);
EXPECT_EQ("mytestevent", event->type());
@@ -66,33 +71,34 @@
EXPECT_FALSE(event->IsBeingDispatched());
EXPECT_FALSE(event->propagation_stopped());
EXPECT_FALSE(event->immediate_propagation_stopped());
- MessageEvent::ResponseType event_data = event->data();
- EXPECT_TRUE(event_data.IsType<std::string>());
- EXPECT_EQ("data_value", event_data.AsType<std::string>());
+ MessageEvent::Response event_data =
+ event->data(window()->environment_settings());
+ EXPECT_TRUE(event_data.IsType<script::Handle<script::ValueHandle>>());
+ auto script_value =
+ event_data.AsType<script::Handle<script::ValueHandle>>().GetScriptValue();
+ auto* isolate = script::GetIsolate(*script_value);
+ script::v8c::EntryScope entry_scope(isolate);
+ v8::Local<v8::Value> v8_value = script::GetV8Value(*script_value);
+ std::string actual =
+ *(v8::String::Utf8Value(isolate, v8_value.As<v8::String>()));
+ EXPECT_EQ("data_value", actual);
}
TEST_F(MessageEventTestWithJavaScript,
ConstructorWithEventTypeAndErrorInitDict) {
std::string result;
- bool success = EvaluateScript(
- "var event = new MessageEvent('dog', "
- " {'cancelable':true, "
- " 'data':'data_value'});"
- "if (event.type == 'dog' &&"
- " event.bubbles == false &&"
- " event.cancelable == true &&"
- " event.data == 'data_value') "
- " event.data;",
- &result);
+ EXPECT_TRUE(
+ EvaluateScript("var event = new MessageEvent('dog', "
+ " {'cancelable':true, "
+ " 'data':'data_value'});"
+ "if (event.type == 'dog' &&"
+ " event.bubbles == false &&"
+ " event.cancelable == true &&"
+ " event.data == 'data_value') "
+ " event.data;",
+ &result))
+ << "Failed to evaluate script.";
EXPECT_EQ("data_value", result);
-
- if (!success) {
- DLOG(ERROR) << "Failed to evaluate test: "
- << "\"" << result << "\"";
- } else {
- LOG(INFO) << "Test result : "
- << "\"" << result << "\"";
- }
}
} // namespace web
diff --git a/cobalt/web/message_port.cc b/cobalt/web/message_port.cc
index bc56140..519e682 100644
--- a/cobalt/web/message_port.cc
+++ b/cobalt/web/message_port.cc
@@ -14,7 +14,9 @@
#include "cobalt/web/message_port.h"
+#include <memory>
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -33,35 +35,63 @@
namespace web {
MessagePort::MessagePort(web::EventTarget* event_target)
- : event_target_(event_target) {}
+ : event_target_(event_target) {
+ if (!event_target_) {
+ return;
+ }
+ Context* context = event_target_->environment_settings()->context();
+ base::MessageLoop* message_loop = context->message_loop();
+ if (!message_loop) {
+ return;
+ }
+ message_loop->task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&Context::AddEnvironmentSettingsChangeObserver,
+ base::Unretained(context), base::Unretained(this)));
+ remove_environment_settings_change_observer_ =
+ base::BindOnce(&Context::RemoveEnvironmentSettingsChangeObserver,
+ base::Unretained(context), base::Unretained(this));
+}
-MessagePort::~MessagePort() { event_target_ = nullptr; }
+MessagePort::~MessagePort() { Close(); }
-void MessagePort::PostMessage(const std::string& messages) {
+void MessagePort::Close() {
+ if (!event_target_) {
+ return;
+ }
+ if (remove_environment_settings_change_observer_) {
+ std::move(remove_environment_settings_change_observer_).Run();
+ }
+ event_target_ = nullptr;
+}
+
+void MessagePort::PostMessage(const script::ValueHandleHolder& message) {
+ PostMessageSerialized(std::move(SerializeScriptValue(message)));
+}
+
+void MessagePort::PostMessageSerialized(
+ std::unique_ptr<script::DataBuffer> data_buffer) {
+ if (!event_target_ || !data_buffer) {
+ return;
+ }
// TODO: Forward the location of the origating API call to the PostTask call.
base::MessageLoop* message_loop =
event_target_->environment_settings()->context()->message_loop();
- if (message_loop) {
- // https://html.spec.whatwg.org/multipage/workers.html#handler-worker-onmessage
- // TODO: Update MessageEvent to support more types. (b/227665847)
- // TODO: Remove dependency of MessageEvent on net iobuffer (b/227665847)
- message_loop->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(
- [](web::EventTarget* event_target, const std::string& messages) {
- scoped_refptr<net::IOBufferWithSize> buf = base::WrapRefCounted(
- new net::IOBufferWithSize(messages.length()));
- memcpy(buf->data(), messages.data(), messages.length());
- if (event_target) {
- event_target->DispatchEvent(new web::MessageEvent(
- base::Tokens::message(), web::MessageEvent::kText, buf));
- }
- LOG_IF(WARNING, !event_target)
- << "MessagePort event not dispatched "
- "because there is no EventTarget.";
- },
- base::Unretained(event_target_), messages));
+ if (!message_loop) {
+ return;
}
+ // https://html.spec.whatwg.org/multipage/workers.html#handler-worker-onmessage
+ // TODO: Update MessageEvent to support more types. (b/227665847)
+ // TODO: Remove dependency of MessageEvent on net iobuffer (b/227665847)
+ message_loop->task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&MessagePort::DispatchMessage, AsWeakPtr(),
+ std::move(data_buffer)));
+}
+
+void MessagePort::DispatchMessage(
+ std::unique_ptr<script::DataBuffer> data_buffer) {
+ event_target_->DispatchEvent(
+ new web::MessageEvent(base::Tokens::message(), std::move(data_buffer)));
}
} // namespace web
diff --git a/cobalt/web/message_port.h b/cobalt/web/message_port.h
index 86ff17b..183e35a 100644
--- a/cobalt/web/message_port.h
+++ b/cobalt/web/message_port.h
@@ -15,8 +15,10 @@
#ifndef COBALT_WEB_MESSAGE_PORT_H_
#define COBALT_WEB_MESSAGE_PORT_H_
+#include <memory>
#include <string>
+#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "cobalt/base/tokens.h"
@@ -24,6 +26,7 @@
#include "cobalt/script/sequence.h"
#include "cobalt/script/value_handle.h"
#include "cobalt/script/wrappable.h"
+#include "cobalt/web/context.h"
#include "cobalt/web/event_target.h"
#include "cobalt/web/event_target_listener_info.h"
#include "cobalt/web/message_event.h"
@@ -32,21 +35,29 @@
namespace web {
class MessagePort : public script::Wrappable,
- public base::SupportsWeakPtr<MessagePort> {
+ public base::SupportsWeakPtr<MessagePort>,
+ public Context::EnvironmentSettingsChangeObserver {
public:
explicit MessagePort(web::EventTarget* event_target);
~MessagePort();
MessagePort(const MessagePort&) = delete;
MessagePort& operator=(const MessagePort&) = delete;
+ void OnEnvironmentSettingsChanged(bool context_valid) override {
+ if (!context_valid) {
+ Close();
+ }
+ }
+
// This may help for adding support of 'object'
// void postMessage(any message, object transfer);
// -> void PostMessage(const script::ValueHandleHolder& message,
// script::Sequence<script::ValueHandle*> transfer) {}
- void PostMessage(const std::string& message);
+ void PostMessage(const script::ValueHandleHolder& message);
+ void PostMessageSerialized(std::unique_ptr<script::DataBuffer> data_buffer);
void Start() {}
- void Close() {}
+ void Close();
const web::EventTargetListenerInfo::EventListenerScriptValue* onmessage()
const {
@@ -57,9 +68,11 @@
void set_onmessage(
const web::EventTargetListenerInfo::EventListenerScriptValue&
event_listener) {
- if (event_target_)
- event_target_->SetAttributeEventListener(base::Tokens::message(),
- event_listener);
+ if (!event_target_) {
+ return;
+ }
+ event_target_->SetAttributeEventListener(base::Tokens::message(),
+ event_listener);
}
const web::EventTargetListenerInfo::EventListenerScriptValue* onmessageerror()
@@ -71,16 +84,21 @@
void set_onmessageerror(
const web::EventTargetListenerInfo::EventListenerScriptValue&
event_listener) {
- if (event_target_)
- event_target_->SetAttributeEventListener(base::Tokens::messageerror(),
- event_listener);
+ if (!event_target_) {
+ return;
+ }
+ event_target_->SetAttributeEventListener(base::Tokens::messageerror(),
+ event_listener);
}
DEFINE_WRAPPABLE_TYPE(MessagePort);
private:
+ void DispatchMessage(std::unique_ptr<script::DataBuffer> data_buffer);
+
// The event target to dispatch events to.
web::EventTarget* event_target_ = nullptr;
+ base::OnceClosure remove_environment_settings_change_observer_;
};
} // namespace web
diff --git a/cobalt/web/message_port.idl b/cobalt/web/message_port.idl
index acacae8..86b9528 100644
--- a/cobalt/web/message_port.idl
+++ b/cobalt/web/message_port.idl
@@ -16,7 +16,7 @@
// https://html.spec.whatwg.org/dev/web-messaging.html#message-ports
interface MessagePort /* : EventTarget */ {
// [RaisesException]
- void postMessage(USVString message);
+ void postMessage(any message);
// void postMessage(USVString message, sequence<USVString> transfer);
// TODO: Support sequence<object>: b/218501774
// void postMessage(any message, sequence<object> transfer);
diff --git a/cobalt/web/testing/stub_web_context.h b/cobalt/web/testing/stub_web_context.h
index f709d0e..dabc4b6 100644
--- a/cobalt/web/testing/stub_web_context.h
+++ b/cobalt/web/testing/stub_web_context.h
@@ -58,6 +58,11 @@
}
~StubWebContext() final { blob_registry_.reset(); }
+ void AddEnvironmentSettingsChangeObserver(
+ Context::EnvironmentSettingsChangeObserver* observer) final {}
+ void RemoveEnvironmentSettingsChangeObserver(
+ Context::EnvironmentSettingsChangeObserver* observer) final {}
+
// WebInstance
//
base::MessageLoop* message_loop() const final {
diff --git a/cobalt/web/window_or_worker_global_scope.cc b/cobalt/web/window_or_worker_global_scope.cc
index 26cfeff..f5a3fc3 100644
--- a/cobalt/web/window_or_worker_global_scope.cc
+++ b/cobalt/web/window_or_worker_global_scope.cc
@@ -14,7 +14,10 @@
#include "cobalt/web/window_or_worker_global_scope.h"
+#include <utility>
+
#include "cobalt/script/environment_settings.h"
+#include "cobalt/web/csp_delegate_factory.h"
#include "cobalt/web/event_target.h"
namespace cobalt {
@@ -28,12 +31,21 @@
namespace web {
WindowOrWorkerGlobalScope::WindowOrWorkerGlobalScope(
script::EnvironmentSettings* settings, StatTracker* stat_tracker,
- base::ApplicationState initial_state)
+ Options options)
// Global scope object EventTargets require special handling for onerror
// events, see EventTarget constructor for more details.
: EventTarget(settings, kUnpackOnErrorEvents),
crypto_(new Crypto()),
- window_timers_(this, stat_tracker, debugger_hooks(), initial_state) {}
+ window_timers_(this, stat_tracker, debugger_hooks(),
+ options.initial_state),
+ preflight_cache_(new loader::CORSPreflightCache()) {
+ std::unique_ptr<web::CspViolationReporter> violation_reporter(
+ new web::CspViolationReporter(this, options.post_sender));
+ csp_delegate_ = web::CspDelegateFactory::GetInstance()->Create(
+ options.csp_enforcement_mode, std::move(violation_reporter),
+ environment_settings()->creation_url(), options.require_csp,
+ options.csp_policy_changed_callback, options.csp_insecure_allowed_token);
+}
bool WindowOrWorkerGlobalScope::IsWindow() {
return GetWrappableType() == base::GetTypeId<dom::Window>();
diff --git a/cobalt/web/window_or_worker_global_scope.h b/cobalt/web/window_or_worker_global_scope.h
index 6f079ca..b2c8ea4 100644
--- a/cobalt/web/window_or_worker_global_scope.h
+++ b/cobalt/web/window_or_worker_global_scope.h
@@ -15,13 +15,17 @@
#ifndef COBALT_WEB_WINDOW_OR_WORKER_GLOBAL_SCOPE_H_
#define COBALT_WEB_WINDOW_OR_WORKER_GLOBAL_SCOPE_H_
+#include <memory>
#include <string>
#include <vector>
#include "base/logging.h"
#include "base/memory/ref_counted.h"
+#include "cobalt/loader/cors_preflight_cache.h"
#include "cobalt/script/environment_settings.h"
#include "cobalt/web/crypto.h"
+#include "cobalt/web/csp_delegate.h"
+#include "cobalt/web/csp_delegate_type.h"
#include "cobalt/web/event_target.h"
#include "cobalt/web/event_target_listener_info.h"
#include "cobalt/web/navigator_base.h"
@@ -42,9 +46,35 @@
// interfaces.
class WindowOrWorkerGlobalScope : public EventTarget {
public:
+ struct Options {
+ explicit Options(base::ApplicationState initial_state)
+ : initial_state(initial_state),
+ csp_enforcement_mode(web::kCspEnforcementEnable) {}
+
+ Options(base::ApplicationState initial_state,
+ const network_bridge::PostSender& post_sender,
+ csp::CSPHeaderPolicy require_csp,
+ web::CspEnforcementType csp_enforcement_mode,
+ base::Closure csp_policy_changed_callback,
+ int csp_insecure_allowed_token = 0)
+ : initial_state(initial_state),
+ post_sender(post_sender),
+ require_csp(require_csp),
+ csp_enforcement_mode(csp_enforcement_mode),
+ csp_policy_changed_callback(csp_policy_changed_callback),
+ csp_insecure_allowed_token(csp_insecure_allowed_token) {}
+
+ base::ApplicationState initial_state;
+ network_bridge::PostSender post_sender;
+ csp::CSPHeaderPolicy require_csp;
+ web::CspEnforcementType csp_enforcement_mode;
+ base::Closure csp_policy_changed_callback;
+ int csp_insecure_allowed_token;
+ };
+
explicit WindowOrWorkerGlobalScope(script::EnvironmentSettings* settings,
StatTracker* stat_tracker,
- base::ApplicationState initial_state);
+ Options options);
WindowOrWorkerGlobalScope(const WindowOrWorkerGlobalScope&) = delete;
WindowOrWorkerGlobalScope& operator=(const WindowOrWorkerGlobalScope&) =
delete;
@@ -68,6 +98,12 @@
return nullptr;
}
+ web::CspDelegate* csp_delegate() const { return csp_delegate_.get(); }
+
+ const scoped_refptr<loader::CORSPreflightCache> get_preflight_cache() {
+ return preflight_cache_;
+ }
+
DEFINE_WRAPPABLE_TYPE(WindowOrWorkerGlobalScope);
// Web API: WindowTimers (implements)
@@ -104,7 +140,10 @@
web::WindowTimers window_timers_;
private:
+ std::unique_ptr<web::CspDelegate> csp_delegate_;
NavigatorBase* navigator_base_ = nullptr;
+ // Global preflight cache.
+ scoped_refptr<loader::CORSPreflightCache> preflight_cache_;
};
} // namespace web
diff --git a/cobalt/websocket/web_socket.cc b/cobalt/websocket/web_socket.cc
index 13f2004..82db7a7 100644
--- a/cobalt/websocket/web_socket.cc
+++ b/cobalt/websocket/web_socket.cc
@@ -153,9 +153,9 @@
return (all_protocols.size() == sub_protocols.size());
}
-bool IsValidBinaryType(cobalt::web::MessageEvent::ResponseTypeCode code) {
- return (code == cobalt::web::MessageEvent::kBlob) ||
- (code == cobalt::web::MessageEvent::kArrayBuffer);
+bool IsValidBinaryType(cobalt::web::MessageEvent::ResponseType response_type) {
+ return (response_type == cobalt::web::MessageEvent::kBlob) ||
+ (response_type == cobalt::web::MessageEvent::kArrayBuffer);
}
} // namespace
@@ -220,12 +220,12 @@
// "arraybuffer", then set the IDL attribute to this new value.
// Otherwise, throw a SyntaxError exception."
base::StringPiece binary_type_string_piece(binary_type);
- web::MessageEvent::ResponseTypeCode response_code =
- web::MessageEvent::GetResponseTypeCode(binary_type_string_piece);
- if (!IsValidBinaryType(response_code)) {
+ web::MessageEvent::ResponseType response_type =
+ web::MessageEvent::GetResponseType(binary_type_string_piece);
+ if (!IsValidBinaryType(response_type)) {
web::DOMException::Raise(web::DOMException::kSyntaxErr, exception_state);
} else {
- binary_type_ = response_code;
+ binary_type_ = response_type;
}
}
@@ -416,12 +416,12 @@
void WebSocket::OnReceivedData(bool is_text_frame,
scoped_refptr<net::IOBufferWithSize> data) {
- web::MessageEvent::ResponseTypeCode response_type_code = binary_type_;
+ web::MessageEvent::ResponseType response_type = binary_type_;
if (is_text_frame) {
- response_type_code = web::MessageEvent::kText;
+ response_type = web::MessageEvent::kText;
}
this->DispatchEvent(
- new web::MessageEvent(base::Tokens::message(), response_type_code, data));
+ new web::MessageEvent(base::Tokens::message(), response_type, data));
}
void WebSocket::OnWriteDone(uint64_t bytes_written) {
@@ -562,18 +562,13 @@
}
web::CspDelegate* WebSocket::csp_delegate() const {
- DCHECK(settings_);
- if (!settings_) {
- return NULL;
- }
- dom::DOMSettings* dom_settings =
- base::polymorphic_downcast<dom::DOMSettings*>(settings_);
- if (dom_settings && dom_settings->window() &&
- dom_settings->window()->document()) {
- return dom_settings->window()->document()->csp_delegate();
- } else {
- return NULL;
- }
+ DCHECK(environment_settings());
+ DCHECK(environment_settings()->context());
+ DCHECK(environment_settings()->context()->GetWindowOrWorkerGlobalScope());
+ return environment_settings()
+ ->context()
+ ->GetWindowOrWorkerGlobalScope()
+ ->csp_delegate();
}
void WebSocket::Connect(const GURL& url,
diff --git a/cobalt/websocket/web_socket.h b/cobalt/websocket/web_socket.h
index 74909b7..2827dbb 100644
--- a/cobalt/websocket/web_socket.h
+++ b/cobalt/websocket/web_socket.h
@@ -201,7 +201,7 @@
// https://www.w3.org/TR/websockets/#dom-websocket-readystate
uint16 ready_state_;
// https://www.w3.org/TR/websockets/#dom-websocket-binarytype
- web::MessageEvent::ResponseTypeCode binary_type_;
+ web::MessageEvent::ResponseType binary_type_;
// https://www.w3.org/TR/websockets/#dom-websocket-extensions
std::string extensions_;
// https://www.w3.org/TR/websockets/#dom-websocket-protocol
diff --git a/cobalt/websocket/web_socket.idl b/cobalt/websocket/web_socket.idl
index d4e642c..76bb69d 100644
--- a/cobalt/websocket/web_socket.idl
+++ b/cobalt/websocket/web_socket.idl
@@ -40,7 +40,7 @@
optional DOMString reason);
// messaging
- attribute EventHandler onmessage;
+ attribute EventHandler onmessage;
[RaisesException] attribute DOMString binaryType;
[RaisesException] void send(DOMString data);
[RaisesException] void send(ArrayBuffer data);
diff --git a/cobalt/worker/client.idl b/cobalt/worker/client.idl
index fe68a12..8d2e4a9 100644
--- a/cobalt/worker/client.idl
+++ b/cobalt/worker/client.idl
@@ -19,7 +19,7 @@
readonly attribute FrameType frameType;
readonly attribute DOMString id;
readonly attribute ClientType type;
- void postMessage(USVString message);
+ void postMessage(any message);
// TODO: Support sequence<object>: b/218501774
// void postMessage(any message, sequence<object> transfer);
// TODO: Support overloads with dictionary parameter: b/218506730
diff --git a/cobalt/worker/dedicated_worker.cc b/cobalt/worker/dedicated_worker.cc
index 69b0300..0dff482 100644
--- a/cobalt/worker/dedicated_worker.cc
+++ b/cobalt/worker/dedicated_worker.cc
@@ -98,7 +98,7 @@
// void postMessage(any message, object transfer);
// -> void PostMessage(const script::ValueHandleHolder& message,
// script::Sequence<script::ValueHandle*> transfer) {}
-void DedicatedWorker::PostMessage(const std::string& message) {
+void DedicatedWorker::PostMessage(const script::ValueHandleHolder& message) {
DCHECK(worker_);
worker_->PostMessage(message);
}
diff --git a/cobalt/worker/dedicated_worker.h b/cobalt/worker/dedicated_worker.h
index 90c9547..b1264d8 100644
--- a/cobalt/worker/dedicated_worker.h
+++ b/cobalt/worker/dedicated_worker.h
@@ -47,7 +47,7 @@
// void postMessage(any message, object transfer);
// -> void PostMessage(const script::ValueHandleHolder& message,
// script::Sequence<script::ValueHandle*> transfer) {}
- void PostMessage(const std::string& message);
+ void PostMessage(const script::ValueHandleHolder& message);
const EventListenerScriptValue* onmessage() const {
return GetAttributeEventListener(base::Tokens::message());
diff --git a/cobalt/worker/dedicated_worker_global_scope.cc b/cobalt/worker/dedicated_worker_global_scope.cc
index 420dd3a..a03e8a0 100644
--- a/cobalt/worker/dedicated_worker_global_scope.cc
+++ b/cobalt/worker/dedicated_worker_global_scope.cc
@@ -72,7 +72,8 @@
}
}
-void DedicatedWorkerGlobalScope::PostMessage(const std::string& message) {
+void DedicatedWorkerGlobalScope::PostMessage(
+ const script::ValueHandleHolder& message) {
base::polymorphic_downcast<worker::WorkerSettings*>(environment_settings())
->message_port()
->PostMessage(message);
diff --git a/cobalt/worker/dedicated_worker_global_scope.h b/cobalt/worker/dedicated_worker_global_scope.h
index 6b140f5..3793608 100644
--- a/cobalt/worker/dedicated_worker_global_scope.h
+++ b/cobalt/worker/dedicated_worker_global_scope.h
@@ -52,7 +52,7 @@
void set_name(const std::string& name) { name_ = name; }
std::string name() { return name_; }
- void PostMessage(const std::string& message);
+ void PostMessage(const script::ValueHandleHolder& message);
void Close() {}
const web::EventTargetListenerInfo::EventListenerScriptValue* onmessage() {
diff --git a/cobalt/worker/dedicated_worker_global_scope.idl b/cobalt/worker/dedicated_worker_global_scope.idl
index 7f3c6a7..1b42584 100644
--- a/cobalt/worker/dedicated_worker_global_scope.idl
+++ b/cobalt/worker/dedicated_worker_global_scope.idl
@@ -20,7 +20,7 @@
] interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
[Replaceable] readonly attribute DOMString name;
- void postMessage(USVString message);
+ void postMessage(any message);
// TODO: Support sequence<object>: b/218501774
// void postMessage(any message, sequence<object> transfer);
// TODO: Support overloads with dictionary parameter: b/218506730
diff --git a/cobalt/worker/service_worker.h b/cobalt/worker/service_worker.h
index 1e39dfe..a281746 100644
--- a/cobalt/worker/service_worker.h
+++ b/cobalt/worker/service_worker.h
@@ -43,7 +43,7 @@
// Web API: ServiceWorker
//
- void PostMessage(const std::string& message) {
+ void PostMessage(const script::ValueHandleHolder& message) {
DCHECK(message_port_);
if (worker_->worker_global_scope()) message_port_->PostMessage(message);
}
diff --git a/cobalt/worker/service_worker.idl b/cobalt/worker/service_worker.idl
index f76c706..b1b9602 100644
--- a/cobalt/worker/service_worker.idl
+++ b/cobalt/worker/service_worker.idl
@@ -17,7 +17,7 @@
[Exposed = (Window, ServiceWorker)] interface ServiceWorker : EventTarget {
// Todo: Implement postMessage b/219986442
- void postMessage(USVString message);
+ void postMessage(any message);
// void postMessage(any message, sequence<object> transfer);
// void postMessage(any message, optional PostMessageOptions options = {});
diff --git a/cobalt/worker/worker.cc b/cobalt/worker/worker.cc
index 495a95d..b8e283b 100644
--- a/cobalt/worker/worker.cc
+++ b/cobalt/worker/worker.cc
@@ -31,6 +31,11 @@
#include "cobalt/worker/worker_options.h"
#include "cobalt/worker/worker_settings.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "v8/include/v8.h"
+
namespace cobalt {
namespace worker {
@@ -313,23 +318,20 @@
// TODO(b/226640425): Implement this when Message Ports can be entangled.
}
-// void postMessage(any message, object transfer);
-// -> void PostMessage(const script::ValueHandleHolder& message,
-// script::Sequence<script::ValueHandle*> transfer) {}
-void Worker::PostMessage(const std::string& message) {
+void Worker::PostMessage(const script::ValueHandleHolder& message) {
DCHECK(message_loop());
+ auto serialized_message = script::SerializeScriptValue(message);
if (base::MessageLoop::current() != message_loop()) {
// Block until the worker thread is ready to execute code to handle the
// event.
execution_ready_.Wait();
message_loop()->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&Worker::PostMessage, base::Unretained(this), message));
- return;
+ FROM_HERE, base::BindOnce(&web::MessagePort::PostMessageSerialized,
+ message_port()->AsWeakPtr(),
+ std::move(serialized_message)));
} else {
DCHECK(execution_ready_.IsSignaled());
- DCHECK(message_port());
- if (message_port()) message_port()->PostMessage(message);
+ message_port()->PostMessageSerialized(std::move(serialized_message));
}
}
diff --git a/cobalt/worker/worker.h b/cobalt/worker/worker.h
index fe78f28..2c488ec 100644
--- a/cobalt/worker/worker.h
+++ b/cobalt/worker/worker.h
@@ -17,6 +17,7 @@
#include <memory>
#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/macros.h"
@@ -83,7 +84,7 @@
return web_agent_ ? web_agent_->message_loop() : nullptr;
}
- void PostMessage(const std::string& message);
+ void PostMessage(const script::ValueHandleHolder& message);
// From base::MessageLoop::DestructionObserver.
void WillDestroyCurrentMessageLoop() override;
diff --git a/cobalt/worker/worker.idl b/cobalt/worker/worker.idl
index b9db12b..e05669f 100644
--- a/cobalt/worker/worker.idl
+++ b/cobalt/worker/worker.idl
@@ -23,7 +23,7 @@
interface Worker : EventTarget {
void terminate();
- void postMessage(USVString message);
+ void postMessage(any message);
// TODO: Support sequence<object>: b/218501774
// void postMessage(any message, sequence<object> transfer);
// TODO: Support overloads with dictionary parameter: b/218506730
diff --git a/cobalt/worker/worker_global_scope.cc b/cobalt/worker/worker_global_scope.cc
index edc69fb..3316581 100644
--- a/cobalt/worker/worker_global_scope.cc
+++ b/cobalt/worker/worker_global_scope.cc
@@ -185,9 +185,11 @@
WorkerGlobalScope::WorkerGlobalScope(script::EnvironmentSettings* settings)
: web::WindowOrWorkerGlobalScope(
settings, /*stat_tracker=*/NULL,
- // TODO (b/233788170): once application state is
- // available, update this to use the actual state.
- base::ApplicationState::kApplicationStateStarted),
+ // Using default options for CSP
+ web::WindowOrWorkerGlobalScope::Options(
+ // TODO (b/233788170): once application state is
+ // available, update this to use the actual state.
+ base::ApplicationState::kApplicationStateStarted)),
location_(new WorkerLocation(settings->creation_url())),
navigator_(new WorkerNavigator(settings)) {
set_navigator_base(navigator_);
diff --git a/cobalt/xhr/xml_http_request.cc b/cobalt/xhr/xml_http_request.cc
index 6f16335..56de1ee 100644
--- a/cobalt/xhr/xml_http_request.cc
+++ b/cobalt/xhr/xml_http_request.cc
@@ -168,6 +168,18 @@
// 5. If request's redirect count is twenty, return a network error.
const int kRedirectLimit = 20;
+std::string ClipUrl(const GURL& url, size_t length) {
+ const std::string& spec = url.possibly_invalid_spec();
+ if (spec.size() < length) {
+ return spec;
+ }
+
+ size_t remain = length - 5;
+ size_t head = remain / 2;
+ size_t tail = remain - head;
+
+ return spec.substr(0, head) + "[...]" + spec.substr(spec.size() - tail);
+}
} // namespace
bool XMLHttpRequestImpl::verbose_ = false;
@@ -417,7 +429,7 @@
return;
}
- web::CspDelegate* csp = this->csp_delegate();
+ web::CspDelegate* csp = csp_delegate();
if (csp && !csp->CanLoad(web::CspDelegate::kXhr, request_url_, false)) {
web::DOMException::Raise(web::DOMException::kSecurityErr, exception_state);
return;
@@ -1044,7 +1056,7 @@
return;
}
// This is a redirect. Re-check the CSP.
- web::CspDelegate* csp = this->csp_delegate();
+ web::CspDelegate* csp = csp_delegate();
if (csp &&
!csp->CanLoad(web::CspDelegate::kXhr, new_url, true /* is_redirect */)) {
HandleRequestError(XMLHttpRequest::kNetworkError);
@@ -1099,11 +1111,10 @@
}
web::CspDelegate* XMLHttpRequestImpl::csp_delegate() const {
- // TODO (b/239733363): csp_delegate is currently available through window.
- // Refactor to make it available outside of window then implement this. At
- // that point, there should be no more need to override this function in
- // DOMXMLHttpRequestImpl.
- return NULL;
+ DCHECK(settings_);
+ DCHECK(settings_->context());
+ DCHECK(settings_->context()->GetWindowOrWorkerGlobalScope());
+ return settings_->context()->GetWindowOrWorkerGlobalScope()->csp_delegate();
}
void XMLHttpRequestImpl::TerminateRequest() {
@@ -1236,6 +1247,7 @@
void XMLHttpRequestImpl::StartRequest(const std::string& request_body) {
TRACK_MEMORY_SCOPE("XHR");
+ LOG(INFO) << "Fetching: " << ClipUrl(request_url_, 200);
response_array_buffer_reference_.reset();
@@ -1283,9 +1295,35 @@
url_fetcher_->AddExtraRequestHeader("Origin:" + origin_.SerializedOrigin());
}
bool dopreflight = false;
- // TODO (b/239733363): Include CORS functionality once preflight cache is
- // accessible outside of window. At that point, there should be no more need
- // to override this function in DOMXMLHttpRequestImpl.
+ if (is_cross_origin_) {
+ corspreflight_.reset(new cobalt::loader::CORSPreflight(
+ request_url_, method_, network_module,
+ base::Bind(&DOMXMLHttpRequestImpl::CORSPreflightSuccessCallback,
+ base::Unretained(this)),
+ origin_.SerializedOrigin(),
+ base::Bind(&DOMXMLHttpRequestImpl::CORSPreflightErrorCallback,
+ base::Unretained(this)),
+ settings_->context()
+ ->GetWindowOrWorkerGlobalScope()
+ ->get_preflight_cache()));
+ corspreflight_->set_headers(request_headers_);
+ // For cross-origin requests, don't send or save auth data / cookies unless
+ // withCredentials was set.
+ // To make a cross-origin request, add origin, referrer source, credentials,
+ // omit credentials flag, force preflight flag
+ if (!with_credentials_) {
+ const uint32 kDisableCookiesLoadFlags =
+ net::LOAD_NORMAL | net::LOAD_DO_NOT_SAVE_COOKIES |
+ net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA;
+ url_fetcher_->SetLoadFlags(kDisableCookiesLoadFlags);
+ } else {
+ // For credentials mode: If the withCredentials attribute value is true,
+ // "include", and "same-origin" otherwise.
+ corspreflight_->set_credentials_mode_is_include(true);
+ }
+ corspreflight_->set_force_preflight(upload_listener_);
+ dopreflight = corspreflight_->Send();
+ }
DLOG_IF(INFO, verbose()) << __FUNCTION__ << *xhr_;
if (!dopreflight) {
DCHECK(settings_->context()->network_module());
@@ -1413,99 +1451,6 @@
request_url_.spec());
}
-web::CspDelegate* DOMXMLHttpRequestImpl::csp_delegate() const {
- DCHECK(settings_);
- if (settings_->window() && settings_->window()->document()) {
- return settings_->window()->document()->csp_delegate();
- } else {
- return NULL;
- }
-}
-
-void DOMXMLHttpRequestImpl::StartRequest(const std::string& request_body) {
- TRACK_MEMORY_SCOPE("XHR");
-
- response_array_buffer_reference_.reset();
-
- network::NetworkModule* network_module =
- settings_->context()->fetcher_factory()->network_module();
- url_fetcher_ = net::URLFetcher::Create(request_url_, method_, xhr_);
- ++url_fetcher_generation_;
- url_fetcher_->SetRequestContext(network_module->url_request_context_getter());
- if (fetch_callback_) {
- response_body_ = new URLFetcherResponseWriter::Buffer(
- URLFetcherResponseWriter::Buffer::kString);
- response_body_->DisablePreallocate();
- } else {
- response_body_ = new URLFetcherResponseWriter::Buffer(
- response_type_ == XMLHttpRequest::kArrayBuffer
- ? URLFetcherResponseWriter::Buffer::kArrayBuffer
- : URLFetcherResponseWriter::Buffer::kString);
- }
- std::unique_ptr<net::URLFetcherResponseWriter> download_data_writer(
- new URLFetcherResponseWriter(response_body_));
- url_fetcher_->SaveResponseWithWriter(std::move(download_data_writer));
- // Don't retry, let the caller deal with it.
- url_fetcher_->SetAutomaticallyRetryOn5xx(false);
- url_fetcher_->SetExtraRequestHeaders(request_headers_.ToString());
-
- // We want to do cors check and preflight during redirects
- url_fetcher_->SetStopOnRedirect(true);
-
- if (request_body.size()) {
- // If applicable, the request body Content-Type is already set in
- // request_headers.
- url_fetcher_->SetUploadData("", request_body);
- }
-
- // We let data url fetch resources freely but with no response headers.
- is_data_url_ = is_data_url_ || request_url_.SchemeIs("data");
- is_cross_origin_ = (is_redirect_ && is_cross_origin_) ||
- (origin_ != loader::Origin(request_url_) && !is_data_url_);
- is_redirect_ = false;
- // If the CORS flag is set, httpRequest’s method is neither `GET` nor `HEAD`
- // or httpRequest’s mode is "websocket", then append `Origin`/httpRequest’s
- // origin, serialized and UTF-8 encoded, to httpRequest’s header list.
- if (is_cross_origin_ ||
- (method_ != net::URLFetcher::GET && method_ != net::URLFetcher::HEAD)) {
- url_fetcher_->AddExtraRequestHeader("Origin:" + origin_.SerializedOrigin());
- }
- bool dopreflight = false;
- if (is_cross_origin_) {
- corspreflight_.reset(new cobalt::loader::CORSPreflight(
- request_url_, method_, network_module,
- base::Bind(&DOMXMLHttpRequestImpl::CORSPreflightSuccessCallback,
- base::Unretained(this)),
- origin_.SerializedOrigin(),
- base::Bind(&DOMXMLHttpRequestImpl::CORSPreflightErrorCallback,
- base::Unretained(this)),
- settings_->window()->get_preflight_cache()));
- corspreflight_->set_headers(request_headers_);
- // For cross-origin requests, don't send or save auth data / cookies unless
- // withCredentials was set.
- // To make a cross-origin request, add origin, referrer source, credentials,
- // omit credentials flag, force preflight flag
- if (!with_credentials_) {
- const uint32 kDisableCookiesLoadFlags =
- net::LOAD_NORMAL | net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA;
- url_fetcher_->SetLoadFlags(kDisableCookiesLoadFlags);
- } else {
- // For credentials mode: If the withCredentials attribute value is true,
- // "include", and "same-origin" otherwise.
- corspreflight_->set_credentials_mode_is_include(true);
- }
- corspreflight_->set_force_preflight(upload_listener_);
- dopreflight = corspreflight_->Send();
- }
- DLOG_IF(INFO, verbose()) << __FUNCTION__ << *xhr_;
- if (!dopreflight) {
- DCHECK(settings_->context()->network_module());
- StartURLFetcher(settings_->context()->network_module()->max_network_delay(),
- url_fetcher_generation_);
- }
-}
-
// https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#document-response-entity-body
scoped_refptr<dom::Document>
DOMXMLHttpRequestImpl::GetDocumentResponseEntityBody() {
diff --git a/cobalt/xhr/xml_http_request.h b/cobalt/xhr/xml_http_request.h
index e3510f0..046e90f 100644
--- a/cobalt/xhr/xml_http_request.h
+++ b/cobalt/xhr/xml_http_request.h
@@ -446,12 +446,7 @@
void GetLoadTimingInfoAndCreateResourceTiming() override;
- protected:
- web::CspDelegate* csp_delegate() const override;
-
private:
- void StartRequest(const std::string& request_body) override;
-
scoped_refptr<dom::Document> GetDocumentResponseEntityBody();
void XMLDecoderLoadCompleteCallback(
diff --git a/docker-compose.yml b/docker-compose.yml
index 1f5f4e3..08f9df6 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -40,6 +40,18 @@
IS_DOCKER: 1
PYTHONPATH: /code
+x-shared-docsite-definitions: &shared-docsite-definitions
+ <<: *build-common-definitions
+ build:
+ context: ./docker/docsite
+ dockerfile: Dockerfile
+ args:
+ - USER=root
+ - UID=2000
+ - GID=2000
+ environment:
+ <<: *shared-build-env
+
x-shared-unittest-definitions: &shared-unittest-definitions
stdin_open: true
tty: true
@@ -125,6 +137,18 @@
- base-bionic
scale: 0
+ docsite:
+ <<: *shared-docsite-definitions
+ image: cobalt-build-docsite
+ ports:
+ # The docsite webapp runs on port 4000.
+ - "4000:4000"
+
+ docsite-deploy:
+ <<: *shared-docsite-definitions
+ image: cobalt-build-docsite-deploy
+ entrypoint: ["/code/third_party/repo-publishing-toolkit-local/preview-site.sh", "deploy"]
+
stub:
<<: *build-common-definitions
build:
@@ -148,7 +172,7 @@
<<: *shared-build-env
PLATFORM: linux-x64x11
CONFIG: ${CONFIG:-debug}
- TARGET: ${TARGET:-cobalt_deploy}
+ TARGET: ${TARGET:-cobalt_install}
linux-x64x11-bionic:
<<: *common-definitions
diff --git a/docker/docsite/Dockerfile b/docker/docsite/Dockerfile
index fc278cc..02b4681 100644
--- a/docker/docsite/Dockerfile
+++ b/docker/docsite/Dockerfile
@@ -12,7 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-FROM ruby:2.7-buster
+ARG FROM_IMAGE
+FROM ${FROM_IMAGE:-cobalt-build-base}
ARG USER
ARG UID
@@ -20,14 +21,13 @@
RUN apt update -qqy \
&& apt install -qqy --no-install-recommends \
+ build-essential \
bundler \
doxygen \
git \
- nodejs \
- python \
- # Required for GN build.
- python3 \
- python3-requests \
+ python-pygments \
+ ruby2.5-dev \
+ ruby-execjs \
&& apt-get clean autoclean \
&& apt-get autoremove -y --purge \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
@@ -37,27 +37,19 @@
RUN bundle install --gemfile=/app/Gemfile
-# === Get GN via CIPD
-ARG GN_SHA256SUM="af7b2dcb3905bca56655e12131b365f1cba8e159db80d2022330c4f522fab2ef /tmp/gn.zip"
-ARG GN_HASH=r3styzkFvKVmVeEhMbNl8cuo4VnbgNICIzDE9SL6su8C
-
-RUN curl --location --silent --output /tmp/gn.zip \
- "https://chrome-infra-packages.appspot.com/dl/gn/gn/linux-amd64/+/${GN_HASH}" \
- && echo ${GN_SHA256SUM} | sha256sum --check \
- && unzip /tmp/gn.zip -d /usr/local/bin \
- && rm /tmp/gn.zip
-
# We create and use a non-root user explicitly so that the generated and
# modified files maintain the same permissions as the user that launched the
# Docker container.
RUN addgroup --group --gid "${GID}" defaultgroup \
- && adduser --disabled-password --gecos '' --uid "${UID}" --gid "${GID}" ${USER:-defaultuser}
+ && adduser --disabled-password --gecos '' --uid "${UID}" --gid "${GID}" defaultuser
-# Allow the new uses to run gn and create a descriptive out directory.
+# The new user must be able to execute gn.
RUN chmod a+x /usr/local/bin/gn
+
+# Create an out directory with a descriptive name for gn.
RUN mkdir /project_out_dir \
&& chown ${USER:-defaultuser}:defaultgroup /project_out_dir
USER ${USER:-defaultuser}
-CMD /cobalt/third_party/repo-publishing-toolkit-local/preview-site.sh
+CMD /code/third_party/repo-publishing-toolkit-local/preview-site.sh run
diff --git a/docker/docsite/README.md b/docker/docsite/README.md
index 06ea6fc..58177d1 100644
--- a/docker/docsite/README.md
+++ b/docker/docsite/README.md
@@ -4,25 +4,14 @@
the current working directory, which should be the root of the Cobalt
repository, if that environment variable is not set.
-When the `docsite` service is run, the container will then host the updated
-cobalt.dev site locally on port `4000`.
+When the `docsite` service is run, the container will generate the site and host
+the updated cobalt.dev site locally on port `4000`.
-When the `docsite-build-only` service is run, the container will build and
+When the `docsite-deploy` service is run, the container will build and
output the site content in the directory `out/deploy/www` at the root of the
Cobalt directory, and copy the app.yaml deployable into `out/deploy`.
# How To Run
-docker-compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) SERVICE
+docker-compose build --no-cache --build-arg USER=defaultuser --build-arg UID=$(id -u) --build-arg GID=$(id -g) SERVICE
docker-compose up SERVICE
-
-# Notes
-
-A separate docker-compose.yml was created due to the root docker-compose.yml
-being unable to locate the Gemfile in the Docker build context.
-
-The Gemfile was copied from third_party/repo-publishing-toolkit/Gemfile because
-we need to run `bundle install` with elevated permissions but if we let the
-`preview-site.sh`, which normally installs gems, run with elevated permissions
-the resulting files added or modified would not be accessible to the user who
-ran the Docker container.
diff --git a/docker/docsite/docker-compose.yml b/docker/docsite/docker-compose.yml
deleted file mode 100644
index 02e0aa5..0000000
--- a/docker/docsite/docker-compose.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2021 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.
-
-version: '2.4'
-
-services:
- docsite:
- build:
- context: .
- dockerfile: Dockerfile
- container_name: docsite
- environment:
- - IS_DOCKER=1
- - PYTHONPATH=/cobalt
- ports:
- - "4000:4000"
- volumes:
- # We use ../../ when the environment variable COBALT_SRC is not set since
- # this file is located two directories under the root of the repository.
- - ${COBALT_SRC:-../../}:/cobalt/
-
- docsite-build-only:
- container_name: docsite-build-only
- environment:
- # SITE_DST specifies where the files required to deploy the site should be
- # placed, and by default this is under the "out" directory.
- - SITE_DST=${SITE_DST:-/cobalt/out/deploy/www}
- extends:
- service: docsite
diff --git a/docker/linux/base/Dockerfile b/docker/linux/base/Dockerfile
index 84368e4..50dd9e0 100644
--- a/docker/linux/base/Dockerfile
+++ b/docker/linux/base/Dockerfile
@@ -27,6 +27,7 @@
python3-pip \
python3-requests \
python3-setuptools \
+ python3-six \
git ccache \
curl xz-utils \
&& /opt/clean-after-apt.sh
diff --git a/net/disk_cache/cobalt/cobalt_backend_impl.cc b/net/disk_cache/cobalt/cobalt_backend_impl.cc
index 76c845a..8f58f6d 100644
--- a/net/disk_cache/cobalt/cobalt_backend_impl.cc
+++ b/net/disk_cache/cobalt/cobalt_backend_impl.cc
@@ -54,13 +54,34 @@
}
void ReadDiskCacheSize(
- cobalt::persistent_storage::PersistentSettings* settings) {
+ cobalt::persistent_storage::PersistentSettings* settings,
+ int64_t max_bytes) {
+ auto total_size = 0;
+ disk_cache::ResourceTypeMetadata kTypeMetadataNew[disk_cache::kTypeCount];
+
for (int i = 0; i < disk_cache::kTypeCount; i++) {
auto metadata = disk_cache::kTypeMetadata[i];
uint32_t bucket_size =
static_cast<uint32_t>(settings->GetPersistentSettingAsDouble(
metadata.directory, metadata.max_size_bytes));
- disk_cache::kTypeMetadata[i] = {metadata.directory, bucket_size};
+ kTypeMetadataNew[i] = {metadata.directory, bucket_size};
+
+ total_size += bucket_size;
+ }
+
+ // Check if PersistentSettings values are valid and can replace the disk_cache::kTypeMetadata.
+ if (total_size <= max_bytes) {
+ std::copy(std::begin(kTypeMetadataNew), std::end(kTypeMetadataNew), std::begin(disk_cache::kTypeMetadata));
+ return;
+ }
+
+ // PersistentSettings values are invalid and will be replaced by the default values in
+ // disk_cache::kTypeMetadata.
+ for (int i = 0; i < disk_cache::kTypeCount; i++) {
+ auto metadata = disk_cache::kTypeMetadata[i];
+ settings->SetPersistentSetting(
+ metadata.directory,
+ std::make_unique<base::Value>(static_cast<double>(metadata.max_size_bytes)));
}
}
@@ -76,7 +97,7 @@
persistent_settings_ =
std::make_unique<cobalt::persistent_storage::PersistentSettings>(
kPersistentSettingsJson, base::MessageLoop::current()->task_runner());
- ReadDiskCacheSize(persistent_settings_.get());
+ ReadDiskCacheSize(persistent_settings_.get(), max_bytes);
// Initialize disk backend for each resource type.
int64_t total_size = 0;
diff --git a/net/disk_cache/cobalt/resource_type.h b/net/disk_cache/cobalt/resource_type.h
index b6b5cc7..60421ba 100644
--- a/net/disk_cache/cobalt/resource_type.h
+++ b/net/disk_cache/cobalt/resource_type.h
@@ -37,13 +37,13 @@
uint32_t max_size_bytes;
};
-static uint32_t kInitialBytes = 3 * 1024 * 1024;
+static uint32_t kInitialBytes = static_cast<uint32_t> (3 * 1024 * 1024);
// These values are updated on start up in application.cc, using the
// persisted values saved in settings.json.
static ResourceTypeMetadata kTypeMetadata[] = {
{"other", kInitialBytes}, {"html", kInitialBytes},
{"css", kInitialBytes}, {"image", kInitialBytes},
- {"font", kInitialBytes}, {"splash", kInitialBytes},
+ {"font", kInitialBytes}, {"splash", 2 * 1024 * 1024},
{"uncompiled_js", kInitialBytes}, {"compiled_js", kInitialBytes},
};
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index da934ee..9f13b95 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -13,6 +13,7 @@
#include <algorithm>
#include <string>
#include <utility>
+#include <vector>
#include "base/auto_reset.h"
#include "base/bind.h"
@@ -61,6 +62,15 @@
namespace {
+#if defined(STARBOARD)
+// Default allowlist based off MIME types associated with top
+// resource types defined in resource_type.h.
+static const char* const kMimeTypesCacheAllowlist[] = {
+ "text/html", "text/css", "image/gif", "image/jpeg",
+ "image/png", "image/svg+xml", "image/webp", "font/otf",
+ "font/ttf", "font/woff", "font/woff2", "text/javascript"};
+#endif
+
constexpr TimeDelta kStaleRevalidateTimeout = TimeDelta::FromSeconds(60);
// From http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-21#section-6
@@ -3070,7 +3080,27 @@
// (even though the cert status contains the actual errors) and no SSL
// blocking page is shown. An alternative would be to reverse-map the cert
// status to a net error and replay the net error.
- if ((response_.headers->HasHeaderValue("cache-control", "no-store")) ||
+
+#if defined(STARBOARD)
+ // Only allow caching for specific mime types.
+ std::string mime_type;
+ response_.headers->GetMimeType(&mime_type);
+ // TODO(b/243727663): Empty mime types should not get cached either.
+ bool is_allowed_mime_type = mime_type.empty();
+ if (!is_allowed_mime_type) {
+ for (auto allowed_type : kMimeTypesCacheAllowlist) {
+ if (mime_type.compare(allowed_type) == 0) {
+ is_allowed_mime_type = true;
+ break;
+ }
+ }
+ }
+#else
+ bool is_allowed_mime_type = true;
+#endif
+
+ if (!is_allowed_mime_type ||
+ (response_.headers->HasHeaderValue("cache-control", "no-store")) ||
IsCertStatusError(response_.ssl_info.cert_status)) {
bool stopped = StopCachingImpl(false);
DCHECK(stopped);
diff --git a/net/test/embedded_test_server/default_handlers.cc b/net/test/embedded_test_server/default_handlers.cc
index 06eeb1d..f8ca3c5 100644
--- a/net/test/embedded_test_server/default_handlers.cc
+++ b/net/test/embedded_test_server/default_handlers.cc
@@ -102,7 +102,12 @@
http_response->AddCustomHeader("Vary", vary);
http_response->set_content(content);
+#if defined(STARBOARD)
+ // Cobalt does not currently support text/plain caching.
+ http_response->set_content_type("text/html");
+#else
http_response->set_content_type("text/plain");
+#endif
http_response->AddCustomHeader("Cache-Control", cache_control);
return std::move(http_response);
}
diff --git a/starboard/android/shared/audio_renderer_passthrough.cc b/starboard/android/shared/audio_renderer_passthrough.cc
index b2f7671..7056e8d 100644
--- a/starboard/android/shared/audio_renderer_passthrough.cc
+++ b/starboard/android/shared/audio_renderer_passthrough.cc
@@ -349,7 +349,16 @@
SbTime playback_time =
seek_to_time_ + playback_head_position * kSbTimeSecond /
audio_sample_info_.samples_per_second;
- if (paused_ || playback_rate_ == 0.0) {
+
+ // When underlying AudioTrack is paused, we use returned playback time
+ // directly. Note that we should not use |paused_| or |playback_rate_| here.
+ // As we sync audio sink state on |audio_track_thread_|, when |paused_| is set
+ // to false, the underlying AudioTrack may still be paused. In that case, the
+ // returned playback time and last frame consumed time would be out of date.
+ // For example, when resume the playback, if we call GetAudioTimestamp()
+ // before calling AudioTrack.Play(), the returned playback time and last frame
+ // consumed time would be the same as at when we pause the video.
+ if (audio_track_paused_) {
return playback_time;
}
@@ -358,6 +367,10 @@
SB_LOG_IF(WARNING, now < updated_at)
<< "now (" << now << ") is not greater than updated_at (" << updated_at
<< ").";
+ SB_LOG_IF(WARNING, now - updated_at > kSbTimeSecond)
+ << "Elapsed time (" << now - updated_at
+ << ") is greater than 1s. (playback_time " << playback_time << ")";
+
playback_time += std::max<SbTime>(now - updated_at, 0);
return playback_time;
@@ -469,11 +482,13 @@
if (previous_state.playing() != current_state.playing()) {
if (current_state.playing()) {
audio_track_bridge_->Play();
+ audio_track_paused_ = false;
SB_LOG(INFO) << "Played on AudioTrack thread.";
ScopedLock scoped_lock(mutex_);
stop_called_ = false;
} else {
audio_track_bridge_->Pause();
+ audio_track_paused_ = true;
SB_LOG(INFO) << "Paused on AudioTrack thread.";
}
}
diff --git a/starboard/android/shared/audio_renderer_passthrough.h b/starboard/android/shared/audio_renderer_passthrough.h
index 58a073c..2b96d52 100644
--- a/starboard/android/shared/audio_renderer_passthrough.h
+++ b/starboard/android/shared/audio_renderer_passthrough.h
@@ -15,6 +15,7 @@
#ifndef STARBOARD_ANDROID_SHARED_AUDIO_RENDERER_PASSTHROUGH_H_
#define STARBOARD_ANDROID_SHARED_AUDIO_RENDERER_PASSTHROUGH_H_
+#include <atomic>
#include <memory>
#include <queue>
@@ -137,6 +138,8 @@
JobToken update_status_and_write_data_token_;
int64_t total_frames_written_on_audio_track_thread_ = 0;
+ std::atomic_bool audio_track_paused_{true};
+
std::unique_ptr<JobThread> audio_track_thread_;
std::unique_ptr<AudioTrackBridge> audio_track_bridge_;
};
diff --git a/starboard/contrib/linux/stadia/main.cc b/starboard/contrib/linux/stadia/main.cc
index ae44e9f..77edff2 100644
--- a/starboard/contrib/linux/stadia/main.cc
+++ b/starboard/contrib/linux/stadia/main.cc
@@ -33,10 +33,12 @@
#if SB_IS(EVERGREEN_COMPATIBLE)
if (starboard::shared::starboard::CommandLine(argc, argv)
- .HasSwitch(starboard::shared::starboard::kStartHandlerAtCrash)) {
- third_party::crashpad::wrapper::InstallCrashpadHandler(true);
- } else {
+ .HasSwitch(starboard::shared::starboard::kStartHandlerAtLaunch) &&
+ !starboard::shared::starboard::CommandLine(argc, argv)
+ .HasSwitch(starboard::shared::starboard::kStartHandlerAtCrash)) {
third_party::crashpad::wrapper::InstallCrashpadHandler(false);
+ } else {
+ third_party::crashpad::wrapper::InstallCrashpadHandler(true);
}
#endif
diff --git a/starboard/elf_loader/exported_symbols.cc b/starboard/elf_loader/exported_symbols.cc
index f5282ef..d7c3684 100644
--- a/starboard/elf_loader/exported_symbols.cc
+++ b/starboard/elf_loader/exported_symbols.cc
@@ -60,11 +60,42 @@
namespace elf_loader {
ExportedSymbols::ExportedSymbols() {
+ REGISTER_SYMBOL(kSbDefaultMmapThreshold);
+ REGISTER_SYMBOL(kSbFileAltSepChar);
+ REGISTER_SYMBOL(kSbFileAltSepString);
+ REGISTER_SYMBOL(kSbFileMaxName);
+ REGISTER_SYMBOL(kSbFileMaxOpen);
+ REGISTER_SYMBOL(kSbFileMaxPath);
+ REGISTER_SYMBOL(kSbFileSepChar);
+ REGISTER_SYMBOL(kSbFileSepString);
+ REGISTER_SYMBOL(kSbHasAc3Audio);
+ REGISTER_SYMBOL(kSbHasMediaWebmVp9Support);
+ REGISTER_SYMBOL(kSbHasThreadPrioritySupport);
+ REGISTER_SYMBOL(kSbMallocAlignment);
+#if SB_API_VERSION >= 14
+ REGISTER_SYMBOL(kSbMaxSystemPathCacheDirectorySize);
+#endif // SB_API_VERSION >= 14
+ REGISTER_SYMBOL(kSbMaxThreadLocalKeys);
+ REGISTER_SYMBOL(kSbMaxThreadNameLength);
+ REGISTER_SYMBOL(kSbMaxThreads);
+ REGISTER_SYMBOL(kSbMediaMaxAudioBitrateInBitsPerSecond);
+ REGISTER_SYMBOL(kSbMediaMaxVideoBitrateInBitsPerSecond);
+ REGISTER_SYMBOL(kSbMediaVideoFrameAlignment);
+ REGISTER_SYMBOL(kSbMemoryLogPath);
+ REGISTER_SYMBOL(kSbMemoryPageSize);
+ REGISTER_SYMBOL(kSbNetworkReceiveBufferSize);
+ REGISTER_SYMBOL(kSbPathSepChar);
+ REGISTER_SYMBOL(kSbPathSepString);
+ REGISTER_SYMBOL(kSbPreferredRgbaByteOrder);
+ REGISTER_SYMBOL(kSbUserMaxSignedIn);
+ REGISTER_SYMBOL(SbAccessibilityGetCaptionSettings);
REGISTER_SYMBOL(SbAccessibilityGetDisplaySettings);
REGISTER_SYMBOL(SbAccessibilityGetTextToSpeechSettings);
+ REGISTER_SYMBOL(SbAccessibilitySetCaptionsEnabled);
REGISTER_SYMBOL(SbAudioSinkCreate);
REGISTER_SYMBOL(SbAudioSinkDestroy);
REGISTER_SYMBOL(SbAudioSinkGetMaxChannels);
+ REGISTER_SYMBOL(SbAudioSinkGetMinBufferSizeInFrames);
REGISTER_SYMBOL(SbAudioSinkGetNearestSupportedSampleFrequency);
REGISTER_SYMBOL(SbAudioSinkIsAudioFrameStorageTypeSupported);
REGISTER_SYMBOL(SbAudioSinkIsAudioSampleTypeSupported);
@@ -90,6 +121,7 @@
REGISTER_SYMBOL(SbConditionVariableSignal);
REGISTER_SYMBOL(SbConditionVariableWait);
REGISTER_SYMBOL(SbConditionVariableWaitTimed);
+ REGISTER_SYMBOL(SbCPUFeaturesGet);
REGISTER_SYMBOL(SbDecodeTargetGetInfo);
REGISTER_SYMBOL(SbDecodeTargetRelease);
REGISTER_SYMBOL(SbDirectoryCanOpen);
@@ -109,9 +141,12 @@
REGISTER_SYMBOL(SbDrmDestroySystem);
REGISTER_SYMBOL(SbDrmGenerateSessionUpdateRequest);
REGISTER_SYMBOL(SbDrmGetMetrics);
+ REGISTER_SYMBOL(SbDrmIsServerCertificateUpdatable);
+ REGISTER_SYMBOL(SbDrmUpdateServerCertificate);
REGISTER_SYMBOL(SbDrmUpdateSession);
REGISTER_SYMBOL(SbEventCancel);
REGISTER_SYMBOL(SbEventSchedule);
+ REGISTER_SYMBOL(SbFileAtomicReplace);
REGISTER_SYMBOL(SbFileCanOpen);
REGISTER_SYMBOL(SbFileClose);
REGISTER_SYMBOL(SbFileDelete);
@@ -125,19 +160,8 @@
REGISTER_SYMBOL(SbFileSeek);
REGISTER_SYMBOL(SbFileTruncate);
REGISTER_SYMBOL(SbFileWrite);
- REGISTER_SYMBOL(SbMediaGetAudioConfiguration);
- REGISTER_SYMBOL(SbMediaGetAudioOutputCount);
-#if SB_API_VERSION < 13
- REGISTER_SYMBOL(SbMediaIsSupported);
-#endif // SB_API_VERSION < 13
- REGISTER_SYMBOL(SbMemoryAllocate);
- REGISTER_SYMBOL(SbMemoryAllocateAligned);
- REGISTER_SYMBOL(SbMemoryAllocateNoReport);
- REGISTER_SYMBOL(SbMemoryDeallocate);
- REGISTER_SYMBOL(SbMemoryDeallocateAligned);
- REGISTER_SYMBOL(SbMemoryDeallocateNoReport);
- REGISTER_SYMBOL(SbMemoryReallocate);
- REGISTER_SYMBOL(SbMemorySetReporter);
+ REGISTER_SYMBOL(SbGetEglInterface);
+ REGISTER_SYMBOL(SbGetGlesInterface);
REGISTER_SYMBOL(SbImageDecode);
REGISTER_SYMBOL(SbImageIsDecodeSupported);
REGISTER_SYMBOL(SbLog);
@@ -148,23 +172,64 @@
REGISTER_SYMBOL(SbLogRawDumpStack);
REGISTER_SYMBOL(SbLogRawFormat);
REGISTER_SYMBOL(SbMediaCanPlayMimeAndKeySystem);
+ REGISTER_SYMBOL(SbMediaGetAudioBufferBudget);
+ REGISTER_SYMBOL(SbMediaGetAudioConfiguration);
+ REGISTER_SYMBOL(SbMediaGetAudioOutputCount);
+ REGISTER_SYMBOL(SbMediaGetBufferAlignment);
+ REGISTER_SYMBOL(SbMediaGetBufferAllocationUnit);
+ REGISTER_SYMBOL(SbMediaGetBufferGarbageCollectionDurationThreshold);
+ REGISTER_SYMBOL(SbMediaGetBufferPadding);
+ REGISTER_SYMBOL(SbMediaGetBufferStorageType);
+ REGISTER_SYMBOL(SbMediaGetInitialBufferCapacity);
+ REGISTER_SYMBOL(SbMediaGetMaxBufferCapacity);
+ REGISTER_SYMBOL(SbMediaGetProgressiveBufferBudget);
+ REGISTER_SYMBOL(SbMediaGetVideoBufferBudget);
+ REGISTER_SYMBOL(SbMediaIsBufferPoolAllocateOnDemand);
+ REGISTER_SYMBOL(SbMediaIsBufferUsingMemoryPool);
+#if SB_API_VERSION < 13
+ REGISTER_SYMBOL(SbMediaIsSupported);
+#endif // SB_API_VERSION < 13
+ REGISTER_SYMBOL(SbMediaSetAudioWriteDuration);
+ REGISTER_SYMBOL(SbMemoryAllocate);
+ REGISTER_SYMBOL(SbMemoryAllocateAligned);
REGISTER_SYMBOL(SbMemoryAllocateAlignedUnchecked);
+ REGISTER_SYMBOL(SbMemoryAllocateNoReport);
REGISTER_SYMBOL(SbMemoryAllocateUnchecked);
#if SB_API_VERSION < 13
REGISTER_SYMBOL(SbMemoryCompare);
REGISTER_SYMBOL(SbMemoryCopy);
+#endif
+ REGISTER_SYMBOL(SbMemoryDeallocate);
+ REGISTER_SYMBOL(SbMemoryDeallocateAligned);
+ REGISTER_SYMBOL(SbMemoryDeallocateNoReport);
+#if SB_API_VERSION < 13
REGISTER_SYMBOL(SbMemoryFindByte);
#endif
+#if SB_CAN(MAP_EXECUTABLE_MEMORY)
+ REGISTER_SYMBOL(SbMemoryFlush);
+#endif // SB_CAN(MAP_EXECUTABLE_MEMORY)
REGISTER_SYMBOL(SbMemoryFree);
REGISTER_SYMBOL(SbMemoryFreeAligned);
REGISTER_SYMBOL(SbMemoryGetStackBounds);
+ REGISTER_SYMBOL(SbMemoryMap);
#if SB_API_VERSION < 13
REGISTER_SYMBOL(SbMemoryMove);
#endif
+ REGISTER_SYMBOL(SbMemoryProtect);
+ REGISTER_SYMBOL(SbMemoryReallocate);
REGISTER_SYMBOL(SbMemoryReallocateUnchecked);
#if SB_API_VERSION < 13
REGISTER_SYMBOL(SbMemorySet);
#endif
+ REGISTER_SYMBOL(SbMemorySetReporter);
+ REGISTER_SYMBOL(SbMemoryUnmap);
+ REGISTER_SYMBOL(SbMicrophoneClose);
+ REGISTER_SYMBOL(SbMicrophoneCreate);
+ REGISTER_SYMBOL(SbMicrophoneDestroy);
+ REGISTER_SYMBOL(SbMicrophoneGetAvailable);
+ REGISTER_SYMBOL(SbMicrophoneIsSampleRateSupported);
+ REGISTER_SYMBOL(SbMicrophoneOpen);
+ REGISTER_SYMBOL(SbMicrophoneRead);
REGISTER_SYMBOL(SbMutexAcquire);
REGISTER_SYMBOL(SbMutexAcquireTry);
REGISTER_SYMBOL(SbMutexCreate);
@@ -174,10 +239,15 @@
REGISTER_SYMBOL(SbPlayerCreate);
REGISTER_SYMBOL(SbPlayerDestroy);
REGISTER_SYMBOL(SbPlayerGetCurrentFrame);
+ REGISTER_SYMBOL(SbPlayerGetInfo2);
+ REGISTER_SYMBOL(SbPlayerGetMaximumNumberOfSamplesPerWrite);
+ REGISTER_SYMBOL(SbPlayerGetPreferredOutputMode);
+ REGISTER_SYMBOL(SbPlayerSeek2);
REGISTER_SYMBOL(SbPlayerSetBounds);
REGISTER_SYMBOL(SbPlayerSetPlaybackRate);
REGISTER_SYMBOL(SbPlayerSetVolume);
REGISTER_SYMBOL(SbPlayerWriteEndOfStream);
+ REGISTER_SYMBOL(SbPlayerWriteSample2);
REGISTER_SYMBOL(SbSocketAccept);
REGISTER_SYMBOL(SbSocketBind);
REGISTER_SYMBOL(SbSocketClearLastError);
@@ -190,6 +260,7 @@
REGISTER_SYMBOL(SbSocketGetLocalAddress);
REGISTER_SYMBOL(SbSocketIsConnected);
REGISTER_SYMBOL(SbSocketIsConnectedAndIdle);
+ REGISTER_SYMBOL(SbSocketIsIpv6Supported);
REGISTER_SYMBOL(SbSocketJoinMulticastGroup);
REGISTER_SYMBOL(SbSocketListen);
REGISTER_SYMBOL(SbSocketReceiveFrom);
@@ -209,6 +280,17 @@
REGISTER_SYMBOL(SbSocketWaiterWait);
REGISTER_SYMBOL(SbSocketWaiterWaitTimed);
REGISTER_SYMBOL(SbSocketWaiterWakeUp);
+#if SB_API_VERSION == 12
+ REGISTER_SYMBOL(SbSpeechRecognizerCancel);
+ REGISTER_SYMBOL(SbSpeechRecognizerCreate);
+ REGISTER_SYMBOL(SbSpeechRecognizerDestroy);
+ REGISTER_SYMBOL(SbSpeechRecognizerIsSupported);
+ REGISTER_SYMBOL(SbSpeechRecognizerStart);
+ REGISTER_SYMBOL(SbSpeechRecognizerStop);
+#endif // SB_API_VERSION == 12
+ REGISTER_SYMBOL(SbSpeechSynthesisCancel);
+ REGISTER_SYMBOL(SbSpeechSynthesisIsSupported);
+ REGISTER_SYMBOL(SbSpeechSynthesisSpeak);
REGISTER_SYMBOL(SbStorageCloseRecord);
REGISTER_SYMBOL(SbStorageDeleteRecord);
REGISTER_SYMBOL(SbStorageGetRecordSize);
@@ -255,9 +337,11 @@
#endif
REGISTER_SYMBOL(SbSystemGetDeviceType);
REGISTER_SYMBOL(SbSystemGetErrorString);
+ REGISTER_SYMBOL(SbSystemGetExtension);
REGISTER_SYMBOL(SbSystemGetLastError);
REGISTER_SYMBOL(SbSystemGetLocaleId);
REGISTER_SYMBOL(SbSystemGetNumberOfProcessors);
+ REGISTER_SYMBOL(SbSystemGetPath);
REGISTER_SYMBOL(SbSystemGetProperty);
REGISTER_SYMBOL(SbSystemGetRandomData);
REGISTER_SYMBOL(SbSystemGetRandomUInt64);
@@ -269,26 +353,35 @@
REGISTER_SYMBOL(SbSystemHasCapability);
REGISTER_SYMBOL(SbSystemHideSplashScreen);
REGISTER_SYMBOL(SbSystemIsDebuggerAttached);
+#if SB_API_VERSION >= 13
+ REGISTER_SYMBOL(SbSystemNetworkIsDisconnected);
+#endif // SB_API_VERSION >= 13
REGISTER_SYMBOL(SbSystemRaisePlatformError);
#if SB_API_VERSION >= 13
REGISTER_SYMBOL(SbSystemRequestBlur);
REGISTER_SYMBOL(SbSystemRequestConceal);
REGISTER_SYMBOL(SbSystemRequestFocus);
REGISTER_SYMBOL(SbSystemRequestFreeze);
+#endif // SB_API_VERSION >= 13
+#if SB_API_VERSION < 13
+ REGISTER_SYMBOL(SbSystemRequestPause);
+#endif // SB_API_VERSION < 13
+#if SB_API_VERSION >= 13
REGISTER_SYMBOL(SbSystemRequestReveal);
REGISTER_SYMBOL(SbSystemRequestStop);
-#else
- REGISTER_SYMBOL(SbSystemRequestPause);
+#endif // SB_API_VERSION >= 13
+#if SB_API_VERSION < 13
REGISTER_SYMBOL(SbSystemRequestStop);
REGISTER_SYMBOL(SbSystemRequestSuspend);
REGISTER_SYMBOL(SbSystemRequestUnpause);
-#endif // SB_API_VERSION >= 13
-
+#endif // SB_API_VERSION < 13
+ REGISTER_SYMBOL(SbSystemSignWithCertificationSecretKey);
#if SB_API_VERSION < 13
REGISTER_SYMBOL(SbSystemSort);
#endif // SB_API_VERSION < 13
-
+ REGISTER_SYMBOL(SbSystemSupportsResume);
REGISTER_SYMBOL(SbSystemSymbolize);
+ REGISTER_SYMBOL(SbThreadContextGetPointer);
REGISTER_SYMBOL(SbThreadCreate);
REGISTER_SYMBOL(SbThreadCreateLocalKey);
REGISTER_SYMBOL(SbThreadDestroyLocalKey);
@@ -299,134 +392,42 @@
REGISTER_SYMBOL(SbThreadGetName);
REGISTER_SYMBOL(SbThreadIsEqual);
REGISTER_SYMBOL(SbThreadJoin);
- REGISTER_SYMBOL(SbThreadSetLocalValue);
- REGISTER_SYMBOL(SbThreadSetName);
- REGISTER_SYMBOL(SbThreadSleep);
- REGISTER_SYMBOL(SbThreadYield);
- REGISTER_SYMBOL(SbTimeGetMonotonicNow);
- REGISTER_SYMBOL(SbTimeGetNow);
- REGISTER_SYMBOL(SbTimeZoneGetCurrent);
- REGISTER_SYMBOL(SbTimeZoneGetName);
- REGISTER_SYMBOL(SbUserGetCurrent);
- REGISTER_SYMBOL(SbUserGetProperty);
- REGISTER_SYMBOL(SbUserGetPropertySize);
- REGISTER_SYMBOL(SbUserGetSignedIn);
- REGISTER_SYMBOL(SbWindowCreate);
- REGISTER_SYMBOL(SbWindowDestroy);
- REGISTER_SYMBOL(SbWindowGetPlatformHandle);
- REGISTER_SYMBOL(SbWindowGetSize);
- REGISTER_SYMBOL(SbWindowSetDefaultOptions);
- REGISTER_SYMBOL(SbSystemGetPath);
- REGISTER_SYMBOL(SbGetEglInterface);
- REGISTER_SYMBOL(SbGetGlesInterface);
- REGISTER_SYMBOL(SbFileAtomicReplace);
-
-#if SB_CAN(MAP_EXECUTABLE_MEMORY)
- REGISTER_SYMBOL(SbMemoryFlush);
-#endif // SB_CAN(MAP_EXECUTABLE_MEMORY)
-
- REGISTER_SYMBOL(SbPlayerGetPreferredOutputMode);
- REGISTER_SYMBOL(SbMemoryMap);
- REGISTER_SYMBOL(SbMemoryUnmap);
- REGISTER_SYMBOL(SbMemoryProtect);
- REGISTER_SYMBOL(SbUiNavGetInterface);
- REGISTER_SYMBOL(SbWindowBlurOnScreenKeyboard);
- REGISTER_SYMBOL(SbWindowFocusOnScreenKeyboard);
- REGISTER_SYMBOL(SbWindowGetOnScreenKeyboardBoundingRect);
- REGISTER_SYMBOL(SbWindowHideOnScreenKeyboard);
- REGISTER_SYMBOL(SbWindowIsOnScreenKeyboardShown);
- REGISTER_SYMBOL(SbWindowSetOnScreenKeyboardKeepFocus);
- REGISTER_SYMBOL(SbWindowShowOnScreenKeyboard);
- REGISTER_SYMBOL(SbWindowOnScreenKeyboardSuggestionsSupported);
- REGISTER_SYMBOL(SbWindowUpdateOnScreenKeyboardSuggestions);
- REGISTER_SYMBOL(SbWindowOnScreenKeyboardIsSupported);
- REGISTER_SYMBOL(SbAccessibilityGetCaptionSettings);
- REGISTER_SYMBOL(SbAccessibilitySetCaptionsEnabled);
- REGISTER_SYMBOL(SbMicrophoneClose);
- REGISTER_SYMBOL(SbMicrophoneCreate);
- REGISTER_SYMBOL(SbMicrophoneDestroy);
- REGISTER_SYMBOL(SbMicrophoneGetAvailable);
- REGISTER_SYMBOL(SbMicrophoneIsSampleRateSupported);
- REGISTER_SYMBOL(SbMicrophoneOpen);
- REGISTER_SYMBOL(SbMicrophoneRead);
- REGISTER_SYMBOL(SbSocketIsIpv6Supported);
- REGISTER_SYMBOL(SbSpeechSynthesisCancel);
- REGISTER_SYMBOL(SbSpeechSynthesisSpeak);
- REGISTER_SYMBOL(SbTimeGetMonotonicThreadNow);
-#if SB_API_VERSION == 12
- REGISTER_SYMBOL(SbSpeechRecognizerIsSupported);
-#endif
-#if SB_API_VERSION == 12
- REGISTER_SYMBOL(SbSpeechRecognizerCreate);
- REGISTER_SYMBOL(SbSpeechRecognizerDestroy);
- REGISTER_SYMBOL(SbSpeechRecognizerStart);
- REGISTER_SYMBOL(SbSpeechRecognizerStop);
- REGISTER_SYMBOL(SbSpeechRecognizerCancel);
-#endif // SB_API_VERSION == 12
- REGISTER_SYMBOL(SbSpeechSynthesisIsSupported);
- REGISTER_SYMBOL(SbTimeIsTimeThreadNowSupported);
- REGISTER_SYMBOL(SbDrmIsServerCertificateUpdatable);
- REGISTER_SYMBOL(SbDrmUpdateServerCertificate);
- REGISTER_SYMBOL(SbMediaGetAudioBufferBudget);
- REGISTER_SYMBOL(SbMediaGetBufferAlignment);
- REGISTER_SYMBOL(SbMediaGetBufferAllocationUnit);
- REGISTER_SYMBOL(SbMediaGetBufferGarbageCollectionDurationThreshold);
- REGISTER_SYMBOL(SbMediaGetBufferPadding);
- REGISTER_SYMBOL(SbMediaGetBufferStorageType);
- REGISTER_SYMBOL(SbMediaGetInitialBufferCapacity);
- REGISTER_SYMBOL(SbMediaGetMaxBufferCapacity);
- REGISTER_SYMBOL(SbMediaGetProgressiveBufferBudget);
- REGISTER_SYMBOL(SbMediaGetVideoBufferBudget);
- REGISTER_SYMBOL(SbMediaIsBufferPoolAllocateOnDemand);
- REGISTER_SYMBOL(SbMediaIsBufferUsingMemoryPool);
- REGISTER_SYMBOL(SbPlayerGetInfo2);
- REGISTER_SYMBOL(SbPlayerGetMaximumNumberOfSamplesPerWrite);
- REGISTER_SYMBOL(SbPlayerSeek2);
- REGISTER_SYMBOL(SbPlayerWriteSample2);
- REGISTER_SYMBOL(SbSystemSupportsResume);
- REGISTER_SYMBOL(SbAudioSinkGetMinBufferSizeInFrames);
- REGISTER_SYMBOL(SbCPUFeaturesGet);
- REGISTER_SYMBOL(SbMediaSetAudioWriteDuration);
- REGISTER_SYMBOL(SbSystemGetExtension);
- REGISTER_SYMBOL(SbSystemSignWithCertificationSecretKey);
- REGISTER_SYMBOL(SbThreadContextGetPointer);
REGISTER_SYMBOL(SbThreadSamplerCreate);
REGISTER_SYMBOL(SbThreadSamplerDestroy);
REGISTER_SYMBOL(SbThreadSamplerFreeze);
REGISTER_SYMBOL(SbThreadSamplerIsSupported);
REGISTER_SYMBOL(SbThreadSamplerThaw);
+ REGISTER_SYMBOL(SbThreadSetLocalValue);
+ REGISTER_SYMBOL(SbThreadSetName);
+ REGISTER_SYMBOL(SbThreadSleep);
+ REGISTER_SYMBOL(SbThreadYield);
+ REGISTER_SYMBOL(SbTimeGetMonotonicNow);
+ REGISTER_SYMBOL(SbTimeGetMonotonicThreadNow);
+ REGISTER_SYMBOL(SbTimeGetNow);
+ REGISTER_SYMBOL(SbTimeIsTimeThreadNowSupported);
+ REGISTER_SYMBOL(SbTimeZoneGetCurrent);
+ REGISTER_SYMBOL(SbTimeZoneGetName);
+ REGISTER_SYMBOL(SbUiNavGetInterface);
+ REGISTER_SYMBOL(SbUserGetCurrent);
+ REGISTER_SYMBOL(SbUserGetProperty);
+ REGISTER_SYMBOL(SbUserGetPropertySize);
+ REGISTER_SYMBOL(SbUserGetSignedIn);
+ REGISTER_SYMBOL(SbWindowBlurOnScreenKeyboard);
+ REGISTER_SYMBOL(SbWindowCreate);
+ REGISTER_SYMBOL(SbWindowDestroy);
+ REGISTER_SYMBOL(SbWindowFocusOnScreenKeyboard);
REGISTER_SYMBOL(SbWindowGetDiagonalSizeInInches);
- REGISTER_SYMBOL(kSbDefaultMmapThreshold);
- REGISTER_SYMBOL(kSbFileMaxName);
- REGISTER_SYMBOL(kSbFileMaxOpen);
- REGISTER_SYMBOL(kSbFileAltSepChar);
- REGISTER_SYMBOL(kSbFileAltSepString);
- REGISTER_SYMBOL(kSbFileMaxPath);
- REGISTER_SYMBOL(kSbFileSepChar);
- REGISTER_SYMBOL(kSbFileSepString);
- REGISTER_SYMBOL(kSbHasAc3Audio);
- REGISTER_SYMBOL(kSbHasMediaWebmVp9Support);
- REGISTER_SYMBOL(kSbHasThreadPrioritySupport);
- REGISTER_SYMBOL(kSbMallocAlignment);
-#if SB_API_VERSION >= 14
- REGISTER_SYMBOL(kSbMaxSystemPathCacheDirectorySize);
-#endif // SB_API_VERSION >= 14
- REGISTER_SYMBOL(kSbMaxThreadLocalKeys);
- REGISTER_SYMBOL(kSbMaxThreadNameLength);
- REGISTER_SYMBOL(kSbMediaMaxAudioBitrateInBitsPerSecond);
- REGISTER_SYMBOL(kSbMediaMaxVideoBitrateInBitsPerSecond);
- REGISTER_SYMBOL(kSbMediaVideoFrameAlignment);
- REGISTER_SYMBOL(kSbMemoryLogPath);
- REGISTER_SYMBOL(kSbMemoryPageSize);
- REGISTER_SYMBOL(kSbNetworkReceiveBufferSize);
- REGISTER_SYMBOL(kSbMaxThreads);
- REGISTER_SYMBOL(kSbPathSepChar);
- REGISTER_SYMBOL(kSbPathSepString);
- REGISTER_SYMBOL(kSbPreferredRgbaByteOrder);
- REGISTER_SYMBOL(kSbUserMaxSignedIn);
-#if SB_API_VERSION >= 13
- REGISTER_SYMBOL(SbSystemNetworkIsDisconnected);
-#endif // SB_API_VERSION >= 13
+ REGISTER_SYMBOL(SbWindowGetOnScreenKeyboardBoundingRect);
+ REGISTER_SYMBOL(SbWindowGetPlatformHandle);
+ REGISTER_SYMBOL(SbWindowGetSize);
+ REGISTER_SYMBOL(SbWindowHideOnScreenKeyboard);
+ REGISTER_SYMBOL(SbWindowIsOnScreenKeyboardShown);
+ REGISTER_SYMBOL(SbWindowOnScreenKeyboardIsSupported);
+ REGISTER_SYMBOL(SbWindowOnScreenKeyboardSuggestionsSupported);
+ REGISTER_SYMBOL(SbWindowSetDefaultOptions);
+ REGISTER_SYMBOL(SbWindowSetOnScreenKeyboardKeepFocus);
+ REGISTER_SYMBOL(SbWindowShowOnScreenKeyboard);
+ REGISTER_SYMBOL(SbWindowUpdateOnScreenKeyboardSuggestions);
} // NOLINT
const void* ExportedSymbols::Lookup(const char* name) {
diff --git a/starboard/linux/x64x11/main.cc b/starboard/linux/x64x11/main.cc
index d2bb68a..56e1caa 100644
--- a/starboard/linux/x64x11/main.cc
+++ b/starboard/linux/x64x11/main.cc
@@ -35,10 +35,12 @@
#if SB_IS(EVERGREEN_COMPATIBLE)
if (starboard::shared::starboard::CommandLine(argc, argv)
- .HasSwitch(starboard::shared::starboard::kStartHandlerAtCrash)) {
- third_party::crashpad::wrapper::InstallCrashpadHandler(true);
- } else {
+ .HasSwitch(starboard::shared::starboard::kStartHandlerAtLaunch) &&
+ !starboard::shared::starboard::CommandLine(argc, argv)
+ .HasSwitch(starboard::shared::starboard::kStartHandlerAtCrash)) {
third_party::crashpad::wrapper::InstallCrashpadHandler(false);
+ } else {
+ third_party::crashpad::wrapper::InstallCrashpadHandler(true);
}
#endif
diff --git a/starboard/raspi/shared/main.cc b/starboard/raspi/shared/main.cc
index d935df8..ee0d66c 100644
--- a/starboard/raspi/shared/main.cc
+++ b/starboard/raspi/shared/main.cc
@@ -38,10 +38,12 @@
#if SB_IS(EVERGREEN_COMPATIBLE)
if (starboard::shared::starboard::CommandLine(argc, argv)
- .HasSwitch(starboard::shared::starboard::kStartHandlerAtCrash)) {
- third_party::crashpad::wrapper::InstallCrashpadHandler(true);
- } else {
+ .HasSwitch(starboard::shared::starboard::kStartHandlerAtLaunch) &&
+ !starboard::shared::starboard::CommandLine(argc, argv)
+ .HasSwitch(starboard::shared::starboard::kStartHandlerAtCrash)) {
third_party::crashpad::wrapper::InstallCrashpadHandler(false);
+ } else {
+ third_party::crashpad::wrapper::InstallCrashpadHandler(true);
}
#endif
starboard::raspi::shared::ApplicationDispmanx application;
diff --git a/starboard/shared/starboard/player/filter/BUILD.gn b/starboard/shared/starboard/player/filter/BUILD.gn
index c37a424..f5f9d4f 100644
--- a/starboard/shared/starboard/player/filter/BUILD.gn
+++ b/starboard/shared/starboard/player/filter/BUILD.gn
@@ -23,8 +23,8 @@
"//starboard/shared/starboard/player/filter/audio_frame_tracker.cc",
"//starboard/shared/starboard/player/filter/audio_frame_tracker.h",
"//starboard/shared/starboard/player/filter/audio_renderer_internal.h",
- "//starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc",
- "//starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h",
+ "//starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.cc",
+ "//starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.h",
"//starboard/shared/starboard/player/filter/audio_renderer_sink.h",
"//starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc",
"//starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h",
diff --git a/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc b/starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.cc
similarity index 87%
rename from starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc
rename to starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.cc
index 5e0536b..709cd8b 100644
--- a/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc
+++ b/starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.h"
#include <algorithm>
#include <string>
@@ -29,7 +29,7 @@
namespace {
// This class works only when the input format and output format are the same.
-// It allows for a simplified AudioRendererImpl implementation by always using a
+// It allows for a simplified AudioRendererPcm implementation by always using a
// resampler.
class IdentityAudioResampler : public AudioResampler {
public:
@@ -50,7 +50,7 @@
bool eos_reached_;
};
-// AudioRendererImpl uses AudioTimeStretcher internally to adjust to playback
+// AudioRendererPcm uses AudioTimeStretcher internally to adjust to playback
// rate. So we try to use kSbMediaAudioSampleTypeFloat32 and only use
// kSbMediaAudioSampleTypeInt16Deprecated when float32 is not supported. To use
// kSbMediaAudioSampleTypeFloat32 will cause an extra conversion from float32 to
@@ -65,7 +65,7 @@
} // namespace
-AudioRendererImpl::AudioRendererImpl(
+AudioRendererPcm::AudioRendererPcm(
scoped_ptr<AudioDecoder> decoder,
scoped_ptr<AudioRendererSink> audio_renderer_sink,
const SbMediaAudioSampleInfo& audio_sample_info,
@@ -80,9 +80,9 @@
frames_consumed_set_at_(SbTimeGetMonotonicNow()),
decoder_(decoder.Pass()),
process_audio_data_job_(
- std::bind(&AudioRendererImpl::ProcessAudioData, this)),
+ std::bind(&AudioRendererPcm::ProcessAudioData, this)),
audio_renderer_sink_(audio_renderer_sink.Pass()) {
- SB_DLOG(INFO) << "Creating AudioRendererImpl with " << channels_
+ SB_DLOG(INFO) << "Creating AudioRendererPcm with " << channels_
<< " channels, " << bytes_per_frame_ << " bytes per frame, "
<< max_cached_frames_ << " max cached frames, and "
<< min_frames_per_append_ << " min frames per append.";
@@ -93,22 +93,22 @@
frame_buffers_[0] = &frame_buffer_[0];
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
- Schedule(std::bind(&AudioRendererImpl::CheckAudioSinkStatus, this),
+ Schedule(std::bind(&AudioRendererPcm::CheckAudioSinkStatus, this),
kCheckAudioSinkStatusInterval);
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
}
-AudioRendererImpl::~AudioRendererImpl() {
- SB_DLOG(INFO) << "Destroying AudioRendererImpl with " << channels_
+AudioRendererPcm::~AudioRendererPcm() {
+ SB_DLOG(INFO) << "Destroying AudioRendererPcm with " << channels_
<< " channels, " << bytes_per_frame_ << " bytes per frame, "
<< max_cached_frames_ << " max cached frames, and "
<< min_frames_per_append_ << " min frames per append.";
SB_DCHECK(BelongsToCurrentThread());
}
-void AudioRendererImpl::Initialize(const ErrorCB& error_cb,
- const PrerolledCB& prerolled_cb,
- const EndedCB& ended_cb) {
+void AudioRendererPcm::Initialize(const ErrorCB& error_cb,
+ const PrerolledCB& prerolled_cb,
+ const EndedCB& ended_cb) {
SB_DCHECK(error_cb);
SB_DCHECK(prerolled_cb);
SB_DCHECK(ended_cb);
@@ -120,11 +120,11 @@
prerolled_cb_ = prerolled_cb;
ended_cb_ = ended_cb;
- decoder_->Initialize(std::bind(&AudioRendererImpl::OnDecoderOutput, this),
+ decoder_->Initialize(std::bind(&AudioRendererPcm::OnDecoderOutput, this),
error_cb);
}
-void AudioRendererImpl::WriteSample(
+void AudioRendererPcm::WriteSample(
const scoped_refptr<InputBuffer>& input_buffer) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(input_buffer);
@@ -139,11 +139,11 @@
can_accept_more_data_ = false;
decoder_->Decode(input_buffer,
- std::bind(&AudioRendererImpl::OnDecoderConsumed, this));
+ std::bind(&AudioRendererPcm::OnDecoderConsumed, this));
first_input_written_ = true;
}
-void AudioRendererImpl::WriteEndOfStream() {
+void AudioRendererPcm::WriteEndOfStream() {
SB_DCHECK(BelongsToCurrentThread());
// TODO: Check |can_accept_more_data_| and make WriteEndOfStream() depend on
// CanAcceptMoreData() or callback.
@@ -162,28 +162,28 @@
first_input_written_ = true;
}
-void AudioRendererImpl::SetVolume(double volume) {
+void AudioRendererPcm::SetVolume(double volume) {
SB_DCHECK(BelongsToCurrentThread());
audio_renderer_sink_->SetVolume(volume);
}
-bool AudioRendererImpl::IsEndOfStreamWritten() const {
+bool AudioRendererPcm::IsEndOfStreamWritten() const {
SB_DCHECK(BelongsToCurrentThread());
return eos_state_ >= kEOSWrittenToDecoder;
}
-bool AudioRendererImpl::IsEndOfStreamPlayed() const {
+bool AudioRendererPcm::IsEndOfStreamPlayed() const {
ScopedLock lock(mutex_);
return IsEndOfStreamPlayed_Locked();
}
-bool AudioRendererImpl::CanAcceptMoreData() const {
+bool AudioRendererPcm::CanAcceptMoreData() const {
SB_DCHECK(BelongsToCurrentThread());
return eos_state_ == kEOSNotReceived && can_accept_more_data_ &&
(!decoder_sample_rate_ || !time_stretcher_.IsQueueFull());
}
-void AudioRendererImpl::Play() {
+void AudioRendererPcm::Play() {
SB_DCHECK(BelongsToCurrentThread());
ScopedLock lock(mutex_);
@@ -191,14 +191,14 @@
consume_frames_called_ = false;
}
-void AudioRendererImpl::Pause() {
+void AudioRendererPcm::Pause() {
SB_DCHECK(BelongsToCurrentThread());
ScopedLock lock(mutex_);
paused_ = true;
}
-void AudioRendererImpl::SetPlaybackRate(double playback_rate) {
+void AudioRendererPcm::SetPlaybackRate(double playback_rate) {
SB_DCHECK(BelongsToCurrentThread());
ScopedLock lock(mutex_);
@@ -223,7 +223,7 @@
}
}
-void AudioRendererImpl::Seek(SbTime seek_to_time) {
+void AudioRendererPcm::Seek(SbTime seek_to_time) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(seek_to_time >= 0);
@@ -272,15 +272,15 @@
CancelPendingJobs();
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
- Schedule(std::bind(&AudioRendererImpl::CheckAudioSinkStatus, this),
+ Schedule(std::bind(&AudioRendererPcm::CheckAudioSinkStatus, this),
kCheckAudioSinkStatusInterval);
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
}
-SbTime AudioRendererImpl::GetCurrentMediaTime(bool* is_playing,
- bool* is_eos_played,
- bool* is_underflow,
- double* playback_rate) {
+SbTime AudioRendererPcm::GetCurrentMediaTime(bool* is_playing,
+ bool* is_eos_played,
+ bool* is_underflow,
+ double* playback_rate) {
SB_DCHECK(is_playing);
SB_DCHECK(is_eos_played);
SB_DCHECK(is_underflow);
@@ -364,10 +364,10 @@
return media_time;
}
-void AudioRendererImpl::GetSourceStatus(int* frames_in_buffer,
- int* offset_in_frames,
- bool* is_playing,
- bool* is_eos_reached) {
+void AudioRendererPcm::GetSourceStatus(int* frames_in_buffer,
+ int* offset_in_frames,
+ bool* is_playing,
+ bool* is_eos_reached) {
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
sink_callbacks_since_last_check_.increment();
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
@@ -406,14 +406,13 @@
if (silence_frames_to_write <= max_cached_frames_ - start_offset) {
memset(frame_buffer_.data() + start_offset * bytes_per_frame_, 0,
- silence_frames_to_write * bytes_per_frame_);
+ silence_frames_to_write * bytes_per_frame_);
} else {
memset(frame_buffer_.data() + start_offset * bytes_per_frame_, 0,
- (max_cached_frames_ - start_offset) * bytes_per_frame_);
- memset(
- frame_buffer_.data(), 0,
- (silence_frames_to_write - max_cached_frames_ + start_offset) *
- bytes_per_frame_);
+ (max_cached_frames_ - start_offset) * bytes_per_frame_);
+ memset(frame_buffer_.data(), 0,
+ (silence_frames_to_write - max_cached_frames_ + start_offset) *
+ bytes_per_frame_);
}
silence_frames_written_after_eos_on_sink_thread_ +=
silence_frames_to_write;
@@ -422,8 +421,8 @@
}
}
-void AudioRendererImpl::ConsumeFrames(int frames_consumed,
- SbTime frames_consumed_at) {
+void AudioRendererPcm::ConsumeFrames(int frames_consumed,
+ SbTime frames_consumed_at) {
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
sink_callbacks_since_last_check_.increment();
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
@@ -450,8 +449,8 @@
}
}
-void AudioRendererImpl::OnError(bool capability_changed,
- const std::string& error_message) {
+void AudioRendererPcm::OnError(bool capability_changed,
+ const std::string& error_message) {
SB_DCHECK(error_cb_);
if (capability_changed) {
error_cb_(kSbPlayerErrorCapabilityChanged, error_message);
@@ -463,7 +462,7 @@
}
}
-void AudioRendererImpl::UpdateVariablesOnSinkThread_Locked(
+void AudioRendererPcm::UpdateVariablesOnSinkThread_Locked(
SbTime system_time_on_consume_frames) {
mutex_.DCheckAcquired();
@@ -504,7 +503,7 @@
}
}
-void AudioRendererImpl::OnFirstOutput(
+void AudioRendererPcm::OnFirstOutput(
const SbMediaAudioSampleType decoded_sample_type,
const SbMediaAudioFrameStorageType decoded_storage_type,
const int decoded_sample_rate) {
@@ -544,13 +543,13 @@
}
}
-bool AudioRendererImpl::IsEndOfStreamPlayed_Locked() const {
+bool AudioRendererPcm::IsEndOfStreamPlayed_Locked() const {
mutex_.DCheckAcquired();
return eos_state_ >= kEOSSentToSink &&
total_frames_sent_to_sink_ == total_frames_consumed_by_sink_;
}
-void AudioRendererImpl::OnDecoderConsumed() {
+void AudioRendererPcm::OnDecoderConsumed() {
SB_DCHECK(BelongsToCurrentThread());
// TODO: Unify EOS and non EOS request once WriteEndOfStream() depends on
@@ -562,7 +561,7 @@
}
}
-void AudioRendererImpl::OnDecoderOutput() {
+void AudioRendererPcm::OnDecoderOutput() {
SB_DCHECK(BelongsToCurrentThread());
++pending_decoder_outputs_;
@@ -575,7 +574,7 @@
ProcessAudioData();
}
-void AudioRendererImpl::ProcessAudioData() {
+void AudioRendererPcm::ProcessAudioData() {
SB_DCHECK(BelongsToCurrentThread());
process_audio_data_job_token_.ResetToInvalid();
@@ -673,7 +672,7 @@
}
}
-bool AudioRendererImpl::AppendAudioToFrameBuffer(bool* is_frame_buffer_full) {
+bool AudioRendererPcm::AppendAudioToFrameBuffer(bool* is_frame_buffer_full) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(is_frame_buffer_full);
@@ -722,17 +721,16 @@
int frames_appended = 0;
if (frames_to_append > max_cached_frames_ - offset_to_append) {
- memcpy(&frame_buffer_[offset_to_append * bytes_per_frame_],
- source_buffer,
- (max_cached_frames_ - offset_to_append) * bytes_per_frame_);
+ memcpy(&frame_buffer_[offset_to_append * bytes_per_frame_], source_buffer,
+ (max_cached_frames_ - offset_to_append) * bytes_per_frame_);
source_buffer += (max_cached_frames_ - offset_to_append) * bytes_per_frame_;
frames_to_append -= max_cached_frames_ - offset_to_append;
frames_appended += max_cached_frames_ - offset_to_append;
offset_to_append = 0;
}
- memcpy(&frame_buffer_[offset_to_append * bytes_per_frame_],
- source_buffer, frames_to_append * bytes_per_frame_);
+ memcpy(&frame_buffer_[offset_to_append * bytes_per_frame_], source_buffer,
+ frames_to_append * bytes_per_frame_);
frames_appended += frames_to_append;
total_frames_sent_to_sink_ += frames_appended;
@@ -741,7 +739,7 @@
}
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
-void AudioRendererImpl::CheckAudioSinkStatus() {
+void AudioRendererPcm::CheckAudioSinkStatus() {
SB_DCHECK(BelongsToCurrentThread());
// Check if sink callbacks are called too frequently.
@@ -770,7 +768,7 @@
<< sink_callbacks_since_last_check
<< " callbacks since last check.";
}
- Schedule(std::bind(&AudioRendererImpl::CheckAudioSinkStatus, this),
+ Schedule(std::bind(&AudioRendererPcm::CheckAudioSinkStatus, this),
kCheckAudioSinkStatusInterval);
}
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
diff --git a/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h b/starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.h
similarity index 92%
rename from starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h
rename to starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.h
index 1129b9d..7c37d7b 100644
--- a/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h
+++ b/starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_IMPL_H_
-#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_IMPL_H_
+#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_PCM_H_
+#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_PCM_H_
#include <functional>
#include <string>
@@ -54,10 +54,10 @@
// A class that sits in between the audio decoder, the audio sink and the
// pipeline to coordinate data transfer between these parties. It also serves
// as the authority of playback time.
-class AudioRendererImpl : public AudioRenderer,
- public MediaTimeProvider,
- private AudioRendererSink::RenderCallback,
- private JobQueue::JobOwner {
+class AudioRendererPcm : public AudioRenderer,
+ public MediaTimeProvider,
+ private AudioRendererSink::RenderCallback,
+ private JobQueue::JobOwner {
public:
// |max_cached_frames| is a soft limit for the max audio frames this class can
// cache so it can:
@@ -66,12 +66,12 @@
// longer accept more data.
// |min_frames_per_append| is the min number of frames that the audio renderer
// tries to append to the sink buffer at once.
- AudioRendererImpl(scoped_ptr<AudioDecoder> decoder,
- scoped_ptr<AudioRendererSink> audio_renderer_sink,
- const SbMediaAudioSampleInfo& audio_sample_info,
- int max_cached_frames,
- int min_frames_per_append);
- ~AudioRendererImpl() override;
+ AudioRendererPcm(scoped_ptr<AudioDecoder> decoder,
+ scoped_ptr<AudioRendererSink> audio_renderer_sink,
+ const SbMediaAudioSampleInfo& audio_sample_info,
+ int max_cached_frames,
+ int min_frames_per_append);
+ ~AudioRendererPcm() override;
void Initialize(const ErrorCB& error_cb,
const PrerolledCB& prerolled_cb,
@@ -215,4 +215,4 @@
} // namespace shared
} // namespace starboard
-#endif // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_IMPL_H_
+#endif // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_PCM_H_
diff --git a/starboard/shared/starboard/player/filter/audio_renderer_sink.h b/starboard/shared/starboard/player/filter/audio_renderer_sink.h
index 5aa8a1f..de4e394 100644
--- a/starboard/shared/starboard/player/filter/audio_renderer_sink.h
+++ b/starboard/shared/starboard/player/filter/audio_renderer_sink.h
@@ -27,7 +27,7 @@
namespace player {
namespace filter {
-// The interface used by AudioRendererImpl to output audio samples.
+// The interface used by AudioRendererPcm to output audio samples.
class AudioRendererSink {
public:
class RenderCallback {
diff --git a/starboard/shared/starboard/player/filter/player_components.cc b/starboard/shared/starboard/player/filter/player_components.cc
index f8eb7b0..94d71e0 100644
--- a/starboard/shared/starboard/player/filter/player_components.cc
+++ b/starboard/shared/starboard/player/filter/player_components.cc
@@ -18,7 +18,7 @@
#include "starboard/shared/starboard/application.h"
#include "starboard/shared/starboard/command_line.h"
#include "starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h"
-#include "starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.h"
#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h"
#include "starboard/shared/starboard/player/filter/media_time_provider_impl.h"
#include "starboard/shared/starboard/player/filter/punchout_video_renderer_sink.h"
@@ -52,7 +52,7 @@
class PlayerComponentsImpl : public PlayerComponents {
public:
PlayerComponentsImpl(scoped_ptr<MediaTimeProviderImpl> media_time_provider,
- scoped_ptr<AudioRendererImpl> audio_renderer,
+ scoped_ptr<AudioRendererPcm> audio_renderer,
scoped_ptr<VideoRendererImpl> video_renderer)
: media_time_provider_(media_time_provider.Pass()),
audio_renderer_(audio_renderer.Pass()),
@@ -72,7 +72,7 @@
private:
// |media_time_provider_| will only be used when |audio_renderer_| is nullptr.
scoped_ptr<MediaTimeProviderImpl> media_time_provider_;
- scoped_ptr<AudioRendererImpl> audio_renderer_;
+ scoped_ptr<AudioRendererPcm> audio_renderer_;
scoped_ptr<VideoRendererImpl> video_renderer_;
};
@@ -216,7 +216,7 @@
}
scoped_ptr<MediaTimeProviderImpl> media_time_provider_impl;
- scoped_ptr<AudioRendererImpl> audio_renderer;
+ scoped_ptr<AudioRendererPcm> audio_renderer;
scoped_ptr<VideoRendererImpl> video_renderer;
if (creation_parameters.audio_codec() != kSbMediaAudioCodecNone) {
@@ -228,9 +228,9 @@
&min_frames_per_append);
audio_renderer.reset(
- new AudioRendererImpl(audio_decoder.Pass(), audio_renderer_sink.Pass(),
- creation_parameters.audio_sample_info(),
- max_cached_frames, min_frames_per_append));
+ new AudioRendererPcm(audio_decoder.Pass(), audio_renderer_sink.Pass(),
+ creation_parameters.audio_sample_info(),
+ max_cached_frames, min_frames_per_append));
}
if (creation_parameters.video_codec() != kSbMediaVideoCodecNone) {
diff --git a/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc b/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
index c7b15c9..ae7e57c 100644
--- a/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
+++ b/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.h"
#include <functional>
#include <set>
@@ -114,7 +114,7 @@
const int kMaxCachedFrames = 256 * 1024;
const int kMaxFramesPerAppend = 16384;
- audio_renderer_.reset(new AudioRendererImpl(
+ audio_renderer_.reset(new AudioRendererPcm(
make_scoped_ptr<AudioDecoder>(audio_decoder_),
make_scoped_ptr<AudioRendererSink>(audio_renderer_sink_),
GetDefaultAudioSampleInfo(), kMaxCachedFrames, kMaxFramesPerAppend));
@@ -231,7 +231,7 @@
AudioDecoder::ConsumedCB consumed_cb_;
bool prerolled_ = true;
- scoped_ptr<AudioRendererImpl> audio_renderer_;
+ scoped_ptr<AudioRendererPcm> audio_renderer_;
MockAudioDecoder* audio_decoder_;
MockAudioRendererSink* audio_renderer_sink_;
AudioRendererSink::RenderCallback* renderer_callback_;
diff --git a/starboard/shared/starboard/starboard_switches.cc b/starboard/shared/starboard/starboard_switches.cc
index 7da02f4..ad4917e 100644
--- a/starboard/shared/starboard/starboard_switches.cc
+++ b/starboard/shared/starboard/starboard_switches.cc
@@ -19,6 +19,7 @@
namespace starboard {
const char kStartHandlerAtCrash[] = "start_handler_at_crash";
+const char kStartHandlerAtLaunch[] = "start_handler_at_launch";
} // namespace starboard
} // namespace shared
diff --git a/starboard/shared/starboard/starboard_switches.h b/starboard/shared/starboard/starboard_switches.h
index 025e03b..55fea4e 100644
--- a/starboard/shared/starboard/starboard_switches.h
+++ b/starboard/shared/starboard/starboard_switches.h
@@ -25,6 +25,10 @@
// before the app runs and keeping it running all the time. This option reduces
// memory consumption by the crash handler.
extern const char kStartHandlerAtCrash[];
+// Use this flag to start the handler
+// before the app launches. Without this flag, the crash handler starts only
+// when a crash happens. This option increases the memory consumption.
+extern const char kStartHandlerAtLaunch[];
} // namespace starboard
} // namespace shared
diff --git a/starboard/shared/test_webapi_extension/BUILD.gn b/starboard/shared/test_webapi_extension/BUILD.gn
deleted file mode 100644
index 331ced9..0000000
--- a/starboard/shared/test_webapi_extension/BUILD.gn
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2021 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.
-
-static_library("cobalt_test_webapi_extension") {
- # List of all source files and header files needed to support the IDL
- # definitions.
- sources = [
- "my_new_interface.cc",
- "my_new_interface.h",
- "webapi_extension.cc",
- ]
-
- deps = [
- "//base",
- "//cobalt/dom",
- "//cobalt/script",
- ]
-}
diff --git a/starboard/shared/test_webapi_extension/my_new_enum.idl b/starboard/shared/test_webapi_extension/my_new_enum.idl
deleted file mode 100644
index 8d2f185..0000000
--- a/starboard/shared/test_webapi_extension/my_new_enum.idl
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 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.
-
-enum MyNewEnum {
- "apples",
- "oranges",
- "peaches"
-};
diff --git a/starboard/shared/test_webapi_extension/my_new_interface.cc b/starboard/shared/test_webapi_extension/my_new_interface.cc
deleted file mode 100644
index e704629..0000000
--- a/starboard/shared/test_webapi_extension/my_new_interface.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 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 "starboard/shared/test_webapi_extension/my_new_interface.h"
-
-namespace cobalt {
-namespace webapi_extension {
-
-MyNewInterface::MyNewInterface(const scoped_refptr<dom::Window>& window) {
- // Provide an initial value for the enum.
- enum_value_ = kMyNewEnumApples;
-}
-
-MyNewInterface::~MyNewInterface() {}
-
-} // namespace webapi_extension
-} // namespace cobalt
diff --git a/starboard/shared/test_webapi_extension/my_new_interface.h b/starboard/shared/test_webapi_extension/my_new_interface.h
deleted file mode 100644
index 29a1fdb..0000000
--- a/starboard/shared/test_webapi_extension/my_new_interface.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2017 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 STARBOARD_SHARED_TEST_WEBAPI_EXTENSION_MY_NEW_INTERFACE_H_
-#define STARBOARD_SHARED_TEST_WEBAPI_EXTENSION_MY_NEW_INTERFACE_H_
-
-#include <string>
-
-#include "cobalt/dom/window.h"
-#include "cobalt/script/wrappable.h"
-#include "starboard/shared/test_webapi_extension/my_new_enum.h"
-
-namespace cobalt {
-namespace webapi_extension {
-
-class MyNewInterface : public script::Wrappable {
- public:
- explicit MyNewInterface(const scoped_refptr<dom::Window>& window);
-
- const std::string& foo() const { return foo_; }
- void set_foo(const std::string& value) { foo_ = value; }
-
- void SetMyNewEnum(MyNewEnum value) { enum_value_ = value; }
- MyNewEnum GetMyNewEnum() const { return enum_value_; }
-
- // All types derived from script::Wrappable must have this annotation.
- DEFINE_WRAPPABLE_TYPE(MyNewInterface);
-
- private:
- // Since script::Wrappable inherits from base::RefCounted<>, we make the
- // destructor private.
- ~MyNewInterface() override;
-
- std::string foo_;
-
- MyNewEnum enum_value_;
-
- DISALLOW_COPY_AND_ASSIGN(MyNewInterface);
-};
-
-} // namespace webapi_extension
-} // namespace cobalt
-
-#endif // STARBOARD_SHARED_TEST_WEBAPI_EXTENSION_MY_NEW_INTERFACE_H_
diff --git a/starboard/shared/test_webapi_extension/webapi_extension.cc b/starboard/shared/test_webapi_extension/webapi_extension.cc
deleted file mode 100644
index 23791dd..0000000
--- a/starboard/shared/test_webapi_extension/webapi_extension.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 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 "base/compiler_specific.h"
-#include "cobalt/script/global_environment.h"
-#include "starboard/shared/test_webapi_extension/my_new_interface.h"
-
-namespace cobalt {
-namespace browser {
-
-base::Optional<std::string> GetWebAPIExtensionObjectPropertyName() {
- return std::string("myInterface");
-}
-
-scoped_refptr<script::Wrappable> CreateWebAPIExtensionObject(
- const scoped_refptr<dom::Window>& window,
- script::GlobalEnvironment* global_environment) {
- return scoped_refptr<script::Wrappable>(
- new webapi_extension::MyNewInterface(window));
-}
-
-} // namespace browser
-} // namespace cobalt
diff --git a/starboard/win/shared/platform_configuration/BUILD.gn b/starboard/win/shared/platform_configuration/BUILD.gn
index 37e60e7..7d01219 100644
--- a/starboard/win/shared/platform_configuration/BUILD.gn
+++ b/starboard/win/shared/platform_configuration/BUILD.gn
@@ -263,6 +263,9 @@
# objects.
# https://connect.microsoft.com/VisualStudio/feedback/details/783808/static-analyzer-warning-c28285-for-std-min-and-std-max
"/wd28285",
+
+ # Deprecated function warning.
+ "/wd4996",
]
}
diff --git a/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
index 57dcb4f..acc7a5a 100644
--- a/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+++ b/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
@@ -162,7 +162,7 @@
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage =
DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
- swapChainDesc.BufferCount = 4;
+ swapChainDesc.BufferCount = 3;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
@@ -200,7 +200,7 @@
result = device->QueryInterface(__uuidof(IDXGIDevice1), (void **)pDXGIDevice.GetAddressOf());
if (SUCCEEDED(result))
{
- pDXGIDevice->SetMaximumFrameLatency(swapChainDesc.BufferCount-1);
+ pDXGIDevice->SetMaximumFrameLatency(swapChainDesc.BufferCount);
}
return result;
diff --git a/third_party/web_platform_tests/cors/resources/304.py b/third_party/web_platform_tests/cors/resources/304.py
index 2fc83b9..265569d 100755
--- a/third_party/web_platform_tests/cors/resources/304.py
+++ b/third_party/web_platform_tests/cors/resources/304.py
@@ -38,7 +38,9 @@
else:
status = 200, "OK"
headers.append(("Access-Control-Allow-Origin", "*"))
- headers.append(("Content-Type", "text/plain"))
+ # Cobalt does not support text/plain caching.
+ # headers.append(("Content-Type", "text/plain"))
+ headers.append(("Content-Type", "text/html"))
headers.append(("Cache-Control", "private, max-age=3, must-revalidate"))
headers.append(("ETag", etag))
return status, headers, "Success"
diff --git a/third_party/web_platform_tests/workers/interfaces/WorkerUtils/WindowTimers/005.html b/third_party/web_platform_tests/workers/interfaces/WorkerUtils/WindowTimers/005.html
index a1e5044..06885e4 100644
--- a/third_party/web_platform_tests/workers/interfaces/WorkerUtils/WindowTimers/005.html
+++ b/third_party/web_platform_tests/workers/interfaces/WorkerUtils/WindowTimers/005.html
@@ -8,7 +8,7 @@
async_test(function () {
var worker = new Worker('005.js');
worker.onmessage = this.step_func(function (e) {
- assert_equals(e.data, '1');
+ assert_equals(e.data, 1);
this.done();
});
});