diff --git a/.github/actions/on_host_tests/action.yaml b/.github/actions/on_host_tests/action.yaml index b4e7f74e91ab..a8c33f90a6ce 100644 --- a/.github/actions/on_host_tests/action.yaml +++ b/.github/actions/on_host_tests/action.yaml @@ -35,17 +35,17 @@ runs: env # Explicitly point to libraries in extracted dir. - LD_LIBRARY_PATH="${test_dir}/out/${{ matrix.platform }}_${{ matrix.config }}/starboard" - LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${test_dir}/out/${{ matrix.platform }}_${{ matrix.config }}" + LD_LIBRARY_PATH="${test_dir}/starboard" + LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${test_dir}" export LD_LIBRARY_PATH # Make results dir available to the archiving step below. results_dir="${GITHUB_WORKSPACE}/results" echo "results_dir=${results_dir}" >> $GITHUB_ENV + failed_suites="" cd ${test_dir} - for test_binary_path in $(ls -d out/**/*tests out/**/nplb); do - test_binary=$(basename "${test_binary_path}") + for test_binary in $(ls {*tests,nplb}); do echo "Running tests for suite: ${test_binary}" test_filter="*" @@ -57,9 +57,16 @@ runs: echo "Test filter evaluated to: ${test_filter}" xml_path="${results_dir}/${test_binary}_testoutput.xml" - /usr/bin/xvfb-run -a --server-args="${XVFB_SERVER_ARGS}" ./$test_binary_path --gtest_filter="${test_filter}" --gtest_output="xml:${xml_path}" + /usr/bin/xvfb-run -a --server-args="${XVFB_SERVER_ARGS}" "./${test_binary}" --gtest_filter="${test_filter}" --gtest_output="xml:${xml_path}" || { + # Set exit code on failure. + failed_suites="${failed_suites} ${test_binary}" + } done echo "Finished running all unit tests..." + if [ -n "${failed_suites}" ]; then + echo "Test suites failed:${failed_suites}" + exit 1 + fi - name: Archive Test Results if: success() || failure() uses: actions/upload-artifact@v4 diff --git a/.github/actions/process_test_results/action.yaml b/.github/actions/process_test_results/action.yaml index 70cd2212ecd2..f5373c49235a 100644 --- a/.github/actions/process_test_results/action.yaml +++ b/.github/actions/process_test_results/action.yaml @@ -16,7 +16,7 @@ inputs: runs: using: "composite" steps: - - name: Download Artifacts + - name: Download Test Results uses: actions/download-artifact@v4 with: name: ${{ inputs.test_results_key }} diff --git a/.github/actions/upload_test_artifacts/action.yaml b/.github/actions/upload_test_artifacts/action.yaml index 53402606ee34..017950dce2ff 100644 --- a/.github/actions/upload_test_artifacts/action.yaml +++ b/.github/actions/upload_test_artifacts/action.yaml @@ -31,13 +31,20 @@ runs: if: inputs.on_host == 'true' run: | set -x - cd src - tar cvf - out/${{ matrix.platform }}_${{ matrix.config }}/*tests out/${{ matrix.platform }}_${{ matrix.config }}/nplb out/${{ matrix.platform }}_${{ matrix.config }}/*.so out/${{ matrix.platform }}_${{ matrix.config }}/*.so.* out/${{ matrix.platform }}_${{ matrix.config }}/starboard/*.so.* out/${{ matrix.platform }}_${{ matrix.config }}/content/test | xz -T0 -1 -z - > test_artifacts.tar.xz + cd src/out/${{ matrix.platform }}_${{ matrix.config }} + test_deps_file="test.deps" + for test_binary in $(ls {nplb,*tests}); do + echo $test_binary + if [ -f "${test_binary}.runtime_deps" ]; then + cat "${test_binary}.runtime_deps" >> "${test_deps_file}" + fi + done + tar cvf - -T "${test_deps_file}" | xz -T0 -1 -z - > "${GITHUB_WORKSPACE}/test_artifacts.tar.xz" shell: bash - name: Upload On-Host Test Artifacts Archive if: inputs.on_host == 'true' uses: actions/upload-artifact@v4 with: name: ${{ inputs.test_artifacts_key }} - path: src/test_artifacts.tar.xz + path: test_artifacts.tar.xz retention-days: 3 diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 7506f6667fe9..8bda5a6786e4 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -156,7 +156,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 # TODO(bug?): android debug builds are broken. - if: ${{ ! (startsWith(matrix.platform, 'android') && matrix.config == 'debug') }} + if: ${{ ! (contains(matrix.platform, 'android') && matrix.config == 'debug') }} with: path: src # Use fetch depth of 0 to get full history for a valid build id. @@ -164,7 +164,7 @@ jobs: - name: Build Cobalt uses: ./src/.github/actions/build # TODO(bug?): android debug builds are broken. - if: ${{ ! (startsWith(matrix.platform, 'android') && matrix.config == 'debug') }} + if: ${{ ! (contains(matrix.platform, 'android') && matrix.config == 'debug') }} with: targets: ${{ needs.initialize.outputs.targets }} - name: Upload Test Artifacts diff --git a/cobalt/build/gn.py b/cobalt/build/gn.py index 998ee7d942af..06d86bc2a02c 100755 --- a/cobalt/build/gn.py +++ b/cobalt/build/gn.py @@ -56,8 +56,7 @@ def get_build_args(build_args_path): }, 'qa': { 'symbol_level': 1, - 'is_debug': 'false', - 'is_official_build': 'true' + 'is_debug': 'false' }, 'gold': { 'symbol_level': 0, diff --git a/cobalt/devinfra/kokoro/bin/common.sh b/cobalt/devinfra/kokoro/bin/common.sh index aff77e3c3704..eed0bbd9f3f5 100755 --- a/cobalt/devinfra/kokoro/bin/common.sh +++ b/cobalt/devinfra/kokoro/bin/common.sh @@ -265,19 +265,9 @@ create_and_upload_nightly_archive () { fi local gcs_archive_path="gs://$(get_bucket_name)/${platform}${gcs_path_suffix}/$(date +%F)/${KOKORO_ROOT_BUILD_NUMBER}/" - # Creates nightly archive from package directory. - python3 "${WORKSPACE_COBALT}/tools/create_archive.py" \ - -s "${package_dir}" \ - -d "${local_archive_path}" \ - --intermediate - init_gcloud - # Uploads nightly archive. - "${GSUTIL}" cp "${local_archive_path}" "${gcs_archive_path}" - - # Uploads build_info.json. - "${GSUTIL}" cp "${build_info_path}" "${gcs_archive_path}" + "${GSUTIL}" cp -r "${package_dir}" "${gcs_archive_path}" } run_package_release_pipeline () { @@ -300,11 +290,7 @@ run_package_release_pipeline () { # Create release package. if [[ "${PLATFORM}" =~ "android" ]]; then - # Creates Android package directory. - python3 "${WORKSPACE_COBALT}/cobalt/devinfra/kokoro/build/android/simple_packager.py" \ - "${out_dir}" \ - "${package_dir}" \ - "${WORKSPACE_COBALT}" + cp "${out_dir}/apks/Cobalt.apk" "${package_dir}" elif [[ "${PLATFORM}" =~ "evergreen" ]]; then local bootloader_out_dir= if [ -n "${BOOTLOADER:-}" ]; then @@ -316,8 +302,7 @@ run_package_release_pipeline () { "${package_dir}" \ "${bootloader_out_dir:-}" else - # Sets package directory as out directory. - package_dir="${out_dir}" + cp "${out_dir}/cobalt" "${package_dir}" fi # Create and upload nightly archive. diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 7824a83f0a7f..7e224c74a664 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn @@ -2321,6 +2321,13 @@ source_set("browser") { "worker_host/worker_script_loader_factory.h", ] + if (is_cobalt) { + sources += [ + "cobalt/crash_annotator/crash_annotator_impl.cc", + "cobalt/crash_annotator/crash_annotator_impl.h", + ] + } + if (use_starscan) { sources += [ "starscan_load_observer.cc", diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 90bd74a313bf..78da69eda21c 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc @@ -174,6 +174,11 @@ #include "third_party/blink/public/public_buildflags.h" #include "url/origin.h" +#if BUILDFLAG(IS_COBALT) +#include "content/browser/cobalt/crash_annotator/crash_annotator_impl.h" +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom.h" +#endif + #if BUILDFLAG(IS_ANDROID) #include "content/browser/android/date_time_chooser_android.h" #include "content/browser/android/text_suggestion_host_android.h" @@ -841,6 +846,11 @@ void PopulateFrameBinders(RenderFrameHostImpl* host, mojo::BinderMap* map) { map->Add(base::BindRepeating( &RenderFrameHostImpl::GetSpeechSynthesis, base::Unretained(host))); +#if BUILDFLAG(IS_COBALT) + map->Add(base::BindRepeating( + &RenderFrameHostImpl::GetCrashAnnotator, base::Unretained(host))); +#endif + #if !BUILDFLAG(IS_ANDROID) map->Add(base::BindRepeating( &RenderFrameHostImpl::GetDeviceInfoService, base::Unretained(host))); diff --git a/content/browser/cobalt/crash_annotator/crash_annotator_impl.cc b/content/browser/cobalt/crash_annotator/crash_annotator_impl.cc new file mode 100644 index 000000000000..72bb36a25658 --- /dev/null +++ b/content/browser/cobalt/crash_annotator/crash_annotator_impl.cc @@ -0,0 +1,31 @@ +// Copyright 2024 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 "content/browser/cobalt/crash_annotator/crash_annotator_impl.h" + +#include "base/functional/bind.h" +#include "base/functional/callback.h" + +namespace content { + +void CrashAnnotatorImpl::SetString(const std::string& key, + const std::string& value, + SetStringCallback callback) { + // TODO(cobalt, b/383301493): actually implement this. + LOG(INFO) << "CrashAnnotatorImpl::SetString key=" << key << " value=" + << value; + std::move(callback).Run(false); +} + +} // namespace content diff --git a/content/browser/cobalt/crash_annotator/crash_annotator_impl.h b/content/browser/cobalt/crash_annotator/crash_annotator_impl.h new file mode 100644 index 000000000000..2573de92f779 --- /dev/null +++ b/content/browser/cobalt/crash_annotator/crash_annotator_impl.h @@ -0,0 +1,47 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CONTENT_BROWSER_CRASH_ANNOTATOR_IMPL_H_ +#define CONTENT_BROWSER_CRASH_ANNOTATOR_IMPL_H_ + +#include + +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom.h" + +namespace content { + +// TODO(cobalt, b/383301493): consider another location for Cobalt's Mojo +// implementations, since they are not "core" services. mcasas@ suggested +// //components or //services as possible destinations. +class CrashAnnotatorImpl : public blink::mojom::CrashAnnotator { + public: + explicit CrashAnnotatorImpl( + mojo::PendingReceiver receiver) + : receiver_(this, std::move(receiver)) {} + CrashAnnotatorImpl(const CrashAnnotatorImpl&) = delete; + CrashAnnotatorImpl& operator=(const CrashAnnotatorImpl&) = delete; + + void SetString(const std::string& key, + const std::string& value, + SetStringCallback callback) override; + + private: + mojo::Receiver receiver_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_CRASH_ANNOTATOR_IMPL_H_ diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 3b35cc5d4492..be77a68af476 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc @@ -269,6 +269,10 @@ #include "url/origin.h" #include "url/url_constants.h" +#if BUILDFLAG(IS_COBALT) +#include "content/browser/cobalt/crash_annotator/crash_annotator_impl.h" +#endif + #if BUILDFLAG(IS_ANDROID) #include "content/browser/android/content_url_loader_factory.h" #include "content/browser/android/java_interfaces_impl.h" @@ -11593,6 +11597,13 @@ void RenderFrameHostImpl::GetFileSystemManager( storage_key(), std::move(receiver))); } +#if BUILDFLAG(IS_COBALT) +void RenderFrameHostImpl::GetCrashAnnotator( + mojo::PendingReceiver receiver) { + crash_annotator_ = std::make_unique(std::move(receiver)); +} +#endif + void RenderFrameHostImpl::GetGeolocationService( mojo::PendingReceiver receiver) { if (!geolocation_service_) { diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 0c61e60b8a11..52c56fd94333 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h @@ -172,6 +172,11 @@ #include "ui/gfx/geometry/rect.h" #include "url/gurl.h" +#if BUILDFLAG(IS_COBALT) +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom-forward.h" +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom.h" +#endif + #if BUILDFLAG(IS_ANDROID) #include "base/containers/id_map.h" #include "services/device/public/mojom/nfc.mojom.h" @@ -249,6 +254,9 @@ class DocumentServiceBase; class AgentSchedulingGroupHost; class BrowsingContextState; class CodeCacheHostImpl; +#if BUILDFLAG(IS_COBALT) +class CrashAnnotatorImpl; +#endif class CrossOriginEmbedderPolicyReporter; class CrossOriginOpenerPolicyAccessReportManager; class FeatureObserver; @@ -1942,6 +1950,11 @@ class CONTENT_EXPORT RenderFrameHostImpl void GetFileSystemAccessManager( mojo::PendingReceiver receiver); +#if BUILDFLAG(IS_COBALT) + void GetCrashAnnotator( + mojo::PendingReceiver receiver); +#endif + #if !BUILDFLAG(IS_ANDROID) void GetHidService(mojo::PendingReceiver receiver); @@ -4492,6 +4505,10 @@ class CONTENT_EXPORT RenderFrameHostImpl // Tracks the document policy which has been set on this frame. std::unique_ptr document_policy_; +#if BUILDFLAG(IS_COBALT) + std::unique_ptr crash_annotator_; +#endif + #if BUILDFLAG(IS_ANDROID) // An InterfaceProvider for Java-implemented interfaces that are scoped to // this RenderFrameHost. This provides access to interfaces implemented in diff --git a/media/starboard/starboard_renderer.cc b/media/starboard/starboard_renderer.cc index 4ed2ed2426f9..9be127ea9fd9 100644 --- a/media/starboard/starboard_renderer.cc +++ b/media/starboard/starboard_renderer.cc @@ -592,9 +592,11 @@ void StarboardRenderer::OnDemuxerStreamRead( DCHECK(audio_read_in_progress_); audio_read_in_progress_ = false; for (const auto& buffer : buffers) { - last_audio_sample_interval_ = - buffer->timestamp() - timestamp_of_last_written_audio_; - timestamp_of_last_written_audio_ = buffer->timestamp(); + if (!buffer->end_of_stream()) { + last_audio_sample_interval_ = + buffer->timestamp() - timestamp_of_last_written_audio_; + timestamp_of_last_written_audio_ = buffer->timestamp(); + } } player_bridge_->WriteBuffers(DemuxerStream::AUDIO, buffers); } else { diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index b1145a98a6d1..a4f61e8fca99 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn @@ -241,6 +241,10 @@ mojom("mojom_platform") { "worker/worker_options.mojom", ] + if (is_cobalt) { + sources += [ "cobalt/crash_annotator/crash_annotator.mojom" ] + } + if (is_android) { sources += [ "input/synchronous_compositor.mojom" ] } diff --git a/third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom b/third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom new file mode 100644 index 000000000000..84deafd8df26 --- /dev/null +++ b/third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom @@ -0,0 +1,22 @@ +// Copyright 2024 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. + +module blink.mojom; + +// The browser process must provide an implementation of this interface so that +// the renderer process can implement the CrashAnnotator Blink API. +interface CrashAnnotator { + // Recieves an annotation to set and responds with the result. + SetString(string key, string value) => (bool result); +}; diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 0b3ea3360c6c..118f11e214c6 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni @@ -2791,6 +2791,13 @@ generated_interface_sources_in_modules = [ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_webgl_sub_image.h", ] +if (is_cobalt) { + generated_interface_sources_in_modules += [ + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_crash_annotator.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_crash_annotator.h", + ] +} + generated_namespace_sources_in_modules = [ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_css.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_css.h", diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 7f915ac9c55d..ea769d605683 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni @@ -1202,6 +1202,14 @@ static_idl_files_in_modules = get_path_info( ], "abspath") +if (is_cobalt) { + static_idl_files_in_modules += get_path_info( + [ "//third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl", + "//third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl", + ], + "abspath") +} + # Direct Sockets # This uses target_os rather than current_os (which is what is_android is set # from) for the case of generating the v8 context snapshot for android. When diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn index 855d33552a2d..19a3b5f5ab47 100644 --- a/third_party/blink/renderer/modules/BUILD.gn +++ b/third_party/blink/renderer/modules/BUILD.gn @@ -167,6 +167,10 @@ component("modules") { "//third_party/blink/renderer/modules/xr", ] + if (is_cobalt) { + sub_modules += [ "//third_party/blink/renderer/modules/cobalt/crash_annotator" ] + } + # This uses target_os rather than current_os (which is what is_android is set # from) for the case of generating the v8 context snapshot for android. When # generating the snapshot for android, blink is compiled with diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/BUILD.gn b/third_party/blink/renderer/modules/cobalt/crash_annotator/BUILD.gn new file mode 100644 index 000000000000..cb5b0e61e73f --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright 2024 The Cobalt Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//third_party/blink/renderer/modules/modules.gni") + +blink_modules_sources("crash_annotator") { + sources = [ + "crash_annotator.cc", + "crash_annotator.h", + ] +} diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.cc b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.cc new file mode 100644 index 000000000000..4485eadbe71a --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.cc @@ -0,0 +1,92 @@ +// Copyright 2024 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 "third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.h" + +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/execution_context/navigator_base.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +// static +const char CrashAnnotator::kSupplementName[] = "CrashAnnotator"; + +// static +CrashAnnotator* CrashAnnotator::crashAnnotator(NavigatorBase& navigator) { + CrashAnnotator* crash_annotator = + Supplement::From(navigator); + if (!crash_annotator && navigator.GetExecutionContext()) { + crash_annotator = MakeGarbageCollected(navigator); + ProvideTo(navigator, crash_annotator); + } + return crash_annotator; +} + +CrashAnnotator::CrashAnnotator(NavigatorBase& navigator) + : Supplement(navigator), + ExecutionContextLifecycleObserver(navigator.GetExecutionContext()), + crash_annotator_(navigator.GetExecutionContext()) {} + +void CrashAnnotator::ContextDestroyed() {} + +ScriptPromise CrashAnnotator::setString(ScriptState* script_state, + const String& key, + const String& value, + ExceptionState& exception_state) { + auto* resolver = MakeGarbageCollected( + script_state, exception_state.GetContext()); + + EnsureReceiverIsBound(); + + crash_annotator_->SetString(key, + value, + WTF::BindOnce( + &CrashAnnotator::OnSetString, + WrapPersistent(this), WrapPersistent(resolver))); + + return resolver->Promise(); +} + +void CrashAnnotator::OnSetString(ScriptPromiseResolver* resolver, bool result) { + resolver->Resolve(result); +} + +void CrashAnnotator::EnsureReceiverIsBound() { + DCHECK(GetExecutionContext()); + + if (crash_annotator_.is_bound()) { + return; + } + + auto task_runner = + GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI); + GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface( + crash_annotator_.BindNewPipeAndPassReceiver(task_runner)); +} + +void CrashAnnotator::Trace(Visitor* visitor) const { + visitor->Trace(crash_annotator_); + Supplement::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); + ScriptWrappable::Trace(visitor); +} + +} // namespace blink diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.h b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.h new file mode 100644 index 000000000000..1ea37ac1e1a0 --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.h @@ -0,0 +1,66 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_COBALT_CRASH_ANNOTATOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_COBALT_CRASH_ANNOTATOR_H_ + +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" +#include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" + +namespace blink { + +class ExecutionContext; +class NavigatorBase; +class ScriptPromiseResolver; +class ScriptState; + +class MODULES_EXPORT CrashAnnotator final + : public ScriptWrappable, + public Supplement, + public ExecutionContextLifecycleObserver { + DEFINE_WRAPPERTYPEINFO(); + + public: + static const char kSupplementName[]; + + // For navigator.crashAnnotator + static CrashAnnotator* crashAnnotator(NavigatorBase&); + + explicit CrashAnnotator(NavigatorBase&); + + void ContextDestroyed() override; + + ScriptPromise setString(ScriptState*, + const String& key, + const String& value, + ExceptionState&); + + void Trace(Visitor*) const override; + + private: + void OnSetString(ScriptPromiseResolver*, bool); + void EnsureReceiverIsBound(); + + HeapMojoRemote crash_annotator_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COBALT_CRASH_ANNOTATOR_H_ diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl new file mode 100644 index 000000000000..9f8596e5456d --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl @@ -0,0 +1,24 @@ +// Copyright 2024 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. + +// Allows (key, value) pairs to be added to uploaded crash reports as context. +[ + Exposed=Window, + SecureContext +] +interface CrashAnnotator { + // Returns a promise of true on success and false on failure. + [CallWith=ScriptState, RaisesException] + Promise setString(DOMString key, DOMString value); +}; diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl b/third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl new file mode 100644 index 000000000000..737ff89f910a --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl @@ -0,0 +1,21 @@ +// Copyright 2024 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. + +// Extends the navigator interface. +[ + ImplementedAs=CrashAnnotator, + SecureContext +] partial interface Navigator { + [SameObject] readonly attribute CrashAnnotator crashAnnotator; +}; diff --git a/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/README.md b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/README.md new file mode 100644 index 000000000000..cd1c51ca4972 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/README.md @@ -0,0 +1,6 @@ +# Web tests for CrashAnnotator + +These automated tests rely on a test-only interface that must be provided by the +browser under test. The pattern from the Serial API is followed: an +implementation of the CrashAnnotator Mojo interface is provided by +`../../resources/chromium/cobalt/fake-crash-annotator.js`. diff --git a/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/crash_annotator_setString.https.any.js b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/crash_annotator_setString.https.any.js new file mode 100644 index 000000000000..21fba8cdd5ae --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/crash_annotator_setString.https.any.js @@ -0,0 +1,18 @@ +// META: global=window +// META: script=/resources/test-only-api.js +// META: script=resources/automation.js + +crash_annotator_test(async (t, fake) => { + let expectedSetStringResult = true; + fake.stubResult(expectedSetStringResult); + let setStringResult = + await navigator.crashAnnotator.setString("some key", "some val"); + assert_equals(setStringResult, expectedSetStringResult); +}, 'setString() returns value provided by browser endpoint'); + +crash_annotator_test(async (t, fake) => { + let key = "some key"; + let value = "some value"; + await navigator.crashAnnotator.setString(key, value); + assert_equals(fake.getAnnotation(key), value); +}, 'setString() sends expected key and value to browser endpoint'); diff --git a/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/resources/automation.js b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/resources/automation.js new file mode 100644 index 000000000000..c630f663ca58 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/resources/automation.js @@ -0,0 +1,26 @@ +'use strict'; + +// These tests use a fake implementation of the CrashAnnotator Mojo interface. + +let fakeCrashAnnotator = undefined; + +function crash_annotator_test(func, name, properties) { + promise_test(async (test) => { + assert_implements(navigator.crashAnnotator, + 'missing navigator.crashAnnotator'); + if (fakeCrashAnnotator === undefined) { + const fakes = + await import('/resources/chromium/cobalt/fake-crash-annotator.js'); + fakeCrashAnnotator = fakes.fakeCrashAnnotator; + } + assert_implements(fakeCrashAnnotator, 'missing fakeCrashAnnotator'); + + fakeCrashAnnotator.start(); + try { + await func(test, fakeCrashAnnotator); + } finally { + fakeCrashAnnotator.stop(); + fakeCrashAnnotator.reset(); + } + }, name, properties); + } diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/cobalt/fake-crash-annotator.js b/third_party/blink/web_tests/external/wpt/resources/chromium/cobalt/fake-crash-annotator.js new file mode 100644 index 000000000000..484bcb57bf36 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resources/chromium/cobalt/fake-crash-annotator.js @@ -0,0 +1,50 @@ +import {CrashAnnotator, CrashAnnotatorReceiver} from '/gen/third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom.m.js'; + +// Implementation of blink.mojom.CrashAnnotator. +class FakeCrashAnnotator { + constructor() { + this.interceptor_ = + new MojoInterfaceInterceptor(CrashAnnotator.$interfaceName); + this.interceptor_.oninterfacerequest = e => this.bind(e.handle); + this.receiver_ = new CrashAnnotatorReceiver(this); + this.stub_result_ = null; + this.annotations_ = new Map(); + } + + start() { + this.interceptor_.start(); + } + + stop() { + this.interceptor_.stop(); + } + + reset() { + this.stub_result_ = null; + this.annotations_ = new Map(); + } + + async setString(key, value) { + this.annotations_.set(key, value); + return { + result: this.stub_result_ + }; + } + + // Added for stubbing setString() result in tests. + stubResult(stub_result) { + this.stub_result_ = stub_result; + } + + // Added for testing setString() interactions. + getAnnotation(key) { + return this.annotations_.get(key); + } + + bind(handle) { + this.receiver_.$.bindHandle(handle); + } + +} + +export const fakeCrashAnnotator = new FakeCrashAnnotator();