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