Import Cobalt 23.master.0.309137
diff --git a/cobalt/BUILD.gn b/cobalt/BUILD.gn index e9c9fcb..c268919 100644 --- a/cobalt/BUILD.gn +++ b/cobalt/BUILD.gn
@@ -19,6 +19,7 @@ "//cobalt/bindings/testing:bindings_test", "//cobalt/browser:browser_test", "//cobalt/cssom:cssom_test", + "//cobalt/demos/simple_sandbox", "//cobalt/dom:dom_test", "//cobalt/dom_parser:dom_parser_test", "//cobalt/encoding:text_encoding_test",
diff --git a/cobalt/CHANGELOG.md b/cobalt/CHANGELOG.md index 9e4ea3e..0a77358 100644 --- a/cobalt/CHANGELOG.md +++ b/cobalt/CHANGELOG.md
@@ -3,10 +3,49 @@ This document records all notable changes made to Cobalt since the last release. ## Version 23 - - **Deleted deprecated --webdriver_listen_ip switch.** + - **Cobalt now uses GN (Generate Ninja) meta-build system** - The `--webdriver_listen_ip` switch was deprecated in Cobalt 22 in favor of - `--dev_servers_listen_ip`. + Cobalt now uses GN instead of GYP which is now fully deprecated. This + significantly improves performance of meta-build generation. + + A [migration guide](https://cobalt.dev/gen/starboard/build/doc/migrating_gyp_to_gn.html) + has been published to help with migrations. + + - **Added support for HTTP caching** + + Cobalt now supports caching HTTP requests and compiled V8 JS for improved + startup times. + + - **Added Identifier For Advertising (IFA) support** + + Cobalt now implements the IFA + [guidelines](https://iabtechlab.com/OTT-IFA). + + - **Added experimental support for Web Workers** + + Partial support for Dedicated Workers and Service Workers has been + implemented. + + - **Added Watchdog for detecting application hangs** + + A Watchdog has been added to Cobalt to detect if Cobalt has hanged and needs + to be restarted. + + - **Evergreen supports LZ4 compressed binaries** + + Evergreen binaries can now be stored compressed, using LZ4, for up to a 50% + reduction in Cobalt binary storage. + + - **Reproducible builds are now supported for production configurations** + + Improvements in the buildsystem now allows for fully reproducible builds for + production configurations. This allows for improved traceability for open + source releases. + + - **Crash handler improvement** + + The crash handler now launches on crash instead of start, saving + 10MB of application memory. ## Version 22 - **C++14 is required to compile Cobalt 22.**
diff --git a/cobalt/account/user_authorizer.h b/cobalt/account/user_authorizer.h index 6bd8ad5..784984a 100644 --- a/cobalt/account/user_authorizer.h +++ b/cobalt/account/user_authorizer.h
@@ -77,7 +77,8 @@ // request. Calling other methods after |Shutdown| may have no effect. virtual void Shutdown() {} - // Instantiates an instance of the platform-specific implementation. + // Instantiates an instance of the platform-specific implementation. This may + // return nullptr if UserAuthorizer functions are not supported. static UserAuthorizer* Create(); private:
diff --git a/cobalt/base/init_cobalt.cc b/cobalt/base/init_cobalt.cc index 9632c5b..a22be1e 100644 --- a/cobalt/base/init_cobalt.cc +++ b/cobalt/base/init_cobalt.cc
@@ -22,8 +22,10 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/path_service.h" +#include "base/threading/platform_thread.h" #include "cobalt/base/cobalt_paths.h" #include "cobalt/base/path_provider.h" +#include "starboard/thread.h" namespace cobalt { namespace { @@ -44,6 +46,11 @@ // Register a path provider for Cobalt-specific paths. base::PathService::RegisterProvider(&PathProvider, paths::PATH_COBALT_START, paths::PATH_COBALT_END); + + // Copy the Starboard thread name to the PlatformThread name. + char thread_name[128] = {'\0'}; + SbThreadGetName(thread_name, 127); + base::PlatformThread::SetName(thread_name); } const char* GetInitialDeepLink() { return s_initial_deep_link.Get().c_str(); }
diff --git a/cobalt/black_box_tests/testdata/web_worker_test.html b/cobalt/black_box_tests/testdata/web_worker_test.html index ce7c99f..2976cdf 100644 --- a/cobalt/black_box_tests/testdata/web_worker_test.html +++ b/cobalt/black_box_tests/testdata/web_worker_test.html
@@ -26,8 +26,19 @@ <body> <script> + var window_error_event_count = 0; + window.onerror = function (message) { + window_error_event_count += 1; + assertIncludes('TypeError: self.Foo is not a function', message); + console.log('window got onerror', message); + }; + var message_event_count = 0; console.log('running'); + + // This is expected trigger a an error event on window. + var worker_with_error = new Worker('web_worker_test_with_syntax_error.js'); + var worker = new Worker('web_worker_test.js'); console.log(worker); worker.onmessage = function (event) { @@ -86,6 +97,7 @@ window.setTimeout( () => { assertEqual(14, message_event_count); + assertEqual(1, window_error_event_count); onEndTest(); }, 250); break;
diff --git a/cobalt/black_box_tests/testdata/web_worker_test_with_syntax_error.js b/cobalt/black_box_tests/testdata/web_worker_test_with_syntax_error.js new file mode 100644 index 0000000..041a9b9 --- /dev/null +++ b/cobalt/black_box_tests/testdata/web_worker_test_with_syntax_error.js
@@ -0,0 +1,16 @@ +// 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. + +console.log('Running script with syntax error.'); +self.Foo('Bar');
diff --git a/cobalt/browser/idl_files.gni b/cobalt/browser/idl_files.gni index 258a1ce..db2d7c5 100644 --- a/cobalt/browser/idl_files.gni +++ b/cobalt/browser/idl_files.gni
@@ -157,7 +157,7 @@ "//cobalt/h5vcc/h5vcc.idl", "//cobalt/h5vcc/h5vcc_accessibility.idl", "//cobalt/h5vcc/h5vcc_account_info.idl", - "//cobalt/h5vcc/h5vcc_account_manager.idl", + "//cobalt/h5vcc/h5vcc_account_manager_internal.idl", "//cobalt/h5vcc/h5vcc_audio_config.idl", "//cobalt/h5vcc/h5vcc_audio_config_array.idl", "//cobalt/h5vcc/h5vcc_crash_log.idl",
diff --git a/cobalt/demos/simple_sandbox/BUILD.gn b/cobalt/demos/simple_sandbox/BUILD.gn new file mode 100644 index 0000000..bd9cf74 --- /dev/null +++ b/cobalt/demos/simple_sandbox/BUILD.gn
@@ -0,0 +1,23 @@ +# 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. + +# This is a sample minimal sandbox application. + +target(final_executable_type, "simple_sandbox") { + sources = [ "simple_sandbox.cc" ] + + deps = [ "//cobalt/base" ] + + deps += cobalt_platform_dependencies +}
diff --git a/cobalt/demos/simple_sandbox/simple_sandbox.cc b/cobalt/demos/simple_sandbox/simple_sandbox.cc new file mode 100644 index 0000000..5c2d32c --- /dev/null +++ b/cobalt/demos/simple_sandbox/simple_sandbox.cc
@@ -0,0 +1,80 @@ +// 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/bind.h" +#include "base/memory/singleton.h" +#include "base/message_loop/message_loop.h" +#include "base/task_runner.h" +#include "base/threading/thread.h" +#include "cobalt/base/wrap_main.h" + +namespace cobalt { +namespace demos { + +class SimpleSandbox { + public: + static SimpleSandbox* GetInstance() { + return base::Singleton<SimpleSandbox>::get(); + } + + static void StartApplication(int argc, char** argv, const char* link, + const base::Closure& quit_closure, + SbTimeMonotonic timestamp); + + static void StopApplication(); + + base::Thread* thread() { return &thread_; } + + private: + base::Thread thread_{"SimpleSandboxThread"}; + // friend struct base::DefaultSingletonTraits<SimpleSandbox>; +}; + +// static +void SimpleSandbox::StartApplication(int argc, char** argv, const char* link, + const base::Closure& quit_closure, + SbTimeMonotonic timestamp) { + LOG(INFO) << "SimpleSandbox::StartApplication"; + + SimpleSandbox::GetInstance()->thread()->Start(); + + SimpleSandbox::GetInstance() + ->thread() + ->message_loop() + ->task_runner() + ->PostDelayedTask(FROM_HERE, + base::BindOnce( + [](base::MessageLoop* main_loop, + const base::Closure& quit_closure) { + LOG(INFO) << "Lambda Function in the thread."; + + // Stop after seconds. + main_loop->task_runner()->PostDelayedTask( + FROM_HERE, quit_closure, + base::TimeDelta::FromSeconds(2)); + }, + base::MessageLoop::current(), quit_closure), + base::TimeDelta(base::TimeDelta::FromSeconds(1))); +} + +// static +void SimpleSandbox::StopApplication() { + LOG(INFO) << "SimpleSandbox::StopApplication"; +} + +} // namespace demos +} // namespace cobalt + +COBALT_WRAP_BASE_MAIN(cobalt::demos::SimpleSandbox::StartApplication, + cobalt::demos::SimpleSandbox::StopApplication);
diff --git a/cobalt/dom/document.cc b/cobalt/dom/document.cc index 4e665a5..41bfa41a 100644 --- a/cobalt/dom/document.cc +++ b/cobalt/dom/document.cc
@@ -448,7 +448,7 @@ return; } if (cookie_jar_) { - cookie_jar_->SetCookie(url_as_gurl(), cookie); + cookie_jar_->SetCookie(location()->url(), cookie); } } @@ -467,7 +467,7 @@ } if (cookie_jar_) { return net::CanonicalCookie::BuildCookieLine( - cookie_jar_->GetCookies(url_as_gurl())); + cookie_jar_->GetCookies(location()->url())); } else { DLOG(WARNING) << "Document has no cookie jar"; return ""; @@ -485,7 +485,7 @@ return; } if (cookie_jar_) { - cookie_jar_->SetCookie(url_as_gurl(), cookie); + cookie_jar_->SetCookie(location()->url(), cookie); } } @@ -501,7 +501,7 @@ } if (cookie_jar_) { return net::CanonicalCookie::BuildCookieLine( - cookie_jar_->GetCookies(url_as_gurl())); + cookie_jar_->GetCookies(location()->url())); } else { DLOG(WARNING) << "Document has no cookie jar"; return ""; @@ -517,7 +517,8 @@ // limited quirks mode, or no-quirks mode), and its type (XML document or HTML // document). // https://www.w3.org/TR/dom/#concept-node-clone - return new Document(html_element_context_, Document::Options(url_as_gurl())); + return new Document(html_element_context_, + Document::Options(location()->url())); } scoped_refptr<HTMLHtmlElement> Document::html() const {
diff --git a/cobalt/dom/document.h b/cobalt/dom/document.h index 2fc0246..89c65c0 100644 --- a/cobalt/dom/document.h +++ b/cobalt/dom/document.h
@@ -247,8 +247,6 @@ FontCache* font_cache() const { return font_cache_.get(); } - const GURL& url_as_gurl() const { return location_->url(); } - scoped_refptr<HTMLHtmlElement> html() const; // List of scripts that will execute in order as soon as possible.
diff --git a/cobalt/dom/document_test.cc b/cobalt/dom/document_test.cc index 8909802..b693173 100644 --- a/cobalt/dom/document_test.cc +++ b/cobalt/dom/document_test.cc
@@ -103,7 +103,7 @@ 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()); + EXPECT_EQ(url, document->location()->url()); } TEST_F(DocumentTest, IsNotXMLDocument) {
diff --git a/cobalt/dom/dom_settings.cc b/cobalt/dom/dom_settings.cc index d07474b..8390913 100644 --- a/cobalt/dom/dom_settings.cc +++ b/cobalt/dom/dom_settings.cc
@@ -44,6 +44,11 @@ DOMSettings::~DOMSettings() {} +Window* DOMSettings::window() const { + DCHECK(context()->GetWindowOrWorkerGlobalScope()->IsWindow()); + return context()->GetWindowOrWorkerGlobalScope()->AsWindow(); +} + const GURL& DOMSettings::base_url() const { // From algorithm for to setup up a window environment settings object: // https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#set-up-a-window-environment-settings-object @@ -51,15 +56,10 @@ // algorithms are defined as follows: // The API base URL // Return the current base URL of window's associated Document. - return window()->document()->url_as_gurl(); + return window()->document()->location()->url(); } -scoped_refptr<Window> DOMSettings::window() const { - DCHECK(context()->GetWindowOrWorkerGlobalScope()->IsWindow()); - return context()->GetWindowOrWorkerGlobalScope()->AsWindow(); -} - -loader::Origin DOMSettings::document_origin() const { +loader::Origin DOMSettings::GetOrigin() const { return window()->document()->location()->GetOriginAsObject(); }
diff --git a/cobalt/dom/dom_settings.h b/cobalt/dom/dom_settings.h index 33a5c0a..58e221f 100644 --- a/cobalt/dom/dom_settings.h +++ b/cobalt/dom/dom_settings.h
@@ -69,7 +69,7 @@ return microphone_options_; } - scoped_refptr<Window> window() const; + Window* window() const; MediaSourceRegistry* media_source_registry() const { return media_source_registry_; @@ -91,13 +91,14 @@ return mutation_observer_task_manager_; } - // Return's document's origin. - loader::Origin document_origin() const; - // From: script::EnvironmentSettings // const GURL& base_url() const override; + // Return the origin of window's associated Document. + // https://html.spec.whatwg.org/#set-up-a-window-environment-settings-object + loader::Origin GetOrigin() const override; + private: const int max_dom_element_depth_; const speech::Microphone::Options microphone_options_;
diff --git a/cobalt/dom/html_anchor_element.cc b/cobalt/dom/html_anchor_element.cc index c262595..0c15a83 100644 --- a/cobalt/dom/html_anchor_element.cc +++ b/cobalt/dom/html_anchor_element.cc
@@ -54,7 +54,7 @@ } // Resolve the URL given by the href attribute, relative to the element. - const GURL& base_url = document->url_as_gurl(); + const GURL& base_url = document->location()->url(); GURL absolute_url = base_url.Resolve(value); // If the previous step fails, then abort these steps.
diff --git a/cobalt/dom/html_element.cc b/cobalt/dom/html_element.cc index aa38f18..970c56e 100644 --- a/cobalt/dom/html_element.cc +++ b/cobalt/dom/html_element.cc
@@ -2025,7 +2025,7 @@ // came from. cssom::GURLMap property_key_to_base_url_map; property_key_to_base_url_map[cssom::kBackgroundImageProperty] = - document->url_as_gurl(); + document->location()->url(); // Flags tracking which cached values must be invalidated. UpdateComputedStyleInvalidationFlags invalidation_flags;
diff --git a/cobalt/dom/html_image_element.cc b/cobalt/dom/html_image_element.cc index 2cbc162..02300ed 100644 --- a/cobalt/dom/html_image_element.cc +++ b/cobalt/dom/html_image_element.cc
@@ -119,7 +119,7 @@ if (!src.empty()) { // 7.1. Resolve selected source, relative to the element. If that is not // successful, abort these steps. - const GURL& base_url = node_document()->url_as_gurl(); + const GURL& base_url = node_document()->location()->url(); const GURL selected_source = base_url.Resolve(src); if (!selected_source.is_valid()) { LOG(WARNING) << src << " cannot be resolved based on " << base_url << "."; @@ -235,7 +235,7 @@ // Resolve selected source, relative to the element. const auto src_attr = GetAttribute("src"); const std::string src = src_attr.value_or(""); - const GURL& base_url = node_document()->url_as_gurl(); + const GURL& base_url = node_document()->location()->url(); const GURL selected_source = base_url.Resolve(src); html_element_context()->performance()->CreatePerformanceResourceTiming(
diff --git a/cobalt/dom/html_link_element.cc b/cobalt/dom/html_link_element.cc index b51d697..17a6de1 100644 --- a/cobalt/dom/html_link_element.cc +++ b/cobalt/dom/html_link_element.cc
@@ -147,7 +147,7 @@ void HTMLLinkElement::ResolveAndSetAbsoluteURL() { // Resolve the URL given by the href attribute, relative to the element. - const GURL& base_url = node_document()->url_as_gurl(); + const GURL& base_url = node_document()->location()->url(); absolute_url_ = base_url.Resolve(href()); LOG_IF(WARNING, !absolute_url_.is_valid()) @@ -316,7 +316,7 @@ // If not loading from network-fetched resources or fetched resource is same // origin as the document, set origin-clean flag to true. if (request_mode_ != loader::kNoCORSMode || !loader_ || - document->url_as_gurl().SchemeIsFile() || + document->location()->url().SchemeIsFile() || (fetched_last_url_origin_ == document->location()->GetOriginAsObject())) { css_style_sheet->SetOriginClean(true); }
diff --git a/cobalt/dom/html_media_element.cc b/cobalt/dom/html_media_element.cc index 099559b..d496b01 100644 --- a/cobalt/dom/html_media_element.cc +++ b/cobalt/dom/html_media_element.cc
@@ -795,7 +795,7 @@ GURL media_url(src); if (media_url.is_empty()) { // Try to resolve it as a relative url. - media_url = node_document()->url_as_gurl().Resolve(src); + media_url = node_document()->location()->url().Resolve(src); } if (media_url.is_empty()) { MediaLoadingFailed(WebMediaPlayer::kNetworkStateFormatError, @@ -1690,7 +1690,7 @@ std::string src = this->src(); GURL current_url = GURL(src); if (current_url.is_empty()) { - current_url = node_document()->url_as_gurl().Resolve(src); + current_url = node_document()->location()->url().Resolve(src); } if (!current_url.SchemeIs("http") && OriginIsSafe(request_mode_, current_url,
diff --git a/cobalt/dom/html_script_element.cc b/cobalt/dom/html_script_element.cc index a036d7c..e003c03 100644 --- a/cobalt/dom/html_script_element.cc +++ b/cobalt/dom/html_script_element.cc
@@ -229,7 +229,7 @@ // 3. Resolve src relative to the element. // 4. If the previous step failed, queue a task to fire a simple event named // error at the element, and abort these steps. - const GURL& base_url = document_->url_as_gurl(); + const GURL& base_url = document_->location()->url(); url_ = base_url.Resolve(src()); if (!url_.is_valid()) { LOG(ERROR) << src() << " cannot be resolved based on " << base_url << ".";
diff --git a/cobalt/dom/lottie_player.cc b/cobalt/dom/lottie_player.cc index 93baab8..4adb4a8 100644 --- a/cobalt/dom/lottie_player.cc +++ b/cobalt/dom/lottie_player.cc
@@ -298,7 +298,7 @@ const std::string src = GetAttribute("src").value_or(""); if (!src.empty()) { - const GURL& base_url = node_document()->url_as_gurl(); + const GURL& base_url = node_document()->location()->url(); const GURL selected_source = base_url.Resolve(src); if (!selected_source.is_valid()) { LOG(WARNING) << src << " cannot be resolved based on " << base_url << ".";
diff --git a/cobalt/dom/source_buffer.cc b/cobalt/dom/source_buffer.cc index f49d151..ffaee80 100644 --- a/cobalt/dom/source_buffer.cc +++ b/cobalt/dom/source_buffer.cc
@@ -105,11 +105,38 @@ } // namespace +SourceBuffer::OnInitSegmentReceivedHelper::OnInitSegmentReceivedHelper( + SourceBuffer* source_buffer) + : source_buffer_(source_buffer) { + DCHECK(source_buffer_); +} + +void SourceBuffer::OnInitSegmentReceivedHelper::Detach() { + DCHECK(task_runner_->BelongsToCurrentThread()); + source_buffer_ = nullptr; +} + +void SourceBuffer::OnInitSegmentReceivedHelper::TryToRunOnInitSegmentReceived( + std::unique_ptr<MediaTracks> tracks) { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, + base::Bind(&OnInitSegmentReceivedHelper::TryToRunOnInitSegmentReceived, + this, base::Passed(&tracks))); + return; + } + + if (source_buffer_) { + source_buffer_->OnInitSegmentReceived(std::move(tracks)); + } +} + 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), + on_init_segment_received_helper_(new OnInitSegmentReceivedHelper(this)), id_(id), asynchronous_reduction_enabled_(asynchronous_reduction_enabled), evict_extra_in_bytes_(GetEvictExtraInBytes(settings)), @@ -130,7 +157,8 @@ chunk_demuxer_->SetTracksWatcher( id_, - base::Bind(&SourceBuffer::OnInitSegmentReceived, base::Unretained(this))); + base::Bind(&OnInitSegmentReceivedHelper::TryToRunOnInitSegmentReceived, + on_init_segment_received_helper_)); chunk_demuxer_->SetParseWarningCallback( id, base::BindRepeating([](::media::SourceBufferParseWarning warning) { LOG(WARNING) << "Encountered SourceBufferParseWarning " @@ -388,6 +416,9 @@ return; } + DCHECK(on_init_segment_received_helper_); + on_init_segment_received_helper_->Detach(); + if (active_algorithm_handle_) { active_algorithm_handle_->Abort(); active_algorithm_handle_ = nullptr; @@ -437,13 +468,6 @@ 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; }
diff --git a/cobalt/dom/source_buffer.h b/cobalt/dom/source_buffer.h index 65bbe48..0cf7f28 100644 --- a/cobalt/dom/source_buffer.h +++ b/cobalt/dom/source_buffer.h
@@ -52,6 +52,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" #include "base/optional.h" #include "base/single_thread_task_runner.h" #include "base/timer/timer.h" @@ -142,6 +143,28 @@ private: typedef ::media::MediaTracks MediaTracks; + // SourceBuffer is inherited from base::RefCounted<> and its ref count cannot + // be used on non-web threads. On the other hand the call to + // OnInitSegmentReceived() may happen on a worker thread for algorithm + // offloading. This object allows to manage the life time of the SourceBuffer + // object across threads while still maintain it as a sub-class of + // base::RefCounted<>. + class OnInitSegmentReceivedHelper + : public base::RefCountedThreadSafe<OnInitSegmentReceivedHelper> { + public: + explicit OnInitSegmentReceivedHelper(SourceBuffer* source_buffer); + void Detach(); + void TryToRunOnInitSegmentReceived(std::unique_ptr<MediaTracks> tracks); + + private: + scoped_refptr<base::SingleThreadTaskRunner> task_runner_ = + base::MessageLoop::current()->task_runner(); + // The access to |source_buffer_| always happens on |task_runner_|, and + // needn't be explicitly synchronized by a mutex. + SourceBuffer* source_buffer_; + }; + + void OnInitSegmentReceived(std::unique_ptr<MediaTracks> tracks); void ScheduleEvent(base::Token event_name); void ScheduleAndMaybeDispatchImmediately(base::Token event_name); @@ -162,14 +185,13 @@ const std::string& track_type, const std::string& byte_stream_track_id) const; + scoped_refptr<OnInitSegmentReceivedHelper> on_init_segment_received_helper_; const std::string id_; const bool asynchronous_reduction_enabled_; const size_t evict_extra_in_bytes_; 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_;
diff --git a/cobalt/dom/storage.cc b/cobalt/dom/storage.cc index 010890f..5706528 100644 --- a/cobalt/dom/storage.cc +++ b/cobalt/dom/storage.cc
@@ -57,7 +57,7 @@ key, old_value, new_value, window_->document()->url(), this)); } -GURL Storage::origin() const { return window_->document()->url_as_gurl(); } +GURL Storage::origin() const { return window_->document()->location()->url(); } } // namespace dom } // namespace cobalt
diff --git a/cobalt/dom/window.cc b/cobalt/dom/window.cc index aca75dc..0284726 100644 --- a/cobalt/dom/window.cc +++ b/cobalt/dom/window.cc
@@ -504,35 +504,33 @@ // 7. Let event be a new trusted ErrorEvent object that does not bubble but is // cancelable, and which has the event name error. // NOTE: Cobalt does not currently support trusted events. - web::ErrorEventInit error_event_init; - error_event_init.set_bubbles(false); - error_event_init.set_cancelable(true); + web::ErrorEventInit error; + error.set_bubbles(false); + error.set_cancelable(true); if (error_report.is_muted) { // 6. If script has muted errors, then set message to "Script error.", set // location to the empty string, set line and col to 0, and set error // object to null. - error_event_init.set_message("Script error."); - error_event_init.set_filename(""); - error_event_init.set_lineno(0); - error_event_init.set_colno(0); - error_event_init.set_error(NULL); + error.set_message("Script error."); + error.set_filename(""); + error.set_lineno(0); + error.set_colno(0); + error.set_error(NULL); } else { // 8. Initialize event's message attribute to message. - error_event_init.set_message(error_report.message); + error.set_message(error_report.message); // 9. Initialize event's filename attribute to location. - error_event_init.set_filename(error_report.filename); + error.set_filename(error_report.filename); // 10. Initialize event's lineno attribute to line. - error_event_init.set_lineno(error_report.line_number); + error.set_lineno(error_report.line_number); // 11. Initialize event's colno attribute to col. - error_event_init.set_colno(error_report.column_number); + error.set_colno(error_report.column_number); // 12. Initialize event's error attribute to error object. - error_event_init.set_error(error_report.error ? error_report.error.get() - : NULL); + error.set_error(error_report.error ? error_report.error.get() : NULL); } - scoped_refptr<web::ErrorEvent> error_event( - new web::ErrorEvent(base::Tokens::error(), error_event_init)); + scoped_refptr<web::ErrorEvent> error_event(new web::ErrorEvent(error)); // 13. Dispatch event at target. DispatchEvent(error_event);
diff --git a/cobalt/dom/xml_document.h b/cobalt/dom/xml_document.h index 422b6e4..8e3f684 100644 --- a/cobalt/dom/xml_document.h +++ b/cobalt/dom/xml_document.h
@@ -29,7 +29,7 @@ // Custom, not in any spec: Node. scoped_refptr<Node> Duplicate() const override { return new XMLDocument(html_element_context(), - Document::Options(url_as_gurl())); + Document::Options(location()->url())); } // Custom, not in any spec: Document.
diff --git a/cobalt/h5vcc/BUILD.gn b/cobalt/h5vcc/BUILD.gn index fd7216f..188c6ed 100644 --- a/cobalt/h5vcc/BUILD.gn +++ b/cobalt/h5vcc/BUILD.gn
@@ -96,8 +96,8 @@ if (enable_account_manager) { sources += [ - "h5vcc_account_manager.cc", - "h5vcc_account_manager.h", + "h5vcc_account_manager_internal.cc", + "h5vcc_account_manager_internal.h", ] }
diff --git a/cobalt/h5vcc/h5vcc.cc b/cobalt/h5vcc/h5vcc.cc index 806f7a1..e88b901 100644 --- a/cobalt/h5vcc/h5vcc.cc +++ b/cobalt/h5vcc/h5vcc.cc
@@ -14,6 +14,11 @@ #include "cobalt/h5vcc/h5vcc.h" +#if defined(COBALT_ENABLE_ACCOUNT_MANAGER) +#include "cobalt/h5vcc/h5vcc_account_manager_internal.h" +#include "cobalt/script/source_code.h" +#endif + #include "cobalt/persistent_storage/persistent_settings.h" #include "cobalt/sso/sso_interface.h" @@ -45,6 +50,23 @@ #else system_ = new H5vccSystem(); #endif + +#if defined(COBALT_ENABLE_ACCOUNT_MANAGER) + // Bind "H5vccAccountManager" if it is supported. (This is not to be confused + // with settings.account_manager.) + if (H5vccAccountManagerInternal::IsSupported()) { + // Since we don't want to bind an instance of a wrappable, we cannot use + // Bind() nor BindTo(). Instead, just evaluate a script to alias the type. + scoped_refptr<script::SourceCode> source = + script::SourceCode::CreateSourceCode( + "H5vccAccountManager = H5vccAccountManagerInternal;" + "window.H5vccAccountManager = window.H5vccAccountManagerInternal;", + base::SourceLocation("h5vcc.cc", __LINE__, 1)); + std::string result; + bool success = settings.global_environment->EvaluateScript(source, &result); + CHECK(success); + } +#endif } void H5vcc::TraceMembers(script::Tracer* tracer) {
diff --git a/cobalt/h5vcc/h5vcc_account_manager.cc b/cobalt/h5vcc/h5vcc_account_manager_internal.cc similarity index 77% rename from cobalt/h5vcc/h5vcc_account_manager.cc rename to cobalt/h5vcc/h5vcc_account_manager_internal.cc index 8705df7..1c0a3c2 100644 --- a/cobalt/h5vcc/h5vcc_account_manager.cc +++ b/cobalt/h5vcc/h5vcc_account_manager_internal.cc
@@ -14,7 +14,7 @@ #include <memory> -#include "cobalt/h5vcc/h5vcc_account_manager.h" +#include "cobalt/h5vcc/h5vcc_account_manager_internal.h" #include "base/command_line.h" #include "base/memory/weak_ptr.h" @@ -24,32 +24,42 @@ namespace cobalt { namespace h5vcc { -H5vccAccountManager::H5vccAccountManager() +H5vccAccountManagerInternal::H5vccAccountManagerInternal() : user_authorizer_(account::UserAuthorizer::Create()), owning_message_loop_(base::MessageLoop::current()), thread_("AccountManager") { thread_.Start(); } -void H5vccAccountManager::GetAuthToken( +// static +bool H5vccAccountManagerInternal::IsSupported() { + auto account_manager = account::UserAuthorizer::Create(); + if (account_manager) { + delete account_manager; + return true; + } + return false; +} + +void H5vccAccountManagerInternal::GetAuthToken( const AccessTokenCallbackHolder& callback) { DLOG(INFO) << "Get authorization token."; PostOperation(kGetToken, callback); } -void H5vccAccountManager::RequestPairing( +void H5vccAccountManagerInternal::RequestPairing( const AccessTokenCallbackHolder& callback) { DLOG(INFO) << "Request application linking."; PostOperation(kPairing, callback); } -void H5vccAccountManager::RequestUnpairing( +void H5vccAccountManagerInternal::RequestUnpairing( const AccessTokenCallbackHolder& callback) { DLOG(INFO) << "Request application unlinking."; PostOperation(kUnpairing, callback); } -void H5vccAccountManager::PostOperation( +void H5vccAccountManagerInternal::PostOperation( OperationType operation_type, const AccessTokenCallbackHolder& callback) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); AccessTokenCallbackReference* token_callback = @@ -57,31 +67,38 @@ pending_callbacks_.push_back( std::unique_ptr<AccessTokenCallbackReference>(token_callback)); thread_.message_loop()->task_runner()->PostTask( - FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal, - user_authorizer_.get(), operation_type, - base::Bind(&H5vccAccountManager::PostResult, - owning_message_loop_, - base::AsWeakPtr(this), token_callback))); + FROM_HERE, + base::Bind(&H5vccAccountManagerInternal::RequestOperationInternal, + user_authorizer_.get(), operation_type, + base::Bind(&H5vccAccountManagerInternal::PostResult, + owning_message_loop_, base::AsWeakPtr(this), + token_callback))); } -H5vccAccountManager::~H5vccAccountManager() { +H5vccAccountManagerInternal::~H5vccAccountManagerInternal() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // Give the UserAuthorizer a chance to abort any long running pending requests // before the message loop gets shut down. - user_authorizer_->Shutdown(); + if (user_authorizer_) { + user_authorizer_->Shutdown(); + } } // static -void H5vccAccountManager::RequestOperationInternal( +void H5vccAccountManagerInternal::RequestOperationInternal( account::UserAuthorizer* user_authorizer, OperationType operation, const base::Callback<void(const std::string&, uint64_t)>& post_result) { + bool enabled = user_authorizer != nullptr; #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(browser::switches::kDisableSignIn)) { + enabled = false; + } +#endif // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) + if (!enabled) { post_result.Run(std::string(), 0); return; } -#endif // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) SbUser current_user = SbUserGetCurrent(); DCHECK(SbUserIsValid(current_user)); @@ -128,18 +145,18 @@ } // static -void H5vccAccountManager::PostResult( +void H5vccAccountManagerInternal::PostResult( base::MessageLoop* message_loop, - base::WeakPtr<H5vccAccountManager> h5vcc_account_manager, + base::WeakPtr<H5vccAccountManagerInternal> h5vcc_account_manager, AccessTokenCallbackReference* token_callback, const std::string& token, uint64_t expiration_in_seconds) { message_loop->task_runner()->PostTask( - FROM_HERE, - base::Bind(&H5vccAccountManager::SendResult, h5vcc_account_manager, - token_callback, token, expiration_in_seconds)); + FROM_HERE, base::Bind(&H5vccAccountManagerInternal::SendResult, + h5vcc_account_manager, token_callback, token, + expiration_in_seconds)); } -void H5vccAccountManager::SendResult( +void H5vccAccountManagerInternal::SendResult( AccessTokenCallbackReference* token_callback, const std::string& token, uint64_t expiration_in_seconds) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/cobalt/h5vcc/h5vcc_account_manager.h b/cobalt/h5vcc/h5vcc_account_manager_internal.h similarity index 68% rename from cobalt/h5vcc/h5vcc_account_manager.h rename to cobalt/h5vcc/h5vcc_account_manager_internal.h index 9057f3c..94585a0 100644 --- a/cobalt/h5vcc/h5vcc_account_manager.h +++ b/cobalt/h5vcc/h5vcc_account_manager_internal.h
@@ -12,12 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_H_ -#define COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_H_ +#ifndef COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_INTERNAL_H_ +#define COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_INTERNAL_H_ #include <memory> #include <queue> #include <string> +#include <vector> #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" @@ -31,24 +32,32 @@ namespace cobalt { namespace h5vcc { -// Implementation of the H5vccAccountManager interface. Requests will be handled -// one-at-time on another thread in FIFO order. When a request is complete, the -// AccessTokenCallback will be fired on the thread that the H5vccAccountManager -// was created on. -class H5vccAccountManager : public script::Wrappable, - public base::SupportsWeakPtr<H5vccAccountManager> { +// Implementation of the H5vccAccountManagerInternal interface. Requests will +// be handled one-at-time on another thread in FIFO order. When a request is +// complete, the AccessTokenCallback will be fired on the thread that the +// H5vccAccountManagerInternal was created on. +class H5vccAccountManagerInternal + : public script::Wrappable, + public base::SupportsWeakPtr<H5vccAccountManagerInternal> { public: typedef script::CallbackFunction<bool(const std::string&, uint64_t)> AccessTokenCallback; typedef script::ScriptValue<AccessTokenCallback> AccessTokenCallbackHolder; - H5vccAccountManager(); - // H5vccAccountManager interface. + // Some platforms may enable the account manager interface at compile-time + // but need a runtime check to determine if it should be presented to the + // web app. If so, H5vccAccountManagerInternal will be bound to + // "H5vccAccountManager". + static bool IsSupported(); + + H5vccAccountManagerInternal(); + + // H5vccAccountManagerInternal interface. void GetAuthToken(const AccessTokenCallbackHolder& callback); void RequestPairing(const AccessTokenCallbackHolder& callback); void RequestUnpairing(const AccessTokenCallbackHolder& callback); - DEFINE_WRAPPABLE_TYPE(H5vccAccountManager); + DEFINE_WRAPPABLE_TYPE(H5vccAccountManagerInternal); private: typedef script::ScriptValue<AccessTokenCallback>::Reference @@ -59,24 +68,24 @@ kGetToken, }; - ~H5vccAccountManager(); + ~H5vccAccountManagerInternal(); // Posts an operation to the account manager thread. void PostOperation(OperationType operation_type, const AccessTokenCallbackHolder& callback); // Processes an operation on the account manager thread. Static because - // H5vccAccountManager may have been destructed before this runs. + // H5vccAccountManagerInternal may have been destructed before this runs. static void RequestOperationInternal( account::UserAuthorizer* user_authorizer, OperationType operation, const base::Callback<void(const std::string&, uint64_t)>& post_result); // Posts the result of an operation from the account manager thread back to - // the owning thread. Static because H5vccAccountManager may have been + // the owning thread. Static because H5vccAccountManagerInternal may have been // destructed before this runs. static void PostResult( base::MessageLoop* message_loop, - base::WeakPtr<H5vccAccountManager> h5vcc_account_manager, + base::WeakPtr<H5vccAccountManagerInternal> h5vcc_account_manager, AccessTokenCallbackReference* token_callback, const std::string& token, uint64_t expiration_in_seconds); @@ -93,9 +102,9 @@ // Thread checker for the thread that creates this instance. THREAD_CHECKER(thread_checker_); - // The message loop that the H5vccAccountManager was created on. The public - // interface must be called from this message loop, and callbacks will be - // fired on this loop as well. + // The message loop that the H5vccAccountManagerInternal was created on. The + // public interface must be called from this message loop, and callbacks will + // be fired on this loop as well. base::MessageLoop* owning_message_loop_; // Each incoming request will have a corresponding task posted to this @@ -105,11 +114,11 @@ // message loop gets flushed. base::Thread thread_; - friend class scoped_refptr<H5vccAccountManager>; - DISALLOW_COPY_AND_ASSIGN(H5vccAccountManager); + friend class scoped_refptr<H5vccAccountManagerInternal>; + DISALLOW_COPY_AND_ASSIGN(H5vccAccountManagerInternal); }; } // namespace h5vcc } // namespace cobalt -#endif // COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_H_ +#endif // COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_INTERNAL_H_
diff --git a/cobalt/h5vcc/h5vcc_account_manager.idl b/cobalt/h5vcc/h5vcc_account_manager_internal.idl similarity index 95% rename from cobalt/h5vcc/h5vcc_account_manager.idl rename to cobalt/h5vcc/h5vcc_account_manager_internal.idl index a62f2d5..0c648a2 100644 --- a/cobalt/h5vcc/h5vcc_account_manager.idl +++ b/cobalt/h5vcc/h5vcc_account_manager_internal.idl
@@ -15,7 +15,7 @@ Conditional=COBALT_ENABLE_ACCOUNT_MANAGER, Constructor ] -interface H5vccAccountManager { +interface H5vccAccountManagerInternal { void getAuthToken(AccessTokenCallback callback); void requestPairing(AccessTokenCallback callback); void requestUnpairing(AccessTokenCallback callback);
diff --git a/cobalt/h5vcc/h5vcc_crash_log.cc b/cobalt/h5vcc/h5vcc_crash_log.cc index 564feda..737d64c 100644 --- a/cobalt/h5vcc/h5vcc_crash_log.cc +++ b/cobalt/h5vcc/h5vcc_crash_log.cc
@@ -126,7 +126,8 @@ bool H5vccCrashLog::Register(const std::string& name, const std::string& description, WatchdogState watchdog_state, - int64_t time_interval, int64_t time_wait, + int64_t time_interval_milliseconds, + int64_t time_wait_milliseconds, WatchdogReplace watchdog_replace) { watchdog::Watchdog* watchdog = watchdog::Watchdog::GetInstance(); if (watchdog) { @@ -162,7 +163,8 @@ replace = watchdog::NONE; } return watchdog->Register(name, description, monitor_state, - time_interval * 1000, time_wait * 1000, replace); + time_interval_milliseconds * 1000, + time_wait_milliseconds * 1000, replace); } return false; }
diff --git a/cobalt/h5vcc/h5vcc_crash_log.h b/cobalt/h5vcc/h5vcc_crash_log.h index 60a51b1..b85c0c5 100644 --- a/cobalt/h5vcc/h5vcc_crash_log.h +++ b/cobalt/h5vcc/h5vcc_crash_log.h
@@ -35,8 +35,10 @@ void TriggerCrash(H5vccCrashType intent); bool Register(const std::string& name, const std::string& description, - WatchdogState watchdog_state, int64_t time_interval, - int64_t time_wait, WatchdogReplace watchdog_replace); + WatchdogState watchdog_state, + int64_t time_interval_milliseconds, + int64_t time_wait_milliseconds, + WatchdogReplace watchdog_replace); bool Unregister(const std::string& name);
diff --git a/cobalt/h5vcc/h5vcc_crash_log.idl b/cobalt/h5vcc/h5vcc_crash_log.idl index 2bbf4df..7892219 100644 --- a/cobalt/h5vcc/h5vcc_crash_log.idl +++ b/cobalt/h5vcc/h5vcc_crash_log.idl
@@ -34,16 +34,17 @@ // description, information on the Watchdog client. // watchdog_state, application state to continue monitoring client up to. // Inclusive. - // 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. + // time_interval_milliseconds, maximum number of milliseconds allowed + // between pings before triggering a Watchdog violation. Min value of + // 1000. + // time_wait_milliseconds, 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 // of the same name. boolean register(DOMString name, DOMString description, - WatchdogState watchdog_state, long long time_interval, - long long time_wait, WatchdogReplace watchdog_replace); + WatchdogState watchdog_state, long long time_interval_milliseconds, + long long time_wait_milliseconds, WatchdogReplace watchdog_replace); // Returns true if Watchdog client was unregistered. Name determines the // Watchdog client to unregister. @@ -61,7 +62,7 @@ // Example json: // { // "test-name":{ - // "description":"test-description", + // "description":"test-desc", // "violations":[ // { // "monitorState":"kApplicationStateStarted",
diff --git a/cobalt/h5vcc/h5vcc_updater.cc b/cobalt/h5vcc/h5vcc_updater.cc index 97162bb..abf3f41 100644 --- a/cobalt/h5vcc/h5vcc_updater.cc +++ b/cobalt/h5vcc/h5vcc_updater.cc
@@ -75,6 +75,22 @@ return cobalt::updater::GetLibrarySha256(index); } +bool H5vccUpdater::GetUseCompressedUpdates() const { + if (!updater_module_) { + return false; + } + + return updater_module_->GetUseCompressedUpdates(); +} + +void H5vccUpdater::SetUseCompressedUpdates(bool use_compressed_updates) { + if (!updater_module_) { + return; + } + + return updater_module_->SetUseCompressedUpdates(use_compressed_updates); +} + #endif // SB_IS(EVERGREEN) } // namespace h5vcc } // namespace cobalt
diff --git a/cobalt/h5vcc/h5vcc_updater.h b/cobalt/h5vcc/h5vcc_updater.h index 22c3185..66f3506 100644 --- a/cobalt/h5vcc/h5vcc_updater.h +++ b/cobalt/h5vcc/h5vcc_updater.h
@@ -48,6 +48,9 @@ std::string GetLibrarySha256(uint16 index) const; + bool GetUseCompressedUpdates() const; + void SetUseCompressedUpdates(bool use_compressed_updates); + #else H5vccUpdater() {} #endif
diff --git a/cobalt/h5vcc/h5vcc_updater.idl b/cobalt/h5vcc/h5vcc_updater.idl index d71d603..96ff583 100644 --- a/cobalt/h5vcc/h5vcc_updater.idl +++ b/cobalt/h5vcc/h5vcc_updater.idl
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Custom API for getting and setting update channel for evergreen. +// Custom API for getting and setting Evergreen update settings. [Conditional=SB_IS_EVERGREEN] interface H5vccUpdater { @@ -27,4 +27,12 @@ DOMString getLibrarySha256(unsigned short index); + boolean getUseCompressedUpdates(); + + // Sets whether compressed (rather than uncompressed) Evergreen binaries + // should be requested, overwriting any value set by the + // --use_compressed_updates command-line switch. This API should only be used + // for testing. + void setUseCompressedUpdates(boolean use_compressed_updates); + };
diff --git a/cobalt/script/BUILD.gn b/cobalt/script/BUILD.gn index fb5b577..1582517 100644 --- a/cobalt/script/BUILD.gn +++ b/cobalt/script/BUILD.gn
@@ -58,6 +58,7 @@ deps = [ "//cobalt/base", + "//cobalt/loader:origin", "//nb", "//starboard:starboard_headers_only", "//third_party/v8",
diff --git a/cobalt/script/environment_settings.h b/cobalt/script/environment_settings.h index d1761da..1980d9b 100644 --- a/cobalt/script/environment_settings.h +++ b/cobalt/script/environment_settings.h
@@ -20,6 +20,7 @@ #include "base/memory/ref_counted.h" #include "cobalt/base/debugger_hooks.h" +#include "cobalt/loader/origin.h" #include "url/gurl.h" namespace cobalt { @@ -47,7 +48,10 @@ const GURL& creation_url() const { return creation_url_; } // https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-origin - const GURL GetOrigin() const { return creation_url().GetOrigin(); } + // TODO(b/244368134): Replace with url::Origin. + virtual loader::Origin GetOrigin() const { + return loader::Origin(base_url().GetOrigin()); + } const base::DebuggerHooks& debugger_hooks() const { return debugger_hooks_; }
diff --git a/cobalt/script/script_runner.cc b/cobalt/script/script_runner.cc index a379a10..8463a48 100644 --- a/cobalt/script/script_runner.cc +++ b/cobalt/script/script_runner.cc
@@ -99,7 +99,7 @@ #if defined(HANDLE_CORE_DUMP) script_runner_log.Get().IncrementFailCount(); #endif - return ""; + return result; } #if defined(HANDLE_CORE_DUMP) script_runner_log.Get().IncrementSuccessCount();
diff --git a/cobalt/updater/configurator.cc b/cobalt/updater/configurator.cc index 2b097ef..033152a 100644 --- a/cobalt/updater/configurator.cc +++ b/cobalt/updater/configurator.cc
@@ -70,6 +70,12 @@ if (network_module != nullptr) { user_agent_string_ = network_module->GetUserAgent(); } + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + browser::switches::kUseCompressedUpdates)) { + use_compressed_updates_.store(true); + } else { + use_compressed_updates_.store(false); + } } Configurator::~Configurator() { LOG(INFO) << "Configurator::~Configurator"; } @@ -171,11 +177,8 @@ "certscope", GetDeviceProperty(kSbSystemPropertyCertificationScope))); // Compression status - params.insert(std::make_pair( - "usecompressedupdates", base::CommandLine::ForCurrentProcess()->HasSwitch( - browser::switches::kUseCompressedUpdates) - ? "True" - : "False")); + params.insert(std::make_pair("usecompressedupdates", + GetUseCompressedUpdates() ? "True" : "False")); return params; } @@ -283,5 +286,13 @@ previous_updater_status_ = status; } +bool Configurator::GetUseCompressedUpdates() const { + return use_compressed_updates_.load(); +} + +void Configurator::SetUseCompressedUpdates(bool use_compressed_updates) { + use_compressed_updates_.store(use_compressed_updates); +} + } // namespace updater } // namespace cobalt
diff --git a/cobalt/updater/configurator.h b/cobalt/updater/configurator.h index 54bb6c0..630861a 100644 --- a/cobalt/updater/configurator.h +++ b/cobalt/updater/configurator.h
@@ -28,6 +28,7 @@ #include "cobalt/network/network_module.h" #include "components/update_client/configurator.h" #include "components/update_client/persisted_data.h" +#include "starboard/atomic.h" class GURL; class PrefService; @@ -98,6 +99,9 @@ void SetMinFreeSpaceBytes(uint64_t bytes) override; uint64_t GetMinFreeSpaceBytes() override; + bool GetUseCompressedUpdates() const override; + void SetUseCompressedUpdates(bool use_compressed_updates) override; + private: friend class base::RefCountedThreadSafe<Configurator>; ~Configurator() override; @@ -117,6 +121,7 @@ std::string user_agent_string_; uint64_t min_free_space_bytes_ = 48 * 1024 * 1024; base::Lock min_free_space_bytes_lock_; + starboard::atomic_bool use_compressed_updates_; DISALLOW_COPY_AND_ASSIGN(Configurator); };
diff --git a/cobalt/updater/updater_module.cc b/cobalt/updater/updater_module.cc index dfbb14b..00460fd 100644 --- a/cobalt/updater/updater_module.cc +++ b/cobalt/updater/updater_module.cc
@@ -327,7 +327,7 @@ LOG(INFO) << "UpdaterModule::GetUpdaterChannel"; auto config = updater_configurator_; if (!config) { - LOG(ERROR) << "UpdaterModule::GetUpdaterChannel: missing config"; + LOG(ERROR) << "UpdaterModule::GetUpdaterChannel: missing configurator"; return ""; } @@ -347,7 +347,7 @@ LOG(INFO) << "UpdaterModule::GetUpdaterStatus"; auto config = updater_configurator_; if (!config) { - LOG(ERROR) << "UpdaterModule::GetUpdaterStatus: missing configuration"; + LOG(ERROR) << "UpdaterModule::GetUpdaterStatus: missing configurator"; return ""; } @@ -409,5 +409,36 @@ } } +// TODO(b/244367569): refactor similar getter and setter methods in this class +// to share common code. +bool UpdaterModule::GetUseCompressedUpdates() const { + LOG(INFO) << "UpdaterModule::GetUseCompressedUpdates"; + auto config = updater_configurator_; + if (!config) { + LOG(ERROR) << "UpdaterModule::GetUseCompressedUpdates: missing " + << "configurator"; + return false; + } + + bool use_compressed_updates = config->GetUseCompressedUpdates(); + LOG(INFO) << "UpdaterModule::GetUseCompressedUpdates use_compressed_updates=" + << use_compressed_updates; + return use_compressed_updates; +} + +void UpdaterModule::SetUseCompressedUpdates(bool use_compressed_updates) { + auto config = updater_configurator_; + if (!config) { + LOG(ERROR) << "UpdaterModule::SetUseCompressedUpdates: missing " + << "configurator"; + return; + } + + LOG(INFO) << "UpdaterModule::SetUseCompressedUpdates use_compressed_updates=" + << use_compressed_updates; + config->SetUseCompressedUpdates(use_compressed_updates); +} + + } // namespace updater } // namespace cobalt
diff --git a/cobalt/updater/updater_module.h b/cobalt/updater/updater_module.h index 0d6f793..157b121 100644 --- a/cobalt/updater/updater_module.h +++ b/cobalt/updater/updater_module.h
@@ -153,6 +153,9 @@ void SetMinFreeSpaceBytes(uint64_t bytes); + bool GetUseCompressedUpdates() const; + void SetUseCompressedUpdates(bool use_compressed_updates); + private: std::unique_ptr<base::Thread> updater_thread_; scoped_refptr<update_client::UpdateClient> update_client_;
diff --git a/cobalt/watchdog/BUILD.gn b/cobalt/watchdog/BUILD.gn index 8e231cf..131d334 100644 --- a/cobalt/watchdog/BUILD.gn +++ b/cobalt/watchdog/BUILD.gn
@@ -25,3 +25,16 @@ "//starboard/common", ] } + +target(gtest_target_type, "watchdog_test") { + testonly = true + + sources = [ "watchdog_test.cc" ] + + deps = [ + ":watchdog", + "//cobalt/test:run_all_unittests", + "//testing/gmock", + "//testing/gtest", + ] +}
diff --git a/cobalt/watchdog/watchdog.cc b/cobalt/watchdog/watchdog.cc index 0a46c90..8ad8474 100644 --- a/cobalt/watchdog/watchdog.cc +++ b/cobalt/watchdog/watchdog.cc
@@ -64,11 +64,21 @@ bool Watchdog::Initialize( persistent_storage::PersistentSettings* persistent_settings) { + return InitializeCustom(persistent_settings, + std::string(kWatchdogViolationsJson), + kWatchdogMonitorFrequency); +} + +bool Watchdog::InitializeCustom( + persistent_storage::PersistentSettings* persistent_settings, + std::string watchdog_file_name, int64_t watchdog_monitor_frequency) { persistent_settings_ = persistent_settings; is_disabled_ = !GetPersistentSettingWatchdogEnable(); if (is_disabled_) return true; + watchdog_file_name_ = watchdog_file_name; + watchdog_monitor_frequency_ = watchdog_monitor_frequency; SB_CHECK(SbMutexCreate(&mutex_)); pending_write_ = false; write_wait_time_microseconds_ = kWatchdogWriteWaitTime; @@ -124,16 +134,16 @@ std::string Watchdog::GetWatchdogFilePath() { // Gets the Watchdog violations file path with lazy initialization. - if (watchdog_file_ == "") { + if (watchdog_file_path_ == "") { // Sets Watchdog violations file path. std::vector<char> cache_dir(kSbFileMaxPath + 1, 0); SbSystemGetPath(kSbSystemPathCacheDirectory, cache_dir.data(), kSbFileMaxPath); - watchdog_file_ = std::string(cache_dir.data()) + kSbFileSepString + - std::string(kWatchdogViolationsJson); - SB_LOG(INFO) << "[Watchdog] Violations filepath: " << watchdog_file_; + watchdog_file_path_ = + std::string(cache_dir.data()) + kSbFileSepString + watchdog_file_name_; + SB_LOG(INFO) << "[Watchdog] Violations filepath: " << watchdog_file_path_; } - return watchdog_file_; + return watchdog_file_path_; } void Watchdog::WriteWatchdogViolations() { @@ -207,7 +217,7 @@ if (watchdog_violation) MaybeTriggerCrash(context); SB_CHECK(SbMutexRelease(&(static_cast<Watchdog*>(context))->mutex_)); - SbThreadSleep(kWatchdogMonitorFrequency); + SbThreadSleep(static_cast<Watchdog*>(context)->watchdog_monitor_frequency_); } return nullptr; } @@ -389,16 +399,17 @@ bool Watchdog::Register(std::string name, std::string description, base::ApplicationState monitor_state, - int64_t time_interval, int64_t time_wait, - Replace replace) { + int64_t time_interval_microseconds, + int64_t time_wait_microseconds, Replace replace) { if (is_disabled_) return true; // Validates parameters. - if (time_interval < kWatchdogMonitorFrequency || time_wait < 0) { + if (time_interval_microseconds < watchdog_monitor_frequency_ || + time_wait_microseconds < 0) { SB_DLOG(ERROR) << "[Watchdog] Unable to Register: " << name; - if (time_interval < kWatchdogMonitorFrequency) { + if (time_interval_microseconds < watchdog_monitor_frequency_) { SB_DLOG(ERROR) << "[Watchdog] Time interval less than min: " - << kWatchdogMonitorFrequency; + << watchdog_monitor_frequency_; } else { SB_DLOG(ERROR) << "[Watchdog] Time wait is negative."; } @@ -433,8 +444,8 @@ client->description = description; client->ping_infos = base::Value(base::Value::Type::LIST); client->monitor_state = monitor_state; - client->time_interval_microseconds = time_interval; - client->time_wait_microseconds = time_wait; + client->time_interval_microseconds = time_interval_microseconds; + client->time_wait_microseconds = time_wait_microseconds; client->time_registered_microseconds = current_time; client->time_registered_monotonic_microseconds = current_monotonic_time; client->time_last_pinged_microseconds = current_time; @@ -515,7 +526,7 @@ return client_exists; } -std::string Watchdog::GetWatchdogViolations() { +std::string Watchdog::GetWatchdogViolations(bool clear) { // Gets a json string containing the Watchdog violations since the last // call (up to the kWatchdogMaxViolations limit). @@ -536,13 +547,13 @@ watchdog_json = std::string(buffer.data()); // Removes all Watchdog violations. - if (violations_map_) { - base::DictionaryValue** dict = nullptr; - violations_map_->GetAsDictionary(dict); - if (dict) (*dict)->Clear(); - violations_count_ = 0; + if (clear) { + if (violations_map_) { + static_cast<base::DictionaryValue*>(violations_map_.get())->Clear(); + violations_count_ = 0; + } + starboard::SbFileDeleteRecursive(GetWatchdogFilePath().c_str(), true); } - starboard::SbFileDeleteRecursive(GetWatchdogFilePath().c_str(), true); SB_LOG(INFO) << "[Watchdog] Reading violations:\n" << watchdog_json; } else { SB_LOG(INFO) << "[Watchdog] No violations.";
diff --git a/cobalt/watchdog/watchdog.h b/cobalt/watchdog/watchdog.h index 1532f79..04ba81d 100644 --- a/cobalt/watchdog/watchdog.h +++ b/cobalt/watchdog/watchdog.h
@@ -73,16 +73,22 @@ class Watchdog : public Singleton<Watchdog> { public: bool Initialize(persistent_storage::PersistentSettings* persistent_settings); + // Directly used for testing only. + bool InitializeCustom( + persistent_storage::PersistentSettings* persistent_settings, + std::string watchdog_file_name, int64_t watchdog_monitor_frequency); bool InitializeStub(); void Uninitialize(); + std::string GetWatchdogFilePath(); void UpdateState(base::ApplicationState state); bool Register(std::string name, std::string description, - base::ApplicationState monitor_state, int64_t time_interval, - int64_t time_wait = 0, Replace replace = NONE); + base::ApplicationState monitor_state, + int64_t time_interval_microseconds, + int64_t time_wait_microseconds = 0, Replace replace = NONE); bool Unregister(const std::string& name, bool lock = true); bool Ping(const std::string& name); bool Ping(const std::string& name, const std::string& info); - std::string GetWatchdogViolations(); + std::string GetWatchdogViolations(bool clear = true); bool GetPersistentSettingWatchdogEnable(); void SetPersistentSettingWatchdogEnable(bool enable_watchdog); bool GetPersistentSettingWatchdogCrash(); @@ -94,7 +100,6 @@ #endif // defined(_DEBUG) private: - std::string GetWatchdogFilePath(); void WriteWatchdogViolations(); static void* Monitor(void* context); static void UpdateViolationsMap(void* context, Client* client, @@ -104,8 +109,10 @@ static void MaybeWriteWatchdogViolations(void* context); static void MaybeTriggerCrash(void* context); - // Watchdog violations file path. - std::string watchdog_file_; + // The Watchdog violations json filename. + std::string watchdog_file_name_; + // The Watchdog violations json filepath. + std::string watchdog_file_path_; // Access to persistent settings. persistent_storage::PersistentSettings* persistent_settings_; // Flag to disable Watchdog. When disabled, Watchdog behaves like a stub @@ -137,6 +144,8 @@ SbThread watchdog_thread_; // Flag to stop monitor thread. bool is_monitoring_; + // The frequency in microseconds of monitor loops. + int64_t watchdog_monitor_frequency_; #if defined(_DEBUG) starboard::Mutex delay_lock_;
diff --git a/cobalt/watchdog/watchdog_test.cc b/cobalt/watchdog/watchdog_test.cc new file mode 100644 index 0000000..fb0cf19 --- /dev/null +++ b/cobalt/watchdog/watchdog_test.cc
@@ -0,0 +1,489 @@ +// 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 <vector> + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "cobalt/watchdog/watchdog.h" +#include "starboard/common/file.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cobalt { +namespace watchdog { + +namespace { + +const char kWatchdogViolationsJson[] = "watchdog_test.json"; +const int64_t kWatchdogMonitorFrequency = 100000; + +} // namespace + +class WatchdogTest : public testing::Test { + protected: + WatchdogTest() {} + + void SetUp() final { + watchdog_ = new watchdog::Watchdog(); + watchdog_->InitializeCustom(nullptr, std::string(kWatchdogViolationsJson), + kWatchdogMonitorFrequency); + watchdog_->GetWatchdogViolations(); + } + + void TearDown() final { + watchdog_->Uninitialize(); + delete watchdog_; + watchdog_ = nullptr; + } + + base::Value CreateDummyViolationDict(std::string desc, int begin, int end) { + base::Value violation_dict(base::Value::Type::DICTIONARY); + violation_dict.SetKey("description", base::Value(desc)); + base::Value list(base::Value::Type::LIST); + for (int i = begin; i < end; i++) + list.GetList().emplace_back(CreateDummyViolation(i)); + violation_dict.SetKey("violations", list.Clone()); + return violation_dict.Clone(); + } + + base::Value CreateDummyViolation(int timestamp_violation) { + base::Value violation(base::Value::Type::DICTIONARY); + base::Value ping_infos(base::Value::Type::LIST); + violation.SetKey("pingInfos", ping_infos.Clone()); + violation.SetKey("monitorState", + base::Value(std::string(GetApplicationStateString( + base::kApplicationStateStarted)))); + violation.SetKey("timeIntervalMilliseconds", base::Value("0")); + violation.SetKey("timeWaitMilliseconds", base::Value("0")); + violation.SetKey("timestampRegisteredMilliseconds", base::Value("0")); + violation.SetKey("timestampLastPingedMilliseconds", base::Value("0")); + violation.SetKey("timestampViolationMilliseconds", + base::Value(std::to_string(timestamp_violation))); + violation.SetKey("violationDurationMilliseconds", base::Value("0")); + base::Value registered_clients(base::Value::Type::LIST); + violation.SetKey("registeredClients", registered_clients.Clone()); + return violation.Clone(); + } + + watchdog::Watchdog* watchdog_; +}; + +TEST_F(WatchdogTest, RedundantRegistersShouldFail) { + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + + ASSERT_FALSE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 0, PING)); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 0, ALL)); + ASSERT_TRUE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, RegisterOnlyAcceptsValidParameters) { + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 0)); + ASSERT_TRUE(watchdog_->Unregister("test-name")); + ASSERT_FALSE(watchdog_->Register("test-name-1", "test-desc-1", + base::kApplicationStateStarted, 1, 0)); + ASSERT_FALSE(watchdog_->Unregister("test-name-1")); + ASSERT_FALSE(watchdog_->Register("test-name-2", "test-desc-2", + base::kApplicationStateStarted, 0, 0)); + ASSERT_FALSE(watchdog_->Unregister("test-name-2")); + ASSERT_FALSE(watchdog_->Register("test-name-3", "test-desc-3", + base::kApplicationStateStarted, -1, 0)); + ASSERT_FALSE(watchdog_->Unregister("test-name-3")); + ASSERT_TRUE(watchdog_->Register("test-name-4", "test-desc-4", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 1)); + ASSERT_TRUE(watchdog_->Unregister("test-name-4")); + ASSERT_TRUE(watchdog_->Register("test-name-5", "test-desc-5", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 0)); + ASSERT_TRUE(watchdog_->Unregister("test-name-5")); + ASSERT_FALSE(watchdog_->Register("test-name-6", "test-desc-6", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, -1)); + ASSERT_FALSE(watchdog_->Unregister("test-name-6")); +} + +TEST_F(WatchdogTest, UnmatchedUnregistersShouldFail) { + ASSERT_FALSE(watchdog_->Unregister("test-name")); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + ASSERT_TRUE(watchdog_->Unregister("test-name")); + ASSERT_FALSE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, UnmatchedPingsShouldFail) { + ASSERT_FALSE(watchdog_->Ping("test-name")); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + ASSERT_TRUE(watchdog_->Ping("test-name")); + ASSERT_TRUE(watchdog_->Ping("test-name")); + ASSERT_TRUE(watchdog_->Unregister("test-name")); + ASSERT_FALSE(watchdog_->Ping("test-name")); +} + +TEST_F(WatchdogTest, PingOnlyAcceptsValidParameters) { + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + ASSERT_TRUE(watchdog_->Ping("test-name", "42")); + ASSERT_FALSE( + watchdog_->Ping("test-name", + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxx")); + ASSERT_TRUE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, ViolationsJsonShouldPersistAndBeValid) { + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + ASSERT_TRUE(watchdog_->Ping("test-name", "test-ping")); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + ASSERT_TRUE(watchdog_->Unregister("test-name")); + TearDown(); + watchdog_ = new watchdog::Watchdog(); + watchdog_->InitializeCustom(nullptr, std::string(kWatchdogViolationsJson), + kWatchdogMonitorFrequency); + + // Validates Violation json file. + std::string json = watchdog_->GetWatchdogViolations(); + ASSERT_NE(json, ""); + std::unique_ptr<base::Value> violations_map = base::JSONReader::Read(json); + ASSERT_NE(violations_map, nullptr); + base::Value* violation_dict = violations_map->FindKey("test-name"); + ASSERT_NE(violation_dict, nullptr); + base::Value* description = violation_dict->FindKey("description"); + ASSERT_NE(description, nullptr); + ASSERT_EQ(description->GetString(), "test-desc"); + base::Value* violations = violation_dict->FindKey("violations"); + ASSERT_NE(violations, nullptr); + ASSERT_EQ(violations->GetList().size(), 1); + base::Value* monitor_state = violations->GetList()[0].FindKey("monitorState"); + ASSERT_NE(monitor_state, nullptr); + ASSERT_EQ( + monitor_state->GetString(), + std::string(GetApplicationStateString(base::kApplicationStateStarted))); + base::Value* ping_infos = violations->GetList()[0].FindKey("pingInfos"); + ASSERT_NE(ping_infos, nullptr); + ASSERT_EQ(ping_infos->GetList().size(), 1); + base::Value* info = ping_infos->GetList()[0].FindKey("info"); + ASSERT_NE(info, nullptr); + ASSERT_EQ(info->GetString(), "test-ping"); + base::Value* timestamp_milliseconds = + ping_infos->GetList()[0].FindKey("timestampMilliseconds"); + ASSERT_NE(timestamp_milliseconds, nullptr); + std::stoll(timestamp_milliseconds->GetString()); + base::Value* registered_clients = + violations->GetList()[0].FindKey("registeredClients"); + ASSERT_NE(registered_clients, nullptr); + ASSERT_EQ(registered_clients->GetList().size(), 1); + ASSERT_EQ(registered_clients->GetList()[0].GetString(), "test-name"); + base::Value* time_interval_milliseconds = + violations->GetList()[0].FindKey("timeIntervalMilliseconds"); + ASSERT_NE(time_interval_milliseconds, nullptr); + std::stoll(time_interval_milliseconds->GetString()); + base::Value* time_wait_milliseconds = + violations->GetList()[0].FindKey("timeWaitMilliseconds"); + ASSERT_NE(time_wait_milliseconds, nullptr); + std::stoll(time_wait_milliseconds->GetString()); + base::Value* timestamp_last_pinged_milliseconds = + violations->GetList()[0].FindKey("timestampLastPingedMilliseconds"); + ASSERT_NE(timestamp_last_pinged_milliseconds, nullptr); + std::stoll(timestamp_last_pinged_milliseconds->GetString()); + base::Value* timestamp_registered_milliseconds = + violations->GetList()[0].FindKey("timestampRegisteredMilliseconds"); + ASSERT_NE(timestamp_registered_milliseconds, nullptr); + std::stoll(timestamp_registered_milliseconds->GetString()); + base::Value* timestamp_violation_milliseconds = + violations->GetList()[0].FindKey("timestampViolationMilliseconds"); + ASSERT_NE(timestamp_violation_milliseconds, nullptr); + std::stoll(timestamp_violation_milliseconds->GetString()); + base::Value* violation_duration_milliseconds = + violations->GetList()[0].FindKey("violationDurationMilliseconds"); + ASSERT_NE(violation_duration_milliseconds, nullptr); + std::stoll(violation_duration_milliseconds->GetString()); +} + +TEST_F(WatchdogTest, RedundantViolationsShouldStack) { + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + std::string json = watchdog_->GetWatchdogViolations(false); + ASSERT_NE(json, ""); + std::unique_ptr<base::Value> uncleared_violations_map = + base::JSONReader::Read(json); + ASSERT_NE(uncleared_violations_map, nullptr); + base::Value* violation_dict = uncleared_violations_map->FindKey("test-name"); + base::Value* violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 1); + std::string uncleared_timestamp = + violations->GetList()[0] + .FindKey("timestampLastPingedMilliseconds") + ->GetString(); + int64_t uncleared_duration = + std::stoll(violations->GetList()[0] + .FindKey("violationDurationMilliseconds") + ->GetString()); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + json = watchdog_->GetWatchdogViolations(false); + ASSERT_NE(json, ""); + std::unique_ptr<base::Value> violations_map = base::JSONReader::Read(json); + ASSERT_NE(violations_map, nullptr); + violation_dict = violations_map->FindKey("test-name"); + violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 1); + std::string timestamp = violations->GetList()[0] + .FindKey("timestampLastPingedMilliseconds") + ->GetString(); + int64_t duration = std::stoll(violations->GetList()[0] + .FindKey("violationDurationMilliseconds") + ->GetString()); + ASSERT_EQ(uncleared_timestamp, timestamp); + ASSERT_LT(uncleared_duration, duration); + ASSERT_TRUE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, ViolationsShouldResetAfterFetch) { + ASSERT_TRUE(watchdog_->Register("test-name-1", "test-desc-1", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + ASSERT_TRUE(watchdog_->Unregister("test-name-1")); + std::string json = watchdog_->GetWatchdogViolations(); + ASSERT_NE(json.find("test-name-1"), std::string::npos); + ASSERT_EQ(json.find("test-name-2"), std::string::npos); + ASSERT_TRUE(watchdog_->Register("test-name-2", "test-desc-2", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + ASSERT_TRUE(watchdog_->Unregister("test-name-2")); + json = watchdog_->GetWatchdogViolations(); + ASSERT_EQ(json.find("test-name-1"), std::string::npos); + ASSERT_NE(json.find("test-name-2"), std::string::npos); + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); +} + +TEST_F(WatchdogTest, PingInfosAreEvictedAfterMax) { + ASSERT_TRUE(watchdog_->Register("test-name", "test_desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + for (int i = 0; i < 21; i++) { + ASSERT_TRUE(watchdog_->Ping("test-name", std::to_string(i))); + } + SbThreadSleep(kWatchdogMonitorFrequency * 2); + std::string json = watchdog_->GetWatchdogViolations(); + ASSERT_NE(json, ""); + std::unique_ptr<base::Value> violations_map = base::JSONReader::Read(json); + ASSERT_NE(violations_map, nullptr); + base::Value* violation_dict = violations_map->FindKey("test-name"); + base::Value* violations = violation_dict->FindKey("violations"); + base::Value* pingInfos = violations->GetList()[0].FindKey("pingInfos"); + ASSERT_EQ(pingInfos->GetList().size(), 20); + ASSERT_EQ(pingInfos->GetList()[0].FindKey("info")->GetString(), "1"); + ASSERT_TRUE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, ViolationsAreEvictedAfterMax) { + // Creates maxed Violation json file. + std::unique_ptr<base::Value> dummy_map = + std::make_unique<base::Value>(base::Value::Type::DICTIONARY); + dummy_map->SetKey("test-name-1", + CreateDummyViolationDict("test-desc-1", 0, 99)); + dummy_map->SetKey("test-name-2", + CreateDummyViolationDict("test-desc-2", 1, 102)); + std::string json; + base::JSONWriter::Write(*dummy_map, &json); + starboard::ScopedFile file(watchdog_->GetWatchdogFilePath().c_str(), + kSbFileCreateAlways | kSbFileWrite); + file.WriteAll(json.c_str(), static_cast<int>(json.size())); + + ASSERT_TRUE(watchdog_->Register("test-name-3", "test-desc-3", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + ASSERT_TRUE(watchdog_->Register("test-name-4", "test-desc-4", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + + json = watchdog_->GetWatchdogViolations(false); + ASSERT_NE(json, ""); + std::unique_ptr<base::Value> uncleared_violations_map = + base::JSONReader::Read(json); + ASSERT_NE(uncleared_violations_map, nullptr); + base::Value* violation_dict = + uncleared_violations_map->FindKey("test-name-1"); + base::Value* violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 99); + violation_dict = uncleared_violations_map->FindKey("test-name-2"); + violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 99); + ASSERT_EQ(violations->GetList()[0] + .FindKey("timestampViolationMilliseconds") + ->GetString(), + "3"); + violation_dict = uncleared_violations_map->FindKey("test-name-3"); + violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 1); + violation_dict = uncleared_violations_map->FindKey("test-name-4"); + violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 1); + + ASSERT_TRUE(watchdog_->Ping("test-name-3")); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + + json = watchdog_->GetWatchdogViolations(); + ASSERT_NE(json, ""); + std::unique_ptr<base::Value> violations_map = base::JSONReader::Read(json); + ASSERT_NE(violations_map, nullptr); + violation_dict = violations_map->FindKey("test-name-1"); + violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 98); + ASSERT_EQ(violations->GetList()[0] + .FindKey("timestampViolationMilliseconds") + ->GetString(), + "1"); + violation_dict = violations_map->FindKey("test-name-2"); + violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 99); + violation_dict = violations_map->FindKey("test-name-3"); + violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 2); + violation_dict = violations_map->FindKey("test-name-4"); + violations = violation_dict->FindKey("violations"); + ASSERT_EQ(violations->GetList().size(), 1); + + ASSERT_TRUE(watchdog_->Unregister("test-name-3")); + ASSERT_TRUE(watchdog_->Unregister("test-name-4")); +} + +TEST_F(WatchdogTest, UpdateStateShouldPreventViolations) { + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + watchdog_->UpdateState(base::kApplicationStateBlurred); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); + ASSERT_TRUE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, TimeWaitShouldPreventViolations) { + ASSERT_TRUE(watchdog_->Register( + "test-name", "test-desc", base::kApplicationStateStarted, + kWatchdogMonitorFrequency, kWatchdogMonitorFrequency * 3)); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); + ASSERT_TRUE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, PingsShouldPreventViolations) { + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + SbThreadSleep(kWatchdogMonitorFrequency / 2); + ASSERT_TRUE(watchdog_->Ping("test-name")); + SbThreadSleep(kWatchdogMonitorFrequency / 2); + ASSERT_TRUE(watchdog_->Ping("test-name")); + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); + SbThreadSleep(kWatchdogMonitorFrequency / 2); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 0, PING)); + SbThreadSleep(kWatchdogMonitorFrequency / 2); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 0, PING)); + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); + SbThreadSleep(kWatchdogMonitorFrequency / 2); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 0, ALL)); + SbThreadSleep(kWatchdogMonitorFrequency / 2); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency, 0, ALL)); + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); + ASSERT_TRUE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, UnregisterShouldPreventViolations) { + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + ASSERT_TRUE(watchdog_->Unregister("test-name")); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); +} + +TEST_F(WatchdogTest, KillSwitchShouldPreventViolations) { + TearDown(); + watchdog_ = new watchdog::Watchdog(); + watchdog_->InitializeStub(); + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + ASSERT_EQ(watchdog_->GetWatchdogViolations(), ""); + ASSERT_TRUE(watchdog_->Unregister("test-name")); +} + +TEST_F(WatchdogTest, FrequentConsecutiveViolationsShouldNotWrite) { + ASSERT_TRUE(watchdog_->Register("test-name", "test-desc", + base::kApplicationStateStarted, + kWatchdogMonitorFrequency)); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + std::string write_json = ""; + starboard::ScopedFile read_file(watchdog_->GetWatchdogFilePath().c_str(), + kSbFileOpenOnly | kSbFileRead); + if (read_file.IsValid()) { + int64_t kFileSize = read_file.GetSize(); + std::vector<char> buffer(kFileSize + 1, 0); + read_file.ReadAll(buffer.data(), kFileSize); + write_json = std::string(buffer.data()); + } + ASSERT_NE(write_json, ""); + ASSERT_TRUE(watchdog_->Ping("test-name")); + SbThreadSleep(kWatchdogMonitorFrequency * 2); + ASSERT_TRUE(watchdog_->Unregister("test-name")); + std::string no_write_json = ""; + starboard::ScopedFile read_file_again( + watchdog_->GetWatchdogFilePath().c_str(), kSbFileOpenOnly | kSbFileRead); + if (read_file_again.IsValid()) { + int64_t kFileSize = read_file_again.GetSize(); + std::vector<char> buffer(kFileSize + 1, 0); + read_file_again.ReadAll(buffer.data(), kFileSize); + no_write_json = std::string(buffer.data()); + } + ASSERT_NE(no_write_json, ""); + ASSERT_EQ(write_json, no_write_json); + std::string json = watchdog_->GetWatchdogViolations(); + ASSERT_NE(write_json, json); +} + +} // namespace watchdog +} // namespace cobalt
diff --git a/cobalt/web/error_event.h b/cobalt/web/error_event.h index 2322f98..8fad2b6 100644 --- a/cobalt/web/error_event.h +++ b/cobalt/web/error_event.h
@@ -33,18 +33,17 @@ // https://www.w3.org/TR/html50/webappapis.html#errorevent class ErrorEvent : public Event { public: - ErrorEvent() : Event(base::Tokens::error()), lineno_(0), colno_(0) {} - explicit ErrorEvent(const std::string& type) - : Event(type), lineno_(0), colno_(0) {} - ErrorEvent(const std::string& type, const web::ErrorEventInit& init_dict) - : Event(type, init_dict), + ErrorEvent() : Event(base::Tokens::error()) {} + explicit ErrorEvent(const std::string& type) : Event(type) {} + explicit ErrorEvent(const web::ErrorEventInit& init_dict) + : Event(base::Tokens::error(), init_dict), message_(init_dict.message()), filename_(init_dict.filename()), lineno_(init_dict.lineno()), colno_(init_dict.colno()) { InitError(init_dict); } - ErrorEvent(base::Token type, const web::ErrorEventInit& init_dict) + ErrorEvent(const std::string& type, const web::ErrorEventInit& init_dict) : Event(type, init_dict), message_(init_dict.message()), filename_(init_dict.filename()), @@ -55,8 +54,8 @@ // Web API: ErrorEvent // - std::string message() const { return message_; } - std::string filename() const { return filename_; } + const std::string& message() const { return message_; } + const std::string& filename() const { return filename_; } uint32 lineno() const { return lineno_; } uint32 colno() const { return colno_; } @@ -82,8 +81,8 @@ std::string message_; std::string filename_; - uint32 lineno_; - uint32 colno_; + uint32 lineno_ = 0; + uint32 colno_ = 0; std::unique_ptr<script::ValueHandleHolder::Reference> error_; };
diff --git a/cobalt/web/message_port.cc b/cobalt/web/message_port.cc index 519e682..e0eb126 100644 --- a/cobalt/web/message_port.cc +++ b/cobalt/web/message_port.cc
@@ -66,7 +66,7 @@ } void MessagePort::PostMessage(const script::ValueHandleHolder& message) { - PostMessageSerialized(std::move(SerializeScriptValue(message))); + PostMessageSerialized(std::move(script::SerializeScriptValue(message))); } void MessagePort::PostMessageSerialized(
diff --git a/cobalt/worker/service_worker_jobs.cc b/cobalt/worker/service_worker_jobs.cc index 0c31df7..e30f364 100644 --- a/cobalt/worker/service_worker_jobs.cc +++ b/cobalt/worker/service_worker_jobs.cc
@@ -841,7 +841,7 @@ ResolveJobPromise(job, registration); // 8. Let settingsObjects be all environment settings objects whose origin is // registration’s scope url's origin. - auto registration_origin = registration->scope_url().GetOrigin(); + auto registration_origin = loader::Origin(registration->scope_url()); // 9. For each settingsObject of settingsObjects... for (auto& context : web_context_registrations_) { if (context->environment_settings()->GetOrigin() == registration_origin) { @@ -1469,7 +1469,7 @@ DCHECK_NE(kServiceWorkerStateParsed, state); // 2. Set worker's state to state. worker->set_state(state); - auto worker_origin = worker->script_url().GetOrigin(); + auto worker_origin = loader::Origin(worker->script_url()); // 3. Let settingsObjects be all environment settings objects whose origin is // worker's script url's origin. // 4. For each settingsObject of settingsObjects... @@ -1615,7 +1615,7 @@ // Algorithm for Unregister: // https://w3c.github.io/ServiceWorker/#unregister-algorithm // 1. If the origin of job’s scope url is not job’s client's origin, then: - if (!url::Origin::Create(job->client->GetOrigin()) + if (!url::Origin::Create(GURL(job->client->GetOrigin().SerializedOrigin())) .IsSameOriginWith(url::Origin::Create(job->scope_url))) { // 1.1. Invoke Reject Job Promise with job and "SecurityError" DOMException. RejectJobPromise(
diff --git a/cobalt/worker/service_worker_object.cc b/cobalt/worker/service_worker_object.cc index 193638b..436f256 100644 --- a/cobalt/worker/service_worker_object.cc +++ b/cobalt/worker/service_worker_object.cc
@@ -153,6 +153,9 @@ // Return serviceWorker’s script url. // The origin // Return its registering service worker client's origin. + WorkerSettings* worker_settings = new WorkerSettings(); + worker_settings->set_origin( + loader::Origin(containing_service_worker_registration()->scope_url())); // The policy container // Return workerGlobalScope’s policy container. // The time origin @@ -162,7 +165,8 @@ // serviceWorker’s script url, top-level creation URL to null, top-level // origin to an implementation-defined value, target browsing context to // null, and active service worker to null. - web_context_->setup_environment_settings(new WorkerSettings()); + + web_context_->setup_environment_settings(worker_settings); web_context_->environment_settings()->set_creation_url(script_url_); scoped_refptr<ServiceWorkerGlobalScope> service_worker_global_scope = new ServiceWorkerGlobalScope(web_context_->environment_settings(), this);
diff --git a/cobalt/worker/worker.cc b/cobalt/worker/worker.cc index b8e283b..a820c8f 100644 --- a/cobalt/worker/worker.cc +++ b/cobalt/worker/worker.cc
@@ -24,16 +24,16 @@ #include "base/threading/thread.h" #include "cobalt/browser/user_agent_platform_info.h" #include "cobalt/script/environment_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 "cobalt/web/error_event.h" +#include "cobalt/web/error_event_init.h" #include "cobalt/web/message_port.h" #include "cobalt/worker/dedicated_worker_global_scope.h" #include "cobalt/worker/worker_global_scope.h" #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 { @@ -85,8 +85,14 @@ // . For the global object, if is shared is true, create a new // SharedWorkerGlobalScope object. Otherwise, create a new // DedicatedWorkerGlobalScope object. - web_context_->setup_environment_settings( - new WorkerSettings(options_.outside_port)); + WorkerSettings* worker_settings = new WorkerSettings(options_.outside_port); + // From algorithm to set up a worker environment settings object + // Let inherited origin be outside settings's origin. + // The origin return a unique opaque origin if worker global scope's url's + // scheme is "data", and inherited origin otherwise. + // https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#set-up-a-worker-environment-settings-object + worker_settings->set_origin(options_.outside_settings->GetOrigin()); + web_context_->setup_environment_settings(worker_settings); // From algorithm for to setup up a worker environment settings object: // https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#set-up-a-worker-environment-settings-object // 5. Set settings object's creation URL to worker global scope's url. @@ -253,10 +259,18 @@ std::string retval = web_context_->script_runner()->Execute( content, script_location, mute_errors, &succeeded); if (!succeeded) { - LOG(WARNING) << "Script execution failed : " << retval; options_.outside_settings->context() - ->GetWindowOrWorkerGlobalScope() - ->DispatchEvent(new web::Event(base::Tokens::error())); + ->message_loop() + ->task_runner() + ->PostTask(FROM_HERE, + base::BindOnce( + [](web::Context* context, const std::string& message) { + web::ErrorEventInit error; + error.set_message(message); + context->GetWindowOrWorkerGlobalScope()->DispatchEvent( + new web::ErrorEvent(error)); + }, + options_.outside_settings->context(), retval)); } // 24. Enable outside port's port message queue.
diff --git a/cobalt/worker/worker_global_scope.cc b/cobalt/worker/worker_global_scope.cc index 3316581..662aaa5 100644 --- a/cobalt/worker/worker_global_scope.cc +++ b/cobalt/worker/worker_global_scope.cc
@@ -359,7 +359,6 @@ } if (!succeeded) { // TODO(): Handle script execution errors. - LOG(WARNING) << "Script Execution Failed : " << retval; web::DOMException::Raise(web::DOMException::kSyntaxErr, exception_state); return;
diff --git a/cobalt/worker/worker_settings.cc b/cobalt/worker/worker_settings.cc index 8e53e10..df42733 100644 --- a/cobalt/worker/worker_settings.cc +++ b/cobalt/worker/worker_settings.cc
@@ -43,6 +43,23 @@ return context()->GetWindowOrWorkerGlobalScope()->AsWorker()->Url(); } +loader::Origin WorkerSettings::GetOrigin() const { + // From algorithm for to setup up a worker environment settings object: + // https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#set-up-a-worker-environment-settings-object + // 3. Let settings object be a new environment settings object whose + // algorithms are defined as follows: + // The origin + // Return a unique opaque origin if worker global scope's url's scheme is + // "data", and inherited origin otherwise. + DCHECK(context()->GetWindowOrWorkerGlobalScope()->IsWorker()); + const GURL& url = + context()->GetWindowOrWorkerGlobalScope()->AsWorker()->Url(); + // TODO(b/244368134): Replace with url::Origin::CreateUniqueOpaque(). + // Note: This does not have to be specialized for service workers, since + // their URL can not be a data URL. + if (url.SchemeIs("data")) return loader::Origin(); + return origin_; +} } // namespace worker } // namespace cobalt
diff --git a/cobalt/worker/worker_settings.h b/cobalt/worker/worker_settings.h index b2d7097..3550b19 100644 --- a/cobalt/worker/worker_settings.h +++ b/cobalt/worker/worker_settings.h
@@ -37,9 +37,16 @@ // const GURL& base_url() const override; + // Return the origin of window's associated Document. + // https://html.spec.whatwg.org/#set-up-a-window-environment-settings-object + void set_origin(const loader::Origin& origin) { origin_ = origin; } + loader::Origin GetOrigin() const override; + private: // Outer message port. web::MessagePort* message_port_ = nullptr; + + loader::Origin origin_; }; } // namespace worker
diff --git a/cobalt/xhr/xml_http_request.cc b/cobalt/xhr/xml_http_request.cc index 56de1ee..d943154 100644 --- a/cobalt/xhr/xml_http_request.cc +++ b/cobalt/xhr/xml_http_request.cc
@@ -570,7 +570,7 @@ if (upload_) { upload_listener_ = upload_->HasOneOrMoreAttributeEventListener(); } - origin_ = loader::Origin(settings_->GetOrigin()); + origin_ = settings_->GetOrigin(); // Step 9 sent_ = true; // Now that a send is happening, prevent this object
diff --git a/cobalt/xhr/xml_http_request.h b/cobalt/xhr/xml_http_request.h index 046e90f..01979a6 100644 --- a/cobalt/xhr/xml_http_request.h +++ b/cobalt/xhr/xml_http_request.h
@@ -26,6 +26,7 @@ #include "cobalt/dom/document.h" #include "cobalt/loader/cors_preflight.h" #include "cobalt/loader/net_fetcher.h" +#include "cobalt/loader/origin.h" #include "cobalt/script/array_buffer.h" #include "cobalt/script/array_buffer_view.h" #include "cobalt/script/environment_settings.h"
diff --git a/components/update_client/configurator.h b/components/update_client/configurator.h index e4619e9..d1b5e40 100644 --- a/components/update_client/configurator.h +++ b/components/update_client/configurator.h
@@ -182,6 +182,9 @@ virtual void SetMinFreeSpaceBytes(uint64_t bytes) = 0; virtual uint64_t GetMinFreeSpaceBytes() = 0; + + virtual bool GetUseCompressedUpdates() const = 0; + virtual void SetUseCompressedUpdates(bool use_compressed_updates) = 0; #endif protected:
diff --git a/components/update_client/test_configurator.h b/components/update_client/test_configurator.h index 9b37687..fa07aa7 100644 --- a/components/update_client/test_configurator.h +++ b/components/update_client/test_configurator.h
@@ -127,7 +127,7 @@ void SetAppGuid(const std::string& app_guid); #if defined(STARBOARD) - // TODO: add unit tests for updater channels and status + // TODO: add unit tests for updater channels, status, and compressed updates. void SetChannel(const std::string& channel) override {} void CompareAndSwapChannelChanged(int old_value, int new_value) override {} std::string GetUpdaterStatus() const override { return ""; } @@ -139,6 +139,9 @@ void SetMinFreeSpaceBytes(uint64_t bytes) override {} uint64_t GetMinFreeSpaceBytes() override { return 0; } + + bool GetUseCompressedUpdates() const override { return false; } + void SetUseCompressedUpdates(bool use_compressed_updates) override {} #else network::TestURLLoaderFactory* test_url_loader_factory() { return &test_url_loader_factory_;
diff --git a/docker/linux/base/Dockerfile b/docker/linux/base/Dockerfile index 50dd9e0..849e656 100644 --- a/docker/linux/base/Dockerfile +++ b/docker/linux/base/Dockerfile
@@ -32,6 +32,4 @@ curl xz-utils \ && /opt/clean-after-apt.sh -RUN python3 -m pip install --upgrade pip - CMD ["/usr/bin/python","--version"]
diff --git a/docker/linux/linux-x64x11/Dockerfile b/docker/linux/linux-x64x11/Dockerfile index f77957f..e28bacb 100644 --- a/docker/linux/linux-x64x11/Dockerfile +++ b/docker/linux/linux-x64x11/Dockerfile
@@ -27,7 +27,8 @@ libxi-dev \ && /opt/clean-after-apt.sh -RUN python3 -m pip install "selenium==3.141.0" "Brotli==1.0.9" +COPY ./linux-x64x11/requirements.txt /opt/requirements.txt +RUN python3 -m pip install --require-hashes --no-deps -r /opt/requirements.txt CMD gn gen ${OUTDIR}/${PLATFORM}_${CONFIG} --args="target_platform=\"${PLATFORM}\" build_type=\"${CONFIG}\" sb_api_version=${SB_API_VERSION:-14}" && \ ninja -v -j ${NINJA_PARALLEL} -C ${OUTDIR}/${PLATFORM}_${CONFIG} ${TARGET:-cobalt_install}
diff --git a/docker/linux/linux-x64x11/requirements.in b/docker/linux/linux-x64x11/requirements.in new file mode 100644 index 0000000..5d8c046 --- /dev/null +++ b/docker/linux/linux-x64x11/requirements.in
@@ -0,0 +1,2 @@ +selenium==3.141.0 +Brotli==1.0.9
diff --git a/docker/linux/linux-x64x11/requirements.txt b/docker/linux/linux-x64x11/requirements.txt new file mode 100644 index 0000000..ef2d62e --- /dev/null +++ b/docker/linux/linux-x64x11/requirements.txt
@@ -0,0 +1,78 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# pip-compile --generate-hashes requirements.in +# +brotli==1.0.9 \ + --hash=sha256:12effe280b8ebfd389022aa65114e30407540ccb89b177d3fbc9a4f177c4bd5d \ + --hash=sha256:160c78292e98d21e73a4cc7f76a234390e516afcd982fa17e1422f7c6a9ce9c8 \ + --hash=sha256:16d528a45c2e1909c2798f27f7bf0a3feec1dc9e50948e738b961618e38b6a7b \ + --hash=sha256:19598ecddd8a212aedb1ffa15763dd52a388518c4550e615aed88dc3753c0f0c \ + --hash=sha256:1c48472a6ba3b113452355b9af0a60da5c2ae60477f8feda8346f8fd48e3e87c \ + --hash=sha256:268fe94547ba25b58ebc724680609c8ee3e5a843202e9a381f6f9c5e8bdb5c70 \ + --hash=sha256:269a5743a393c65db46a7bb982644c67ecba4b8d91b392403ad8a861ba6f495f \ + --hash=sha256:26d168aac4aaec9a4394221240e8a5436b5634adc3cd1cdf637f6645cecbf181 \ + --hash=sha256:29d1d350178e5225397e28ea1b7aca3648fcbab546d20e7475805437bfb0a130 \ + --hash=sha256:2aad0e0baa04517741c9bb5b07586c642302e5fb3e75319cb62087bd0995ab19 \ + --hash=sha256:3496fc835370da351d37cada4cf744039616a6db7d13c430035e901443a34daa \ + --hash=sha256:35a3edbe18e876e596553c4007a087f8bcfd538f19bc116917b3c7522fca0429 \ + --hash=sha256:3b78a24b5fd13c03ee2b7b86290ed20efdc95da75a3557cc06811764d5ad1126 \ + --hash=sha256:40d15c79f42e0a2c72892bf407979febd9cf91f36f495ffb333d1d04cebb34e4 \ + --hash=sha256:44bb8ff420c1d19d91d79d8c3574b8954288bdff0273bf788954064d260d7ab0 \ + --hash=sha256:4688c1e42968ba52e57d8670ad2306fe92e0169c6f3af0089be75bbac0c64a3b \ + --hash=sha256:495ba7e49c2db22b046a53b469bbecea802efce200dffb69b93dd47397edc9b6 \ + --hash=sha256:4d1b810aa0ed773f81dceda2cc7b403d01057458730e309856356d4ef4188438 \ + --hash=sha256:503fa6af7da9f4b5780bb7e4cbe0c639b010f12be85d02c99452825dd0feef3f \ + --hash=sha256:56d027eace784738457437df7331965473f2c0da2c70e1a1f6fdbae5402e0389 \ + --hash=sha256:5913a1177fc36e30fcf6dc868ce23b0453952c78c04c266d3149b3d39e1410d6 \ + --hash=sha256:5b6ef7d9f9c38292df3690fe3e302b5b530999fa90014853dcd0d6902fb59f26 \ + --hash=sha256:5cb1e18167792d7d21e21365d7650b72d5081ed476123ff7b8cac7f45189c0c7 \ + --hash=sha256:61a7ee1f13ab913897dac7da44a73c6d44d48a4adff42a5701e3239791c96e14 \ + --hash=sha256:622a231b08899c864eb87e85f81c75e7b9ce05b001e59bbfbf43d4a71f5f32b2 \ + --hash=sha256:68715970f16b6e92c574c30747c95cf8cf62804569647386ff032195dc89a430 \ + --hash=sha256:6b2ae9f5f67f89aade1fab0f7fd8f2832501311c363a21579d02defa844d9296 \ + --hash=sha256:6c772d6c0a79ac0f414a9f8947cc407e119b8598de7621f39cacadae3cf57d12 \ + --hash=sha256:6d847b14f7ea89f6ad3c9e3901d1bc4835f6b390a9c71df999b0162d9bb1e20f \ + --hash=sha256:76ffebb907bec09ff511bb3acc077695e2c32bc2142819491579a695f77ffd4d \ + --hash=sha256:7bbff90b63328013e1e8cb50650ae0b9bac54ffb4be6104378490193cd60f85a \ + --hash=sha256:7cb81373984cc0e4682f31bc3d6be9026006d96eecd07ea49aafb06897746452 \ + --hash=sha256:7ee83d3e3a024a9618e5be64648d6d11c37047ac48adff25f12fa4226cf23d1c \ + --hash=sha256:854c33dad5ba0fbd6ab69185fec8dab89e13cda6b7d191ba111987df74f38761 \ + --hash=sha256:85f7912459c67eaab2fb854ed2bc1cc25772b300545fe7ed2dc03954da638649 \ + --hash=sha256:87fdccbb6bb589095f413b1e05734ba492c962b4a45a13ff3408fa44ffe6479b \ + --hash=sha256:88c63a1b55f352b02c6ffd24b15ead9fc0e8bf781dbe070213039324922a2eea \ + --hash=sha256:8a674ac10e0a87b683f4fa2b6fa41090edfd686a6524bd8dedbd6138b309175c \ + --hash=sha256:93130612b837103e15ac3f9cbacb4613f9e348b58b3aad53721d92e57f96d46a \ + --hash=sha256:9744a863b489c79a73aba014df554b0e7a0fc44ef3f8a0ef2a52919c7d155031 \ + --hash=sha256:9749a124280a0ada4187a6cfd1ffd35c350fb3af79c706589d98e088c5044267 \ + --hash=sha256:97f715cf371b16ac88b8c19da00029804e20e25f30d80203417255d239f228b5 \ + --hash=sha256:9bf919756d25e4114ace16a8ce91eb340eb57a08e2c6950c3cebcbe3dff2a5e7 \ + --hash=sha256:9d12cf2851759b8de8ca5fde36a59c08210a97ffca0eb94c532ce7b17c6a3d1d \ + --hash=sha256:9ed4c92a0665002ff8ea852353aeb60d9141eb04109e88928026d3c8a9e5433c \ + --hash=sha256:a72661af47119a80d82fa583b554095308d6a4c356b2a554fdc2799bc19f2a43 \ + --hash=sha256:afde17ae04d90fbe53afb628f7f2d4ca022797aa093e809de5c3cf276f61bbfa \ + --hash=sha256:b336c5e9cf03c7be40c47b5fd694c43c9f1358a80ba384a21969e0b4e66a9b17 \ + --hash=sha256:b663f1e02de5d0573610756398e44c130add0eb9a3fc912a09665332942a2efb \ + --hash=sha256:b83bb06a0192cccf1eb8d0a28672a1b79c74c3a8a5f2619625aeb6f28b3a82bb \ + --hash=sha256:c2415d9d082152460f2bd4e382a1e85aed233abc92db5a3880da2257dc7daf7b \ + --hash=sha256:c83aa123d56f2e060644427a882a36b3c12db93727ad7a7b9efd7d7f3e9cc2c4 \ + --hash=sha256:cfc391f4429ee0a9370aa93d812a52e1fee0f37a81861f4fdd1f4fb28e8547c3 \ + --hash=sha256:db844eb158a87ccab83e868a762ea8024ae27337fc7ddcbfcddd157f841fdfe7 \ + --hash=sha256:defed7ea5f218a9f2336301e6fd379f55c655bea65ba2476346340a0ce6f74a1 \ + --hash=sha256:e16eb9541f3dd1a3e92b89005e37b1257b157b7256df0e36bd7b33b50be73bcb \ + --hash=sha256:e23281b9a08ec338469268f98f194658abfb13658ee98e2b7f85ee9dd06caa91 \ + --hash=sha256:e2d9e1cbc1b25e22000328702b014227737756f4b5bf5c485ac1d8091ada078b \ + --hash=sha256:e48f4234f2469ed012a98f4b7874e7f7e173c167bed4934912a29e03167cf6b1 \ + --hash=sha256:e4c4e92c14a57c9bd4cb4be678c25369bf7a092d55fd0866f759e425b9660806 \ + --hash=sha256:ec1947eabbaf8e0531e8e899fc1d9876c179fc518989461f5d24e2223395a9e3 \ + --hash=sha256:f909bbbc433048b499cb9db9e713b5d8d949e8c109a2a548502fb9aa8630f0b1 + # via -r requirements.in +selenium==3.141.0 \ + --hash=sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c \ + --hash=sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d + # via -r requirements.in +urllib3==1.26.12 \ + --hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \ + --hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997 + # via selenium
diff --git a/docker/precommit_hooks/Dockerfile b/docker/precommit_hooks/Dockerfile index 956c86c..f263390 100644 --- a/docker/precommit_hooks/Dockerfile +++ b/docker/precommit_hooks/Dockerfile
@@ -24,7 +24,8 @@ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ && rm -rf /var/lib/{apt,dpkg,cache,log} -RUN pip3 install "pre-commit<3" "cpplint<2" "yapf<1" "pylint<3" +COPY requirements.txt /opt/requirements.txt +RUN pip3 install --require-hashes --no-deps -r /opt/requirements.txt # === Get GN via CIPD ARG GN_SHA256SUM="af7b2dcb3905bca56655e12131b365f1cba8e159db80d2022330c4f522fab2ef /tmp/gn.zip"
diff --git a/docker/precommit_hooks/requirements.in b/docker/precommit_hooks/requirements.in new file mode 100644 index 0000000..daa21ff --- /dev/null +++ b/docker/precommit_hooks/requirements.in
@@ -0,0 +1,4 @@ +pre-commit<3 +cpplint<2 +yapf<1 +pylint<3
diff --git a/docker/precommit_hooks/requirements.txt b/docker/precommit_hooks/requirements.txt new file mode 100644 index 0000000..cc066e8 --- /dev/null +++ b/docker/precommit_hooks/requirements.txt
@@ -0,0 +1,228 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# pip-compile --allow-unsafe --generate-hashes requirements.in +# +astroid==2.11.7 \ + --hash=sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b \ + --hash=sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946 + # via pylint +cfgv==3.3.1 \ + --hash=sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426 \ + --hash=sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736 + # via pre-commit +cpplint==1.6.1 \ + --hash=sha256:00ddc86d6e4de2a9dcfa272402dcbe21593363a93b7c475bc391e335062f34b1 \ + --hash=sha256:d430ce8f67afc1839340e60daa89e90de08b874bc27149833077bba726dfc13a + # via -r requirements.in +dill==0.3.5.1 \ + --hash=sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302 \ + --hash=sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86 + # via pylint +distlib==0.3.5 \ + --hash=sha256:a7f75737c70be3b25e2bee06288cec4e4c221de18455b2dd037fe2a795cab2fe \ + --hash=sha256:b710088c59f06338ca514800ad795a132da19fda270e3ce4affc74abf955a26c + # via virtualenv +filelock==3.8.0 \ + --hash=sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc \ + --hash=sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4 + # via virtualenv +identify==2.5.3 \ + --hash=sha256:25851c8c1370effb22aaa3c987b30449e9ff0cece408f810ae6ce408fdd20893 \ + --hash=sha256:887e7b91a1be152b0d46bbf072130235a8117392b9f1828446079a816a05ef44 + # via pre-commit +isort==5.10.1 \ + --hash=sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7 \ + --hash=sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951 + # via pylint +lazy-object-proxy==1.7.1 \ + --hash=sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7 \ + --hash=sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a \ + --hash=sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c \ + --hash=sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc \ + --hash=sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f \ + --hash=sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09 \ + --hash=sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442 \ + --hash=sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e \ + --hash=sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029 \ + --hash=sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61 \ + --hash=sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb \ + --hash=sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0 \ + --hash=sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35 \ + --hash=sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42 \ + --hash=sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1 \ + --hash=sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad \ + --hash=sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443 \ + --hash=sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd \ + --hash=sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9 \ + --hash=sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148 \ + --hash=sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38 \ + --hash=sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55 \ + --hash=sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36 \ + --hash=sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a \ + --hash=sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b \ + --hash=sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44 \ + --hash=sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6 \ + --hash=sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69 \ + --hash=sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4 \ + --hash=sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84 \ + --hash=sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de \ + --hash=sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28 \ + --hash=sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c \ + --hash=sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1 \ + --hash=sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8 \ + --hash=sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b \ + --hash=sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb + # via astroid +mccabe==0.7.0 \ + --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ + --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e + # via pylint +nodeenv==1.7.0 \ + --hash=sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e \ + --hash=sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b + # via pre-commit +platformdirs==2.5.2 \ + --hash=sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788 \ + --hash=sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19 + # via + # pylint + # virtualenv +pre-commit==2.20.0 \ + --hash=sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7 \ + --hash=sha256:a978dac7bc9ec0bcee55c18a277d553b0f419d259dadb4b9418ff2d00eb43959 + # via -r requirements.in +pylint==2.14.5 \ + --hash=sha256:487ce2192eee48211269a0e976421f334cf94de1806ca9d0a99449adcdf0285e \ + --hash=sha256:fabe30000de7d07636d2e82c9a518ad5ad7908590fe135ace169b44839c15f90 + # via -r requirements.in +pyyaml==6.0 \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via pre-commit +toml==0.10.2 \ + --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ + --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f + # via pre-commit +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f + # via pylint +tomlkit==0.11.4 \ + --hash=sha256:25d4e2e446c453be6360c67ddfb88838cfc42026322770ba13d1fbd403a93a5c \ + --hash=sha256:3235a9010fae54323e727c3ac06fb720752fe6635b3426e379daec60fbd44a83 + # via pylint +virtualenv==20.16.3 \ + --hash=sha256:4193b7bc8a6cd23e4eb251ac64f29b4398ab2c233531e66e40b19a6b7b0d30c1 \ + --hash=sha256:d86ea0bb50e06252d79e6c241507cb904fcd66090c3271381372d6221a3970f9 + # via pre-commit +wrapt==1.14.1 \ + --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ + --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \ + --hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \ + --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \ + --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \ + --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \ + --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \ + --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \ + --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \ + --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \ + --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \ + --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \ + --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \ + --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \ + --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \ + --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \ + --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \ + --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \ + --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \ + --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \ + --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \ + --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \ + --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \ + --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \ + --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \ + --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \ + --hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \ + --hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \ + --hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \ + --hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \ + --hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \ + --hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \ + --hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \ + --hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \ + --hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \ + --hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \ + --hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \ + --hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \ + --hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \ + --hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \ + --hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \ + --hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \ + --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \ + --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \ + --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \ + --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \ + --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \ + --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \ + --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \ + --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \ + --hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \ + --hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \ + --hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \ + --hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \ + --hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \ + --hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \ + --hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \ + --hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \ + --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \ + --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \ + --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \ + --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \ + --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ + --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af + # via astroid +yapf==0.32.0 \ + --hash=sha256:8fea849025584e486fd06d6ba2bed717f396080fd3cc236ba10cb97c4c51cf32 \ + --hash=sha256:a3f5085d37ef7e3e004c4ba9f9b3e40c54ff1901cd111f05145ae313a7c67d1b + # via -r requirements.in + +# The following packages are considered to be unsafe in a requirements file: +setuptools==65.3.0 \ + --hash=sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82 \ + --hash=sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57 + # via + # astroid + # nodeenv
diff --git a/docker/pytest/Dockerfile b/docker/pytest/Dockerfile index 962201e..d78f0c1 100644 --- a/docker/pytest/Dockerfile +++ b/docker/pytest/Dockerfile
@@ -15,7 +15,7 @@ FROM cobalt-base COPY requirements.txt /opt/requirements.txt -RUN pip3 install -r /opt/requirements.txt +RUN pip3 install --require-hashes --no-deps -r /opt/requirements.txt WORKDIR /code
diff --git a/docker/pytest/requirements.txt b/docker/pytest/requirements.txt index a93c321..bdb88a3 100644 --- a/docker/pytest/requirements.txt +++ b/docker/pytest/requirements.txt
@@ -1,40 +1,130 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.10 # To update, run: # -# pip-compile --output-file=docker/pytest/requirements.txt docker/pytest/requirements.in +# pip-compile --generate-hashes requirements.in # -attrs==21.4.0 +attrs==21.4.0 \ + --hash=sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4 \ + --hash=sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd # via # jsonschema # pytest -certifi==2021.10.8 +certifi==2021.10.8 \ + --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ + --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 # via requests -chardet==4.0.0 +chardet==4.0.0 \ + --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ + --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 # via requests -coverage==6.3.2 - # via -r docker/pytest/requirements.in -idna==2.10 +coverage==6.3.2 \ + --hash=sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9 \ + --hash=sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d \ + --hash=sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf \ + --hash=sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7 \ + --hash=sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6 \ + --hash=sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4 \ + --hash=sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059 \ + --hash=sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39 \ + --hash=sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536 \ + --hash=sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac \ + --hash=sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c \ + --hash=sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903 \ + --hash=sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d \ + --hash=sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05 \ + --hash=sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684 \ + --hash=sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1 \ + --hash=sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f \ + --hash=sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7 \ + --hash=sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca \ + --hash=sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad \ + --hash=sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca \ + --hash=sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d \ + --hash=sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92 \ + --hash=sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4 \ + --hash=sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf \ + --hash=sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6 \ + --hash=sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1 \ + --hash=sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4 \ + --hash=sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359 \ + --hash=sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3 \ + --hash=sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620 \ + --hash=sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512 \ + --hash=sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69 \ + --hash=sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2 \ + --hash=sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518 \ + --hash=sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0 \ + --hash=sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa \ + --hash=sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4 \ + --hash=sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e \ + --hash=sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1 \ + --hash=sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2 + # via -r requirements.in +idna==2.10 \ + --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ + --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 # via requests -iniconfig==1.1.1 +iniconfig==1.1.1 \ + --hash=sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3 \ + --hash=sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32 # via pytest -jsonschema==4.4.0 - # via -r docker/pytest/requirements.in -packaging==21.3 +jsonschema==4.4.0 \ + --hash=sha256:636694eb41b3535ed608fe04129f26542b59ed99808b4f688aa32dcf55317a83 \ + --hash=sha256:77281a1f71684953ee8b3d488371b162419767973789272434bbc3f29d9c8823 + # via -r requirements.in +packaging==21.3 \ + --hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \ + --hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522 # via pytest -pluggy==1.0.0 +pluggy==1.0.0 \ + --hash=sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159 \ + --hash=sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3 # via pytest -py==1.11.0 +py==1.11.0 \ + --hash=sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719 \ + --hash=sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378 # via pytest -pyparsing==3.0.7 +pyparsing==3.0.7 \ + --hash=sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea \ + --hash=sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484 # via packaging -pyrsistent==0.18.1 +pyrsistent==0.18.1 \ + --hash=sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c \ + --hash=sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc \ + --hash=sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e \ + --hash=sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26 \ + --hash=sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec \ + --hash=sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286 \ + --hash=sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045 \ + --hash=sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec \ + --hash=sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8 \ + --hash=sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c \ + --hash=sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca \ + --hash=sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22 \ + --hash=sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a \ + --hash=sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96 \ + --hash=sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc \ + --hash=sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1 \ + --hash=sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07 \ + --hash=sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6 \ + --hash=sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b \ + --hash=sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5 \ + --hash=sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6 # via jsonschema -pytest==7.1.1 - # via -r docker/pytest/requirements.in -requests==2.25.1 - # via -r docker/pytest/requirements.in -tomli==2.0.1 +pytest==7.1.1 \ + --hash=sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63 \ + --hash=sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea + # via -r requirements.in +requests==2.25.1 \ + --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ + --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e + # via -r requirements.in +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f # via pytest -urllib3==1.26.9 +urllib3==1.26.9 \ + --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 \ + --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e # via requests
diff --git a/docker/windows/base/build/Dockerfile b/docker/windows/base/build/Dockerfile index ec4ebaa..19aa9b6 100644 --- a/docker/windows/base/build/Dockerfile +++ b/docker/windows/base/build/Dockerfile
@@ -45,8 +45,9 @@ Copy-Item C:\Python3\python.exe C:\Python3\python3.exe # Install python3 packages via PIP and set various configurations. +COPY ./requirements.txt /requirements.txt RUN mkdir C:\pip-cache;` - python3 -m pip install six --cache-dir C:\pip-cache;` + python3 -m pip install --require-hashes --no-deps -r /requirements.txt --cache-dir C:\pip-cache;` C:\fast-win-rmdir.cmd C:\pip-cache;` # Configure git global settings. git config --global core.autocrlf false;`
diff --git a/docker/windows/base/build/requirements.in b/docker/windows/base/build/requirements.in new file mode 100644 index 0000000..ffe2fce --- /dev/null +++ b/docker/windows/base/build/requirements.in
@@ -0,0 +1 @@ +six
diff --git a/docker/windows/base/build/requirements.txt b/docker/windows/base/build/requirements.txt new file mode 100644 index 0000000..1fc47bb --- /dev/null +++ b/docker/windows/base/build/requirements.txt
@@ -0,0 +1,10 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# pip-compile --generate-hashes requirements.in +# +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via -r requirements.in
diff --git a/starboard/CHANGELOG.md b/starboard/CHANGELOG.md index 99eece6..69ca601 100644 --- a/starboard/CHANGELOG.md +++ b/starboard/CHANGELOG.md
@@ -63,6 +63,15 @@ set `kSbMaxSystemPathCacheDirectorySize` to a larger value in "starboard/<PLATFORM_PATH>/configuration_constants.cc". +### Add nplb tests to enforce performance of SbMediaCanPlayMimeAndKeySystem(). +Add SbMediaCanPlayMimeAndKeySystem.ValidatePerformance to enforce the +performance of SbMediaCanPlayMimeAndKeySystem(). On platforms that fail such +tests, MimeSupportabilityCache and KeySystemSupportabilityCache can be enabled +to improve the performance. The caches store the results of previous queries and +reuse them for repeated queries. Note that if caches are enabled, the platform +need to clear the caches if there's any codec or audio/video output capability +change. + ## Version 13 ### Changed lifecycle events to add support for a concealed state.
diff --git a/starboard/android/apk/apk_sources.gni b/starboard/android/apk/apk_sources.gni index e0378ea..07912f6 100644 --- a/starboard/android/apk/apk_sources.gni +++ b/starboard/android/apk/apk_sources.gni
@@ -21,7 +21,6 @@ "//starboard/android/apk/app/src/main/java/dev/cobalt/account/AccessToken.java", "//starboard/android/apk/app/src/main/java/dev/cobalt/account/NoopUserAuthorizer.java", "//starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizer.java", - "//starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizerImpl.java", "//starboard/android/apk/app/src/main/java/dev/cobalt/coat/AudioPermissionRequester.java", "//starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltA11yHelper.java", "//starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java",
diff --git a/starboard/android/apk/app/src/app/java/dev/cobalt/app/MainActivity.java b/starboard/android/apk/app/src/app/java/dev/cobalt/app/MainActivity.java index dc26a8a..ee4cdee 100644 --- a/starboard/android/apk/app/src/app/java/dev/cobalt/app/MainActivity.java +++ b/starboard/android/apk/app/src/app/java/dev/cobalt/app/MainActivity.java
@@ -16,7 +16,7 @@ import android.app.Activity; import android.app.Service; -import dev.cobalt.account.UserAuthorizerImpl; +import dev.cobalt.account.NoopUserAuthorizer; import dev.cobalt.coat.CobaltActivity; import dev.cobalt.coat.CobaltService; import dev.cobalt.coat.StarboardBridge; @@ -42,8 +42,7 @@ getStarboardBridge().requestStop(0); } }; - UserAuthorizerImpl userAuthorizer = - new UserAuthorizerImpl(getApplicationContext(), activityHolder, stopRequester); + NoopUserAuthorizer userAuthorizer = new NoopUserAuthorizer(); StarboardBridge bridge = new StarboardBridge( getApplicationContext(),
diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/account/NoopUserAuthorizer.java b/starboard/android/apk/app/src/main/java/dev/cobalt/account/NoopUserAuthorizer.java index e995dd2..cf5b7f9 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/account/NoopUserAuthorizer.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/account/NoopUserAuthorizer.java
@@ -18,6 +18,7 @@ import dev.cobalt.util.UsedByNative; /** UserAuthorizer implementation that doesn't try to sign in. */ +@UsedByNative public class NoopUserAuthorizer implements UserAuthorizer { @Override @@ -55,5 +56,4 @@ @Override public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults) {} - }
diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizerImpl.java b/starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizerImpl.java deleted file mode 100644 index 1d96237..0000000 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/account/UserAuthorizerImpl.java +++ /dev/null
@@ -1,537 +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. - -package dev.cobalt.account; - -import static android.Manifest.permission.GET_ACCOUNTS; -import static dev.cobalt.util.Log.TAG; - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.accounts.OnAccountsUpdateListener; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.os.Handler; -import android.os.Looper; -import android.text.TextUtils; -import android.widget.Toast; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; -import com.google.android.gms.auth.GoogleAuthException; -import com.google.android.gms.auth.GoogleAuthUtil; -import com.google.android.gms.auth.UserRecoverableAuthException; -import com.google.android.gms.common.AccountPicker; -import com.google.android.gms.common.AccountPicker.AccountChooserOptions; -import dev.cobalt.coat.R; -import dev.cobalt.util.Holder; -import dev.cobalt.util.Log; -import dev.cobalt.util.UsedByNative; -import java.io.IOException; -import java.util.Arrays; - -/** - * Java side implementation for starboard::android::shared::cobalt::AndroidUserAuthorizer. - * - * This implements the following business logic: - * First run... - * - if there are no accounts, just be be signed-out - * - if there is one account, sign-in without any UI - * - if there are more than one accounts, prompt to choose account - * Subsequent runs... - * - sign-in to the same account last used to sign-in - * - if previously signed-out stay signed-out - * When user clicks 'sign-in' in the UI... - * - if there are no accounts, allow user to add an account - * - if there is one account, sign-in without any UI - * - if there are more than one accounts, prompt to choose account - * If the last signed-in account is deleted... - * - kill the app if stopped in the background to prompt next time it starts - * - at the next app start, show a toast that the account isn't available - * - if there are no accounts left, just be be signed-out - * - if there are one or more accounts left, prompt to choose account - */ -public class UserAuthorizerImpl implements OnAccountsUpdateListener, UserAuthorizer { - - /** Pseudo account indicating the user chose to be signed-out. */ - public static final Account SIGNED_OUT_ACCOUNT = new Account("-", "-"); - - /** Pseudo account indicating a saved account no longer exists. */ - private static final Account MISSING_ACCOUNT = new Account("!", "!"); - - /** Foreshortened expiry of Google OAuth token, which typically lasts 1 hour. */ - private static final long DEFAULT_EXPIRY_SECONDS = 5 * 60; - - private static final String GOOGLE_ACCOUNT_TYPE = "com.google"; - private static final String[] OAUTH_SCOPES = { - "https://www.googleapis.com/auth/youtube" - }; - - private static final String SHARED_PREFS_NAME = "user_auth"; - private static final String ACCOUNT_NAME_PREF_KEY = "signed_in_account"; - - /** The thread on which the current request is running, or null if none. */ - private volatile Thread requestThread; - - private final Context appContext; - private final Holder<Activity> activityHolder; - private final Runnable stopRequester; - private final Handler mainHandler; - - private Account currentAccount = null; - private AccessToken currentToken = null; - - // Result from the account picker UI lands here. - private String chosenAccountName; - - private volatile boolean waitingForPermission; - private volatile boolean permissionGranted; - - public UserAuthorizerImpl( - Context appContext, Holder<Activity> activityHolder, Runnable stopRequester) { - this.appContext = appContext; - this.activityHolder = activityHolder; - this.stopRequester = stopRequester; - this.mainHandler = new Handler(Looper.getMainLooper()); - addOnAccountsUpdatedListener(this); - } - - @Override - public void shutdown() { - removeOnAccountsUpdatedListener(this); - } - - @Override - @SuppressWarnings("unused") - @UsedByNative - public void interrupt() { - Thread t = requestThread; - if (t != null) { - t.interrupt(); - } - } - - @Override - @SuppressWarnings("unused") - @UsedByNative - public AccessToken authorizeUser() { - ensureBackgroundThread(); - requestThread = Thread.currentThread(); - // Let the user choose an account, or add one if there are none to choose. - // However, if there's only one account just choose it without any prompt. - currentAccount = autoSelectOrAddAccount(); - writeAccountPref(currentAccount); - AccessToken accessToken = refreshCurrentToken(); - requestThread = null; - return accessToken; - } - - @Override - @SuppressWarnings("unused") - @UsedByNative - public boolean deauthorizeUser() { - ensureBackgroundThread(); - requestThread = Thread.currentThread(); - currentAccount = SIGNED_OUT_ACCOUNT; - writeAccountPref(currentAccount); - clearCurrentToken(); - requestThread = null; - return true; - } - - @Override - @SuppressWarnings("unused") - @UsedByNative - public AccessToken refreshAuthorization() { - ensureBackgroundThread(); - requestThread = Thread.currentThread(); - - // If we haven't yet determined which account to use, check preferences for a saved account. - if (currentAccount == null) { - Account savedAccount = readAccountPref(); - if (savedAccount == null) { - // No saved account, so this is the first ever run of the app. - currentAccount = autoSelectAccount(); - } else if (savedAccount.equals(MISSING_ACCOUNT)) { - // The saved account got deleted. - currentAccount = forceSelectAccount(); - } else { - // Use the saved account. - currentAccount = savedAccount; - } - writeAccountPref(currentAccount); - } - - AccessToken accessToken = refreshCurrentToken(); - requestThread = null; - return accessToken; - } - - private static void ensureBackgroundThread() { - if (Looper.myLooper() == Looper.getMainLooper()) { - throw new UnsupportedOperationException("UserAuthorizer can't be called on main thread"); - } - } - - private void showToast(int resId, Object... formatArgs) { - final String msg = appContext.getResources().getString(resId, formatArgs); - mainHandler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(appContext, msg, Toast.LENGTH_LONG).show(); - } - }); - } - - private Account readAccountPref() { - String savedAccountName = loadSignedInAccountName(); - if (TextUtils.isEmpty(savedAccountName)) { - return null; - } else if (savedAccountName.equals(SIGNED_OUT_ACCOUNT.name)) { - // Don't request permissions or look for a device account if we were signed-out. - return SIGNED_OUT_ACCOUNT; - } else if (!checkPermission()) { - // We won't be able to get the account without permission, so warn the user and be signed-out. - showToast(R.string.starboard_missing_account, savedAccountName); - return SIGNED_OUT_ACCOUNT; - } else { - // Find the saved account name among all accounts on the device. - for (Account account : getAccounts()) { - if (account.name.equals(savedAccountName)) { - return account; - } - } - showToast(R.string.starboard_missing_account, savedAccountName); - return MISSING_ACCOUNT; - } - } - - private void writeAccountPref(Account account) { - if (account == null) { - return; - } - // Always write the account name, even if it's the signed-out pseudo account. - saveSignedInAccountName(account.name); - } - - private void clearCurrentToken() { - if (currentToken != null) { - clearToken(currentToken.getTokenValue()); - currentToken = null; - } - } - - private AccessToken refreshCurrentToken() { - clearCurrentToken(); - if (currentAccount == null || SIGNED_OUT_ACCOUNT.equals(currentAccount)) { - return null; - } - String tokenValue = getToken(currentAccount); - if (tokenValue == null) { - showToast(R.string.starboard_account_auth_error); - tokenValue = ""; - } - // TODO: Get the token details and use the actual expiry. - long expiry = System.currentTimeMillis() / 1000 + DEFAULT_EXPIRY_SECONDS; - currentToken = new AccessToken(tokenValue, expiry); - return currentToken; - } - - /** - * Prompts the user to select an account, or to add an account if there are none. The prompt is - * skipped if there is exactly one account to choose from. - */ - private Account autoSelectOrAddAccount() { - if (!checkPermission()) { - return SIGNED_OUT_ACCOUNT; - } - Account[] accounts = getAccounts(); - if (accounts.length == 1) { - return accounts[0]; - } - return selectOrAddAccount(); - } - - /** - * Prompts the user to select an account. The prompt is skipped if there are zero or one accounts - * to choose from. - */ - private Account autoSelectAccount() { - if (!checkPermission()) { - return SIGNED_OUT_ACCOUNT; - } - Account[] accounts = getAccounts(); - if (accounts.length == 0) { - return SIGNED_OUT_ACCOUNT; - } else if (accounts.length == 1) { - return accounts[0]; - } - return selectOrAddAccount(); - } - - /** - * Prompts the user to select an account, even if there's only one to choose from. The prompt is - * skipped if there are zero accounts to choose from. - */ - private Account forceSelectAccount() { - // We don't check permissions before calling selectOrAddAccount() because if the account is - // missing, readAccountPref() must have just checked, and we don't want to show permission - // prompt or rationale to the user twice. - Account[] accounts = getAccounts(); - if (accounts.length == 0) { - return SIGNED_OUT_ACCOUNT; - } - return selectOrAddAccount(); - } - - /** - * Prompts the user to select an account, even if there's only one to choose from. If there are - * zero accounts to choose from, the user is prompted to add one. - * - * The caller should ensure permissions are granted before calling this method to avoid showing - * a picker with accounts that we can't access. - */ - private Account selectOrAddAccount() { - String accountName = showAccountPicker(); - // If user cancelled the picker stay signed-out. - if (TextUtils.isEmpty(accountName)) { - return SIGNED_OUT_ACCOUNT; - } - // Get the accounts after the picker in case one was added in the account picker. - for (Account account : getAccounts()) { - if (account.name.equals(accountName)) { - return account; - } - } - // This shouldn't happen, but if it does let the user know we're still signed-out. - Log.e(TAG, "Selected account is missing"); - showToast(R.string.starboard_missing_account, accountName); - return SIGNED_OUT_ACCOUNT; - } - - private synchronized String showAccountPicker() { - Activity activity = activityHolder.get(); - Intent chooseAccountIntent = newChooseAccountIntent(currentAccount); - if (activity == null || chooseAccountIntent == null) { - return ""; - } - chosenAccountName = null; - activity.startActivityForResult(chooseAccountIntent, R.id.rc_choose_account); - - // Block until the account picker activity returns its result. - while (chosenAccountName == null) { - try { - wait(); - } catch (InterruptedException e) { - Log.e(TAG, "Account picker interrupted"); - // Return empty string, as if the picker was cancelled. - return ""; - } - } - return chosenAccountName; - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == R.id.rc_choose_account) { - String accountName = null; - if (resultCode == Activity.RESULT_OK) { - accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); - } else if (resultCode != Activity.RESULT_CANCELED) { - Log.e(TAG, "Account picker error " + resultCode); - showToast(R.string.starboard_account_picker_error); - } - - // Notify showAccountPicker() which account was chosen. - synchronized (this) { - // Return empty string if the picker is cancelled or there's an unexpected result. - chosenAccountName = (accountName == null) ? "" : accountName; - notifyAll(); - } - } - } - - @Override - public void onAccountsUpdated(Account[] unused) { - if (currentAccount == null || SIGNED_OUT_ACCOUNT.equals(currentAccount)) { - // We're not signed-in; the update doesn't affect us. - return; - } - // Call getAccounts() since the param may not match the accounts we can access. - for (Account account : getAccounts()) { - if (account.name.equals(currentAccount.name)) { - // The current account is still there; the update doesn't affect us. - return; - } - } - // The current account is gone; leave the app so we prompt for sign-in next time. - // This should only happen while stopped in the background since we don't delete accounts. - stopRequester.run(); - } - - /** - * Calls framework AccountManager.addOnAccountsUpdatedListener(). - */ - private void addOnAccountsUpdatedListener(OnAccountsUpdateListener listener) { - AccountManager.get(appContext).addOnAccountsUpdatedListener(listener, null, false); - } - - /** - * Calls framework AccountManager.removeOnAccountsUpdatedListener(). - */ - private void removeOnAccountsUpdatedListener(OnAccountsUpdateListener listener) { - AccountManager.get(appContext).removeOnAccountsUpdatedListener(listener); - } - - /** - * Calls framework AccountManager.getAccountsByType() for Google accounts. - */ - private Account[] getAccounts() { - return AccountManager.get(appContext).getAccountsByType(GOOGLE_ACCOUNT_TYPE); - } - - /** - * Calls GMS AccountPicker.newChooseAccountIntent(). - * - * Returns an Intent that when started will always show the account picker even if there's just - * one account on the device. If there are no accounts on the device it shows the UI to add one. - */ - private Intent newChooseAccountIntent(Account defaultAccount) { - AccountChooserOptions chooserOptions = new AccountChooserOptions.Builder() - .setSelectedAccount(defaultAccount) - .setAllowableAccountsTypes(Arrays.asList(GOOGLE_ACCOUNT_TYPE)) - .setAlwaysShowAccountPicker(true) - .build(); - return AccountPicker.newChooseAccountIntent(chooserOptions); - } - - /** - * Calls GMS GoogleAuthUtil.getToken(), without throwing any exceptions. - * - * Returns an empty string if no token is available for the account. - * Returns null if there was an error getting the token. - */ - private String getToken(Account account) { - String joinedScopes = "oauth2:" + TextUtils.join(" ", OAUTH_SCOPES); - try { - return GoogleAuthUtil.getToken(appContext, account, joinedScopes); - } catch (UserRecoverableAuthException e) { - Log.w(TAG, "Recoverable error getting OAuth token", e); - Intent intent = e.getIntent(); - Activity activity = activityHolder.get(); - if (intent != null && activity != null) { - activity.startActivity(intent); - } else { - Log.e(TAG, "Failed to recover OAuth token", e); - } - return null; - - } catch (IOException | GoogleAuthException e) { - Log.e(TAG, "Error getting auth token", e); - return null; - } - } - - /** - * Calls GMS GoogleAuthUtil.clearToken(), without throwing any exceptions. - */ - private void clearToken(String tokenValue) { - try { - GoogleAuthUtil.clearToken(appContext, tokenValue); - } catch (GoogleAuthException | IOException e) { - Log.e(TAG, "Error clearing auth token", e); - } - } - - /** - * Checks whether the app has necessary permissions, asking for them if needed. - * - * This blocks until permissions are granted/declined, and should not be called on the UI thread. - * - * Returns true if permissions are granted. - */ - private synchronized boolean checkPermission() { - if (ContextCompat.checkSelfPermission(appContext, GET_ACCOUNTS) - == PackageManager.PERMISSION_GRANTED) { - return true; - } - - final Activity activity = activityHolder.get(); - if (activity == null) { - return false; - } - - // Check if we have previously been denied permission. - if (ActivityCompat.shouldShowRequestPermissionRationale(activity, GET_ACCOUNTS)) { - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(activity, R.string.starboard_accounts_permission, Toast.LENGTH_LONG) - .show(); - } - }); - return false; - } - - // Request permission. - waitingForPermission = true; - permissionGranted = false; - ActivityCompat.requestPermissions( - activity, new String[]{GET_ACCOUNTS}, R.id.rc_get_accounts_permission); - try { - while (waitingForPermission) { - wait(); - } - } catch (InterruptedException e) { - return false; - } - return permissionGranted; - } - - /** - * Callback pass-thru from the Activity with the result from requesting permissions. - */ - @Override - public void onRequestPermissionsResult( - int requestCode, String[] permissions, int[] grantResults) { - if (requestCode == R.id.rc_get_accounts_permission) { - synchronized (this) { - permissionGranted = grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED; - waitingForPermission = false; - notifyAll(); - } - } - } - - /** - * Remember the name of the signed-in account. - */ - private void saveSignedInAccountName(String accountName) { - getPreferences().edit().putString(ACCOUNT_NAME_PREF_KEY, accountName).commit(); - } - - /** - * Returns the remembered name of the signed-in account. - */ - private String loadSignedInAccountName() { - return getPreferences().getString(ACCOUNT_NAME_PREF_KEY, ""); - } - - private SharedPreferences getPreferences() { - return appContext.getSharedPreferences(SHARED_PREFS_NAME, 0); - } -}
diff --git a/starboard/android/shared/audio_renderer_passthrough.cc b/starboard/android/shared/audio_renderer_passthrough.cc index 7056e8d..b65ca06 100644 --- a/starboard/android/shared/audio_renderer_passthrough.cc +++ b/starboard/android/shared/audio_renderer_passthrough.cc
@@ -435,7 +435,9 @@ // silence can be observed after seeking on some audio receivers. // TODO: Consider reusing audio sink for non-passthrough playbacks, to see if // it reduces latency after seeking. - audio_track_bridge_->PauseAndFlush(); + if (audio_track_bridge_ && audio_track_bridge_->is_valid()) { + audio_track_bridge_->PauseAndFlush(); + } seek_to_time_ = seek_to_time; paused_ = true; if (update_status_and_write_data_token_.is_valid()) {
diff --git a/starboard/android/shared/cobalt/android_user_authorizer.cc b/starboard/android/shared/cobalt/android_user_authorizer.cc index d8eb6c9..9b19e75 100644 --- a/starboard/android/shared/cobalt/android_user_authorizer.cc +++ b/starboard/android/shared/cobalt/android_user_authorizer.cc
@@ -14,6 +14,8 @@ #include "starboard/android/shared/cobalt/android_user_authorizer.h" +#include <memory> + #include "base/time/time.h" #include "starboard/android/shared/jni_env_ext.h" #include "starboard/android/shared/jni_utils.h" @@ -29,6 +31,17 @@ namespace shared { namespace cobalt { +bool UserAuthorizerIsSupported() { + // If using the NoopUserAuthorizer, then user authorizer functionally is not + // supported. + JniEnvExt* env = JniEnvExt::Get(); + jobject local_ref = env->CallStarboardObjectMethodOrAbort( + "getUserAuthorizer", "()Ldev/cobalt/account/UserAuthorizer;"); + return !env->IsInstanceOf( + local_ref, + env->FindClassExtOrAbort("dev/cobalt/account/NoopUserAuthorizer")); +} + AndroidUserAuthorizer::AndroidUserAuthorizer() : shutdown_(false) { JniEnvExt* env = JniEnvExt::Get(); jobject local_ref = env->CallStarboardObjectMethodOrAbort( @@ -71,8 +84,8 @@ "()Z"); } -std::unique_ptr<AccessToken> -AndroidUserAuthorizer::RefreshAuthorization(SbUser user) { +std::unique_ptr<AccessToken> AndroidUserAuthorizer::RefreshAuthorization( + SbUser user) { SB_DCHECK(user == &::starboard::shared::nouser::g_user); if (shutdown_) { DLOG(WARNING) << "No-op RefreshAuthorization after shutdown"; @@ -85,8 +98,8 @@ return CreateAccessToken(j_token.Get()); } -std::unique_ptr<AccessToken> -AndroidUserAuthorizer::CreateAccessToken(jobject j_token) { +std::unique_ptr<AccessToken> AndroidUserAuthorizer::CreateAccessToken( + jobject j_token) { if (!j_token) { return std::unique_ptr<AccessToken>(); } @@ -101,8 +114,8 @@ env->GetStringStandardUTFOrAbort(j_token_string.Get()); } - jlong j_expiry = env->CallLongMethodOrAbort( - j_token, "getExpirySeconds", "()J"); + jlong j_expiry = + env->CallLongMethodOrAbort(j_token, "getExpirySeconds", "()J"); if (j_expiry > 0) { access_token->expiry = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(j_expiry); @@ -120,7 +133,10 @@ namespace account { UserAuthorizer* UserAuthorizer::Create() { - return new ::starboard::android::shared::cobalt::AndroidUserAuthorizer(); + if (::starboard::android::shared::cobalt::UserAuthorizerIsSupported()) { + return new ::starboard::android::shared::cobalt::AndroidUserAuthorizer(); + } + return nullptr; } } // namespace account
diff --git a/starboard/audio_sink.h b/starboard/audio_sink.h index 7d6c794..a3b9b14 100644 --- a/starboard/audio_sink.h +++ b/starboard/audio_sink.h
@@ -117,7 +117,6 @@ // |context|: A value that is passed back to all callbacks and is generally // used to point at a class or struct that contains state associated with the // audio sink. - SB_EXPORT SbAudioSink SbAudioSinkCreate(int channels, int sampling_frequency_hz,
diff --git a/starboard/common/ref_counted.h b/starboard/common/ref_counted.h index cd94aa1..4c3c8c3 100644 --- a/starboard/common/ref_counted.h +++ b/starboard/common/ref_counted.h
@@ -6,6 +6,7 @@ #define STARBOARD_COMMON_REF_COUNTED_H_ #include <algorithm> +#include <utility> #include "starboard/atomic.h" #include "starboard/common/log.h" @@ -148,7 +149,8 @@ : public starboard::RefCountedThreadSafe<starboard::RefCountedData<T> > { public: RefCountedData() : data() {} - RefCountedData(const T& in_value) : data(in_value) {} + RefCountedData(const T& in_value) : data(in_value) {} // NOLINT + RefCountedData(T&& in_value) : data(std::move(in_value)) {} // NOLINT T data; @@ -212,7 +214,7 @@ scoped_refptr() : ptr_(NULL) {} - scoped_refptr(T* p) : ptr_(p) { + scoped_refptr(T* p) : ptr_(p) { // NOLINT if (ptr_) ptr_->AddRef(); } @@ -222,6 +224,20 @@ ptr_->AddRef(); } + // Move constructor. This is required in addition to the move conversion + // constructor below. + scoped_refptr(scoped_refptr<T>&& r) noexcept : ptr_(r.ptr_) { + r.ptr_ = nullptr; + } + + // Move conversion constructor. + template <typename U, + typename = typename std::enable_if< + std::is_convertible<U*, T*>::value>::type> + scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.get()) { + r.ptr_ = nullptr; + } + template <typename U> scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { if (ptr_) @@ -275,6 +291,11 @@ protected: T* ptr_; + + private: + // Friend required for move constructors that set r.ptr_ to null. + template <typename U> + friend class scoped_refptr; }; // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
diff --git a/third_party/crashpad/wrapper/proto/BUILD.gn b/third_party/crashpad/wrapper/proto/BUILD.gn new file mode 100644 index 0000000..4819e31 --- /dev/null +++ b/third_party/crashpad/wrapper/proto/BUILD.gn
@@ -0,0 +1,20 @@ +# 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. + +import("//third_party/protobuf/proto_library.gni") + +proto_library("crashpad_annotations_proto") { + sources = [ "crashpad_annotations.proto" ] + generate_python = false +}
diff --git a/third_party/crashpad/wrapper/proto/crashpad_annotations.proto b/third_party/crashpad/wrapper/proto/crashpad_annotations.proto new file mode 100644 index 0000000..eb739bc --- /dev/null +++ b/third_party/crashpad/wrapper/proto/crashpad_annotations.proto
@@ -0,0 +1,36 @@ +// 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. + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +package crashpad.wrapper; + +// Annotations that can be shared between Cobalt and Crashpad handler processes. +// Next id: 5 +message CrashpadAnnotations { + // The product name. + string product = 1; + + // The product version. + string version = 2; + + // The User-Agent string that identifies brand, model, etc. + string user_agent_string = 3; + + // Annotations with keys that are unknown at compile time. + map<string, string> runtime_annotations = 4; +} +
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore deleted file mode 100644 index 1294fe2..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore +++ /dev/null
@@ -1,3 +0,0 @@ -out -node_modules -package-lock.json
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore deleted file mode 100644 index 5ff3c19..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore +++ /dev/null
@@ -1,9 +0,0 @@ -.vscode/** -.vscode-test/** -out/test/** -test/** -src/** -**/*.map -.gitignore -tsconfig.json -vsc-extension-quickstart.md
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE deleted file mode 100644 index c558158..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE +++ /dev/null
@@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 The LLVM Developers - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE.
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/README.md b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/README.md deleted file mode 100644 index f950cb6..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/README.md +++ /dev/null
@@ -1,76 +0,0 @@ -# vscode-clangd - -Provides C/C++ language IDE features for VS Code using [clangd](https://clang.llvm.org/extra/clangd.html). - -## Usage - -`vscode-clangd` provides the features designated by the [Language Server -Protocol](https://github.com/Microsoft/language-server-protocol), such as -code completion, code formatting and goto definition. - -**Note**: `clangd` is under heavy development, not all LSP features are -implemented. See [Current Status](https://clang.llvm.org/extra/clangd.html#current-status) -for details. - -To use `vscode-clangd` extension in VS Code, you need to install `vscode-clangd` -from VS Code extension marketplace. - -`vscode-clangd` will attempt to find the `clangd` binary on your `PATH`. -Alternatively, the `clangd` executable can be specified in your VS Code -`settings.json` file: - -```json -{ - "clangd.path": "/absolute/path/to/clangd" -} -``` - -To obtain `clangd` binary, please see the [installing Clangd](https://clang.llvm.org/extra/clangd.html#installing-clangd). - -## Development - -A guide of developing `vscode-clangd` extension. - -### Requirements - -* VS Code -* node.js and npm - -### Steps - -1. Make sure you disable the installed `vscode-clangd` extension in VS Code. -2. Make sure you have clangd in /usr/bin/clangd or edit src/extension.ts to -point to the binary. -3. In order to start a development instance of VS code extended with this, run: - -```bash - $ cd /path/to/clang-tools-extra/clangd/clients/clangd-vscode/ - $ npm install - $ code . - # When VS Code starts, press <F5>. -``` - -## Publish to VS Code Marketplace - -New changes to `clangd-vscode` are not released until a new version is published -to the marketplace. - -### Requirements - -* Make sure install the `vsce` command (`npm install -g vsce`) -* `llvm-vs-code-extensions` account -* Bump the version in `package.json`, and commit the change to upstream - -The extension is published under `llvm-vs-code-extensions` account, which is -currently maintained by clangd developers. If you want to make a new release, -please contact cfe-dev@lists.llvm.org. - -### Steps - -```bash - $ cd /path/to/clang-tools-extra/clangd/clients/clangd-vscode/ - # For the first time, you need to login in the account. vsce will ask you for - the Personal Access Token, and remember it for future commands. - $ vsce login llvm-vs-code-extensions - $ vsce publish -```
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/package.json b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/package.json deleted file mode 100644 index eeb5112..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/package.json +++ /dev/null
@@ -1,79 +0,0 @@ -{ - "name": "vscode-clangd", - "displayName": "vscode-clangd", - "description": "Clang Language Server", - "version": "0.0.6", - "publisher": "llvm-vs-code-extensions", - "homepage": "https://clang.llvm.org/extra/clangd.html", - "engines": { - "vscode": "^1.18.0" - }, - "categories": [ - "Programming Languages", - "Linters", - "Snippets" - ], - "keywords": [ - "C", - "C++", - "LSP", - "Clangd", - "LLVM" - ], - "activationEvents": [ - "onLanguage:cpp", - "onLanguage:c" - ], - "main": "./out/src/extension", - "scripts": { - "vscode:prepublish": "tsc -p ./", - "compile": "tsc -watch -p ./", - "postinstall": "node ./node_modules/vscode/bin/install", - "test": "node ./node_modules/vscode/bin/test" - }, - "dependencies": { - "vscode-languageclient": "^4.0.0", - "vscode-languageserver": "^4.0.0" - }, - "devDependencies": { - "typescript": "^2.0.3", - "vscode": "^1.1.0", - "mocha": "^2.3.3", - "@types/node": "^6.0.40", - "@types/mocha": "^2.2.32" - }, - "repository": { - "type": "svn", - "url": "http://llvm.org/svn/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/" - }, - "contributes": { - "configuration": { - "type": "object", - "title": "clangd configuration", - "properties": { - "clangd.path": { - "type": "string", - "default": "clangd", - "description": "The path to clangd executable, e.g.: /usr/bin/clangd" - }, - "clangd.arguments": { - "type": "array", - "default": [], - "items": { - "type": "string" - }, - "description": "Arguments for clangd server" - }, - "clangd.syncFileEvents": { - "type": "boolean", - "default": true, - "description": "Whether or not to send file events to clangd (File created, changed or deleted). This can be disabled for performance consideration." - }, - "clangd.trace": { - "type": "string", - "description": "Names a file that clangd should log a performance trace to, in chrome trace-viewer JSON format." - } - } - } - } -}
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts deleted file mode 100644 index a126a19..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts +++ /dev/null
@@ -1,58 +0,0 @@ -import * as vscode from 'vscode'; -import * as vscodelc from 'vscode-languageclient'; -import { realpathSync } from 'fs'; - -/** - * Method to get workspace configuration option - * @param option name of the option (e.g. for clangd.path should be path) - * @param defaultValue default value to return if option is not set - */ -function getConfig<T>(option: string, defaultValue?: any): T { - const config = vscode.workspace.getConfiguration('clangd'); - return config.get<T>(option, defaultValue); -} - -/** - * this method is called when your extension is activate - * your extension is activated the very first time the command is executed - */ -export function activate(context: vscode.ExtensionContext) { - const syncFileEvents = getConfig<boolean>('syncFileEvents', true); - - const clangd: vscodelc.Executable = { - command: getConfig<string>('path'), - args: getConfig<string[]>('arguments') - }; - const traceFile = getConfig<string>('trace'); - if (!!traceFile) { - const trace = { CLANGD_TRACE: traceFile }; - clangd.options = { env: { ...process.env, ...trace } }; - } - const serverOptions: vscodelc.ServerOptions = clangd; - - const filePattern: string = '**/*.{' + - ['cpp', 'c', 'cc', 'cxx', 'c++', 'm', 'mm', 'h', 'hh', 'hpp', 'hxx', 'inc'].join() + '}'; - const clientOptions: vscodelc.LanguageClientOptions = { - // Register the server for C/C++ files - documentSelector: [{ scheme: 'file', pattern: filePattern }], - synchronize: !syncFileEvents ? undefined : { - fileEvents: vscode.workspace.createFileSystemWatcher(filePattern) - }, - // Resolve symlinks for all files provided by clangd. - // This is a workaround for a bazel + clangd issue - bazel produces a symlink tree to build in, - // and when navigating to the included file, clangd passes its path inside the symlink tree - // rather than its filesystem path. - // FIXME: remove this once clangd knows enough about bazel to resolve the - // symlinks where needed (or if this causes problems for other workflows). - uriConverters: { - code2Protocol: (value: vscode.Uri) => value.toString(), - protocol2Code: (value: string) => - vscode.Uri.file(realpathSync(vscode.Uri.parse(value).fsPath)) - } - }; - - const clangdClient = new vscodelc.LanguageClient('Clang Language Server', serverOptions, clientOptions); - console.log('Clang Language Server is now active!'); - - const disposable = clangdClient.start(); -}
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts deleted file mode 100644 index de4e068..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts +++ /dev/null
@@ -1,15 +0,0 @@ -/** The module 'assert' provides assertion methods from node */ -import * as assert from 'assert'; - -import * as vscode from 'vscode'; -import * as myExtension from '../src/extension'; - -// TODO: add tests -suite("Extension Tests", () => { - - // Defines a Mocha unit test - test("Something 1", () => { - assert.equal(-1, [1, 2, 3].indexOf(5)); - assert.equal(-1, [1, 2, 3].indexOf(0)); - }); -}); \ No newline at end of file
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts deleted file mode 100644 index 50bae45..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts +++ /dev/null
@@ -1,22 +0,0 @@ -// -// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING -// -// This file is providing the test runner to use when running extension tests. -// By default the test runner in use is Mocha based. -// -// You can provide your own test runner if you want to override it by exporting -// a function run(testRoot: string, clb: (error:Error) => void) that the extension -// host can call to run the tests. The test runner is expected to use console.log -// to report the results back to the caller. When the tests are finished, return -// a possible error to the callback or null if none. - -var testRunner = require('vscode/lib/testrunner'); - -// You can directly control Mocha options by uncommenting the following lines -// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info -testRunner.configure({ - ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) - useColors: true // colored output from test results -}); - -module.exports = testRunner; \ No newline at end of file
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json deleted file mode 100644 index 0b05f30..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json +++ /dev/null
@@ -1,29 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6", - "es2015.core", - "es2015.collection", - "es2015.generator", - "es2015.iterable", - "es2015.promise", - "es2015.symbol", - "es2016.array.include" - ], - "sourceMap": true, - "rootDir": ".", - "alwaysStrict": true, - "noEmitOnError": true, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "noImplicitThis": true - }, - "exclude": [ - "node_modules", - ".vscode-test" - ] -} \ No newline at end of file
diff --git a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/vsc-extension-quickstart.md b/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/vsc-extension-quickstart.md deleted file mode 100644 index 24675ec..0000000 --- a/third_party/llvm-project/clang-tools-extra/clangd/clients/clangd-vscode/vsc-extension-quickstart.md +++ /dev/null
@@ -1,33 +0,0 @@ -# Toy VS Code Extension for clangd - -## What's in the folder -* This folder contains all of the files necessary for your extension -* `package.json` - this is the manifest file in which you declare your extension and command. -The sample plugin registers a command and defines its title and command name. With this information -VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. -* `src/extension.ts` - this is the main file where you will provide the implementation of your command. -The file exports one function, `activate`, which is called the very first time your extension is -activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. -We pass the function containing the implementation of the command as the second parameter to -`registerCommand`. - -## Get up and running straight away -* press `F5` to open a new window with your extension loaded -* run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World` -* set breakpoints in your code inside `src/extension.ts` to debug your extension -* find output from your extension in the debug console - -## Make changes -* you can relaunch the extension from the debug toolbar after changing code in `src/extension.ts` -* you can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes - -## Explore the API -* you can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts` - -## Run tests -* open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Launch Tests` -* press `F5` to run the tests in a new window with your extension loaded -* see the output of the test result in the debug console -* make changes to `test/extension.test.ts` or create new test files inside the `test` folder - * by convention, the test runner will only consider files matching the name pattern `**.test.ts` - * you can create folders inside the `test` folder to structure your tests any way you want \ No newline at end of file