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