Import Cobalt 23.lts.1.309136
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/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/black_box_tests.py b/cobalt/black_box_tests/black_box_tests.py
index 14b8bc6..7ac37d0 100644
--- a/cobalt/black_box_tests/black_box_tests.py
+++ b/cobalt/black_box_tests/black_box_tests.py
@@ -69,7 +69,6 @@
'persistent_cookie',
'soft_mic_platform_service_test',
'text_encoding_test',
- 'web_crypto_api_test',
'web_debugger',
'web_platform_tests',
'web_worker_test',
diff --git a/cobalt/black_box_tests/testdata/web_crypto_api_test.html b/cobalt/black_box_tests/testdata/web_crypto_api_test.html
deleted file mode 100644
index 18feadf..0000000
--- a/cobalt/black_box_tests/testdata/web_crypto_api_test.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-<!--
- 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.
--->
-
-<html>
-
-<head>
- <title>Cobalt WebCryptoAPI Worker Test</title>
- <script src='black_box_js_test_utils.js'></script>
-</head>
-
-<body>
- <script>
- const tests = [
- 'crypto_defined',
- 'subtle_encrypt_decrypt',
- 'subtle_importKey_verify_sign',
- 'getRandomValues',
- ];
- let pending = tests.length;
- const worker = new Worker('web_crypto_api_test.js');
- worker.onmessage = event => {
- assertEqual('pass', event.data);
- pending--;
- if (pending === 0) {
- onEndTest();
- }
- };
- tests.map(test => worker.postMessage(test));
- setupFinished();
- window.setTimeout(notReached, 3000);
- </script>
-</body>
-</html>
diff --git a/cobalt/black_box_tests/testdata/web_crypto_api_test.js b/cobalt/black_box_tests/testdata/web_crypto_api_test.js
deleted file mode 100644
index 9d653b1..0000000
--- a/cobalt/black_box_tests/testdata/web_crypto_api_test.js
+++ /dev/null
@@ -1,392 +0,0 @@
-// Copyright 2022 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Tests borrowed from Web Platform Tests.
-// TODO(b/237798928): remove these tests and enable web platform tests. This
-// requires supporting sending/receiving objects using
-// |postMessage()|.
-
-const getHmacImportedTestVectors = (() => {
- const plaintext = new Uint8Array([95, 77, 186, 79, 50, 12, 12, 232, 118, 114, 90, 252, 229, 251, 210, 91, 248, 62, 90, 113, 37, 160, 140, 175, 231, 60, 62, 186, 196, 33, 119, 157, 249, 213, 93, 24, 12, 58, 233, 148, 38, 69, 225, 216, 47, 238, 140, 157, 41, 75, 60, 177, 160, 138, 153, 49, 32, 27, 60, 14, 129, 252, 71, 202, 207, 131, 21, 162, 175, 102, 50, 65, 19, 195, 182, 98, 48, 195, 70, 8, 196, 244, 89, 54, 52, 206, 2, 178, 103, 54, 34, 119, 240, 168, 64, 202, 116, 188, 61, 26, 98, 54, 149, 44, 94, 215, 170, 248, 168, 254, 203, 221, 250, 117, 132, 230, 151, 140, 234, 93, 42, 91, 159, 183, 241, 180, 140, 139, 11, 229, 138, 48, 82, 2, 117, 77, 131, 118, 16, 115, 116, 121, 60, 240, 38, 170, 238, 83, 0, 114, 125, 131, 108, 215, 30, 113, 179, 69, 221, 178, 228, 68, 70, 255, 197, 185, 1, 99, 84, 19, 137, 13, 145, 14, 163, 128, 152, 74, 144, 25, 16, 49, 50, 63, 22, 219, 204, 157, 107, 225, 104, 184, 72, 133, 56, 76, 160, 62, 18, 96, 10, 193, 194, 72, 2, 138, 243, 114, 108, 201, 52, 99, 136, 46, 168, 192, 42, 171]);
- const raw = {
- 'SHA-1': new Uint8Array([71, 162, 7, 70, 209, 113, 121, 219, 101, 224, 167, 157, 237, 255, 199, 253, 241, 129, 8, 27]),
- 'SHA-256': new Uint8Array([229, 136, 236, 8, 17, 70, 61, 118, 114, 65, 223, 16, 116, 180, 122, 228, 7, 27, 81, 242, 206, 54, 83, 123, 166, 156, 205, 195, 253, 194, 183, 168]),
- 'SHA-384': new Uint8Array([107, 29, 162, 142, 171, 31, 88, 42, 217, 113, 142, 255, 224, 94, 35, 213, 253, 44, 152, 119, 162, 217, 68, 63, 144, 190, 192, 147, 190, 206, 46, 167, 210, 53, 76, 208, 189, 197, 225, 71, 210, 233, 0, 147, 115, 73, 68, 136]),
- 'SHA-512': new Uint8Array([93, 204, 53, 148, 67, 170, 246, 82, 250, 19, 117, 214, 179, 230, 31, 220, 242, 155, 180, 162, 139, 213, 211, 220, 250, 64, 248, 47, 144, 107, 178, 128, 4, 85, 219, 3, 181, 211, 31, 185, 114, 161, 90, 109, 1, 3, 162, 78, 86, 209, 86, 161, 25, 192, 229, 161, 233, 42, 68, 195, 197, 101, 124, 249])
- };
- const signatures = {
- 'SHA-1': new Uint8Array([5, 51, 144, 42, 153, 248, 82, 78, 229, 10, 240, 29, 56, 222, 220, 225, 51, 217, 140, 160]),
- 'SHA-256': new Uint8Array([133, 164, 12, 234, 46, 7, 140, 40, 39, 163, 149, 63, 251, 102, 194, 123, 41, 26, 71, 43, 13, 112, 160, 0, 11, 69, 216, 35, 128, 62, 235, 84]),
- 'SHA-384': new Uint8Array([33, 124, 61, 80, 240, 186, 154, 109, 110, 174, 30, 253, 215, 165, 24, 254, 46, 56, 128, 181, 130, 164, 13, 6, 30, 144, 153, 193, 224, 38, 239, 88, 130, 84, 139, 93, 92, 236, 221, 85, 152, 217, 155, 107, 111, 48, 87, 255]),
- 'SHA-512': new Uint8Array([97, 251, 39, 140, 63, 251, 12, 206, 43, 241, 207, 114, 61, 223, 216, 239, 31, 147, 28, 12, 97, 140, 37, 144, 115, 36, 96, 89, 57, 227, 249, 162, 198, 244, 175, 105, 11, 218, 52, 7, 220, 47, 87, 112, 246, 160, 164, 75, 149, 77, 100, 163, 50, 227, 238, 8, 33, 171, 248, 43, 127, 62, 153, 193])
- };
- return key_usage => Object.keys(raw).map(hash =>
- crypto.subtle.importKey(
- 'raw',
- raw[hash],
- {name: 'HMAC', hash},
- false,
- key_usage,
- ).then(key => ({
- name: `HMAC with ${hash}`,
- algorithm: {name: 'HMAC', hash},
- key,
- plaintext,
- signature: signatures[hash],
- })));
-})();
-
-const copyBuffer = sourceBuffer => {
- const source = new Uint8Array(sourceBuffer);
- const copy = new Uint8Array(sourceBuffer.byteLength)
- for (let i = 0; i < source.byteLength; i++) {
- copy[i] = source[i];
- }
- return copy;
-};
-
-const copyAndAlterBuffer = buffer => {
- const copy = copyBuffer(buffer);
- copy[0] = 255 - copy[0];
- return copy;
-};
-
-const runSubtleImportKeyVerifySignTests = () => {
- const test_cases = [
- {test_name: 'verification'},
- {
- test_name: 'verification with altered signature after call',
- modify_vector: v => {
- v.signature = copyBuffer(v.signature);
- return v;
- },
- },
- {
- test_name: 'with altered plaintext after call',
- modify_vector: v => {
- v.plaintext = copyBuffer(v.plaintext);
- return v;
- },
- },
- {
- test_name: 'no verify usage',
- key_usage: ['sign'],
- expected_is_verified: null,
- expected_err: err => err.name === 'InvalidAccessError',
- },
- {
- test_name: 'round trip',
- sign: true,
- },
- {
- test_name: 'verification failure due to wrong plaintext',
- modify_vector: v => {
- v.plaintext = copyAndAlterBuffer(v.plaintext);
- return v;
- },
- expected_is_verified: false,
- },
- {
- test_name: 'verification failure due to wrong signature',
- modify_vector: v => {
- v.signature = copyAndAlterBuffer(v.signature);
- return v;
- },
- expected_is_verified: false,
- },
- {
- test_name: 'verification failure due to wrong signature length',
- modify_vector: v => {
- v.signature = v.signature.slice(1);
- return v;
- },
- expected_is_verified: false,
- },
- ];
- return Promise.all(test_cases.flatMap(({
- key_usage=['verify', 'sign'],
- modify_vector=(v => v),
- sign=false,
- expected_is_verified=true,
- expected_err=(err => false),
- test_name,
- }) =>
- getHmacImportedTestVectors(key_usage).map(promise_vector =>
- promise_vector
- .then(modify_vector)
- .then(vector =>
- (sign ? crypto.subtle.sign(vector.algorithm, vector.key, vector.plaintext) : Promise.resolve(vector.signature))
- .then(signature => crypto.subtle.verify(vector.algorithm, vector.key, signature, vector.plaintext))
- .then(is_verified => [is_verified === expected_is_verified, 'is_verified'])
- .catch(err => [expected_err(err), 'error for test ' + vector.name + ': ' + err.message + '\''])
- .then(result => [result[0], vector.name + ' ' + test_name + ': ' + result[1]]))
- .catch(err => [false, test_name + ': importVectorKeys failed'])
- )));
-};
-
-const runGetRandomValuesTests = () =>
- Promise.resolve([
- Int8Array,
- Int16Array,
- Int32Array,
- Uint8Array,
- Uint8ClampedArray,
- Uint16Array,
- Uint32Array,
- ].map(ctor => [crypto.getRandomValues(new ctor(8)).constructor === ctor, `${ctor.name} mismatch`]));
-
-const getAesCtrImportedTestVectors = (() => {
- const plaintext = new Uint8Array([84, 104, 105, 115, 32, 115,
- 112, 101, 99, 105, 102, 105, 99, 97, 116, 105, 111, 110,
- 32, 100, 101, 115, 99, 114, 105, 98, 101, 115, 32, 97, 32,
- 74, 97, 118, 97, 83, 99, 114, 105, 112, 116, 32, 65, 80,
- 73, 32, 102, 111, 114, 32, 112, 101, 114, 102, 111, 114,
- 109, 105, 110, 103, 32, 98, 97, 115, 105, 99, 32, 99, 114,
- 121, 112, 116, 111, 103, 114, 97, 112, 104, 105, 99, 32,
- 111, 112, 101, 114, 97, 116, 105, 111, 110, 115, 32, 105,
- 110, 32, 119, 101, 98, 32, 97, 112, 112, 108, 105, 99, 97,
- 116, 105, 111, 110, 115, 44, 32, 115, 117, 99, 104, 32, 97,
- 115, 32, 104, 97, 115, 104, 105, 110, 103, 44, 32, 115,
- 105, 103, 110, 97, 116, 117, 114, 101, 32, 103, 101, 110,
- 101, 114, 97, 116, 105, 111, 110, 32, 97, 110, 100, 32,
- 118, 101, 114, 105, 102, 105, 99, 97, 116, 105, 111, 110,
- 44, 32, 97, 110, 100, 32, 101, 110, 99, 114, 121, 112,
- 116, 105, 111, 110, 32, 97, 110, 100, 32, 100, 101, 99,
- 114, 121, 112, 116, 105, 111, 110, 46, 32, 65, 100, 100,
- 105, 116, 105, 111, 110, 97, 108, 108, 121, 44, 32, 105,
- 116, 32, 100, 101, 115, 99, 114, 105, 98, 101, 115, 32, 97,
- 110, 32, 65, 80, 73, 32, 102, 111, 114, 32, 97, 112, 112,
- 108, 105, 99, 97, 116, 105, 111, 110, 115, 32, 116, 111,
- 32, 103, 101, 110, 101, 114, 97, 116, 101, 32, 97, 110,
- 100, 47, 111, 114, 32, 109, 97, 110, 97, 103, 101, 32, 116,
- 104, 101, 32, 107, 101, 121, 105, 110, 103, 32, 109, 97,
- 116, 101, 114, 105, 97, 108, 32, 110, 101, 99, 101, 115,
- 115, 97, 114, 121, 32, 116, 111, 32, 112, 101, 114, 102,
- 111, 114, 109, 32, 116, 104, 101, 115, 101, 32, 111, 112,
- 101, 114, 97, 116, 105, 111, 110, 115, 46, 32, 85, 115,
- 101, 115, 32, 102, 111, 114, 32, 116, 104, 105, 115, 32,
- 65, 80, 73, 32, 114, 97, 110, 103, 101, 32, 102, 114, 111,
- 109, 32, 117, 115, 101, 114, 32, 111, 114, 32, 115, 101,
- 114, 118, 105, 99, 101, 32, 97, 117, 116, 104, 101, 110,
- 116, 105, 99, 97, 116, 105, 111, 110, 44, 32, 100, 111,
- 99, 117, 109, 101, 110, 116, 32, 111, 114, 32, 99, 111,
- 100, 101, 32, 115, 105, 103, 110, 105, 110, 103, 44, 32,
- 97, 110, 100, 32, 116, 104, 101, 32, 99, 111, 110, 102,
- 105, 100, 101, 110, 116, 105, 97, 108, 105, 116, 121, 32,
- 97, 110, 100, 32, 105, 110, 116, 101, 103, 114, 105, 116,
- 121, 32, 111, 102, 32, 99, 111, 109, 109, 117, 110, 105,
- 99, 97, 116, 105, 111, 110, 115, 46]);
-
- // We want some random key bytes of various sizes.
- // These were randomly generated from a script.
- const keyBytes = {
- 128: new Uint8Array([222, 192, 212, 252, 191, 60, 71,
- 65, 200, 146, 218, 189, 28, 212, 192, 78]),
- 192: new Uint8Array([208, 238, 131, 65, 63, 68, 196, 63, 186, 208,
- 61, 207, 166, 18, 99, 152, 29, 109, 221, 95, 240, 30, 28, 246]),
- 256: new Uint8Array([103, 105, 56, 35, 251, 29, 88, 7, 63, 145, 236,
- 233, 204, 58, 249, 16, 229, 83, 38, 22, 164, 210, 123, 19, 235, 123, 116,
- 216, 0, 11, 191, 48])
- };
-
- // AES-CTR needs a 16 byte (128 bit) counter.
- const counter = new Uint8Array([85, 170, 248, 155, 168, 148, 19, 213, 78, 167, 39,
- 167, 108, 39, 162, 132]);
-
- // Results. These were created using the Python cryptography module.
-
- // AES-CTR produces ciphertext
- const ciphertext = {
- 128: new Uint8Array([233, 17, 117, 253, 164, 245, 234, 87, 197, 43, 13, 0, 11, 190, 152, 175, 104, 192, 165, 144, 88, 174, 237, 138, 181, 183, 6, 53, 3, 161, 206, 71, 13, 121, 218, 209, 116, 249, 10, 170, 250, 165, 68, 157, 132, 141, 200, 178, 197, 87, 209, 231, 250, 75, 154, 65, 162, 251, 30, 159, 234, 20, 20, 181, 147, 218, 180, 12, 4, 241, 75, 79, 129, 64, 15, 228, 60, 147, 153, 1, 129, 176, 150, 161, 85, 97, 22, 154, 234, 23, 127, 16, 4, 22, 226, 11, 104, 16, 176, 14, 225, 176, 79, 239, 103, 243, 190, 222, 40, 186, 244, 212, 29, 57, 125, 175, 21, 17, 233, 2, 13, 119, 102, 233, 230, 4, 16, 222, 56, 225, 67, 45, 191, 250, 15, 153, 45, 193, 240, 212, 117, 101, 68, 232, 199, 101, 175, 125, 247, 6, 249, 14, 0, 157, 185, 56, 76, 51, 228, 77, 234, 84, 60, 42, 119, 187, 213, 32, 34, 222, 65, 231, 215, 26, 73, 141, 231, 254, 185, 118, 14, 180, 126, 80, 51, 102, 200, 141, 204, 45, 26, 56, 119, 136, 222, 45, 143, 120, 231, 44, 43, 221, 136, 21, 188, 138, 84, 232, 208, 238, 226, 117, 104, 60, 165, 4, 18, 144, 240, 49, 173, 90, 68, 84, 239, 161, 124, 196, 144, 119, 24, 243, 239, 75, 117, 254, 219, 209, 53, 131, 37, 79, 68, 26, 21, 168, 163, 50, 59, 18, 244, 11, 143, 190, 188, 129, 108, 249, 180, 104, 216, 215, 165, 160, 251, 84, 132, 152, 195, 154, 110, 216, 70, 21, 248, 148, 146, 152, 56, 174, 248, 227, 1, 102, 15, 118, 182, 50, 73, 63, 35, 112, 159, 237, 253, 94, 16, 127, 120, 38, 127, 51, 27, 96, 163, 140, 20, 111, 151, 16, 72, 74, 74, 205, 239, 241, 16, 179, 183, 116, 95, 248, 58, 168, 203, 93, 233, 225, 91, 17, 226, 10, 120, 85, 114, 4, 31, 40, 82, 161, 152, 17, 86, 237, 207, 7, 228, 110, 182, 65, 68, 68, 156, 206, 116, 185, 204, 148, 22, 58, 111, 218, 138, 225, 146, 25, 114, 29, 96, 183, 87, 181, 181, 236, 113, 141, 171, 213, 9, 84, 182, 230, 163, 147, 246, 86, 246, 52, 111, 64, 34, 157, 12, 80, 224, 28, 21, 112, 31, 42, 79, 229, 210, 90, 23, 78, 223, 155, 144, 238, 12, 14, 191, 158, 6, 181, 254, 0, 85, 134, 56, 161, 234, 55, 129, 64, 59, 12, 146, 6, 217, 232, 20, 214, 167, 159, 183, 165, 96, 96, 225, 199, 23, 106, 243, 108, 106, 26, 214, 53, 152, 26, 155, 253, 128, 7, 216, 207, 109, 159, 147, 240, 232, 226, 43, 147, 169, 162, 204, 215, 9, 10, 177, 223, 99, 206, 163, 240, 64]),
- 192: new Uint8Array([98, 123, 235, 65, 14, 86, 80, 133, 88, 104, 244, 125, 165, 185, 163, 4, 3, 230, 62, 58, 113, 222, 46, 210, 17, 155, 95, 19, 125, 125, 70, 234, 105, 54, 23, 246, 114, 9, 237, 191, 9, 194, 34, 254, 156, 11, 50, 216, 80, 178, 185, 221, 132, 154, 27, 85, 82, 49, 241, 123, 23, 106, 119, 134, 203, 0, 151, 66, 149, 218, 124, 247, 227, 233, 236, 184, 88, 234, 174, 250, 83, 168, 33, 15, 122, 26, 96, 213, 210, 4, 52, 92, 20, 12, 64, 12, 209, 197, 69, 100, 15, 56, 60, 63, 241, 52, 18, 189, 93, 146, 47, 60, 33, 200, 218, 243, 43, 169, 17, 108, 19, 199, 174, 33, 107, 186, 57, 95, 167, 138, 180, 187, 53, 113, 208, 148, 190, 48, 167, 53, 209, 52, 153, 184, 231, 63, 168, 54, 179, 238, 93, 130, 125, 3, 149, 119, 60, 25, 142, 150, 183, 193, 29, 18, 3, 219, 235, 219, 26, 116, 217, 196, 108, 6, 96, 103, 212, 48, 227, 91, 124, 77, 181, 169, 18, 111, 123, 83, 26, 169, 230, 88, 103, 185, 153, 93, 143, 152, 142, 231, 41, 226, 226, 156, 179, 206, 212, 67, 18, 193, 187, 53, 252, 214, 15, 228, 246, 131, 170, 101, 134, 212, 100, 170, 146, 47, 57, 125, 50, 230, 51, 246, 74, 175, 129, 196, 178, 206, 176, 52, 153, 39, 77, 24, 186, 99, 137, 83, 105, 111, 168, 35, 176, 24, 29, 170, 223, 74, 160, 138, 247, 12, 102, 233, 136, 59, 172, 228, 242, 84, 13, 34, 155, 80, 80, 87, 180, 143, 129, 61, 213, 54, 41, 8, 183, 102, 126, 179, 127, 77, 55, 176, 152, 41, 131, 85, 86, 225, 87, 216, 139, 226, 196, 195, 210, 34, 33, 161, 249, 153, 205, 197, 128, 41, 28, 121, 6, 159, 25, 211, 168, 137, 26, 217, 249, 113, 81, 141, 18, 1, 250, 228, 68, 238, 74, 54, 99, 167, 236, 176, 199, 148, 161, 143, 156, 51, 189, 204, 59, 240, 151, 170, 85, 63, 23, 38, 152, 199, 12, 81, 217, 244, 178, 231, 249, 159, 224, 107, 214, 58, 127, 116, 143, 219, 155, 80, 55, 213, 171, 80, 127, 235, 20, 247, 12, 104, 228, 147, 202, 124, 143, 110, 223, 76, 221, 154, 175, 143, 185, 237, 222, 189, 104, 218, 72, 244, 55, 253, 138, 183, 92, 231, 68, 176, 239, 171, 100, 10, 63, 61, 194, 228, 15, 133, 216, 45, 60, 135, 203, 142, 127, 153, 172, 223, 213, 230, 220, 189, 223, 234, 156, 134, 238, 220, 251, 104, 209, 117, 175, 47, 46, 148, 6, 61, 216, 215, 39, 30, 116, 212, 45, 112, 202, 227, 198, 98, 253, 97, 177, 120, 74, 238, 68, 99, 240, 96, 43, 88, 166]),
- 256: new Uint8Array([55, 82, 154, 67, 47, 80, 186, 78, 83, 56, 95, 130, 102, 236, 61, 236, 204, 236, 234, 222, 122, 226, 147, 149, 233, 41, 16, 118, 201, 91, 185, 162, 79, 71, 146, 252, 221, 110, 165, 137, 75, 129, 94, 219, 93, 94, 64, 34, 250, 190, 5, 90, 6, 177, 167, 224, 25, 121, 85, 91, 87, 152, 56, 100, 191, 35, 1, 156, 177, 179, 127, 253, 173, 176, 87, 247, 40, 207, 178, 175, 10, 51, 209, 70, 52, 76, 251, 160, 172, 203, 77, 191, 97, 58, 123, 238, 82, 60, 166, 214, 134, 14, 71, 74, 156, 15, 77, 6, 141, 76, 10, 205, 148, 204, 85, 203, 242, 30, 66, 133, 202, 21, 17, 108, 151, 2, 15, 44, 51, 180, 88, 80, 8, 248, 254, 151, 201, 226, 156, 6, 39, 197, 212, 124, 72, 217, 75, 232, 139, 155, 22, 199, 242, 223, 116, 10, 141, 42, 7, 85, 99, 5, 184, 43, 145, 159, 122, 135, 202, 46, 209, 157, 178, 114, 98, 194, 119, 194, 19, 242, 167, 236, 162, 94, 90, 106, 219, 234, 67, 11, 162, 225, 6, 17, 152, 23, 16, 84, 40, 90, 255, 158, 8, 105, 198, 56, 220, 213, 36, 203, 241, 242, 85, 218, 103, 90, 202, 214, 215, 134, 121, 169, 149, 139, 122, 143, 155, 178, 29, 217, 197, 128, 173, 25, 111, 154, 14, 76, 106, 101, 0, 215, 187, 33, 223, 116, 205, 89, 52, 206, 60, 77, 141, 31, 57, 211, 74, 42, 219, 88, 210, 36, 196, 128, 151, 136, 124, 222, 157, 59, 225, 70, 163, 234, 59, 173, 228, 198, 134, 76, 249, 228, 69, 181, 196, 194, 179, 239, 78, 43, 143, 94, 234, 10, 177, 192, 185, 171, 231, 164, 254, 91, 44, 11, 29, 148, 223, 107, 18, 149, 61, 50, 115, 38, 14, 128, 189, 9, 77, 236, 151, 163, 23, 122, 156, 236, 11, 80, 66, 190, 24, 4, 4, 12, 148, 57, 64, 59, 143, 114, 247, 66, 111, 167, 86, 173, 98, 102, 207, 44, 134, 89, 231, 64, 50, 157, 208, 210, 79, 159, 133, 73, 118, 98, 202, 215, 57, 247, 29, 97, 116, 1, 28, 119, 248, 243, 31, 180, 66, 38, 40, 141, 251, 134, 129, 126, 241, 113, 22, 50, 28, 113, 187, 158, 217, 125, 182, 233, 144, 246, 32, 88, 88, 15, 0, 102, 131, 67, 31, 34, 150, 98, 241, 213, 227, 205, 175, 254, 3, 53, 70, 124, 167, 38, 53, 104, 140, 147, 158, 200, 179, 45, 100, 101, 246, 81, 166, 53, 247, 60, 10, 78, 127, 10, 173, 176, 232, 31, 91, 203, 250, 236, 38, 113, 172, 151, 253, 194, 253, 50, 242, 76, 148, 23, 117, 195, 122, 104, 16, 212, 177, 113, 188, 138, 186, 144, 168, 102, 3])
- };
-
- const keyLengths = [128, 192, 256];
- return key_usage => {
- const keyLength = keyLengths[0];
- return {
- passing: keyLengths.map(keyLength =>
- crypto.subtle.importKey(
- 'raw',
- keyBytes[keyLength],
- {name: 'AES-CTR'},
- false,
- key_usage,
- )
- .then(key => ({
- name: "AES-CTR " + keyLength + "-bit key",
- algorithm: {name: "AES-CTR", counter, length: 64},
- key,
- plaintext,
- result: ciphertext[keyLength]
- }))),
- failing: keyLengths.flatMap(keyLength =>
- [
- {
- name: "AES-CTR " + keyLength + "-bit key, 0-bit counter",
- algorithm: {name: "AES-CTR", counter, length: 0},
- plaintext,
- result: ciphertext[keyLength],
- },
- {
- name: "AES-CTR " + keyLength + "-bit key, 129-bit counter",
- algorithm: {name: "AES-CTR", counter, length: 129},
- plaintext,
- result: ciphertext[keyLength],
- },
- ].map(vector =>
- crypto.subtle.importKey(
- 'raw',
- keyBytes[keyLength],
- {name: 'AES-CTR'},
- false,
- key_usage,
- ).then(key => Object.assign(vector, {key}))
- )
- )
- }};
-})();
-
-const equalBuffers = (a, b) => {
- if (a.byteLength !== b.byteLength) {
- return false;
- }
- const aBytes = new Uint8Array(a);
- const bBytes = new Uint8Array(b);
-
- for (let i = 0; i < a.byteLength; i++) {
- if (aBytes[i] !== bBytes[i]) {
- return false;
- }
- }
-
- return true;
-};
-
-const runSubtleEncryptDecrptTests = () => {
- const test_cases = [
- {test_name: 'encrypt'},
- {
- test_name: 'altered plaintext',
- modify_vector: vector => {
- vector.plaintext = copyBuffer(vector.plaintext);
- return vector;
- },
- },
- {
- test_name: 'decrypt',
- encrypt_or_decrypt: 'decrypt',
- },
- {
- test_name: 'decrypt with altered ciphertext',
- modify_vector: vector => {
- vector.result = copyBuffer(vector.result);
- return vector;
- },
- encrypt_or_decrypt: 'decrypt',
- },
- {
- test_name: 'without encrypt usage',
- key_usage: ['decrypt'],
- expected_result: false,
- expected_err: err => err.name === 'InvalidAccessError',
- },
- {
- test_name: 'mismatched key and algorithm',
- modify_vector: vector => {
- vector.algorithm.name = 'AES-CBC';
- vector.algorithm.iv = new Uint8Array(16); // Need syntactically valid parameter to get to error being checked.
- return vector;
- },
- expected_result: false,
- expected_err: err => err.name === 'InvalidAccessError',
- },
- {
- test_name: 'without decrypt usage',
- key_usage: ['encrypt'],
- encrypt_or_decrypt: 'decrypt',
- expected_result: false,
- expected_err: err => err.name === 'InvalidAccessError',
- },
- {
- test_name: 'OperationError due to data lengths',
- vector_type: 'failing',
- expected_result: false,
- expected_err: err => err.name === 'OperationError',
- },
- {
- test_name: 'OperationError due to data lengths for decryption',
- vector_type: 'failing',
- encrypt_or_decrypt: 'decrypt',
- expected_result: false,
- expected_err: err => err.name === 'OperationError',
- },
- ];
- return Promise.all([test_cases].flatMap(({
- key_usage=['encrypt', 'decrypt'],
- modify_vector=(v => v),
- vector_type='passing',
- encrypt_or_decrypt='encrypt',
- expected_result=true,
- expected_err=(err => false),
- test_name,
- }) =>
- getAesCtrImportedTestVectors(key_usage)[vector_type].map(promiseVector =>
- promiseVector
- .then(modify_vector)
- .then(vector =>
- (encrypt_or_decrypt === 'encrypt' ?
- crypto.subtle.encrypt(vector.algorithm, vector.key, vector.plaintext)
- .then(result => [equalBuffers(result, vector.result) === expected_result, 'Should return expected result'])
- .catch(err => [expected_err(err), 'encrypt error for test ' + vector.name + ': ' + err.message]) :
- crypto.subtle.decrypt(vector.algorithm, vector.key, vector.result)
- .then(plaintext => [equalBuffers(plaintext, vector.plaintext) === expected_result, 'Should return expected result'])
- .catch(err => [expected_err(err), 'decrypt error for test ' + vector.name + ': ' + err.message]))
- .then(result => [result[0], vector.name + ' ' + test_name + ': ' + result[1]])
- .catch(err => [false, 'importKey failed for ' + vector.name])))));
-};
-
-const postResults = (promise_results, suite_name) =>
- promise_results
- .then(results => {
- const failures = results.filter(([status, message]) => !status).map(([status, message]) => message);
- if (failures.length === 0) {
- postMessage('pass');
- } else {
- postMessage('\n' + `Failures for ${suite_name}:` + '\n' + failures.join('\n'));
- }
- })
- .catch(err => postMessage(err + ': ' + err.message));
-
-onmessage = event => {
- if (event.data === 'crypto_defined') {
- postResults(Promise.resolve([
- [!!crypto, 'crypto is not defined.'],
- [!!crypto.subtle, 'crypto.subtle is not defined.'],
- [!!crypto.subtle.importKey, 'crypto.subtle.importKey is not defined.'],
- [!!crypto.subtle.sign, 'crypto.subtle.sign is not defined.'],
- [!!crypto.subtle.verify, 'crypto.subtle.verify is not defined.'],
- [!!crypto.getRandomValues, 'crypto.getRandomValues is not defined.'],
- ]), event.data);
- } else if (event.data === 'subtle_encrypt_decrypt') {
- postResults(runSubtleEncryptDecrptTests(), event.data);
- } else if (event.data === 'subtle_importKey_verify_sign') {
- postResults(runSubtleImportKeyVerifySignTests(), event.data);
- } else if (event.data === 'getRandomValues') {
- postResults(runGetRandomValuesTests(), event.data);
- } else {
- postMessage(`Unexpected message received: ${event.data}.`);
- }
-};
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/black_box_tests/tests/web_crypto_api_test.py b/cobalt/black_box_tests/tests/web_crypto_api_test.py
deleted file mode 100644
index 96f453d..0000000
--- a/cobalt/black_box_tests/tests/web_crypto_api_test.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2022 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Tests basic WebCrypto API functionality."""
-
-from cobalt.black_box_tests import black_box_tests
-from cobalt.black_box_tests.threaded_web_server import ThreadedWebServer
-
-
-class WebCryptoApiTest(black_box_tests.BlackBoxTestCase):
- """Test basic WebCrypto API functionality."""
-
- def test_simple(self):
-
- with ThreadedWebServer(binding_address=self.GetBindingAddress()) as server:
- url = server.GetURL(file_name='testdata/web_crypto_api_test.html')
-
- with self.CreateCobaltRunner(url=url) as runner:
- runner.WaitForJSTestsSetup()
- self.assertTrue(runner.JSTestsSucceeded())
diff --git a/cobalt/demos/content/BUILD.gn b/cobalt/demos/content/BUILD.gn
index c23edf1..9e6b742 100644
--- a/cobalt/demos/content/BUILD.gn
+++ b/cobalt/demos/content/BUILD.gn
@@ -111,8 +111,8 @@
if (is_internal_build) {
sources += [
+ "internal/runtime-dump.html",
"javascript-fuzzer/index.html",
- "kabuki/runtime-dump.html",
"media-element-demo/public/assets/ac3.mp4",
"media-element-demo/public/assets/dash-audio.mp4",
"media-element-demo/public/assets/dash-video-1080p.mp4",
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/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/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/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 c953dc0..ea03435 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;
}
@@ -282,5 +285,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/worker/worker.cc b/cobalt/worker/worker.cc
index b8e283b..aeed129 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 {
@@ -253,10 +253,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/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/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/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/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/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