Import Cobalt 20.master.0.234144 Includes the following patches: https://cobalt-review.googlesource.com/c/cobalt/+/5590 by n1214.hwang@samsung.com https://cobalt-review.googlesource.com/c/cobalt/+/5530 by errong.leng@samsung.com https://cobalt-review.googlesource.com/c/cobalt/+/5570 by devin.cai@mediatek.com
diff --git a/src/base/base.gyp b/src/base/base.gyp index 9cbd82f..5eccf13 100644 --- a/src/base/base.gyp +++ b/src/base/base.gyp
@@ -142,6 +142,8 @@ 'files/file_util.cc', 'files/file_util.h', 'files/file_util_starboard.cc', + 'files/important_file_writer.cc', + 'files/important_file_writer.h', 'files/platform_file.h', 'files/scoped_file.cc', 'files/scoped_file.h', @@ -773,6 +775,7 @@ 'files/file_proxy_unittest.cc', 'files/file_unittest.cc', 'files/file_util_unittest.cc', + 'files/important_file_writer_unittest.cc', 'files/scoped_temp_dir_unittest.cc', 'gmock_unittest.cc', 'guid_unittest.cc',
diff --git a/src/base/cpp14oncpp11.h b/src/base/cpp14oncpp11.h index bc791ea..ae23cd3 100644 --- a/src/base/cpp14oncpp11.h +++ b/src/base/cpp14oncpp11.h
@@ -162,45 +162,55 @@ template<typename T> using add_volatile_t = typename add_volatile<T>::type; -template< class C > +template< class C > auto rbegin( C& c ) -> decltype(c.rbegin()) { return c.rbegin(); } -template< class C > +template< class C > auto rbegin( const C& c ) -> decltype(c.rbegin()) { return c.rbegin(); } -template< class T, size_t N > +template< class T, size_t N > reverse_iterator<T*> rbegin( T (&array)[N] ) { return reverse_iterator<T*>(array + N); } -template< class C > +template <class C> +constexpr auto cbegin(const C& c) -> decltype(std::begin(c)) { + return std::begin(c); +} + +template< class C > auto crbegin( const C& c ) -> decltype(std::rbegin(c)) { return std::rbegin(c); } -template< class C > +template< class C > auto rend( C& c ) -> decltype(c.rend()) { return c.rend(); } -template< class C > +template< class C > auto rend( const C& c ) -> decltype(c.rend()) { return c.rend(); } -template< class T, size_t N > +template< class T, size_t N > reverse_iterator<T*> rend( T (&array)[N] ) { return reverse_iterator<T*>(array); } -template< class C > +template< class C > auto crend( const C& c ) -> decltype(std::rend(c)) { return std::rend(c); } + +template <class C> +constexpr auto cend(const C& c) -> decltype(std::end(c)) { + return std::end(c); +} #endif } // namespace std
diff --git a/src/base/files/important_file_writer.cc b/src/base/files/important_file_writer.cc index c5a120f..968c753 100644 --- a/src/base/files/important_file_writer.cc +++ b/src/base/files/important_file_writer.cc
@@ -27,6 +27,7 @@ #include "base/threading/thread.h" #include "base/time/time.h" #include "build/build_config.h" +#include "starboard/file.h" #include "starboard/types.h" namespace base { @@ -130,6 +131,22 @@ } // namespace +#if defined(OS_STARBOARD) +// static +bool ImportantFileWriter::WriteFileAtomically(const FilePath& path, + StringPiece data, + StringPiece histogram_suffix) { + SB_UNREFERENCED_PARAMETER(histogram_suffix); +#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + return SbFileAtomicReplace(path.value().c_str(), data.data(), data.size()); +#else + SB_NOTREACHED() + << "SbFileAtomicReplace is not available before starboard version " + << SB_FILE_ATOMIC_REPLACE_VERSION; + return false; +#endif +} +#else // static bool ImportantFileWriter::WriteFileAtomically(const FilePath& path, StringPiece data, @@ -210,6 +227,7 @@ return true; } +#endif ImportantFileWriter::ImportantFileWriter( const FilePath& path,
diff --git a/src/base/files/important_file_writer.h b/src/base/files/important_file_writer.h index 386811a..f0cbfd2 100644 --- a/src/base/files/important_file_writer.h +++ b/src/base/files/important_file_writer.h
@@ -17,8 +17,6 @@ #include "base/time/time.h" #include "base/timer/timer.h" -#if !defined(STARBOARD) - namespace base { class SequencedTaskRunner; @@ -160,6 +158,4 @@ } // namespace base -#endif // #if !defined(STARBOARD) - #endif // BASE_FILES_IMPORTANT_FILE_WRITER_H_
diff --git a/src/base/files/important_file_writer_unittest.cc b/src/base/files/important_file_writer_unittest.cc index 5dddc71..680a2f8 100644 --- a/src/base/files/important_file_writer_unittest.cc +++ b/src/base/files/important_file_writer_unittest.cc
@@ -23,6 +23,7 @@ #include "base/timer/mock_timer.h" #include "testing/gtest/include/gtest/gtest.h" +#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION namespace base { namespace { @@ -179,6 +180,9 @@ EXPECT_EQ("baz", GetFileContent(writer.path())); } +// Disable the test as win32 SbFileOpen doesn't fail on relative path +// like bad/../path.tmp +#if !defined(OS_STARBOARD) TEST_F(ImportantFileWriterTest, FailedWriteWithObserver) { // Use an invalid file path (relative paths are invalid) to get a // FILE_ERROR_ACCESS_DENIED error when trying to write the file. @@ -196,6 +200,7 @@ write_callback_observer_.GetAndResetObservationState()); EXPECT_FALSE(PathExists(writer.path())); } +#endif TEST_F(ImportantFileWriterTest, CallbackRunsOnWriterThread) { base::Thread file_writer_thread("ImportantFileWriter test thread"); @@ -327,6 +332,7 @@ EXPECT_FALSE(PathExists(writer.path())); } +#if !defined(OS_STARBOARD) TEST_F(ImportantFileWriterTest, WriteFileAtomicallyHistogramSuffixTest) { base::HistogramTester histogram_tester; EXPECT_FALSE(PathExists(file_)); @@ -347,5 +353,8 @@ histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError", 1); histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError.test", 1); } +#endif } // namespace base + +#endif // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
diff --git a/src/base/time/time.cc b/src/base/time/time.cc index 90e22cc..b975053 100644 --- a/src/base/time/time.cc +++ b/src/base/time/time.cc
@@ -30,7 +30,8 @@ TimeTicksNowFunction g_time_ticks_now_function = &subtle::TimeTicksNowIgnoringOverride; -#if SB_HAS(TIME_THREAD_NOW) +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \ + SB_HAS(TIME_THREAD_NOW) ThreadTicksNowFunction g_thread_ticks_now_function = &subtle::ThreadTicksNowIgnoringOverride; #endif @@ -323,11 +324,14 @@ // static ThreadTicks ThreadTicks::Now() { -#if SB_HAS(TIME_THREAD_NOW) - return internal::g_thread_ticks_now_function(); -#else - return ThreadTicks(); +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \ + SB_HAS(TIME_THREAD_NOW) +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION + if (SbTimeIsTimeThreadNowSupported()) #endif + return internal::g_thread_ticks_now_function(); +#endif + return ThreadTicks(); } std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
diff --git a/src/base/time/time.h b/src/base/time/time.h index fba813a..8ee1b6d 100644 --- a/src/base/time/time.h +++ b/src/base/time/time.h
@@ -997,7 +997,9 @@ // Returns true if ThreadTicks::Now() is supported on this system. static bool IsSupported() WARN_UNUSED_RESULT { #if defined(STARBOARD) -#if SB_HAS(TIME_THREAD_NOW) +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION + return SbTimeIsTimeThreadNowSupported(); +#elif SB_HAS(TIME_THREAD_NOW) return true; #else return false;
diff --git a/src/base/time/time_now_starboard.cc b/src/base/time/time_now_starboard.cc index f876e9c..e80ffaf 100644 --- a/src/base/time/time_now_starboard.cc +++ b/src/base/time/time_now_starboard.cc
@@ -62,12 +62,15 @@ namespace subtle { ThreadTicks ThreadTicksNowIgnoringOverride() { -#if SB_HAS(TIME_THREAD_NOW) - return ThreadTicks() + - TimeDelta::FromMicroseconds(SbTimeGetMonotonicThreadNow()); -#else - return ThreadTicks(); +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \ + SB_HAS(TIME_THREAD_NOW) +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION + if (SbTimeIsTimeThreadNowSupported()) #endif + return ThreadTicks() + + TimeDelta::FromMicroseconds(SbTimeGetMonotonicThreadNow()); +#endif + return ThreadTicks(); } } // namespace subtle
diff --git a/src/base/time/time_override.cc b/src/base/time/time_override.cc index 6232bfe..63f4d8e 100644 --- a/src/base/time/time_override.cc +++ b/src/base/time/time_override.cc
@@ -26,7 +26,8 @@ } if (time_ticks_override) internal::g_time_ticks_now_function = time_ticks_override; -#if SB_HAS(TIME_THREAD_NOW) +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \ + SB_HAS(TIME_THREAD_NOW) if (thread_ticks_override) internal::g_thread_ticks_now_function = thread_ticks_override; #endif @@ -37,7 +38,8 @@ internal::g_time_now_from_system_time_function = &TimeNowFromSystemTimeIgnoringOverride; internal::g_time_ticks_now_function = &TimeTicksNowIgnoringOverride; -#if SB_HAS(TIME_THREAD_NOW) +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \ + SB_HAS(TIME_THREAD_NOW) internal::g_thread_ticks_now_function = &ThreadTicksNowIgnoringOverride; #endif #if DCHECK_IS_ON()
diff --git a/src/base/trace_event/memory_usage_estimator.h b/src/base/trace_event/memory_usage_estimator.h index 53ce8f7..24f144f 100644 --- a/src/base/trace_event/memory_usage_estimator.h +++ b/src/base/trace_event/memory_usage_estimator.h
@@ -211,10 +211,12 @@ struct EMUCaller { // std::is_same<> below makes static_assert depend on T, in order to // prevent it from asserting regardless instantiation. +#if !defined(_GLIBCXX_DEBUG) && !defined(_LIBCPP_DEBUG) static_assert(std::is_same<T, std::false_type>::value, "Neither global function 'size_t EstimateMemoryUsage(T)' " "nor member function 'size_t T::EstimateMemoryUsage() const' " "is defined for the type."); +#endif static size_t Call(const T&) { return 0; } };
diff --git a/src/base/util/values/values_util.cc b/src/base/util/values/values_util.cc new file mode 100644 index 0000000..43b317b --- /dev/null +++ b/src/base/util/values/values_util.cc
@@ -0,0 +1,60 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/util/values/values_util.h" + +#include "base/strings/string_number_conversions.h" + +namespace util { + +base::Value Int64ToValue(int64_t integer) { + return base::Value(base::NumberToString(integer)); +} + +base::Optional<int64_t> ValueToInt64(const base::Value* value) { + return value ? ValueToInt64(*value) : base::nullopt; +} + +base::Optional<int64_t> ValueToInt64(const base::Value& value) { + if (!value.is_string()) + return base::nullopt; + + int64_t integer; + if (!base::StringToInt64(value.GetString(), &integer)) + return base::nullopt; + + return integer; +} + +base::Value TimeDeltaToValue(base::TimeDelta time_delta) { + return Int64ToValue(time_delta.InMicroseconds()); +} + +base::Optional<base::TimeDelta> ValueToTimeDelta(const base::Value* value) { + return value ? ValueToTimeDelta(*value) : base::nullopt; +} + +base::Optional<base::TimeDelta> ValueToTimeDelta(const base::Value& value) { + base::Optional<int64_t> integer = ValueToInt64(value); + if (!integer) + return base::nullopt; + return base::TimeDelta::FromMicroseconds(*integer); +} + +base::Value TimeToValue(base::Time time) { + return TimeDeltaToValue(time.ToDeltaSinceWindowsEpoch()); +} + +base::Optional<base::Time> ValueToTime(const base::Value* value) { + return value ? ValueToTime(*value) : base::nullopt; +} + +base::Optional<base::Time> ValueToTime(const base::Value& value) { + base::Optional<base::TimeDelta> time_delta = ValueToTimeDelta(value); + if (!time_delta) + return base::nullopt; + return base::Time::FromDeltaSinceWindowsEpoch(*time_delta); +} + +} // namespace util
diff --git a/src/base/util/values/values_util.gyp b/src/base/util/values/values_util.gyp new file mode 100644 index 0000000..0c537c0 --- /dev/null +++ b/src/base/util/values/values_util.gyp
@@ -0,0 +1,29 @@ +# Copyright 2019 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. + +{ + 'targets': [ + { + 'target_name': 'values_util', + 'type': 'static_library', + 'sources': [ + 'values_util.cc', + 'values_util.h', + ], + 'dependencies': [ + '<(DEPTH)/base/base.gyp:base', + ], + }, + ] +}
diff --git a/src/base/util/values/values_util.h b/src/base/util/values/values_util.h new file mode 100644 index 0000000..de9fd1b --- /dev/null +++ b/src/base/util/values/values_util.h
@@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_UTIL_VALUES_VALUES_UTIL_H_ +#define BASE_UTIL_VALUES_VALUES_UTIL_H_ + +#include "base/optional.h" +#include "base/time/time.h" +#include "base/values.h" + +namespace util { + +// Simple helper functions for converting int64_t, base::TimeDelta and +// base::Time to numeric string base::Values. +// Because base::TimeDelta and base::Time share the same internal representation +// as int64_t they are stored using the exact same numeric string format. + +// Stores the int64_t as a string. +base::Value Int64ToValue(int64_t integer); +base::Optional<int64_t> ValueToInt64(const base::Value* value); +base::Optional<int64_t> ValueToInt64(const base::Value& value); + +// Converts the TimeDelta to an int64_t of microseconds. +base::Value TimeDeltaToValue(base::TimeDelta time_delta); +base::Optional<base::TimeDelta> ValueToTimeDelta(const base::Value* value); +base::Optional<base::TimeDelta> ValueToTimeDelta(const base::Value& value); + +// Converts the Time to a TimeDelta from the Windows epoch. +base::Value TimeToValue(base::Time time); +base::Optional<base::Time> ValueToTime(const base::Value* value); +base::Optional<base::Time> ValueToTime(const base::Value& value); + +} // namespace util + +#endif // BASE_UTIL_VALUES_VALUES_UTIL_H_
diff --git a/src/build/common.gypi b/src/build/common.gypi index 7078e81..da3d978 100644 --- a/src/build/common.gypi +++ b/src/build/common.gypi
@@ -331,6 +331,7 @@ ['(OS == "win" or target_arch=="xb1") and component=="shared_library"', { 'msvs_disabled_warnings': [ 4251, # class 'std::xx' needs to have dll-interface. + 4715, # Not all control paths return a value. ], }], ],
diff --git a/src/cobalt/CHANGELOG.md b/src/cobalt/CHANGELOG.md index 7f3a40e..06fe9c7 100644 --- a/src/cobalt/CHANGELOG.md +++ b/src/cobalt/CHANGELOG.md
@@ -4,6 +4,13 @@ ## Version 21 + - **DevTools and WebDriver listen to ANY interface, except on Linux.** + + DevTools and WebDriver servers listen to connections on any network interface + by default, except on Linux where they listen only to loopback (localhost) by + default. A new "--dev_servers_listen_ip" command line parameter can be used to + specify a different interface for both of them to listen to. + - **DevTools shows asynchronous stack traces.** When stopped at a breakpoint within the handler function for an asynchronous
diff --git a/src/cobalt/audio/audio_buffer_source_node.cc b/src/cobalt/audio/audio_buffer_source_node.cc index 8481b6b..654e6a8 100644 --- a/src/cobalt/audio/audio_buffer_source_node.cc +++ b/src/cobalt/audio/audio_buffer_source_node.cc
@@ -31,8 +31,9 @@ // numberOfInputs : 0 // numberOfOutputs : 1 -AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context) - : AudioNode(context), +AudioBufferSourceNode::AudioBufferSourceNode( + script::EnvironmentSettings* settings, AudioContext* context) + : AudioNode(settings, context), task_runner_(base::MessageLoop::current()->task_runner()), state_(kNone), read_index_(0),
diff --git a/src/cobalt/audio/audio_buffer_source_node.h b/src/cobalt/audio/audio_buffer_source_node.h index a3623e0..1731aef 100644 --- a/src/cobalt/audio/audio_buffer_source_node.h +++ b/src/cobalt/audio/audio_buffer_source_node.h
@@ -24,6 +24,7 @@ #include "cobalt/base/tokens.h" #include "cobalt/media/base/interleaved_sinc_resampler.h" #include "cobalt/media/base/shell_audio_bus.h" +#include "cobalt/script/environment_settings.h" namespace cobalt { namespace audio { @@ -37,7 +38,8 @@ typedef media::ShellAudioBus ShellAudioBus; public: - explicit AudioBufferSourceNode(AudioContext* context); + AudioBufferSourceNode(script::EnvironmentSettings* settings, + AudioContext* context); // Web API: AudioBufferSourceNode //
diff --git a/src/cobalt/audio/audio_context.cc b/src/cobalt/audio/audio_context.cc index 7ba55a5..e909b72 100644 --- a/src/cobalt/audio/audio_context.cc +++ b/src/cobalt/audio/audio_context.cc
@@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/audio/audio_context.h" +#include <memory> + #include "base/callback.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/dom/dom_settings.h" @@ -24,7 +24,8 @@ namespace audio { AudioContext::AudioContext(script::EnvironmentSettings* settings) - : global_environment_( + : dom::EventTarget(settings), + global_environment_( base::polymorphic_downcast<dom::DOMSettings*>(settings) ->global_environment()), ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), @@ -36,7 +37,7 @@ current_time_(0.0f), audio_lock_(new AudioLock()), ALLOW_THIS_IN_INITIALIZER_LIST( - destination_(new AudioDestinationNode(this))), + destination_(new AudioDestinationNode(settings, this))), next_callback_id_(0), main_message_loop_(base::MessageLoop::current()->task_runner()) { DCHECK(main_message_loop_); @@ -68,10 +69,12 @@ kStorageTypeInterleaved)))); } -scoped_refptr<AudioBufferSourceNode> AudioContext::CreateBufferSource() { +scoped_refptr<AudioBufferSourceNode> AudioContext::CreateBufferSource( + script::EnvironmentSettings* settings) { DCHECK(main_message_loop_->BelongsToCurrentThread()); - return scoped_refptr<AudioBufferSourceNode>(new AudioBufferSourceNode(this)); + return scoped_refptr<AudioBufferSourceNode>( + new AudioBufferSourceNode(settings, this)); } void AudioContext::PreventGarbageCollection() {
diff --git a/src/cobalt/audio/audio_context.h b/src/cobalt/audio/audio_context.h index 26f8994..a4667bf 100644 --- a/src/cobalt/audio/audio_context.h +++ b/src/cobalt/audio/audio_context.h
@@ -83,7 +83,8 @@ // // The AudioBuffer is representing the decoded PCM audio data. typedef script::CallbackFunction<void( - const scoped_refptr<AudioBuffer>& decoded_data)> DecodeSuccessCallback; + const scoped_refptr<AudioBuffer>& decoded_data)> + DecodeSuccessCallback; typedef script::ScriptValue<DecodeSuccessCallback> DecodeSuccessCallbackArg; typedef DecodeSuccessCallbackArg::Reference DecodeSuccessCallbackReference; @@ -132,7 +133,8 @@ const DecodeErrorCallbackArg& error_handler); // Creates an AudioBufferSourceNode. - scoped_refptr<AudioBufferSourceNode> CreateBufferSource(); + scoped_refptr<AudioBufferSourceNode> CreateBufferSource( + script::EnvironmentSettings* settings); // Creates a new, empty AudioBuffer object. scoped_refptr<AudioBuffer> CreateBuffer(uint32 num_of_channels, uint32 length,
diff --git a/src/cobalt/audio/audio_context.idl b/src/cobalt/audio/audio_context.idl index eda8c5b..f62770a 100644 --- a/src/cobalt/audio/audio_context.idl +++ b/src/cobalt/audio/audio_context.idl
@@ -28,7 +28,7 @@ optional DecodeErrorCallback errorCallback); // AudioNode creation - AudioBufferSourceNode createBufferSource(); + [CallWith=EnvironmentSettings] AudioBufferSourceNode createBufferSource(); // AudioBuffer creation AudioBuffer createBuffer(unsigned long numOfChannels, unsigned long length,
diff --git a/src/cobalt/audio/audio_destination_node.cc b/src/cobalt/audio/audio_destination_node.cc index b728fbe..4107070 100644 --- a/src/cobalt/audio/audio_destination_node.cc +++ b/src/cobalt/audio/audio_destination_node.cc
@@ -32,8 +32,9 @@ // numberOfInputs : 1 // numberOfOutputs : 0 -AudioDestinationNode::AudioDestinationNode(AudioContext* context) - : AudioNode(context), +AudioDestinationNode::AudioDestinationNode( + script::EnvironmentSettings* settings, AudioContext* context) + : AudioNode(settings, context), message_loop_(base::MessageLoop::current()), max_channel_count_(kMaxChannelCount) { AudioLock::AutoLock lock(audio_lock());
diff --git a/src/cobalt/audio/audio_destination_node.h b/src/cobalt/audio/audio_destination_node.h index 9713e44..fd090c8 100644 --- a/src/cobalt/audio/audio_destination_node.h +++ b/src/cobalt/audio/audio_destination_node.h
@@ -23,6 +23,7 @@ #include "cobalt/audio/audio_helpers.h" #include "cobalt/audio/audio_node.h" #include "cobalt/media/base/shell_audio_bus.h" +#include "cobalt/script/environment_settings.h" namespace cobalt { namespace audio { @@ -39,7 +40,8 @@ typedef media::ShellAudioBus ShellAudioBus; public: - explicit AudioDestinationNode(AudioContext* context); + AudioDestinationNode(script::EnvironmentSettings* settings, + AudioContext* context); // Web API: AudioDestinationNode //
diff --git a/src/cobalt/audio/audio_node.cc b/src/cobalt/audio/audio_node.cc index 756f0ec..ed2cc42 100644 --- a/src/cobalt/audio/audio_node.cc +++ b/src/cobalt/audio/audio_node.cc
@@ -20,8 +20,10 @@ namespace cobalt { namespace audio { -AudioNode::AudioNode(AudioContext* context) - : audio_context_(context), +AudioNode::AudioNode(script::EnvironmentSettings* settings, + AudioContext* context) + : EventTarget(settings), + audio_context_(context), audio_lock_(context->audio_lock()), channel_count_(2), channel_count_mode_(kAudioNodeChannelCountModeMax),
diff --git a/src/cobalt/audio/audio_node.h b/src/cobalt/audio/audio_node.h index 4374112..38d67cf 100644 --- a/src/cobalt/audio/audio_node.h +++ b/src/cobalt/audio/audio_node.h
@@ -28,6 +28,7 @@ #include "cobalt/dom/dom_exception.h" #include "cobalt/dom/event_target.h" #include "cobalt/media/base/shell_audio_bus.h" +#include "cobalt/script/environment_settings.h" namespace cobalt { namespace audio { @@ -51,7 +52,7 @@ typedef media::ShellAudioBus ShellAudioBus; public: - explicit AudioNode(AudioContext* context); + AudioNode(script::EnvironmentSettings* settings, AudioContext* context); // Web API: AudioNode //
diff --git a/src/cobalt/audio/audio_node_input_output_test.cc b/src/cobalt/audio/audio_node_input_output_test.cc index 19cec61..c4bf0bb 100644 --- a/src/cobalt/audio/audio_node_input_output_test.cc +++ b/src/cobalt/audio/audio_node_input_output_test.cc
@@ -13,12 +13,14 @@ // limitations under the License. #include <math.h> + #include <memory> #include "cobalt/audio/audio_buffer_source_node.h" #include "cobalt/audio/audio_context.h" #include "cobalt/audio/audio_helpers.h" #include "cobalt/dom/dom_settings.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/window.h" #include "cobalt/script/global_environment.h" #include "cobalt/script/javascript_engine.h" @@ -39,8 +41,9 @@ typedef media::ShellAudioBus ShellAudioBus; public: - explicit AudioDestinationNodeMock(AudioContext* context) - : AudioNode(context) { + AudioDestinationNodeMock(script::EnvironmentSettings* settings, + AudioContext* context) + : AudioNode(settings, context) { AudioLock::AutoLock lock(audio_lock()); AddInput(new AudioNodeInput(this)); @@ -71,20 +74,18 @@ std::unique_ptr<ShellAudioBus> src_data, const AudioNodeChannelInterpretation& interpretation, ShellAudioBus* audio_bus, bool* silence) { - std::unique_ptr<script::EnvironmentSettings> environment_settings_ = - std::unique_ptr<script::EnvironmentSettings>(new dom::DOMSettings( - 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + dom::testing::StubEnvironmentSettings environment_settings; scoped_refptr<AudioContext> audio_context( - new AudioContext(environment_settings_.get())); + new AudioContext(&environment_settings)); scoped_refptr<AudioBufferSourceNode> source( - audio_context->CreateBufferSource()); + audio_context->CreateBufferSource(&environment_settings)); scoped_refptr<AudioBuffer> buffer( new AudioBuffer(audio_context->sample_rate(), std::move(src_data))); source->set_buffer(buffer); scoped_refptr<AudioDestinationNodeMock> destination( - new AudioDestinationNodeMock(audio_context.get())); + new AudioDestinationNodeMock(&environment_settings, audio_context.get())); destination->set_channel_interpretation(interpretation); source->Connect(destination, 0, 0, NULL); source->Start(0, 0, NULL); @@ -97,9 +98,8 @@ AudioNodeInputOutputTest() : engine_(script::JavaScriptEngine::CreateEngine()), global_environment_(engine_->CreateGlobalEnvironment()) { - environment_settings_ = - std::unique_ptr<script::EnvironmentSettings>(new dom::DOMSettings( - 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + environment_settings_ = std::unique_ptr<script::EnvironmentSettings>( + new dom::testing::StubEnvironmentSettings); global_environment_->CreateGlobalObject(); } @@ -118,13 +118,13 @@ return environment_settings_.get(); } + protected: + base::MessageLoop message_loop_; + private: std::unique_ptr<script::JavaScriptEngine> engine_; scoped_refptr<script::GlobalEnvironment> global_environment_; std::unique_ptr<script::EnvironmentSettings> environment_settings_; - - protected: - base::MessageLoop message_loop_; }; TEST_F(AudioNodeInputOutputTest, StereoToStereoSpeakersLayoutTest) { @@ -697,7 +697,7 @@ std::unique_ptr<ShellAudioBus> src_data_1(new ShellAudioBus( kNumOfSrcChannels, kNumOfFrames_1, src_data_in_float_1)); scoped_refptr<AudioBufferSourceNode> source_1( - audio_context->CreateBufferSource()); + audio_context->CreateBufferSource(environment_settings())); scoped_refptr<AudioBuffer> buffer_1( new AudioBuffer(audio_context->sample_rate(), std::move(src_data_1))); @@ -715,13 +715,14 @@ std::unique_ptr<ShellAudioBus> src_data_2(new ShellAudioBus( kNumOfSrcChannels, kNumOfFrames_2, src_data_in_float_2)); scoped_refptr<AudioBufferSourceNode> source_2( - audio_context->CreateBufferSource()); + audio_context->CreateBufferSource(environment_settings())); scoped_refptr<AudioBuffer> buffer_2( new AudioBuffer(audio_context->sample_rate(), std::move(src_data_2))); source_2->set_buffer(buffer_2); scoped_refptr<AudioDestinationNodeMock> destination( - new AudioDestinationNodeMock(audio_context.get())); + new AudioDestinationNodeMock(environment_settings(), + audio_context.get())); destination->set_channel_interpretation(kInterpretation); source_1->Connect(destination, 0, 0, NULL); source_2->Connect(destination, 0, 0, NULL); @@ -980,11 +981,12 @@ scoped_refptr<AudioContext> audio_context( new AudioContext(environment_settings())); scoped_refptr<AudioBufferSourceNode> source( - audio_context->CreateBufferSource()); + audio_context->CreateBufferSource(environment_settings())); source->set_buffer(buffer); scoped_refptr<AudioDestinationNodeMock> destination( - new AudioDestinationNodeMock(audio_context.get())); + new AudioDestinationNodeMock(environment_settings(), + audio_context.get())); destination->set_channel_interpretation(kInterpretation); source->Connect(destination, 0, 0, NULL); source->Start(0, 0, NULL);
diff --git a/src/cobalt/base/circular_buffer_shell_unittest.cc b/src/cobalt/base/circular_buffer_shell_unittest.cc index ea1c0cf..9c90eaf 100644 --- a/src/cobalt/base/circular_buffer_shell_unittest.cc +++ b/src/cobalt/base/circular_buffer_shell_unittest.cc
@@ -251,7 +251,7 @@ EXPECT_EQ(10, bytes_peeked); IsSame(UNSET_DATA, destination, 9); - IsSame(UNSET_DATA + 9 + bytes_peeked, destination + 9 + bytes_peeked, + IsSame(&UNSET_DATA[9] + bytes_peeked, destination + 9 + bytes_peeked, sizeof(UNSET_DATA) - 9 - bytes_peeked); IsSame(kTestData, destination + 9, 10); peek_offset += bytes_peeked; @@ -264,7 +264,7 @@ EXPECT_EQ(7, bytes_peeked); IsSame(UNSET_DATA, destination, 9); - IsSame(UNSET_DATA + 9 + bytes_peeked, destination + 9 + bytes_peeked, + IsSame(&UNSET_DATA[9] + bytes_peeked, destination + 9 + bytes_peeked, sizeof(UNSET_DATA) - 9 - bytes_peeked); IsSame(kTestData + peek_offset, destination + 9, bytes_peeked); peek_offset += bytes_peeked; @@ -277,7 +277,7 @@ EXPECT_EQ(3, bytes_peeked); IsSame(UNSET_DATA, destination, 9); - IsSame(UNSET_DATA + 9 + bytes_peeked, destination + 9 + bytes_peeked, + IsSame(&UNSET_DATA[9] + bytes_peeked, destination + 9 + bytes_peeked, sizeof(UNSET_DATA) - 9 - bytes_peeked); IsSame(kTestData + peek_offset, destination + 9, bytes_peeked); peek_offset += bytes_peeked;
diff --git a/src/cobalt/base/debugger_hooks.h b/src/cobalt/base/debugger_hooks.h index b0ac836..f555dd1 100644 --- a/src/cobalt/base/debugger_hooks.h +++ b/src/cobalt/base/debugger_hooks.h
@@ -23,6 +23,13 @@ // directly access the DebugModule. class DebuggerHooks { public: + // Indicates whether an asynchronous task will run at most once or if it might + // run multiple times. + enum class AsyncTaskFrequency { + kOneshot, + kRecurring, + }; + // Record the JavaScript stack on the WebModule thread at the point a task is // initiated that will run at a later time (on the same thread), allowing it // to be seen as the originator when breaking in the asynchronous task. @@ -34,43 +41,45 @@ // |name| is a user-visible label shown in the debugger to identify what the // asynchronous stack trace is. // - // |recurring| is true if the task may be run more than once. - virtual void AsyncTaskScheduled(void* task, const std::string& name, - bool recurring = false) const = 0; + // |frequency| whether the task runs at most once or might run multiple times. + // If kOneshot then the task will be implicitly canceled after it is finished, + // and if kRecurring then it must be explicitly canceled. + virtual void AsyncTaskScheduled(const void* task, const std::string& name, + AsyncTaskFrequency frequency) const = 0; // Inform the debugger that a scheduled task is starting to run. - virtual void AsyncTaskStarted(void* task) const = 0; + virtual void AsyncTaskStarted(const void* task) const = 0; // Inform the debugger that a scheduled task has finished running. - virtual void AsyncTaskFinished(void* task) const = 0; + virtual void AsyncTaskFinished(const void* task) const = 0; // Inform the debugger that a scheduled task will no longer be run, and that // it may free any resources associated with it. - virtual void AsyncTaskCanceled(void* task) const = 0; + virtual void AsyncTaskCanceled(const void* task) const = 0; }; // Helper to start & finish async tasks using RAII. class ScopedAsyncTask { public: - ScopedAsyncTask(const DebuggerHooks& debugger_hooks, void* task) + ScopedAsyncTask(DebuggerHooks* debugger_hooks, const void* task) : debugger_hooks_(debugger_hooks), task_(task) { - debugger_hooks_.AsyncTaskStarted(task_); + debugger_hooks_->AsyncTaskStarted(task_); } - ~ScopedAsyncTask() { debugger_hooks_.AsyncTaskFinished(task_); } + ~ScopedAsyncTask() { debugger_hooks_->AsyncTaskFinished(task_); } private: - const DebuggerHooks& debugger_hooks_; - void* const task_; + DebuggerHooks* debugger_hooks_; + const void* const task_; }; // Null implementation for gold builds and tests where there is no debugger. class NullDebuggerHooks : public DebuggerHooks { public: - void AsyncTaskScheduled(void* task, const std::string& name, - bool recurring) const override {} - void AsyncTaskStarted(void* task) const override {} - void AsyncTaskFinished(void* task) const override {} - void AsyncTaskCanceled(void* task) const override {} + void AsyncTaskScheduled(const void* task, const std::string& name, + AsyncTaskFrequency frequency) const override {} + void AsyncTaskStarted(const void* task) const override {} + void AsyncTaskFinished(const void* task) const override {} + void AsyncTaskCanceled(const void* task) const override {} }; } // namespace base
diff --git a/src/cobalt/base/instance_counter.h b/src/cobalt/base/instance_counter.h new file mode 100644 index 0000000..ccf343e --- /dev/null +++ b/src/cobalt/base/instance_counter.h
@@ -0,0 +1,50 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COBALT_BASE_INSTANCE_COUNTER_H_ +#define COBALT_BASE_INSTANCE_COUNTER_H_ + +#include "base/logging.h" + +#if defined(COBALT_BUILD_TYPE_GOLD) + +#define DECLARE_INSTANCE_COUNTER(class_name) +#define ON_INSTANCE_CREATED(class_name) +#define ON_INSTANCE_RELEASED(class_name) + +#else // defined(COBALT_BUILD_TYPE_GOLD) + +#define DECLARE_INSTANCE_COUNTER(class_name) \ + namespace { \ + SbAtomic32 s_##class_name##_instance_count = 0; \ + } + +#define ON_INSTANCE_CREATED(class_name) \ + { \ + LOG(INFO) << "New instance of " << #class_name << " is created. We have " \ + << (SbAtomicNoBarrier_Increment( \ + &s_##class_name##_instance_count, 1)) \ + << " instances in total."; \ + } + +#define ON_INSTANCE_RELEASED(class_name) \ + { \ + LOG(INFO) << "Instance of " << #class_name << " is released. We have " \ + << (SbAtomicNoBarrier_Increment( \ + &s_##class_name##_instance_count, -1)) \ + << " instances in total."; \ + } +#endif // defined(COBALT_BUILD_TYPE_GOLD) + +#endif // COBALT_BASE_INSTANCE_COUNTER_H_
diff --git a/src/cobalt/base/wrap_main_starboard.h b/src/cobalt/base/wrap_main_starboard.h index 7ff43f1..49e6c0d 100644 --- a/src/cobalt/base/wrap_main_starboard.h +++ b/src/cobalt/base/wrap_main_starboard.h
@@ -115,7 +115,8 @@ #if SB_API_VERSION >= 8 case kSbEventTypeWindowSizeChanged: #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) case kSbEventTypeOnScreenKeyboardShown: case kSbEventTypeOnScreenKeyboardHidden: case kSbEventTypeOnScreenKeyboardFocused: @@ -123,10 +124,11 @@ #if SB_API_VERSION >= 11 case kSbEventTypeOnScreenKeyboardSuggestionsUpdated: #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) case kSbEventTypeAccessibilityCaptionSettingsChanged: -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) event_function(event); break; }
diff --git a/src/cobalt/bindings/shared/idl_conditional_macros.h b/src/cobalt/bindings/shared/idl_conditional_macros.h index c4ee247..a20612b 100644 --- a/src/cobalt/bindings/shared/idl_conditional_macros.h +++ b/src/cobalt/bindings/shared/idl_conditional_macros.h
@@ -23,16 +23,18 @@ // Conditionals that are dependent on Starboard feature macros that get defined // in header files. -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // This is used to conditionally define the On Screen Keyboard interface and // attribute. #define COBALT_ENABLE_ON_SCREEN_KEYBOARD -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) #if SB_API_VERSION >= 11 // This is used to conditionally define setMaxVideoCapabilities() in // HTMLVideoElement. #define COBALT_ENABLE_SET_MAX_VIDEO_CAPABILITIES -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= 11 #endif // COBALT_BINDINGS_SHARED_IDL_CONDITIONAL_MACROS_H_
diff --git a/src/cobalt/bindings/testing/bindings_test_base.h b/src/cobalt/bindings/testing/bindings_test_base.h index eedc6ba..f8a0ba8 100644 --- a/src/cobalt/bindings/testing/bindings_test_base.h +++ b/src/cobalt/bindings/testing/bindings_test_base.h
@@ -19,6 +19,7 @@ #include <string> #include "base/memory/ref_counted.h" +#include "base/test/scoped_task_environment.h" #include "cobalt/bindings/testing/window.h" #include "cobalt/script/environment_settings.h" #include "cobalt/script/global_environment.h" @@ -87,6 +88,7 @@ Window* window() { return window_.get(); } protected: + base::test::ScopedTaskEnvironment task_env_; const std::unique_ptr<script::EnvironmentSettings> environment_settings_; const std::unique_ptr<script::JavaScriptEngine> engine_; const scoped_refptr<script::GlobalEnvironment> global_environment_;
diff --git a/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template b/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template index 037df6f..5c5741f 100644 --- a/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template +++ b/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template
@@ -70,7 +70,8 @@ // JSValue -> IDL enum algorithm described here: // http://heycam.github.io/webidl/#es-enumeration // 1. Let S be the result of calling ToString(V). - v8::MaybeLocal<v8::String> maybe_string = value->ToString(isolate->GetCurrentContext()); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + v8::MaybeLocal<v8::String> maybe_string = value->ToString(context); v8::Local<v8::String> string; if (!maybe_string.ToLocal(&string)) { exception_state->SetSimpleException(cobalt::script::kConvertToEnumFailed); @@ -81,7 +82,7 @@ // 3. Return the enumeration value of type E that is equal to S. {% for value, idl_value in value_pairs %} {{-" else " if not loop.first}} if ( - NewInternalString(isolate, "{{idl_value}}")->Equals(value)) + NewInternalString(isolate, "{{idl_value}}")->Equals(context, value).ToChecked()) { *out_enum = {{namespace}}::{{value}}; }
diff --git a/src/cobalt/bindings/v8c/templates/interface.cc.template b/src/cobalt/bindings/v8c/templates/interface.cc.template index 2b29c85..29db60a 100644 --- a/src/cobalt/bindings/v8c/templates/interface.cc.template +++ b/src/cobalt/bindings/v8c/templates/interface.cc.template
@@ -129,7 +129,8 @@ void IndexedPropertyGetterCallback( uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { - v8::Local<v8::String> as_string = v8::Integer::New(info.GetIsolate(), index)->ToString(); + v8::Local<v8::String> as_string = (v8::Integer::New(info.GetIsolate(), index)->ToString( + info.GetIsolate()->GetCurrentContext())).ToLocalChecked(); NamedPropertyGetterCallback(as_string, info); } {% endif %} @@ -218,7 +219,8 @@ uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { - v8::Local<v8::String> as_string = v8::Integer::New(info.GetIsolate(), index)->ToString(); + v8::Local<v8::String> as_string = (v8::Integer::New(info.GetIsolate(), index)->ToString( + info.GetIsolate()->GetCurrentContext())).ToLocalChecked(); NamedPropertySetterCallback(as_string, value, info); } {% endif %} @@ -251,7 +253,8 @@ uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) { v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::String> as_string = v8::Integer::New(info.GetIsolate(), index)->ToString(); + v8::Local<v8::String> as_string = (v8::Integer::New(info.GetIsolate(), index)->ToString( + info.GetIsolate()->GetCurrentContext())).ToLocalChecked(); NamedPropertyDeleterCallback(as_string, info); } {% endif %} @@ -287,12 +290,13 @@ void IndexedPropertyEnumeratorCallback( const v8::PropertyCallbackInfo<v8::Array>& info) { v8::Isolate* isolate = info.GetIsolate(); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); v8::Local<v8::Object> object = info.Holder(); {{ get_impl_class_instance(impl_class) }} const uint32_t length = impl->length(); v8::Local<v8::Array> array = v8::Array::New(isolate, length); for (uint32_t i = 0; i < length; ++i) { - array->Set(i, v8::Integer::New(isolate, i)); + array->Set(context, i, v8::Integer::New(isolate, i)).Check(); } info.GetReturnValue().Set(array); } @@ -828,7 +832,8 @@ // Intentionally not an |EntryScope|, since the context doesn't exist yet. v8::Isolate::Scope isolate_scope(isolate_); v8::HandleScope handle_scope(isolate_); - v8::Local<v8::ObjectTemplate> global_object_template = {{binding_class}}::GetTemplate(isolate_)->InstanceTemplate(); + v8::Local<v8::ObjectTemplate> global_object_template = + {{binding_class}}::GetTemplate(isolate_)->InstanceTemplate(); v8::Local<v8::Context> context = v8::Context::New(isolate_, nullptr, global_object_template); @@ -845,7 +850,8 @@ v8::Local<v8::Object> global_object = context->Global(); new WrapperPrivate(isolate_, global_interface, global_object); - auto actual_global_object = global_object->GetPrototype()->ToObject(); + auto actual_global_object = global_object->GetPrototype()-> + ToObject(context).ToLocalChecked(); new WrapperPrivate(isolate_, global_interface, actual_global_object); {% for interface in all_interfaces %} @@ -869,7 +875,8 @@ void GlobalEnvironment::CreateGlobalObject<{{impl_class}}>( const scoped_refptr<{{impl_class}}>& global_interface, EnvironmentSettings* environment_settings) { - base::polymorphic_downcast<v8c::V8cGlobalEnvironment*>(this)->CreateGlobalObject(global_interface, environment_settings); + base::polymorphic_downcast<v8c::V8cGlobalEnvironment*>(this)-> + CreateGlobalObject(global_interface, environment_settings); } } // namespace script
diff --git a/src/cobalt/bindings/v8c/templates/macros.cc.template b/src/cobalt/bindings/v8c/templates/macros.cc.template index 67b53cf..ce11720 100644 --- a/src/cobalt/bindings/v8c/templates/macros.cc.template +++ b/src/cobalt/bindings/v8c/templates/macros.cc.template
@@ -386,6 +386,7 @@ {% macro overload_resolution_implementation( overload_context, bound_function_prefix) %} v8::Isolate* isolate = info.GetIsolate(); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); switch(info.Length()) { {% for length, distinguishing_argument_index, resolution_tests in @@ -399,7 +400,7 @@ WrapperFactory* wrapper_factory = V8cGlobalEnvironment::GetFromIsolate(isolate)->wrapper_factory(); v8::Local<v8::Object> object; if (arg->IsObject()) { - object = arg->ToObject(); + object = arg->ToObject(context).ToLocalChecked(); } {% endif %} {% for test, overload in resolution_tests %}
diff --git a/src/cobalt/black_box_tests/black_box_tests.py b/src/cobalt/black_box_tests/black_box_tests.py index 108972e..c209f91 100644 --- a/src/cobalt/black_box_tests/black_box_tests.py +++ b/src/cobalt/black_box_tests/black_box_tests.py
@@ -60,14 +60,8 @@ _device_params = None # Binding address used to create the test server. _binding_address = None - - -def GetDeviceParams(): - - global _device_params - _device_params = cobalt_runner.GetDeviceParamsFromCommandLine() - # Keep other modules from seeing these args - sys.argv = sys.argv[:1] +# Port used to create the web platform test http server. +_wpt_http_port = None class BlackBoxTestCase(unittest.TestCase): @@ -100,9 +94,11 @@ def GetBindingAddress(self): return _binding_address + def GetWptHttpPort(self): + return _wpt_http_port + def LoadTests(platform, config, device_id, out_directory): - launcher = abstract_launcher.LauncherFactory( platform, 'cobalt', @@ -127,19 +123,38 @@ class BlackBoxTests(object): """Helper class to run all black box tests and return results.""" - def __init__(self, test_name=None, proxy_port_number=None): + def __init__(self, server_binding_address, proxy_address=None, + proxy_port=None, test_name=None, wpt_http_port=None): logging.basicConfig(level=logging.DEBUG) - GetDeviceParams() - # Port number used to create the proxy server. If the --proxy target param - # is not set, a random free port is used. - if proxy_port_number is None: - proxy_port_number = str(self.GetUnusedPort(_binding_address)) - _device_params.target_params.append('--proxy=%s:%s' % (_binding_address, - proxy_port_number)) + # Setup global variables used by test cases + global _device_params + _device_params = cobalt_runner.GetDeviceParamsFromCommandLine() + # Keep other modules from seeing these args + sys.argv = sys.argv[:1] + global _binding_address + _binding_address = server_binding_address + # Port used to create the web platform test http server. If not specified, + # a random free port is used. + if wpt_http_port is None: + wpt_http_port = str(self.GetUnusedPort([server_binding_address])) + global _wpt_http_port + _wpt_http_port = wpt_http_port + _device_params.target_params.append( + '--web-platform-test-server=http://web-platform.test:%s' % + wpt_http_port) + # Port used to create the proxy server. If not specified, a random free + # port is used. + if proxy_port is None: + proxy_port = str(self.GetUnusedPort([server_binding_address])) + if proxy_address is None: + proxy_address = server_binding_address + _device_params.target_params.append('--proxy=%s:%s' % + (proxy_address, proxy_port)) + + self.proxy_port = proxy_port self.test_name = test_name - self.proxy_port_number = proxy_port_number # Test domains used in web platform tests to be resolved to the server # binding address. @@ -151,14 +166,14 @@ 'xn--n8j6ds53lwwkrqhv28a.web-platform.test', 'xn--lve-6lad.web-platform.test' ] - self.host_resolve_map = dict([(host, _binding_address) for host in hosts]) + self.host_resolve_map = dict([(host, server_binding_address) for host in hosts]) def Run(self): - if self.proxy_port_number == '-1': + if self.proxy_port == '-1': return 1 - logging.info('Using proxy port number: %s', self.proxy_port_number) + logging.info('Using proxy port: %s', self.proxy_port) - with ProxyServer(port=self.proxy_port_number, + with ProxyServer(port=self.proxy_port, host_resolve_map=self.host_resolve_map): if self.test_name: suite = unittest.TestLoader().loadTestsFromModule( @@ -171,42 +186,66 @@ verbosity=0, stream=sys.stdout).run(suite).wasSuccessful() return return_code - def GetUnusedPort(self, machine_address): - """Find a free port on the machine address by pinging with socket.""" - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + def GetUnusedPort(self, addresses): + """Find a free port on the list of addresses by pinging with sockets.""" + SOCKET_SUCCESS = 0 + + if not addresses: + logging.error('Can not find unused port on invalid addresses.') + return -1 + + socks = [] + for address in addresses: + socks.append((address, socket.socket(socket.AF_INET, socket.SOCK_STREAM))) try: - for i in range(1, _PORT_SELECTION_RETRY_LIMIT): - port_number = random.randint(_PORT_SELECTION_RANGE[0], - _PORT_SELECTION_RANGE[1]) - result = sock.connect_ex((machine_address, port_number)) - if result != 0: - return port_number - if i == _PORT_SELECTION_RETRY_LIMIT - 1: - logging.error( - 'Can not find unused port on target machine within %s attempts.', - _PORT_SELECTION_RETRY_LIMIT) - return -1 + for _ in range(_PORT_SELECTION_RETRY_LIMIT): + port = random.randint(_PORT_SELECTION_RANGE[0], _PORT_SELECTION_RANGE[1]) + unused = True + for sock in socks: + result = sock[1].connect_ex((sock[0], port)) + if result == SOCKET_SUCCESS: + ununsed = False + break + if unused: + return port + logging.error( + 'Can not find unused port on addresses within %s attempts.' % + _PORT_SELECTION_RETRY_LIMIT) + return -1 finally: - sock.close() + for sock in socks: + sock[1].close() def main(): parser = argparse.ArgumentParser() - parser.add_argument('--test_name', - help=('Name of test to be run. If not specified, all ' - 'tests are run.')) parser.add_argument('--server_binding_address', default='127.0.0.1', help='Binding address used to create the test server.') - parser.add_argument('--proxy_port_number', - help=('Port number used to create the proxy http server' - 'that all black box tests are run through. If not' + parser.add_argument('--proxy_address', + default=None, + help=('Address to the proxy server that all black box' + 'tests are run through. If not specified, the' + 'server binding address is used.')) + parser.add_argument('--proxy_port', + default=None, + help=('Port used to create the proxy server that all' + 'black box tests are run through. If not' 'specified, a random free port is used.')) + parser.add_argument('--test_name', + default=None, + help=('Name of test to be run. If not specified, all ' + 'tests are run.')) + parser.add_argument('--wpt_http_port', + default=None, + help=('Port used to create the web platform test http' + 'server. If not specified, a random free port is' + 'used.')) args, _ = parser.parse_known_args() - global _binding_address - _binding_address = args.server_binding_address - test_object = BlackBoxTests(args.test_name, args.proxy_port_number) + test_object = BlackBoxTests(args.server_binding_address, args.proxy_address, + args.proxy_port, args.test_name, + args.wpt_http_port) sys.exit(test_object.Run())
diff --git a/src/cobalt/black_box_tests/testdata/web_debugger.html b/src/cobalt/black_box_tests/testdata/web_debugger.html index 2ef6a09..aee0e79 100644 --- a/src/cobalt/black_box_tests/testdata/web_debugger.html +++ b/src/cobalt/black_box_tests/testdata/web_debugger.html
@@ -3,6 +3,7 @@ <head> <title>Connect to web debugger</title> <script src='black_box_js_test_utils.js'></script> + <script src='web_debugger_test_utils.js'></script> </head> <body>
diff --git a/src/cobalt/black_box_tests/testdata/web_debugger_test_utils.js b/src/cobalt/black_box_tests/testdata/web_debugger_test_utils.js new file mode 100644 index 0000000..2b70459 --- /dev/null +++ b/src/cobalt/black_box_tests/testdata/web_debugger_test_utils.js
@@ -0,0 +1,129 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// This is the function we set the breakpoint on. +function asyncBreak() { + foo = "bar"; +} + +// Tests AsyncTask reporting in WindowTimers. +function testSetTimeout() { + asyncA(asyncBreak); +} + +function asyncA(f) { + setTimeout(function timeoutA() { asyncB(f) }, 1); +} + +function asyncB(f) { + setTimeout(function timeoutB() { asyncC(f) }, 1); +} + +function asyncC(f) { + f(); +} + +// Tests AsyncTask reporting in a Promise using its 'then' method. +function testPromise() { + let p = makePromise(); + waitPromise(p); +} + +function makePromise() { + return new Promise(function promiseExecutor(resolve, reject) { + setTimeout(function promiseTimeout() { + resolve(); + }, 1) + }); +} + +function waitPromise(p) { + p.then(promiseThen); +} + +function promiseThen() { + asyncBreak(); +} + +// Tests AsyncTask reporting in a JS async function that awaits a promise. +function testAsyncFunction() { + let p = makePromise(); + asyncAwait(p); +} + +async function asyncAwait(p) { + await p; + asyncBreak(); +} + +// Tests AsyncTask reporting in EventTarget. +function testXHR(url) { + doXHR(url); +} + +function doXHR(url) { + let xhr = new XMLHttpRequest(); + xhr.onload = function fileLoaded() { + asyncBreak(); + } + xhr.open('GET', url); + xhr.send(); +} + +// Tests AsyncTask reporting in a MutationObserver. +function testMutate() { + let target = document.getElementById('test'); + let config = {attributes: true, childList: true, subtree: true}; + let observer = new MutationObserver(mutationCallback); + observer.observe(target, config); + doSetAttribute(target, 'foo', 'bar'); +} + +function mutationCallback(mutationsList, observer) { + asyncBreak(); +} + +function doSetAttribute(node, attr, value) { + node.setAttribute(attr, value); +} + +function testAnimationFrame() { + doRequestAnimationFrame(); +} + +function doRequestAnimationFrame() { + window.requestAnimationFrame(function animationFrameCallback() { + asyncBreak(); + }); +} + +// Tests AsyncTask reporting in a MediaSource (that uses an EventQueue). +function testMediaSource(){ + let elem = document.createElement('video'); + let ms = new MediaSource; + setSourceListener(ms); + attachMediaSource(elem, ms); +} + +function setSourceListener(source) { + source.addEventListener('sourceopen', function sourceOpenCallback() { + asyncBreak(); + }); +} + +function attachMediaSource(elem, ms) { + let url = window.URL.createObjectURL(ms); + elem.src = url; +}
diff --git a/src/cobalt/black_box_tests/tests/web_debugger.py b/src/cobalt/black_box_tests/tests/web_debugger.py index e170032..68553c2 100644 --- a/src/cobalt/black_box_tests/tests/web_debugger.py +++ b/src/cobalt/black_box_tests/tests/web_debugger.py
@@ -49,6 +49,17 @@ super(DebuggerCommandError, self).__init__(code + error['message']) +class JavaScriptError(Exception): + """Exception when a JavaScript exception occurs in an evaluation.""" + + def __init__(self, exception_details): + # All the fields we care about are optional, so gracefully fallback. + ex = exception_details.get('exception', {}) + fallback = ex.get('className', 'Unknown error') + ' (No description)' + msg = ex.get('description', fallback) + super(JavaScriptError, self).__init__(msg) + + class DebuggerConnection(object): """Connection to debugger over a WebSocket. @@ -164,15 +175,23 @@ def evaluate_js(self, expression): """Helper for the 'Runtime.evaluate' command to run some JavaScript.""" - return self.run_command('Runtime.evaluate', { + response = self.run_command('Runtime.evaluate', { 'contextId': self.context_id, 'expression': expression, }) + if 'exceptionDetails' in response['result']: + raise JavaScriptError(response['result']['exceptionDetails']) + return response['result'] class WebDebuggerTest(black_box_tests.BlackBoxTestCase): """Test interaction with the web debugger over a WebSocket.""" + def setUpWith(self, cm): + val = cm.__enter__() + self.addCleanup(cm.__exit__, None, None, None) + return val + def setUp(self): platform_vars = self.platform_config.GetVariables(self.device_params.config) if platform_vars['javascript_engine'] != 'v8': @@ -182,8 +201,16 @@ if not cobalt_vars['enable_debugger']: self.skipTest('DevTools is disabled on this platform') - def create_debugger_connection(self, runner): - devtools_url = runner.GetCval('Cobalt.Server.DevTools') + self.server = self.setUpWith( + ThreadedWebServer(binding_address=self.GetBindingAddress())) + url = self.server.GetURL(file_name='testdata/web_debugger.html') + self.runner = self.setUpWith(self.CreateCobaltRunner(url=url)) + self.debugger = self.setUpWith(self.create_debugger_connection()) + self.runner.WaitForJSTestsSetup() + self.debugger.enable_runtime() + + def create_debugger_connection(self): + devtools_url = self.runner.GetCval('Cobalt.Server.DevTools') parts = list(urlparse.urlsplit(devtools_url)) parts[0] = 'ws' # scheme parts[2] = '/devtools/page/cobalt' # path @@ -191,170 +218,323 @@ return DebuggerConnection(ws_url) def test_runtime(self): - with ThreadedWebServer(binding_address=self.GetBindingAddress()) as server: - url = server.GetURL(file_name='testdata/web_debugger.html') - with self.CreateCobaltRunner(url=url) as runner: - with self.create_debugger_connection(runner) as debugger: - runner.WaitForJSTestsSetup() - debugger.enable_runtime() + # Evaluate a simple expression. + eval_result = self.debugger.evaluate_js('6 * 7') + self.assertEqual(42, eval_result['result']['value']) - # Evaluate a simple expression. - eval_response = debugger.evaluate_js('6 * 7') - self.assertEqual(42, eval_response['result']['result']['value']) + # Set an attribute and read it back w/ WebDriver. + self.debugger.evaluate_js( + 'document.body.setAttribute("web_debugger", "tested")') + self.assertEqual( + 'tested', + self.runner.UniqueFind('body').get_attribute('web_debugger')) - # Set an attribute and read it back w/ WebDriver. - debugger.evaluate_js( - 'document.body.setAttribute("web_debugger", "tested")') - self.assertEqual( - 'tested', - runner.UniqueFind('body').get_attribute('web_debugger')) + # Log to console, and check we get the console event. + self.debugger.evaluate_js('console.log("hello")') + console_event = self.debugger.wait_event('Runtime.consoleAPICalled') + self.assertEqual('hello', console_event['params']['args'][0]['value']) - # Log to console, and check we get the console event. - debugger.evaluate_js('console.log("hello")') - console_event = debugger.wait_event('Runtime.consoleAPICalled') - self.assertEqual('hello', console_event['params']['args'][0]['value']) - - # End the test. - debugger.evaluate_js('onEndTest()') - self.assertTrue(runner.JSTestsSucceeded()) + # End the test. + self.debugger.evaluate_js('onEndTest()') + self.assertTrue(self.runner.JSTestsSucceeded()) def test_dom(self): - with ThreadedWebServer(binding_address=self.GetBindingAddress()) as server: - url = server.GetURL(file_name='testdata/web_debugger.html') - with self.CreateCobaltRunner(url=url) as runner: - with self.create_debugger_connection(runner) as debugger: - runner.WaitForJSTestsSetup() - debugger.enable_runtime() - debugger.run_command('DOM.enable') + self.debugger.run_command('DOM.enable') - doc_response = debugger.run_command('DOM.getDocument') - doc_root = doc_response['result']['root'] - self.assertEqual('#document', doc_root['nodeName']) + doc_response = self.debugger.run_command('DOM.getDocument') + doc_root = doc_response['result']['root'] + self.assertEqual('#document', doc_root['nodeName']) - doc_url = doc_root['documentURL'] - # remove query params (cert_scope, etc.) - doc_url = doc_url.split('?')[0] - self.assertEqual(url, doc_url) + doc_url = doc_root['documentURL'] + # remove query params (cert_scope, etc.) + doc_url = doc_url.split('?')[0] + self.assertEqual(self.runner.url, doc_url) - # document: <html><head></head><body></body></html> - html_node = doc_root['children'][0] - body_node = html_node['children'][1] - self.assertEqual('BODY', body_node['nodeName']) + # document: <html><head></head><body></body></html> + html_node = doc_root['children'][0] + body_node = html_node['children'][1] + self.assertEqual('BODY', body_node['nodeName']) - # body: - # <h1><span>Web debugger</span></h1> - # <div#test> - # <div#A><div#A1/><div#A2/></div#A> - # <div#B/> - # </div#test> - debugger.run_command('DOM.requestChildNodes', { - 'nodeId': body_node['nodeId'], - 'depth': -1, # entire subtree - }) - child_nodes_event = debugger.wait_event('DOM.setChildNodes') + # body: + # <h1><span>Web debugger</span></h1> + # <div#test> + # <div#A><div#A1/><div#A2/></div#A> + # <div#B/> + # </div#test> + self.debugger.run_command('DOM.requestChildNodes', { + 'nodeId': body_node['nodeId'], + 'depth': -1, # entire subtree + }) + child_nodes_event = self.debugger.wait_event('DOM.setChildNodes') - h1 = child_nodes_event['params']['nodes'][0] - span = h1['children'][0] - text = span['children'][0] - self.assertEqual('H1', h1['nodeName']) - self.assertEqual('SPAN', span['nodeName']) - self.assertEqual('#text', text['nodeName']) - self.assertEqual('Web debugger', text['nodeValue']) + h1 = child_nodes_event['params']['nodes'][0] + span = h1['children'][0] + text = span['children'][0] + self.assertEqual('H1', h1['nodeName']) + self.assertEqual('SPAN', span['nodeName']) + self.assertEqual('#text', text['nodeName']) + self.assertEqual('Web debugger', text['nodeValue']) - test_div = child_nodes_event['params']['nodes'][1] - child_a = test_div['children'][0] - child_a1 = child_a['children'][0] - child_a2 = child_a['children'][1] - child_b = test_div['children'][1] - self.assertEqual(2, test_div['childNodeCount']) - self.assertEqual(2, child_a['childNodeCount']) - self.assertEqual(0, child_b['childNodeCount']) - self.assertEqual(['id', 'test'], test_div['attributes']) - self.assertEqual(['id', 'A'], child_a['attributes']) - self.assertEqual(['id', 'A1'], child_a1['attributes']) - self.assertEqual(['id', 'A2'], child_a2['attributes']) - self.assertEqual(['id', 'B'], child_b['attributes']) - self.assertEqual([], child_b['children']) + test_div = child_nodes_event['params']['nodes'][1] + child_a = test_div['children'][0] + child_a1 = child_a['children'][0] + child_a2 = child_a['children'][1] + child_b = test_div['children'][1] + self.assertEqual(2, test_div['childNodeCount']) + self.assertEqual(2, child_a['childNodeCount']) + self.assertEqual(0, child_b['childNodeCount']) + self.assertEqual(['id', 'test'], test_div['attributes']) + self.assertEqual(['id', 'A'], child_a['attributes']) + self.assertEqual(['id', 'A1'], child_a1['attributes']) + self.assertEqual(['id', 'A2'], child_a2['attributes']) + self.assertEqual(['id', 'B'], child_b['attributes']) + self.assertEqual([], child_b['children']) - # Repeat, but only to depth 2 - not reporting children of A & B. - debugger.run_command('DOM.requestChildNodes', { - 'nodeId': body_node['nodeId'], - 'depth': 2, - }) - child_nodes_event = debugger.wait_event('DOM.setChildNodes') + # Repeat, but only to depth 2 - not reporting children of A & B. + self.debugger.run_command('DOM.requestChildNodes', { + 'nodeId': body_node['nodeId'], + 'depth': 2, + }) + child_nodes_event = self.debugger.wait_event('DOM.setChildNodes') - test_div = child_nodes_event['params']['nodes'][1] - child_a = test_div['children'][0] - child_b = test_div['children'][1] - self.assertFalse('children' in child_a) - self.assertFalse('children' in child_b) - self.assertEqual(2, test_div['childNodeCount']) - self.assertEqual(2, child_a['childNodeCount']) - self.assertEqual(0, child_b['childNodeCount']) - self.assertEqual(['id', 'test'], test_div['attributes']) - self.assertEqual(['id', 'A'], child_a['attributes']) - self.assertEqual(['id', 'B'], child_b['attributes']) + test_div = child_nodes_event['params']['nodes'][1] + child_a = test_div['children'][0] + child_b = test_div['children'][1] + self.assertFalse('children' in child_a) + self.assertFalse('children' in child_b) + self.assertEqual(2, test_div['childNodeCount']) + self.assertEqual(2, child_a['childNodeCount']) + self.assertEqual(0, child_b['childNodeCount']) + self.assertEqual(['id', 'test'], test_div['attributes']) + self.assertEqual(['id', 'A'], child_a['attributes']) + self.assertEqual(['id', 'B'], child_b['attributes']) - # Repeat, to default depth of 1 - not reporting children of "#test". - debugger.run_command('DOM.requestChildNodes', { - 'nodeId': body_node['nodeId'], - }) - child_nodes_event = debugger.wait_event('DOM.setChildNodes') + # Repeat, to default depth of 1 - not reporting children of "#test". + self.debugger.run_command('DOM.requestChildNodes', { + 'nodeId': body_node['nodeId'], + }) + child_nodes_event = self.debugger.wait_event('DOM.setChildNodes') - test_div = child_nodes_event['params']['nodes'][1] - self.assertFalse('children' in test_div) - self.assertEqual(2, test_div['childNodeCount']) - self.assertEqual(['id', 'test'], test_div['attributes']) + test_div = child_nodes_event['params']['nodes'][1] + self.assertFalse('children' in test_div) + self.assertEqual(2, test_div['childNodeCount']) + self.assertEqual(['id', 'test'], test_div['attributes']) - # Get the test div as a remote object, and request it as a node. - # This sends a 'DOM.setChildNodes' event for each node up to the root. - eval_result = debugger.evaluate_js('document.getElementById("test")') - node_response = debugger.run_command('DOM.requestNode', { - 'objectId': eval_result['result']['result']['objectId'], - }) - self.assertEqual(test_div['nodeId'], - node_response['result']['nodeId']) + # Get the test div as a remote object, and request it as a node. + # This sends a 'DOM.setChildNodes' event for each node up to the root. + eval_result = self.debugger.evaluate_js('document.getElementById("test")') + node_response = self.debugger.run_command('DOM.requestNode', { + 'objectId': eval_result['result']['objectId'], + }) + self.assertEqual(test_div['nodeId'], + node_response['result']['nodeId']) - # Event reporting the requested <div#test> - node_event = debugger.wait_event('DOM.setChildNodes') - self.assertEqual(test_div['nodeId'], - node_event['params']['nodes'][0]['nodeId']) - self.assertEqual(body_node['nodeId'], - node_event['params']['parentId']) + # Event reporting the requested <div#test> + node_event = self.debugger.wait_event('DOM.setChildNodes') + self.assertEqual(test_div['nodeId'], + node_event['params']['nodes'][0]['nodeId']) + self.assertEqual(body_node['nodeId'], + node_event['params']['parentId']) - # Event reporting the parent <body> - node_event = debugger.wait_event('DOM.setChildNodes') - self.assertEqual(body_node['nodeId'], - node_event['params']['nodes'][0]['nodeId']) - self.assertEqual(html_node['nodeId'], - node_event['params']['parentId']) + # Event reporting the parent <body> + node_event = self.debugger.wait_event('DOM.setChildNodes') + self.assertEqual(body_node['nodeId'], + node_event['params']['nodes'][0]['nodeId']) + self.assertEqual(html_node['nodeId'], + node_event['params']['parentId']) - # Event reporting the parent <html> - node_event = debugger.wait_event('DOM.setChildNodes') - self.assertEqual(html_node['nodeId'], - node_event['params']['nodes'][0]['nodeId']) - self.assertEqual(doc_root['nodeId'], node_event['params']['parentId']) + # Event reporting the parent <html> + node_event = self.debugger.wait_event('DOM.setChildNodes') + self.assertEqual(html_node['nodeId'], + node_event['params']['nodes'][0]['nodeId']) + self.assertEqual(doc_root['nodeId'], node_event['params']['parentId']) - # Round trip resolving test div to an object, then back to a node. - resolve_response = debugger.run_command('DOM.resolveNode', { - 'nodeId': test_div['nodeId'], - }) - node_response = debugger.run_command('DOM.requestNode', { - 'objectId': resolve_response['result']['object']['objectId'], - }) - self.assertEqual(test_div['nodeId'], - node_response['result']['nodeId']) + # Round trip resolving test div to an object, then back to a node. + resolve_response = self.debugger.run_command('DOM.resolveNode', { + 'nodeId': test_div['nodeId'], + }) + node_response = self.debugger.run_command('DOM.requestNode', { + 'objectId': resolve_response['result']['object']['objectId'], + }) + self.assertEqual(test_div['nodeId'], + node_response['result']['nodeId']) - # Event reporting the requested <div#test> - node_event = debugger.wait_event('DOM.setChildNodes') - self.assertEqual(test_div['nodeId'], - node_event['params']['nodes'][0]['nodeId']) - self.assertEqual(body_node['nodeId'], - node_event['params']['parentId']) - # Ignore the other two events reporting the parents. - node_event = debugger.wait_event('DOM.setChildNodes') - node_event = debugger.wait_event('DOM.setChildNodes') + # Event reporting the requested <div#test> + node_event = self.debugger.wait_event('DOM.setChildNodes') + self.assertEqual(test_div['nodeId'], + node_event['params']['nodes'][0]['nodeId']) + self.assertEqual(body_node['nodeId'], + node_event['params']['parentId']) + # Ignore the other two events reporting the parents. + node_event = self.debugger.wait_event('DOM.setChildNodes') + node_event = self.debugger.wait_event('DOM.setChildNodes') - # End the test. - debugger.evaluate_js('onEndTest()') - self.assertTrue(runner.JSTestsSucceeded()) + # End the test. + self.debugger.evaluate_js('onEndTest()') + self.assertTrue(self.runner.JSTestsSucceeded()) + + def assert_paused(self, expected_stacks): + """Checks that the debugger is paused at a breakpoint. + + Waits for the expected |Debugger.paused| event from hitting the breakpoint + and then asserts that the expected_stacks match the call stacks in that + event. Execution is always resumed before returning so that more JS can be + evaluated, as needed to continue or end the test. + + Args: + expected_stacks: A list of lists of strings with the expected function + names in the call stacks in a series of asynchronous executions. + """ + paused_event = self.debugger.wait_event('Debugger.paused') + try: + call_stacks = [] + # First the main stack where the breakpoint was hit. + call_frames = paused_event['params']['callFrames'] + call_stack = [frame['functionName'] for frame in call_frames] + call_stacks.append(call_stack) + # Then asynchronous stacks that preceeded the main stack. + async_trace = paused_event['params'].get('asyncStackTrace') + while async_trace: + call_frames = async_trace['callFrames'] + call_stack = [frame['functionName'] for frame in call_frames] + call_stacks.append(call_stack) + async_trace = async_trace.get('parent') + self.assertEqual(expected_stacks, call_stacks) + finally: + # We must resume in order to avoid hanging if something goes wrong. + self.debugger.run_command('Debugger.resume') + + def test_debugger_breakpoint(self): + self.debugger.run_command('Debugger.enable') + + # Get the ID and source of our JavaScript test utils. + script_id = '' + while not script_id: + script_event = self.debugger.wait_event('Debugger.scriptParsed') + script_url = script_event['params']['url'] + if script_url.endswith('web_debugger_test_utils.js'): + script_id = script_event['params']['scriptId'] + source_response = self.debugger.run_command('Debugger.getScriptSource', { + 'scriptId': script_id, + }) + script_source = source_response['result']['scriptSource'].splitlines() + + # Set a breakpoint on the asyncBreak() function. + line_number = next(n for n, l in enumerate(script_source) + if l.startswith('function asyncBreak')) + self.debugger.run_command('Debugger.setBreakpoint', { + 'location': { + 'scriptId': script_id, + 'lineNumber': line_number, + }, + }) + self.debugger.run_command('Debugger.setAsyncCallStackDepth', { + 'maxDepth': 99, + }) + + # Check the breakpoint within a SetTimeout() callback. + self.debugger.evaluate_js('testSetTimeout()') + self.assert_paused([ + [ + 'asyncBreak', + 'asyncC', + 'timeoutB', + ], + [ + 'asyncB', + 'timeoutA', + ], + [ + 'asyncA', + 'testSetTimeout', + '', # Anonymous function for the 'Runtime.evaluate' command. + ] + ]) + + # Check the breakpoint within a promise "then" after being resolved. + self.debugger.evaluate_js('testPromise()') + self.assert_paused([ + [ + 'asyncBreak', + 'promiseThen', + ], + [ + 'waitPromise', + 'testPromise', + '', # Anonymous function for the 'Runtime.evaluate' command. + ] + ]) + + # Check the breakpoint after async await for a promise to resolve. + self.debugger.evaluate_js('testAsyncFunction()') + self.assert_paused([ + [ + 'asyncBreak', + 'asyncAwait', + ], + [ + 'asyncAwait', + 'testAsyncFunction', + '', # Anonymous function for the 'Runtime.evaluate' command. + ] + ]) + + # Check the breakpoint within an XHR event handler. + self.debugger.evaluate_js('testXHR(window.location.href)') + self.assert_paused([ + [ + 'asyncBreak', + 'fileLoaded', + ], + [ + 'doXHR', + 'testXHR', + '', # Anonymous function for the 'Runtime.evaluate' command. + ] + ]) + + # Check the breakpoint within a MutationObserver. + self.debugger.evaluate_js('testMutate()') + self.assert_paused([ + [ + 'asyncBreak', + 'mutationCallback', + ], + [ + 'doSetAttribute', + 'testMutate', + '', # Anonymous function for the 'Runtime.evaluate' command. + ], + ]) + + # Check the breakpoint within an animation callback. + self.debugger.evaluate_js('testAnimationFrame()') + self.assert_paused([ + [ + 'asyncBreak', + 'animationFrameCallback', + ], + [ + 'doRequestAnimationFrame', + 'testAnimationFrame', + '', # Anonymous function for the 'Runtime.evaluate' command. + ], + ]) + + # Check the breakpoint on a media callback going through EventQueue. + self.debugger.evaluate_js('testMediaSource()') + self.assert_paused([ + [ + 'asyncBreak', + 'sourceOpenCallback', + ], + [ + 'setSourceListener', + 'testMediaSource', + '', # Anonymous function for the 'Runtime.evaluate' command. + ], + ]) + + # End the test. + self.debugger.evaluate_js('onEndTest()') + self.assertTrue(self.runner.JSTestsSucceeded())
diff --git a/src/cobalt/black_box_tests/tests/web_platform_tests.py b/src/cobalt/black_box_tests/tests/web_platform_tests.py index 12adcd0..283b5d6 100644 --- a/src/cobalt/black_box_tests/tests/web_platform_tests.py +++ b/src/cobalt/black_box_tests/tests/web_platform_tests.py
@@ -33,20 +33,28 @@ self.skipTest('Can only run web platform tests on debug or devel config.') def test_simple(self): - with WebPlatformTestServer(binding_address=self.GetBindingAddress()): + with WebPlatformTestServer(binding_address=self.GetBindingAddress(), + wpt_http_port=self.GetWptHttpPort()): target_params = [] filters = self.cobalt_config.GetWebPlatformTestFilters() + used_filters = [] - if test_filter.DISABLE_TESTING in filters: - return + for filter in filters: + if filter == test_filter.DISABLE_TESTING: + return + if filter == test_filter.FILTER_ALL: + return + if isinstance(filter, test_filter.TestFilter): + if filter.config and filter.config != self.device_params.config: + continue + used_filters.append(filter.test_name) + else: + used_filters.append(filter) - if test_filter.FILTER_ALL in filters: - return - - if filters: - target_params.append('--gtest_filter=-{}'.format(':'.join( - filters))) + if used_filters: + target_params.append('--gtest_filter=-{}'.format( + ':'.join(used_filters))) if self.device_params.target_params: target_params += self.device_params.target_params @@ -58,6 +66,7 @@ device_id=self.device_params.device_id, target_params=target_params, output_file=None, - out_directory=self.device_params.out_directory) + out_directory=self.device_params.out_directory, + env_variables={'ASAN_OPTIONS': 'intercept_tls_get_addr=0'}) status = launcher.Run() self.assertEqual(status, 0)
diff --git a/src/cobalt/black_box_tests/web_platform_test_server.py b/src/cobalt/black_box_tests/web_platform_test_server.py index 5199151..d3a9d96 100644 --- a/src/cobalt/black_box_tests/web_platform_test_server.py +++ b/src/cobalt/black_box_tests/web_platform_test_server.py
@@ -31,12 +31,16 @@ class WebPlatformTestServer(object): """Runs a WPT StashServer on its own thread in a Python context manager.""" - def __init__(self, binding_address=None): + def __init__(self, binding_address=None, wpt_http_port=None): # IP config['host'] should map to either through a dns or the hosts file. if binding_address: self._binding_address = binding_address else: self._binding_address = '127.0.0.1' + if wpt_http_port: + self._wpt_http_port = wpt_http_port + else: + self._wpt_http_port = '8000' def main(self): kwargs = vars(serve.get_parser().parse_args()) @@ -45,6 +49,7 @@ config = serve.load_config(os.path.join(WPT_DIR, 'config.default.json'), os.path.join(WPT_DIR, 'config.json'), **kwargs) + config['ports']['http'][0] = int(self._wpt_http_port) serve.setup_logger(config['log_level'])
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc index 045fcdf..9b76975 100644 --- a/src/cobalt/browser/application.cc +++ b/src/cobalt/browser/application.cc
@@ -86,6 +86,30 @@ return !base::strcasecmp(str.c_str(), "none"); } +#if defined(ENABLE_WEBDRIVER) || defined(ENABLE_DEBUGGER) +std::string GetDevServersListenIp() { + bool ip_v6; +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION + ip_v6 = SbSocketIsIpv6Supported(); +#elif SB_HAS(IPV6) + ip_v6 = true; +#else + ip_v6 = false; +#endif + std::string listen_ip(ip_v6 ? "::" : "0.0.0.0"); + +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDevServersListenIp)) { + listen_ip = + command_line->GetSwitchValueASCII(switches::kDevServersListenIp); + } +#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES + + return listen_ip; +} +#endif // defined(ENABLE_WEBDRIVER) || defined(ENABLE_DEBUGGER) + #if defined(ENABLE_DEBUGGER) int GetRemoteDebuggingPort() { #if defined(SB_OVERRIDE_DEFAULT_REMOTE_DEBUGGING_PORT) @@ -145,11 +169,13 @@ std::string GetWebDriverListenIp() { // The default IP on which the webdriver server should listen for incoming // connections. - std::string webdriver_listen_ip = - webdriver::WebDriverModule::kDefaultListenIp; + std::string webdriver_listen_ip = GetDevServersListenIp(); #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(switches::kWebDriverListenIp)) { + DLOG(WARNING) << "The \"--" << switches::kWebDriverListenIp + << "\" switch is deprecated; please use \"--" + << switches::kDevServersListenIp << "\" instead."; webdriver_listen_ip = command_line->GetSwitchValueASCII(switches::kWebDriverListenIp); } @@ -183,20 +209,23 @@ } #if SB_API_VERSION >= 11 - // Append the device authentication query parameters based on the platform's - // certification secret to the initial URL. - std::string query = initial_url.query(); - std::string device_authentication_query_string = - GetDeviceAuthenticationSignedURLQueryString(); - if (!query.empty() && !device_authentication_query_string.empty()) { - query += "&"; - } - query += device_authentication_query_string; + if (!command_line->HasSwitch( + switches::kOmitDeviceAuthenticationQueryParameters)) { + // Append the device authentication query parameters based on the platform's + // certification secret to the initial URL. + std::string query = initial_url.query(); + std::string device_authentication_query_string = + GetDeviceAuthenticationSignedURLQueryString(); + if (!query.empty() && !device_authentication_query_string.empty()) { + query += "&"; + } + query += device_authentication_query_string; - if (!query.empty()) { - GURL::Replacements replacements; - replacements.SetQueryStr(query); - initial_url = initial_url.ReplaceComponents(replacements); + if (!query.empty()) { + GURL::Replacements replacements; + replacements.SetQueryStr(query); + initial_url = initial_url.ReplaceComponents(replacements); + } } #endif // SB_API_VERSION >= 11 @@ -524,11 +553,13 @@ options.storage_manager_options.savegame_options.factory = &storage::SavegameFake::Create; } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) if (command_line->HasSwitch(browser::switches::kDisableOnScreenKeyboard)) { options.enable_on_screen_keyboard = false; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) #endif // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) @@ -668,7 +699,8 @@ event_dispatcher_.AddEventCallback(base::WindowSizeChangedEvent::TypeId(), window_size_change_event_callback_); #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) on_screen_keyboard_shown_event_callback_ = base::Bind( &Application::OnOnScreenKeyboardShownEvent, base::Unretained(this)); event_dispatcher_.AddEventCallback(base::OnScreenKeyboardShownEvent::TypeId(), @@ -696,15 +728,16 @@ base::OnScreenKeyboardSuggestionsUpdatedEvent::TypeId(), on_screen_keyboard_suggestions_updated_event_callback_); #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) on_caption_settings_changed_event_callback_ = base::Bind( &Application::OnCaptionSettingsChangedEvent, base::Unretained(this)); event_dispatcher_.AddEventCallback( base::AccessibilityCaptionSettingsChangedEvent::TypeId(), on_caption_settings_changed_event_callback_); -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) #if defined(ENABLE_WEBDRIVER) #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) bool create_webdriver_module = @@ -732,7 +765,7 @@ << switches::kRemoteDebuggingPort << " is 0."; } else { debug_web_server_.reset(new debug::remote::DebugWebServer( - remote_debugging_port, + remote_debugging_port, GetDevServersListenIp(), base::Bind(&BrowserModule::CreateDebugClient, base::Unretained(browser_module_.get())))); } @@ -770,7 +803,8 @@ event_dispatcher_.RemoveEventCallback(base::WindowSizeChangedEvent::TypeId(), window_size_change_event_callback_); #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) event_dispatcher_.RemoveEventCallback( base::OnScreenKeyboardShownEvent::TypeId(), on_screen_keyboard_shown_event_callback_); @@ -788,12 +822,13 @@ base::OnScreenKeyboardSuggestionsUpdatedEvent::TypeId(), on_screen_keyboard_suggestions_updated_event_callback_); #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) event_dispatcher_.RemoveEventCallback( base::AccessibilityCaptionSettingsChangedEvent::TypeId(), on_caption_settings_changed_event_callback_); -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) app_status_ = kShutDownAppStatus; } @@ -851,7 +886,8 @@ ->size)); break; #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) case kSbEventTypeOnScreenKeyboardShown: DCHECK(starboard_event->data); DispatchEventInternal(new base::OnScreenKeyboardShownEvent( @@ -876,7 +912,8 @@ *static_cast<int*>(starboard_event->data))); break; #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) case kSbEventTypeLink: { const char* link = static_cast<const char*>(starboard_event->data); DispatchEventInternal(new base::DeepLinkEvent(link)); @@ -885,12 +922,12 @@ case kSbEventTypeAccessiblitySettingsChanged: DispatchEventInternal(new base::AccessibilitySettingsChangedEvent()); break; -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) case kSbEventTypeAccessibilityCaptionSettingsChanged: DispatchEventInternal( new base::AccessibilityCaptionSettingsChangedEvent()); break; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) // Explicitly list unhandled cases here so that the compiler can give a // warning when a value is added, but not handled. case kSbEventTypeInput: @@ -966,10 +1003,11 @@ #if SB_API_VERSION >= 8 case kSbEventTypeWindowSizeChanged: #endif -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) case kSbEventTypeAccessibilityCaptionSettingsChanged: -#endif // SB_HAS(CAPTIONS) -#if SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) case kSbEventTypeOnScreenKeyboardBlurred: case kSbEventTypeOnScreenKeyboardFocused: case kSbEventTypeOnScreenKeyboardHidden: @@ -977,7 +1015,8 @@ #if SB_API_VERSION >= 11 case kSbEventTypeOnScreenKeyboardSuggestionsUpdated: #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) case kSbEventTypeAccessiblitySettingsChanged: case kSbEventTypeInput: case kSbEventTypeLink: @@ -1021,7 +1060,8 @@ } #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void Application::OnOnScreenKeyboardShownEvent(const base::Event* event) { TRACE_EVENT0("cobalt::browser", "Application::OnOnScreenKeyboardShownEvent()"); @@ -1064,9 +1104,10 @@ const base::OnScreenKeyboardSuggestionsUpdatedEvent*>(event)); } #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) void Application::OnCaptionSettingsChangedEvent(const base::Event* event) { TRACE_EVENT0("cobalt::browser", "Application::OnCaptionSettingsChangedEvent()"); @@ -1074,7 +1115,7 @@ base::polymorphic_downcast< const base::AccessibilityCaptionSettingsChangedEvent*>(event)); } -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) void Application::WebModuleRecreated() { TRACE_EVENT0("cobalt::browser", "Application::WebModuleRecreated()");
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h index 66ff3c7..db55875 100644 --- a/src/cobalt/browser/application.h +++ b/src/cobalt/browser/application.h
@@ -73,7 +73,8 @@ void OnWindowSizeChangedEvent(const base::Event* event); #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void OnOnScreenKeyboardShownEvent(const base::Event* event); void OnOnScreenKeyboardHiddenEvent(const base::Event* event); void OnOnScreenKeyboardFocusedEvent(const base::Event* event); @@ -81,11 +82,12 @@ #if SB_API_VERSION >= 11 void OnOnScreenKeyboardSuggestionsUpdatedEvent(const base::Event* event); #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) void OnCaptionSettingsChangedEvent(const base::Event* event); -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) // Called when a navigation occurs in the BrowserModule. void WebModuleRecreated(); @@ -105,7 +107,8 @@ #if SB_API_VERSION >= 8 base::EventCallback window_size_change_event_callback_; #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) base::EventCallback on_screen_keyboard_shown_event_callback_; base::EventCallback on_screen_keyboard_hidden_event_callback_; base::EventCallback on_screen_keyboard_focused_event_callback_; @@ -113,10 +116,11 @@ #if SB_API_VERSION >= 11 base::EventCallback on_screen_keyboard_suggestions_updated_event_callback_; #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) base::EventCallback on_caption_settings_changed_event_callback_; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) // Thread checkers to ensure that callbacks for network and application events // always occur on the same thread.
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc index 18aeeca..6052b23 100644 --- a/src/cobalt/browser/browser_module.cc +++ b/src/cobalt/browser/browser_module.cc
@@ -252,13 +252,16 @@ &storage_manager_, event_dispatcher_, options_.network_module_options), splash_screen_cache_(new SplashScreenCache()), -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) on_screen_keyboard_bridge_( - options.enable_on_screen_keyboard + OnScreenKeyboardStarboardBridge::IsSupported() && + options.enable_on_screen_keyboard ? new OnScreenKeyboardStarboardBridge(base::Bind( &BrowserModule::GetSbWindow, base::Unretained(this))) : NULL), -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) web_module_loaded_(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED), web_module_recreated_callback_(options_.web_module_recreated_callback), @@ -570,9 +573,7 @@ base::Bind(&BrowserModule::OnLoad, base::Unretained(this))); #if defined(ENABLE_FAKE_MICROPHONE) if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kFakeMicrophone) || - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kInputFuzzer)) { + switches::kFakeMicrophone)) { options.dom_settings_options.microphone_options.enable_fake_microphone = true; } @@ -931,7 +932,8 @@ } #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void BrowserModule::OnOnScreenKeyboardShown( const base::OnScreenKeyboardShownEvent* event) { DCHECK_EQ(base::MessageLoop::current(), self_message_loop_); @@ -982,16 +984,17 @@ } } #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) void BrowserModule::OnCaptionSettingsChanged( const base::AccessibilityCaptionSettingsChangedEvent* /*event*/) { if (web_module_) { web_module_->InjectCaptionSettingsChangedEvent(); } } -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) #if defined(ENABLE_DEBUGGER) void BrowserModule::OnFuzzerToggle(const std::string& message) { @@ -1063,7 +1066,7 @@ return; } - if (debug_console_->GetMode() == debug::console::DebugHub::kDebugConsoleOff) { + if (!debug_console_->IsVisible()) { // If the layer already has no render tree then simply return. In that case // nothing is changing. if (!debug_console_layer_->HasRenderTree()) { @@ -1080,7 +1083,8 @@ #endif // defined(ENABLE_DEBUGGER) -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void BrowserModule::OnOnScreenKeyboardInputEventProduced( base::Token type, const dom::InputEventInit& event) { TRACE_EVENT0("cobalt::browser", @@ -1094,18 +1098,15 @@ } #if defined(ENABLE_DEBUGGER) - // If the debug console is fully visible, it gets the next chance to handle - // input events. - if (debug_console_->GetMode() >= debug::console::DebugHub::kDebugConsoleOn) { - if (!debug_console_->InjectOnScreenKeyboardInputEvent(type, event)) { - return; - } + if (!debug_console_->FilterOnScreenKeyboardInputEvent(type, event)) { + return; } #endif // defined(ENABLE_DEBUGGER) InjectOnScreenKeyboardInputEventToMainWebModule(type, event); } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) void BrowserModule::OnKeyEventProduced(base::Token type, const dom::KeyboardEventInit& event) { @@ -1136,14 +1137,9 @@ } #if defined(ENABLE_DEBUGGER) - // If the debug console is fully visible, it gets the next chance to handle - // pointer events. - if (debug_console_->GetMode() >= debug::console::DebugHub::kDebugConsoleOn) { - if (!debug_console_->FilterPointerEvent(type, event)) { - return; - } + if (!debug_console_->FilterPointerEvent(type, event)) { + return; } - #endif // defined(ENABLE_DEBUGGER) DCHECK(web_module_); @@ -1161,14 +1157,9 @@ } #if defined(ENABLE_DEBUGGER) - // If the debug console is fully visible, it gets the next chance to handle - // wheel events. - if (debug_console_->GetMode() >= debug::console::DebugHub::kDebugConsoleOn) { - if (!debug_console_->FilterWheelEvent(type, event)) { - return; - } + if (!debug_console_->FilterWheelEvent(type, event)) { + return; } - #endif // defined(ENABLE_DEBUGGER) DCHECK(web_module_); @@ -1190,7 +1181,8 @@ web_module_->InjectKeyboardEvent(type, event); } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void BrowserModule::InjectOnScreenKeyboardInputEventToMainWebModule( base::Token type, const dom::InputEventInit& event) { TRACE_EVENT0( @@ -1208,7 +1200,8 @@ DCHECK(web_module_); web_module_->InjectOnScreenKeyboardInputEvent(type, event); } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) void BrowserModule::OnError(const GURL& url, const std::string& error) { TRACE_EVENT0("cobalt::browser", "BrowserModule::OnError()"); @@ -1291,12 +1284,8 @@ } #if defined(ENABLE_DEBUGGER) - // If the debug console is fully visible, it gets the next chance to handle - // key events. - if (debug_console_->GetMode() >= debug::console::DebugHub::kDebugConsoleOn) { - if (!debug_console_->FilterKeyEvent(type, event)) { - return false; - } + if (!debug_console_->FilterKeyEvent(type, event)) { + return false; } #endif // defined(ENABLE_DEBUGGER) @@ -1310,7 +1299,7 @@ if (event.key_code() == dom::keycode::kF1 || (event.ctrl_key() && event.key_code() == dom::keycode::kO)) { if (type == base::Tokens::keydown()) { - // Ctrl+O toggles the debug console display. + // F1 or Ctrl+O cycles the debug console display. debug_console_->CycleMode(); } return false; @@ -1319,6 +1308,12 @@ // F5 reloads the page. Reload(); } + } else if (event.ctrl_key() && event.key_code() == dom::keycode::kS) { + if (type == base::Tokens::keydown()) { + // Ctrl+S suspends Cobalt. + SbSystemRequestSuspend(); + } + return false; } #endif // defined(ENABLE_DEBUGGER) @@ -1609,10 +1604,12 @@ base::Bind(&BrowserModule::OnPointerEventProduced, base::Unretained(this)), base::Bind(&BrowserModule::OnWheelEventProduced, base::Unretained(this)), -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) base::Bind(&BrowserModule::OnOnScreenKeyboardInputEventProduced, base::Unretained(this)), -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) system_window_.get()); InstantiateRendererModule();
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h index 0bc7d1a..b44418a 100644 --- a/src/cobalt/browser/browser_module.h +++ b/src/cobalt/browser/browser_module.h
@@ -190,7 +190,8 @@ float video_pixel_ratio); #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void OnOnScreenKeyboardShown(const base::OnScreenKeyboardShownEvent* event); void OnOnScreenKeyboardHidden(const base::OnScreenKeyboardHiddenEvent* event); void OnOnScreenKeyboardFocused( @@ -201,12 +202,13 @@ void OnOnScreenKeyboardSuggestionsUpdated( const base::OnScreenKeyboardSuggestionsUpdatedEvent* event); #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) void OnCaptionSettingsChanged( const base::AccessibilityCaptionSettingsChangedEvent* event); -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) private: #if SB_HAS(CORE_DUMP_HANDLER_SUPPORT) @@ -253,13 +255,15 @@ // persist the user's preference. void SaveDebugConsoleMode(); -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // Glue function to deal with the production of an input event from an on // screen keyboard input device, and manage handing it off to the web module // for interpretation. void OnOnScreenKeyboardInputEventProduced(base::Token type, const dom::InputEventInit& event); -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) // Glue function to deal with the production of a keyboard input event from a // keyboard input device, and manage handing it off to the web module for @@ -278,12 +282,14 @@ // interpretation. void OnWheelEventProduced(base::Token type, const dom::WheelEventInit& event); -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // Injects an on screen keyboard input event directly into the main web // module. void InjectOnScreenKeyboardInputEventToMainWebModule( base::Token type, const dom::InputEventInit& event); -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) // Injects a key event directly into the main web module, useful for setting // up an input fuzzer whose input should be sent directly to the main
diff --git a/src/cobalt/browser/cobalt.gyp b/src/cobalt/browser/cobalt.gyp index ec30b50..8320f9b 100644 --- a/src/cobalt/browser/cobalt.gyp +++ b/src/cobalt/browser/cobalt.gyp
@@ -15,6 +15,7 @@ { 'variables': { 'sb_pedantic_warnings': 1, + 'has_updater%' : '<!(python ../../build/file_exists.py <(DEPTH)/cobalt/updater/updater.gyp)', }, 'targets': [ { @@ -33,6 +34,11 @@ '<(DEPTH)/cobalt/browser/splash_screen/splash_screen.gyp:copy_splash_screen', ], }], + ['sb_evergreen == 1 and has_updater == "True"', { + 'dependencies': [ + '<(DEPTH)/cobalt/updater/updater.gyp:updater', + ], + }], ], }, {
diff --git a/src/cobalt/browser/debug_console.cc b/src/cobalt/browser/debug_console.cc index b769196..56223d9 100644 --- a/src/cobalt/browser/debug_console.cc +++ b/src/cobalt/browser/debug_console.cc
@@ -13,6 +13,7 @@ // limitations under the License. #include "cobalt/browser/debug_console.h" + #include "base/bind.h" #include "base/command_line.h" #include "base/files/file_util.h" @@ -144,44 +145,55 @@ DebugConsole::~DebugConsole() {} +bool DebugConsole::ShouldInjectInputEvents() { + switch (GetMode()) { + case debug::console::DebugHub::kDebugConsoleOff: + case debug::console::DebugHub::kDebugConsoleHud: + return false; + default: + return true; + } +} + bool DebugConsole::FilterKeyEvent(base::Token type, const dom::KeyboardEventInit& event) { - // Assume here the full debug console is visible - pass all events to its - // web module, and return false to indicate the event has been consumed. + // Return true to indicate the event should still be handled. + if (!ShouldInjectInputEvents()) return true; + web_module_->InjectKeyboardEvent(type, event); return false; } bool DebugConsole::FilterWheelEvent(base::Token type, const dom::WheelEventInit& event) { - // Assume here the full debug console is visible - pass all events to its - // web module, and return false to indicate the event has been consumed. + // Return true to indicate the event should still be handled. + if (!ShouldInjectInputEvents()) return true; + web_module_->InjectWheelEvent(type, event); return false; } bool DebugConsole::FilterPointerEvent(base::Token type, const dom::PointerEventInit& event) { - // Assume here the full debug console is visible - pass all events to its - // web module, and return false to indicate the event has been consumed. + // Return true to indicate the event should still be handled. + if (!ShouldInjectInputEvents()) return true; + web_module_->InjectPointerEvent(type, event); return false; } -#if SB_HAS(ON_SCREEN_KEYBOARD) -bool DebugConsole::InjectOnScreenKeyboardInputEvent( +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) +bool DebugConsole::FilterOnScreenKeyboardInputEvent( base::Token type, const dom::InputEventInit& event) { - // Assume here the full debug console is visible - pass all events to its - // web module, and return false to indicate the event has been consumed. + // Return true to indicate the event should still be handled. + if (!ShouldInjectInputEvents()) return true; + web_module_->InjectOnScreenKeyboardInputEvent(type, event); return false; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) - -void DebugConsole::SetMode(int mode) { - base::AutoLock lock(mode_mutex_); - mode_ = mode; -} +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) void DebugConsole::CycleMode() { base::AutoLock lock(mode_mutex_);
diff --git a/src/cobalt/browser/debug_console.h b/src/cobalt/browser/debug_console.h index a027803..bb1fe25 100644 --- a/src/cobalt/browser/debug_console.h +++ b/src/cobalt/browser/debug_console.h
@@ -68,23 +68,26 @@ // false if it was consumed within this function. bool FilterWheelEvent(base::Token type, const dom::WheelEventInit& event); -#if SB_HAS(ON_SCREEN_KEYBOARD) - // Inject an on screen keyboard input event. +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) + // Filters an on screen keyboard input event. // Returns true if the event should be passed on to other handlers, // false if it was consumed within this function. - bool InjectOnScreenKeyboardInputEvent(base::Token type, + bool FilterOnScreenKeyboardInputEvent(base::Token type, const dom::InputEventInit& event); -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) const WebModule& web_module() const { return *web_module_; } WebModule& web_module() { return *web_module_; } - // Sets the debug console's visibility mode. - void SetMode(int mode); // Cycles through each different possible debug console visibility mode. void CycleMode(); - // Returns the currently set debug console visibility mode. - int GetMode(); + + // Returns true iff the console is in a mode that is visible. + bool IsVisible() { + return (GetMode() != debug::console::DebugHub::kDebugConsoleOff); + } void SetSize(const cssom::ViewportSize& window_dimensions, float video_pixel_ratio) { @@ -110,6 +113,13 @@ LOG(ERROR) << error; } + // Returns the currently set debug console visibility mode. + int GetMode(); + + // Returns true iff the debug console is in a state where it should route + // input events to its web module. + bool ShouldInjectInputEvents(); + // The current console visibility mode. The mutex is required since the debug // console's visibility mode may be accessed from both the WebModule thread // and the DebugConsole's host thread.
diff --git a/src/cobalt/browser/device_authentication.cc b/src/cobalt/browser/device_authentication.cc index 7c8eeea..4a41510 100644 --- a/src/cobalt/browser/device_authentication.cc +++ b/src/cobalt/browser/device_authentication.cc
@@ -146,6 +146,10 @@ CHECK(!cert_scope.empty()); CHECK(!start_time.empty()); + if (base64_signature.empty()) { + return std::string(); + } + std::map<std::string, std::string> signed_query_components; signed_query_components["cert_scope"] = cert_scope; signed_query_components["start_time"] = start_time;
diff --git a/src/cobalt/browser/device_authentication_test.cc b/src/cobalt/browser/device_authentication_test.cc index a820d94..5592d0c 100644 --- a/src/cobalt/browser/device_authentication_test.cc +++ b/src/cobalt/browser/device_authentication_test.cc
@@ -140,6 +140,11 @@ "yacs", "11111111", "11111111111111111111111111111111111111111111")); } +TEST(DeviceAuthenticationTest, NoCertSignatureImpliesNoQueryParameters) { + EXPECT_EQ("", GetDeviceAuthenticationSignedURLQueryStringFromComponents( + "my_cert_scope", "1234", "")); +} + #endif // SB_API_VERSION >= 11 } // namespace browser
diff --git a/src/cobalt/browser/memory_settings/auto_mem_settings.cc b/src/cobalt/browser/memory_settings/auto_mem_settings.cc index c0df087..55e0a7c 100644 --- a/src/cobalt/browser/memory_settings/auto_mem_settings.cc +++ b/src/cobalt/browser/memory_settings/auto_mem_settings.cc
@@ -26,13 +26,16 @@ #include "base/strings/string_util.h" #include "cobalt/browser/memory_settings/constants.h" #include "cobalt/browser/switches.h" +#include "starboard/blitter.h" namespace cobalt { namespace browser { namespace memory_settings { namespace { bool HasBlitter() { -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + const bool has_blitter = SbBlitterIsBlitterSupported(); +#elif SB_HAS(BLITTER) const bool has_blitter = true; #else const bool has_blitter = false;
diff --git a/src/cobalt/browser/on_screen_keyboard_starboard_bridge.cc b/src/cobalt/browser/on_screen_keyboard_starboard_bridge.cc index 47c92ea..bc2f657 100644 --- a/src/cobalt/browser/on_screen_keyboard_starboard_bridge.cc +++ b/src/cobalt/browser/on_screen_keyboard_starboard_bridge.cc
@@ -19,9 +19,19 @@ #include "starboard/event.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) namespace cobalt { namespace browser { +// static +bool OnScreenKeyboardStarboardBridge::IsSupported() { +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + return SbWindowOnScreenKeyboardIsSupported(); +#else + return true; +#endif +} + void OnScreenKeyboardStarboardBridge::Show(const char* input_text, int ticket) { // Delay providing the SbWindow until as late as possible. SbWindowShowOnScreenKeyboard(sb_window_provider_.Run(), input_text, ticket); @@ -105,4 +115,5 @@ } } // namespace browser } // namespace cobalt -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/cobalt/browser/on_screen_keyboard_starboard_bridge.h b/src/cobalt/browser/on_screen_keyboard_starboard_bridge.h index 2b6bda0..1186f7d 100644 --- a/src/cobalt/browser/on_screen_keyboard_starboard_bridge.h +++ b/src/cobalt/browser/on_screen_keyboard_starboard_bridge.h
@@ -21,7 +21,8 @@ #include "cobalt/dom/on_screen_keyboard_bridge.h" #include "starboard/window.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) namespace cobalt { namespace browser { @@ -36,6 +37,8 @@ DCHECK(!sb_window_provider_.is_null()); } + static bool IsSupported(); + void Show(const char* input_text, int ticket) override; void Hide(int ticket) override; @@ -63,5 +66,6 @@ } // namespace browser } // namespace cobalt -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) #endif // COBALT_BROWSER_ON_SCREEN_KEYBOARD_STARBOARD_BRIDGE_H_
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc index 0465c29..edb849b 100644 --- a/src/cobalt/browser/switches.cc +++ b/src/cobalt/browser/switches.cc
@@ -13,6 +13,7 @@ // limitations under the License. #include "cobalt/browser/switches.h" + #include <map> namespace cobalt { @@ -27,13 +28,20 @@ const char kDebugConsoleModeHelp[] = "Switches different debug console modes: on | hud | off"; +const char kDevServersListenIp[] = "dev_servers_listen_ip"; +const char kDevServersListenIpHelp[] = + "IP address of the interface that internal development servers (remote web " + "debugger and WebDriver) listen on. If unspecified, INADDR_ANY (on most " + "platforms). Tip: To listen to ANY interface use \"::\" (\"0.0.0.0\" for " + "IPv4), and to listen to LOOPBACK use \"::1\" (\"127.0.0.1\" for IPv4)"; + #if defined(ENABLE_DEBUGGER) const char kRemoteDebuggingPort[] = "remote_debugging_port"; const char kRemoteDebuggingPortHelp[] = "Remote web debugger is served from the specified port. If 0, then the " "remote web debugger is disabled."; - const char kWaitForWebDebugger[] = "wait_for_web_debugger"; +const char kWaitForWebDebugger[] = "wait_for_web_debugger"; const char kWaitForWebDebuggerHelp[] = "Waits for remote web debugger to connect before loading the page. A " "number may optionally be specified to indicate which in a sequence of " @@ -184,17 +192,20 @@ const char kWebDriverListenIp[] = "webdriver_listen_ip"; const char kWebDriverListenIpHelp[] = "IP that the WebDriver server should be listening on. (INADDR_ANY if " - "unspecified)."; + "unspecified). This is deprecated in favor of --dev_servers_listen_ip (if " + "both are specified, --webdriver_listen_ip is used)."; const char kWebDriverPort[] = "webdriver_port"; const char kWebDriverPortHelp[] = "Port that the WebDriver server should be listening on."; -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) const char kDisableOnScreenKeyboard[] = "disable_on_screen_keyboard"; const char kDisableOnScreenKeyboardHelp[] = "Disable the on screen keyboard for testing."; -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) #endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES @@ -286,6 +297,12 @@ "limit allows. It is recommended that enough memory be reserved for two " "RGBA atlases about a quarter of the frame size."; +const char kOmitDeviceAuthenticationQueryParameters[] = + "omit_device_authentication_query_parameters"; +const char kOmitDeviceAuthenticationQueryParametersHelp[] = + "When set, no device authentication parameters will be appended to the" + "initial URL."; + const char kProxy[] = "proxy"; const char kProxyHelp[] = "Specifies a proxy to use for network connections. " @@ -383,8 +400,10 @@ std::map<const char*, const char*> help_map { #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) {kDebugConsoleMode, kDebugConsoleModeHelp}, + {kDevServersListenIp, kDevServersListenIpHelp}, #if defined(ENABLE_DEBUGGER) {kWaitForWebDebugger, kWaitForWebDebuggerHelp}, + {kRemoteDebuggingPort, kRemoteDebuggingPortHelp}, #endif // ENABLE_DEBUGGER {kDisableImageAnimations, kDisableImageAnimationsHelp}, {kForceDeterministicRendering, kForceDeterministicRenderingHelp}, @@ -400,7 +419,6 @@ {kMinCompatibilityVersion, kMinCompatibilityVersionHelp}, {kMinLogLevel, kMinLogLevelHelp}, {kNullSavegame, kNullSavegameHelp}, {kDisablePartialLayout, kDisablePartialLayoutHelp}, {kProd, kProdHelp}, - {kRemoteDebuggingPort, kRemoteDebuggingPortHelp}, {kRequireCSP, kRequireCSPHelp}, {kRequireHTTPSLocation, kRequireHTTPSLocationHelp}, {kShutdownAfter, kShutdownAfterHelp}, @@ -410,9 +428,11 @@ {kUserAgentOsNameVersion, kUserAgentOsNameVersionHelp}, {kUseTTS, kUseTTSHelp}, {kWebDriverListenIp, kWebDriverListenIpHelp}, {kWebDriverPort, kWebDriverPortHelp}, -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) {kDisableOnScreenKeyboard, kDisableOnScreenKeyboardHelp}, -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) #endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES {kDisableJavaScriptJit, kDisableJavaScriptJitHelp}, @@ -431,6 +451,8 @@ {kMaxCobaltGpuUsage, kMaxCobaltGpuUsageHelp}, {kOffscreenTargetCacheSizeInBytes, kOffscreenTargetCacheSizeInBytesHelp}, + {kOmitDeviceAuthenticationQueryParameters, + kOmitDeviceAuthenticationQueryParametersHelp}, {kProxy, kProxyHelp}, {kQrCodeOverlay, kQrCodeOverlayHelp}, {kReduceCpuMemoryBy, kReduceCpuMemoryByHelp}, {kReduceGpuMemoryBy, kReduceGpuMemoryByHelp},
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h index 6b3b163..9d400e7 100644 --- a/src/cobalt/browser/switches.h +++ b/src/cobalt/browser/switches.h
@@ -26,6 +26,8 @@ #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) extern const char kDebugConsoleMode[]; extern const char kDebugConsoleModeHelp[]; +extern const char kDevServersListenIp[]; +extern const char kDevServersListenIpHelp[]; #if defined(ENABLE_DEBUGGER) extern const char kRemoteDebuggingPort[]; @@ -87,10 +89,12 @@ extern const char kWebDriverPort[]; extern const char kWebDriverPortHelp[]; -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) extern const char kDisableOnScreenKeyboard[]; extern const char kDisableOnScreenKeyboardHelp[]; -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) #endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES extern const char kDisableJavaScriptJit[]; @@ -121,6 +125,8 @@ extern const char kMaxCobaltGpuUsageHelp[]; extern const char kOffscreenTargetCacheSizeInBytes[]; extern const char kOffscreenTargetCacheSizeInBytesHelp[]; +extern const char kOmitDeviceAuthenticationQueryParameters[]; +extern const char kOmitDeviceAuthenticationQueryParametersHelp[]; extern const char kProxy[]; extern const char kProxyHelp[]; extern const char kQrCodeOverlay[];
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc index 43468e0..3b10308 100644 --- a/src/cobalt/browser/web_module.cc +++ b/src/cobalt/browser/web_module.cc
@@ -29,6 +29,7 @@ #include "base/synchronization/waitable_event.h" #include "base/trace_event/trace_event.h" #include "cobalt/base/c_val.h" +#include "cobalt/base/debugger_hooks.h" #include "cobalt/base/language.h" #include "cobalt/base/startup_timer.h" #include "cobalt/base/tokens.h" @@ -67,6 +68,7 @@ #include "cobalt/storage/storage_manager.h" #include "starboard/accessibility.h" #include "starboard/common/log.h" +#include "starboard/gles.h" #if defined(ENABLE_DEBUGGER) #include "cobalt/debug/backend/debug_module.h" @@ -121,7 +123,8 @@ } #endif // ENABLE_DEBUGGER -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // Injects an on screen keyboard input event into the web module. Event is // directed at a specific element if the element is non-null. Otherwise, the // currently focused element receives the event. If element is specified, we @@ -146,7 +149,8 @@ // module. Event is directed at the on screen keyboard element. void InjectOnScreenKeyboardSuggestionsUpdatedEvent(int ticket); #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) // Injects a keyboard event into the web module. Event is directed at a // specific element if the element is non-null. Otherwise, the currently @@ -496,13 +500,22 @@ // Note that it is important that we do not parse map-to-mesh filters if we // cannot render them, since web apps may check for map-to-mesh support by // testing whether it parses or not via the CSS.supports() Web API. - css_parser::Parser::SupportsMapToMeshFlag supports_map_to_mesh = -#if defined(ENABLE_MAP_TO_MESH) - data.options.enable_map_to_mesh_rectangular - ? css_parser::Parser::kSupportsMapToMeshRectangular - : css_parser::Parser::kSupportsMapToMesh; + css_parser::Parser::SupportsMapToMeshFlag supports_map_to_mesh; +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + if (SbGetGlesInterface()) { + supports_map_to_mesh = + data.options.enable_map_to_mesh_rectangular + ? css_parser::Parser::kSupportsMapToMeshRectangular + : css_parser::Parser::kSupportsMapToMesh; + } else { + supports_map_to_mesh = css_parser::Parser::kDoesNotSupportMapToMesh; + } +#elif defined(ENABLE_MAP_TO_MESH) + supports_map_to_mesh = data.options.enable_map_to_mesh_rectangular + ? css_parser::Parser::kSupportsMapToMeshRectangular + : css_parser::Parser::kSupportsMapToMesh; #else - css_parser::Parser::kDoesNotSupportMapToMesh; + supports_map_to_mesh = css_parser::Parser::kDoesNotSupportMapToMesh; #endif css_parser_ = css_parser::Parser::Create(supports_map_to_mesh); @@ -602,10 +615,19 @@ media_source_registry_.reset(new dom::MediaSource::Registry); + environment_settings_.reset(new dom::DOMSettings( + kDOMMaxElementDepth, fetcher_factory_.get(), data.network_module, + media_source_registry_.get(), blob_registry_.get(), + data.can_play_type_handler, javascript_engine_.get(), + global_environment_.get(), &debugger_hooks_, + &mutation_observer_task_manager_, data.options.dom_settings_options)); + DCHECK(environment_settings_); + media_session_client_ = media_session::MediaSessionClient::Create(); media_session_client_->SetMediaPlayerFactory(data.web_media_player_factory); - system_caption_settings_ = new cobalt::dom::captions::SystemCaptionSettings(); + system_caption_settings_ = new cobalt::dom::captions::SystemCaptionSettings( + environment_settings_.get()); dom::Window::CacheCallback splash_screen_cache_callback = CacheUrlContentCallback(data.options.splash_screen_cache); @@ -636,10 +658,10 @@ #endif window_ = new dom::Window( - data.window_dimensions, data.video_pixel_ratio, - data.initial_application_state, css_parser_.get(), dom_parser_.get(), - fetcher_factory_.get(), loader_factory_.get(), &resource_provider_, - animated_image_tracker_.get(), image_cache_.get(), + environment_settings_.get(), data.window_dimensions, + data.video_pixel_ratio, data.initial_application_state, css_parser_.get(), + dom_parser_.get(), fetcher_factory_.get(), loader_factory_.get(), + &resource_provider_, animated_image_tracker_.get(), image_cache_.get(), reduced_image_cache_capacity_manager_.get(), remote_typeface_cache_.get(), mesh_cache_.get(), local_storage_database_.get(), data.can_play_type_handler, data.web_media_player_factory, @@ -665,9 +687,8 @@ base::Unretained(this)), base::Bind(&WebModule::Impl::OnStopDispatchEvent, base::Unretained(this)), data.options.provide_screenshot_function, &synchronous_loader_interrupt_, - debugger_hooks_, data.ui_nav_root, - data.options.csp_insecure_allowed_token, data.dom_max_element_depth, - data.options.video_playback_rate_multiplier, + data.ui_nav_root, data.options.csp_insecure_allowed_token, + data.dom_max_element_depth, data.options.video_playback_rate_multiplier, #if defined(ENABLE_TEST_RUNNER) data.options.layout_trigger == layout::LayoutManager::kTestRunnerMode ? dom::Window::kClockTypeTestRunner @@ -683,15 +704,7 @@ window_weak_ = base::AsWeakPtr(window_.get()); DCHECK(window_weak_); - environment_settings_.reset(new dom::DOMSettings( - kDOMMaxElementDepth, fetcher_factory_.get(), data.network_module, window_, - media_source_registry_.get(), blob_registry_.get(), - data.can_play_type_handler, javascript_engine_.get(), - global_environment_.get(), &mutation_observer_task_manager_, - data.options.dom_settings_options)); - DCHECK(environment_settings_); - - window_->SetEnvironmentSettings(environment_settings_.get()); + environment_settings_->set_window(window_); global_environment_->CreateGlobalObject(window_, environment_settings_.get()); @@ -823,7 +836,8 @@ } } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void WebModule::Impl::InjectOnScreenKeyboardInputEvent( scoped_refptr<dom::Element> element, base::Token type, const dom::InputEventInit& event) { @@ -879,7 +893,8 @@ window_->on_screen_keyboard()->DispatchSuggestionsUpdatedEvent(ticket); } #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) void WebModule::Impl::InjectKeyboardEvent(scoped_refptr<dom::Element> element, base::Token type, @@ -1385,7 +1400,8 @@ impl_.reset(new Impl(data)); } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void WebModule::InjectOnScreenKeyboardInputEvent( base::Token type, const dom::InputEventInit& event) { @@ -1460,7 +1476,8 @@ base::Unretained(impl_.get()), ticket)); } #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) void WebModule::InjectKeyboardEvent(base::Token type, const dom::KeyboardEventInit& event) {
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h index 7f8ad01..8c33295 100644 --- a/src/cobalt/browser/web_module.h +++ b/src/cobalt/browser/web_module.h
@@ -286,7 +286,8 @@ float layout_refresh_rate, const Options& options); ~WebModule(); -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // Injects an on screen keyboard input event into the web module. The value // for type represents beforeinput or input. void InjectOnScreenKeyboardInputEvent(base::Token type, @@ -304,7 +305,8 @@ // module. void InjectOnScreenKeyboardSuggestionsUpdatedEvent(int ticket); #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) // Injects a keyboard event into the web module. The value for type // represents the event name, for example 'keydown' or 'keyup'.
diff --git a/src/cobalt/build/all.gyp b/src/cobalt/build/all.gyp index 15b5dc5..e0d3b20 100644 --- a/src/cobalt/build/all.gyp +++ b/src/cobalt/build/all.gyp
@@ -16,6 +16,10 @@ # default. { + 'variables': { + 'has_elf_loader%' : '<!(python ../../build/file_exists.py <(DEPTH)/starboard/elf_loader/elf_loader.gyp)', + 'has_loader_app%' : '<!(python ../../build/file_exists.py <(DEPTH)/starboard/loader_app/loader_app.gyp)', + }, 'targets': [ { 'target_name': 'Default', @@ -30,7 +34,7 @@ 'target_name': 'All', 'type': 'none', 'dependencies': [ - '<(DEPTH)/base/base.gyp:base_unittests', + '<(DEPTH)/base/base.gyp:base_unittests_deploy', '<(DEPTH)/cobalt/audio/audio.gyp:*', '<(DEPTH)/cobalt/audio/audio_test.gyp:*', '<(DEPTH)/cobalt/base/base.gyp:*', @@ -84,20 +88,34 @@ '<(DEPTH)/cobalt/webdriver/webdriver_test.gyp:*', '<(DEPTH)/cobalt/websocket/websocket.gyp:*', '<(DEPTH)/cobalt/xhr/xhr.gyp:*', - '<(DEPTH)/crypto/crypto.gyp:crypto_unittests', + '<(DEPTH)/crypto/crypto.gyp:crypto_unittests_deploy', '<(DEPTH)/third_party/boringssl/boringssl_tool.gyp:*', - '<(DEPTH)/net/net.gyp:net_unittests', - '<(DEPTH)/sql/sql.gyp:sql_unittests', - '<(DEPTH)/starboard/elf_loader/elf_loader.gyp:elf_loader_test', + '<(DEPTH)/net/net.gyp:net_unittests_deploy', + '<(DEPTH)/sql/sql.gyp:sql_unittests_deploy', ], 'conditions': [ + ['has_elf_loader == "True"', { + 'dependencies': [ + '<(DEPTH)/starboard/elf_loader/elf_loader.gyp:elf_loader_test_deploy', + ], + }], + ['has_loader_app == "True"', { + 'dependencies': [ + '<(DEPTH)/starboard/loader_app/loader_app.gyp:*', + ], + }], ['OS=="starboard"', { 'dependencies': [ - '<(DEPTH)/nb/nb_test.gyp:nb_test', + '<(DEPTH)/nb/nb_test.gyp:nb_test_deploy', '<(DEPTH)/nb/nb_test.gyp:reuse_allocator_benchmark', '<(DEPTH)/starboard/starboard_all.gyp:starboard_all', ], }], + ['sb_evergreen==1', { + 'dependencies': [ + '<(DEPTH)/third_party/musl/musl.gyp:musl_unittests', + ], + }], ], }, ],
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id index 8a3eeb1..a86f8a5 100644 --- a/src/cobalt/build/build.id +++ b/src/cobalt/build/build.id
@@ -1 +1 @@ -224424 \ No newline at end of file +234144 \ No newline at end of file
diff --git a/src/cobalt/build/cobalt_archive.py b/src/cobalt/build/cobalt_archive.py deleted file mode 100644 index e91dfe7..0000000 --- a/src/cobalt/build/cobalt_archive.py +++ /dev/null
@@ -1,533 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""Tools for creating and extracting a Cobalt Archive.""" - -import argparse -import fnmatch -import hashlib -import json -import logging -import os -import random -import stat -import sys -import time -import zipfile - -import _env # pylint: disable=relative-import,unused-import -from cobalt.build import cobalt_archive_extract -import starboard.build.filelist as filelist -import starboard.build.port_symlink as port_symlink -from starboard.tools.app_launcher_packager import CopyAppLauncherTools -from starboard.tools.build import GetPlatformConfig -from starboard.tools.config import GetAll as GetAllConfigs -import starboard.tools.paths as paths -from starboard.tools.platform import GetAll as GetAllPlatforms -from starboard.tools.util import SetupDefaultLoggingConfig - - -################################################################################ -# API # -################################################################################ - - -def MakeCobaltArchiveFromFileList(output_archive_path, - input_file_list, # class FileList - platform_name, - platform_sdk_version, - config, - additional_buildinfo_dict=None): - if additional_buildinfo_dict is None: - additional_buildinfo_dict = {} - archive = CobaltArchive(archive_zip_path=output_archive_path) - archive.MakeArchive(platform_name=platform_name, - platform_sdk_version=platform_sdk_version, - config=config, - file_list=input_file_list, - additional_buildinfo_dict=additional_buildinfo_dict) - - -def MakeCobaltArchiveFromSource(output_archive_path, - platform_name, - config, - platform_sdk_version, - additional_buildinfo_dict=None, - include_black_box_tests=False): - """Returns None, failure is signaled via exception.""" - if additional_buildinfo_dict is None: - additional_buildinfo_dict = {} - _MakeCobaltArchiveFromSource( - output_archive_path=output_archive_path, - platform_name=platform_name, - config=config, - platform_sdk_version=platform_sdk_version, - additional_buildinfo_dict=additional_buildinfo_dict, - include_black_box_tests=include_black_box_tests) - - -def ExtractCobaltArchive(input_zip_path, - output_directory_path, - outstream=None): - """Returns True if the extract operation was successfull.""" - archive = CobaltArchive(archive_zip_path=input_zip_path) - return archive.ExtractTo(output_dir=output_directory_path, - outstream=outstream) - - -def ReadCobaltArchiveInfo(input_zip_path): - archive = CobaltArchive(archive_zip_path=input_zip_path) - return archive.ReadMetaData() - - -################################################################################ -# IMPL # -################################################################################ - - -# Source resource paths. -_SELF_DIR = os.path.abspath(os.path.dirname(__file__)) -_SRC_CONTENT_PATH = os.path.join(_SELF_DIR, 'cobalt_archive_content') - - -# Relative paths from the resulting archive root. The path seperator -# is normalized to '/'. -_OUT_ARCHIVE_ROOT = '__cobalt_archive' -_OUT_FINALIZE_DECOMPRESSION_PATH = '%s/%s' % (_OUT_ARCHIVE_ROOT, - 'finalize_decompression') -_OUT_METADATA_PATH = '%s/%s' % (_OUT_ARCHIVE_ROOT, 'metadata.json') -_OUT_DECOMP_JSON = '%s/%s' % (_OUT_FINALIZE_DECOMPRESSION_PATH, - 'decompress.json') - - -class CobaltArchive(object): - """CobaltArchive is a utility generating archives.""" - - def __init__(self, archive_zip_path): - self.archive_zip_path = archive_zip_path - - def ExtractTo(self, output_dir, outstream=None): - """Returns True if all files were extracted, False otherwise.""" - return cobalt_archive_extract.ExtractTo( - self.archive_zip_path, output_dir, outstream) - - def ReadMetaData(self): - json_str = self.ReadFile(_OUT_METADATA_PATH) - return json.loads(json_str) - - def ReadFile(self, file_path): - with zipfile.ZipFile(self.archive_zip_path, 'r', allowZip64=True) as zf: - return zf.read(file_path) - - def MakeArchive(self, - platform_name, - platform_sdk_version, - config, - file_list, # class FileList - additional_buildinfo_dict=None): - """Creates an archive for the given platform and config.""" - logging.info('Making cobalt archive...') - is_windows = port_symlink.IsWindows() - if additional_buildinfo_dict is None: - additional_buildinfo_dict = {} - if config not in GetAllConfigs(): - raise ValueError('Expected %s to be one of %s' - % (config, GetAllConfigs())) - additional_buildinfo_dict = dict(additional_buildinfo_dict) # Copy - build_info_str = _GenerateBuildInfoStr( - platform_name=platform_name, - platform_sdk_version=platform_sdk_version, - config=config, - additional_buildinfo_dict=additional_buildinfo_dict) - with zipfile.ZipFile(self.archive_zip_path, mode='w', - compression=zipfile.ZIP_DEFLATED, - allowZip64=True) as zf: - # Copy the cobalt_archive_content directory into the root of the archive. - content_file_list = filelist.FileList() - content_file_list.AddAllFilesInPath(root_dir=_SRC_CONTENT_PATH, - sub_path=_SRC_CONTENT_PATH) - for file_path, archive_path in content_file_list.file_list: - # Skip the fake metadata.json file because the real one - # is a generated in it's place. - if os.path.basename(file_path) == 'metadata.json': - continue - zf.write(file_path, arcname=archive_path) - # Write out the metadata. - zf.writestr(_OUT_METADATA_PATH, build_info_str) - if file_list.file_list: - logging.info(' Compressing %d files', len(file_list.file_list)) - - executable_files = [] - n_file_list = len(file_list.file_list) - progress_set = set() - for i in range(n_file_list): - # Logging every 5% increment during compression step. - prog = int((float(i)/n_file_list) * 100) - if prog not in progress_set: - progress_set.add(prog) - logging.info(' Compressed %d%%...', prog) - file_path, archive_path = file_list.file_list[i] - if not is_windows: - perms = _GetFilePermissions(file_path) - if (stat.S_IXUSR) & perms: - executable_files.append(archive_path) - # TODO: Use and implement _FoldIdenticalFiles() to reduce - # duplicate files. This will help platforms like nxswitch which include - # a lot of duplicate files for the sdk. - try: - zf.write(file_path, arcname=archive_path) - except WindowsError: # pylint: disable=undefined-variable - # Happens for long file path names. - zf.write(cobalt_archive_extract.ToWinUncPath(file_path), - arcname=archive_path) - - if file_list.symlink_dir_list: - logging.info(' Compressing %d symlinks', - len(file_list.symlink_dir_list)) - # Generate the decompress.json file used by decompress.py. - # Removes the first element which is the root directory, which is not - # important for symlink creation. - symlink_dir_list = [l[1:] for l in file_list.symlink_dir_list] - # Replace '\\' with '/' - symlink_dir_list = [_ToUnixPaths(l) for l in symlink_dir_list] - decompress_json_str = _JsonDumpPrettyPrint({ - 'symlink_dir': symlink_dir_list, - 'symlink_dir_doc': '[link_dir_path, target_dir_path]', - 'executable_files': executable_files, - }) - zf.writestr(_OUT_DECOMP_JSON, decompress_json_str) - logging.info('Done...') - - -def _ToUnixPaths(path_list): - out = [] - for p in path_list: - out.append(p.replace('\\', '/')) - return out - - -def _GetFilePermissions(path): - return stat.S_IMODE(os.stat(path).st_mode) - - -def _JsonDumpPrettyPrint(data): - return json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) - - -def _MakeDirs(path): - if not os.path.isdir(path): - os.makedirs(path) - - -def _FindPossibleDeployPaths(build_root): - """Searches for folders that are likely required for archiving.""" - out = [] - # Ultimately, this function should not be needed as each platform should - # implement GetDeployPathPatterns(). This is stop-gap for platforms that do - # not have GetDeployPathPatterns() implemented yet. - root_paths = os.listdir(build_root) - for p in root_paths: - if p in ('gen', 'gypfiles', 'gyp-win-tool', 'obj', 'obj.host'): - continue - if p.endswith('.pdb'): - continue # Skip pdb files for size (only applies to Windows). - p = os.path.join(build_root, p) - if os.path.isfile(p): - out.append(p) - continue - if port_symlink.IsSymLink(p): - continue - out.append(os.path.normpath(p)) - return out - - -def _PathMatchesPatterns(file_path, patterns): - for p in patterns: - if fnmatch.fnmatch(file_path, p): - logging.debug('pattern %s matched %s', p, file_path) - return True - logging.debug('Skipping %s', file_path) - return False - - -def _GetDeployPaths(platform_name, config): - """Returns a list of paths that should be included in the archive.""" - try: - gyp_config = GetPlatformConfig(platform_name) - patterns = gyp_config.GetDeployPathPatterns() - logging.info('Found platform include patterns: [%s]', ', '.join(patterns)) - out_directory = paths.BuildOutputDirectory(platform_name, config) - out_paths = [] - for root, _, files in port_symlink.OsWalk(out_directory): - for f in files: - full_path = os.path.join(root, f) - file_path = os.path.relpath(full_path, out_directory) - if _PathMatchesPatterns(file_path, patterns): - out_paths.append(file_path) - return out_paths - except NotImplementedError: # Abstract class throws NotImplementedError. - logging.warning('** AUTO INCLUDE: ** Specific deploy paths were not found ' - 'so including known possible deploy paths from the ' - 'platform out directory.') - build_root = paths.BuildOutputDirectory(platform_name, config) - deploy_paths = _FindPossibleDeployPaths(build_root) - return deploy_paths - - -def _MakeCobaltArchiveFromSource(output_archive_path, - platform_name, - config, - platform_sdk_version, - additional_buildinfo_dict, - include_black_box_tests): - """Finds necessary files and makes an archive.""" - _MakeDirs(os.path.dirname(output_archive_path)) - out_directory = paths.BuildOutputDirectory(platform_name, config) - root_dir = os.path.abspath( - os.path.normpath(os.path.join(out_directory, '..', '..'))) - flist = filelist.FileList() - inc_paths = _GetDeployPaths(platform_name, config) - logging.info('Adding binary files to bundle...') - for path in inc_paths: - path = os.path.join(out_directory, path) - if not os.path.exists(path): - logging.info('Skipping deploy path %s because it does not exist.', - path) - continue - logging.info(' adding %s', os.path.abspath(path)) - flist.AddAllFilesInPath(root_dir=root_dir, sub_path=path) - logging.info('...done') - launcher_tools_path = os.path.join( - os.path.dirname(output_archive_path), - '____app_launcher') - if os.path.exists(launcher_tools_path): - port_symlink.Rmtree(launcher_tools_path) - logging.info('Adding app_launcher_files to bundle in %s', - os.path.abspath(launcher_tools_path)) - - try: - CopyAppLauncherTools(repo_root=paths.REPOSITORY_ROOT, - dest_root=launcher_tools_path, - additional_glob_patterns=[], - include_black_box_tests=include_black_box_tests) - flist.AddAllFilesInPath(root_dir=launcher_tools_path, - sub_path=launcher_tools_path) - logging.info('...done') - - MakeCobaltArchiveFromFileList( - output_archive_path, - input_file_list=flist, - platform_name=platform_name, - platform_sdk_version=platform_sdk_version, - config=config, - additional_buildinfo_dict=additional_buildinfo_dict) - logging.info('...done') - finally: - port_symlink.Rmtree(launcher_tools_path) - - -def _FoldIdenticalFiles(file_path_list): - """Takes input files and determines which are md5 identical and folds them. - - TODO: Implement into Cobalt Archive. - - Example: - files, copy_list = _FoldIdenticalFiles(['in0/test.txt', 'in1/test.txt']) - Output: - files => ['in0/test.txt'] - copy_list => ['in0/test.txt', 'in1/test.txt'] - - Args: - file_path_list: A list of files that will be processed. - - Returns: - A 2-tuple (files, copy_list) where files is a list of physical files and - copy_list is the list of files that are identical. - """ - # Remove duplicates. - file_path_list = list(set(file_path_list)) - file_path_list.sort() - def Md5File(fpath): - hash_md5 = hashlib.md5() - with open(fpath, 'rb') as f: - for chunk in iter(lambda: f.read(4096), b''): - hash_md5.update(chunk) - return hash_md5.hexdigest() - # Output - phy_file_list = [] - copy_list = [] - # Temp data structure. - file_map = {} - for file_path in file_path_list: - name = os.path.basename(file_path) - fsize = os.stat(file_path).st_size - entry = (name, fsize) - files = file_map.get(entry, []) - files.append(file_path) - file_map[entry] = files - for (fname, fsize), path_list in file_map.iteritems(): # pylint: disable=unused-variable - assert path_list - phy_file_list.append(path_list[0]) - if len(path_list) == 1: - continue - else: - md5_dict = {Md5File(path_list[0]): path_list[0]} - for tail_file in path_list[1:]: - new_md5 = Md5File(tail_file) - matching_file = md5_dict.get(new_md5, None) - if matching_file is not None: - # Match found. - copy_list.append((matching_file, tail_file)) - else: - phy_file_list.append(tail_file) - md5_dict[new_md5] = tail_file - return phy_file_list, copy_list - - -def _GenerateBuildInfoStr(platform_name, platform_sdk_version, - config, additional_buildinfo_dict): - """Generates a build info string (for the metadata file).""" - build_info = dict(additional_buildinfo_dict) # Copy dict. - build_info['archive_time_RFC_2822'] = ( - time.strftime('%a, %d %b %Y %H:%M:%S +0000', time.gmtime())) - build_info['archive_time_local'] = time.asctime() - build_info['platform'] = platform_name - build_info['config'] = config - build_info['sdk_version'] = platform_sdk_version - # Can be used by clients for caching reasons. - build_info['nonce'] = random.randint(0, 0xffffffffffffffff) - build_info_str = _JsonDumpPrettyPrint(build_info) - return build_info_str - - -################################################################################ -# CMD LINE # -################################################################################ - - -def _MakeCobaltPlatformArchive(platform, config, output_zip, - include_black_box_tests): - """Makes a Cobalt Archive, prompting for missing platform/config.""" - if not platform: - platform = raw_input('platform: ') - if platform not in GetAllPlatforms(): - raise ValueError('Platform "%s" not recognized, expected one of: \n%s' - % (platform, GetAllPlatforms())) - if not config: - config = raw_input('config: ') - if not output_zip: - output_zip = os.path.normpath(raw_input('output_zip: ')) - if not output_zip.endswith('.zip'): - output_zip += '.zip' - start_time = time.time() - MakeCobaltArchiveFromSource( - output_zip, - platform, - config, - platform_sdk_version='TEST', - additional_buildinfo_dict=None, - include_black_box_tests=include_black_box_tests) - time_delta = time.time() - start_time - if not os.path.isfile(output_zip): - raise ValueError('Expected zip file at ' + output_zip) - logging.info('\nGenerated: %s in %d seconds', output_zip, int(time_delta)) - - -# Returns True/False -def _DecompressArchive(in_zip, out_path): - if not in_zip: - in_zip = raw_input('cobalt archive path: ') - if not out_path: - out_path = raw_input('output path: ') - return ExtractCobaltArchive(input_zip_path=in_zip, - output_directory_path=out_path) - - -def _CreateArgumentParser(): - """Creates a parser that will print the full help on failure to parse.""" - - class MyParser(argparse.ArgumentParser): - - def error(self, message): - sys.stderr.write('error: %s\n' % message) - self.print_help() - sys.exit(2) - help_msg = ( - 'Example 1:\n' - ' python cobalt_archive.py --create --platform nxswitch' - ' --config devel --out_path <OUT_ZIP>\n\n' - 'Example 2:\n' - ' python cobalt_archive.py --extract --in_path <ARCHIVE_PATH.ZIP>' - ' --out_path <OUT_DIR>') - # Enables new lines in the description and epilog. - formatter_class = argparse.RawDescriptionHelpFormatter - parser = MyParser(epilog=help_msg, formatter_class=formatter_class) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument( - '-c', - '--create', - help='Creates an archive from source directory, optional arguments' - ' include --platform --config and --out_path', - action='store_true') - group.add_argument( - '-x', - '--extract', - help='Extract archive from IN_PATH to OUT_PATH, optional arguments ' - 'include --in_path and --out_path', - action='store_true') - parser.add_argument('--platform', type=str, - help='Optional, used for --create', - default=None) - parser.add_argument('--config', type=str, - help='Optional, used for --create', - choices=GetAllConfigs(), - default=None) - parser.add_argument('--out_path', type=str, - help='Optional, used for --create and --decompress', - default=None) - parser.add_argument('--in_path', type=str, - help='Optional, used for decompress', - default=None) - parser.add_argument('--include_black_box_tests', - help='Optional, used for --create to add blackbox tests', - action='store_true') - return parser - - -def main(): - SetupDefaultLoggingConfig() - parser = _CreateArgumentParser() - args, unknown_args = parser.parse_known_args() - if unknown_args: - logging.warning('Unknown (ignored) args: %s', unknown_args) - if args.create: - _MakeCobaltPlatformArchive( - platform=args.platform, - config=args.config, - output_zip=os.path.normpath(args.out_path), - include_black_box_tests=args.include_black_box_tests) - sys.exit(0) - elif args.extract: - ok = _DecompressArchive(args.in_path, args.out_path) - rc = 0 if ok else 1 - sys.exit(rc) - else: - parser.print_help() - - -if __name__ == '__main__': - main()
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/finalize_decompression/decompress.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/finalize_decompression/decompress.py deleted file mode 100644 index 3f34428..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/finalize_decompression/decompress.py +++ /dev/null
@@ -1,123 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""Finalizes decompression. - -This is meant to be run after the zip is decompressed into the temp directory -and includes support for special file system operations not supported by the -zip file. -""" - - -import json -import logging -import os -import subprocess -import sys - - -_SELF_DIR = os.path.dirname(__file__) -_ARCHIVE_ROOT = os.path.join(_SELF_DIR, os.pardir, os.pardir) -_DATA_JSON_PATH = os.path.abspath(os.path.join(_SELF_DIR, 'decompress.json')) -_FULL_PERMISSIONS = 0o777 - - -_IS_WINDOWS = sys.platform in ['win32', 'cygwin'] - - -def _CreateWin32Symlink(source, link_name): - rc = subprocess.call('mklink /D %s %s' % (link_name, source), shell=True) - if rc != 0: - # Some older versions of windows require admin permissions for /D style - # reparse points. In this case fallback to using /J. - cmd = 'mklink /J %s %s' % (link_name, source), - rc = subprocess.call(cmd, shell=True) - if rc != 0: - logging.critical('Error using %s during %s, cwd=%s', rc, cmd, os.getcwd()) - - -def _CreateSymlink(source, link_name): - if _IS_WINDOWS: - _CreateWin32Symlink(source, link_name) - else: - os.symlink(source, link_name) - - -def _MakeDirs(path): - if _IS_WINDOWS: - # Necessary for long file name support - subprocess.check_call('mkdir %s' % path, shell=True) - else: - os.makedirs(path) - - -def _ExtractSymlinks(archive_root, symlink_dir_list): - """Recreates symlinks on Windows and linux.""" - archive_root = os.path.normpath(archive_root) - if _IS_WINDOWS: - archive_root = '\\\\?\\' + archive_root - for link_path, real_path in symlink_dir_list: - # link_path and real_path are assumed to be both relative paths. - real_path = os.path.normpath(real_path) - link_path = os.path.normpath(link_path) - target_path = os.path.relpath(real_path, os.path.dirname(link_path)) - link_path = os.path.join(archive_root, link_path) - if not os.path.exists(os.path.dirname(link_path)): - _MakeDirs(os.path.dirname(link_path)) - _CreateSymlink(target_path, link_path) - # Check that all the symlinks point to an existing directory. - all_ok = True - cwd = os.getcwd() - for link_path, _ in symlink_dir_list: - link_path = os.path.join(archive_root, link_path) - try: - # This will raise an error if the link points to an invalid directory. - os.chdir(link_path) - except: - all_ok = False - finally: - os.chdir(cwd) - if not all_ok: - logging.critical('\n*******************************************' - '\nErrors happended during symlink extraction.' - '\n*******************************************') - - -def _SetExecutionBits(cwd, executable_files): - if not executable_files: - return - logging.info('Setting Permissions %s on %d files', - _FULL_PERMISSIONS, len(executable_files)) - for f in executable_files: - full_path = os.path.abspath(os.path.join(cwd, f)) - logging.info(' %s', full_path) - os.chmod(full_path, _FULL_PERMISSIONS) - - -def main(): - logging.basicConfig(level=logging.INFO, - format='%(filename)s(%(lineno)s): %(message)s') - assert(os.path.exists(_DATA_JSON_PATH)), _DATA_JSON_PATH - with open(_DATA_JSON_PATH) as fd: - json_str = fd.read() - data = json.loads(json_str) - _ExtractSymlinks(_ARCHIVE_ROOT, data.get('symlink_dir', [])) - _SetExecutionBits(_ARCHIVE_ROOT, data.get('executable_files', [])) - - -if __name__ == '__main__': - main()
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/metadata.json b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/metadata.json deleted file mode 100644 index 632f04c..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/metadata.json +++ /dev/null
@@ -1,9 +0,0 @@ -{ - "comment": "TEST", - "archive_time_RFC_2822": "Tue, 30 Apr 2019 00:14:18 +0000", - "archive_time_local": "Tue Apr 30 00:14:18 2019", - "config": "CONFIG_STRING", - "platform": "PLATFORM_STRING", - "random_uint64": 0, - "sdk_version": "any" -} \ No newline at end of file
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/__init__.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/__init__.py deleted file mode 100644 index dbab2d5..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/__init__.py +++ /dev/null
@@ -1,15 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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.
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/__init__.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/__init__.py deleted file mode 100644 index dbab2d5..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/__init__.py +++ /dev/null
@@ -1,15 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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.
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/run_test.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/run_test.py deleted file mode 100644 index b1a300d..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/run_test.py +++ /dev/null
@@ -1,67 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""Unit tests the run.py trampoline.""" - -import os -import sys -import unittest - -sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) -import run # pylint: disable=relative-import,g-bad-import-order,g-import-not-at-top - - -class RunGeneralTrampolineTest(unittest.TestCase): - """Tests trampoline substitutions for run_cobalt.py.""" - - def setUp(self): - """Change the trampoline internals for testing purposes.""" - super(RunGeneralTrampolineTest, self).setUp() - run.trampoline.PLATFORM = 'MY_PLATFORM' - run.trampoline.CONFIG = 'MY_CONFIG' - - def testOneTarget(self): - """Tests that one target gets resolved.""" - expected_output = ( - 'python starboard/tools/example/app_launcher_client.py' - ' --platform MY_PLATFORM --config MY_CONFIG' - ' --target_name cobalt') - cmd_str = run._ResolveTrampoline(argv=['cobalt']) - self.assertEqual(expected_output, cmd_str) - - def testTwoTargets(self): - """Tests that two targets gets resolved.""" - expected_output = ( - 'python starboard/tools/example/app_launcher_client.py' - ' --platform MY_PLATFORM --config MY_CONFIG' - ' --target_name cobalt --target_name nplb') - cmd_str = run._ResolveTrampoline(argv=['cobalt', 'nplb']) - self.assertEqual(expected_output, cmd_str) - - def testTargetParams(self): - """Tests that the the target_params gets correctly resolved.""" - expected_output = ( - 'python starboard/tools/example/app_launcher_client.py' - ' --platform MY_PLATFORM --config MY_CONFIG' - ' --target_params="--url=http://my.server.test"') - argv = ['--target_params', '"--url=http://my.server.test"'] - cmd_str = run._ResolveTrampoline(argv=argv) - self.assertEqual(expected_output, cmd_str) - - -if __name__ == '__main__': - unittest.main(verbosity=2)
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/run_tests_test.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/run_tests_test.py deleted file mode 100644 index cffc18d..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/run_tests_test.py +++ /dev/null
@@ -1,57 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""Unit tests the run.py trampoline.""" - -import os -import sys -import unittest - -sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) -import run_tests # pylint: disable=relative-import,g-bad-import-order,g-import-not-at-top - - -class RunUnitTestsTrampolineTest(unittest.TestCase): - """Tests trampoline substitutions for run_unit_tests.py.""" - - def setUp(self): - """Change the trampoline internals for testing purposes.""" - super(RunUnitTestsTrampolineTest, self).setUp() - run_tests.trampoline.PLATFORM = 'MY_PLATFORM' - run_tests.trampoline.CONFIG = 'MY_CONFIG' - - def testOne(self): - """Tests that --target_name resolves to the expected value.""" - expected_output = ( - 'python starboard/tools/testing/test_runner.py' - ' --target_name nplb --platform MY_PLATFORM --config MY_CONFIG') - cmd_str = run_tests._ResolveTrampoline(argv=['--target_name', 'nplb']) - self.assertEqual(expected_output, cmd_str) - - def testTwo(self): - """Tests that --target_name used twice resolves to the expected value.""" - expected_output = ( - 'python starboard/tools/testing/test_runner.py' - ' --platform MY_PLATFORM --config MY_CONFIG' - ' --target_name nplb --target_name nb_test') - argv=['nplb', 'nb_test'] - cmd_str = run_tests._ResolveTrampoline(argv=argv) - self.assertEqual(expected_output, cmd_str) - - -if __name__ == '__main__': - unittest.main(verbosity=2)
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/trampoline.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/trampoline.py deleted file mode 100644 index 059c1e3..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/trampoline.py +++ /dev/null
@@ -1,165 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""Trampoline resolves a trampoline to a command string.""" - - -import argparse -import json -import os -import subprocess -import sys - - -################################################################################ -# API # -################################################################################ - - -def RunTrampolineThenExit(trampoline, argv=None): - cmd_str = ResolveTrampoline(trampoline, argv) - sys.exit(_ShellCmd(cmd_str)) - - -def ResolveTrampoline(trampoline, argv=None): - r"""Resolves the trampoline list and returns a fully resolve strings. - - The result of this function call is to return the cmd string with - the platform, config, device_id resolved to values. - Example input: - ['python starboard/tools/example/app_launcher_client.py -t cobalt', - '{platform_arg}', '{config_arg}', '{device_id_arg}'] - Example Output: - 'python starboard/tools/example/app_launcher_client.py -t cobalt ' + \ - '--platform linux --config devel --device_id IP_ADDRESS' - - Args: - trampoline: a list of commands mixed in with unresolved symobls. - argv: a list of known resolves symbols to use in the trampoline. - - Returns: - A string representing the resolved shell command. - """ - return _ResolveTrampoline(trampoline, argv) - - -def RunThenExit(cmd_str, cwd=None): - if cwd == None: - cwd = _FindCwd() - sys.exit(_ShellCmd(cmd_str, cwd=cwd)) - - -################################################################################ -# IMPL # -################################################################################ - - -_SELF_DIR = os.path.dirname(__file__) -_META_FILE = os.path.normpath( - os.path.join(_SELF_DIR, '..', '..', 'metadata.json')) -with open(_META_FILE) as fd: - data = fd.read() - _META_DATA = json.loads(data) - - -# Tests can modify these values and alter the output of the trampoline -# resolver. -PLATFORM = _META_DATA['platform'] -CONFIG = _META_DATA['config'] -IS_TEST = _META_DATA.get('comment', None) == 'TEST' - - -def _FindCwd(): - """Gets the current working directory. - - This is detected by whether the metadata.json is real (meaning we are in a - cobalt archive) or in the source directory. - - Returns: - current working directory for execution. - """ - if IS_TEST: - p = os.path.join(_SELF_DIR, '..', '..', '..', '..', '..', '..') - else: - p = os.path.join(_SELF_DIR, '..', '..', '..') - return os.path.normpath(p) - - -def _ShellCmd(cmd_str, cwd): - sys.stdout.write('in: %s\n' % os.path.abspath(cwd)) - sys.stdout.write('Calling: %s\n\n' % cmd_str) - return subprocess.call(cmd_str, cwd=cwd, shell=True, - universal_newlines=True) - - -def _UnQuote(s): - if len(s) < 2: - return s - elif s[0] == '"' and s[-1] == '"': - return s[1:-1] - else: - return s - - -def _ResolveTrampoline(trampoline, argv): - """Implemention, see ResolveTrampoline() above.""" - if argv is None: - argv = sys.argv[2:] - known_args, unknown_args = _ParseArgs(argv) - placeholders = { - 'platform_arg': '--platform %s' % PLATFORM, - 'config_arg': '--config %s' % CONFIG - } - placeholders['device_id_arg'] = ( - '' if not known_args.device_id - else '--device_id %s' % known_args.device_id) - placeholders['target_params_arg'] = ( - '' if not known_args.target_params else - '--target_params="%s"' % _UnQuote(known_args.target_params)) - if not known_args.target_name: - placeholders['target_names_arg'] = '' - else: - targets = ['--target_name ' + name for name in known_args.target_name] - placeholders['target_names_arg'] = ' '.join(targets) - trampoline = [part.format(**placeholders) for part in trampoline] - trampoline = [t for t in trampoline if t.strip()] - return ' '.join(trampoline), unknown_args - - -def _ParseArgs(argv): - """Parses arguments.""" - - class MyParser(argparse.ArgumentParser): - - def error(self, message): - sys.stderr.write('error: %s\n' % message) - self.print_help() - - formatter_class = argparse.RawDescriptionHelpFormatter - parser = MyParser(formatter_class=formatter_class) - parser.add_argument('--device_id', type=str, - help=('Choices are a device_id (usually an IP) ' - 'passed to the launcher.'), - default=None) - parser.add_argument('--target_params', type=str, - help='Key=Value list of args to pass to the client.', - default=None) - parser.add_argument('-t', '--target_name', action='append', - help=('Name of executable target. Repeatable for ' - 'multiple targets.')) - args = parser.parse_known_args(argv) - return args
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/trampoline_test.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/trampoline_test.py deleted file mode 100644 index cc34e91..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/impl/trampoline_test.py +++ /dev/null
@@ -1,75 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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 unittest - -import trampoline # pylint: disable=relative-import,g-bad-import-order,g-import-not-at-top - - -class TrampolineTest(unittest.TestCase): - """Tests trampoline substitutions.""" - - def setUp(self): - super(TrampolineTest, self).setUp() - # Change the trampoline internals for testing purposes. - trampoline.PLATFORM = 'MY_PLATFORM' - trampoline.CONFIG ='MY_CONFIG' - - def testResolvePlatformConfig(self): - """Tests that a device_id resolves to the expected value.""" - tramp = [ - 'python dummy.py', '{platform_arg}', '{config_arg}', '{device_id_arg}', - '{target_params_arg}', - ] - expected_output = ( - 'python dummy.py --platform MY_PLATFORM --config MY_CONFIG') - cmd_str, _ = trampoline.ResolveTrampoline(tramp, argv=[]) - self.assertEqual(expected_output, cmd_str) - - def testResolveDeviceId(self): - """Tests that a device_id resolves to the expected value.""" - tramp = [ - 'python dummy.py', '{platform_arg}', '{config_arg}', '{device_id_arg}', - '{target_params_arg}', - ] - expected_output = ( - 'python dummy.py --platform MY_PLATFORM --config MY_CONFIG' - ' --device_id 1234') - cmd_str, _ = trampoline.ResolveTrampoline( - tramp, - argv=['--device_id', '1234']) - self.assertEqual(expected_output, cmd_str) - - def testTargetParams(self): - """Tests that target_params resolves to the expected value.""" - tramp = [ - 'python dummy.py', '--target_name cobalt', - '{platform_arg}', '{config_arg}', '{device_id_arg}', - '{target_params_arg}', - ] - expected_output = ( - 'python dummy.py' - ' --target_name cobalt --platform MY_PLATFORM' - ' --config MY_CONFIG --target_params="--url=http://my.server.test"') - cmd_str, _ = trampoline.ResolveTrampoline( - tramp, - argv=['--target_params', '"--url=http://my.server.test"']) - self.assertEqual(expected_output, cmd_str) - - -if __name__ == '__main__': - unittest.main(verbosity=2)
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/readme.md b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/readme.md deleted file mode 100644 index df9ef75..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/readme.md +++ /dev/null
@@ -1,20 +0,0 @@ -## Trampoline Readme - -**Trampoline**: - An operation which will forward control to a delegate. - -*Maps f(device_id) -> g(platform, config, device_id)* - -Trampolines reduce the complexity for invoking cobalt/starboard binaries -and tests by reading parameters from the `metadata.json` file of a Cobalt -Archive. The delegate is then run with the full command-line argument -set including platform and configuration data. The calling signature is -therefore *stable* and any Cobalt archive can be run the same binaries/tests -using the same shell command. - -Example: - python __cobalt_archive/run/run_cobalt.py --device_id IP - - Could translate into: - python starboard/tools/example/app_launcher_client.py - -t cobalt --platform linux --config devel --device_id IP
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run.py deleted file mode 100644 index 896010a..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run.py +++ /dev/null
@@ -1,51 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""A trampoline that launches starboard/tools/example/app_launcher.py. - - - Example: python __cobalt_archive/run/run.py cobalt -""" - - -import sys -sys.path.insert(0, '.') -from impl import trampoline # pylint: disable=relative-import,g-import-not-at-top - - -TRAMPOLINE = [ - 'python starboard/tools/example/app_launcher_client.py', - '{platform_arg}', - '{config_arg}', - '{device_id_arg}', - '{target_params_arg}', -] - - -def _ResolveTrampoline(argv=None): - if argv == None: - argv = sys.argv[1:] - resolved_cmd, unresolve_args = trampoline.ResolveTrampoline( - TRAMPOLINE, argv=argv) - # Interpret all tail args as the target_name param. - tail_args = ['--target_name %s' % a for a in unresolve_args] - resolved_cmd = ' '.join([resolved_cmd] + tail_args) - return resolved_cmd - - -if __name__ == '__main__': - trampoline.RunThenExit(_ResolveTrampoline())
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_black_box_tests.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_black_box_tests.py deleted file mode 100644 index dda40e7..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_black_box_tests.py +++ /dev/null
@@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""A trampoline that launches cobalt/tools/buildbot/run_black_box_tests.py. - - - Example: python __cobalt_archive/run/run_black_box_tests.py -""" - - -import sys -sys.path.insert(0, '.') -from impl import trampoline # pylint: disable=relative-import,g-import-not-at-top - - -TRAMPOLINE = [ - 'python cobalt/tools/buildbot/run_black_box_tests.py', - '--action', 'run', - '{platform_arg}', - '{config_arg}', - '{device_id_arg}', - '{target_params_arg}', -] - - -def _ResolveTrampoline(argv=None): - if argv == None: - argv = sys.argv[1:] - resolved_cmd, _ = trampoline.ResolveTrampoline( - TRAMPOLINE, argv=argv) - return resolved_cmd - - -if __name__ == '__main__': - trampoline.RunThenExit(_ResolveTrampoline())
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_platform_tests.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_platform_tests.py deleted file mode 100644 index f74a7ad..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_platform_tests.py +++ /dev/null
@@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""A trampoline for running the unit tests from a Cobalt Archive. - - This will invoke starboard/tools/testing/test_runner.py with - --platform_tests_only, which only runs a subset of tests related to platform - include nplb, starboard_platform_tests and others. - - Example: python __cobalt_archive/run/run_platform_tests.py -""" - - -import sys -sys.path.insert(0, '.') -from impl import trampoline # pylint: disable=relative-import,g-import-not-at-top - - -TRAMPOLINE = [ - 'python starboard/tools/testing/test_runner.py', - '--platform_tests_only', - '{platform_arg}', - '{config_arg}', - '{device_id_arg}', - '{target_params_arg}', -] - - -def _ResolveTrampoline(argv=None): - if argv == None: - argv = sys.argv[1:] - resolved_cmd, unresolve_args = trampoline.ResolveTrampoline( - TRAMPOLINE, argv=argv) - return resolved_cmd - - -if __name__ == '__main__': - trampoline.RunThenExit(_ResolveTrampoline())
diff --git a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_tests.py b/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_tests.py deleted file mode 100644 index 041278e..0000000 --- a/src/cobalt/build/cobalt_archive_content/__cobalt_archive/run/run_tests.py +++ /dev/null
@@ -1,60 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""A trampoline for running the unit tests from a Cobalt Archive. - - This will invoke starboard/tools/testing/test_runner.py, which runs the - specified test with a test filter list for the patform. - - Note that this is different from run.py will invoke - starboard/tools/example/app_launcher_client.py which does NOT filter any - tests. - - Example: python __cobalt_archive/run/run_tests.py nplb nb_test - - Example: python __cobalt_archive/run/run_tests.py (runs all tests) -""" - - -import sys -sys.path.insert(0, '.') -from impl import trampoline # pylint: disable=relative-import,g-import-not-at-top - - -TRAMPOLINE = [ - 'python starboard/tools/testing/test_runner.py', - '{target_names_arg}', - '{platform_arg}', - '{config_arg}', - '{device_id_arg}', - '{target_params_arg}', -] - - -def _ResolveTrampoline(argv=None): - if argv == None: - argv = sys.argv[1:] - resolved_cmd, unresolve_args = trampoline.ResolveTrampoline( - TRAMPOLINE, argv=argv) - # Interpret all tail args as the target_name param. - tail_args = ['--target_name %s' % a for a in unresolve_args] - resolved_cmd = ' '.join([resolved_cmd] + tail_args) - return resolved_cmd - - -if __name__ == '__main__': - trampoline.RunThenExit(_ResolveTrampoline())
diff --git a/src/cobalt/build/cobalt_archive_extract.py b/src/cobalt/build/cobalt_archive_extract.py deleted file mode 100644 index 617d1e8..0000000 --- a/src/cobalt/build/cobalt_archive_extract.py +++ /dev/null
@@ -1,166 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - -"""Tools for extracting a Cobalt Archive. - -This no-dependency tool will extract a Cobalt Archive across all platforms. - -This is slightly complicated because of issues on Windows where the poor -support for pathnames longer than 255 characters is an issue. -""" - - -import argparse -import logging -import os -import shutil -import subprocess -import sys -import zipfile - - -################################################################################ -# API # -################################################################################ - - -def ExtractTo(archive_zip_path, output_dir, outstream=None): - return _ExtractTo(archive_zip_path=archive_zip_path, - output_dir=output_dir, - outstream=outstream) - - -def ToWinUncPath(dos_path, encoding=None): - """Returns a windows UNC path which enables long path names in win32 apis.""" - return _ToWinUncPath(dos_path, encoding) - - -################################################################################ -# IMPL # -################################################################################ - - -_OUT_ARCHIVE_ROOT = '__cobalt_archive' -_OUT_FINALIZE_DECOMPRESSION_PATH = '%s/%s' % (_OUT_ARCHIVE_ROOT, - 'finalize_decompression') -_OUT_DECOMP_PY = '%s/%s' % (_OUT_FINALIZE_DECOMPRESSION_PATH, - 'decompress.py') -_OUT_DECOMP_JSON = '%s/%s' % (_OUT_FINALIZE_DECOMPRESSION_PATH, - 'decompress.json') - -_IS_WINDOWS = sys.platform in ['win32', 'cygwin'] - - -def _ToWinUncPath(dos_path, encoding=None): - """Windows supports long file names when using a UNC path.""" - assert _IS_WINDOWS - do_convert = (not isinstance(dos_path, unicode) and encoding is not None) - if do_convert: - dos_path = dos_path.decode(encoding) - path = os.path.abspath(dos_path) - if path.startswith(u'\\\\'): - return u'\\\\?\\UNC\\' + path[2:] - return u'\\\\?\\' + path - - -def _GetZipFileClass(): - """Get the ZipFile class for the platform""" - if not _IS_WINDOWS: - return zipfile.ZipFile - else: - class ZipFileLongPaths(zipfile.ZipFile): - """Handles extracting to paths longer than 255 characters.""" - - def _extract_member(self, member, targetpath, pwd): - targetpath = _ToWinUncPath(targetpath) - return zipfile.ZipFile._extract_member(self, member, targetpath, pwd) - return ZipFileLongPaths - - -def _UnzipFiles(input_zip_path, output_dir, outstream): - """Returns True if all files were extracted, else False.""" - if outstream is None: - outstream = sys.stdout - all_ok = True - zf_class = _GetZipFileClass() - with zf_class(input_zip_path, 'r', allowZip64=True) as zf: - for zinfo in zf.infolist(): - try: - logging.debug('Extracting: %s -> %s', zinfo.filename, output_dir) - zf.extract(zinfo, path=output_dir) - except Exception as err: # pylint: disable=broad-except - msg = 'Exception happend during bundle extraction: ' + str(err) + '\n' - outstream.write(msg) - all_ok = False - return all_ok - - -def _ExtractTo(archive_zip_path, output_dir, outstream=None): - """Returns True if all files were extracted, False otherwise.""" - outstream = outstream if outstream else sys.stdout - assert os.path.exists(archive_zip_path), 'No archive at %s' % archive_zip_path - logging.info('UNZIPPING %s -> %s', archive_zip_path, output_dir) - ok = _UnzipFiles(archive_zip_path, output_dir, outstream) - # Now that all files have been extracted, execute the final decompress - # step. - decomp_py = os.path.abspath(os.path.join(output_dir, _OUT_DECOMP_PY)) - assert(os.path.isfile(decomp_py)), decomp_py - cmd_str = 'python ' + decomp_py - outstream.write('Executing: %s\n' % cmd_str) - rc = subprocess.call(cmd_str, shell=True, stdout=outstream, - stderr=outstream) - ok = ok & (rc == 0) - return ok - - -def _CreateArgumentParser(): - """Creates a parser that will print the full help on failure to parse.""" - parser = argparse.ArgumentParser() - parser.add_argument('archive_path', help='Archive to extract.') - parser.add_argument('output_path', help='Output path to extract the archive.') - parser.add_argument('--delete', action='store_true', - help='Deletes output_path if it exists.') - parser.add_argument('--verbose', action='store_true') - return parser - - -def main(): - parser = _CreateArgumentParser() - # To make this future compatible parse_known_args() is used and any unknown - # args will generate a warning rather than be a fatal event. This allows - # any flags used in the future to be used on this tool. - args, unknown_args = parser.parse_known_args() - logging_lvl = logging.INFO - if args.verbose: - logging_lvl = logging.DEBUG - fmt = '[%(filename)s:%(lineno)s:%(levelname)s] %(message)s' - logging.basicConfig(format=fmt, level=logging_lvl) - if unknown_args: - logging.warning('Unknown (ignored) args: %s', unknown_args) - if args.delete: - logging.info('Removing previous folder at %s', args.output_path) - shutil.rmtree(args.output_path, ignore_errors=True) - all_ok = ExtractTo(args.archive_path, args.output_path) - if all_ok: - sys.exit(0) - else: - logging.critical('Errors happened.') - sys.exit(1) - - -if __name__ == '__main__': - main() -
diff --git a/src/cobalt/build/cobalt_archive_test.py b/src/cobalt/build/cobalt_archive_test.py deleted file mode 100644 index fe232e5..0000000 --- a/src/cobalt/build/cobalt_archive_test.py +++ /dev/null
@@ -1,215 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2019 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 json -import os -import shutil -import stat -import subprocess -import unittest - -import _env # pylint: disable=relative-import,unused-import -from cobalt.build import cobalt_archive -from starboard.build import filelist -from starboard.build import filelist_test -from starboard.build import port_symlink -from starboard.tools import util - - -class CobaltArchiveTest(unittest.TestCase): - - def testFoldIdenticalFiles(self): - tf_root = filelist_test.TempFileSystem('bundler_fold') - tf_root.Clear() - tf1 = filelist_test.TempFileSystem(os.path.join('bundler_fold', '1')) - tf2 = filelist_test.TempFileSystem(os.path.join('bundler_fold', '2')) - tf1.Make() - tf2.Make() - flist = filelist.FileList() - subdirs = [tf1.root_in_tmp, tf2.root_in_tmp] - flist.AddAllFilesInPaths(tf_root.root_tmp, subdirs) - flist.Print() - identical_files = [tf1.test_txt, tf2.test_txt] - physical_files, copy_files = cobalt_archive._FoldIdenticalFiles( - identical_files) - self.assertEqual(tf1.test_txt, physical_files[0]) - self.assertIn(tf1.test_txt, copy_files[0][0]) - self.assertIn(tf2.test_txt, copy_files[0][1]) - - def testMakesDeployInfo(self): - flist = filelist.FileList() - tf = filelist_test.TempFileSystem() - tf.Clear() - tf.Make() - bundle_zip = os.path.join(tf.root_tmp, 'bundle.zip') - car = cobalt_archive.CobaltArchive(bundle_zip) - car.MakeArchive(platform_name='fake', - platform_sdk_version='fake_sdk', - config='devel', - file_list=flist) - out_dir = os.path.join(tf.root_tmp, 'out') - car.ExtractTo(out_dir) - out_metadata_file = os.path.join(out_dir, cobalt_archive._OUT_METADATA_PATH) - self.assertEqual(filelist.GetFileType(out_metadata_file), - filelist.TYPE_FILE) - with open(out_metadata_file) as fd: - text = fd.read() - js = json.loads(text) - self.assertTrue(js) - self.assertEqual(js['sdk_version'], 'fake_sdk') - self.assertEqual(js['platform'], 'fake') - self.assertEqual(js['config'], 'devel') - - def testExtractTo(self): - flist = filelist.FileList() - tf = filelist_test.TempFileSystem() - tf.Clear() - tf.Make() - flist.AddFile(tf.root_in_tmp, tf.test_txt) - flist.AddSymLink(tf.root_in_tmp, tf.sym_dir) - bundle_zip = os.path.join(tf.root_tmp, 'bundle.zip') - car = cobalt_archive.CobaltArchive(bundle_zip) - car.MakeArchive(platform_name='fake', - platform_sdk_version='fake_sdk', - config='devel', - file_list=flist) - out_dir = os.path.join(tf.root_tmp, 'out') - car.ExtractTo(out_dir) - out_from_dir = os.path.join(out_dir, 'from_dir') - out_from_dir_lnk = os.path.join(out_dir, 'from_dir_lnk') - self.assertEqual(filelist.GetFileType(out_from_dir), - filelist.TYPE_DIRECTORY) - self.assertEqual(filelist.GetFileType(out_from_dir_lnk), - filelist.TYPE_SYMLINK_DIR) - resolved_from_link_path = os.path.join( - out_dir, port_symlink.ReadSymLink(out_from_dir_lnk)) - self.assertEqual(os.path.abspath(out_from_dir), - os.path.abspath(resolved_from_link_path)) - - def testExtractFileWithLongFileName(self): - """Tests that a long file name can be archived and extracted.""" - flist = filelist.FileList() - tf = filelist_test.TempFileSystem() - tf.Clear() - tf.Make() - self.assertTrue(os.path.exists(tf.root_in_tmp)) - suffix_path = os.path.join( - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'test.txt' - ) - input_dst = os.path.join(tf.root_in_tmp, suffix_path) - out_dir = os.path.join(tf.root_tmp, 'out') - output_dst = os.path.join(out_dir, suffix_path) - _MoveFileWithLongPath(tf.test_txt, input_dst) - self.assertTrue(_LongPathExists(input_dst)) - flist.AddFile(tf.root_in_tmp, input_dst) - - bundle_zip = os.path.join(tf.root_tmp, 'bundle.zip') - car = cobalt_archive.CobaltArchive(bundle_zip) - car.MakeArchive(platform_name='fake', - platform_sdk_version='fake_sdk', - config='devel', - file_list=flist) - car.ExtractTo(out_dir) - self.assertTrue(_LongPathExists(output_dst)) - - @unittest.skipIf(port_symlink.IsWindows(), 'Any platform but windows.') - def testExecutionAttribute(self): - flist = filelist.FileList() - tf = filelist_test.TempFileSystem() - tf.Make() - # Execution bit seems to turn off the read bit, so we just set all - # read/write/execute bit for the user. - write_flags = stat.S_IXUSR | stat.S_IWUSR | stat.S_IRUSR - os.chmod(tf.test_txt, write_flags) - self.assertNotEqual( - 0, write_flags & cobalt_archive._GetFilePermissions(tf.test_txt)) - flist.AddFile(tf.root_tmp, tf.test_txt) - bundle_zip = os.path.join(tf.root_tmp, 'bundle.zip') - car = cobalt_archive.CobaltArchive(bundle_zip) - car.MakeArchive(platform_name='fake', - platform_sdk_version='fake_sdk', - config='devel', - file_list=flist) - # Now grab the json file and check that the file appears in the - # executable_file list. - json_str = car.ReadFile( - '__cobalt_archive/finalize_decompression/decompress.json') - decompress_dict = json.loads(json_str) - executable_files = decompress_dict.get('executable_files') - # Expect that the executable file appears in the executable_files. - self.assertTrue(executable_files) - archive_path = os.path.relpath(tf.test_txt, tf.root_tmp) - self.assertIn(archive_path, executable_files) - out_dir = os.path.join(tf.root_tmp, 'out') - car.ExtractTo(output_dir=out_dir) - out_file = os.path.join(out_dir, tf.test_txt) - self.assertTrue(_LongPathExists(out_file)) - perms = cobalt_archive._GetFilePermissions(out_file) - self.assertTrue(perms & stat.S_IXUSR) - - -def _SilentCall(cmd_str): - proc = subprocess.Popen(cmd_str, - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - (_, _) = proc.communicate() - return proc.returncode - - -def _LongPathExists(p): - if port_symlink.IsWindows(): - rc = _SilentCall('dir /s /b "%s"' % p) - return rc == 0 - else: - return os.path.isfile(p) - - -def _MoveFileWithLongPath(src_file, dst_file): - dst_dir = os.path.dirname(dst_file) - if port_symlink.IsWindows(): - # Work around for file-length path limitations on Windows. - src_dir = os.path.dirname(src_file) - file_name = os.path.basename(src_file) - shell_cmd = 'robocopy "%s" "%s" "%s" /MOV' % (src_dir, dst_dir, file_name) - rc = _SilentCall(shell_cmd) - if 1 != rc: # Robocopy returns 1 if a file was copied. - raise OSError('File %s was not copied' % src_file) - expected_out_file = os.path.join(dst_dir, file_name) - if not _LongPathExists(expected_out_file): - raise OSError('File did not end up in %s' % dst_dir) - return - else: - if not os.path.isdir(dst_dir): - os.makedirs(dst_dir) - shutil.move(src_file, dst_file) - if not os.path.isfile(dst_file): - raise OSError('File did not end up in %s' % dst_dir) - - -if __name__ == '__main__': - util.SetupDefaultLoggingConfig() - unittest.main(verbosity=2)
diff --git a/src/cobalt/build/cobalt_configuration.gypi b/src/cobalt/build/cobalt_configuration.gypi index 9feeca1..995c8d6 100644 --- a/src/cobalt/build/cobalt_configuration.gypi +++ b/src/cobalt/build/cobalt_configuration.gypi
@@ -34,7 +34,8 @@ 'variables': { 'cobalt_webapi_extension_source_idl_files%': [], 'cobalt_webapi_extension_generated_header_idl_files%': [], - 'cobalt_v8_buildtime_snapshot%': "true", + 'cobalt_v8_buildtime_snapshot%': 1, + 'cobalt_v8_enable_embedded_builtins%': 1, }, # Whether Cobalt is being built. @@ -121,7 +122,7 @@ 'cobalt_version%': '<(BUILD_NUMBER)', # Defines what kind of rasterizer will be used. This can be adjusted to - # force a stub graphics implementation or software graphics implementation. + # force a stub graphics implementation. # It can be one of the following options: # 'direct-gles' -- Uses a light wrapper over OpenGL ES to handle most # draw elements. This will fall back to the skia hardware @@ -131,9 +132,6 @@ # 'hardware' -- As much hardware acceleration of graphics commands as # possible. This uses skia to wrap OpenGL ES commands. # Required for 360 rendering. - # 'software' -- Perform most rasterization using the CPU and only - # interact with the GPU to send the final image to the - # output window. # 'stub' -- Stub graphics rasterization. A rasterizer object will # still be available and valid, but it will do nothing. 'rasterizer_type%': 'direct-gles', @@ -586,7 +584,7 @@ 'ENABLE_DEBUGGER', ], }], - ['cobalt_v8_buildtime_snapshot == "true"', { + ['cobalt_v8_buildtime_snapshot == 1', { 'defines': [ 'COBALT_V8_BUILDTIME_SNAPSHOT=1', ], @@ -595,7 +593,14 @@ 'defines': [ 'COBALT_ENABLE_QUIC', ], - }] + }], + ['host_os=="win"', { + # A few flags to mute MSVC compiler errors that does not appear on Linux. + 'compiler_flags_host': [ + '/wd4267', # Possible loss of precision from size_t to a smaller type. + '/wd4715', # Not all control paths return value. + ], + }], ], }, # end of target_defaults
diff --git a/src/cobalt/build/cobalt_configuration.py b/src/cobalt/build/cobalt_configuration.py index ddb656e..bd661d4 100644 --- a/src/cobalt/build/cobalt_configuration.py +++ b/src/cobalt/build/cobalt_configuration.py
@@ -152,6 +152,7 @@ 'storage_upgrade_test', 'web_animations_test', 'webdriver_test', + 'websocket_test', 'xhr_test', ]
diff --git a/src/cobalt/csp/source_list.cc b/src/cobalt/csp/source_list.cc index e5098a4..71e54a8 100644 --- a/src/cobalt/csp/source_list.cc +++ b/src/cobalt/csp/source_list.cc
@@ -120,11 +120,14 @@ if (allow_insecure_connections_to_localhost_) { std::string host; -#if SB_HAS(IPV6) - host = url.HostNoBrackets(); -#else + // This will be our host string if we are not using IPV6. host.append(valid_spec.c_str() + parsed.host.begin, valid_spec.c_str() + parsed.host.begin + parsed.host.len); +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION || SB_HAS(IPV6) +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION + if (SbSocketIsIpv6Supported()) +#endif + host = url.HostNoBrackets(); #endif if (net::HostStringIsLocalhost(host)) { return true;
diff --git a/src/cobalt/cssom/property_definitions.cc b/src/cobalt/cssom/property_definitions.cc index 72d36ac..6a4db89 100644 --- a/src/cobalt/cssom/property_definitions.cc +++ b/src/cobalt/cssom/property_definitions.cc
@@ -884,7 +884,7 @@ SetShorthandPropertyDefinition(kBorderRadiusProperty, "border-radius", border_radius_longhand_properties); - // https://www.w3.org/TR/css3-background/#border + // https://www.w3.org/TR/css-backgrounds-3/#propdef-border LonghandPropertySet border_longhand_properties; border_longhand_properties.insert(kBorderColorProperty); border_longhand_properties.insert(kBorderStyleProperty);
diff --git a/src/cobalt/debug/backend/command_map.h b/src/cobalt/debug/backend/command_map.h index 4e01994..b929808 100644 --- a/src/cobalt/debug/backend/command_map.h +++ b/src/cobalt/debug/backend/command_map.h
@@ -42,18 +42,19 @@ : agent_(agent), domain_(domain) {} // Calls the mapped method implementation. - // Returns a true iff the command method is mapped and has been run. - bool RunCommand(const Command& command) { + // Passes ownership of the command to the mapped method, otherwise returns + // ownership of the not-run command for a fallback JS implementation. + std::unique_ptr<Command> RunCommand(std::unique_ptr<Command> command) { // If the domain matches, trim it and the dot from the method name. const std::string& method = - (domain_ == command.GetDomain()) - ? command.GetMethod().substr(domain_.size() + 1) - : command.GetMethod(); + (domain_ == command->GetDomain()) + ? command->GetMethod().substr(domain_.size() + 1) + : command->GetMethod(); auto iter = this->find(method); - if (iter == this->end()) return false; + if (iter == this->end()) return command; auto command_fn = iter->second; - (agent_->*command_fn)(command); - return true; + (agent_->*command_fn)(*command); + return nullptr; } // Binds |RunCommand| to a callback to be registered with |DebugDispatcher|.
diff --git a/src/cobalt/debug/backend/debug_dispatcher.cc b/src/cobalt/debug/backend/debug_dispatcher.cc index ec6f7f7..7454404 100644 --- a/src/cobalt/debug/backend/debug_dispatcher.cc +++ b/src/cobalt/debug/backend/debug_dispatcher.cc
@@ -22,6 +22,10 @@ #include "base/values.h" #include "cobalt/debug/debug_client.h" +namespace { +void NoOpResponseCallback(const base::Optional<std::string>& response) {} +} // namespace + namespace cobalt { namespace debug { namespace backend { @@ -78,13 +82,14 @@ clients_.erase(client); } -void DebugDispatcher::SendCommand(const Command& command) { +void DebugDispatcher::SendCommand(std::unique_ptr<Command> command) { // Create a closure that will run the command and the response callback. // The task is either posted to the debug target (WebModule) thread if // that thread is running normally, or added to a queue of debugger tasks // being processed while paused. - base::Closure command_closure = base::Bind(&DebugDispatcher::DispatchCommand, - base::Unretained(this), command); + base::Closure command_closure = + base::Bind(&DebugDispatcher::DispatchCommand, base::Unretained(this), + base::Passed(std::move(command))); if (is_paused_) { DispatchCommandWhilePaused(command_closure); @@ -93,26 +98,37 @@ } } -void DebugDispatcher::DispatchCommand(Command command) { +void DebugDispatcher::DispatchCommand(std::unique_ptr<Command> command) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DomainRegistry::iterator iter = domain_registry_.find(command.GetDomain()); - if (iter != domain_registry_.end() && iter->second.Run(command)) { - // The agent command implementation ran and sends its own response. - return; + // This workaround allows both the overlay console and remote DevTools to + // connect at the same time. Each time a client sends the "Runtime.enable" + // command, we first inject a "Runtime.disable" command so that the V8 + // Inspector will send the "Runtime.executionContextCreated" event for every + // "Runtime.enable" command rather than just for the first one. + if (command->GetMethod() == "Runtime.enable") { + DispatchCommand(std::make_unique<Command>( + "Runtime.disable", "", base::Bind(&NoOpResponseCallback))); + } + + DomainRegistry::iterator iter = domain_registry_.find(command->GetDomain()); + if (iter != domain_registry_.end()) { + command = iter->second.Run(std::move(command)); + // The agent command implementation kept the command to send the response. + if (!command) return; } // The agent didn't have a native implementation. Try to run a // JavaScript implementation (which the agent would have loaded at the // same time as it registered its domain command handler). JSONObject response = - RunScriptCommand(command.GetMethod(), command.GetParams()); + RunScriptCommand(command->GetMethod(), command->GetParams()); if (response) { - command.SendResponse(response); + command->SendResponse(response); } else { - DLOG(WARNING) << "Command not implemented: " << command.GetMethod(); - command.SendErrorResponse(Command::kMethodNotFound, - "Command not implemented"); + DLOG(WARNING) << "Command not implemented: " << command->GetMethod(); + command->SendErrorResponse(Command::kMethodNotFound, + "Command not implemented"); } }
diff --git a/src/cobalt/debug/backend/debug_dispatcher.h b/src/cobalt/debug/backend/debug_dispatcher.h index 41dc4fd..c114035 100644 --- a/src/cobalt/debug/backend/debug_dispatcher.h +++ b/src/cobalt/debug/backend/debug_dispatcher.h
@@ -106,8 +106,13 @@ std::set<DebugClient*> clients_; }; - // A command execution function stored in the domain registry. - typedef base::Callback<bool(const Command& command)> CommandHandler; + // A command execution function stored in the domain registry. If the command + // is supported, ownership of the command parameter should be kept and used to + // send the response. If the command is not supported, the command should be + // returned so the dispatcher can try calling a JS fallback implementation. + typedef base::Callback<std::unique_ptr<Command>( + std::unique_ptr<Command> command)> + CommandHandler; DebugDispatcher(script::ScriptDebugger* script_debugger, DebugScriptRunner* script_runner); @@ -150,7 +155,7 @@ // called from any thread - the command will be run on the dispatcher's // message loop, and the response will be sent to the callback and message // loop held in the command object. - void SendCommand(const Command& command); + void SendCommand(std::unique_ptr<Command> command); // Sets or unsets the paused state and calls |HandlePause| if set. // Must be called on the debug target (WebModule) thread. @@ -175,7 +180,7 @@ // name in the command registry and running the corresponding function. // The response callback will be run on the message loop specified in the // info structure with the result as an argument. - void DispatchCommand(Command command); + void DispatchCommand(std::unique_ptr<Command> command); // Called by |SendCommand| if a debugger command is received while script // execution is paused.
diff --git a/src/cobalt/debug/backend/debugger_hooks_impl.cc b/src/cobalt/debug/backend/debugger_hooks_impl.cc index 2ba4d2d..ef17028 100644 --- a/src/cobalt/debug/backend/debugger_hooks_impl.cc +++ b/src/cobalt/debug/backend/debugger_hooks_impl.cc
@@ -32,26 +32,28 @@ script_debugger_ = nullptr; } -void DebuggerHooksImpl::AsyncTaskScheduled(void* task, const std::string& name, - bool recurring) const { +void DebuggerHooksImpl::AsyncTaskScheduled(const void* task, + const std::string& name, + AsyncTaskFrequency frequency) const { if (script_debugger_) { - script_debugger_->AsyncTaskScheduled(task, name, recurring); + script_debugger_->AsyncTaskScheduled( + task, name, (frequency == AsyncTaskFrequency::kRecurring)); } } -void DebuggerHooksImpl::AsyncTaskStarted(void* task) const { +void DebuggerHooksImpl::AsyncTaskStarted(const void* task) const { if (script_debugger_) { script_debugger_->AsyncTaskStarted(task); } } -void DebuggerHooksImpl::AsyncTaskFinished(void* task) const { +void DebuggerHooksImpl::AsyncTaskFinished(const void* task) const { if (script_debugger_) { script_debugger_->AsyncTaskFinished(task); } } -void DebuggerHooksImpl::AsyncTaskCanceled(void* task) const { +void DebuggerHooksImpl::AsyncTaskCanceled(const void* task) const { if (script_debugger_) { script_debugger_->AsyncTaskCanceled(task); }
diff --git a/src/cobalt/debug/backend/debugger_hooks_impl.h b/src/cobalt/debug/backend/debugger_hooks_impl.h index 17a6115..a856cb1 100644 --- a/src/cobalt/debug/backend/debugger_hooks_impl.h +++ b/src/cobalt/debug/backend/debugger_hooks_impl.h
@@ -31,11 +31,11 @@ class DebuggerHooksImpl : public base::DebuggerHooks { public: - void AsyncTaskScheduled(void* task, const std::string& name, - bool recurring) const override; - void AsyncTaskStarted(void* task) const override; - void AsyncTaskFinished(void* task) const override; - void AsyncTaskCanceled(void* task) const override; + void AsyncTaskScheduled(const void* task, const std::string& name, + AsyncTaskFrequency frequency) const override; + void AsyncTaskStarted(const void* task) const override; + void AsyncTaskFinished(const void* task) const override; + void AsyncTaskCanceled(const void* task) const override; private: // Only DebugModule can attach/detach the debugger.
diff --git a/src/cobalt/debug/backend/script_debugger_agent.cc b/src/cobalt/debug/backend/script_debugger_agent.cc index c9afc99..c2c312f 100644 --- a/src/cobalt/debug/backend/script_debugger_agent.cc +++ b/src/cobalt/debug/backend/script_debugger_agent.cc
@@ -61,7 +61,8 @@ return agent_state; } -bool ScriptDebuggerAgent::RunCommand(const Command& command) { +std::unique_ptr<Command> ScriptDebuggerAgent::RunCommand( + std::unique_ptr<Command> command) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // Use an internal ID to store the pending command until we get a response. @@ -69,21 +70,26 @@ JSONObject message(new base::DictionaryValue()); message->SetInteger(kId, command_id); - message->SetString(kMethod, command.GetMethod()); - JSONObject params = JSONParse(command.GetParams()); + message->SetString(kMethod, command->GetMethod()); + JSONObject params = JSONParse(command->GetParams()); if (params) { message->Set(kParams, std::move(params)); } // Store the pending command before dispatching it so that we can find it if // the script debugger sends a synchronous response before returning. - pending_commands_.emplace(command_id, command); - if (!script_debugger_->DispatchProtocolMessage(command.GetMethod(), - JSONStringify(message))) { - pending_commands_.erase(command_id); - return false; + std::string method = command->GetMethod(); + pending_commands_.emplace(command_id, std::move(command)); + if (script_debugger_->DispatchProtocolMessage(method, + JSONStringify(message))) { + // The command has been dispached; keep ownership of it in the map. + return nullptr; } - return true; + + // Take the command back out of the map and return it for fallback. + command = std::move(pending_commands_.at(command_id)); + pending_commands_.erase(command_id); + return command; } void ScriptDebuggerAgent::SendCommandResponse( @@ -98,7 +104,7 @@ // Use the stripped ID to lookup the command it's a response for. auto iter = pending_commands_.find(command_id); if (iter != pending_commands_.end()) { - iter->second.SendResponse(response); + iter->second->SendResponse(response); pending_commands_.erase(iter); } else { DLOG(ERROR) << "Spurious debugger response: " << json_response;
diff --git a/src/cobalt/debug/backend/script_debugger_agent.h b/src/cobalt/debug/backend/script_debugger_agent.h index ef6956d..7e906f0 100644 --- a/src/cobalt/debug/backend/script_debugger_agent.h +++ b/src/cobalt/debug/backend/script_debugger_agent.h
@@ -41,7 +41,7 @@ bool IsSupportedDomain(const std::string& domain) { return supported_domains_.count(domain) != 0; } - bool RunCommand(const Command& command); + std::unique_ptr<Command> RunCommand(std::unique_ptr<Command> command); void SendCommandResponse(const std::string& json_response); void SendEvent(const std::string& json_event); @@ -53,7 +53,7 @@ const std::set<std::string> supported_domains_; int last_command_id_ = 0; - std::map<int, Command> pending_commands_; + std::map<int, std::unique_ptr<Command>> pending_commands_; }; } // namespace backend
diff --git a/src/cobalt/debug/command.h b/src/cobalt/debug/command.h index 05659d5..f403d48 100644 --- a/src/cobalt/debug/command.h +++ b/src/cobalt/debug/command.h
@@ -42,14 +42,17 @@ kServerError = -32000, }; - explicit Command(const std::string& method, const std::string& json_params, - const DebugClient::ResponseCallback& response_callback) + Command(const std::string& method, const std::string& json_params, + const DebugClient::ResponseCallback& response_callback) : method_(method), domain_(method_, 0, method_.find('.')), json_params_(json_params), callback_(response_callback), task_runner_(base::MessageLoop::current()->task_runner()) {} + Command(Command&) = delete; + Command(Command&&) = delete; + const std::string& GetMethod() const { return method_; } const std::string& GetDomain() const { return domain_; } const std::string& GetParams() const { return json_params_; }
diff --git a/src/cobalt/debug/debug_client.cc b/src/cobalt/debug/debug_client.cc index db21401..cfb9269 100644 --- a/src/cobalt/debug/debug_client.cc +++ b/src/cobalt/debug/debug_client.cc
@@ -67,7 +67,8 @@ DLOG(WARNING) << "Debug client is not attached to dispatcher."; return; } - dispatcher_->SendCommand(Command(method, json_params, callback)); + dispatcher_->SendCommand( + std::make_unique<Command>(method, json_params, callback)); } } // namespace debug
diff --git a/src/cobalt/debug/remote/debug_web_server.cc b/src/cobalt/debug/remote/debug_web_server.cc index ef83a5c..1f27f07 100644 --- a/src/cobalt/debug/remote/debug_web_server.cc +++ b/src/cobalt/debug/remote/debug_web_server.cc
@@ -79,38 +79,6 @@ return base::nullopt; } -base::Optional<std::string> GetLocalIpAddress() { - net::IPEndPoint ip_addr; - SbSocketAddress local_ip; - SbMemorySet(&local_ip, 0, sizeof(local_ip)); - bool result = false; - - // Prefer IPv4 addresses, as they're easier to type for debugging. - SbSocketAddressType address_types[] = {kSbSocketAddressTypeIpv4, - kSbSocketAddressTypeIpv6}; - - for (std::size_t i = 0; i != SB_ARRAY_SIZE(address_types); ++i) { - SbSocketAddress destination; - SbMemorySet(&(destination.address), 0, sizeof(destination.address)); - destination.type = address_types[i]; - if (!SbSocketGetInterfaceAddress(&destination, &local_ip, NULL)) { - continue; - } - - if (ip_addr.FromSbSocketAddress(&local_ip)) { - result = true; - break; - } - } - - if (!result) { - DLOG(WARNING) << "Unable to get a local interface address."; - return base::nullopt; - } - - return ip_addr.ToStringWithoutPort(); -} - const char kContentDir[] = "cobalt/debug/remote"; const char kDetached[] = "Inspector.detached"; const char kDetachReasonField[] = "params.reason"; @@ -121,13 +89,16 @@ constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotation = net::DefineNetworkTrafficAnnotation("cobalt_debug_web_server", "cobalt_debug_web_server"); + +constexpr int kUnattachedWebSocketId = -1; } // namespace DebugWebServer::DebugWebServer( - int port, const CreateDebugClientCallback& create_debug_client_callback) + int port, const std::string& listen_ip, + const CreateDebugClientCallback& create_debug_client_callback) : http_server_thread_("DebugWebServer"), create_debug_client_callback_(create_debug_client_callback), - websocket_id_(-1), + websocket_id_(kUnattachedWebSocketId), // Local address will be set when the web server is successfully started. local_address_("Cobalt.Server.DevTools", "<NOT RUNNING>", "Address to connect to for remote debugging.") { @@ -142,8 +113,8 @@ http_server_thread_.StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, stack_size)); http_server_thread_.message_loop()->task_runner()->PostTask( - FROM_HERE, - base::Bind(&DebugWebServer::StartServer, base::Unretained(this), port)); + FROM_HERE, base::Bind(&DebugWebServer::StartServer, + base::Unretained(this), port, listen_ip)); } DebugWebServer::~DebugWebServer() { @@ -213,6 +184,11 @@ std::string path = info.path; DLOG(INFO) << "Got web socket request [" << connection_id << "]: " << path; + // Disconnect any other DevTools client that's already attached. + if (websocket_id_ != kUnattachedWebSocketId) { + server_->Close(websocket_id_); + } + // Ignore the path and bind any web socket request to the debugger. websocket_id_ = connection_id; server_->AcceptWebSocket(connection_id, info, kNetworkTrafficAnnotation); @@ -220,10 +196,16 @@ debug_client_ = create_debug_client_callback_.Run(this); } +void DebugWebServer::OnClose(int connection_id) { + if (connection_id == websocket_id_) { + websocket_id_ = kUnattachedWebSocketId; + } +} + void DebugWebServer::OnWebSocketMessage(int connection_id, const std::string& json) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK_EQ(connection_id, websocket_id_); + DCHECK_EQ(connection_id, websocket_id_) << "Mismatched WebSocket ID"; // Parse the json string to get id, method and params. JSONObject json_object = JSONParse(json); @@ -324,35 +306,21 @@ kNetworkTrafficAnnotation); } -int DebugWebServer::GetLocalAddress(std::string* out) const { - net::IPEndPoint ip_addr; - int result = server_->GetLocalAddress(&ip_addr); - if (result == net::OK) { - *out = std::string("http://") + ip_addr.ToString(); - } - return result; -} - -void DebugWebServer::StartServer(int port) { +void DebugWebServer::StartServer(int port, const std::string& listen_ip) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // Create http server - const base::Optional<std::string> ip_addr = GetLocalIpAddress(); - if (!ip_addr) { - DLOG(WARNING) - << "Could not get a local IP address for the debug web server."; - return; - } auto* server_socket = new net::TCPServerSocket(NULL /*net_log*/, net::NetLogSource()); server_socket->ListenWithAddressAndPort( - ip_addr.value(), static_cast<uint16_t>(port), 1 /*backlog*/); + listen_ip, static_cast<uint16_t>(port), 1 /*backlog*/); server_.reset(new net::HttpServer( std::unique_ptr<net::ServerSocket>(server_socket), this)); - std::string address; - int result = GetLocalAddress(&address); + net::IPEndPoint ip_addr; + int result = server_->GetLocalInterfaceAddress(&ip_addr); if (result == net::OK) { + std::string address = "http://" + ip_addr.ToString(); // clang-format off LOG(INFO) << "\n---------------------------------" << "\n Connect to the web debugger at:"
diff --git a/src/cobalt/debug/remote/debug_web_server.h b/src/cobalt/debug/remote/debug_web_server.h index 896de2d..af57a25 100644 --- a/src/cobalt/debug/remote/debug_web_server.h +++ b/src/cobalt/debug/remote/debug_web_server.h
@@ -38,7 +38,7 @@ class DebugWebServer : public net::HttpServer::Delegate, public DebugClient::Delegate { public: - DebugWebServer(int port, + DebugWebServer(int port, const std::string& listen_ip, const CreateDebugClientCallback& create_debug_client_callback); ~DebugWebServer(); @@ -53,7 +53,7 @@ void OnWebSocketMessage(int connection_id, const std::string& json) override; - void OnClose(int /*connection_id*/) override {} + void OnClose(int connection_id) override; // Debugger command response handler. void OnDebuggerResponse(int id, const base::Optional<std::string>& response); @@ -66,9 +66,7 @@ void OnDebugClientDetach(const std::string& reason) override; private: - int GetLocalAddress(std::string* out) const; - - void StartServer(int port); + void StartServer(int port, const std::string& listen_ip); void StopServer();
diff --git a/src/cobalt/debug/remote/devtools/inspector_protocol/inspector_protocol.gyp b/src/cobalt/debug/remote/devtools/inspector_protocol/inspector_protocol.gyp index 6137633..4ff730e 100644 --- a/src/cobalt/debug/remote/devtools/inspector_protocol/inspector_protocol.gyp +++ b/src/cobalt/debug/remote/devtools/inspector_protocol/inspector_protocol.gyp
@@ -29,7 +29,7 @@ 'input_files': [ 'browser_protocol.pdl', 'browser_protocol-1.3.json', - '<(DEPTH)/v8/src/inspector/js_protocol.json', + '<(DEPTH)/v8/include/js_protocol.pdl', ], 'stamp_file': '<(SHARED_INTERMEDIATE_DIR)/cobalt/debug/remote/inspector_protocol/browser_protocol.stamp', }, @@ -57,7 +57,7 @@ 'script_path': '<(DEPTH)/third_party/inspector_protocol/concatenate_protocols.py', 'input_files': [ 'browser_protocol.pdl', - '<(DEPTH)/v8/src/inspector/js_protocol.json', + '<(DEPTH)/v8/include/js_protocol.pdl', ], 'output_file': '<(SHARED_INTERMEDIATE_DIR)/cobalt/debug/remote/inspector_protocol/inspector_protocol.json', },
diff --git a/src/cobalt/demos/content/deep-link-demo/deep-link-demo.html b/src/cobalt/demos/content/deep-link-demo/deep-link-demo.html index a99d33d..011fdf0 100644 --- a/src/cobalt/demos/content/deep-link-demo/deep-link-demo.html +++ b/src/cobalt/demos/content/deep-link-demo/deep-link-demo.html
@@ -5,9 +5,9 @@ console.log("h5vcc.runtime.initialDeepLink: " + h5vcc.runtime.initialDeepLink); - h5vcc.runtime.onDeepLink = function(link) { + h5vcc.runtime.onDeepLink.addListener(function(link) { console.log("h5vcc.runtime.onDeepLink: " + link); - }; + }); </script> </head> <body style="background-color:#48C"></body>
diff --git a/src/cobalt/demos/content/system-caption-settings/index.html b/src/cobalt/demos/content/system-caption-settings/index.html new file mode 100644 index 0000000..48afae3 --- /dev/null +++ b/src/cobalt/demos/content/system-caption-settings/index.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> + <head> + <style> + #captionWindow { + position: absolute; + bottom: 10px; + text-align: center; + padding: 25px; + } + </style> + </head> + <body> + <div id="captionWindow"> + <span id="caption">Captions will look like this</span> + </div> + </body> + <script> + // Ignore characterEdgeStyle attribute because it is currently unsupported by Cobalt. + // + // Ignore fontFamily, backgroundOpacity, fontOpacity, and windowOpacity attributes because + // they require lengthy conversion (and will likely be provided if the other attributes are). + + let settings = navigator.systemCaptionSettings; + console.log(settings); + + let setCaptionStyle = (elementId, cssProperty, state, captionStyle) => { + if (state == "set" || state == "override") { + document.getElementById(elementId).style[cssProperty] = captionStyle; + } + } + + setCaptionStyle("caption", "backgroundColor", settings.backgroundColorState, settings.backgroundColor); + setCaptionStyle("caption", "color", settings.fontColorState, settings.fontColor); + setCaptionStyle("caption", "fontSize", settings.fontSizeState, `${settings.fontSize}px`); + setCaptionStyle("captionWindow", "backgroundColor", settings.windowColorState, settings.windowColor); + </script> +</html>
diff --git a/src/cobalt/doc/net_log.md b/src/cobalt/doc/net_log.md new file mode 100644 index 0000000..dfc3c98 --- /dev/null +++ b/src/cobalt/doc/net_log.md
@@ -0,0 +1,30 @@ +# Cobalt NetLog + +Chromium has a very useful network diagnostic tool called the NetLog and Cobalt +is hooked up to use it. It's the main tool to track network traffic and debug +network code. + +### Activate the NetLog + +The following command line switch will activate the NetLog and store net log +record to the specified location. +`./cobalt --net_log=/PATH/TO/YOUR_NETLOG_NAME.json` +The output json file will be stored at the file location you choose. + + +### Read the NetLog records + +The produced json file is not human-friendly, use the +[NetLog Viewer](https://netlog-viewer.appspot.com/#import) + +Cobalt's net_log can not enable some features in the web viewer, but all the +network traffic is recorded in the event tab. + + +### Add NetLog entries + +To Add NetLog entry, get the NetLog instance owned by NetworkModule to where you +want to add entries and start/end your entry according to the NetLog interface. + +A NetLog object is created at each NetworkModule initialization and is passed +into Chromium net through URLRequestContext.
diff --git a/src/cobalt/doc/web_debugging.md b/src/cobalt/doc/web_debugging.md index ca1d90d..b43a59b 100644 --- a/src/cobalt/doc/web_debugging.md +++ b/src/cobalt/doc/web_debugging.md
@@ -39,10 +39,9 @@ > If you have trouble connecting: > * Ensure you have an IP route from your desktop to the target device that > allows traffic on the debugging port (default 9222). -> * If both IPv4 andIPv6 networks are available, the debug server will prefer to -> bind to the IPv4 network interface. -> * If you are running Cobalt locally on your desktop, then use your actual IP -> address (not localhost nor 127.0.0.1). +> * If you are running Cobalt locally on your desktop, then use +> http://localhost:9222 since the Linux build only listens to the loopback +> network interface by default. If you're not sure what IP address to use, look in the terminal log output for a message telling you the URL of Cobalt's DevTools (which you may be able to open @@ -174,3 +173,6 @@ * You can use the `--remote_debugging_port` command line switch to specify a remote debugging port other than the default 9222. + +* You can use the `--dev_servers_listen_ip` command line switch to change + which network interface the remote debugging server is listening to.
diff --git a/src/cobalt/dom/abort_controller.cc b/src/cobalt/dom/abort_controller.cc index 546d5c4..68ccb9a 100644 --- a/src/cobalt/dom/abort_controller.cc +++ b/src/cobalt/dom/abort_controller.cc
@@ -17,8 +17,8 @@ namespace cobalt { namespace dom { -AbortController::AbortController() { - abort_signal_ = new AbortSignal(); +AbortController::AbortController(script::EnvironmentSettings* settings) { + abort_signal_ = new AbortSignal(settings); } void AbortController::Abort() {
diff --git a/src/cobalt/dom/abort_controller.h b/src/cobalt/dom/abort_controller.h index be273b0..e8d0c5d 100644 --- a/src/cobalt/dom/abort_controller.h +++ b/src/cobalt/dom/abort_controller.h
@@ -16,6 +16,8 @@ #define COBALT_DOM_ABORT_CONTROLLER_H_ #include "cobalt/dom/abort_signal.h" +#include "cobalt/script/environment_settings.h" +#include "cobalt/script/global_environment.h" #include "cobalt/script/wrappable.h" namespace cobalt { @@ -26,7 +28,7 @@ class AbortController : public script::Wrappable { public: // Web API: AbortController - AbortController(); + explicit AbortController(script::EnvironmentSettings* settings); const scoped_refptr<AbortSignal>& signal() const { return abort_signal_; } void Abort();
diff --git a/src/cobalt/dom/abort_controller.idl b/src/cobalt/dom/abort_controller.idl index 7612f56..36ebebd 100644 --- a/src/cobalt/dom/abort_controller.idl +++ b/src/cobalt/dom/abort_controller.idl
@@ -14,7 +14,10 @@ // https://dom.spec.whatwg.org/#interface-abortcontroller -[Constructor] +[ + Constructor, + ConstructorCallWith=EnvironmentSettings, +] interface AbortController { [SameObject] readonly attribute AbortSignal signal; void abort();
diff --git a/src/cobalt/dom/abort_signal.h b/src/cobalt/dom/abort_signal.h index 69db444..e544e31 100644 --- a/src/cobalt/dom/abort_signal.h +++ b/src/cobalt/dom/abort_signal.h
@@ -19,6 +19,7 @@ #include "cobalt/base/tokens.h" #include "cobalt/dom/event_target.h" +#include "cobalt/script/environment_settings.h" namespace cobalt { namespace dom { @@ -27,7 +28,8 @@ // https://dom.spec.whatwg.org/#interface-AbortSignal class AbortSignal : public EventTarget { public: - AbortSignal() {} + explicit AbortSignal(script::EnvironmentSettings* settings) + : EventTarget(settings) {} // Web API: AbortSignal bool aborted() const { return aborted_; }
diff --git a/src/cobalt/dom/animation_frame_request_callback_list.cc b/src/cobalt/dom/animation_frame_request_callback_list.cc index eaa9cab..2b27de6 100644 --- a/src/cobalt/dom/animation_frame_request_callback_list.cc +++ b/src/cobalt/dom/animation_frame_request_callback_list.cc
@@ -15,6 +15,7 @@ #include "cobalt/dom/animation_frame_request_callback_list.h" #include "base/trace_event/trace_event.h" +#include "cobalt/base/debugger_hooks.h" #include "cobalt/dom/global_stats.h" namespace cobalt { @@ -30,6 +31,9 @@ frame_request_callbacks_.emplace_back( new FrameRequestCallbackWithCancelledFlag(owner_, frame_request_callback)); + debugger_hooks_->AsyncTaskScheduled( + frame_request_callbacks_.back().get(), "requestAnimationFrame", + base::DebuggerHooks::AsyncTaskFrequency::kOneshot); return static_cast<int32>(frame_request_callbacks_.size()); } @@ -38,7 +42,9 @@ // frame request callback. const size_t handle = static_cast<size_t>(in_handle); if (handle > 0 && handle <= frame_request_callbacks_.size()) { - frame_request_callbacks_[handle - 1]->cancelled = true; + auto& callback = frame_request_callbacks_.at(handle - 1); + debugger_hooks_->AsyncTaskCanceled(callback.get()); + callback->cancelled = true; } } @@ -52,6 +58,7 @@ for (InternalList::const_iterator iter = frame_request_callbacks_.begin(); iter != frame_request_callbacks_.end(); ++iter) { if (!(*iter)->cancelled) { + base::ScopedAsyncTask async_task(debugger_hooks_, iter->get()); (*iter)->callback.value().Run(animation_time); } }
diff --git a/src/cobalt/dom/animation_frame_request_callback_list.h b/src/cobalt/dom/animation_frame_request_callback_list.h index 83a22ae..a809cd9 100644 --- a/src/cobalt/dom/animation_frame_request_callback_list.h +++ b/src/cobalt/dom/animation_frame_request_callback_list.h
@@ -23,6 +23,10 @@ #include "cobalt/script/script_value.h" #include "cobalt/script/wrappable.h" +namespace base { +class DebuggerHooks; +} + namespace cobalt { namespace dom { @@ -34,8 +38,9 @@ typedef script::CallbackFunction<void(double)> FrameRequestCallback; typedef script::ScriptValue<FrameRequestCallback> FrameRequestCallbackArg; - explicit AnimationFrameRequestCallbackList(script::Wrappable* const owner) - : owner_(owner) {} + explicit AnimationFrameRequestCallbackList( + script::Wrappable* const owner, base::DebuggerHooks* const debugger_hooks) + : owner_(owner), debugger_hooks_(debugger_hooks) {} int32 RequestAnimationFrame( const FrameRequestCallbackArg& frame_request_callback); @@ -63,6 +68,7 @@ InternalList; script::Wrappable* const owner_; + base::DebuggerHooks* const debugger_hooks_; // Our list of frame request callbacks. InternalList frame_request_callbacks_; };
diff --git a/src/cobalt/dom/audio_track_list.h b/src/cobalt/dom/audio_track_list.h index 130f006..0e5662d 100644 --- a/src/cobalt/dom/audio_track_list.h +++ b/src/cobalt/dom/audio_track_list.h
@@ -18,6 +18,7 @@ #include "cobalt/dom/audio_track.h" #include "cobalt/dom/html_media_element.h" #include "cobalt/dom/track_list_base.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/wrappable.h" namespace cobalt { @@ -29,8 +30,9 @@ public: // Custom, not in any spec. // - explicit AudioTrackList(HTMLMediaElement* media_element) - : TrackListBase<AudioTrack>(media_element) {} + AudioTrackList(script::EnvironmentSettings* settings, + HTMLMediaElement* media_element) + : TrackListBase<AudioTrack>(settings, media_element) {} // Web API: AudioTrackList //
diff --git a/src/cobalt/dom/captions/system_caption_settings.cc b/src/cobalt/dom/captions/system_caption_settings.cc index 42f65a5..876057b 100644 --- a/src/cobalt/dom/captions/system_caption_settings.cc +++ b/src/cobalt/dom/captions/system_caption_settings.cc
@@ -35,7 +35,7 @@ namespace dom { namespace captions { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) namespace { CaptionColor ToCobaltCaptionColor(SbAccessibilityCaptionColor color) { @@ -173,7 +173,7 @@ } // namespace -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) void SystemCaptionSettings::OnCaptionSettingsChanged() { DispatchEventNameAndRunCallback( @@ -182,7 +182,7 @@ } base::Optional<std::string> SystemCaptionSettings::background_color() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -200,11 +200,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::background_color_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -215,11 +215,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } base::Optional<std::string> SystemCaptionSettings::background_opacity() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -237,11 +237,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::background_opacity_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -252,11 +252,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } base::Optional<std::string> SystemCaptionSettings::character_edge_style() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -276,11 +276,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::character_edge_style_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -291,11 +291,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } base::Optional<std::string> SystemCaptionSettings::font_color() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -313,11 +313,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::font_color_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -328,11 +328,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } base::Optional<std::string> SystemCaptionSettings::font_family() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -350,11 +350,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::font_family_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -365,11 +365,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } base::Optional<std::string> SystemCaptionSettings::font_opacity() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -387,11 +387,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::font_opacity_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -402,11 +402,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } base::Optional<std::string> SystemCaptionSettings::font_size() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -425,11 +425,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::font_size_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -440,11 +440,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } base::Optional<std::string> SystemCaptionSettings::window_color() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -462,11 +462,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::window_color_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -477,11 +477,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } base::Optional<std::string> SystemCaptionSettings::window_opacity() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -499,11 +499,11 @@ } #else return base::nullopt; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } CaptionState SystemCaptionSettings::window_opacity_state() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -514,11 +514,11 @@ } #else return CaptionState::kCaptionStateUnsupported; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } bool SystemCaptionSettings::is_enabled() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -527,7 +527,7 @@ #else return false; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } void SystemCaptionSettings::set_is_enabled(bool active) { @@ -535,7 +535,7 @@ } bool SystemCaptionSettings::supports_is_enabled() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -544,11 +544,11 @@ #else return false; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } bool SystemCaptionSettings::supports_set_enabled() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -557,11 +557,11 @@ #else return false; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } bool SystemCaptionSettings::supports_override() { -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) SbAccessibilityCaptionSettings caption_settings; SbMemorySet(&caption_settings, 0, sizeof(caption_settings)); bool success = SbAccessibilityGetCaptionSettings(&caption_settings); @@ -570,7 +570,7 @@ #else return false; -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } const EventTarget::EventListenerScriptValue* SystemCaptionSettings::onchanged()
diff --git a/src/cobalt/dom/captions/system_caption_settings.h b/src/cobalt/dom/captions/system_caption_settings.h index e9af9c0..f48c6f8 100644 --- a/src/cobalt/dom/captions/system_caption_settings.h +++ b/src/cobalt/dom/captions/system_caption_settings.h
@@ -27,6 +27,7 @@ #include "cobalt/dom/captions/caption_opacity_percentage.h" #include "cobalt/dom/captions/caption_state.h" #include "cobalt/dom/event_target.h" +#include "cobalt/script/environment_settings.h" namespace cobalt { namespace dom { @@ -34,7 +35,8 @@ class SystemCaptionSettings : public EventTarget { public: - SystemCaptionSettings() {} + explicit SystemCaptionSettings(script::EnvironmentSettings* settings) + : EventTarget(settings) {} base::Optional<std::string> background_color(); CaptionState background_color_state();
diff --git a/src/cobalt/dom/captions/system_caption_settings.idl b/src/cobalt/dom/captions/system_caption_settings.idl index fbb8d79..46a5bc0 100644 --- a/src/cobalt/dom/captions/system_caption_settings.idl +++ b/src/cobalt/dom/captions/system_caption_settings.idl
@@ -41,7 +41,6 @@ // not supported, it will return false. If you try to write to it and doing so // is not supported, the value will silently not change. -[Constructor] interface SystemCaptionSettings : EventTarget { // TODO: Make the functions for style properties return nullable enum types @@ -101,4 +100,4 @@ attribute EventHandler onchanged; -}; \ No newline at end of file +};
diff --git a/src/cobalt/dom/crypto_test.cc b/src/cobalt/dom/crypto_test.cc index 2e714a2..f629920 100644 --- a/src/cobalt/dom/crypto_test.cc +++ b/src/cobalt/dom/crypto_test.cc
@@ -16,6 +16,7 @@ #include "cobalt/dom/crypto.h" +#include "base/test/scoped_task_environment.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/dom/dom_exception.h" #include "cobalt/dom/dom_settings.h" @@ -40,6 +41,7 @@ TEST(CryptoTest, GetRandomValues) { StrictMock<MockExceptionState> exception_state; + base::test::ScopedTaskEnvironment task_env_; std::unique_ptr<script::JavaScriptEngine> javascript_engine = script::JavaScriptEngine::CreateEngine(); scoped_refptr<script::GlobalEnvironment> global_environment = @@ -92,6 +94,7 @@ scoped_refptr<Crypto> crypto = new Crypto; StrictMock<MockExceptionState> exception_state; scoped_refptr<script::ScriptException> exception; + base::test::ScopedTaskEnvironment task_env_; std::unique_ptr<script::JavaScriptEngine> javascript_engine = script::JavaScriptEngine::CreateEngine(); scoped_refptr<script::GlobalEnvironment> global_environment = @@ -115,6 +118,7 @@ // QuotaExceededErr. scoped_refptr<Crypto> crypto = new Crypto; StrictMock<MockExceptionState> exception_state; + base::test::ScopedTaskEnvironment task_env_; std::unique_ptr<script::JavaScriptEngine> javascript_engine = script::JavaScriptEngine::CreateEngine(); scoped_refptr<script::GlobalEnvironment> global_environment =
diff --git a/src/cobalt/dom/custom_event_test.cc b/src/cobalt/dom/custom_event_test.cc index 1c12230..5d19f85 100644 --- a/src/cobalt/dom/custom_event_test.cc +++ b/src/cobalt/dom/custom_event_test.cc
@@ -21,12 +21,12 @@ #include "base/callback.h" #include "base/optional.h" #include "base/threading/platform_thread.h" -#include "cobalt/base/debugger_hooks.h" #include "cobalt/css_parser/parser.h" #include "cobalt/cssom/viewport_size.h" #include "cobalt/dom/custom_event_init.h" #include "cobalt/dom/local_storage_database.h" #include "cobalt/dom/testing/gtest_workarounds.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/window.h" #include "cobalt/dom_parser/parser.h" #include "cobalt/loader/fetcher_factory.h" @@ -60,7 +60,7 @@ public: CustomEventTest() : message_loop_(base::MessageLoop::TYPE_DEFAULT), - environment_settings_(new script::EnvironmentSettings), + environment_settings_(new testing::StubEnvironmentSettings), css_parser_(css_parser::Parser::Create()), dom_parser_(new dom_parser::Parser(mock_error_callback_)), fetcher_factory_(new loader::FetcherFactory(NULL)), @@ -72,10 +72,10 @@ engine_ = script::JavaScriptEngine::CreateEngine(); global_environment_ = engine_->CreateGlobalEnvironment(); window_ = new Window( - ViewportSize(1920, 1080), 1.f, base::kApplicationStateStarted, - css_parser_.get(), dom_parser_.get(), fetcher_factory_.get(), - loader_factory_.get(), NULL, NULL, NULL, NULL, NULL, NULL, - &local_storage_database_, NULL, NULL, NULL, NULL, + environment_settings_.get(), ViewportSize(1920, 1080), 1.f, + base::kApplicationStateStarted, css_parser_.get(), dom_parser_.get(), + fetcher_factory_.get(), loader_factory_.get(), NULL, NULL, NULL, NULL, + NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, global_environment_->script_value_factory(), NULL, NULL, url_, "", "en-US", "en", base::Callback<void(const GURL&)>(), base::Bind(&MockErrorCallback::Run, @@ -87,8 +87,7 @@ base::Closure() /* window_minimize */, NULL, NULL, NULL, dom::Window::OnStartDispatchEventCallback(), dom::Window::OnStopDispatchEventCallback(), - dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), NULL, - null_debugger_hooks_); + dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), NULL); global_environment_->CreateGlobalObject(window_, environment_settings_.get()); } @@ -98,7 +97,7 @@ private: base::MessageLoop message_loop_; std::unique_ptr<script::JavaScriptEngine> engine_; - const std::unique_ptr<script::EnvironmentSettings> environment_settings_; + const std::unique_ptr<testing::StubEnvironmentSettings> environment_settings_; scoped_refptr<script::GlobalEnvironment> global_environment_; MockErrorCallback mock_error_callback_; std::unique_ptr<css_parser::Parser> css_parser_; @@ -107,7 +106,6 @@ std::unique_ptr<loader::LoaderFactory> loader_factory_; dom::LocalStorageDatabase local_storage_database_; GURL url_; - base::NullDebuggerHooks null_debugger_hooks_; scoped_refptr<Window> window_; };
diff --git a/src/cobalt/dom/directionality.h b/src/cobalt/dom/directionality.h index 0ae5659..5c6f825 100644 --- a/src/cobalt/dom/directionality.h +++ b/src/cobalt/dom/directionality.h
@@ -20,10 +20,8 @@ // The enum Directionality is used to track the explicit direction of the html // element: -// https://dev.w3.org/html5/spec-preview/global-attributes.html#the-directionality -// NOTE: Value "auto" is not supported. +// https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-directionality enum Directionality { - kNoExplicitDirectionality, kLeftToRightDirectionality, kRightToLeftDirectionality, };
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc index f14bfa4..ab3e410 100644 --- a/src/cobalt/dom/document.cc +++ b/src/cobalt/dom/document.cc
@@ -72,7 +72,7 @@ Document::Document(HTMLElementContext* html_element_context, const Options& options) - : ALLOW_THIS_IN_INITIALIZER_LIST(Node(this)), + : ALLOW_THIS_IN_INITIALIZER_LIST(Node(html_element_context, this)), html_element_context_(html_element_context), page_visibility_state_(html_element_context_->page_visibility_state()), window_(options.window), @@ -286,6 +286,33 @@ const scoped_refptr<Location>& Document::location() const { return location_; } +// Algorithm for dir: +// https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#dom-dir +std::string Document::dir() const { + // The dir IDL attribute on Document objects must reflect the dir content + // attribute of the html element, if any, limited to only known values. If + // there is no such element, then the attribute must return the empty string + // and do nothing on setting. + HTMLHtmlElement* html_element = html(); + if (!html_element) { + return ""; + } + return html_element->dir(); +} + +// Algorithm for dir: +// https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#dom-dir +void Document::set_dir(const std::string& value) { + // The dir IDL attribute on Document objects must reflect the dir content + // attribute of the html element, if any, limited to only known values. If + // there is no such element, then the attribute must return the empty string + // and do nothing on setting. + HTMLHtmlElement* html_element = html(); + if (html_element) { + html_element->set_dir(value); + } +} + // Algorithm for body: // https://www.w3.org/TR/html5/dom.html#dom-document-body scoped_refptr<HTMLBodyElement> Document::body() const {
diff --git a/src/cobalt/dom/document.h b/src/cobalt/dom/document.h index 2cc9f32..19eb1d3 100644 --- a/src/cobalt/dom/document.h +++ b/src/cobalt/dom/document.h
@@ -194,6 +194,9 @@ // const scoped_refptr<Location>& location() const; + std::string dir() const; + void set_dir(const std::string& value); + scoped_refptr<HTMLBodyElement> body() const; void set_body(const scoped_refptr<HTMLBodyElement>& body);
diff --git a/src/cobalt/dom/document_html5.idl b/src/cobalt/dom/document_html5.idl index 9cee3f0..cd0b0fd 100644 --- a/src/cobalt/dom/document_html5.idl +++ b/src/cobalt/dom/document_html5.idl
@@ -17,6 +17,7 @@ [OverrideBuiltins] partial /*sealed*/ interface Document { [PutForwards=href, Unforgeable] readonly attribute Location? location; + attribute DOMString dir; // body attribute is changed, from the spec's: // attribute HTMLElement? body; // This is because we don't support frameset element, body has to be an
diff --git a/src/cobalt/dom/document_test.cc b/src/cobalt/dom/document_test.cc index 3a7c4f9..e2cd356 100644 --- a/src/cobalt/dom/document_test.cc +++ b/src/cobalt/dom/document_test.cc
@@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/document.h" +#include <memory> + #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/css_parser/parser.h" #include "cobalt/cssom/css_style_sheet.h" @@ -39,6 +39,7 @@ #include "cobalt/dom/node_list.h" #include "cobalt/dom/testing/gtest_workarounds.h" #include "cobalt/dom/testing/html_collection_testing.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/text.h" #include "cobalt/dom/ui_event.h" #include "cobalt/script/testing/mock_exception_state.h" @@ -48,10 +49,10 @@ namespace dom { namespace { +using script::testing::MockExceptionState; +using ::testing::_; using ::testing::SaveArg; using ::testing::StrictMock; -using ::testing::_; -using script::testing::MockExceptionState; ////////////////////////////////////////////////////////////////////////// // DocumentTest @@ -63,6 +64,7 @@ ~DocumentTest() override; base::MessageLoop message_loop_; + testing::StubEnvironmentSettings environment_settings_; std::unique_ptr<css_parser::Parser> css_parser_; std::unique_ptr<DomStatTracker> dom_stat_tracker_; HTMLElementContext html_element_context_; @@ -71,10 +73,10 @@ DocumentTest::DocumentTest() : css_parser_(css_parser::Parser::Create()), dom_stat_tracker_(new DomStatTracker("DocumentTest")), - html_element_context_(NULL, NULL, css_parser_.get(), NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, dom_stat_tracker_.get(), "", - base::kApplicationStateStarted, NULL) { + html_element_context_( + &environment_settings_, NULL, NULL, css_parser_.get(), NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + dom_stat_tracker_.get(), "", base::kApplicationStateStarted, NULL) { EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks()); }
diff --git a/src/cobalt/dom/dom.gyp b/src/cobalt/dom/dom.gyp index e4a81eb..0eceae5 100644 --- a/src/cobalt/dom/dom.gyp +++ b/src/cobalt/dom/dom.gyp
@@ -124,6 +124,8 @@ 'event_queue.h', 'event_target.cc', 'event_target.h', + 'event_target_listener_info.cc', + 'event_target_listener_info.h', 'focus_event.cc', 'focus_event.h', 'focus_event_init.h', @@ -135,8 +137,6 @@ 'font_face_updater.h', 'font_list.cc', 'font_list.h', - 'generic_event_handler_reference.cc', - 'generic_event_handler_reference.h', 'global_stats.cc', 'global_stats.h', 'history.cc',
diff --git a/src/cobalt/dom/dom_parser_test.cc b/src/cobalt/dom/dom_parser_test.cc index 5f0bf77..4d159e3 100644 --- a/src/cobalt/dom/dom_parser_test.cc +++ b/src/cobalt/dom/dom_parser_test.cc
@@ -12,14 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "cobalt/dom/dom_parser.h" + #include <memory> #include <string> #include "base/threading/platform_thread.h" #include "cobalt/dom/document.h" -#include "cobalt/dom/dom_parser.h" #include "cobalt/dom/html_element_context.h" #include "cobalt/dom/testing/stub_css_parser.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/testing/stub_script_runner.h" #include "cobalt/dom_parser/parser.h" #include "cobalt/loader/fetcher_factory.h" @@ -34,6 +36,7 @@ DOMParserTest(); ~DOMParserTest() override {} + testing::StubEnvironmentSettings environment_settings_; loader::FetcherFactory fetcher_factory_; loader::LoaderFactory loader_factory_; testing::StubCSSParser stub_css_parser_; @@ -50,12 +53,12 @@ 0 /* encoded_image_cache_capacity */, base::ThreadPriority::DEFAULT), dom_parser_parser_(new dom_parser::Parser()), html_element_context_( - &fetcher_factory_, &loader_factory_, &stub_css_parser_, - dom_parser_parser_.get(), NULL /* can_play_type_handler */, - NULL /* web_media_player_factory */, &stub_script_runner_, - NULL /* script_value_factory */, NULL /* media_source_registry */, - NULL /* resource_provider */, NULL /* animated_image_tracker */, - NULL /* image_cache */, + &environment_settings_, &fetcher_factory_, &loader_factory_, + &stub_css_parser_, dom_parser_parser_.get(), + NULL /* can_play_type_handler */, NULL /* web_media_player_factory */, + &stub_script_runner_, NULL /* script_value_factory */, + NULL /* media_source_registry */, NULL /* resource_provider */, + NULL /* animated_image_tracker */, NULL /* image_cache */, NULL /* reduced_image_cache_capacity_manager */, NULL /* remote_typeface_cache */, NULL /* mesh_cache */, NULL /* dom_stat_tracker */, "" /* language */,
diff --git a/src/cobalt/dom/dom_settings.cc b/src/cobalt/dom/dom_settings.cc index 66ef360..9490e3b 100644 --- a/src/cobalt/dom/dom_settings.cc +++ b/src/cobalt/dom/dom_settings.cc
@@ -23,23 +23,24 @@ DOMSettings::DOMSettings( const int max_dom_element_depth, loader::FetcherFactory* fetcher_factory, - network::NetworkModule* network_module, const scoped_refptr<Window>& window, + network::NetworkModule* network_module, MediaSourceRegistry* media_source_registry, Blob::Registry* blob_registry, media::CanPlayTypeHandler* can_play_type_handler, script::JavaScriptEngine* engine, script::GlobalEnvironment* global_environment, + base::DebuggerHooks* debugger_hooks, MutationObserverTaskManager* mutation_observer_task_manager, const Options& options) : max_dom_element_depth_(max_dom_element_depth), microphone_options_(options.microphone_options), fetcher_factory_(fetcher_factory), network_module_(network_module), - window_(window), media_source_registry_(media_source_registry), blob_registry_(blob_registry), can_play_type_handler_(can_play_type_handler), javascript_engine_(engine), global_environment_(global_environment), + debugger_hooks_(debugger_hooks), mutation_observer_task_manager_(mutation_observer_task_manager) {} DOMSettings::~DOMSettings() {}
diff --git a/src/cobalt/dom/dom_settings.h b/src/cobalt/dom/dom_settings.h index b83a49b..804b02a 100644 --- a/src/cobalt/dom/dom_settings.h +++ b/src/cobalt/dom/dom_settings.h
@@ -16,6 +16,7 @@ #define COBALT_DOM_DOM_SETTINGS_H_ #include "base/memory/ref_counted.h" +#include "cobalt/base/debugger_hooks.h" #include "cobalt/dom/blob.h" #include "cobalt/dom/mutation_observer_task_manager.h" #include "cobalt/dom/url_registry.h" @@ -35,7 +36,7 @@ namespace script { class GlobalEnvironment; class JavaScriptEngine; -} +} // namespace script namespace dom { class MediaSource; class Window; @@ -54,12 +55,12 @@ DOMSettings(const int max_dom_element_depth, loader::FetcherFactory* fetcher_factory, network::NetworkModule* network_module, - const scoped_refptr<Window>& window, MediaSourceRegistry* media_source_registry, Blob::Registry* blob_registry, media::CanPlayTypeHandler* can_play_type_handler, script::JavaScriptEngine* engine, script::GlobalEnvironment* global_environment_proxy, + base::DebuggerHooks* debugger_hooks, MutationObserverTaskManager* mutation_observer_task_manager, const Options& options = Options()); ~DOMSettings() override; @@ -92,6 +93,7 @@ media::CanPlayTypeHandler* can_play_type_handler() const { return can_play_type_handler_; } + base::DebuggerHooks* debugger_hooks() const { return debugger_hooks_; } MutationObserverTaskManager* mutation_observer_task_manager() const { return mutation_observer_task_manager_; } @@ -114,6 +116,7 @@ media::CanPlayTypeHandler* can_play_type_handler_; script::JavaScriptEngine* javascript_engine_; script::GlobalEnvironment* global_environment_; + base::DebuggerHooks* debugger_hooks_; MutationObserverTaskManager* mutation_observer_task_manager_; DISALLOW_COPY_AND_ASSIGN(DOMSettings);
diff --git a/src/cobalt/dom/element_test.cc b/src/cobalt/dom/element_test.cc index ab4ec8f..f30ffa3 100644 --- a/src/cobalt/dom/element_test.cc +++ b/src/cobalt/dom/element_test.cc
@@ -33,6 +33,7 @@ #include "cobalt/dom/node_list.h" #include "cobalt/dom/testing/gtest_workarounds.h" #include "cobalt/dom/testing/html_collection_testing.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/text.h" #include "cobalt/dom/xml_document.h" #include "cobalt/dom_parser/parser.h" @@ -50,6 +51,7 @@ ElementTest(); ~ElementTest() override; + testing::StubEnvironmentSettings environment_settings_; std::unique_ptr<css_parser::Parser> css_parser_; std::unique_ptr<dom_parser::Parser> dom_parser_; std::unique_ptr<DomStatTracker> dom_stat_tracker_; @@ -62,9 +64,10 @@ : css_parser_(css_parser::Parser::Create()), dom_parser_(new dom_parser::Parser()), dom_stat_tracker_(new DomStatTracker("ElementTest")), - html_element_context_(NULL, NULL, css_parser_.get(), dom_parser_.get(), + html_element_context_(&environment_settings_, NULL, NULL, + css_parser_.get(), dom_parser_.get(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, dom_stat_tracker_.get(), "", + NULL, dom_stat_tracker_.get(), "", base::kApplicationStateStarted, NULL) { EXPECT_TRUE(GlobalStats::GetInstance()->CheckNoLeaks()); document_ = new Document(&html_element_context_);
diff --git a/src/cobalt/dom/eme/media_key_session.cc b/src/cobalt/dom/eme/media_key_session.cc index 8cf2253..3570c14 100644 --- a/src/cobalt/dom/eme/media_key_session.cc +++ b/src/cobalt/dom/eme/media_key_session.cc
@@ -35,10 +35,12 @@ // See step 3.1 of // https://www.w3.org/TR/encrypted-media/#dom-mediakeys-createsession. MediaKeySession::MediaKeySession( + script::EnvironmentSettings* settings, const scoped_refptr<media::DrmSystem>& drm_system, script::ScriptValueFactory* script_value_factory, const ClosedCallback& closed_callback) - : ALLOW_THIS_IN_INITIALIZER_LIST(event_queue_(this)), + : EventTarget(settings), + ALLOW_THIS_IN_INITIALIZER_LIST(event_queue_(this)), drm_system_(drm_system), drm_system_session_(drm_system->CreateSession( base::Bind(&MediaKeySession::OnSessionUpdateKeyStatuses,
diff --git a/src/cobalt/dom/eme/media_key_session.h b/src/cobalt/dom/eme/media_key_session.h index d8acc09..e95c7de 100644 --- a/src/cobalt/dom/eme/media_key_session.h +++ b/src/cobalt/dom/eme/media_key_session.h
@@ -47,7 +47,8 @@ typedef base::Callback<void(MediaKeySession* session)> ClosedCallback; // Custom, not in any spec. - MediaKeySession(const scoped_refptr<media::DrmSystem>& drm_system, + MediaKeySession(script::EnvironmentSettings* settings, + const scoped_refptr<media::DrmSystem>& drm_system, script::ScriptValueFactory* script_value_factory, const ClosedCallback& closed_callback);
diff --git a/src/cobalt/dom/eme/media_key_system_access.cc b/src/cobalt/dom/eme/media_key_system_access.cc index 602069c..988fe43 100644 --- a/src/cobalt/dom/eme/media_key_system_access.cc +++ b/src/cobalt/dom/eme/media_key_system_access.cc
@@ -36,7 +36,8 @@ // See // https://www.w3.org/TR/encrypted-media/#dom-mediakeysystemaccess-createmediakeys. script::Handle<MediaKeySystemAccess::InterfacePromise> -MediaKeySystemAccess::CreateMediaKeys() const { +MediaKeySystemAccess::CreateMediaKeys( + script::EnvironmentSettings* settings) const { // 1. Let promise be a new promise. script::Handle<MediaKeySystemAccess::InterfacePromise> promise = script_value_factory_->CreateInterfacePromise<scoped_refptr<MediaKeys>>(); @@ -59,7 +60,7 @@ // 2.10. Let media keys be a new MediaKeys object. // 2.10.5. Let the cdm instance value be instance. scoped_refptr<MediaKeys> media_keys( - new MediaKeys(drm_system, script_value_factory_)); + new MediaKeys(settings, drm_system, script_value_factory_)); // 2.11. Resolve promise with media keys. promise->Resolve(media_keys);
diff --git a/src/cobalt/dom/eme/media_key_system_access.h b/src/cobalt/dom/eme/media_key_system_access.h index 0f18419..5849374 100644 --- a/src/cobalt/dom/eme/media_key_system_access.h +++ b/src/cobalt/dom/eme/media_key_system_access.h
@@ -18,6 +18,7 @@ #include <string> #include "cobalt/dom/eme/media_key_system_configuration.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/promise.h" #include "cobalt/script/script_value_factory.h" #include "cobalt/script/wrappable.h" @@ -42,7 +43,8 @@ const MediaKeySystemConfiguration& GetConfiguration() const { return configuration_; } - script::Handle<InterfacePromise> CreateMediaKeys() const; + script::Handle<InterfacePromise> CreateMediaKeys( + script::EnvironmentSettings* settings) const; DEFINE_WRAPPABLE_TYPE(MediaKeySystemAccess);
diff --git a/src/cobalt/dom/eme/media_key_system_access.idl b/src/cobalt/dom/eme/media_key_system_access.idl index 3dae4e1..319ba16 100644 --- a/src/cobalt/dom/eme/media_key_system_access.idl +++ b/src/cobalt/dom/eme/media_key_system_access.idl
@@ -17,5 +17,5 @@ interface MediaKeySystemAccess { readonly attribute DOMString keySystem; MediaKeySystemConfiguration getConfiguration(); - Promise<MediaKeys> createMediaKeys(); + [CallWith=EnvironmentSettings] Promise<MediaKeys> createMediaKeys(); };
diff --git a/src/cobalt/dom/eme/media_keys.cc b/src/cobalt/dom/eme/media_keys.cc index b7c94d6..26376f8 100644 --- a/src/cobalt/dom/eme/media_keys.cc +++ b/src/cobalt/dom/eme/media_keys.cc
@@ -23,10 +23,14 @@ namespace dom { namespace eme { -MediaKeys::MediaKeys(const scoped_refptr<media::DrmSystem>& drm_system, +MediaKeys::MediaKeys(script::EnvironmentSettings* settings, + const scoped_refptr<media::DrmSystem>& drm_system, script::ScriptValueFactory* script_value_factory) - : script_value_factory_(script_value_factory), drm_system_(drm_system) { - SB_DCHECK(drm_system_->is_valid()) << "DrmSystem provided on initialization is invalid."; + : settings_(settings), + script_value_factory_(script_value_factory), + drm_system_(drm_system) { + SB_DCHECK(drm_system_->is_valid()) + << "DrmSystem provided on initialization is invalid."; } // See https://www.w3.org/TR/encrypted-media/#dom-mediakeys-createsession. @@ -44,7 +48,7 @@ // |MediaKeys| are passed to |MediaKeySession| as weak pointer because the // order of destruction is not guaranteed due to JavaScript memory management. scoped_refptr<MediaKeySession> session(new MediaKeySession( - drm_system_, script_value_factory_, + settings_, drm_system_, script_value_factory_, base::Bind(&MediaKeys::OnSessionClosed, AsWeakPtr()))); open_sessions_.push_back(session); return session;
diff --git a/src/cobalt/dom/eme/media_keys.h b/src/cobalt/dom/eme/media_keys.h index d276af7..313f52f 100644 --- a/src/cobalt/dom/eme/media_keys.h +++ b/src/cobalt/dom/eme/media_keys.h
@@ -24,6 +24,7 @@ #include "cobalt/dom/eme/media_key_session.h" #include "cobalt/dom/eme/media_key_session_type.h" #include "cobalt/media/base/drm_system.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/script_value_factory.h" #include "cobalt/script/wrappable.h" #include "starboard/drm.h" @@ -42,7 +43,8 @@ typedef script::Handle<script::Promise<bool>> BoolPromiseHandle; typedef script::ScriptValue<script::Promise<bool>> BoolPromiseValue; - MediaKeys(const scoped_refptr<media::DrmSystem>& drm_system, + MediaKeys(script::EnvironmentSettings* settings, + const scoped_refptr<media::DrmSystem>& drm_system, script::ScriptValueFactory* script_value_factory); scoped_refptr<media::DrmSystem> drm_system() const { return drm_system_; } @@ -66,6 +68,7 @@ BoolPromiseValue::Reference* promise_reference, SbDrmStatus status, const std::string& error_message); + script::EnvironmentSettings* settings_; script::ScriptValueFactory* script_value_factory_; scoped_refptr<media::DrmSystem> drm_system_;
diff --git a/src/cobalt/dom/error_event_test.cc b/src/cobalt/dom/error_event_test.cc index abf844b..05d7bce 100644 --- a/src/cobalt/dom/error_event_test.cc +++ b/src/cobalt/dom/error_event_test.cc
@@ -21,12 +21,12 @@ #include "base/callback.h" #include "base/optional.h" #include "base/threading/platform_thread.h" -#include "cobalt/base/debugger_hooks.h" #include "cobalt/css_parser/parser.h" #include "cobalt/cssom/viewport_size.h" #include "cobalt/dom/error_event_init.h" #include "cobalt/dom/local_storage_database.h" #include "cobalt/dom/testing/gtest_workarounds.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/window.h" #include "cobalt/dom_parser/parser.h" #include "cobalt/loader/fetcher_factory.h" @@ -60,7 +60,7 @@ public: ErrorEventTest() : message_loop_(base::MessageLoop::TYPE_DEFAULT), - environment_settings_(new script::EnvironmentSettings), + environment_settings_(new testing::StubEnvironmentSettings), css_parser_(css_parser::Parser::Create()), dom_parser_(new dom_parser::Parser(mock_load_complete_callback_)), fetcher_factory_(new loader::FetcherFactory(NULL)), @@ -74,11 +74,12 @@ ViewportSize view_size(1920, 1080); window_ = new Window( - view_size, 1.f, base::kApplicationStateStarted, css_parser_.get(), - dom_parser_.get(), fetcher_factory_.get(), loader_factory_.get(), NULL, - NULL, NULL, NULL, NULL, NULL, &local_storage_database_, NULL, NULL, - NULL, NULL, global_environment_->script_value_factory(), NULL, NULL, - url_, "", "en-US", "en", base::Callback<void(const GURL&)>(), + environment_settings_.get(), view_size, 1.f, + base::kApplicationStateStarted, css_parser_.get(), dom_parser_.get(), + fetcher_factory_.get(), loader_factory_.get(), NULL, NULL, NULL, NULL, + NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, + global_environment_->script_value_factory(), NULL, NULL, url_, "", + "en-US", "en", base::Callback<void(const GURL&)>(), base::Bind(&MockLoadCompleteCallback::Run, base::Unretained(&mock_load_complete_callback_)), NULL, network_bridge::PostSender(), csp::kCSPRequired, @@ -88,8 +89,7 @@ base::Closure() /* window_minimize */, NULL, NULL, NULL, dom::Window::OnStartDispatchEventCallback(), dom::Window::OnStopDispatchEventCallback(), - dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), NULL, - null_debugger_hooks_); + dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), NULL); global_environment_->CreateGlobalObject(window_, environment_settings_.get()); @@ -100,7 +100,7 @@ private: base::MessageLoop message_loop_; std::unique_ptr<script::JavaScriptEngine> engine_; - const std::unique_ptr<script::EnvironmentSettings> environment_settings_; + const std::unique_ptr<testing::StubEnvironmentSettings> environment_settings_; scoped_refptr<script::GlobalEnvironment> global_environment_; MockLoadCompleteCallback mock_load_complete_callback_; std::unique_ptr<css_parser::Parser> css_parser_; @@ -109,7 +109,6 @@ std::unique_ptr<loader::LoaderFactory> loader_factory_; dom::LocalStorageDatabase local_storage_database_; GURL url_; - base::NullDebuggerHooks null_debugger_hooks_; scoped_refptr<Window> window_; };
diff --git a/src/cobalt/dom/event_queue_test.cc b/src/cobalt/dom/event_queue_test.cc index a76a29d..625cafb 100644 --- a/src/cobalt/dom/event_queue_test.cc +++ b/src/cobalt/dom/event_queue_test.cc
@@ -12,21 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/event_queue.h" +#include <memory> + #include "base/message_loop/message_loop.h" #include "cobalt/dom/event.h" #include "cobalt/dom/event_target.h" #include "cobalt/dom/testing/mock_event_listener.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/script/testing/fake_script_value.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::_; using ::testing::AllOf; using ::testing::Eq; using ::testing::Property; -using ::testing::_; namespace cobalt { namespace dom { @@ -48,11 +49,13 @@ _)) .RetiresOnSaturation(); } + testing::StubEnvironmentSettings environment_settings_; base::MessageLoop message_loop_; }; TEST_F(EventQueueTest, EventWithoutTargetTest) { - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("event")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); @@ -68,7 +71,8 @@ } TEST_F(EventQueueTest, EventWithTargetTest) { - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("event")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); @@ -85,7 +89,8 @@ } TEST_F(EventQueueTest, CancelAllEventsTest) { - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("event")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); @@ -105,8 +110,10 @@ // correctness of event propagation like capturing or bubbling are tested in // the unit tests of EventTarget. TEST_F(EventQueueTest, EventWithDifferentTargetTest) { - scoped_refptr<EventTarget> event_target_1 = new EventTarget; - scoped_refptr<EventTarget> event_target_2 = new EventTarget; + scoped_refptr<EventTarget> event_target_1 = + new EventTarget(&environment_settings_); + scoped_refptr<EventTarget> event_target_2 = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("event")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create();
diff --git a/src/cobalt/dom/event_target.cc b/src/cobalt/dom/event_target.cc index f256173..367d872 100644 --- a/src/cobalt/dom/event_target.cc +++ b/src/cobalt/dom/event_target.cc
@@ -12,16 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/event_target.h" +#include <memory> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/trace_event/trace_event.h" +#include "cobalt/base/polymorphic_downcast.h" #include "cobalt/dom/dom_exception.h" +#include "cobalt/dom/dom_settings.h" #include "cobalt/dom/global_stats.h" #include "cobalt/xhr/xml_http_request_event_target.h" #include "nb/memory_scope.h" @@ -29,6 +31,16 @@ namespace cobalt { namespace dom { +EventTarget::EventTarget( + script::EnvironmentSettings* settings, + UnpackOnErrorEventsBool onerror_event_parameter_handling) + : debugger_hooks_( + base::polymorphic_downcast<DOMSettings*>(settings)->debugger_hooks()), + unpack_onerror_events_(onerror_event_parameter_handling == + kUnpackOnErrorEvents) { + DCHECK(debugger_hooks_); +} + void EventTarget::AddEventListener(const std::string& type, const EventListenerScriptValue& listener, bool use_capture) { @@ -37,11 +49,9 @@ return; } - std::unique_ptr<GenericEventHandlerReference> listener_reference( - new GenericEventHandlerReference(this, listener)); - - AddEventListenerInternal(base::Token(type), std::move(listener_reference), - use_capture, kNotAttribute); + AddEventListenerInternal(base::WrapUnique(new EventTargetListenerInfo( + this, base::Token(type), EventTargetListenerInfo::kAddEventListener, + use_capture, listener))); } void EventTarget::RemoveEventListener(const std::string& type, @@ -52,11 +62,13 @@ return; } + EventTargetListenerInfo listener_info( + this, base::Token(type), EventTargetListenerInfo::kAddEventListener, + use_capture, listener); for (EventListenerInfos::iterator iter = event_listener_infos_.begin(); iter != event_listener_infos_.end(); ++iter) { - if ((*iter)->listener_type == kNotAttribute && - (*iter)->type == type.c_str() && (*iter)->listener->EqualTo(listener) && - (*iter)->use_capture == use_capture) { + if ((*iter)->EqualTo(listener_info)) { + debugger_hooks_->AsyncTaskCanceled((*iter)->task()); event_listener_infos_.erase(iter); return; } @@ -157,69 +169,54 @@ base::Token type, const EventListenerScriptValue& listener) { DCHECK(!unpack_onerror_events_ || type != base::Tokens::error()); - std::unique_ptr<GenericEventHandlerReference> listener_reference( - new GenericEventHandlerReference(this, listener)); - SetAttributeEventListenerInternal(type, std::move(listener_reference)); + AddEventListenerInternal(base::WrapUnique(new EventTargetListenerInfo( + this, type, EventTargetListenerInfo::kSetAttribute, + false /* use_capture */, listener))); } const EventTarget::EventListenerScriptValue* EventTarget::GetAttributeEventListener(base::Token type) const { DCHECK(!unpack_onerror_events_ || type != base::Tokens::error()); - GenericEventHandlerReference* handler = + EventTargetListenerInfo* listener_info = GetAttributeEventListenerInternal(type); - return handler ? handler->event_listener_value() : NULL; + return listener_info ? listener_info->event_listener_value() : NULL; } void EventTarget::SetAttributeOnErrorEventListener( base::Token type, const OnErrorEventListenerScriptValue& listener) { DCHECK_EQ(base::Tokens::error(), type); - std::unique_ptr<GenericEventHandlerReference> listener_reference( - new GenericEventHandlerReference(this, listener)); - SetAttributeEventListenerInternal(type, std::move(listener_reference)); + AddEventListenerInternal(base::WrapUnique(new EventTargetListenerInfo( + this, type, EventTargetListenerInfo::kSetAttribute, + false /* use_capture */, unpack_onerror_events_, listener))); } const EventTarget::OnErrorEventListenerScriptValue* EventTarget::GetAttributeOnErrorEventListener(base::Token type) const { DCHECK_EQ(base::Tokens::error(), type); - GenericEventHandlerReference* handler = + EventTargetListenerInfo* listener_info = GetAttributeEventListenerInternal(type); - return handler ? handler->on_error_event_listener_value() : NULL; + return listener_info ? listener_info->on_error_event_listener_value() : NULL; } bool EventTarget::HasOneOrMoreAttributeEventListener() const { for (EventListenerInfos::const_iterator iter = event_listener_infos_.begin(); iter != event_listener_infos_.end(); ++iter) { - if ((*iter)->listener_type == kAttribute) { + if ((*iter)->is_attribute()) { return true; } } return false; } -void EventTarget::SetAttributeEventListenerInternal( - base::Token type, - std::unique_ptr<GenericEventHandlerReference> event_handler) { - // Remove existing attribute listener of the same type. - for (EventListenerInfos::iterator iter = event_listener_infos_.begin(); - iter != event_listener_infos_.end(); ++iter) { - if ((*iter)->listener_type == kAttribute && (*iter)->type == type) { - event_listener_infos_.erase(iter); - break; - } - } - - AddEventListenerInternal(type, std::move(event_handler), false, kAttribute); -} - -GenericEventHandlerReference* EventTarget::GetAttributeEventListenerInternal( +EventTargetListenerInfo* EventTarget::GetAttributeEventListenerInternal( base::Token type) const { for (EventListenerInfos::const_iterator iter = event_listener_infos_.begin(); iter != event_listener_infos_.end(); ++iter) { - if ((*iter)->listener_type == kAttribute && (*iter)->type == type) { - return (*iter)->listener.get(); + if ((*iter)->is_attribute() && (*iter)->type() == type) { + return iter->get(); } } return NULL; @@ -235,12 +232,9 @@ EventListenerInfos event_listener_infos; for (EventListenerInfos::iterator iter = event_listener_infos_.begin(); iter != event_listener_infos_.end(); ++iter) { - if ((*iter)->type == event->type()) { - event_listener_infos.emplace_back(new EventListenerInfo( - (*iter)->type, - base::WrapUnique( - new GenericEventHandlerReference(this, *(*iter)->listener)), - (*iter)->use_capture, (*iter)->listener_type)); + if ((*iter)->type() == event->type()) { + event_listener_infos.emplace_back( + base::WrapUnique(new EventTargetListenerInfo(this, **iter))); } } @@ -251,16 +245,17 @@ } // Only call listeners marked as capture during capturing phase. if (event->event_phase() == Event::kCapturingPhase && - !(*iter)->use_capture) { + !(*iter)->use_capture()) { continue; } // Don't call any listeners marked as capture during bubbling phase. - if (event->event_phase() == Event::kBubblingPhase && (*iter)->use_capture) { + if (event->event_phase() == Event::kBubblingPhase && + (*iter)->use_capture()) { continue; } - (*iter)->listener->HandleEvent(event, (*iter)->listener_type == kAttribute, - unpack_onerror_events_); + base::ScopedAsyncTask async_task(debugger_hooks_, (*iter)->task()); + (*iter)->HandleEvent(event); } event->set_current_target(NULL); @@ -273,27 +268,38 @@ } void EventTarget::AddEventListenerInternal( - base::Token type, std::unique_ptr<GenericEventHandlerReference> listener, - bool use_capture, Type listener_type) { + std::unique_ptr<EventTargetListenerInfo> listener_info) { TRACK_MEMORY_SCOPE("DOM"); - if (listener->IsNull()) { + // Remove existing attribute listener of the same type. + if (listener_info->is_attribute()) { + for (EventListenerInfos::iterator iter = event_listener_infos_.begin(); + iter != event_listener_infos_.end(); ++iter) { + if ((*iter)->is_attribute() && (*iter)->type() == listener_info->type()) { + debugger_hooks_->AsyncTaskCanceled((*iter)->task()); + event_listener_infos_.erase(iter); + break; + } + } + } + + if (listener_info->IsNull()) { return; } for (EventListenerInfos::iterator iter = event_listener_infos_.begin(); iter != event_listener_infos_.end(); ++iter) { - if ((*iter)->type == type && (*iter)->listener->EqualTo(*listener) && - (*iter)->use_capture == use_capture && - (*iter)->listener_type == listener_type) { + if ((*iter)->EqualTo(*listener_info)) { // Attribute listeners should have already been removed. - DCHECK_EQ(listener_type, kNotAttribute); + DCHECK(!listener_info->is_attribute()); return; } } - event_listener_infos_.emplace_back(new EventListenerInfo( - type, std::move(listener), use_capture, listener_type)); + debugger_hooks_->AsyncTaskScheduled( + listener_info->task(), listener_info->type().c_str(), + base::DebuggerHooks::AsyncTaskFrequency::kRecurring); + event_listener_infos_.push_back(std::move(listener_info)); } bool EventTarget::HasEventListener(base::Token type) { @@ -301,26 +307,12 @@ for (EventListenerInfos::iterator iter = event_listener_infos_.begin(); iter != event_listener_infos_.end(); ++iter) { - if ((*iter)->type == type) { + if ((*iter)->type() == type) { return true; } } return false; } -EventTarget::EventListenerInfo::EventListenerInfo( - base::Token type, std::unique_ptr<GenericEventHandlerReference> listener, - bool use_capture, Type listener_type) - : type(type), - listener(std::move(listener)), - use_capture(use_capture), - listener_type(listener_type) { - GlobalStats::GetInstance()->AddEventListener(); -} - -EventTarget::EventListenerInfo::~EventListenerInfo() { - GlobalStats::GetInstance()->RemoveEventListener(); -} - } // namespace dom } // namespace cobalt
diff --git a/src/cobalt/dom/event_target.h b/src/cobalt/dom/event_target.h index b4e9bd9..82715ce 100644 --- a/src/cobalt/dom/event_target.h +++ b/src/cobalt/dom/event_target.h
@@ -23,13 +23,15 @@ #include "base/location.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "cobalt/base/debugger_hooks.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/base/token.h" #include "cobalt/base/tokens.h" #include "cobalt/dom/event.h" #include "cobalt/dom/event_listener.h" -#include "cobalt/dom/generic_event_handler_reference.h" +#include "cobalt/dom/event_target_listener_info.h" #include "cobalt/dom/on_error_event_listener.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/exception_state.h" #include "cobalt/script/script_value.h" #include "cobalt/script/wrappable.h" @@ -45,13 +47,6 @@ class EventTarget : public script::Wrappable, public base::SupportsWeakPtr<EventTarget> { public: - // EventHandlers are implemented as EventListener?, so use this to - // differentiate between the two. - enum Type { - kAttribute, - kNotAttribute, - }; - // Helper enum to decide whether or not onerror event parameters should be // unpacked or not (e.g. in the special case of the |window| object). // This special handling is described in: @@ -65,13 +60,11 @@ // The parameter |unpack_onerror_events| can be set to true (e.g. for the // |window| object) in order to indicate that the ErrorEvent should have // its members unpacked before calling its event handler. This is to - // accommodate for a special case in the window.onerror handling. This - // special handling + // accommodate for a special case in the window.onerror handling. explicit EventTarget( + script::EnvironmentSettings* settings, UnpackOnErrorEventsBool onerror_event_parameter_handling = - kDoNotUnpackOnErrorEvents) - : unpack_onerror_events_(onerror_event_parameter_handling == - kUnpackOnErrorEvents) {} + kDoNotUnpackOnErrorEvents); typedef script::ScriptValue<EventListener> EventListenerScriptValue; typedef script::ScriptValue<OnErrorEventListener> @@ -476,32 +469,24 @@ DEFINE_WRAPPABLE_TYPE(EventTarget); void TraceMembers(script::Tracer* tracer) override; - private: - struct EventListenerInfo { - EventListenerInfo(base::Token type, - std::unique_ptr<GenericEventHandlerReference> listener, - bool use_capture, Type listener_type); - ~EventListenerInfo(); + base::DebuggerHooks* debugger_hooks() { return debugger_hooks_; } - base::Token type; - std::unique_ptr<GenericEventHandlerReference> listener; - bool use_capture; - Type listener_type; - }; - typedef std::vector<std::unique_ptr<EventListenerInfo>> EventListenerInfos; + private: + typedef std::vector<std::unique_ptr<EventTargetListenerInfo>> + EventListenerInfos; void SetAttributeEventListenerInternal( - base::Token type, - std::unique_ptr<GenericEventHandlerReference> event_handler); - GenericEventHandlerReference* GetAttributeEventListenerInternal( + std::unique_ptr<EventTargetListenerInfo> event_handler); + EventTargetListenerInfo* GetAttributeEventListenerInternal( base::Token type) const; void AddEventListenerInternal( - base::Token type, std::unique_ptr<GenericEventHandlerReference> listener, - bool use_capture, Type listener_type); + std::unique_ptr<EventTargetListenerInfo> listener); EventListenerInfos event_listener_infos_; + base::DebuggerHooks* debugger_hooks_; + // Tracks whether this current event listener should unpack the onerror // event object when calling its callback. This is needed to implement // the special case of window.onerror handling.
diff --git a/src/cobalt/dom/event_target_listener_info.cc b/src/cobalt/dom/event_target_listener_info.cc new file mode 100644 index 0000000..7309029 --- /dev/null +++ b/src/cobalt/dom/event_target_listener_info.cc
@@ -0,0 +1,143 @@ +// Copyright 2018 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cobalt/dom/event_target_listener_info.h" + +#include "base/trace_event/trace_event.h" +#include "cobalt/dom/event.h" +#include "cobalt/dom/event_target.h" +#include "cobalt/dom/global_stats.h" + +namespace cobalt { +namespace dom { + +EventTargetListenerInfo::EventTargetListenerInfo( + script::Wrappable* wrappable, base::Token type, AttachMethod attach, + bool use_capture, const EventListenerScriptValue& script_value) + : ALLOW_THIS_IN_INITIALIZER_LIST(task_(this)), + type_(type), + is_attribute_(attach == kSetAttribute), + use_capture_(use_capture), + unpack_error_event_(false) { + if (!script_value.IsNull()) { + GlobalStats::GetInstance()->AddEventListener(); + event_listener_reference_.reset( + new EventListenerScriptValue::Reference(wrappable, script_value)); + } +} + +EventTargetListenerInfo::EventTargetListenerInfo( + script::Wrappable* wrappable, base::Token type, AttachMethod attach, + bool use_capture, bool unpack_error_event, + const OnErrorEventListenerScriptValue& script_value) + : ALLOW_THIS_IN_INITIALIZER_LIST(task_(this)), + type_(type), + is_attribute_(attach == kSetAttribute), + use_capture_(use_capture), + unpack_error_event_(unpack_error_event) { + if (!script_value.IsNull()) { + GlobalStats::GetInstance()->AddEventListener(); + on_error_event_listener_reference_.reset( + new OnErrorEventListenerScriptValue::Reference(wrappable, + script_value)); + } +} + +EventTargetListenerInfo::EventTargetListenerInfo( + script::Wrappable* wrappable, const EventTargetListenerInfo& other) + : task_(other.task_), + type_(other.type_), + is_attribute_(other.is_attribute_), + use_capture_(other.use_capture_), + unpack_error_event_(other.unpack_error_event_) { + if (other.event_listener_reference_) { + DCHECK(!other.event_listener_reference_->referenced_value().IsNull()); + GlobalStats::GetInstance()->AddEventListener(); + event_listener_reference_.reset(new EventListenerScriptValue::Reference( + wrappable, other.event_listener_reference_->referenced_value())); + } else if (other.on_error_event_listener_reference_) { + GlobalStats::GetInstance()->AddEventListener(); + on_error_event_listener_reference_.reset( + new OnErrorEventListenerScriptValue::Reference( + wrappable, + other.on_error_event_listener_reference_->referenced_value())); + } +} + +EventTargetListenerInfo::~EventTargetListenerInfo() { + if (!IsNull()) { + GlobalStats::GetInstance()->RemoveEventListener(); + } +} + +void EventTargetListenerInfo::HandleEvent(const scoped_refptr<Event>& event) { + TRACE_EVENT1("cobalt::dom", "EventTargetListenerInfo::HandleEvent", + "Event Name", TRACE_STR_COPY(event->type().c_str())); + bool had_exception; + base::Optional<bool> result; + + // Forward the HandleEvent() call to the appropriate internal object. + if (event_listener_reference_) { + // Non-onerror event handlers cannot have their parameters unpacked. + result = event_listener_reference_->value().HandleEvent( + event->current_target(), event, &had_exception); + } else if (on_error_event_listener_reference_) { + result = on_error_event_listener_reference_->value().HandleEvent( + event->current_target(), event, &had_exception, unpack_error_event_); + } else { + NOTREACHED(); + had_exception = true; + } + + if (had_exception) { + return; + } + // EventHandlers (EventListeners set as attributes) may return false rather + // than call event.preventDefault() in the handler function. + if (is_attribute() && result && !result.value()) { + event->PreventDefault(); + } +} + +bool EventTargetListenerInfo::EqualTo(const EventTargetListenerInfo& other) { + if (type() != other.type() || is_attribute() != other.is_attribute() || + use_capture() != other.use_capture()) { + return false; + } + + if (IsNull() && other.IsNull()) { + return true; + } + + if (event_listener_reference_ && other.event_listener_reference_) { + return event_listener_reference_->referenced_value().EqualTo( + other.event_listener_reference_->referenced_value()); + } + if (on_error_event_listener_reference_ && + other.on_error_event_listener_reference_) { + return on_error_event_listener_reference_->referenced_value().EqualTo( + other.on_error_event_listener_reference_->referenced_value()); + } + return false; +} + +bool EventTargetListenerInfo::IsNull() const { + return (!event_listener_reference_ || + event_listener_reference_->referenced_value().IsNull()) && + (!on_error_event_listener_reference_ || + on_error_event_listener_reference_->referenced_value().IsNull()); +} + +} // namespace dom +} // namespace cobalt
diff --git a/src/cobalt/dom/event_target_listener_info.h b/src/cobalt/dom/event_target_listener_info.h new file mode 100644 index 0000000..0323236 --- /dev/null +++ b/src/cobalt/dom/event_target_listener_info.h
@@ -0,0 +1,135 @@ +// Copyright 2018 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COBALT_DOM_EVENT_TARGET_LISTENER_INFO_H_ +#define COBALT_DOM_EVENT_TARGET_LISTENER_INFO_H_ + +#include <memory> + +#include "base/memory/ref_counted.h" +#include "cobalt/dom/event_listener.h" +#include "cobalt/dom/on_error_event_listener.h" +#include "cobalt/script/script_value.h" +#include "cobalt/script/wrappable.h" + +namespace cobalt { +namespace dom { + +// Holds the event listener for an EventTarget, along with metadata describing +// in what manner the listener was attached to the EventTarget. +// +// The listener itself is a script::ScriptValue<T> where T may be either of: +// [EventListener, OnErrorEventListener]. In particular it primarily +// allows code in event_target.cc to not need to concern itself with which +// exact EventListener script value type it is dealing with. The need for +// this abstraction arises from the fact that the |window.onerror| event +// handler requires special case handling: +// https://html.spec.whatwg.org/#onerroreventhandler +// +// NOTE that this is *not* an ideal solution to the problem of generalizing +// over multiple ScriptValue types. The problem is that the ScriptValue +// base class is both templated and abstract, making it difficult to cast its +// internal type to get a new ScriptValue. This problem could be solved by +// refactoring ScriptValue such that there is a non-templated abstract type +// (say, RawScriptValue) with a function like "void* GetValue()", but usually +// not referenced directly by client code. Instead there would be a separate +// templated concrete wrapper type (say, ScriptValue) that wraps RawScriptValue +// and manages the casting and type checking. This would allow us to convert +// between OnErrorEventListener and EventListener, if OnErrorEventListener was +// derived from EventListener. +class EventTargetListenerInfo { + public: + typedef script::ScriptValue<EventListener> EventListenerScriptValue; + typedef script::ScriptValue<OnErrorEventListener> + OnErrorEventListenerScriptValue; + + // Whether an event listener is attached as an attribute or with + // AddEventListener(). + enum AttachMethod { + kSetAttribute, + kAddEventListener, + }; + + EventTargetListenerInfo(script::Wrappable* wrappable, base::Token type, + AttachMethod attach, bool use_capture, + const EventListenerScriptValue& script_value); + EventTargetListenerInfo(script::Wrappable* wrappable, base::Token type, + AttachMethod attach, bool use_capture, + bool unpack_error_event, + const OnErrorEventListenerScriptValue& script_value); + EventTargetListenerInfo(script::Wrappable* wrappable, + const EventTargetListenerInfo& other); + + EventTargetListenerInfo(const EventTargetListenerInfo&) = delete; + EventTargetListenerInfo& operator=(const EventTargetListenerInfo&) = delete; + + ~EventTargetListenerInfo(); + + const void* task() const { return task_; } + base::Token type() const { return type_; } + bool is_attribute() const { return is_attribute_; } + bool use_capture() const { return use_capture_; } + + // Forwards on to the internal event listener's HandleEvent() call, passing + // in the value of |unpack_error_event| if the internal type is a + // OnErrorEventListenerScriptValue type. + void HandleEvent(const scoped_refptr<Event>& event); + + bool EqualTo(const EventTargetListenerInfo& other); + bool IsNull() const; + + // If the internal type is a EventListenerScriptValue, then its value will + // be returned, otherwise null is returned; + const EventListenerScriptValue* event_listener_value() { + return event_listener_reference_ + ? &event_listener_reference_->referenced_value() + : nullptr; + } + + // If the internal type is a OnErrorEventListenerScriptValue, then its value + // will be returned, otherwise null is returned; + const OnErrorEventListenerScriptValue* on_error_event_listener_value() { + return on_error_event_listener_reference_ + ? &on_error_event_listener_reference_->referenced_value() + : nullptr; + } + + private: + // A nonce to identify the "scheduled" asynchronous task that could call the + // listener when the event is fired. The constructors that create a new + // "attachment" of a listener initialize it to |this| as a unique nonce value. + // However, the copy(ish) constructor copies the task since the copy still + // represents the same attachment of the same listener. It is specifically NOT + // tied to the ScriptValue since the same JS listener may be attached multiple + // times to one or several |EventTarget|s, and each of those attachments is a + // unique task. + const void* const task_; + + base::Token const type_; + bool const is_attribute_; + bool const use_capture_; + bool const unpack_error_event_; + + // At most only one of the below two fields may be non-null... They are + // serving as a poor man's std::variant. + std::unique_ptr<EventListenerScriptValue::Reference> + event_listener_reference_; + std::unique_ptr<OnErrorEventListenerScriptValue::Reference> + on_error_event_listener_reference_; +}; + +} // namespace dom +} // namespace cobalt + +#endif // COBALT_DOM_EVENT_TARGET_LISTENER_INFO_H_
diff --git a/src/cobalt/dom/event_target_test.cc b/src/cobalt/dom/event_target_test.cc index 834ae3a..1e09756 100644 --- a/src/cobalt/dom/event_target_test.cc +++ b/src/cobalt/dom/event_target_test.cc
@@ -12,35 +12,50 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/event_target.h" +#include <memory> + #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/dom/dom_exception.h" +#include "cobalt/dom/dom_settings.h" #include "cobalt/dom/testing/mock_event_listener.h" #include "cobalt/script/testing/fake_script_value.h" #include "cobalt/script/testing/mock_exception_state.h" +#include "cobalt/test/mock_debugger_hooks.h" #include "testing/gtest/include/gtest/gtest.h" namespace cobalt { namespace dom { namespace { +using script::testing::FakeScriptValue; +using script::testing::MockExceptionState; +using ::testing::_; using ::testing::AllOf; using ::testing::DoAll; using ::testing::Eq; using ::testing::InSequence; using ::testing::Invoke; using ::testing::InvokeWithoutArgs; +using testing::MockEventListener; using ::testing::Pointee; using ::testing::Property; using ::testing::SaveArg; using ::testing::StrictMock; -using ::testing::_; -using script::testing::FakeScriptValue; -using script::testing::MockExceptionState; -using testing::MockEventListener; + +constexpr auto kRecurring = base::DebuggerHooks::AsyncTaskFrequency::kRecurring; + +class EventTargetTest : public ::testing::Test { + protected: + EventTargetTest() + : environment_settings_(0, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, &debugger_hooks_, nullptr, + DOMSettings::Options()) {} + + StrictMock<test::MockDebuggerHooks> debugger_hooks_; + DOMSettings environment_settings_; +}; base::Optional<bool> DispatchEventOnCurrentTarget( const scoped_refptr<script::Wrappable>, const scoped_refptr<Event>& event, @@ -63,37 +78,48 @@ return base::nullopt; } -TEST(EventTargetTest, SingleEventListenerFired) { +TEST_F(EventTargetTest, SingleEventListenerFired) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); - event_listener->ExpectHandleEventCall(event, event_target); + const void* async_task; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listener.get()), false); + + event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task)); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } -TEST(EventTargetTest, SingleEventListenerNotFired) { +TEST_F(EventTargetTest, SingleEventListenerNotFired) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); - event_listener->ExpectNoHandleEventCall(); + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "notfired", kRecurring)); event_target->AddEventListener( "notfired", FakeScriptValue<EventListener>(event_listener.get()), false); + + event_listener->ExpectNoHandleEventCall(); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } // Test if multiple event listeners of different event types can be added and // fired properly. -TEST(EventTargetTest, MultipleEventListeners) { +TEST_F(EventTargetTest, MultipleEventListeners) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listenerfired_1 = MockEventListener::Create(); @@ -103,9 +129,16 @@ MockEventListener::Create(); InSequence in_sequence; - event_listenerfired_1->ExpectHandleEventCall(event, event_target); - event_listenerfired_2->ExpectHandleEventCall(event, event_target); - event_listenernot_fired->ExpectNoHandleEventCall(); + + const void* async_task_1; + const void* async_task_2; + const void* async_task_not_fired; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_1)); + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "notfired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_not_fired)); + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_2)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listenerfired_1.get()), @@ -116,37 +149,61 @@ event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listenerfired_2.get()), true); + + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + event_listenerfired_1->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); + + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_2)); + event_listenerfired_2->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_2)); + + event_listenernot_fired->ExpectNoHandleEventCall(); + EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } // Test if event listener can be added and later removed. -TEST(EventTargetTest, AddRemoveEventListener) { +TEST_F(EventTargetTest, AddRemoveEventListener) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); - event_listener->ExpectHandleEventCall(event, event_target); + const void* async_task_1; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_1)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listener.get()), false); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); - event_listener->ExpectNoHandleEventCall(); + EXPECT_CALL(debugger_hooks_, AsyncTaskCanceled(async_task_1)); event_target->RemoveEventListener( "fired", FakeScriptValue<EventListener>(event_listener.get()), false); + event_listener->ExpectNoHandleEventCall(); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); - event_listener->ExpectHandleEventCall(event, event_target); + const void* async_task_2; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_2)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listener.get()), false); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_2)); + event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_2)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } // Test if attribute event listener works. -TEST(EventTargetTest, AttributeListener) { +TEST_F(EventTargetTest, AttributeListener) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> non_attribute_event_listener = MockEventListener::Create(); @@ -155,75 +212,113 @@ std::unique_ptr<MockEventListener> attribute_event_listener2 = MockEventListener::Create(); + const void* non_attribute_async_task; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&non_attribute_async_task)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(non_attribute_event_listener.get()), false); - - non_attribute_event_listener->ExpectHandleEventCall(event, event_target); - attribute_event_listener1->ExpectHandleEventCall(event, event_target); + const void* async_task_1; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_1)); event_target->SetAttributeEventListener( base::Token("fired"), FakeScriptValue<EventListener>(attribute_event_listener1.get())); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(non_attribute_async_task)); + non_attribute_event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(non_attribute_async_task)); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + attribute_event_listener1->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); - non_attribute_event_listener->ExpectHandleEventCall(event, event_target); - attribute_event_listener1->ExpectNoHandleEventCall(); - attribute_event_listener2->ExpectHandleEventCall(event, event_target); + const void* async_task_2; + EXPECT_CALL(debugger_hooks_, AsyncTaskCanceled(async_task_1)); + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_2)); event_target->SetAttributeEventListener( base::Token("fired"), FakeScriptValue<EventListener>(attribute_event_listener2.get())); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(non_attribute_async_task)); + non_attribute_event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(non_attribute_async_task)); + attribute_event_listener1->ExpectNoHandleEventCall(); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_2)); + attribute_event_listener2->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_2)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); - non_attribute_event_listener->ExpectHandleEventCall(event, event_target); - attribute_event_listener1->ExpectNoHandleEventCall(); - attribute_event_listener2->ExpectNoHandleEventCall(); + EXPECT_CALL(debugger_hooks_, AsyncTaskCanceled(async_task_2)); event_target->SetAttributeEventListener(base::Token("fired"), FakeScriptValue<EventListener>(NULL)); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(non_attribute_async_task)); + non_attribute_event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(non_attribute_async_task)); + attribute_event_listener1->ExpectNoHandleEventCall(); + attribute_event_listener2->ExpectNoHandleEventCall(); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } // Test if one event listener can be used by multiple events. -TEST(EventTargetTest, EventListenerReuse) { +TEST_F(EventTargetTest, EventListenerReuse) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event_1 = new Event(base::Token("fired_1")); scoped_refptr<Event> event_2 = new Event(base::Token("fired_2")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); - event_listener->ExpectHandleEventCall(event_1, event_target); - event_listener->ExpectHandleEventCall(event_2, event_target); + const void* async_task_1; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired_1", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_1)); event_target->AddEventListener( "fired_1", FakeScriptValue<EventListener>(event_listener.get()), false); + const void* async_task_2; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired_2", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_2)); event_target->AddEventListener( "fired_2", FakeScriptValue<EventListener>(event_listener.get()), false); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + event_listener->ExpectHandleEventCall(event_1, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); EXPECT_TRUE(event_target->DispatchEvent(event_1, &exception_state)); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_2)); + event_listener->ExpectHandleEventCall(event_2, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_2)); EXPECT_TRUE(event_target->DispatchEvent(event_2, &exception_state)); - event_listener->ExpectHandleEventCall(event_1, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskCanceled(async_task_2)); event_target->RemoveEventListener( "fired_2", FakeScriptValue<EventListener>(event_listener.get()), false); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + event_listener->ExpectHandleEventCall(event_1, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); EXPECT_TRUE(event_target->DispatchEvent(event_1, &exception_state)); EXPECT_TRUE(event_target->DispatchEvent(event_2, &exception_state)); - event_listener->ExpectHandleEventCall(event_1, event_target); // The capture flag is not the same so the event will not be removed. event_target->RemoveEventListener( "fired_1", FakeScriptValue<EventListener>(event_listener.get()), true); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + event_listener->ExpectHandleEventCall(event_1, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); EXPECT_TRUE(event_target->DispatchEvent(event_1, &exception_state)); EXPECT_TRUE(event_target->DispatchEvent(event_2, &exception_state)); - event_listener->ExpectNoHandleEventCall(); + EXPECT_CALL(debugger_hooks_, AsyncTaskCanceled(async_task_1)); event_target->RemoveEventListener( "fired_1", FakeScriptValue<EventListener>(event_listener.get()), false); + event_listener->ExpectNoHandleEventCall(); EXPECT_TRUE(event_target->DispatchEvent(event_1, &exception_state)); EXPECT_TRUE(event_target->DispatchEvent(event_2, &exception_state)); } -TEST(EventTargetTest, StopPropagation) { +TEST_F(EventTargetTest, StopPropagation) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listenerfired_1 = MockEventListener::Create(); @@ -231,68 +326,97 @@ MockEventListener::Create(); InSequence in_sequence; - event_listenerfired_1->ExpectHandleEventCall( - event, event_target, &MockEventListener::StopPropagation); - event_listenerfired_2->ExpectHandleEventCall(event, event_target); + const void* async_task_1; + const void* async_task_2; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_1)); + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_2)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listenerfired_1.get()), false); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listenerfired_2.get()), true); + + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + event_listenerfired_1->ExpectHandleEventCall( + event, event_target, &MockEventListener::StopPropagation); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_2)); + event_listenerfired_2->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_2)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } -TEST(EventTargetTest, StopImmediatePropagation) { +TEST_F(EventTargetTest, StopImmediatePropagation) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listenerfired_1 = MockEventListener::Create(); std::unique_ptr<MockEventListener> event_listenerfired_2 = MockEventListener::Create(); - event_listenerfired_1->ExpectHandleEventCall( - event, event_target, &MockEventListener::StopImmediatePropagation); - event_listenerfired_2->ExpectNoHandleEventCall(); - + const void* async_task_1; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_1)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listenerfired_1.get()), false); + const void* async_task_2; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_2)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listenerfired_2.get()), true); + + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + event_listenerfired_1->ExpectHandleEventCall( + event, event_target, &MockEventListener::StopImmediatePropagation); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); + event_listenerfired_2->ExpectNoHandleEventCall(); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } -TEST(EventTargetTest, PreventDefault) { +TEST_F(EventTargetTest, PreventDefault) { StrictMock<MockExceptionState> exception_state; scoped_refptr<Event> event; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); std::unique_ptr<MockEventListener> event_listenerfired = MockEventListener::Create(); + const void* async_task; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listenerfired.get()), false); event = new Event(base::Token("fired"), Event::kNotBubbles, Event::kNotCancelable); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task)); event_listenerfired->ExpectHandleEventCall( event, event_target, &MockEventListener::PreventDefault); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); event = new Event(base::Token("fired"), Event::kNotBubbles, Event::kCancelable); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task)); event_listenerfired->ExpectHandleEventCall( event, event_target, &MockEventListener::PreventDefault); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task)); EXPECT_FALSE(event_target->DispatchEvent(event, &exception_state)); } -TEST(EventTargetTest, RaiseException) { +TEST_F(EventTargetTest, RaiseException) { StrictMock<MockExceptionState> exception_state; scoped_refptr<script::ScriptException> exception; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event; std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); @@ -316,68 +440,110 @@ base::polymorphic_downcast<DOMException*>(exception.get())->code()); exception = NULL; + const void* async_task; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task)); event_target->AddEventListener( "fired", FakeScriptValue<EventListener>(event_listener.get()), false); event = new Event(base::Token("fired"), Event::kNotBubbles, Event::kNotCancelable); // Dispatch event again when it is being dispatched. + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task)); EXPECT_CALL(*event_listener, HandleEvent(_, _, _)) .WillOnce(Invoke(DispatchEventOnCurrentTarget)); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } -TEST(EventTargetTest, AddSameListenerMultipleTimes) { +TEST_F(EventTargetTest, AddSameListenerMultipleTimes) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); FakeScriptValue<EventListener> script_object(event_listener.get()); InSequence in_sequence; - event_listener->ExpectHandleEventCall(event, event_target); // The same listener should only get added once. + const void* async_task; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task)); event_target->AddEventListener("fired", script_object, false); event_target->AddEventListener("fired", script_object, false); event_target->AddEventListener("fired", script_object, false); + + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task)); + event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } -TEST(EventTargetTest, AddSameAttributeListenerMultipleTimes) { +TEST_F(EventTargetTest, AddSameAttributeListenerMultipleTimes) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); FakeScriptValue<EventListener> script_object(event_listener.get()); InSequence in_sequence; - event_listener->ExpectHandleEventCall(event, event_target); // The same listener should only get added once. + const void* async_task_1; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_1)); event_target->SetAttributeEventListener(base::Token("fired"), script_object); + + const void* async_task_2; + EXPECT_CALL(debugger_hooks_, AsyncTaskCanceled(async_task_1)); + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_2)); event_target->SetAttributeEventListener(base::Token("fired"), script_object); + + const void* async_task_3; + EXPECT_CALL(debugger_hooks_, AsyncTaskCanceled(async_task_2)); + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_3)); event_target->SetAttributeEventListener(base::Token("fired"), script_object); + + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_3)); + event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_3)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); } -TEST(EventTargetTest, SameEventListenerAsAttribute) { +TEST_F(EventTargetTest, SameEventListenerAsAttribute) { StrictMock<MockExceptionState> exception_state; - scoped_refptr<EventTarget> event_target = new EventTarget; + scoped_refptr<EventTarget> event_target = + new EventTarget(&environment_settings_); scoped_refptr<Event> event = new Event(base::Token("fired")); std::unique_ptr<MockEventListener> event_listener = MockEventListener::Create(); FakeScriptValue<EventListener> script_object(event_listener.get()); InSequence in_sequence; - event_listener->ExpectHandleEventCall(event, event_target); - event_listener->ExpectHandleEventCall(event, event_target); // The same script object can be registered as both an attribute and // non-attribute listener. Both should be fired. + const void* async_task_1; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_1)); event_target->AddEventListener("fired", script_object, false); + + const void* async_task_2; + EXPECT_CALL(debugger_hooks_, AsyncTaskScheduled(_, "fired", kRecurring)) + .WillOnce(SaveArg<0>(&async_task_2)); event_target->SetAttributeEventListener(base::Token("fired"), script_object); + + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_1)); + event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_1)); + EXPECT_CALL(debugger_hooks_, AsyncTaskStarted(async_task_2)); + event_listener->ExpectHandleEventCall(event, event_target); + EXPECT_CALL(debugger_hooks_, AsyncTaskFinished(async_task_2)); EXPECT_TRUE(event_target->DispatchEvent(event, &exception_state)); }
diff --git a/src/cobalt/dom/generic_event_handler_reference.cc b/src/cobalt/dom/generic_event_handler_reference.cc deleted file mode 100644 index 1066cf8..0000000 --- a/src/cobalt/dom/generic_event_handler_reference.cc +++ /dev/null
@@ -1,120 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cobalt/dom/generic_event_handler_reference.h" - -#include "base/trace_event/trace_event.h" -#include "cobalt/dom/event.h" -#include "cobalt/dom/event_target.h" - -namespace cobalt { -namespace dom { - -GenericEventHandlerReference::GenericEventHandlerReference( - script::Wrappable* wrappable, - const EventListenerScriptValue& script_value) { - if (!script_value.IsNull()) { - event_listener_reference_.reset( - new EventListenerScriptValue::Reference(wrappable, script_value)); - } -} - -GenericEventHandlerReference::GenericEventHandlerReference( - script::Wrappable* wrappable, - const OnErrorEventListenerScriptValue& script_value) { - if (!script_value.IsNull()) { - on_error_event_listener_reference_.reset( - new OnErrorEventListenerScriptValue::Reference(wrappable, - script_value)); - } -} - -GenericEventHandlerReference::GenericEventHandlerReference( - script::Wrappable* wrappable, const GenericEventHandlerReference& other) { - if (other.event_listener_reference_) { - event_listener_reference_.reset(new EventListenerScriptValue::Reference( - wrappable, other.event_listener_reference_->referenced_value())); - } else if (other.on_error_event_listener_reference_) { - on_error_event_listener_reference_.reset( - new OnErrorEventListenerScriptValue::Reference( - wrappable, - other.on_error_event_listener_reference_->referenced_value())); - } -} - -void GenericEventHandlerReference::HandleEvent( - const scoped_refptr<Event>& event, bool is_attribute, - bool unpack_error_event) { - TRACE_EVENT1("cobalt::dom", "GenericEventHandlerReference::HandleEvent", - "Event Name", TRACE_STR_COPY(event->type().c_str())); - bool had_exception; - base::Optional<bool> result; - - // Forward the HandleEvent() call to the appropriate internal object. - if (event_listener_reference_) { - // Non-onerror event handlers cannot have their parameters unpacked. - result = event_listener_reference_->value().HandleEvent( - event->current_target(), event, &had_exception); - } else if (on_error_event_listener_reference_) { - result = on_error_event_listener_reference_->value().HandleEvent( - event->current_target(), event, &had_exception, unpack_error_event); - } else { - NOTREACHED(); - had_exception = true; - } - - if (had_exception) { - return; - } - // EventHandlers (EventListeners set as attributes) may return false rather - // than call event.preventDefault() in the handler function. - if (is_attribute && result && !result.value()) { - event->PreventDefault(); - } -} - -bool GenericEventHandlerReference::EqualTo( - const EventListenerScriptValue& other) { - return (IsNull() && other.IsNull()) || - (event_listener_reference_ && - event_listener_reference_->referenced_value().EqualTo(other)); -} - -bool GenericEventHandlerReference::EqualTo( - const GenericEventHandlerReference& other) { - if (IsNull() && other.IsNull()) { - return true; - } - - if (event_listener_reference_ && other.event_listener_reference_) { - return event_listener_reference_->referenced_value().EqualTo( - other.event_listener_reference_->referenced_value()); - } - if (on_error_event_listener_reference_ && - other.on_error_event_listener_reference_) { - return on_error_event_listener_reference_->referenced_value().EqualTo( - other.on_error_event_listener_reference_->referenced_value()); - } - return false; -} - -bool GenericEventHandlerReference::IsNull() const { - return (!event_listener_reference_ || - event_listener_reference_->referenced_value().IsNull()) && - (!on_error_event_listener_reference_ || - on_error_event_listener_reference_->referenced_value().IsNull()); -} - -} // namespace dom -} // namespace cobalt
diff --git a/src/cobalt/dom/generic_event_handler_reference.h b/src/cobalt/dom/generic_event_handler_reference.h deleted file mode 100644 index 8a02c15..0000000 --- a/src/cobalt/dom/generic_event_handler_reference.h +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef COBALT_DOM_GENERIC_EVENT_HANDLER_REFERENCE_H_ -#define COBALT_DOM_GENERIC_EVENT_HANDLER_REFERENCE_H_ - -#include <memory> - -#include "base/memory/ref_counted.h" -#include "cobalt/dom/event_listener.h" -#include "cobalt/dom/on_error_event_listener.h" -#include "cobalt/script/script_value.h" -#include "cobalt/script/wrappable.h" - -namespace cobalt { -namespace dom { - -// Essentially acts as an abstract interface of the union for types -// [script::ScriptValue<EventListener>, -// script::ScriptValue<OnErrorEventListener>]. In particular it primarily -// allows code in event_target.cc to not need to concern itself with which -// exact EventListener script value type it is dealing with. The need for -// this abstraction arises from the fact that the |window.onerror| event -// handler requires special case handling: -// https://html.spec.whatwg.org/#onerroreventhandler ) -// -// NOTE that this is *not* an ideal solution to the problem of generalizing -// over multiple ScriptValue types. The problem is that the ScriptValue -// base class is both templated and abstract, making it difficult to cast its -// internal type to get a new ScriptValue. This problem could be solved by -// refactoring ScriptValue such that there is a non-templated abstract type -// (say, RawScriptValue) with a function like "void* GetValue()", but usually -// not referenced directly by client code. Instead there would be a separate -// templated concrete wrapper type (say, ScriptValue) that wraps RawScriptValue -// and manages the casting and type checking. This would allow us to convert -// between OnErrorEventListener and EventListener, if OnErrorEventListener was -// derived from EventListener. -class GenericEventHandlerReference { - public: - typedef script::ScriptValue<EventListener> EventListenerScriptValue; - typedef script::ScriptValue<OnErrorEventListener> - OnErrorEventListenerScriptValue; - - GenericEventHandlerReference(script::Wrappable* wrappable, - const EventListenerScriptValue& script_value); - GenericEventHandlerReference( - script::Wrappable* wrappable, - const OnErrorEventListenerScriptValue& script_value); - GenericEventHandlerReference(script::Wrappable* wrappable, - const GenericEventHandlerReference& other); - - // Forwards on to the internal event handler's HandleEvent() call, passing - // in the value of |unpack_error_event| if the internal type is a - // OnErrorEventListenerScriptValue type. - void HandleEvent(const scoped_refptr<Event>& event, bool is_attribute, - bool unpack_error_event); - - bool EqualTo(const EventListenerScriptValue& other); - bool EqualTo(const GenericEventHandlerReference& other); - bool IsNull() const; - - // If the internal type is a EventListenerScriptValue, then its value will - // be returned, otherwise null is returned; - const EventListenerScriptValue* event_listener_value() { - return event_listener_reference_ - ? &event_listener_reference_->referenced_value() - : nullptr; - } - - // If the internal type is a OnErrorEventListenerScriptValue, then its value - // will be returned, otherwise null is returned; - const OnErrorEventListenerScriptValue* on_error_event_listener_value() { - return on_error_event_listener_reference_ - ? &on_error_event_listener_reference_->referenced_value() - : nullptr; - } - - private: - // At most only one of the below two fields may be non-null... They are - // serving as a poor man's std::variant. - std::unique_ptr<EventListenerScriptValue::Reference> - event_listener_reference_; - std::unique_ptr<OnErrorEventListenerScriptValue::Reference> - on_error_event_listener_reference_; - - DISALLOW_COPY_AND_ASSIGN(GenericEventHandlerReference); -}; - -} // namespace dom -} // namespace cobalt - -#endif // COBALT_DOM_GENERIC_EVENT_HANDLER_REFERENCE_H_
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc index c52faae8..1d3a522 100644 --- a/src/cobalt/dom/html_element.cc +++ b/src/cobalt/dom/html_element.cc
@@ -169,9 +169,9 @@ // https://dev.w3.org/html5/spec-preview/global-attributes.html#the-directionality // https://dev.w3.org/html5/spec-preview/common-dom-interfaces.html#limited-to-only-known-values // NOTE: Value "auto" is not supported. - if (directionality_ == kLeftToRightDirectionality) { + if (dir_ == kDirLeftToRight) { return "ltr"; - } else if (directionality_ == kRightToLeftDirectionality) { + } else if (dir_ == kDirRightToLeft) { return "rtl"; } else { return ""; @@ -179,10 +179,7 @@ } void HTMLElement::set_dir(const std::string& value) { - // The dir attribute is limited to only known values. On setting, the dir - // attribute must be set to the specified new value. - // https://dev.w3.org/html5/spec-preview/global-attributes.html#the-directionality - // https://dev.w3.org/html5/spec-preview/common-dom-interfaces.html#limited-to-only-known-values + // Funnel through OnSetAttribute. SetAttribute("dir", value); } @@ -360,7 +357,7 @@ int32 element_scroll_width = 0; if (layout_boxes_) { element_scroll_width = static_cast<int32>( - layout_boxes_->GetScrollArea(directionality_).width()); + layout_boxes_->GetScrollArea(directionality()).width()); } // 3. Let viewport width be the width of the viewport excluding the width of @@ -396,7 +393,7 @@ int32 element_scroll_height = 0; if (layout_boxes_) { element_scroll_height = static_cast<int32>( - layout_boxes_->GetScrollArea(directionality_).height()); + layout_boxes_->GetScrollArea(directionality()).height()); } // 3. Let viewport height be the height of the viewport excluding the height @@ -776,7 +773,7 @@ // Copy cached attributes. new_html_element->tabindex_ = tabindex_; - new_html_element->directionality_ = directionality_; + new_html_element->dir_ = dir_; return new_html_element; } @@ -1144,6 +1141,7 @@ pseudo_element->reset_layout_boxes(); } } + directionality_ = base::nullopt; } void HTMLElement::OnUiNavBlur() { @@ -1170,7 +1168,7 @@ : Element(document, local_name), dom_stat_tracker_(document->html_element_context()->dom_stat_tracker()), locked_for_focus_(false), - directionality_(kNoExplicitDirectionality), + dir_(kDirNotDefined), style_(new cssom::CSSDeclaredStyleDeclaration( document->html_element_context()->css_parser())), computed_style_valid_(false), @@ -1242,7 +1240,7 @@ const std::string& value) { // Be sure to update HTMLElement::Duplicate() to copy over values as needed. if (name == "dir") { - SetDirectionality(value); + SetDir(value); } else if (name == "tabindex") { SetTabIndex(value); } @@ -1254,7 +1252,7 @@ void HTMLElement::OnRemoveAttribute(const std::string& name) { if (name == "dir") { - SetDirectionality(""); + SetDir(""); } else if (name == "tabindex") { SetTabIndex(""); } @@ -1391,18 +1389,26 @@ ClearRuleMatchingState(); } -void HTMLElement::SetDirectionality(const std::string& value) { +void HTMLElement::SetDir(const std::string& value) { + // https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-dir-attribute // NOTE: Value "auto" is not supported. - Directionality previous_directionality = directionality_; + auto previous_dir = dir_; if (value == "ltr") { - directionality_ = kLeftToRightDirectionality; + dir_ = kDirLeftToRight; } else if (value == "rtl") { - directionality_ = kRightToLeftDirectionality; + dir_ = kDirRightToLeft; } else { - directionality_ = kNoExplicitDirectionality; + dir_ = kDirNotDefined; + + // Reset the attribute so that element.getAttribute('dir') returns the + // same thing as element.dir. + if (value.size() > 0) { + LOG(WARNING) << "Unsupported value '" << value << "' for attribute 'dir'"; + SetAttribute("dir", ""); + } } - if (directionality_ != previous_directionality) { + if (dir_ != previous_dir) { InvalidateLayoutBoxesOfNodeAndAncestors(); InvalidateLayoutBoxesOfDescendants(); } @@ -1417,6 +1423,92 @@ } } +// Algorithm: +// https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-directionality +Directionality HTMLElement::directionality() { + // Use the cached value if available. + if (directionality_) { + return *directionality_; + } + + // The directionality of an element (any element, not just an HTML element) + // is either 'ltr' or 'rtl', and is determined as per the first appropriate + // set of steps from the following list: + + // If the element's dir attribute is in the ltr state + // If the element is a document element and the dir attribute is not in a + // defined state (i.e. it is not present or has an invalid value) + // If the element is an input element whose type attribute is in the + // Telephone state, and the dir attribute is not in a defined state (i.e. + // it is not present or has an invalid value) + // --> The directionality of the element is 'ltr'. + if (dir_ == kDirLeftToRight) { + directionality_ = kLeftToRightDirectionality; + return *directionality_; + } + // [Case of undefined 'dir' is handled later in this function.] + + // If the element's dir attribute is in the rtl state + // --> The directionality of the element is 'rtl'. + if (dir_ == kDirRightToLeft) { + directionality_ = kRightToLeftDirectionality; + return *directionality_; + } + + // If the element is an input element whose type attribute is in the Text, + // Search, Telephone, URL, or E-mail state, and the dir attribute is in the + // auto state + // If the element is a textarea element and the dir attribute is in the auto + // state + // --> Cobalt does not support these element types. + + // If the element's dir attribute is in the auto state + // If the element is a bdi element and the dir attribute is not in a defined + // state (i.e. it is not present or has an invalid value) + // --> Find the first character in tree order that matches the following + // criteria: + // The character is from a Text node that is a descendant of the + // element whose directionality is being determined. + // The character is of bidirectional character type L, AL, or R. [BIDI] + // The character is not in a Text node that has an ancestor element + // that is a descendant of the element whose directionality is being + // determined and that is either: + // A bdi element. + // A script element. + // A style element. + // A textarea element. + // An element with a dir attribute in a defined state. + // If such a character is found and it is of bidirectional character type + // AL or R, the directionality of the element is 'rtl'. + // If such a character is found and it is of bidirectional character type + // L, the directionality of the element is 'ltr'. + // Otherwise, if the element is a document element, the directionality of + // the element is 'ltr'. + // Otherwise, the directionality of the element is the same as the + // element's parent element's directionality. + + // If the element has a parent element and the dir attribute is not in a + // defined state (i.e. it is not present or has an invalid value) + // --> The directionality of the element is the same as the element's parent + // element's directionality. + for (Node* ancestor_node = parent_node(); ancestor_node; + ancestor_node = ancestor_node->parent_node()) { + Element* ancestor_element = ancestor_node->AsElement(); + if (!ancestor_element) { + continue; + } + HTMLElement* ancestor_html_element = ancestor_element->AsHTMLElement(); + if (!ancestor_html_element) { + continue; + } + directionality_ = ancestor_html_element->directionality(); + return *directionality_; + } + + directionality_ = kLeftToRightDirectionality; + return *directionality_; +} + namespace { scoped_refptr<cssom::CSSComputedStyleData> PromoteMatchingRulesToComputedStyle(
diff --git a/src/cobalt/dom/html_element.h b/src/cobalt/dom/html_element.h index 5cf5a48..5166bf8 100644 --- a/src/cobalt/dom/html_element.h +++ b/src/cobalt/dom/html_element.h
@@ -134,6 +134,14 @@ kAncestorsAreNotDisplayed, }; + // https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-dir-attribute + // NOTE: 'auto' is not supported. + enum DirState { + kDirLeftToRight, + kDirRightToLeft, + kDirNotDefined, + }; + // Web API: HTMLElement // std::string dir() const; @@ -220,9 +228,14 @@ virtual scoped_refptr<HTMLVideoElement> AsHTMLVideoElement(); // Returns the directionality of the element, which is based upon the - // underlying "dir" attribute, and is updated when the attribute changes. - // https://dev.w3.org/html5/spec-preview/global-attributes.html#the-directionalityy. - Directionality directionality() const { return directionality_; } + // element's "dir" attribute if it was set, or that of the parent's if not + // set. + // https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-directionality + Directionality directionality(); + + // Retrieve the dir attribute state. This is similar to dir() but returns the + // enumerated state rather than string. + DirState dir_state() const { return dir_; } // Rule matching related methods. // @@ -368,14 +381,9 @@ void RunFocusingSteps(); void RunUnFocusingSteps(); - // This both updates the directionality based upon the string value and + // This both updates the 'dir' attribute based upon the string value and // invalidates layout box caching if the value has changed. - // NOTE1: Value "auto" is not supported. - // NOTE2: Cobalt does not support either the CSS 'direction" or "unicode-bidi' - // properties, and instead relies entirely upon the 'dir' attribute for - // determining directionality of elements. As a result of this, setting the - // directionality does not invalidate the computed style. - void SetDirectionality(const std::string& value); + void SetDir(const std::string& value); // Update the cached value of tabindex. void SetTabIndex(const std::string& value); @@ -416,15 +424,17 @@ bool locked_for_focus_; - // The directionality of the html element is determined by the 'dir' - // attribute. - // https://dev.w3.org/html5/spec-preview/global-attributes.html#the-directionality - // NOTE1: Value "auto" is not supported. - // NOTE2: Cobalt does not support either the CSS 'direction" or "unicode-bidi' + // This represents the enumerated value of the 'dir' attribute. + // https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-dir-attribute + DirState dir_; + + // This represents the computed directionality for this element. + // https://html.spec.whatwg.org/commit-snapshots/ebcac971c2add28a911283899da84ec509876c44/#the-directionality + // NOTE: Cobalt does not support either the CSS 'direction' or 'unicode-bidi' // properties, and instead relies entirely upon the 'dir' attribute for // determining directionality. Inheritance of directionality occurs via the // base direction of the parent element's paragraph. - Directionality directionality_; + base::Optional<Directionality> directionality_; // Cache the tabindex value. base::Optional<int32> tabindex_;
diff --git a/src/cobalt/dom/html_element_context.cc b/src/cobalt/dom/html_element_context.cc index f288b4e..7e55422 100644 --- a/src/cobalt/dom/html_element_context.cc +++ b/src/cobalt/dom/html_element_context.cc
@@ -16,11 +16,18 @@ #include "cobalt/dom/html_element_factory.h" +#if !defined(COBALT_BUILD_TYPE_GOLD) +#include "cobalt/dom/testing/stub_environment_settings.h" +#endif // !defined(COBALT_BUILD_TYPE_GOLD) + namespace cobalt { namespace dom { +#if !defined(COBALT_BUILD_TYPE_GOLD) HTMLElementContext::HTMLElementContext() - : fetcher_factory_(NULL), + : stub_environment_settings_(new testing::StubEnvironmentSettings), + environment_settings_(stub_environment_settings_.get()), + fetcher_factory_(NULL), loader_factory_(NULL), css_parser_(NULL), dom_parser_(NULL), @@ -42,8 +49,10 @@ html_element_factory_(new HTMLElementFactory()) { sync_load_thread_.Start(); } +#endif // !defined(COBALT_BUILD_TYPE_GOLD) HTMLElementContext::HTMLElementContext( + script::EnvironmentSettings* environment_settings, loader::FetcherFactory* fetcher_factory, loader::LoaderFactory* loader_factory, cssom::CSSParser* css_parser, Parser* dom_parser, media::CanPlayTypeHandler* can_play_type_handler, @@ -62,7 +71,8 @@ base::ApplicationState initial_application_state, base::WaitableEvent* synchronous_loader_interrupt, float video_playback_rate_multiplier) - : fetcher_factory_(fetcher_factory), + : environment_settings_(environment_settings), + fetcher_factory_(fetcher_factory), loader_factory_(loader_factory), css_parser_(css_parser), dom_parser_(dom_parser),
diff --git a/src/cobalt/dom/html_element_context.h b/src/cobalt/dom/html_element_context.h index e67b6d1..71d761c 100644 --- a/src/cobalt/dom/html_element_context.h +++ b/src/cobalt/dom/html_element_context.h
@@ -33,6 +33,7 @@ #include "cobalt/media/can_play_type_handler.h" #include "cobalt/media/web_media_player_factory.h" #include "cobalt/page_visibility/page_visibility_state.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/script_runner.h" #include "cobalt/script/script_value_factory.h" @@ -49,8 +50,13 @@ public: typedef UrlRegistry<MediaSource> MediaSourceRegistry; +#if !defined(COBALT_BUILD_TYPE_GOLD) + // No-args constructor for tests. HTMLElementContext(); +#endif // !defined(COBALT_BUILD_TYPE_GOLD) + HTMLElementContext( + script::EnvironmentSettings* environment_settings, loader::FetcherFactory* fetcher_factory, loader::LoaderFactory* loader_factory, cssom::CSSParser* css_parser, Parser* dom_parser, media::CanPlayTypeHandler* can_play_type_handler, @@ -71,6 +77,10 @@ float video_playback_rate_multiplier = 1.0); ~HTMLElementContext(); + script::EnvironmentSettings* environment_settings() const { + return environment_settings_; + } + loader::FetcherFactory* fetcher_factory() { return fetcher_factory_; } loader::LoaderFactory* loader_factory() { return loader_factory_; } @@ -146,6 +156,12 @@ } private: +#if !defined(COBALT_BUILD_TYPE_GOLD) + // StubEnvironmentSettings for no-args test constructor. + std::unique_ptr<script::EnvironmentSettings> stub_environment_settings_; +#endif // !defined(COBALT_BUILD_TYPE_GOLD) + + script::EnvironmentSettings* environment_settings_; loader::FetcherFactory* const fetcher_factory_; loader::LoaderFactory* const loader_factory_; cssom::CSSParser* const css_parser_;
diff --git a/src/cobalt/dom/html_element_factory.cc b/src/cobalt/dom/html_element_factory.cc index 5af905d..6612cdd 100644 --- a/src/cobalt/dom/html_element_factory.cc +++ b/src/cobalt/dom/html_element_factory.cc
@@ -15,6 +15,7 @@ #include "cobalt/dom/html_element_factory.h" #include "base/bind.h" +#include "base/third_party/icu/icu_utf.h" #include "cobalt/dom/html_anchor_element.h" #include "cobalt/dom/html_audio_element.h" #include "cobalt/dom/html_body_element.h" @@ -54,6 +55,91 @@ return new T(document, base::Token(local_name)); } +bool IsValidAsciiChar(char32_t c) { + const bool isLowerAscii = c >= 'a' && c <= 'z'; + const bool isLowerDigit = c >= '0' && c <= '9'; + return isLowerAscii || isLowerDigit || c == '.' || c == '_'; +} + +// Grandfathered HTML elements that meet CustomElement naming spec: +// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name +bool IsBlacklistedTag(const char* tag, int length) { + switch (length) { + case 9: + if (SbStringCompareAll(tag, "font-face") == 0) { + return true; + } + break; + case 13: + if (SbStringCompareAll(tag, "font-face-src") == 0 || + SbStringCompareAll(tag, "missing-glyph") == 0 || + SbStringCompareAll(tag, "color-profile") == 0 || + SbStringCompareAll(tag, "font-face-uri") == 0) { + return true; + } + break; + case 14: + if (SbStringCompareAll(tag, "font-face-name") == 0 || + SbStringCompareAll(tag, "annotation-xml") == 0) { + return true; + } + break; + case 16: + if (SbStringCompareAll(tag, "font-face-format") == 0) { + return true; + } + break; + default: + return false; + } + return false; +} + +// Follows naming spec at +// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name +bool IsValidCustomElementName(base::Token tag_name) { + // Consider adding support for customElements.define in order to + // formally register CustomElements rather than filter out errors + // for all potential custom names. + + const char* tag = tag_name.c_str(); + char c = tag[0]; + if (c < 'a' || c > 'z') { + return false; + } + bool contains_hyphen = false; + int length = 1; + + while ((c = tag[length]) != '\0') { + // Early return to avoid utf32 conversion cost for most cases. + if (IsValidAsciiChar(c)) { + length++; + continue; + } + if (c == '-') { + contains_hyphen = true; + length++; + continue; + } + base_icu::UChar32 c32; + + CBU8_NEXT(tag, length, -1, c32); + bool is_valid_char = + c32 == 0xb7 || (c32 >= 0xc0 && c32 <= 0xd6) || + (c32 >= 0xd8 && c32 <= 0xf6) || (c32 >= 0xf8 && c32 <= 0x037d) || + (c32 >= 0x037f && c32 <= 0x1fff) || (c32 >= 0x200c && c32 <= 0x200d) || + (c32 >= 0x203f && c32 <= 0x2040) || (c32 >= 0x2070 && c32 <= 0x218f) || + (c32 >= 0x2c00 && c32 <= 0x2fef) || (c32 >= 0x3001 && c32 <= 0xd7ff) || + (c32 >= 0xf900 && c32 <= 0xfdcf) || (c32 >= 0xfdf0 && c32 <= 0xfffd) || + (c32 >= 0x00010000 && c32 <= 0x000effff); + if (!is_valid_char) { + return false; + } + } + + return contains_hyphen && !IsBlacklistedTag(tag, length); +} + } // namespace HTMLElementFactory::HTMLElementFactory() { @@ -89,7 +175,8 @@ if (iter != tag_name_to_create_html_element_t_callback_map_.end()) { return iter->second.Run(document); } else { - LOG(WARNING) << "Unknown HTML element: <" << tag_name << ">."; + LOG_IF(WARNING, !IsValidCustomElementName(tag_name)) + << "Unknown HTML element: <" << tag_name << ">."; return new HTMLUnknownElement(document, tag_name); } }
diff --git a/src/cobalt/dom/html_element_factory_test.cc b/src/cobalt/dom/html_element_factory_test.cc index f252c75..8b54486 100644 --- a/src/cobalt/dom/html_element_factory_test.cc +++ b/src/cobalt/dom/html_element_factory_test.cc
@@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/html_element_factory.h" +#include <memory> + #include "base/message_loop/message_loop.h" #include "base/threading/platform_thread.h" #include "cobalt/dom/document.h" @@ -41,6 +41,7 @@ #include "cobalt/dom/html_unknown_element.h" #include "cobalt/dom/html_video_element.h" #include "cobalt/dom/testing/stub_css_parser.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/testing/stub_script_runner.h" #include "cobalt/dom_parser/parser.h" #include "cobalt/loader/fetcher_factory.h" @@ -61,8 +62,9 @@ dom_parser_(new dom_parser::Parser()), dom_stat_tracker_(new DomStatTracker("HTMLElementFactoryTest")), html_element_context_( - &fetcher_factory_, &loader_factory_, &stub_css_parser_, - dom_parser_.get(), NULL /* can_play_type_handler */, + &environment_settings_, &fetcher_factory_, &loader_factory_, + &stub_css_parser_, dom_parser_.get(), + NULL /* can_play_type_handler */, NULL /* web_media_player_factory */, &stub_script_runner_, NULL /* script_value_factory */, NULL /* media_source_registry */, NULL /* resource_provider */, NULL /* animated_image_tracker */, @@ -75,6 +77,7 @@ document_(new Document(&html_element_context_)) {} ~HTMLElementFactoryTest() override {} + testing::StubEnvironmentSettings environment_settings_; loader::FetcherFactory fetcher_factory_; loader::LoaderFactory loader_factory_; std::unique_ptr<Parser> dom_parser_;
diff --git a/src/cobalt/dom/html_element_test.cc b/src/cobalt/dom/html_element_test.cc index 8fa740f..25ad26b 100644 --- a/src/cobalt/dom/html_element_test.cc +++ b/src/cobalt/dom/html_element_test.cc
@@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/html_element.h" +#include <memory> + #include "base/basictypes.h" #include "base/message_loop/message_loop.h" #include "cobalt/base/polymorphic_downcast.h" @@ -32,6 +32,7 @@ #include "cobalt/dom/html_element_context.h" #include "cobalt/dom/layout_boxes.h" #include "cobalt/dom/named_node_map.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/testing/stub_window.h" #include "cobalt/dom/window.h" #include "cobalt/media_session/media_session.h" @@ -40,8 +41,8 @@ #include "testing/gtest/include/gtest/gtest.h" using cobalt::cssom::ViewportSize; -using testing::Return; using testing::_; +using testing::Return; namespace cobalt { namespace dom { @@ -69,10 +70,9 @@ const char kFooBarDeclarationString[] = "foo: bar;"; const char kDisplayInlineDeclarationString[] = "display: inline;"; const char* kHtmlElementTagNames[] = { - // "audio", "script", and "video" are excluded since they need more setup. - "a", "body", "br", "div", "head", "h1", "html", "img", "link", - "meta", "p", "span", "style", "title" -}; + // "audio", "script", and "video" are excluded since they need more setup. + "a", "body", "br", "div", "head", "h1", "html", + "img", "link", "meta", "p", "span", "style", "title"}; class MockLayoutBoxes : public LayoutBoxes { public: @@ -132,10 +132,10 @@ protected: HTMLElementTest() : dom_stat_tracker_(new DomStatTracker("HTMLElementTest")), - html_element_context_(NULL, NULL, &css_parser_, NULL, NULL, NULL, NULL, + html_element_context_(&environment_settings_, NULL, NULL, &css_parser_, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - dom_stat_tracker_.get(), "", - base::kApplicationStateStarted, NULL), + NULL, NULL, NULL, NULL, dom_stat_tracker_.get(), + "", base::kApplicationStateStarted, NULL), document_(new Document(&html_element_context_)) {} ~HTMLElementTest() override {} @@ -147,6 +147,7 @@ void SetElementStyle(const scoped_refptr<cssom::CSSDeclaredStyleData>& data, HTMLElement* html_element); + testing::StubEnvironmentSettings environment_settings_; cssom::testing::MockCSSParser css_parser_; std::unique_ptr<DomStatTracker> dom_stat_tracker_; HTMLElementContext html_element_context_;
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc index d803d68..44340f2 100644 --- a/src/cobalt/dom/html_media_element.cc +++ b/src/cobalt/dom/html_media_element.cc
@@ -25,6 +25,7 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/trace_event/trace_event.h" +#include "cobalt/base/instance_counter.h" #include "cobalt/base/tokens.h" #include "cobalt/cssom/map_to_mesh_function.h" #include "cobalt/dom/csp_delegate.h" @@ -69,6 +70,8 @@ #endif // LOG_MEDIA_ELEMENT_ACTIVITIES +DECLARE_INSTANCE_COUNTER(HTMLMediaElement); + loader::RequestMode GetRequestMode( const base::Optional<std::string>& cross_origin_attribute) { // https://html.spec.whatwg.org/#cors-settings-attribute @@ -91,7 +94,7 @@ if (resource_url.SchemeIs("data")) { return true; } - // Check if resource_url is an hls url. Hls url must contain "hls_variant" + // Check if resource_url is an hls url. Hls url must contain "hls_variant". return resource_url.spec().find("hls_variant") != std::string::npos; } #endif // SB_HAS(PLAYER_WITH_URL) @@ -151,12 +154,14 @@ request_mode_(loader::kNoCORSMode) { TRACE_EVENT0("cobalt::dom", "HTMLMediaElement::HTMLMediaElement()"); MLOG(); + ON_INSTANCE_CREATED(HTMLMediaElement); } HTMLMediaElement::~HTMLMediaElement() { TRACE_EVENT0("cobalt::dom", "HTMLMediaElement::~HTMLMediaElement()"); MLOG(); ClearMediaSource(); + ON_INSTANCE_RELEASED(HTMLMediaElement); } scoped_refptr<MediaError> HTMLMediaElement::error() const { @@ -593,6 +598,10 @@ if (!src.empty()) { set_src(src); } + + if (HasAttribute("muted")) { + set_muted(true); + } } void HTMLMediaElement::TraceMembers(script::Tracer* tracer) { @@ -1599,7 +1608,7 @@ void HTMLMediaElement::SawUnsupportedTracks() { NOTIMPLEMENTED(); } -float HTMLMediaElement::Volume() const { return volume(NULL); } +float HTMLMediaElement::Volume() const { return muted_ ? 0 : volume(NULL); } void HTMLMediaElement::SourceOpened(ChunkDemuxer* chunk_demuxer) { TRACE_EVENT0("cobalt::dom", "HTMLMediaElement::SourceOpened()");
diff --git a/src/cobalt/dom/media_source.cc b/src/cobalt/dom/media_source.cc index 57bc8c0..c3df595 100644 --- a/src/cobalt/dom/media_source.cc +++ b/src/cobalt/dom/media_source.cc
@@ -64,10 +64,10 @@ namespace cobalt { namespace dom { -using media::PipelineStatus; -using media::CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR; using media::CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR; +using media::CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR; using media::PIPELINE_OK; +using media::PipelineStatus; namespace { @@ -102,12 +102,13 @@ } // namespace -MediaSource::MediaSource() - : chunk_demuxer_(NULL), +MediaSource::MediaSource(script::EnvironmentSettings* settings) + : EventTarget(settings), + chunk_demuxer_(NULL), ready_state_(kMediaSourceReadyStateClosed), ALLOW_THIS_IN_INITIALIZER_LIST(event_queue_(this)), - source_buffers_(new SourceBufferList(&event_queue_)), - active_source_buffers_(new SourceBufferList(&event_queue_)), + source_buffers_(new SourceBufferList(settings, &event_queue_)), + active_source_buffers_(new SourceBufferList(settings, &event_queue_)), live_seekable_range_(new TimeRanges) {} MediaSource::~MediaSource() { SetReadyState(kMediaSourceReadyStateClosed); } @@ -218,7 +219,7 @@ switch (status) { case ChunkDemuxer::kOk: source_buffer = - new SourceBuffer(guid, this, chunk_demuxer_, &event_queue_); + new SourceBuffer(settings, guid, this, chunk_demuxer_, &event_queue_); break; case ChunkDemuxer::kNotSupported: DOMException::Raise(DOMException::kNotSupportedErr, exception_state);
diff --git a/src/cobalt/dom/media_source.h b/src/cobalt/dom/media_source.h index 5c3157e..5951b33 100644 --- a/src/cobalt/dom/media_source.h +++ b/src/cobalt/dom/media_source.h
@@ -77,7 +77,7 @@ // Custom, not in any spec. // - MediaSource(); + explicit MediaSource(script::EnvironmentSettings* settings); ~MediaSource(); // Web API: MediaSource
diff --git a/src/cobalt/dom/media_source.idl b/src/cobalt/dom/media_source.idl index 5529e0f..63a64d8 100644 --- a/src/cobalt/dom/media_source.idl +++ b/src/cobalt/dom/media_source.idl
@@ -15,7 +15,11 @@ // https://www.w3.org/TR/media-source/#idl-def-mediasource // https://www.w3.org/TR/2016/CR-media-source-20160705/#idl-def-MediaSource -[Constructor] interface MediaSource : EventTarget { +[ + Constructor, + ConstructorCallWith=EnvironmentSettings, +] +interface MediaSource : EventTarget { // All the source buffers created by this object. readonly attribute SourceBufferList sourceBuffers; // Subset of sourceBuffers that provide data for the selected/enabled tracks.
diff --git a/src/cobalt/dom/mutation_observer.cc b/src/cobalt/dom/mutation_observer.cc index 55c33ca..0472f70 100644 --- a/src/cobalt/dom/mutation_observer.cc +++ b/src/cobalt/dom/mutation_observer.cc
@@ -15,6 +15,7 @@ #include "cobalt/dom/mutation_observer.h" #include "base/trace_event/trace_event.h" +#include "cobalt/base/debugger_hooks.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/dom/dom_settings.h" #include "cobalt/dom/mutation_observer_task_manager.h" @@ -83,8 +84,9 @@ MutationObserver::MutationObserver( const NativeMutationCallback& native_callback, - MutationObserverTaskManager* task_manager) - : task_manager_(task_manager) { + MutationObserverTaskManager* task_manager, + base::DebuggerHooks* debugger_hooks) + : task_manager_(task_manager), debugger_hooks_(debugger_hooks) { callback_.reset(new NativeCallback(native_callback)); task_manager_->OnMutationObserverCreated(this); } @@ -92,7 +94,9 @@ MutationObserver::MutationObserver(script::EnvironmentSettings* settings, const MutationCallbackArg& callback) : task_manager_(base::polymorphic_downcast<DOMSettings*>(settings) - ->mutation_observer_task_manager()) { + ->mutation_observer_task_manager()), + debugger_hooks_(base::polymorphic_downcast<DOMSettings*>(settings) + ->debugger_hooks()) { callback_.reset(new ScriptCallback(callback, this)); task_manager_->OnMutationObserverCreated(this); } @@ -108,6 +112,7 @@ } void MutationObserver::Disconnect() { + CancelDebuggerAsyncTasks(); // The disconnect() method must, for each node in the context object's // list of nodes, remove any registered observer on node for which the context // object is the observer, and also empty context object's record queue. @@ -123,6 +128,7 @@ } MutationObserver::MutationRecordSequence MutationObserver::TakeRecords() { + CancelDebuggerAsyncTasks(); // The takeRecords() method must return a copy of the record queue and then // empty the record queue. MutationRecordSequence record_queue; @@ -135,6 +141,10 @@ TRACE_EVENT0("cobalt::dom", "MutationObserver::QueueMutationRecord()"); record_queue_.push_back(record); task_manager_->QueueMutationObserverMicrotask(); + MutationRecord* task = record.get(); + debugger_hooks_->AsyncTaskScheduled( + task, record->type().c_str(), + base::DebuggerHooks::AsyncTaskFrequency::kOneshot); } bool MutationObserver::Notify() { @@ -143,7 +153,8 @@ // Step 3 of "notify mutation observers" steps: // 1. Let queue be a copy of mo's record queue. // 2. Empty mo's record queue. - MutationRecordSequence records = TakeRecords(); + MutationRecordSequence records; + records.swap(record_queue_); // 3. Remove all transient registered observers whose observer is mo. // TODO: handle transient registered observers. @@ -152,6 +163,9 @@ // argument, and mo (itself) as second argument and callback this // value. If this throws an exception, report the exception. if (!records.empty()) { + // Report the first (earliest) stack as the async cause. + MutationRecord* task = records.begin()->get(); + base::ScopedAsyncTask async_task(debugger_hooks_, task); return callback_->RunCallback(records, base::WrapRefCounted(this)); } // If no records, return true to indicate no error occurred. @@ -163,6 +177,13 @@ tracer->TraceItems(record_queue_); } +void MutationObserver::CancelDebuggerAsyncTasks() { + for (auto record : record_queue_) { + MutationRecord* task = record.get(); + debugger_hooks_->AsyncTaskCanceled(task); + } +} + void MutationObserver::TrackObservedNode(const scoped_refptr<dom::Node>& node) { for (WeakNodeVector::iterator it = observed_nodes_.begin(); it != observed_nodes_.end();) {
diff --git a/src/cobalt/dom/mutation_observer.h b/src/cobalt/dom/mutation_observer.h index 962ea0a..c7f50ef 100644 --- a/src/cobalt/dom/mutation_observer.h +++ b/src/cobalt/dom/mutation_observer.h
@@ -29,6 +29,10 @@ #include "cobalt/script/sequence.h" #include "cobalt/script/wrappable.h" +namespace base { +class DebuggerHooks; +} // namespace base + namespace cobalt { namespace dom { @@ -55,7 +59,8 @@ // Not part of the spec. Support creating MutationObservers from native Cobalt // code. MutationObserver(const NativeMutationCallback& native_callback, - MutationObserverTaskManager* task_manager); + MutationObserverTaskManager* task_manager, + base::DebuggerHooks* debugger_hooks); // Web Api: MutationObserver MutationObserver(script::EnvironmentSettings* settings, @@ -95,6 +100,7 @@ void TraceMembers(script::Tracer* tracer) override; private: + void CancelDebuggerAsyncTasks(); void TrackObservedNode(const scoped_refptr<dom::Node>& node); void ObserveInternal(const scoped_refptr<Node>& target, @@ -106,6 +112,7 @@ WeakNodeVector observed_nodes_; MutationRecordSequence record_queue_; MutationObserverTaskManager* task_manager_; + base::DebuggerHooks* debugger_hooks_; }; } // namespace dom } // namespace cobalt
diff --git a/src/cobalt/dom/mutation_observer_test.cc b/src/cobalt/dom/mutation_observer_test.cc index e168c80..edae725 100644 --- a/src/cobalt/dom/mutation_observer_test.cc +++ b/src/cobalt/dom/mutation_observer_test.cc
@@ -26,12 +26,15 @@ #include "cobalt/script/sequence.h" #include "cobalt/script/testing/mock_exception_state.h" #include "cobalt/test/empty_document.h" +#include "cobalt/test/mock_debugger_hooks.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::_; using ::testing::SaveArg; +constexpr auto kOneshot = base::DebuggerHooks::AsyncTaskFrequency::kOneshot; + namespace cobalt { namespace dom { // Helper struct for childList mutations. @@ -42,6 +45,8 @@ scoped_refptr<dom::NodeList> removed_nodes; }; +typedef ::testing::StrictMock<test::MockDebuggerHooks> DebuggerHooksMock; + class MutationCallbackMock { public: MOCK_METHOD2(NativeMutationCallback, @@ -53,6 +58,7 @@ protected: dom::Document* document() { return empty_document_.document(); } MutationObserverTaskManager* task_manager() { return &task_manager_; } + DebuggerHooksMock* debugger_hooks() { return &debugger_hooks_; } MutationCallbackMock* callback_mock() { return &callback_mock_; } scoped_refptr<Element> CreateDiv() { @@ -66,7 +72,7 @@ return new MutationObserver( base::Bind(&MutationCallbackMock::NativeMutationCallback, base::Unretained(&callback_mock_)), - &task_manager_); + &task_manager_, &debugger_hooks_); } ChildListMutationArguments CreateChildListMutationArguments() { @@ -85,6 +91,7 @@ private: MutationObserverTaskManager task_manager_; + DebuggerHooksMock debugger_hooks_; test::EmptyDocument empty_document_; MutationCallbackMock callback_mock_; base::MessageLoop message_loop_; @@ -220,9 +227,14 @@ scoped_refptr<MutationRecord> record = MutationRecord::CreateCharacterDataMutationRecord( target, std::string("old_character_data")); + const void* async_task; + EXPECT_CALL(*debugger_hooks(), + AsyncTaskScheduled(_, "characterData", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); observer->QueueMutationRecord(record); // The queued record can be taken once. + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task)); records = observer->TakeRecords(); ASSERT_EQ(1, records.size()); ASSERT_EQ(records.at(0), record); @@ -238,13 +250,19 @@ scoped_refptr<MutationRecord> record = MutationRecord::CreateCharacterDataMutationRecord( target, std::string("old_character_data")); + const void* async_task; + EXPECT_CALL(*debugger_hooks(), + AsyncTaskScheduled(_, "characterData", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); observer->QueueMutationRecord(record); // Callback should be fired with the first argument being a sequence of the // queued record, and the second argument being the observer. MutationObserver::MutationRecordSequence records; + EXPECT_CALL(*debugger_hooks(), AsyncTaskStarted(async_task)); EXPECT_CALL(*callback_mock(), NativeMutationCallback(_, observer)) .WillOnce(SaveArg<0>(&records)); + EXPECT_CALL(*debugger_hooks(), AsyncTaskFinished(async_task)); observer->Notify(); ASSERT_EQ(1, records.size()); EXPECT_EQ(record, records.at(0)); @@ -253,6 +271,26 @@ // fired. records = observer->TakeRecords(); EXPECT_TRUE(records.empty()); + + // Queue another mutation record on the same ovserver. + record = MutationRecord::CreateAttributeMutationRecord( + target, "attribute_name", std::string("old_attribute_data")); + EXPECT_CALL(*debugger_hooks(), AsyncTaskScheduled(_, "attributes", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); + observer->QueueMutationRecord(record); + + // Check that the new record goes to the callback. + EXPECT_CALL(*debugger_hooks(), AsyncTaskStarted(async_task)); + EXPECT_CALL(*callback_mock(), NativeMutationCallback(_, observer)) + .WillOnce(SaveArg<0>(&records)); + EXPECT_CALL(*debugger_hooks(), AsyncTaskFinished(async_task)); + observer->Notify(); + ASSERT_EQ(1, records.size()); + EXPECT_EQ(record, records.at(0)); + + // No more records after notifying. + records = observer->TakeRecords(); + EXPECT_TRUE(records.empty()); } TEST_F(MutationObserverTest, ReportMutation) { @@ -273,6 +311,13 @@ MutationReporter reporter(target.get(), std::move(registered_observers)); // Report a few mutations. + const void* async_task_1; + const void* async_task_2; + EXPECT_CALL(*debugger_hooks(), AsyncTaskScheduled(_, "attributes", kOneshot)) + .WillOnce(SaveArg<0>(&async_task_1)); + EXPECT_CALL(*debugger_hooks(), + AsyncTaskScheduled(_, "characterData", kOneshot)) + .WillOnce(SaveArg<0>(&async_task_2)); reporter.ReportAttributesMutation("attribute_name", std::string("old_value")); reporter.ReportCharacterDataMutation("old_character_data"); ChildListMutationArguments args = CreateChildListMutationArguments(); @@ -281,6 +326,8 @@ // Check that mutation records for the mutation types we care about have // been queued. + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task_1)); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task_2)); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); ASSERT_EQ(2, records.size()); EXPECT_EQ(records.at(0)->type(), "attributes"); @@ -306,12 +353,19 @@ RegisteredObserver(target.get(), observer, init)); MutationReporter reporter(target.get(), std::move(registered_observers)); - // Report a few attribute mutations. + // Report a few attribute mutations, two of which will get through the filter. + const void* async_task_1; + const void* async_task_2; + EXPECT_CALL(*debugger_hooks(), AsyncTaskScheduled(_, "attributes", kOneshot)) + .WillOnce(SaveArg<0>(&async_task_1)) + .WillOnce(SaveArg<0>(&async_task_2)); reporter.ReportAttributesMutation("banana", std::string("rotten")); reporter.ReportAttributesMutation("apple", std::string("wormy")); reporter.ReportAttributesMutation("potato", std::string("mashed")); // Check that mutation records for the filtered attrbiutes have been queued. + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task_1)); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task_2)); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); ASSERT_EQ(2, records.size()); EXPECT_STREQ(records.at(0)->attribute_name()->c_str(), "banana"); @@ -415,6 +469,12 @@ MutationObserverInit options; options.set_subtree(true); options.set_child_list(true); + + const void* async_task_1; + const void* async_task_2; + EXPECT_CALL(*debugger_hooks(), AsyncTaskScheduled(_, "childList", kOneshot)) + .WillOnce(SaveArg<0>(&async_task_1)) + .WillOnce(SaveArg<0>(&async_task_2)); observer->Observe(root, options); scoped_refptr<Element> child1 = document()->CreateElement("div"); @@ -425,6 +485,8 @@ root->AppendChild(child1); child1->AppendChild(child2); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task_1)); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task_2)); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); ASSERT_EQ(2, records.size()); EXPECT_EQ("childList", records.at(0)->type()); @@ -458,10 +520,15 @@ MutationObserverInit options; options.set_subtree(true); options.set_child_list(true); + + const void* async_task; + EXPECT_CALL(*debugger_hooks(), AsyncTaskScheduled(_, "childList", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); observer->Observe(root, options); child1->RemoveChild(child2); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task)); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); ASSERT_EQ(1, records.size()); EXPECT_EQ("childList", records.at(0)->type()); @@ -481,10 +548,16 @@ MutationObserverInit options; options.set_subtree(true); options.set_character_data(true); + + const void* async_task; + EXPECT_CALL(*debugger_hooks(), + AsyncTaskScheduled(_, "characterData", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); observer->Observe(root, options); text->set_data("new-data"); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task)); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); ASSERT_EQ(1, records.size()); EXPECT_EQ("characterData", records.at(0)->type()); @@ -502,10 +575,16 @@ MutationObserverInit options; options.set_subtree(true); options.set_character_data_old_value(true); + + const void* async_task; + EXPECT_CALL(*debugger_hooks(), + AsyncTaskScheduled(_, "characterData", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); observer->Observe(root, options); text->set_data("new-data"); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task)); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); ASSERT_EQ(1, records.size()); EXPECT_EQ("characterData", records.at(0)->type()); @@ -525,11 +604,16 @@ MutationObserverInit options; options.set_attributes(true); options.set_attribute_filter(filter); + + const void* async_task; + EXPECT_CALL(*debugger_hooks(), AsyncTaskScheduled(_, "attributes", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); observer->Observe(root, options); root->SetAttribute("banana", "yellow"); root->SetAttribute("apple", "brown"); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task)); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); ASSERT_EQ(1, records.size()); EXPECT_EQ("attributes", records.at(0)->type()); @@ -546,10 +630,15 @@ scoped_refptr<MutationObserver> observer = CreateObserver(); MutationObserverInit options; options.set_attribute_old_value(true); + + const void* async_task; + EXPECT_CALL(*debugger_hooks(), AsyncTaskScheduled(_, "attributes", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); observer->Observe(root, options); root->SetAttribute("banana", "yellow"); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task)); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); ASSERT_EQ(1, records.size()); EXPECT_EQ("attributes", records.at(0)->type()); @@ -570,11 +659,17 @@ MutationObserverInit options; options.set_subtree(true); options.set_character_data(true); + + const void* async_task; + EXPECT_CALL(*debugger_hooks(), + AsyncTaskScheduled(_, "characterData", kOneshot)) + .WillOnce(SaveArg<0>(&async_task)); observer->Observe(root, options); // This should queue up a mutation record. text->set_data("new-data"); + EXPECT_CALL(*debugger_hooks(), AsyncTaskCanceled(async_task)); observer->Disconnect(); MutationObserver::MutationRecordSequence records = observer->TakeRecords(); // MutationObserver.disconnect() should clear any queued records.
diff --git a/src/cobalt/dom/navigator.cc b/src/cobalt/dom/navigator.cc index be7175b..f9507de 100644 --- a/src/cobalt/dom/navigator.cc +++ b/src/cobalt/dom/navigator.cc
@@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/navigator.h" +#include <memory> + #include "base/optional.h" #include "cobalt/dom/captions/system_caption_settings.h" #include "cobalt/dom/dom_exception.h" @@ -37,8 +37,8 @@ namespace dom { Navigator::Navigator( - const std::string& user_agent, const std::string& language, - scoped_refptr<MediaSession> media_session, + script::EnvironmentSettings* settings, const std::string& user_agent, + const std::string& language, scoped_refptr<MediaSession> media_session, scoped_refptr<cobalt::dom::captions::SystemCaptionSettings> captions, script::ScriptValueFactory* script_value_factory) : user_agent_(user_agent), @@ -46,7 +46,8 @@ mime_types_(new MimeTypeArray()), plugins_(new PluginArray()), media_session_(media_session), - media_devices_(new media_capture::MediaDevices(script_value_factory)), + media_devices_( + new media_capture::MediaDevices(settings, script_value_factory)), system_caption_settings_(captions), script_value_factory_(script_value_factory) {}
diff --git a/src/cobalt/dom/navigator.h b/src/cobalt/dom/navigator.h index 8bde10b..3a4e119 100644 --- a/src/cobalt/dom/navigator.h +++ b/src/cobalt/dom/navigator.h
@@ -38,7 +38,8 @@ class Navigator : public script::Wrappable { public: Navigator( - const std::string& user_agent, const std::string& language, + script::EnvironmentSettings* settings, const std::string& user_agent, + const std::string& language, scoped_refptr<cobalt::media_session::MediaSession> media_session, scoped_refptr<cobalt::dom::captions::SystemCaptionSettings> captions, script::ScriptValueFactory* script_value_factory); @@ -80,10 +81,6 @@ DEFINE_WRAPPABLE_TYPE(Navigator); void TraceMembers(script::Tracer* tracer) override; - void SetEnvironmentSettings(script::EnvironmentSettings* settings) { - media_devices_->SetEnvironmentSettings(settings); - } - private: ~Navigator() override {}
diff --git a/src/cobalt/dom/navigator_licenses_test.cc b/src/cobalt/dom/navigator_licenses_test.cc index ffdac52..d7f2172 100644 --- a/src/cobalt/dom/navigator_licenses_test.cc +++ b/src/cobalt/dom/navigator_licenses_test.cc
@@ -13,7 +13,7 @@ // limitations under the License. #include "cobalt/dom/navigator.h" - +#include "cobalt/dom/testing/stub_environment_settings.h" #include "testing/gtest/include/gtest/gtest.h" namespace cobalt { @@ -21,8 +21,10 @@ // Tests the Navigator::licenses function for non-empty return. TEST(NavigatorLicensesTest, NonEmpty) { - scoped_refptr<cobalt::dom::Navigator> navigator = new cobalt::dom::Navigator( - std::string(), std::string(), nullptr, nullptr, nullptr); + testing::StubEnvironmentSettings environment_settings; + scoped_refptr<cobalt::dom::Navigator> navigator = + new cobalt::dom::Navigator(&environment_settings, std::string(), + std::string(), nullptr, nullptr, nullptr); ASSERT_TRUE(navigator != nullptr); EXPECT_FALSE(navigator->licenses().empty());
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc index c7f01b7..e411663 100644 --- a/src/cobalt/dom/node.cc +++ b/src/cobalt/dom/node.cc
@@ -450,7 +450,11 @@ } Node::Node(Document* document) - : node_document_(base::AsWeakPtr(document)), + : Node(document->html_element_context(), document) {} + +Node::Node(HTMLElementContext* html_element_context, Document* document) + : EventTarget(html_element_context->environment_settings()), + node_document_(base::AsWeakPtr(document)), parent_(NULL), previous_sibling_(NULL), last_child_(NULL),
diff --git a/src/cobalt/dom/node.h b/src/cobalt/dom/node.h index 3f6cd23..921a31a 100644 --- a/src/cobalt/dom/node.h +++ b/src/cobalt/dom/node.h
@@ -37,6 +37,7 @@ class DocumentType; class Element; class HTMLCollection; +class HTMLElementContext; class NodeList; class Text; @@ -238,6 +239,12 @@ void TraceMembers(script::Tracer* tracer) override; protected: + // Constructor only for Document, since its html_element_context is not yet + // initialized. + Node(HTMLElementContext* html_element_context, Document* document); + + // Constructor for everything else since we can get html_element_context() + // from the document. explicit Node(Document* document); virtual ~Node();
diff --git a/src/cobalt/dom/node_list_live_test.cc b/src/cobalt/dom/node_list_live_test.cc index b13b8d9..6d23f82 100644 --- a/src/cobalt/dom/node_list_live_test.cc +++ b/src/cobalt/dom/node_list_live_test.cc
@@ -18,6 +18,7 @@ #include "cobalt/dom/dom_stat_tracker.h" #include "cobalt/dom/element.h" #include "cobalt/dom/html_element_context.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "testing/gtest/include/gtest/gtest.h" namespace cobalt { @@ -27,14 +28,15 @@ protected: NodeListLiveTest() : dom_stat_tracker_("NodeListLiveTest"), - html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - &dom_stat_tracker_, "", + html_element_context_(&environment_settings_, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, &dom_stat_tracker_, "", base::kApplicationStateStarted, NULL), document_(new Document(&html_element_context_)) {} ~NodeListLiveTest() override {} + testing::StubEnvironmentSettings environment_settings_; DomStatTracker dom_stat_tracker_; HTMLElementContext html_element_context_; scoped_refptr<Document> document_;
diff --git a/src/cobalt/dom/node_list_test.cc b/src/cobalt/dom/node_list_test.cc index e1a3bc4..4cd3d6f 100644 --- a/src/cobalt/dom/node_list_test.cc +++ b/src/cobalt/dom/node_list_test.cc
@@ -12,14 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/node_list.h" +#include <memory> + #include "cobalt/dom/document.h" #include "cobalt/dom/dom_stat_tracker.h" #include "cobalt/dom/element.h" #include "cobalt/dom/html_element_context.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "testing/gtest/include/gtest/gtest.h" namespace cobalt { @@ -29,14 +30,15 @@ protected: NodeListTest() : dom_stat_tracker_(new DomStatTracker("NodeListTest")), - html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - dom_stat_tracker_.get(), "", + html_element_context_(&environment_settings_, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, dom_stat_tracker_.get(), "", base::kApplicationStateStarted, NULL), document_(new Document(&html_element_context_)) {} ~NodeListTest() override {} + testing::StubEnvironmentSettings environment_settings_; std::unique_ptr<DomStatTracker> dom_stat_tracker_; HTMLElementContext html_element_context_; scoped_refptr<Document> document_;
diff --git a/src/cobalt/dom/on_screen_keyboard.cc b/src/cobalt/dom/on_screen_keyboard.cc index ffa725b..fde3fe7 100644 --- a/src/cobalt/dom/on_screen_keyboard.cc +++ b/src/cobalt/dom/on_screen_keyboard.cc
@@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/on_screen_keyboard.h" +#include <memory> + #include "base/callback.h" #include "base/compiler_specific.h" #include "cobalt/dom/event_target.h" @@ -25,9 +25,10 @@ namespace dom { OnScreenKeyboard::OnScreenKeyboard( - OnScreenKeyboardBridge* bridge, + script::EnvironmentSettings* settings, OnScreenKeyboardBridge* bridge, script::ScriptValueFactory* script_value_factory) - : bridge_(bridge), + : EventTarget(settings), + bridge_(bridge), script_value_factory_(script_value_factory), next_ticket_(0) { DCHECK(bridge_) << "OnScreenKeyboardBridge must not be NULL";
diff --git a/src/cobalt/dom/on_screen_keyboard.h b/src/cobalt/dom/on_screen_keyboard.h index 57a0487..bc781f9 100644 --- a/src/cobalt/dom/on_screen_keyboard.h +++ b/src/cobalt/dom/on_screen_keyboard.h
@@ -25,6 +25,7 @@ #include "cobalt/dom/event_target.h" #include "cobalt/dom/on_screen_keyboard_bridge.h" #include "cobalt/dom/window.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/promise.h" #include "cobalt/script/sequence.h" #include "cobalt/script/wrappable.h" @@ -43,7 +44,8 @@ typedef std::unordered_map<int, std::unique_ptr<VoidPromiseValue::Reference>> TicketToPromiseMap; - OnScreenKeyboard(OnScreenKeyboardBridge* bridge, + OnScreenKeyboard(script::EnvironmentSettings* settings, + OnScreenKeyboardBridge* bridge, script::ScriptValueFactory* script_value_factory); // Shows the on screen keyboard by calling a Starboard function.
diff --git a/src/cobalt/dom/on_screen_keyboard_test.cc b/src/cobalt/dom/on_screen_keyboard_test.cc index 59e4260..bd2b4ac 100644 --- a/src/cobalt/dom/on_screen_keyboard_test.cc +++ b/src/cobalt/dom/on_screen_keyboard_test.cc
@@ -19,12 +19,12 @@ #include "base/callback.h" #include "base/optional.h" #include "base/threading/platform_thread.h" -#include "cobalt/base/debugger_hooks.h" #include "cobalt/bindings/testing/utils.h" #include "cobalt/css_parser/parser.h" #include "cobalt/cssom/viewport_size.h" #include "cobalt/dom/local_storage_database.h" #include "cobalt/dom/testing/gtest_workarounds.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/window.h" #include "cobalt/dom_parser/parser.h" #include "cobalt/loader/fetcher_factory.h" @@ -193,7 +193,7 @@ class OnScreenKeyboardTest : public ::testing::Test { public: OnScreenKeyboardTest() - : environment_settings_(new script::EnvironmentSettings), + : environment_settings_(new testing::StubEnvironmentSettings), message_loop_(base::MessageLoop::TYPE_DEFAULT), css_parser_(css_parser::Parser::Create()), dom_parser_(new dom_parser::Parser(mock_error_callback_)), @@ -207,10 +207,11 @@ global_environment_(engine_->CreateGlobalEnvironment()), on_screen_keyboard_bridge_(new OnScreenKeyboardMockBridge()), window_(new Window( - ViewportSize(1920, 1080), 1.f, base::kApplicationStateStarted, - css_parser_.get(), dom_parser_.get(), fetcher_factory_.get(), - loader_factory_.get(), NULL, NULL, NULL, NULL, NULL, NULL, - &local_storage_database_, NULL, NULL, NULL, NULL, + environment_settings_.get(), ViewportSize(1920, 1080), 1.f, + base::kApplicationStateStarted, css_parser_.get(), + dom_parser_.get(), fetcher_factory_.get(), loader_factory_.get(), + NULL, NULL, NULL, NULL, NULL, NULL, &local_storage_database_, NULL, + NULL, NULL, NULL, global_environment_ ->script_value_factory() /* script_value_factory */, NULL, NULL, url_, "", "en-US", "en", @@ -226,7 +227,7 @@ dom::Window::OnStartDispatchEventCallback(), dom::Window::OnStopDispatchEventCallback(), dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), - NULL, null_debugger_hooks_)) { + NULL)) { global_environment_->CreateGlobalObject(window_, environment_settings_.get()); on_screen_keyboard_bridge_->window_ = window_; @@ -261,7 +262,7 @@ Window* window() const { return window_.get(); } private: - const std::unique_ptr<script::EnvironmentSettings> environment_settings_; + const std::unique_ptr<testing::StubEnvironmentSettings> environment_settings_; base::MessageLoop message_loop_; MockErrorCallback mock_error_callback_; std::unique_ptr<css_parser::Parser> css_parser_; @@ -274,7 +275,6 @@ std::unique_ptr<script::JavaScriptEngine> engine_; scoped_refptr<script::GlobalEnvironment> global_environment_; std::unique_ptr<OnScreenKeyboardMockBridge> on_screen_keyboard_bridge_; - base::NullDebuggerHooks null_debugger_hooks_; scoped_refptr<Window> window_; }; @@ -294,7 +294,8 @@ } // namespace -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) TEST_F(OnScreenKeyboardTest, ObjectExists) { std::string result; EXPECT_TRUE(EvaluateScript("window.onScreenKeyboard;", &result)); @@ -638,7 +639,7 @@ TEST_F(OnScreenKeyboardTest, BoundingRect) { std::string result; EXPECT_CALL(*(on_screen_keyboard_bridge()), BoundingRectMock()) - .WillOnce(testing::Return(nullptr)); + .WillOnce(::testing::Return(nullptr)); EXPECT_TRUE(EvaluateScript("window.onScreenKeyboard.boundingRect;", &result)); EXPECT_EQ("null", result); } @@ -663,7 +664,8 @@ )"; EXPECT_TRUE(EvaluateScript(script, NULL)); } -#else // SB_HAS(ON_SCREEN_KEYBOARD) +#else // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) TEST_F(OnScreenKeyboardTest, ObjectDoesntExist) { std::string result; @@ -692,7 +694,8 @@ EXPECT_TRUE(EvaluateScript(object_script, &result)); EXPECT_EQ("true", result); } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) } // namespace dom } // namespace cobalt
diff --git a/src/cobalt/dom/rule_matching_test.cc b/src/cobalt/dom/rule_matching_test.cc index 18531c3..75f1f51 100644 --- a/src/cobalt/dom/rule_matching_test.cc +++ b/src/cobalt/dom/rule_matching_test.cc
@@ -32,11 +32,12 @@ #include "cobalt/dom/node.h" #include "cobalt/dom/node_descendants_iterator.h" #include "cobalt/dom/node_list.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/testing/stub_window.h" #include "cobalt/dom_parser/parser.h" -#include "testing/gtest/include/gtest/gtest.h" #include "cobalt/script/script_exception.h" #include "cobalt/script/testing/mock_exception_state.h" +#include "testing/gtest/include/gtest/gtest.h" using cobalt::cssom::ViewportSize; @@ -52,9 +53,10 @@ : css_parser_(css_parser::Parser::Create()), dom_parser_(new dom_parser::Parser()), dom_stat_tracker_(new DomStatTracker("RuleMatchingTest")), - html_element_context_(NULL, NULL, css_parser_.get(), dom_parser_.get(), + html_element_context_(&environment_settings_, NULL, NULL, + css_parser_.get(), dom_parser_.get(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, dom_stat_tracker_.get(), "", + NULL, dom_stat_tracker_.get(), "", base::kApplicationStateStarted, NULL), document_(new Document(&html_element_context_)), root_(document_->CreateElement("html")->AsHTMLElement()), @@ -74,6 +76,7 @@ return document_->style_sheets()->Item(index)->AsCSSStyleSheet(); } + testing::StubEnvironmentSettings environment_settings_; std::unique_ptr<css_parser::Parser> css_parser_; std::unique_ptr<dom_parser::Parser> dom_parser_; std::unique_ptr<DomStatTracker> dom_stat_tracker_;
diff --git a/src/cobalt/dom/screenshot_manager.cc b/src/cobalt/dom/screenshot_manager.cc index f687626..b7aa043 100644 --- a/src/cobalt/dom/screenshot_manager.cc +++ b/src/cobalt/dom/screenshot_manager.cc
@@ -12,24 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom/screenshot_manager.h" +#include <memory> + #include "base/time/time.h" #include "cobalt/dom/screenshot.h" #include "cobalt/render_tree/node.h" -#include "cobalt/script/array_buffer.h" - #include "cobalt/render_tree/resource_provider_stub.h" +#include "cobalt/script/array_buffer.h" namespace cobalt { namespace dom { ScreenshotManager::ScreenshotManager( + script::EnvironmentSettings* settings, const ScreenshotManager::ProvideScreenshotFunctionCallback& screenshot_function_callback) - : screenshot_function_callback_(screenshot_function_callback) {} + : environment_settings_(settings), + screenshot_function_callback_(screenshot_function_callback) {} void ScreenshotManager::Screenshot( loader::image::EncodedStaticImage::ImageFormat desired_format, @@ -56,11 +57,6 @@ render_tree_root, /*clip_rect=*/base::nullopt, fill_screenshot); } -void ScreenshotManager::SetEnvironmentSettings( - script::EnvironmentSettings* settings) { - environment_settings_ = settings; -} - void ScreenshotManager::FillScreenshot( int64_t token, scoped_refptr<base::SingleThreadTaskRunner> expected_task_runner,
diff --git a/src/cobalt/dom/screenshot_manager.h b/src/cobalt/dom/screenshot_manager.h index f26269f..3a2d559 100644 --- a/src/cobalt/dom/screenshot_manager.h +++ b/src/cobalt/dom/screenshot_manager.h
@@ -49,14 +49,14 @@ const OnUnencodedImageCallback&)>; explicit ScreenshotManager( - const ProvideScreenshotFunctionCallback& screenshot_function_callback_); + script::EnvironmentSettings* settings, + const ProvideScreenshotFunctionCallback& screenshot_function_callback); void Screenshot( loader::image::EncodedStaticImage::ImageFormat desired_format, const scoped_refptr<render_tree::Node>& render_tree_root, std::unique_ptr<ScreenshotManager::InterfacePromiseValue::Reference> promise_reference); - void SetEnvironmentSettings(script::EnvironmentSettings* settings); private: void FillScreenshot(
diff --git a/src/cobalt/dom/serializer_test.cc b/src/cobalt/dom/serializer_test.cc index e7ac9f0..510d624 100644 --- a/src/cobalt/dom/serializer_test.cc +++ b/src/cobalt/dom/serializer_test.cc
@@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "cobalt/dom/serializer.h" + #include <memory> #include <sstream> #include <string> @@ -21,7 +23,7 @@ #include "cobalt/dom/document_type.h" #include "cobalt/dom/element.h" #include "cobalt/dom/html_element_context.h" -#include "cobalt/dom/serializer.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom_parser/parser.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,6 +35,7 @@ SerializerTest(); ~SerializerTest() override {} + testing::StubEnvironmentSettings environment_settings_; std::unique_ptr<dom_parser::Parser> dom_parser_; std::unique_ptr<DomStatTracker> dom_stat_tracker_; HTMLElementContext html_element_context_; @@ -45,9 +48,9 @@ SerializerTest::SerializerTest() : dom_parser_(new dom_parser::Parser()), dom_stat_tracker_(new DomStatTracker("SerializerTest")), - html_element_context_(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - dom_stat_tracker_.get(), "", + html_element_context_(&environment_settings_, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, dom_stat_tracker_.get(), "", base::kApplicationStateStarted, NULL), document_(new Document(&html_element_context_)), root_(new Element(document_, base::Token("root"))),
diff --git a/src/cobalt/dom/source_buffer.cc b/src/cobalt/dom/source_buffer.cc index b879fc4..08ea6e4 100644 --- a/src/cobalt/dom/source_buffer.cc +++ b/src/cobalt/dom/source_buffer.cc
@@ -86,10 +86,12 @@ } // namespace -SourceBuffer::SourceBuffer(const std::string& id, MediaSource* media_source, +SourceBuffer::SourceBuffer(script::EnvironmentSettings* settings, + const std::string& id, MediaSource* media_source, media::ChunkDemuxer* chunk_demuxer, EventQueue* event_queue) - : id_(id), + : EventTarget(settings), + id_(id), chunk_demuxer_(chunk_demuxer), media_source_(media_source), track_defaults_(new TrackDefaultList(NULL)), @@ -97,8 +99,10 @@ mode_(kSourceBufferAppendModeSegments), updating_(false), timestamp_offset_(0), - audio_tracks_(new AudioTrackList(media_source->GetMediaElement())), - video_tracks_(new VideoTrackList(media_source->GetMediaElement())), + audio_tracks_( + new AudioTrackList(settings, media_source->GetMediaElement())), + video_tracks_( + new VideoTrackList(settings, media_source->GetMediaElement())), append_window_start_(0), append_window_end_(std::numeric_limits<double>::infinity()), first_initialization_segment_received_(false),
diff --git a/src/cobalt/dom/source_buffer.h b/src/cobalt/dom/source_buffer.h index 8c8b904..efdd34b 100644 --- a/src/cobalt/dom/source_buffer.h +++ b/src/cobalt/dom/source_buffer.h
@@ -65,6 +65,7 @@ #include "cobalt/media/filters/chunk_demuxer.h" #include "cobalt/script/array_buffer.h" #include "cobalt/script/array_buffer_view.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/exception_state.h" namespace cobalt { @@ -79,8 +80,9 @@ public: // Custom, not in any spec. // - SourceBuffer(const std::string& id, MediaSource* media_source, - media::ChunkDemuxer* chunk_demuxer, EventQueue* event_queue); + SourceBuffer(script::EnvironmentSettings* settings, const std::string& id, + MediaSource* media_source, media::ChunkDemuxer* chunk_demuxer, + EventQueue* event_queue); // Web API: SourceBuffer //
diff --git a/src/cobalt/dom/source_buffer_list.cc b/src/cobalt/dom/source_buffer_list.cc index 5417fa9..2431228 100644 --- a/src/cobalt/dom/source_buffer_list.cc +++ b/src/cobalt/dom/source_buffer_list.cc
@@ -60,8 +60,9 @@ const int kSizeOfSourceBufferToReserveInitially = 2; } // namespace -SourceBufferList::SourceBufferList(EventQueue* event_queue) - : event_queue_(event_queue) { +SourceBufferList::SourceBufferList(script::EnvironmentSettings* settings, + EventQueue* event_queue) + : EventTarget(settings), event_queue_(event_queue) { DCHECK(event_queue_); source_buffers_.reserve(kSizeOfSourceBufferToReserveInitially); }
diff --git a/src/cobalt/dom/source_buffer_list.h b/src/cobalt/dom/source_buffer_list.h index cbd4092..4e1da23 100644 --- a/src/cobalt/dom/source_buffer_list.h +++ b/src/cobalt/dom/source_buffer_list.h
@@ -52,6 +52,7 @@ #include "cobalt/dom/event_queue.h" #include "cobalt/dom/event_target.h" #include "cobalt/dom/source_buffer.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/wrappable.h" namespace cobalt { @@ -65,7 +66,8 @@ public: // Custom, not in any spec. // - explicit SourceBufferList(EventQueue* event_queue); + SourceBufferList(script::EnvironmentSettings* settings, + EventQueue* event_queue); ~SourceBufferList() override; // Web API: SourceBuffer
diff --git a/src/cobalt/dom/testing/dom_testing.gyp b/src/cobalt/dom/testing/dom_testing.gyp index 2f4ccd2..dfb0175 100644 --- a/src/cobalt/dom/testing/dom_testing.gyp +++ b/src/cobalt/dom/testing/dom_testing.gyp
@@ -26,6 +26,7 @@ 'mock_event_listener.h', 'stub_css_parser.cc', 'stub_css_parser.h', + 'stub_environment_settings.h', 'stub_script_runner.cc', 'stub_script_runner.h', 'stub_window.h',
diff --git a/src/cobalt/dom/testing/stub_environment_settings.h b/src/cobalt/dom/testing/stub_environment_settings.h new file mode 100644 index 0000000..81e11f7 --- /dev/null +++ b/src/cobalt/dom/testing/stub_environment_settings.h
@@ -0,0 +1,40 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COBALT_DOM_TESTING_STUB_ENVIRONMENT_SETTINGS_H_ +#define COBALT_DOM_TESTING_STUB_ENVIRONMENT_SETTINGS_H_ + +#include "cobalt/base/debugger_hooks.h" +#include "cobalt/dom/dom_settings.h" + +namespace cobalt { +namespace dom { +namespace testing { + +class StubEnvironmentSettings : public DOMSettings { + public: + explicit StubEnvironmentSettings(const Options& options = Options()) + : DOMSettings(0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, &null_debugger_hooks_, nullptr, options) {} + ~StubEnvironmentSettings() override {} + + private: + base::NullDebuggerHooks null_debugger_hooks_; +}; + +} // namespace testing +} // namespace dom +} // namespace cobalt + +#endif // COBALT_DOM_TESTING_STUB_ENVIRONMENT_SETTINGS_H_
diff --git a/src/cobalt/dom/testing/stub_window.h b/src/cobalt/dom/testing/stub_window.h index 4e4964a..c059eab 100644 --- a/src/cobalt/dom/testing/stub_window.h +++ b/src/cobalt/dom/testing/stub_window.h
@@ -61,11 +61,17 @@ dom_stat_tracker_(new dom::DomStatTracker("StubWindow")) { engine_ = script::JavaScriptEngine::CreateEngine(); global_environment_ = engine_->CreateGlobalEnvironment(); + environment_settings_ = + environment_settings.get() + ? std::move(environment_settings) + : std::unique_ptr<script::EnvironmentSettings>(new DOMSettings( + 0, NULL, NULL, NULL, NULL, NULL, engine_.get(), + global_environment(), &null_debugger_hooks_, NULL)); window_ = new dom::Window( - cssom::ViewportSize(1920, 1080), 1.f, base::kApplicationStateStarted, - css_parser_.get(), dom_parser_.get(), fetcher_factory_.get(), - loader_factory_.get(), NULL, NULL, NULL, NULL, NULL, NULL, - &local_storage_database_, NULL, NULL, NULL, NULL, + environment_settings_.get(), cssom::ViewportSize(1920, 1080), 1.f, + base::kApplicationStateStarted, css_parser_.get(), dom_parser_.get(), + fetcher_factory_.get(), loader_factory_.get(), NULL, NULL, NULL, NULL, + NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, global_environment_->script_value_factory(), NULL, dom_stat_tracker_.get(), url_, "", "en-US", "en", base::Callback<void(const GURL&)>(), @@ -77,15 +83,9 @@ base::Closure() /* window_minimize */, NULL, NULL, NULL, dom::Window::OnStartDispatchEventCallback(), dom::Window::OnStopDispatchEventCallback(), - dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), NULL, - null_debugger_hooks_); - environment_settings_ = - environment_settings.get() - ? std::move(environment_settings) - : std::unique_ptr<script::EnvironmentSettings>( - new DOMSettings(0, NULL, NULL, window_, NULL, NULL, NULL, - engine_.get(), global_environment(), NULL)); - window_->SetEnvironmentSettings(environment_settings_.get()); + dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), NULL); + base::polymorphic_downcast<dom::DOMSettings*>(environment_settings_.get()) + ->set_window(window_); global_environment_->CreateGlobalObject(window_, environment_settings_.get()); }
diff --git a/src/cobalt/dom/track_list_base.h b/src/cobalt/dom/track_list_base.h index 02ae484..37c83b1 100644 --- a/src/cobalt/dom/track_list_base.h +++ b/src/cobalt/dom/track_list_base.h
@@ -26,6 +26,7 @@ #include "cobalt/dom/event_target.h" #include "cobalt/dom/html_media_element.h" #include "cobalt/dom/track_event.h" +#include "cobalt/script/environment_settings.h" namespace cobalt { namespace dom { @@ -34,7 +35,9 @@ template <typename TrackType> class TrackListBase : public EventTarget { public: - explicit TrackListBase(HTMLMediaElement* media_element) { + TrackListBase(script::EnvironmentSettings* settings, + HTMLMediaElement* media_element) + : EventTarget(settings) { DCHECK(media_element); media_element_ = base::AsWeakPtr(media_element); }
diff --git a/src/cobalt/dom/video_track_list.h b/src/cobalt/dom/video_track_list.h index 38c80c0..2cdbcba 100644 --- a/src/cobalt/dom/video_track_list.h +++ b/src/cobalt/dom/video_track_list.h
@@ -21,6 +21,7 @@ #include "cobalt/dom/html_media_element.h" #include "cobalt/dom/track_list_base.h" #include "cobalt/dom/video_track.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/wrappable.h" namespace cobalt { @@ -32,8 +33,9 @@ public: // Custom, not in any spec. // - explicit VideoTrackList(HTMLMediaElement* media_element) - : TrackListBase<VideoTrack>(media_element) {} + VideoTrackList(script::EnvironmentSettings* settings, + HTMLMediaElement* media_element) + : TrackListBase<VideoTrack>(settings, media_element) {} // Web API: VideoTrackList //
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc index d11d43d..62edced 100644 --- a/src/cobalt/dom/window.cc +++ b/src/cobalt/dom/window.cc
@@ -91,8 +91,8 @@ } // namespace Window::Window( - const ViewportSize& view_size, float device_pixel_ratio, - base::ApplicationState initial_application_state, + script::EnvironmentSettings* settings, const ViewportSize& view_size, + float device_pixel_ratio, base::ApplicationState initial_application_state, cssom::CSSParser* css_parser, Parser* dom_parser, loader::FetcherFactory* fetcher_factory, loader::LoaderFactory* loader_factory, @@ -130,7 +130,6 @@ const ScreenshotManager::ProvideScreenshotFunctionCallback& screenshot_function_callback, base::WaitableEvent* synchronous_loader_interrupt, - const base::DebuggerHooks& debugger_hooks, const scoped_refptr<ui_navigation::NavItem>& ui_nav_root, int csp_insecure_allowed_token, int dom_max_element_depth, float video_playback_rate_multiplier, ClockType clock_type, @@ -139,7 +138,7 @@ bool log_tts) // 'window' object EventTargets require special handling for onerror events, // see EventTarget constructor for more details. - : EventTarget(kUnpackOnErrorEvents), + : EventTarget(settings, kUnpackOnErrorEvents), viewport_size_(view_size), device_pixel_ratio_(device_pixel_ratio), is_resize_event_pending_(false), @@ -148,7 +147,7 @@ test_runner_(new TestRunner()), #endif // ENABLE_TEST_RUNNER html_element_context_(new HTMLElementContext( - fetcher_factory, loader_factory, css_parser, dom_parser, + settings, fetcher_factory, loader_factory, css_parser, dom_parser, can_play_type_handler, web_media_player_factory, script_runner, script_value_factory, media_source_registry, resource_provider, animated_image_tracker, image_cache, @@ -169,17 +168,18 @@ csp_insecure_allowed_token, dom_max_element_depth)))), document_loader_(nullptr), history_(new History()), - navigator_(new Navigator(user_agent, language, media_session, captions, - script_value_factory)), + navigator_(new Navigator(settings, user_agent, language, media_session, + captions, script_value_factory)), ALLOW_THIS_IN_INITIALIZER_LIST( relay_on_load_event_(new RelayLoadEvent(this))), console_(new Console(execution_state)), ALLOW_THIS_IN_INITIALIZER_LIST( - window_timers_(new WindowTimers(this, debugger_hooks))), + window_timers_(new WindowTimers(this, debugger_hooks()))), ALLOW_THIS_IN_INITIALIZER_LIST(animation_frame_request_callback_list_( - new AnimationFrameRequestCallbackList(this))), + new AnimationFrameRequestCallbackList(this, debugger_hooks()))), crypto_(new Crypto()), - speech_synthesis_(new speech::SpeechSynthesis(navigator_, log_tts)), + speech_synthesis_( + new speech::SpeechSynthesis(settings, navigator_, log_tts)), ALLOW_THIS_IN_INITIALIZER_LIST(local_storage_( new Storage(this, Storage::kLocalStorage, local_storage_database))), ALLOW_THIS_IN_INITIALIZER_LIST( @@ -193,13 +193,14 @@ // We only have an on_screen_keyboard_bridge when the platform supports // it. Otherwise don't even expose it in the DOM. on_screen_keyboard_(on_screen_keyboard_bridge - ? new OnScreenKeyboard(on_screen_keyboard_bridge, + ? new OnScreenKeyboard(settings, + on_screen_keyboard_bridge, script_value_factory) : NULL), splash_screen_cache_callback_(splash_screen_cache_callback), on_start_dispatch_event_callback_(on_start_dispatch_event_callback), on_stop_dispatch_event_callback_(on_stop_dispatch_event_callback), - screenshot_manager_(screenshot_function_callback), + screenshot_manager_(settings, screenshot_function_callback), ui_nav_root_(ui_nav_root) { #if !defined(ENABLE_TEST_RUNNER) SB_UNREFERENCED_PARAMETER(clock_type); @@ -501,7 +502,7 @@ // Then setup the Window's frame request callback list with a freshly // created and empty one. animation_frame_request_callback_list_.reset( - new AnimationFrameRequestCallbackList(this)); + new AnimationFrameRequestCallbackList(this, debugger_hooks())); // Now, iterate through each of the callbacks and call them. frame_request_list->RunCallbacks(*document_->timeline()->current_time()); @@ -701,11 +702,6 @@ tracer->Trace(on_screen_keyboard_); } -void Window::SetEnvironmentSettings(script::EnvironmentSettings* settings) { - screenshot_manager_.SetEnvironmentSettings(settings); - navigator_->SetEnvironmentSettings(settings); -} - void Window::CacheSplashScreen(const std::string& content) { if (splash_screen_cache_callback_.is_null()) { return;
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h index a824e37..27fa7a9 100644 --- a/src/cobalt/dom/window.h +++ b/src/cobalt/dom/window.h
@@ -27,7 +27,6 @@ #include "base/timer/timer.h" #include "cobalt/base/application_state.h" #include "cobalt/base/clock.h" -#include "cobalt/base/debugger_hooks.h" #include "cobalt/cssom/css_parser.h" #include "cobalt/cssom/css_style_declaration.h" #include "cobalt/cssom/viewport_size.h" @@ -132,6 +131,7 @@ }; Window( + script::EnvironmentSettings* settings, const cssom::ViewportSize& view_size, float device_pixel_ratio, base::ApplicationState initial_application_state, cssom::CSSParser* css_parser, Parser* dom_parser, @@ -173,7 +173,6 @@ const ScreenshotManager::ProvideScreenshotFunctionCallback& screenshot_function_callback, base::WaitableEvent* synchronous_loader_interrupt, - const base::DebuggerHooks& debugger_hooks, const scoped_refptr<ui_navigation::NavItem>& ui_nav_root = nullptr, int csp_insecure_allowed_token = 0, int dom_max_element_depth = 0, float video_playback_rate_multiplier = 1.f, @@ -398,8 +397,6 @@ void TraceMembers(script::Tracer* tracer) override; - void SetEnvironmentSettings(script::EnvironmentSettings* settings); - const scoped_refptr<ui_navigation::NavItem>& GetUiNavRoot() const { return ui_nav_root_; }
diff --git a/src/cobalt/dom/window_test.cc b/src/cobalt/dom/window_test.cc index 80bc5c6..9a44ac4 100644 --- a/src/cobalt/dom/window_test.cc +++ b/src/cobalt/dom/window_test.cc
@@ -26,6 +26,7 @@ #include "cobalt/cssom/viewport_size.h" #include "cobalt/dom/local_storage_database.h" #include "cobalt/dom/screen.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom_parser/parser.h" #include "cobalt/loader/fetcher_factory.h" #include "cobalt/media_session/media_session.h" @@ -50,7 +51,8 @@ class WindowTest : public ::testing::Test { protected: WindowTest() - : message_loop_(base::MessageLoop::TYPE_DEFAULT), + : environment_settings_(new testing::StubEnvironmentSettings), + message_loop_(base::MessageLoop::TYPE_DEFAULT), css_parser_(css_parser::Parser::Create()), dom_parser_(new dom_parser::Parser(mock_error_callback_)), fetcher_factory_(new loader::FetcherFactory(NULL)), @@ -61,9 +63,10 @@ ViewportSize view_size(1920, 1080); window_ = new Window( - view_size, 1.f, base::kApplicationStateStarted, css_parser_.get(), - dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL, NULL, - NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, + environment_settings_.get(), view_size, 1.f, + base::kApplicationStateStarted, css_parser_.get(), dom_parser_.get(), + fetcher_factory_.get(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &local_storage_database_, NULL, NULL, NULL, NULL, global_environment_->script_value_factory(), NULL, NULL, url_, "", "en-US", "en", base::Callback<void(const GURL &)>(), base::Bind(&MockErrorCallback::Run, @@ -75,12 +78,12 @@ base::Closure() /* window_minimize */, NULL, NULL, NULL, dom::Window::OnStartDispatchEventCallback(), dom::Window::OnStopDispatchEventCallback(), - dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), NULL, - null_debugger_hooks_); + dom::ScreenshotManager::ProvideScreenshotFunctionCallback(), NULL); } ~WindowTest() override {} + const std::unique_ptr<testing::StubEnvironmentSettings> environment_settings_; base::MessageLoop message_loop_; MockErrorCallback mock_error_callback_; std::unique_ptr<css_parser::Parser> css_parser_; @@ -90,7 +93,6 @@ std::unique_ptr<script::JavaScriptEngine> engine_; scoped_refptr<script::GlobalEnvironment> global_environment_; GURL url_; - base::NullDebuggerHooks null_debugger_hooks_; scoped_refptr<Window> window_; };
diff --git a/src/cobalt/dom/window_timers.cc b/src/cobalt/dom/window_timers.cc index dd88196..be3bc87 100644 --- a/src/cobalt/dom/window_timers.cc +++ b/src/cobalt/dom/window_timers.cc
@@ -43,7 +43,9 @@ base::Unretained(this), handle)); timers_[handle] = new TimerInfo( owner_, std::unique_ptr<base::internal::TimerBase>(timer), handler); - debugger_hooks_.AsyncTaskScheduled(timers_[handle], "SetTimeout"); + debugger_hooks_->AsyncTaskScheduled( + timers_[handle], "SetTimeout", + base::DebuggerHooks::AsyncTaskFrequency::kOneshot); } else { timers_[handle] = nullptr; } @@ -69,7 +71,9 @@ base::Unretained(this), handle)); timers_[handle] = new TimerInfo( owner_, std::unique_ptr<base::internal::TimerBase>(timer), handler); - debugger_hooks_.AsyncTaskScheduled(timers_[handle], "SetInterval"); + debugger_hooks_->AsyncTaskScheduled( + timers_[handle], "SetInterval", + base::DebuggerHooks::AsyncTaskFrequency::kRecurring); } else { timers_[handle] = nullptr; } @@ -80,14 +84,14 @@ void WindowTimers::ClearInterval(int handle) { Timers::iterator timer = timers_.find(handle); if (timer != timers_.end()) { - debugger_hooks_.AsyncTaskCanceled(timer->second); + debugger_hooks_->AsyncTaskCanceled(timer->second); timers_.erase(timer); } } void WindowTimers::ClearAllIntervalsAndTimeouts() { for (auto& timer_entry : timers_) { - debugger_hooks_.AsyncTaskCanceled(timer_entry.second); + debugger_hooks_->AsyncTaskCanceled(timer_entry.second); } timers_.clear(); } @@ -96,7 +100,7 @@ callbacks_active_ = false; // Immediately cancel any pending timers. for (auto& timer_entry : timers_) { - debugger_hooks_.AsyncTaskCanceled(timer_entry.second); + debugger_hooks_->AsyncTaskCanceled(timer_entry.second); timer_entry.second = nullptr; } } @@ -145,7 +149,7 @@ // If the timer is not deleted and is not running, it means it is an oneshot // timer and has just fired the shot, and it should be deleted now. if (timer != timers_.end() && !timer->second->timer()->IsRunning()) { - debugger_hooks_.AsyncTaskCanceled(timer->second); + debugger_hooks_->AsyncTaskCanceled(timer->second); timers_.erase(timer); }
diff --git a/src/cobalt/dom/window_timers.h b/src/cobalt/dom/window_timers.h index 73bec1f..f17f0d8 100644 --- a/src/cobalt/dom/window_timers.h +++ b/src/cobalt/dom/window_timers.h
@@ -33,10 +33,12 @@ typedef script::CallbackFunction<void()> TimerCallback; typedef script::ScriptValue<TimerCallback> TimerCallbackArg; explicit WindowTimers(script::Wrappable* const owner, - const base::DebuggerHooks& debugger_hooks) + base::DebuggerHooks* debugger_hooks) : current_timer_index_(0), owner_(owner), - debugger_hooks_(debugger_hooks) {} + debugger_hooks_(debugger_hooks) { + DCHECK(debugger_hooks_); + } ~WindowTimers() {} int SetTimeout(const TimerCallbackArg& handler, int timeout); @@ -86,7 +88,7 @@ Timers timers_; int current_timer_index_; script::Wrappable* const owner_; - const base::DebuggerHooks& debugger_hooks_; + base::DebuggerHooks* debugger_hooks_; // Set to false when we're about to shutdown, to ensure that no new JavaScript // is fired as we are waiting for it to drain.
diff --git a/src/cobalt/dom_parser/html_decoder_test.cc b/src/cobalt/dom_parser/html_decoder_test.cc index 80cfb29..646a077 100644 --- a/src/cobalt/dom_parser/html_decoder_test.cc +++ b/src/cobalt/dom_parser/html_decoder_test.cc
@@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/dom_parser/html_decoder.h" +#include <memory> + #include "base/callback.h" #include "base/message_loop/message_loop.h" #include "base/optional.h" @@ -28,6 +28,7 @@ #include "cobalt/dom/html_element_context.h" #include "cobalt/dom/named_node_map.h" #include "cobalt/dom/testing/stub_css_parser.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/testing/stub_script_runner.h" #include "cobalt/dom/text.h" #include "cobalt/dom_parser/parser.h" @@ -52,6 +53,7 @@ HTMLDecoderTest(); ~HTMLDecoderTest() override {} + dom::testing::StubEnvironmentSettings environment_settings_; loader::FetcherFactory fetcher_factory_; loader::LoaderFactory loader_factory_; std::unique_ptr<Parser> dom_parser_; @@ -75,12 +77,12 @@ dom_parser_(new Parser()), dom_stat_tracker_(new dom::DomStatTracker("HTMLDecoderTest")), html_element_context_( - &fetcher_factory_, &loader_factory_, &stub_css_parser_, - dom_parser_.get(), NULL /* can_play_type_handler */, - NULL /* web_media_player_factory */, &stub_script_runner_, - NULL /* script_value_factory */, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, dom_stat_tracker_.get(), "", base::kApplicationStateStarted, - NULL), + &environment_settings_, &fetcher_factory_, &loader_factory_, + &stub_css_parser_, dom_parser_.get(), + NULL /* can_play_type_handler */, NULL /* web_media_player_factory */, + &stub_script_runner_, NULL /* script_value_factory */, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, dom_stat_tracker_.get(), "", + base::kApplicationStateStarted, NULL), document_(new dom::Document(&html_element_context_)), root_(new dom::Element(document_, base::Token("element"))), source_location_(base::SourceLocation("[object HTMLDecoderTest]", 1, 1)) {
diff --git a/src/cobalt/extension/graphics.h b/src/cobalt/extension/graphics.h index 1baa343..b68ac9f 100644 --- a/src/cobalt/extension/graphics.h +++ b/src/cobalt/extension/graphics.h
@@ -44,6 +44,9 @@ // is executed a little too early. Return a negative number if frames should // only be presented when something changes (i.e. there is no maximum frame // interval). + // NOTE: The gyp variable 'cobalt_minimum_frame_time_in_milliseconds' takes + // precedence over this. For example, if the minimum frame time is 8ms and + // the maximum frame interval is 0ms, then the renderer will target 125 fps. float (*GetMaximumFrameIntervalInMilliseconds)(); } CobaltExtensionGraphicsApi;
diff --git a/src/cobalt/input/input_device_manager.h b/src/cobalt/input/input_device_manager.h index 94a1f72..5045901 100644 --- a/src/cobalt/input/input_device_manager.h +++ b/src/cobalt/input/input_device_manager.h
@@ -40,10 +40,12 @@ typedef base::Callback<void(base::Token type, const dom::WheelEventInit&)> WheelEventCallback; -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) typedef base::Callback<void(base::Token type, const dom::InputEventInit&)> InputEventCallback; -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) // InputDeviceManager listens to events from platform-specific input devices // and maps them to platform-independent keyboard key events. @@ -55,9 +57,11 @@ const KeyboardEventCallback& keyboard_event_callback, const PointerEventCallback& pointer_event_callback, const WheelEventCallback& wheel_event_callback, -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) const InputEventCallback& input_event_callback, -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) system_window::SystemWindow* system_window); virtual ~InputDeviceManager() {}
diff --git a/src/cobalt/input/input_device_manager_desktop.cc b/src/cobalt/input/input_device_manager_desktop.cc index 9c2e9e7..85ccbb1 100644 --- a/src/cobalt/input/input_device_manager_desktop.cc +++ b/src/cobalt/input/input_device_manager_desktop.cc
@@ -52,17 +52,21 @@ const KeyboardEventCallback& keyboard_event_callback, const PointerEventCallback& pointer_event_callback, const WheelEventCallback& wheel_event_callback, -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) const InputEventCallback& input_event_callback, -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) system_window::SystemWindow* system_window) : system_window_(system_window), system_window_input_event_callback_( base::Bind(&InputDeviceManagerDesktop::HandleSystemWindowInputEvent, base::Unretained(this))), -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) input_event_callback_(input_event_callback), -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) keypress_generator_filter_(keyboard_event_callback), pointer_event_callback_(pointer_event_callback), wheel_event_callback_(wheel_event_callback) { @@ -297,7 +301,8 @@ wheel_event_callback_.Run(type, wheel_event); } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void InputDeviceManagerDesktop::HandleInputEvent( const system_window::InputEvent* event) { // Note: we currently treat all dom::InputEvents as input (never beforeinput). @@ -309,7 +314,8 @@ input_event.set_is_composing(event->is_composing()); input_event_callback_.Run(type, input_event); } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) void InputDeviceManagerDesktop::HandleSystemWindowInputEvent( const base::Event* event) { @@ -369,10 +375,12 @@ HandleWheelEvent(input_event); break; case system_window::InputEvent::kInput: -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) HandleInputEvent(input_event); break; -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) case system_window::InputEvent::kKeyMove: break; }
diff --git a/src/cobalt/input/input_device_manager_desktop.h b/src/cobalt/input/input_device_manager_desktop.h index d52ac4a..c72ec67 100644 --- a/src/cobalt/input/input_device_manager_desktop.h +++ b/src/cobalt/input/input_device_manager_desktop.h
@@ -28,9 +28,11 @@ const KeyboardEventCallback& keyboard_event_callback, const PointerEventCallback& pointer_event_callback, const WheelEventCallback& wheel_event_callback, -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) const InputEventCallback& input_event_callback, -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) system_window::SystemWindow* system_window); ~InputDeviceManagerDesktop() override; @@ -44,9 +46,11 @@ void HandleKeyboardEvent(bool is_key_down, const system_window::InputEvent* input_event, int key_code); -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void HandleInputEvent(const system_window::InputEvent* event); -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) void HandlePointerEvent(base::Token type, const system_window::InputEvent* input_event); @@ -61,10 +65,12 @@ // object is destroyed. base::EventCallback system_window_input_event_callback_; -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // Called to handle an input_event. InputEventCallback input_event_callback_; -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) // Keyboard event filters to process the events generated. KeypressGeneratorFilter keypress_generator_filter_;
diff --git a/src/cobalt/input/input_device_manager_starboard.cc b/src/cobalt/input/input_device_manager_starboard.cc index cbc9c47..5827d99 100644 --- a/src/cobalt/input/input_device_manager_starboard.cc +++ b/src/cobalt/input/input_device_manager_starboard.cc
@@ -24,15 +24,19 @@ const KeyboardEventCallback& keyboard_event_callback, const PointerEventCallback& pointer_event_callback, const WheelEventCallback& wheel_event_callback, -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) const InputEventCallback& input_event_callback, -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) system_window::SystemWindow* system_window) { return std::unique_ptr<InputDeviceManager>(new InputDeviceManagerDesktop( keyboard_event_callback, pointer_event_callback, wheel_event_callback, -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) input_event_callback, -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) system_window)); }
diff --git a/src/cobalt/layout/anonymous_block_box.cc b/src/cobalt/layout/anonymous_block_box.cc index 55dd91e..709eda9 100644 --- a/src/cobalt/layout/anonymous_block_box.cc +++ b/src/cobalt/layout/anonymous_block_box.cc
@@ -40,6 +40,19 @@ css_computed_style_declaration->data()->font_weight())) {} Box::Level AnonymousBlockBox::GetLevel() const { return kBlockLevel; } +Box::MarginCollapsingStatus AnonymousBlockBox::GetMarginCollapsingStatus() + const { + // If all enclosed boxes are absolutely-positioned, ignore it for + // margin-collapse. + if (std::all_of(child_boxes().begin(), child_boxes().end(), + [](Box* b) { return b->IsAbsolutelyPositioned(); })) { + return kIgnore; + } + + // If any enclosed block is inline-level, break collapsing model for + // parent/siblings. + return kSeparateAdjoiningMargins; +} AnonymousBlockBox* AnonymousBlockBox::AsAnonymousBlockBox() { return this; } const AnonymousBlockBox* AnonymousBlockBox::AsAnonymousBlockBox() const {
diff --git a/src/cobalt/layout/anonymous_block_box.h b/src/cobalt/layout/anonymous_block_box.h index c6787cd..a5a6b69 100644 --- a/src/cobalt/layout/anonymous_block_box.h +++ b/src/cobalt/layout/anonymous_block_box.h
@@ -40,6 +40,7 @@ // From |Box|. Level GetLevel() const override; + MarginCollapsingStatus GetMarginCollapsingStatus() const override; AnonymousBlockBox* AsAnonymousBlockBox() override; const AnonymousBlockBox* AsAnonymousBlockBox() const override;
diff --git a/src/cobalt/layout/block_container_box.cc b/src/cobalt/layout/block_container_box.cc index 006baff..b5f1fbf 100644 --- a/src/cobalt/layout/block_container_box.cc +++ b/src/cobalt/layout/block_container_box.cc
@@ -118,6 +118,10 @@ child_layout_params.containing_block_size.set_height(LayoutUnit()); } } + child_layout_params.maybe_margin_top = maybe_margin_top; + child_layout_params.maybe_margin_bottom = maybe_margin_bottom; + child_layout_params.maybe_height = maybe_height; + std::unique_ptr<FormattingContext> formatting_context = UpdateRectOfInFlowChildBoxes(child_layout_params); @@ -676,9 +680,20 @@ const base::Optional<LayoutUnit>& maybe_margin_top, const base::Optional<LayoutUnit>& maybe_margin_bottom, const FormattingContext& formatting_context) { - // If "margin-top", or "margin-bottom" are "auto", their used value is 0. - set_margin_top(maybe_margin_top.value_or(LayoutUnit())); - set_margin_bottom(maybe_margin_bottom.value_or(LayoutUnit())); + if (collapsed_empty_margin_) { + // If empty box has a collapsed margin, only set top margin. + // https://www.w3.org/TR/CSS22/box.html#collapsing-margins + set_margin_top(collapsed_empty_margin_.value()); + set_margin_bottom(LayoutUnit()); + } else { + // If "margin-top", or "margin-bottom" are "auto", their used value is 0. + LayoutUnit margin_top = + collapsed_margin_top_.value_or(maybe_margin_top.value_or(LayoutUnit())); + LayoutUnit margin_bottom = collapsed_margin_bottom_.value_or( + maybe_margin_bottom.value_or(LayoutUnit())); + set_margin_top(margin_top); + set_margin_bottom(margin_bottom); + } // If "height" is "auto", the used value is the distance from box's top // content edge to the first applicable of the following:
diff --git a/src/cobalt/layout/block_formatting_block_container_box.cc b/src/cobalt/layout/block_formatting_block_container_box.cc index e85367d..a05e390 100644 --- a/src/cobalt/layout/block_formatting_block_container_box.cc +++ b/src/cobalt/layout/block_formatting_block_container_box.cc
@@ -18,6 +18,7 @@ #include <memory> #include "cobalt/cssom/computed_style.h" +#include "cobalt/cssom/computed_style_utils.h" #include "cobalt/cssom/keyword_value.h" #include "cobalt/layout/anonymous_block_box.h" #include "cobalt/layout/block_formatting_context.h" @@ -62,19 +63,33 @@ std::unique_ptr<FormattingContext> BlockFormattingBlockContainerBox::UpdateRectOfInFlowChildBoxes( const LayoutParams& child_layout_params) { + // Only collapse in-flow, block-level boxes. Do not collapse root element and + // the initial containing block. Do not collapse boxes with overflow not equal + // to 'visible', because these create new formatting contexts. + bool is_collapsable = + !IsAbsolutelyPositioned() && GetLevel() == Box::kBlockLevel && parent() && + parent()->parent() && !IsOverflowCropped(computed_style()); + + // Margins should only collapse if no padding or border separate them. + // https://www.w3.org/TR/CSS22/box.html#collapsing-margins + bool top_margin_is_collapsable = is_collapsable && + padding_top() == LayoutUnit() && + border_top_width() == LayoutUnit(); // Lay out child boxes in the normal flow. // https://www.w3.org/TR/CSS21/visuren.html#normal-flow std::unique_ptr<BlockFormattingContext> block_formatting_context( - new BlockFormattingContext(child_layout_params)); + new BlockFormattingContext(child_layout_params, + top_margin_is_collapsable)); for (Boxes::const_iterator child_box_iterator = child_boxes().begin(); child_box_iterator != child_boxes().end(); ++child_box_iterator) { Box* child_box = *child_box_iterator; - if (child_box->IsAbsolutelyPositioned()) { - block_formatting_context->EstimateStaticPosition(child_box); - } else { - block_formatting_context->UpdateRect(child_box); - } + block_formatting_context->UpdateRect(child_box); } + + if (is_collapsable) { + block_formatting_context->CollapseContainingMargins(this); + } + return std::unique_ptr<FormattingContext>(block_formatting_context.release()); }
diff --git a/src/cobalt/layout/block_formatting_context.cc b/src/cobalt/layout/block_formatting_context.cc index 8ecb79c..33b8510 100644 --- a/src/cobalt/layout/block_formatting_context.cc +++ b/src/cobalt/layout/block_formatting_context.cc
@@ -23,8 +23,10 @@ namespace layout { BlockFormattingContext::BlockFormattingContext( - const LayoutParams& layout_params) - : layout_params_(layout_params), collapsing_margin_(0) {} + const LayoutParams& layout_params, const bool is_margin_collapsable) + : layout_params_(layout_params), + margin_collapsing_params_(MarginCollapsingParams(is_margin_collapsable)) { +} BlockFormattingContext::~BlockFormattingContext() {} @@ -32,6 +34,11 @@ DCHECK(!child_box->IsAbsolutelyPositioned()); child_box->UpdateSize(layout_params_); + + // In a block formatting context, each box's left outer edge touches + // the left edge of the containing block. + // https://www.w3.org/TR/CSS21/visuren.html#block-formatting + child_box->set_left(LayoutUnit()); UpdatePosition(child_box); // Shrink-to-fit width cannot be less than the width of the widest child. @@ -45,7 +52,6 @@ // child. // https://www.w3.org/TR/CSS21/visudet.html#normal-block set_auto_height(child_box->GetMarginBoxBottomEdgeOffsetFromContainingBlock()); - collapsing_margin_ = child_box->margin_bottom(); // The baseline of an "inline-block" is the baseline of its last line box // in the normal flow, unless it has no in-flow line boxes. @@ -56,23 +62,108 @@ } } -void BlockFormattingContext::EstimateStaticPosition(Box* child_box) { - DCHECK(child_box->IsAbsolutelyPositioned()); - - // The term "static position" (of an element) refers, roughly, to the position - // an element would have had in the normal flow. - // https://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width - UpdatePosition(child_box); -} - void BlockFormattingContext::UpdatePosition(Box* child_box) { DCHECK_EQ(Box::kBlockLevel, child_box->GetLevel()); - // In a block formatting context, each box's left outer edge touches - // the left edge of the containing block. - // https://www.w3.org/TR/CSS21/visuren.html#block-formatting - child_box->set_left(LayoutUnit()); + switch (child_box->GetMarginCollapsingStatus()) { + case Box::kIgnore: + child_box->set_top(auto_height()); + break; + case Box::kSeparateAdjoiningMargins: + child_box->set_top(auto_height()); + margin_collapsing_params_.collapsing_margin = LayoutUnit(); + margin_collapsing_params_.should_collapse_margin_bottom = false; + if (!margin_collapsing_params_.context_margin_top) { + margin_collapsing_params_.should_collapse_margin_top = false; + } + margin_collapsing_params_.should_collapse_own_margins_together = false; + break; + case Box::kCollapseMargins: + margin_collapsing_params_.should_collapse_margin_bottom = true; + // For first child, if top margin will collapse with parent's top margin, + // parent will handle margin positioning for both itself and the child. + if (!margin_collapsing_params_.context_margin_top && + margin_collapsing_params_.should_collapse_margin_top) { + child_box->set_top(auto_height() - child_box->margin_top()); + if (child_box->collapsed_empty_margin_) { + margin_collapsing_params_.should_collapse_margin_bottom = false; + } + } else { + // Collapse top margin with previous sibling's bottom margin. + LayoutUnit collapsed_margin = + CollapseMargins(child_box->margin_top(), + margin_collapsing_params_.collapsing_margin); + LayoutUnit combined_margin = + margin_collapsing_params_.collapsing_margin + + child_box->margin_top(); + LayoutUnit position_difference = combined_margin - collapsed_margin; + child_box->set_top(auto_height() - position_difference); + } + + // Collapse margins for in-flow siblings. + margin_collapsing_params_.collapsing_margin = + child_box->collapsed_empty_margin_.value_or( + child_box->margin_bottom()); + if (!margin_collapsing_params_.context_margin_top) { + margin_collapsing_params_.context_margin_top = child_box->margin_top(); + } + break; + } +} + +void BlockFormattingContext::CollapseContainingMargins(Box* containing_box) { + bool has_padding_top = containing_box->padding_top() != LayoutUnit(); + bool has_border_top = containing_box->border_top_width() != LayoutUnit(); + bool has_padding_bottom = containing_box->padding_bottom() != LayoutUnit(); + bool has_border_bottom = + containing_box->border_bottom_width() != LayoutUnit(); + LayoutUnit margin_top = + layout_params_.maybe_margin_top.value_or(LayoutUnit()); + LayoutUnit margin_bottom = + layout_params_.maybe_margin_bottom.value_or(LayoutUnit()); + + // If no in-flow children, do not collapse margins with children. + if (!margin_collapsing_params_.context_margin_top) { + // Empty boxes with auto or 0 height collapse top/bottom margins together. + // https://www.w3.org/TR/CSS22/box.html#collapsing-margins + if (!has_padding_top && !has_border_top && !has_padding_bottom && + !has_border_bottom && + layout_params_.containing_block_size.height() == LayoutUnit() && + margin_collapsing_params_.should_collapse_own_margins_together) { + containing_box->collapsed_empty_margin_ = + CollapseMargins(margin_top, margin_bottom); + return; + } + // Reset in case min-height iteration reverses 0/auto height criteria. + containing_box->collapsed_empty_margin_.reset(); + return; + } + + // Collapse top margin with top margin of first in-flow child. + if (!has_padding_top && !has_border_top && + margin_collapsing_params_.should_collapse_margin_top) { + LayoutUnit collapsed_margin_top = CollapseMargins( + margin_top, + margin_collapsing_params_.context_margin_top.value_or(LayoutUnit())); + containing_box->collapsed_margin_top_ = collapsed_margin_top; + } + + // If height is auto, collapse bottom margin with bottom margin of last + // in-flow child. + if (!layout_params_.maybe_height && !has_padding_bottom && + !has_border_bottom && + margin_collapsing_params_.should_collapse_margin_bottom) { + LayoutUnit collapsed_margin_bottom = CollapseMargins( + margin_bottom, margin_collapsing_params_.collapsing_margin); + containing_box->collapsed_margin_bottom_ = collapsed_margin_bottom; + set_auto_height(auto_height() - + margin_collapsing_params_.collapsing_margin); + } +} + +LayoutUnit BlockFormattingContext::CollapseMargins( + const LayoutUnit box_margin, const LayoutUnit adjoining_margin) { // In a block formatting context, boxes are laid out one after the other, // vertically, beginning at the top of a containing block. The vertical // distance between two sibling boxes is determined by the "margin" @@ -83,28 +174,25 @@ // When two or more margins collapse, the resulting margin width is the // maximum of the collapsing margins' widths. // https://www.w3.org/TR/CSS21/box.html#collapsing-margins - const LayoutUnit margin_top = child_box->margin_top(); LayoutUnit collapsed_margin; - if ((margin_top >= LayoutUnit()) && (collapsing_margin_ >= LayoutUnit())) { - collapsed_margin = std::max(margin_top, collapsing_margin_); - } else if ((margin_top < LayoutUnit()) && - (collapsing_margin_ < LayoutUnit())) { + if ((box_margin >= LayoutUnit()) && (adjoining_margin >= LayoutUnit())) { + collapsed_margin = std::max(box_margin, adjoining_margin); + } else if ((box_margin < LayoutUnit()) && (adjoining_margin < LayoutUnit())) { // If there are no positive margins, the maximum of the absolute values of // the adjoining margins is deducted from zero. - collapsed_margin = LayoutUnit() + std::min(margin_top, collapsing_margin_); + collapsed_margin = LayoutUnit() + std::min(box_margin, adjoining_margin); } else { // In the case of negative margins, the maximum of the absolute values of // the negative adjoining margins is deducted from the maximum of the // positive adjoining margins. // When there is only one negative and one positive margin, that translates // to: The margins are summed. - DCHECK(collapsing_margin_.GreaterEqualOrNaN(LayoutUnit()) || - margin_top.GreaterEqualOrNaN(LayoutUnit())); - collapsed_margin = collapsing_margin_ + margin_top; + DCHECK(adjoining_margin.GreaterEqualOrNaN(LayoutUnit()) || + box_margin.GreaterEqualOrNaN(LayoutUnit())); + collapsed_margin = adjoining_margin + box_margin; } - LayoutUnit combined_margin = collapsing_margin_ + margin_top; - child_box->set_top(auto_height() - combined_margin + collapsed_margin); + return collapsed_margin; } } // namespace layout
diff --git a/src/cobalt/layout/block_formatting_context.h b/src/cobalt/layout/block_formatting_context.h index 8fee091..2096453 100644 --- a/src/cobalt/layout/block_formatting_context.h +++ b/src/cobalt/layout/block_formatting_context.h
@@ -24,6 +24,20 @@ namespace cobalt { namespace layout { +struct MarginCollapsingParams { + MarginCollapsingParams(const bool is_margin_collapsable) + : collapsing_margin(0), + should_collapse_own_margins_together(true), + should_collapse_margin_bottom(true), + should_collapse_margin_top(is_margin_collapsable) {} + + LayoutUnit collapsing_margin; + base::Optional<LayoutUnit> context_margin_top; + bool should_collapse_own_margins_together; + bool should_collapse_margin_bottom; + bool should_collapse_margin_top; +}; + // In a block formatting context, boxes are laid out one after the other, // vertically, beginning at the top of a containing block. // https://www.w3.org/TR/CSS21/visuren.html#block-formatting @@ -35,22 +49,24 @@ // to update the position of the subsequent children passed to it. class BlockFormattingContext : public FormattingContext { public: - explicit BlockFormattingContext(const LayoutParams& layout_params); + explicit BlockFormattingContext(const LayoutParams& layout_params, + const bool is_margin_collapsable); ~BlockFormattingContext() override; + // Updates the top and bottom margins of the containing box after children + // have been processed. + void CollapseContainingMargins(Box* containing_box); + // Calculates the position and size of the given child box and updates // the internal state in the preparation for the next child. void UpdateRect(Box* child_box); - // Estimates the static position of the given child box. In CSS 2.1 the static - // position is only defined for absolutely positioned boxes. - void EstimateStaticPosition(Box* child_box); - private: void UpdatePosition(Box* child_box); - + LayoutUnit CollapseMargins(const LayoutUnit box_margin, + const LayoutUnit adjoining_margin); const LayoutParams layout_params_; - LayoutUnit collapsing_margin_; + MarginCollapsingParams margin_collapsing_params_; DISALLOW_COPY_AND_ASSIGN(BlockFormattingContext); };
diff --git a/src/cobalt/layout/box.h b/src/cobalt/layout/box.h index 3d661e2..8195c59 100644 --- a/src/cobalt/layout/box.h +++ b/src/cobalt/layout/box.h
@@ -16,7 +16,7 @@ #define COBALT_LAYOUT_BOX_H_ #include <iosfwd> -#include <iostream> +#include <ostream> #include <string> #include <vector> @@ -97,6 +97,10 @@ freeze_height == rhs.freeze_height && containing_block_size == rhs.containing_block_size; } + + base::Optional<LayoutUnit> maybe_margin_top; + base::Optional<LayoutUnit> maybe_margin_bottom; + base::Optional<LayoutUnit> maybe_height; }; inline std::ostream& operator<<(std::ostream& stream, @@ -134,6 +138,12 @@ kInlineLevel, }; + enum MarginCollapsingStatus { + kCollapseMargins, + kIgnore, + kSeparateAdjoiningMargins, + }; + enum RelationshipToBox { kIsBoxAncestor, kIsBox, @@ -215,6 +225,10 @@ // Do not confuse with the formatting context that the element may establish. virtual Level GetLevel() const = 0; + virtual MarginCollapsingStatus GetMarginCollapsingStatus() const { + return Box::kCollapseMargins; + } + // Returns true if the box is positioned (e.g. position is non-static or // transform is not None). Intuitively, this is true if the element does // not follow standard layout flow rules for determining its position. @@ -319,6 +333,21 @@ LayoutUnit GetMarginBoxWidth() const; LayoutUnit GetMarginBoxHeight() const; + // Used values of "margin" properties are set by overriders + // of |UpdateContentSizeAndMargins| method. + void set_margin_left(LayoutUnit margin_left) { + margin_insets_.set_left(margin_left); + } + void set_margin_top(LayoutUnit margin_top) { + margin_insets_.set_top(margin_top); + } + void set_margin_right(LayoutUnit margin_right) { + margin_insets_.set_right(margin_right); + } + void set_margin_bottom(LayoutUnit margin_bottom) { + margin_insets_.set_bottom(margin_bottom); + } + math::Matrix3F GetMarginBoxTransformFromContainingBlock( const ContainerBox* containing_block) const; @@ -335,6 +364,11 @@ BaseDirection base_direction) const; // Border box. + LayoutUnit border_left_width() const { return border_insets_.left(); } + LayoutUnit border_top_width() const { return border_insets_.top(); } + LayoutUnit border_right_width() const { return border_insets_.right(); } + LayoutUnit border_bottom_width() const { return border_insets_.bottom(); } + RectLayoutUnit GetBorderBoxFromRoot(bool transform_forms_root) const; LayoutUnit GetBorderBoxWidth() const; @@ -347,6 +381,10 @@ Vector2dLayoutUnit GetBorderBoxOffsetFromMarginBox() const; // Padding box. + LayoutUnit padding_left() const { return padding_insets_.left(); } + LayoutUnit padding_top() const { return padding_insets_.top(); } + LayoutUnit padding_right() const { return padding_insets_.right(); } + LayoutUnit padding_bottom() const { return padding_insets_.bottom(); } LayoutUnit GetPaddingBoxWidth() const; LayoutUnit GetPaddingBoxHeight() const; SizeLayoutUnit GetClampedPaddingBoxSize() const; @@ -657,6 +695,10 @@ const scoped_refptr<IntersectionObserverRoot>& intersection_observer_root) const; + base::Optional<LayoutUnit> collapsed_margin_top_; + base::Optional<LayoutUnit> collapsed_margin_bottom_; + base::Optional<LayoutUnit> collapsed_empty_margin_; + protected: UsedStyleProvider* used_style_provider() const { return used_style_provider_; @@ -674,35 +716,6 @@ virtual void UpdateContentSizeAndMargins( const LayoutParams& layout_params) = 0; - // Margin box accessors. - // - // Used values of "margin" properties are set by overriders - // of |UpdateContentSizeAndMargins| method. - void set_margin_left(LayoutUnit margin_left) { - margin_insets_.set_left(margin_left); - } - void set_margin_top(LayoutUnit margin_top) { - margin_insets_.set_top(margin_top); - } - void set_margin_right(LayoutUnit margin_right) { - margin_insets_.set_right(margin_right); - } - void set_margin_bottom(LayoutUnit margin_bottom) { - margin_insets_.set_bottom(margin_bottom); - } - - // Border box read-only accessors. - LayoutUnit border_left_width() const { return border_insets_.left(); } - LayoutUnit border_top_width() const { return border_insets_.top(); } - LayoutUnit border_right_width() const { return border_insets_.right(); } - LayoutUnit border_bottom_width() const { return border_insets_.bottom(); } - - // Padding box read-only accessors. - LayoutUnit padding_left() const { return padding_insets_.left(); } - LayoutUnit padding_top() const { return padding_insets_.top(); } - LayoutUnit padding_right() const { return padding_insets_.right(); } - LayoutUnit padding_bottom() const { return padding_insets_.bottom(); } - // Content box setters. // // Used values of "width" and "height" properties are set by overriders
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc index b9fe273..b286b23 100644 --- a/src/cobalt/layout/box_generator.cc +++ b/src/cobalt/layout/box_generator.cc
@@ -406,6 +406,8 @@ namespace { +typedef dom::HTMLElement::DirState DirState; + class ContainerBoxGenerator : public cssom::NotReachedPropertyValueVisitor { public: enum CloseParagraph { @@ -413,12 +415,12 @@ kCloseParagraph, }; - ContainerBoxGenerator(dom::Directionality directionality, + ContainerBoxGenerator(DirState element_dir, const scoped_refptr<cssom::CSSComputedStyleDeclaration>& css_computed_style_declaration, scoped_refptr<Paragraph>* paragraph, const BoxGenerator::Context* context) - : directionality_(directionality), + : element_dir_(element_dir), css_computed_style_declaration_(css_computed_style_declaration), context_(context), has_scoped_directional_embedding_(false), @@ -433,7 +435,7 @@ private: void CreateScopedParagraph(CloseParagraph close_prior_paragraph); - const dom::Directionality directionality_; + const DirState element_dir_; const scoped_refptr<cssom::CSSComputedStyleDeclaration> css_computed_style_declaration_; const BoxGenerator::Context* context_; @@ -532,10 +534,11 @@ // paragraph, when the ContainerBoxGenerator goes out of scope. // https://dev.w3.org/html5/spec-preview/global-attributes.html#the-directionality // http://unicode.org/reports/tr9/#Explicit_Directional_Embeddings - if (directionality_ == dom::kLeftToRightDirectionality) { + // http://unicode.org/reports/tr9/#Markup_And_Formatting + if (element_dir_ == DirState::kDirLeftToRight) { has_scoped_directional_embedding_ = true; (*paragraph_)->AppendCodePoint(Paragraph::kLeftToRightEmbedCodePoint); - } else if (directionality_ == dom::kRightToLeftDirectionality) { + } else if (element_dir_ == DirState::kDirRightToLeft) { has_scoped_directional_embedding_ = true; (*paragraph_)->AppendCodePoint(Paragraph::kRightToLeftEmbedCodePoint); } @@ -675,9 +678,9 @@ // it is inherited from the parent element. // https://dev.w3.org/html5/spec-preview/global-attributes.html#the-directionality BaseDirection base_direction; - if (directionality_ == dom::kLeftToRightDirectionality) { + if (element_dir_ == DirState::kDirLeftToRight) { base_direction = kLeftToRightBaseDirection; - } else if (directionality_ == dom::kRightToLeftDirectionality) { + } else if (element_dir_ == DirState::kDirRightToLeft) { base_direction = kRightToLeftBaseDirection; } else { base_direction = prior_paragraph_->GetDirectionalEmbeddingStackDirection(); @@ -880,7 +883,7 @@ pseudo_element->reset_layout_boxes(); ContainerBoxGenerator pseudo_element_box_generator( - dom::kNoExplicitDirectionality, + DirState::kDirNotDefined, pseudo_element->css_computed_style_declaration(), paragraph_, context_); pseudo_element->computed_style()->display()->Accept( &pseudo_element_box_generator); @@ -966,7 +969,7 @@ html_element->css_computed_style_declaration()); ContainerBoxGenerator container_box_generator( - html_element->directionality(), + html_element->dir_state(), html_element == context_->ignore_background_element ? StripBackground(element_style) : element_style,
diff --git a/src/cobalt/layout/flex_container_box.cc b/src/cobalt/layout/flex_container_box.cc index bacd234..8bb4127 100644 --- a/src/cobalt/layout/flex_container_box.cc +++ b/src/cobalt/layout/flex_container_box.cc
@@ -311,8 +311,11 @@ set_margin_right(maybe_margin_right.value_or(LayoutUnit())); set_margin_top(maybe_margin_top.value_or(LayoutUnit())); set_margin_bottom(maybe_margin_bottom.value_or(LayoutUnit())); - if (child_boxes().empty()) { - baseline_ = GetBorderBoxHeight(); + + UpdateRectOfPositionedChildBoxes(child_layout_params, layout_params); + + if (items.empty()) { + baseline_ = GetPaddingBoxHeight() + border_bottom_width() + margin_bottom(); } else { baseline_ = flex_formatting_context.GetBaseline(); } @@ -480,8 +483,7 @@ } AnonymousBlockBox* FlexContainerBox::GetLastChildAsAnonymousBlockBox() { - return child_boxes().empty() ? NULL - : child_boxes().back()->AsAnonymousBlockBox(); + return NULL; } AnonymousBlockBox* FlexContainerBox::GetOrAddAnonymousBlockBox() {
diff --git a/src/cobalt/layout/flex_container_box.h b/src/cobalt/layout/flex_container_box.h index a962d44..5e55ce2 100644 --- a/src/cobalt/layout/flex_container_box.h +++ b/src/cobalt/layout/flex_container_box.h
@@ -15,6 +15,9 @@ #ifndef COBALT_LAYOUT_FLEX_CONTAINER_BOX_H_ #define COBALT_LAYOUT_FLEX_CONTAINER_BOX_H_ +#include <memory> + +#include "base/optional.h" #include "cobalt/cssom/css_computed_style_declaration.h" #include "cobalt/layout/base_direction.h" #include "cobalt/layout/block_container_box.h"
diff --git a/src/cobalt/layout/flex_line.cc b/src/cobalt/layout/flex_line.cc index 124099a..a55819f 100644 --- a/src/cobalt/layout/flex_line.cc +++ b/src/cobalt/layout/flex_line.cc
@@ -358,7 +358,7 @@ // If the remaining free space is positive and at least one main-axis margin // on this line is auto, distribute the free space equally among these // margins. - std::vector<bool> auto_margins(items_.size()); + std::vector<bool> auto_margins(items_.size() * 2); int auto_margin_count = 0; int margin_idx = 0; for (auto& item : items_) {
diff --git a/src/cobalt/layout/layout_boxes.cc b/src/cobalt/layout/layout_boxes.cc index df06332..e387472 100644 --- a/src/cobalt/layout/layout_boxes.cc +++ b/src/cobalt/layout/layout_boxes.cc
@@ -211,7 +211,6 @@ float top = padding_area.y(); float bottom = scroll_area.bottom(); switch (dir) { - case dom::kNoExplicitDirectionality: case dom::kLeftToRightDirectionality: left = padding_area.x(); break;
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc index 3d2a447..ab107f5 100644 --- a/src/cobalt/layout/replaced_box.cc +++ b/src/cobalt/layout/replaced_box.cc
@@ -366,8 +366,8 @@ if (IsAbsolutelyPositioned()) { // TODO: Implement CSS section 10.3.8, see // https://www.w3.org/TR/CSS21/visudet.html#abs-replaced-width. - set_left(maybe_left.value_or(LayoutUnit())); - set_top(maybe_top.value_or(LayoutUnit())); + set_left(maybe_left.value_or(LayoutUnit(GetStaticPositionLeft()))); + set_top(maybe_top.value_or(LayoutUnit(GetStaticPositionTop()))); } // Note that computed height may be "auto", even if it is specified as a // percentage (depending on conditions of the containing block). See details
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-cropped-overflow-should-form-collapsed-margin-with-parent-but-not-child-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-cropped-overflow-should-form-collapsed-margin-with-parent-but-not-child-expected.png new file mode 100644 index 0000000..fba304f --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-cropped-overflow-should-form-collapsed-margin-with-parent-but-not-child-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-cropped-overflow-should-form-collapsed-margin-with-parent-but-not-child.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-cropped-overflow-should-form-collapsed-margin-with-parent-but-not-child.html new file mode 100644 index 0000000..35ccd52 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-cropped-overflow-should-form-collapsed-margin-with-parent-but-not-child.html
@@ -0,0 +1,31 @@ +<html> + <style> + div { + width: 50px; + height: 50px; + } + #blue { + background-color: blue; + margin-top: 50px; + overflow: hidden; + top: 50px; + } + #yellow { + background-color: yellow; + height: 60px; + margin-top: 30px; + } + #green { + background-color: green; + height: 70px; + margin-top: 50px; + } + </style> + <body> + <div id=green> + <div id=blue> + <div id=yellow></div> + </div> + </div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-in-flow-child-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-in-flow-child-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..3b77c41 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-in-flow-child-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-in-flow-child-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-in-flow-child-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..2200a60 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-in-flow-child-should-not-form-collapsed-margin.html
@@ -0,0 +1,25 @@ +<html> + <style> + #green { + margin-top: 50px; + background-color: green; + margin-bottom: 60px; + } + #blue { + background-color: blue; + width: 50px; + height: 50px; + } + #yellow { + background-color: yellow; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=blue></div> + </div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-inline-child-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-inline-child-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..99cfaad --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-inline-child-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-inline-child-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-inline-child-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..26bb5fa --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-inline-child-should-not-form-collapsed-margin.html
@@ -0,0 +1,20 @@ +<html> + <style> + #green { + margin-top: 50px; + background-color: green; + margin-bottom: 60px; + } + #yellow { + background-color: yellow; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <span>Hello World</span> + </div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-min-height-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-min-height-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..b8e0a0c --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-min-height-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-min-height-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-min-height-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..ae3204e --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-min-height-should-not-form-collapsed-margin.html
@@ -0,0 +1,29 @@ +<html> + <style> + #green { + margin-top: 50px; + background-color: green; + margin-bottom: 60px; + min-height: 20px; + } + #blue { + background-color: blue; + margin-top: 50px; + position: absolute; + top: 0; + width: 50px; + height: 50px; + } + #yellow { + background-color: yellow; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=blue></div> + </div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-no-in-flow-or-inline-children-should-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-no-in-flow-or-inline-children-should-form-collapsed-margin-expected.png new file mode 100644 index 0000000..efdf5a0 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-no-in-flow-or-inline-children-should-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-no-in-flow-or-inline-children-should-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-no-in-flow-or-inline-children-should-form-collapsed-margin.html new file mode 100644 index 0000000..6a9767d --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-box-with-no-in-flow-or-inline-children-should-form-collapsed-margin.html
@@ -0,0 +1,28 @@ +<html> + <style> + #green { + margin-top: 50px; + background-color: green; + margin-bottom: 60px; + } + #blue { + background-color: blue; + margin-top: 50px; + position: absolute; + top: 0; + width: 50px; + height: 50px; + } + #yellow { + background-color: yellow; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=blue></div> + </div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-bottom-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-bottom-margin-expected.png new file mode 100644 index 0000000..174669e --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-bottom-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-bottom-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-bottom-margin.html new file mode 100644 index 0000000..e9344e8 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-bottom-margin.html
@@ -0,0 +1,27 @@ +<html> + <style> + #green { + background-color: green; + } + #blue { + background-color: blue; + width: 50px; + height: 50px; + } + #red { + margin-top: 50px; + } + #yellow { + background-color: yellow; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=blue></div> + <div id=red></div> + </div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-top-but-not-bottom-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-top-but-not-bottom-margin-expected.png new file mode 100644 index 0000000..cfa5749 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-top-but-not-bottom-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-top-but-not-bottom-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-top-but-not-bottom-margin.html new file mode 100644 index 0000000..b7a8771 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-top-but-not-bottom-margin.html
@@ -0,0 +1,24 @@ +<html> + <style> + #green { + background-color: green; + min-height: 50px; + margin-bottom: 20px; + margin-top: 20px; + } + #red { + margin-bottom: 50px; + } + #yellow { + background-color: yellow; + height: 50px; + width: 50px; + } + </style> + <body> + <div id=green> + <div id=red></div> + </div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-absolute-box-should-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-absolute-box-should-form-collapsed-margin-expected.png new file mode 100644 index 0000000..a73ea6d --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-absolute-box-should-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-absolute-box-should-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-absolute-box-should-form-collapsed-margin.html new file mode 100644 index 0000000..ce51aee --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-absolute-box-should-form-collapsed-margin.html
@@ -0,0 +1,28 @@ +<html> + <style> + div { + width: 50px; + height: 50px; + } + #green { + margin-top: 20px; + background-color: green; + margin-bottom: 20px; + } + #blue { + background-color: blue; + margin-top: 40px; + position: absolute; + top: 30px; + } + #yellow { + background-color: yellow; + margin-top: 50px; + } + </style> + <body> + <div id=green></div> + <div id=blue></div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-inline-box-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-inline-box-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..312a572 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-inline-box-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-inline-box-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-inline-box-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..bd26cfe --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-separated-by-inline-box-should-not-form-collapsed-margin.html
@@ -0,0 +1,27 @@ +<html> + <style> + body { + font-family: Roboto; + font-size: 50px; + font-weight: bold; + color: black; + } + div { + width: 50px; + height: 50px; + } + #green { + background-color: green; + margin-bottom: 50px; + } + #yellow { + background-color: yellow; + margin-top: 50px; + } + </style> + <body> + <div id=green></div> + <span>Hello world</span> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-should-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-should-form-collapsed-margin-expected.png new file mode 100644 index 0000000..65743d9 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-should-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-in-flow-siblings-should-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-should-form-collapsed-margin.html similarity index 100% rename from src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-in-flow-siblings-should-form-collapsed-margin.html rename to src/cobalt/layout_tests/testdata/css-2-1/8-3-1-in-flow-siblings-should-form-collapsed-margin.html
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-inline-level-boxes-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-inline-level-boxes-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..f9cdb25 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-inline-level-boxes-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-inline-level-boxes-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-inline-level-boxes-should-not-form-collapsed-margin.html similarity index 100% rename from src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-inline-level-boxes-should-not-form-collapsed-margin.html rename to src/cobalt/layout_tests/testdata/css-2-1/8-3-1-inline-level-boxes-should-not-form-collapsed-margin.html
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin-expected.png new file mode 100644 index 0000000..5bc9961 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin.html new file mode 100644 index 0000000..403127d --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin.html
@@ -0,0 +1,28 @@ +<html> + <style> + div { + width: 50px; + height: 50px; + } + #red { + background-color: red; + margin-top: 50px; + } + #blue { + background-color: blue; + margin-top: 60px; + position: absolute; + top: 40px; + } + #yellow { + background-color: yellow; + margin-top: 50px; + } + </style> + <body> + <div id=red> + <div id=blue></div> + <div id=yellow></div> + </div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-border-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-border-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..2994923 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-border-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-border-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-border-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..648dac1 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-border-should-not-form-collapsed-margin.html
@@ -0,0 +1,20 @@ +<html> + <style> + #green { + background-color: green; + margin-top: 50px; + } + #red { + background-color: red; + margin-top: 50px; + border-top: 10px solid blue; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=red></div> + </div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..84a4dd1 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..cdb72fd --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin.html
@@ -0,0 +1,26 @@ +<html> + <style> + body { + font-family: Roboto; + font-size: 50px; + font-weight: bold; + color: white; + } + #green { + background-color: green; + margin-top: 50px; + } + #blue { + background-color: blue; + margin-top: 50px; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <span>Hello World</span> + <div id=blue></div> + </div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-padding-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-padding-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..5312214 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-padding-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-padding-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-padding-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..9c0a24d --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-separated-by-padding-should-not-form-collapsed-margin.html
@@ -0,0 +1,20 @@ +<html> + <style> + #green { + background-color: green; + margin-top: 50px; + } + #red { + background-color: red; + margin-top: 50px; + padding-top: 20px; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=red></div> + </div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-should-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-should-form-collapsed-margin-expected.png new file mode 100644 index 0000000..f3f7314 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-should-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-parent-and-first-in-flow-child-should-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-should-form-collapsed-margin.html similarity index 100% rename from src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-parent-and-first-in-flow-child-should-form-collapsed-margin.html rename to src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-first-in-flow-child-should-form-collapsed-margin.html
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin-expected.png new file mode 100644 index 0000000..5a4fa3c --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin.html new file mode 100644 index 0000000..b493c12 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin.html
@@ -0,0 +1,34 @@ +<html> + <style> + div { + width: 50px; + height: 50px; + } + #red { + background-color: red; + margin-bottom: 50px; + margin-top: 10px; + } + #blue { + background-color: blue; + margin-bottom: 60px; + margin-top: 20px; + position: absolute; + top: 40px; + } + #green { + background-color: green; + margin-bottom: 50px; + } + #yellow { + background-color: yellow; + } + </style> + <body> + <div id=red> + <div id=green></div> + <div id=blue></div> + </div> + <div id="yellow"></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-border-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-border-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..af12d2f --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-border-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-border-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-border-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..3a1ce38 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-border-should-not-form-collapsed-margin.html
@@ -0,0 +1,26 @@ +<html> + <style> + #green { + background-color: green; + margin-bottom: 50px; + } + #red { + background-color: red; + margin-bottom: 50px; + border-bottom: 10px solid blue; + width: 50px; + height: 50px; + } + #yellow { + background-color: yellow; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=red></div> + </div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..38157f0 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..8c0d4e5 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin.html
@@ -0,0 +1,33 @@ +<html> + <style> + body { + font-family: Roboto; + font-size: 50px; + font-weight: bold; + color: white; + } + #green { + background-color: green; + margin-bottom: 50px; + margin-top: 10px; + } + #blue { + background-color: blue; + margin-bottom: 50px; + width: 50px; + height: 50px; + } + #yellow { + background-color: yellow; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=blue></div> + <span>Hello World</span> + </div> + <div id="yellow"></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-padding-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-padding-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..dbf48d6 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-padding-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-padding-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-padding-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..5652318 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-separated-by-padding-should-not-form-collapsed-margin.html
@@ -0,0 +1,26 @@ +<html> + <style> + #green { + background-color: green; + margin-bottom: 50px; + } + #red { + background-color: red; + margin-bottom: 50px; + padding-bottom: 20px; + width: 50px; + height: 50px; + } + #yellow { + background-color: yellow; + width: 50px; + height: 50px; + } + </style> + <body> + <div id=green> + <div id=red></div> + </div> + <div id=yellow></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-should-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-should-form-collapsed-margin-expected.png new file mode 100644 index 0000000..bafe0f6 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-should-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-parent-and-last-in-flow-child-should-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-should-form-collapsed-margin.html similarity index 100% rename from src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-parent-and-last-in-flow-child-should-form-collapsed-margin.html rename to src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-and-last-in-flow-child-should-form-collapsed-margin.html
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-with-non-auto-height-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-with-non-auto-height-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..3ec7148 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-with-non-auto-height-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-parent-with-non-auto-height-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-with-non-auto-height-should-not-form-collapsed-margin.html similarity index 100% rename from src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-parent-with-non-auto-height-should-not-form-collapsed-margin.html rename to src/cobalt/layout_tests/testdata/css-2-1/8-3-1-parent-with-non-auto-height-should-not-form-collapsed-margin.html
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-statically-positioned-absolute-box-should-not-form-collapsed-margin-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-statically-positioned-absolute-box-should-not-form-collapsed-margin-expected.png new file mode 100644 index 0000000..9d70442 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-statically-positioned-absolute-box-should-not-form-collapsed-margin-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-statically-positioned-absolute-box-should-not-form-collapsed-margin.html b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-statically-positioned-absolute-box-should-not-form-collapsed-margin.html new file mode 100644 index 0000000..eff2c6b --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-2-1/8-3-1-statically-positioned-absolute-box-should-not-form-collapsed-margin.html
@@ -0,0 +1,34 @@ +<html> + <style> + div { + width: 50px; + height: 50px; + } + #green { + background-color: green; + margin-bottom: 10px; + } + #blue { + background-color: blue; + margin-top: 20px; + margin-bottom: 20px; + top: 30px; + } + #yellow { + background-color: yellow; + margin-top: 10px; + margin-bottom: 20px; + } + #purple { + background-color: #673ab7; + margin-top: 20px; + position: absolute; + } + </style> + <body> + <div id=green></div> + <div id=blue></div> + <div id=yellow></div> + <div id=purple></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-top-and-bottom-margins-of-empty-element-should-collapse.html b/src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-top-and-bottom-margins-of-empty-element-should-collapse.html deleted file mode 100644 index 9602fdb..0000000 --- a/src/cobalt/layout_tests/testdata/css-2-1/DISABLED-8-3-1-top-and-bottom-margins-of-empty-element-should-collapse.html +++ /dev/null
@@ -1,33 +0,0 @@ -<!DOCTYPE html> -<!-- - | Adjoining vertical margins collapse if both belong to vertically-adjacent box - | edges, i.e. top margin of a box and top margin of its first in-flow child. - | https://www.w3.org/TR/CSS21/box.html#collapsing-margins - --> -<html> -<head> - <style> - .outer-blue { - background-color: #03a9f4; - height: 100px; - width: 100px; - } - .outer-green { - background-color: #00e676; - margin-top: 10px; - } - .inner-green { - background-color: #00c853; - height: 100px; - margin-top: 100px; - width: 100px; - } - </style> -</head> -<body> - <div class="outer-blue"></div> - <div class="outer-green"> - <div class="inner-green"></div> - </div> -</body> -</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/layout_tests.txt b/src/cobalt/layout_tests/testdata/css-2-1/layout_tests.txt index 2d1ed62..0ec39c3 100644 --- a/src/cobalt/layout_tests/testdata/css-2-1/layout_tests.txt +++ b/src/cobalt/layout_tests/testdata/css-2-1/layout_tests.txt
@@ -110,6 +110,29 @@ 18-4-outline-animation 18-4-outline-overflow-hidden 8-1-margin-should-be-transparent +8-3-1-box-with-cropped-overflow-should-form-collapsed-margin-with-parent-but-not-child +8-3-1-box-with-in-flow-child-should-not-form-collapsed-margin +8-3-1-box-with-inline-child-should-not-form-collapsed-margin +8-3-1-box-with-min-height-should-not-form-collapsed-margin +8-3-1-box-with-no-in-flow-or-inline-children-should-form-collapsed-margin +8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-top-but-not-bottom-margin +8-3-1-empty-box-margin-collapses-itself-then-collapses-with-parent-bottom-margin +8-3-1-in-flow-siblings-separated-by-absolute-box-should-form-collapsed-margin +8-3-1-in-flow-siblings-separated-by-inline-box-should-not-form-collapsed-margin +8-3-1-in-flow-siblings-should-form-collapsed-margin +8-3-1-inline-level-boxes-should-not-form-collapsed-margin +8-3-1-parent-and-first-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin +8-3-1-parent-and-first-in-flow-child-separated-by-border-should-not-form-collapsed-margin +8-3-1-parent-and-first-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin +8-3-1-parent-and-first-in-flow-child-separated-by-padding-should-not-form-collapsed-margin +8-3-1-parent-and-first-in-flow-child-should-form-collapsed-margin +8-3-1-parent-and-last-in-flow-child-separated-by-absolute-box-should-form-collapsed-margin +8-3-1-parent-and-last-in-flow-child-separated-by-border-should-not-form-collapsed-margin +8-3-1-parent-and-last-in-flow-child-separated-by-inline-box-should-not-form-collapsed-margin +8-3-1-parent-and-last-in-flow-child-separated-by-padding-should-not-form-collapsed-margin +8-3-1-parent-and-last-in-flow-child-should-form-collapsed-margin +8-3-1-parent-with-non-auto-height-should-not-form-collapsed-margin +8-3-1-statically-positioned-absolute-box-should-not-form-collapsed-margin 8-3-margin-percentage-should-refer-containing-block-width 8-3-negative-margins-should-be-allowed 8-3-negative_margins-should-be-allowed-to-produce_negative-box-widths
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children-expected.png b/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children-expected.png new file mode 100644 index 0000000..cb33c85 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children.html b/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children.html new file mode 100644 index 0000000..52e896a --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children.html
@@ -0,0 +1,75 @@ +<!DOCTYPE html> +<!-- + | Tests for CSS Flexible Box Layout Module. + | Testing absolutely positioned flex container children. + --> +<html> +<head> +<style> + body { + margin: 0px; + font-family: Roboto; + background-color: gray; + font-size: 12px; + } + .flex { + display: inline-flex; + flex-flow: row wrap; + color: fuchsia; + background-color: yellow; + opacity: 0.75; + min-width: 400px; + min-height: 200px; + margin: 10px 20px 40px 30px; + border: solid white; + border-width: 10px 25px 25px 25px; + -no-position: relative; + -no-transform: translateX(0); + } + .absolute { + background-color: blue; + position: absolute; + } + .fixed { + background-color: purple; + position: fixed; + } + div > span { + padding: 1.25%; + border: 10px solid black; + } + div > video { + opacity: 1; + width: 5%; + height: 5%; + z-index: 1; + } +</style> +</head> +<body> + -gh- + <div style="height: 5px; background-color: black;"></div> + <div style="display: inline-flex; width: 5px; height: 50px; background-color: black;"></div> + <span style="display: inline-block; width: 40px; background-color: lime;">-gh-</span> + <div class="flex"> + <video class="absolute" style="top: 20%;"></video> + <video class="absolute" style="top: 30%; left: 0%;"></video> + <video class="absolute" style="left: 20%;"></video> + <video class="absolute" style="left: 30%; top: 0%;"></video> + <video class="fixed" style="top: 40%;"></video> + <video class="fixed" style="top: 50%; left: 0%;"></video> + <video class="fixed" style="left: 40%;"></video> + <video class="fixed" style="left: 50%; top: 0%;"></video> + <span class="absolute" style="top: 60%;"></span> + <span class="absolute" style="top: 70%; left: 0%;"></span> + <span class="absolute" style="left: 60%;"></span> + <span class="absolute" style="left: 70%; top: 0%;"></span> + <span class="fixed" style="top: 80%;"></span> + <span class="fixed" style="top: 90%; left: 0%;"></span> + <span class="fixed" style="left: 80%;"></span> + <span class="fixed" style="left: 90%; top: 0%"></span> + </div> + <div style="display: inline-flex; width: 5px; height: 50px; background-color: black;"></div> + <div style="height: 5px; background-color: black;"></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/combined-baseline-expected.png b/src/cobalt/layout_tests/testdata/css3-flexbox/combined-baseline-expected.png index 4afe5c9..b9b6c39 100644 --- a/src/cobalt/layout_tests/testdata/css3-flexbox/combined-baseline-expected.png +++ b/src/cobalt/layout_tests/testdata/css3-flexbox/combined-baseline-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline-expected.png b/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline-expected.png new file mode 100644 index 0000000..8b26646 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline.html b/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline.html new file mode 100644 index 0000000..e605155 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<!-- + | Tests for CSS Flexible Box Layout Module. + | Testing absolutely positioned flex container children. + --> +<html> +<head> +<style> + body { + margin: 0px; + font-family: Roboto; + background-color: gray; + font-size: 36px; + } + .flex { + display: inline-flex; + flex-flow: row wrap; + color: fuchsia; + background-color: yellow; + opacity: 0.75; + min-width: 10px; + min-height: 10px; + border: solid white; + } + .absolute { + background-color: blue; + position: absolute; + } + .fixed { + background-color: purple; + position: fixed; + } + div > span { + padding: 1.25%; + border: 10px solid black; + } + div > video { + opacity: 1; + width: 5%; + height: 5%; + z-index: 1; + } + .margin-a { + margin: 6px 12px 24px 16px; + } + .margin-b { + margin: 24px 16px 6px 12px; + } + .border-a { + border-width: 6px 12px 12px 12px; + } + .border-b { + border-width: 12px 12px 5px 12px; + } +</style> +</head> +<body> + -gh- + <div style="height: 5px; background-color: black;"></div> + <div style="display: inline-flex; width: 5px; height: 50px; background-color: black;"></div> + <span style="display: inline-block; width: 60px; background-color: lime">-gh- -gh-</span> + <div class="flex"></div> + <div class="flex margin-a"></div> + <div class="flex margin-b"></div> + <div class="flex border-a"></div> + <div class="flex border-b"></div> + <div class="flex margin-a border-a"></div> + <div class="flex margin-a border-b""></div> + <div class="flex margin-b border-a"></div> + <div class="flex margin-b border-b""></div> + <div style="display: inline-flex; width: 5px; height: 50px; background-color: black;"></div> + <div style="height: 5px; background-color: black;"></div> + </body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/layout_tests.txt b/src/cobalt/layout_tests/testdata/css3-flexbox/layout_tests.txt index c8a34e8..26b3994 100644 --- a/src/cobalt/layout_tests/testdata/css3-flexbox/layout_tests.txt +++ b/src/cobalt/layout_tests/testdata/css3-flexbox/layout_tests.txt
@@ -1,3 +1,4 @@ +absolutely-positioned-children combined-baseline combined-container-sizing-edge-cases combined-order-and-multiline @@ -133,5 +134,6 @@ csswg_flex-shrink-006 csswg_flex-shrink-007 csswg_flex-shrink-008 +empty_container_baseline flex-items-flexibility positioned-containers
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-001.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-001.html new file mode 100644 index 0000000..f5c24ed --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-001.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=rtl basic test</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-001-ref.html"> +<meta name="assert" content="If the element's dir attribute is in the rtl state, the directionality of the element is rtl."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"><p dir="rtl">مكتب W3C הישראלי</p><p>left <span dir="rtl">مكتب W3C הישראלי</span> right</p></div> +<div class="ref"><p style="text-align: right;">‫مكتب W3C הישראלי‬</p><p>left ‫مكتب W3C הישראלי‬ right</p></div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-002.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-002.html new file mode 100644 index 0000000..a3f16fa --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-002.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=ltr basic test</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-002-ref.html"> +<meta name="assert" content="If the element's dir attribute is in the ltr state, the directionality of the element is ltr."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test" dir="rtl"><p dir="ltr">مكتب W3C הישראלי</p><p>נכון <span dir="ltr">مكتب W3C הישראלי</span> שמאל</p></div> +<div class="ref"><p>‪مكتب W3C הישראלי‬</p><p style="text-align: right;">שמאל ‪مكتب W3C הישראלי‬ נכון</p></div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-003.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-003.html new file mode 100644 index 0000000..cf2e392 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-003.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: ltr context, rtl table</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-003-ref.html"> +<meta name="assert" content="[Exploratory] When dir='rtl' is added to a table in a ltr context, (a) directional runs in a table are ordered right-to-left, (b) columns run right-to-left, (c) text is right-aligned within cells, and (d) the table is left-aligned on the page."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +td { border: 1px dotted #ccc; } .ref table { align: right; } .ref td { text-align: right; } +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"> + <table dir="rtl"> + <tr><td>1</td><td>2</td><td>3</td></tr> + <tr><td>مكتب W3C הישראלי</td><td>مكتب W3C הישראלי</td><td>مكتب W3C הישראלי</td></tr> + </table> + </div> +<div class="ref" style="text-align:right;"> + <table> + <tr><td>3</td><td>2</td><td>1</td></tr> + <tr><td>‫مكتب W3C הישראלי‬</td><td>‫مكتب W3C הישראלי‬</td><td>‫مكتب W3C הישראלי‬</td></tr> + </table> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-004.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-004.html new file mode 100644 index 0000000..c30e242 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-004.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: rtl context, ltr table</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-004-ref.html"> +<meta name="assert" content="[Exploratory] When dir='ltr' is added to a table in a rtl context, (a) directional runs in the table are ordered left-to-right, (b) columns run left-to-right, (c) text is left-aligned within cells, and (d) the table is right-aligned on the page."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +td { border: 1px dotted #ccc; } .ref table { align: left; } +</style> +</head> +<body> +<p class="instructions">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test" dir="rtl"> + <table dir="ltr"> + <tr><td>1</td><td>2</td><td>3</td></tr> + <tr><td>مكتب W3C הישראלי</td><td>مكتب W3C הישראלי</td><td>مكتب W3C הישראלי</td></tr> + </table> + </div> +<div class="ref"> + <table style="float:right;"> + <tr><td>1</td><td>2</td><td>3</td></tr> + <tr><td>مكتب W3C הישראלי</td><td>مكتب W3C הישראלי</td><td>مكتب W3C הישראלי</td></tr> + </table> + <br style="clear:both;"/> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-005.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-005.html new file mode 100644 index 0000000..7e3addb --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-005.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: ordered and unordered lists</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<meta name="assert" content="[Exploratory] In a rtl context, all list items should start from the right, regardless of the direction of the script in the list item."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions">Test passes if all bullets and numbers are to the right of the list item.</p> +<div class="test" dir="rtl"> + <ul> + <li>left right</li> + <li>حق غادر</li> + <li>נכון שמאל</li> + </ul> + <ol> + <li>left right</li> + <li>حق غادر</li> + <li>נכון שמאל</li> + </ol> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-006.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-006.html new file mode 100644 index 0000000..f500b8b --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-006.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dl lists</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-006-ref.html"> +<meta name="assert" content="[Exploratory] In a rtl context, all list items should start from the right, regardless of the direction of the script in the list item."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +dt { font-weight: bold; margin:0; padding: 0; margin-top: 1em; } + dd { margin:0; padding: 0; margin-right: 40px; } + .ref { text-align: right; } + .ref dd { margin:0; padding: 0; margin-right: 40px; } +</style> +</head> +<body> +<p class="instructions">Test passes if you see no red characters.</p> +<div class="test" dir="rtl"> + <dl> + <dt>left right</dt> + <dd>left right</dd> + <dt>حق غادر</dt> + <dd>حق غادر</dd> + <dt>נכון שמאל</dt> + <dd>נכון שמאל</dd> + </dl> + </div> +<div class="ref"> + <dl> + <dt>left right</dt> + <dd>left right</dd> + <dt>حق غادر</dt> + <dd>حق غادر</dd> + <dt>נכון שמאל</dt> + <dd>נכון שמאל</dd> + </dl> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-007.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-007.html new file mode 100644 index 0000000..0fde1f8 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-007.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: inheritance</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-007-ref.html"> +<meta name="assert" content="If an element has no dir attribute, but has a parent element, the directionality of the element is the same as the parent element's directionality."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"> + <div dir="rtl"><p>مكتب W3C הישראלי</p><p>مكتب W3C הישראלי</p></div> + <div dir="rtl"><div><p>مكتب W3C הישראלי</p><p>مكتب W3C הישראלי</p></div></div> + <div dir="ltr"><p>مكتب W3C הישראלי</p><p>مكتب W3C הישראלי</p></div> + <div dir="ltr"><div><p>مكتب W3C הישראלי</p><p>مكتب W3C הישראלי</p></div></div> + </div> +<div style="position: relative"> +<div class="test"> + <div style="text-align: right;"><p>‫مكتب W3C הישראלי‬</p><p>‫مكتب W3C הישראלי‬</p></div> + <div style="text-align: right;"><p>‫مكتب W3C הישראלי‬</p><p>‫مكتب W3C הישראלי‬</p></div> + <div><p>‪مكتب W3C הישראלי‬</p><p>‪مكتب W3C הישראלי‬</p></div> + <div><p>‪مكتب W3C הישראלי‬</p><p>‪مكتب W3C הישראלי‬</p></div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-008.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-008.html new file mode 100644 index 0000000..6183429 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-008.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: invalid value and inheritance</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-008-ref.html"> +<meta name="assert" content="If an element has a dir attribute with an invalid value ('foo' or 'bar'), and has a parent element, the directionality of the element is the same as the parent element's directionality."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"> + <div dir="rtl"><p dir="foo">مكتب W3C הישראלי</p></div> + <div dir="ltr"><p dir="bar">مكتب W3C הישראלי</p></div> + </div> +<div style="position: relative"> +<div class="test"> + <div style="text-align: right;"><p>‫مكتب W3C הישראלי‬</p></div> + <div><p>‪مكتب W3C הישראלי‬</p></div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-009.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-009.html new file mode 100644 index 0000000..1fc1a3a --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-009.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: invalid values left and right</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-009-ref.html"> +<meta name="assert" content="If an element has a dir attribute with an invalid value ('left' or 'right' or 'rl' or 'lr'), and has a parent element, the directionality of the element is the same as the parent element's directionality."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"> + <div dir="rtl"><p dir="left">مكتب W3C הישראלי</p></div> + <div dir="rtl"><p dir="lr">مكتب W3C הישראלי</p></div> + <div dir="ltr"><p dir="right">مكتب W3C הישראלי</p></div> + <div dir="ltr"><p dir="rl">مكتب W3C הישראלי</p></div> + </div> +<div style="position: relative"> +<div class="test"> + <div style="text-align: right;"><p>‫مكتب W3C הישראלי‬</p></div> + <div style="text-align: right;"><p>‫مكتب W3C הישראלי‬</p></div> + <div><p>‪مكتب W3C הישראלי‬</p></div> + <div><p>‪مكتب W3C הישראלי‬</p></div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-010.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-010.html new file mode 100644 index 0000000..65e7fb3 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-010.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: default direction, basic test</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-010-ref.html"> +<meta name="assert" content="If the root element has no dir attribute, the directionality of an element is 'ltr'."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"><p>مكتب W3C הישראלי</p></div> +<div style="position: relative"> +<div class="test"><p>‪مكتب W3C הישראלי‬</p></div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-011.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-011.html new file mode 100644 index 0000000..38e2053 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-011.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html dir="right" lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: default direction, invalid value 'right'</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-011-ref.html"> +<meta name="assert" content="If the root element has an invalid dir attribute ('right'), the directionality of an element is 'ltr'."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"><p>مكتب W3C הישראלי</p></div> +<div style="position: relative"> +<div class="test"><p>‪مكتب W3C הישראלי‬</p></div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-012.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-012.html new file mode 100644 index 0000000..570e674 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-012.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html dir="rl" lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: default direction, invalid value 'rl'</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-012-ref.html"> +<meta name="assert" content="If the root element has an invalid dir attribute ('rl'), the directionality of an element is 'ltr'."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"><p>مكتب W3C הישראלי</p></div> +<div style="position: relative"> +<div class="test"><p>‪مكتب W3C הישראלי‬</p></div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-046.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-046.html new file mode 100644 index 0000000..df6d3b0 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-046.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, inline auto direction</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-046-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of the text. dir=auto is applied to an inline element here, in various base direction contexts."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ‭ - The LRO (left-to-right-override) formatting character. + ‬ - The PDF (pop directional formatting) formatting character; closes LRO. + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="rtl"> + א <span dir="auto">a!</span> א + </div> + <div dir="ltr"> + א <span dir="auto">a!</span> א + </div> + <div dir="ltr"> + a <span dir="auto">א!</span> a + </div> + <div dir="rtl"> + a <span dir="auto">א!</span> a + </div> + </div> +<div class="ref"> + <div dir="rtl"> + ‭א a! א‬ + </div> + <div dir="ltr"> + ‭א a! א‬ + </div> + <div dir="ltr"> + ‭a !א a‬ + </div> + <div dir="rtl"> + ‭a !א a‬ + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-047.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-047.html new file mode 100644 index 0000000..c1ca2c3 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-047.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, inline isolation</title> +<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-047-ref.html"> +<meta name="assert" content="dir='auto' on an inline element will directionally isolate its contents from a following number."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ‭ - The LRO (left-to-right-override) formatting character. + ‬ - The PDF (pop directional formatting) formatting character; closes LRO. + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"><span dir="auto">א</span> 5 a</div> + <div dir=rtl><span dir="auto">a</span> 5 א</div> + </div> +<div class="ref"> + <div dir="ltr"> + ‭א 5 a‬ + </div> + <div dir="rtl"> + ‭א 5 a‬ + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-048.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-048.html new file mode 100644 index 0000000..b2d09dd --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-048.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-048-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of the text. In this test, it is the Latin letter A, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + + input, textarea { + font-size:1em; + } +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">ABCאבג.</p> + </div> + <div dir="rtl"> + <p dir="auto">ABCאבג.</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="ltr">ABCאבג.</p> + </div> + <div dir="rtl"> + <p dir="ltr">ABCאבג.</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-049.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-049.html new file mode 100644 index 0000000..8e45184 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-049.html
@@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with R/AL</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='author' title='Richard Ishida' href='mailto:ishida2w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-049-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of the text. In this test, it is the Hebrew or Arabic letter Alef, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + + input, textarea { + font-size:1em; + } +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">אבגABC.</p> + <p dir="auto">ابةABC.</p> + </div> + <div dir="rtl"> + <p dir="auto">אבגABC.</p> + <p dir="auto">ابةABC.</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="rtl">אבגABC.</p> + <p dir="rtl">ابةABC.</p> + </div> + <div dir="rtl"> + <p dir="rtl">אבגABC.</p> + <p dir="rtl">ابةABC.</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-050.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-050.html new file mode 100644 index 0000000..8b75080 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-050.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, isolated in LTR text</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-050-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text, but the element behaves externally as a neutral character. In this test, it allows a preceding R to form a single directional run with a succeeding number."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ‭ - The LRO (left-to-right-override) formatting character. + ‬ - The PDF (pop directional formatting) formatting character; closes LRO. + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + א <span dir="auto">a!</span> 1 + </div> + <div dir="rtl"> + a <span dir="auto">א!</span> 1 + </div> + </div> +<div class="ref"> + <div dir="ltr"> + ‭1 a! א‬ + </div> + <div dir="rtl"> + ‭a !א 1‬ + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-051.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-051.html new file mode 100644 index 0000000..976548e --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-051.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with bdi, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-051-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text while ignoring bdi elements. In this test, it is the Latin letter A, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + ד - The Hebrew letter Dalet (strongly RTL). + ה - The Hebrew letter He (strongly RTL). + ו - The Hebrew letter Vav (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><bdi>דהו</bdi>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="auto"><bdi>דהו</bdi>ABCאבג.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="ltr"><bdi>דהו</bdi>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="ltr"><bdi>דהו</bdi>ABCאבג.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-052.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-052.html new file mode 100644 index 0000000..8a91881 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-052.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with bdi, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-052-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of the text while ignoring bdi elements. In this test, it is the Hebrew letter Alef, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><bdi>DEF</bdi>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="auto"><bdi>DEF</bdi>אבגABC.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="rtl"><bdi>DEF</bdi>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="rtl"><bdi>DEF</bdi>אבגABC.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-053.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-053.html new file mode 100644 index 0000000..ab10ff7 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-053.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with dir=auto, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-053-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text while ignoring contained elements with an explicit dir of their own. In this test, it is the Latin letter A, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + ד - The Hebrew letter Dalet (strongly RTL). + ה - The Hebrew letter He (strongly RTL). + ו - The Hebrew letter Vav (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><p dir="auto">דהו</p>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="auto"><p dir="auto">דהו</p>ABCאבג.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="ltr"><p dir="rtl">דהו</p>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="ltr"><p dir="rtl">דהו</p>ABCאבג.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-054.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-054.html new file mode 100644 index 0000000..b8c30ae --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-054.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with dir=auto, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-054-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of the text while ignoring contained elements with an explicit dir of their own. In this test, it is the Hebrew letter Alef, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><p dir="auto">DEF</p>.-=123אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="auto"><p dir="auto">DEF</p>.-=123אבגABC.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="rtl"><p dir="ltr">DEF</p>.-=123אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="rtl"><p dir="ltr">DEF</p>.-=123אבגABC.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-055.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-055.html new file mode 100644 index 0000000..617a35b --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-055.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with dir, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-055-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of the text while ignoring contained elements with an explicit dir of their own. In this test, it is the Latin letter A, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + ד - The Hebrew letter Dalet (strongly RTL). + ה - The Hebrew letter He (strongly RTL). + ו - The Hebrew letter Vav (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><p dir="rtl">דהו</p>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="auto"><p dir="rtl">דהו</p>ABCאבג.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="ltr"><p dir="rtl">דהו</p>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="ltr"><p dir="rtl">דהו</p>ABCאבג.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-056.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-056.html new file mode 100644 index 0000000..253462b --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-056.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with dir, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-056-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text while ignoring contained elements with an explicit dir of their own. In this test, it is the Hebrew letter Alef, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><p dir="ltr">DEF</p>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="auto"><p dir="ltr">DEF</p>אבגABC.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="rtl"><p dir="ltr">DEF</p>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="rtl"><p dir="ltr">DEF</p>אבגABC.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-057.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-057.html new file mode 100644 index 0000000..37d9888 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-057.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with L within contained element</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-057-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of the text, including text within contained elements. In this test, it is the Latin letter A, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + ד - The Hebrew letter Dalet (strongly RTL). + ה - The Hebrew letter He (strongly RTL). + ו - The Hebrew letter Vav (strongly RTL). + ז - The Hebrew letter Zayin (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><div><div>ABCאבג.</div>דה</div>ו</div> + </div> + <div dir="rtl"> + <div dir="auto"><div><div>ABCאבג.</div>דה</div>ו</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="ltr"><div><div>ABCאבג.</div>דה</div>ו</div> + </div> + <div dir="rtl"> + <div dir="ltr"><div><div>ABCאבג.</div>דה</div>ו</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-058.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-058.html new file mode 100644 index 0000000..e432262 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-058.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with R within contained element</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-058-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text, including text within contained elements. In this test, it is the Hebrew letter Alef, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><div><div>אבגABC.</div>XY</div>Z</div> + </div> + <div dir="rtl"> + <div dir="auto"><div><div>אבגABC.</div>XY</div>Z</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="rtl"><div><div>אבגABC.</div>XY</div>Z</div> + </div> + <div dir="rtl"> + <div dir="rtl"><div><div>אבגABC.</div>XY</div>Z</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-059.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-059.html new file mode 100644 index 0000000..fea83f2 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-059.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with script, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-059-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of descendant text while ignoring descendant script elements. In this test, it is the Latin letter A, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><script>\u05d0 = 3;</script>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="auto"><script>\u05d0 = 3;</script>ABCאבג.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="ltr"><script>\u05d0 = 3;</script>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="ltr"><script>\u05d0 = 3;</script>ABCאבג.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-060.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-060.html new file mode 100644 index 0000000..0a427e1 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-060.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with script, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-060-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of descendant text while ignoring descendant script elements. In this test, it is the Hebrew letter Alef, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><script>x = 3;</script>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="auto"><script>x = 3;</script>אבגABC.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="rtl"><script>x = 3;</script>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="rtl"><script>x = 3;</script>אבגABC.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-061.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-061.html new file mode 100644 index 0000000..26a65d8 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-061.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with style, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-061-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of descendant text while ignoring descendant style elements. In this test, it is the Latin letter A, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><style>body {color:black;}</style>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="auto"><style>body {color:black;}</style>ABCאבג.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="ltr"><style>body {color:black;}</style>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="ltr"><style>body {color:black;}</style>ABCאבג.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-062.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-062.html new file mode 100644 index 0000000..9ec04c3 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-062.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with style, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-062-ref.html"> +<meta name="assert" content="When dir='auto', the direction is set according to the first strong character of descendant text while ignoring descendant style elements. In this test, it is the Hebrew letter Alef, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><style>body {color:black;}</style>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="auto"><style>body {color:black;}</style>אבגABC.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="rtl"><style>body {color:black;}</style>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="rtl"><style>body {color:black;}</style>אבגABC.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-063.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-063.html new file mode 100644 index 0000000..e9d99a1 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-063.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with textarea, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-063-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of descendant text while ignoring descendant textarea elements. In this test, it is the Latin letter A, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +textarea { font-size: 1em; } +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + ד - The Hebrew letter Dalet (strongly RTL). + ה - The Hebrew letter He (strongly RTL). + ו - The Hebrew letter Vav (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><textarea>דהו</textarea>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="auto"><textarea>דהו</textarea>ABCאבג.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="ltr"><textarea>דהו</textarea>ABCאבג.</div> + </div> + <div dir="rtl"> + <div dir="ltr"><textarea>דהו</textarea>ABCאבג.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-064.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-064.html new file mode 100644 index 0000000..b5c865a --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-064.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with textarea, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-064-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of descendant text while ignoring descendant textarea elements. In this test, it is the Hebrew letter Alef, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +textarea { font-size: 1em; } +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <div dir="auto"><textarea>DEF</textarea>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="auto"><textarea>DEF</textarea>אבגABC.</div> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <div dir="rtl"><textarea>DEF</textarea>אבגABC.</div> + </div> + <div dir="rtl"> + <div dir="rtl"><textarea>DEF</textarea>אבגABC.</div> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-065.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-065.html new file mode 100644 index 0000000..b496f49 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-065.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with EN, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-065-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text. In this test, it is the Latin letter A since digits are not strongly directional, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">123ABCאבג.</p> + </div> + <div dir="rtl"> + <p dir="auto">123ABCאבג.</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="ltr">123ABCאבג.</p> + </div> + <div dir="rtl"> + <p dir="ltr">123ABCאבג.</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-066.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-066.html new file mode 100644 index 0000000..d629a20 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-066.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with EN, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-066-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text. In this test, it is the Hebrew letter Alef since digits are not strongly directional, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">123אבגABC.</p> + </div> + <div dir="rtl"> + <p dir="auto">123אבגABC.</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="rtl">123אבגABC.</p> + </div> + <div dir="rtl"> + <p dir="rtl">123אבגABC.</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-067.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-067.html new file mode 100644 index 0000000..f8f7c62 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-067.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with N, then EN, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-067-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text. In this test, it is the Latin letter A since neutrals and digits are not strongly directional, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">.-=123ABCאבג.</p> + </div> + <div dir="rtl"> + <p dir="auto">.-=123ABCאבג.</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="ltr">.-=123ABCאבג.</p> + </div> + <div dir="rtl"> + <p dir="ltr">.-=123ABCאבג.</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-068.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-068.html new file mode 100644 index 0000000..1e21dff --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-068.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with N, then EN, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-068-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text. In this test, it is the Hebrew letter Alef since neutrals and digits are not strongly directional, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">.-=123אבגABC.</p> + </div> + <div dir="rtl"> + <p dir="auto">.-=123אבגABC.</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="rtl">.-=123אבגABC.</p> + </div> + <div dir="rtl"> + <p dir="rtl">.-=123אבגABC.</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-069.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-069.html new file mode 100644 index 0000000..02c2618 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-069.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with N, then EN, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-069-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text, ignoring neutrals and numbers. If there is no strong character, as in this test, the direction defaults to LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">@123!</p> + </div> + <div dir="rtl"> + <p dir="auto">@123!</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="ltr">@123!</p> + </div> + <div dir="rtl"> + <p dir="ltr">@123!</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-070.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-070.html new file mode 100644 index 0000000..89032f3 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-070.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with N, then L</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-070-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text. In this test, it is the Latin letter A since neutrals are not strongly directional, thus the direction must be resolved as LTR."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">.-=ABCאבג.</p> + </div> + <div dir="rtl"> + <p dir="auto">.-=ABCאבג.</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="ltr">.-=ABCאבג.</p> + </div> + <div dir="rtl"> + <p dir="ltr">.-=ABCאבג.</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-071.html b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-071.html new file mode 100644 index 0000000..ce39343 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/the-dir-attribute/the-dir-attribute-071.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en" > +<head> +<meta charset="utf-8"/> +<title>The dir attribute: dir=auto, start with N, then R</title> +<link rel='author' title='HTML5 bidi test WG' href='mailto:public-i18n-bidi@w3.org'> +<link rel='help' href='https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute'> +<link rel="match" href="reference/the-dir-attribute-071-ref.html"> +<meta name="assert" content=" When dir='auto', the direction is set according to the first strong character of the text. In this test, it is the Hebrew letter Alef since neutrals are not strongly directional, thus the direction must be resolved as RTL."> +<style type='text/css'> +.test, .ref { width: 90%; margin: 0 4%; font-size: 2em; position: absolute; top: 0; } +.ref { color: red; z-index: -100; } + +</style> +</head> +<body> +<p class="instructions" dir="ltr">Test passes if you see no red characters.</p> +<!--<div class="comments"> + Key to entities used below: + א - The Hebrew letter Alef (strongly RTL). + ב - The Hebrew letter Bet (strongly RTL). + ג - The Hebrew letter Gimel (strongly RTL). + </div>--> +<div style="position: relative"> +<div class="test"> + <div dir="ltr"> + <p dir="auto">.-=אבגABC.</p> + </div> + <div dir="rtl"> + <p dir="auto">.-=אבגABC.</p> + </div> + </div> +<div class="ref"> + <div dir="ltr"> + <p dir="rtl">.-=אבגABC.</p> + </div> + <div dir="rtl"> + <p dir="rtl">.-=אבגABC.</p> + </div> + </div> +</div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/web_platform_test_parser.cc b/src/cobalt/layout_tests/web_platform_test_parser.cc index d90a43e..0e1b721 100644 --- a/src/cobalt/layout_tests/web_platform_test_parser.cc +++ b/src/cobalt/layout_tests/web_platform_test_parser.cc
@@ -23,6 +23,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/test/scoped_task_environment.h" #include "cobalt/base/cobalt_paths.h" #include "cobalt/layout_tests/test_utils.h" #include "cobalt/script/global_environment.h" @@ -103,6 +104,7 @@ if (precondition) { // Evaluate the javascript precondition. Enumerate the web platform tests // only if the precondition is true. + base::test::ScopedTaskEnvironment task_env_; std::unique_ptr<script::JavaScriptEngine> engine = script::JavaScriptEngine::CreateEngine(); scoped_refptr<script::GlobalEnvironment> global_environment =
diff --git a/src/cobalt/loader/cobalt_url_fetcher_string_writer.cc b/src/cobalt/loader/cobalt_url_fetcher_string_writer.cc deleted file mode 100644 index 142032b..0000000 --- a/src/cobalt/loader/cobalt_url_fetcher_string_writer.cc +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2019 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "cobalt/loader/cobalt_url_fetcher_string_writer.h" -#include "net/base/net_errors.h" - -namespace cobalt { -// CobaltURLFetcherStringWriter::CobaltURLFetcherStringWriter(OnWriteCallback -// callback, base::TaskRunner* consumer_task_runner) : -// on_write_callback_(callback), consumer_task_runner_(consumer_task_runner) { -// DCHECK(consumer_task_runner); -// } - -CobaltURLFetcherStringWriter::CobaltURLFetcherStringWriter() = default; - -CobaltURLFetcherStringWriter::~CobaltURLFetcherStringWriter() = default; - -int CobaltURLFetcherStringWriter::Initialize( - net::CompletionOnceCallback /*callback*/) { - return net::OK; -} - -std::unique_ptr<std::string> CobaltURLFetcherStringWriter::data() { - base::AutoLock auto_lock(lock_); - if (!data_) { - return std::make_unique<std::string>(); - } - return std::move(data_); -} - -int CobaltURLFetcherStringWriter::Write( - net::IOBuffer* buffer, int num_bytes, - net::CompletionOnceCallback /*callback*/) { - base::AutoLock auto_lock(lock_); - if (!data_) { - data_ = std::make_unique<std::string>(); - } - - data_->append(buffer->data(), num_bytes); - // consumer_task_runner_->PostTask(FROM_HERE, - // base::Bind((on_write_callback_.Run), std::move(data))); - return num_bytes; -} - -int CobaltURLFetcherStringWriter::Finish( - int /*net_error*/, net::CompletionOnceCallback /*callback*/) { - return net::OK; -} - -} // namespace cobalt \ No newline at end of file
diff --git a/src/cobalt/loader/cobalt_url_fetcher_string_writer.h b/src/cobalt/loader/cobalt_url_fetcher_string_writer.h deleted file mode 100644 index 5a615e3..0000000 --- a/src/cobalt/loader/cobalt_url_fetcher_string_writer.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2019 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef COBALT_URL_FETCHER_RESPONSE_WRITER_H_ -#define COBALT_URL_FETCHER_RESPONSE_WRITER_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/synchronization/lock.h" -#include "base/task_runner.h" -#include "net/base/io_buffer.h" -#include "net/url_request/url_fetcher_response_writer.h" - -namespace cobalt { - -class CobaltURLFetcherStringWriter : public net::URLFetcherResponseWriter { - public: - // typedef base::RepeatingCallback<void(std::unique_ptr<std::string>)> - // OnWriteCallback; CobaltURLFetcherStringWriter(OnWriteCallback callback, - // base::TaskRunner* consumer_task_runner); - CobaltURLFetcherStringWriter(); - ~CobaltURLFetcherStringWriter() override; - - std::unique_ptr<std::string> data(); - - // URLFetcherResponseWriter overrides: - int Initialize(net::CompletionOnceCallback callback) override; - int Write(net::IOBuffer* buffer, int num_bytes, - net::CompletionOnceCallback callback) override; - int Finish(int net_error, net::CompletionOnceCallback callback) override; - - private: - // This class can be accessed by both network thread and MainWebModule - // thread. - base::Lock lock_; - std::unique_ptr<std::string> data_; - // OnWriteCallback on_write_callback_; - // base::TaskRunner* consumer_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(CobaltURLFetcherStringWriter); -}; - -} // namespace cobalt - -#endif // COBALT_URL_FETCHER_RESPONSE_WRITER_H_ \ No newline at end of file
diff --git a/src/cobalt/loader/image/image_decoder.cc b/src/cobalt/loader/image/image_decoder.cc index 0ea0aef..f4384c4 100644 --- a/src/cobalt/loader/image/image_decoder.cc +++ b/src/cobalt/loader/image/image_decoder.cc
@@ -29,6 +29,7 @@ #include "net/base/mime_util.h" #include "net/http/http_status_code.h" #include "starboard/configuration.h" +#include "starboard/gles.h" #include "starboard/image.h" namespace cobalt { @@ -380,19 +381,23 @@ // static bool ImageDecoder::AllowDecodingToMultiPlane() { -#if SB_HAS(GLES2) && defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION && \ + defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER) // Many image formats can produce native output in multi plane images in YUV - // 420. Allow these images to be decoded into multi plane image not only + // 420. Allowing these images to be decoded into multi plane image not only // reduces the space to store the decoded image to 37.5%, but also improves // decoding performance by not converting the output from YUV to RGBA. - bool allow_image_decoding_to_multi_plane = true; -#else // SB_HAS(GLES2) && defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER) - // Decoding to single plane by default because blitter platforms usually - // don't have the ability to perform hardware accelerated YUV-formatted - // image blitting. + // + // Blitter platforms usually don't have the ability to perform hardware + // accelerated YUV-formatted image blitting, so we decode to a single plane + // when we do not support gles. // This also applies to skia based "hardware" rasterizers as the rendering // of multi plane images in such cases are not optimized, but this may be // improved in future. + bool allow_image_decoding_to_multi_plane = SbGetGlesInterface() != nullptr; +#elif SB_HAS(GLES2) && defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER) + bool allow_image_decoding_to_multi_plane = true; +#else // SB_HAS(GLES2) && defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER) bool allow_image_decoding_to_multi_plane = false; #endif // SB_HAS(GLES2) && defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER)
diff --git a/src/cobalt/loader/loader.gyp b/src/cobalt/loader/loader.gyp index cb1fbe5..87cdade 100644 --- a/src/cobalt/loader/loader.gyp +++ b/src/cobalt/loader/loader.gyp
@@ -24,8 +24,6 @@ 'sources': [ 'blob_fetcher.cc', 'blob_fetcher.h', - 'cobalt_url_fetcher_string_writer.cc', - 'cobalt_url_fetcher_string_writer.h', 'cache_fetcher.cc', 'cache_fetcher.h', 'cors_preflight.cc', @@ -96,6 +94,8 @@ 'sync_loader.cc', 'sync_loader.h', 'text_decoder.h', + 'url_fetcher_string_writer.cc', + 'url_fetcher_string_writer.h', ], 'includes': [ '<(DEPTH)/cobalt/renderer/renderer_parameters_setup.gypi',
diff --git a/src/cobalt/loader/net_fetcher.cc b/src/cobalt/loader/net_fetcher.cc index cb084a1..3302418 100644 --- a/src/cobalt/loader/net_fetcher.cc +++ b/src/cobalt/loader/net_fetcher.cc
@@ -20,6 +20,7 @@ #include "base/strings/stringprintf.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/loader/cors_preflight.h" +#include "cobalt/loader/url_fetcher_string_writer.h" #include "cobalt/network/network_module.h" #include "net/url_request/url_fetcher.h" #if defined(OS_STARBOARD) @@ -87,9 +88,9 @@ url_fetcher_ = net::URLFetcher::Create(url, options.request_method, this); url_fetcher_->SetRequestContext( network_module->url_request_context_getter().get()); - auto* download_data_writer = new CobaltURLFetcherStringWriter(); - url_fetcher_->SaveResponseWithWriter( - std::unique_ptr<CobaltURLFetcherStringWriter>(download_data_writer)); + std::unique_ptr<URLFetcherStringWriter> download_data_writer( + new URLFetcherStringWriter()); + url_fetcher_->SaveResponseWithWriter(std::move(download_data_writer)); if (request_mode != kNoCORSMode && !url.SchemeIs("data") && origin != Origin(url)) { request_cross_origin_ = true; @@ -169,7 +170,7 @@ const int response_code = source->GetResponseCode(); if (status.is_success() && IsResponseCodeSuccess(response_code)) { auto* download_data_writer = - base::polymorphic_downcast<CobaltURLFetcherStringWriter*>( + base::polymorphic_downcast<URLFetcherStringWriter*>( source->GetResponseWriter()); std::unique_ptr<std::string> data = download_data_writer->data(); if (!data->empty()) { @@ -206,7 +207,7 @@ int64_t /*current_network_bytes*/) { if (IsResponseCodeSuccess(source->GetResponseCode())) { auto* download_data_writer = - base::polymorphic_downcast<CobaltURLFetcherStringWriter*>( + base::polymorphic_downcast<URLFetcherStringWriter*>( source->GetResponseWriter()); std::unique_ptr<std::string> data = download_data_writer->data(); if (data->empty()) {
diff --git a/src/cobalt/loader/net_fetcher.h b/src/cobalt/loader/net_fetcher.h index 2ab6df8..a7ce094 100644 --- a/src/cobalt/loader/net_fetcher.h +++ b/src/cobalt/loader/net_fetcher.h
@@ -24,7 +24,6 @@ #include "base/message_loop/message_loop.h" #include "base/threading/thread_checker.h" #include "cobalt/csp/content_security_policy.h" -#include "cobalt/loader/cobalt_url_fetcher_string_writer.h" #include "cobalt/loader/fetcher.h" #include "cobalt/network/network_module.h" #include "net/url_request/url_fetcher.h"
diff --git a/src/cobalt/loader/url_fetcher_string_writer.cc b/src/cobalt/loader/url_fetcher_string_writer.cc new file mode 100644 index 0000000..b583799 --- /dev/null +++ b/src/cobalt/loader/url_fetcher_string_writer.cc
@@ -0,0 +1,63 @@ +// Copyright 2019 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cobalt/loader/url_fetcher_string_writer.h" +#include "net/base/net_errors.h" + +namespace cobalt { +namespace loader { + +// URLFetcherStringWriter::URLFetcherStringWriter(OnWriteCallback +// callback, base::TaskRunner* consumer_task_runner) : +// on_write_callback_(callback), consumer_task_runner_(consumer_task_runner) { +// DCHECK(consumer_task_runner); +// } + +URLFetcherStringWriter::URLFetcherStringWriter() = default; + +URLFetcherStringWriter::~URLFetcherStringWriter() = default; + +int URLFetcherStringWriter::Initialize( + net::CompletionOnceCallback /*callback*/) { + return net::OK; +} + +std::unique_ptr<std::string> URLFetcherStringWriter::data() { + base::AutoLock auto_lock(lock_); + if (!data_) { + return std::make_unique<std::string>(); + } + return std::move(data_); +} + +int URLFetcherStringWriter::Write(net::IOBuffer* buffer, int num_bytes, + net::CompletionOnceCallback /*callback*/) { + base::AutoLock auto_lock(lock_); + if (!data_) { + data_ = std::make_unique<std::string>(); + } + + data_->append(buffer->data(), num_bytes); + // consumer_task_runner_->PostTask(FROM_HERE, + // base::Bind((on_write_callback_.Run), std::move(data))); + return num_bytes; +} + +int URLFetcherStringWriter::Finish(int /*net_error*/, + net::CompletionOnceCallback /*callback*/) { + return net::OK; +} + +} // namespace loader +} // namespace cobalt
diff --git a/src/cobalt/loader/url_fetcher_string_writer.h b/src/cobalt/loader/url_fetcher_string_writer.h new file mode 100644 index 0000000..3bab4a6 --- /dev/null +++ b/src/cobalt/loader/url_fetcher_string_writer.h
@@ -0,0 +1,60 @@ +// Copyright 2019 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COBALT_LOADER_URL_FETCHER_STRING_WRITER_H_ +#define COBALT_LOADER_URL_FETCHER_STRING_WRITER_H_ + +#include <memory> +#include <string> + +#include "base/callback.h" +#include "base/synchronization/lock.h" +#include "base/task_runner.h" +#include "net/base/io_buffer.h" +#include "net/url_request/url_fetcher_response_writer.h" + +namespace cobalt { +namespace loader { + +class URLFetcherStringWriter : public net::URLFetcherResponseWriter { + public: + // typedef base::RepeatingCallback<void(std::unique_ptr<std::string>)> + // OnWriteCallback; URLFetcherStringWriter(OnWriteCallback callback, + // base::TaskRunner* consumer_task_runner); + URLFetcherStringWriter(); + ~URLFetcherStringWriter() override; + + std::unique_ptr<std::string> data(); + + // URLFetcherResponseWriter overrides: + int Initialize(net::CompletionOnceCallback callback) override; + int Write(net::IOBuffer* buffer, int num_bytes, + net::CompletionOnceCallback callback) override; + int Finish(int net_error, net::CompletionOnceCallback callback) override; + + private: + // This class can be accessed by both network thread and MainWebModule + // thread. + base::Lock lock_; + std::unique_ptr<std::string> data_; + // OnWriteCallback on_write_callback_; + // base::TaskRunner* consumer_task_runner_; + + DISALLOW_COPY_AND_ASSIGN(URLFetcherStringWriter); +}; + +} // namespace loader +} // namespace cobalt + +#endif // COBALT_LOADER_URL_FETCHER_STRING_WRITER_H_
diff --git a/src/cobalt/media/base/drm_system.cc b/src/cobalt/media/base/drm_system.cc index ab0cedd..8ad4118 100644 --- a/src/cobalt/media/base/drm_system.cc +++ b/src/cobalt/media/base/drm_system.cc
@@ -20,10 +20,13 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" +#include "cobalt/base/instance_counter.h" namespace cobalt { namespace media { +DECLARE_INSTANCE_COUNTER(DrmSystem); + DrmSystem::Session::Session( DrmSystem* drm_system , @@ -102,12 +105,18 @@ message_loop_(base::MessageLoop::current()->task_runner()), ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), weak_this_(weak_ptr_factory_.GetWeakPtr()) { + ON_INSTANCE_CREATED(DrmSystem); + if (!is_valid()) { SB_LOG(ERROR) << "Failed to initialize the underlying wrapped DrmSystem."; } } -DrmSystem::~DrmSystem() { SbDrmDestroySystem(wrapped_drm_system_); } +DrmSystem::~DrmSystem() { + ON_INSTANCE_RELEASED(DrmSystem); + + SbDrmDestroySystem(wrapped_drm_system_); +} std::unique_ptr<DrmSystem::Session> DrmSystem::CreateSession( SessionUpdateKeyStatusesCallback session_update_key_statuses_callback
diff --git a/src/cobalt/media/base/sbplayer_pipeline.cc b/src/cobalt/media/base/sbplayer_pipeline.cc index a01c7be..ac9a15b 100644 --- a/src/cobalt/media/base/sbplayer_pipeline.cc +++ b/src/cobalt/media/base/sbplayer_pipeline.cc
@@ -1313,6 +1313,9 @@ } if (player_) { + // Cancel pending delayed calls to OnNeedData. After player_->Resume(), + // |player_| will call OnNeedData again. + audio_read_delayed_ = false; player_->Suspend(); }
diff --git a/src/cobalt/media/base/sbplayer_set_bounds_helper.cc b/src/cobalt/media/base/sbplayer_set_bounds_helper.cc index 618ccb2..1783cd5 100644 --- a/src/cobalt/media/base/sbplayer_set_bounds_helper.cc +++ b/src/cobalt/media/base/sbplayer_set_bounds_helper.cc
@@ -22,21 +22,28 @@ namespace { // StaticAtomicSequenceNumber is safe to be initialized statically. +// +// Cobalt renderer renders from back to front, using a monotonically increasing +// sequence guarantees that all video layers are correctly ordered on z axis. base::AtomicSequenceNumber s_z_index; } // namespace void SbPlayerSetBoundsHelper::SetPlayer(StarboardPlayer* player) { base::AutoLock auto_lock(lock_); player_ = player; + if (player_ && rect_.has_value()) { + player_->SetBounds(s_z_index.GetNext(), rect_.value()); + } } bool SbPlayerSetBoundsHelper::SetBounds(const gfx::Rect& rect) { base::AutoLock auto_lock(lock_); - if (!player_) { - return false; + rect_ = rect; + if (player_) { + player_->SetBounds(s_z_index.GetNext(), rect_.value()); } - player_->SetBounds(s_z_index.GetNext(), rect); - return true; + + return player_ != nullptr; } } // namespace media
diff --git a/src/cobalt/media/base/sbplayer_set_bounds_helper.h b/src/cobalt/media/base/sbplayer_set_bounds_helper.h index 65bdd77..074ff7b 100644 --- a/src/cobalt/media/base/sbplayer_set_bounds_helper.h +++ b/src/cobalt/media/base/sbplayer_set_bounds_helper.h
@@ -16,6 +16,7 @@ #define COBALT_MEDIA_BASE_SBPLAYER_SET_BOUNDS_HELPER_H_ #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/synchronization/lock.h" #include "ui/gfx/rect.h" @@ -27,14 +28,15 @@ class SbPlayerSetBoundsHelper : public base::RefCountedThreadSafe<SbPlayerSetBoundsHelper> { public: - SbPlayerSetBoundsHelper() : player_(NULL) {} + SbPlayerSetBoundsHelper() {} void SetPlayer(StarboardPlayer* player); bool SetBounds(const gfx::Rect& rect); private: base::Lock lock_; - StarboardPlayer* player_; + StarboardPlayer* player_ = nullptr; + base::Optional<gfx::Rect> rect_; DISALLOW_COPY_AND_ASSIGN(SbPlayerSetBoundsHelper); };
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc index 628898c..c41e9ac 100644 --- a/src/cobalt/media/base/starboard_player.cc +++ b/src/cobalt/media/base/starboard_player.cc
@@ -337,6 +337,13 @@ base::TimeDelta* buffer_start_time, base::TimeDelta* buffer_length_time) { DCHECK(buffer_start_time || buffer_length_time); DCHECK(is_url_based_); + + if (state_ == kSuspended) { + *buffer_start_time = base::TimeDelta(); + *buffer_length_time = base::TimeDelta(); + return; + } + DCHECK(SbPlayerIsValid(player_)); SbUrlPlayerExtraInfo url_player_info; @@ -355,9 +362,16 @@ void StarboardPlayer::GetVideoResolution(int* frame_width, int* frame_height) { DCHECK(frame_width); DCHECK(frame_height); - DCHECK(SbPlayerIsValid(player_)); DCHECK(is_url_based_); + if (state_ == kSuspended) { + *frame_width = video_sample_info_.frame_width; + *frame_height = video_sample_info_.frame_height; + return; + } + + DCHECK(SbPlayerIsValid(player_)); + SbPlayerInfo2 out_player_info; SbPlayerGetInfo2(player_, &out_player_info);
diff --git a/src/cobalt/media/decoder_buffer_allocator.cc b/src/cobalt/media/decoder_buffer_allocator.cc index 95238ea..f6e2021 100644 --- a/src/cobalt/media/decoder_buffer_allocator.cc +++ b/src/cobalt/media/decoder_buffer_allocator.cc
@@ -16,6 +16,7 @@ #include <vector> +#include "cobalt/math/size.h" #include "cobalt/media/base/starboard_utils.h" #include "cobalt/media/base/video_resolution.h" #include "nb/allocator.h" @@ -29,7 +30,6 @@ namespace { -const bool kEnableMultiblockAllocate = false; const bool kEnableAllocationLog = false; const std::size_t kAllocationRecordGranularity = 512 * 1024; @@ -39,227 +39,206 @@ return size > kSmallAllocationThreshold; } +bool IsMemoryPoolEnabled() { +#if SB_API_VERSION >= 10 + return SbMediaIsBufferUsingMemoryPool(); +#elif COBALT_MEDIA_BUFFER_INITIAL_CAPACITY > 0 || \ + COBALT_MEDIA_BUFFER_ALLOCATION_UNIT > 0 + return true; +#endif // COBALT_MEDIA_BUFFER_INITIAL_CAPACITY == 0 && + // COBALT_MEDIA_BUFFER_ALLOCATION_UNIT == 0 + return false; +} + +bool IsMemoryPoolAllocatedOnDemand() { +#if SB_API_VERSION >= 10 + return SbMediaIsBufferPoolAllocateOnDemand(); +#else // SB_API_VERSION >= 10 + return COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND; +#endif // SB_API_VERSION >= 10 +} + +int GetInitialBufferCapacity() { +#if SB_API_VERSION >= 10 + return SbMediaGetInitialBufferCapacity(); +#else // SB_API_VERSION >= 10 + return COBALT_MEDIA_BUFFER_INITIAL_CAPACITY; +#endif // SB_API_VERSION >= 10 +} + +int GetBufferAllocationUnit() { +#if SB_API_VERSION >= 10 + return SbMediaGetBufferAllocationUnit(); +#else // SB_API_VERSION >= 10 + return COBALT_MEDIA_BUFFER_ALLOCATION_UNIT; +#endif // SB_API_VERSION >= 10 +} + } // namespace -DecoderBufferAllocator::DecoderBufferAllocator() { -#if SB_API_VERSION >= 10 - using_memory_pool_ = SbMediaIsBufferUsingMemoryPool(); - bool pool_allocate_on_demand = SbMediaIsBufferPoolAllocateOnDemand(); -#elif COBALT_MEDIA_BUFFER_USING_MEMORY_POOL - using_memory_pool_ = true; - bool pool_allocate_on_demand = COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND; -#endif // SB_API_VERSION >= 10 - -#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 - if (using_memory_pool_) { - if (pool_allocate_on_demand) { - DLOG(INFO) << "Allocated media buffer pool on demand."; - } else { - TRACK_MEMORY_SCOPE("Media"); -#if SB_API_VERSION >= 10 - int initial_capacity = SbMediaGetInitialBufferCapacity(); - // We cannot call SbMediaGetMaxBufferCapacity because |video_codec_| is - // not set yet. Use 0 (unbounded) until |video_codec_| is updated in - // UpdateVideoConfig. - int max_capacity = 0; - int allocation_unit = SbMediaGetBufferAllocationUnit(); -#else // SB_API_VERSION >= 10 - int initial_capacity = COBALT_MEDIA_BUFFER_INITIAL_CAPACITY; - int max_capacity = COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P; - int allocation_unit = COBALT_MEDIA_BUFFER_ALLOCATION_UNIT; -#endif // SB_API_VERSION >= 10 - reuse_allocator_.reset(new ReuseAllocator(&fallback_allocator_, - initial_capacity, - allocation_unit, max_capacity)); - DLOG(INFO) << "Allocated " << initial_capacity - << " bytes for media buffer pool as its initial buffer."; - } +DecoderBufferAllocator::DecoderBufferAllocator() + : using_memory_pool_(IsMemoryPoolEnabled()), + is_memory_pool_allocated_on_demand_(IsMemoryPoolAllocatedOnDemand()), + initial_capacity_(GetInitialBufferCapacity()), + allocation_unit_(GetBufferAllocationUnit()) { + if (!using_memory_pool_) { + DLOG(INFO) << "Allocated media buffer memory using SbMemory* functions."; return; } -#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 - DLOG(INFO) << "Allocated media buffer memory using SbMemory* functions."; + + if (is_memory_pool_allocated_on_demand_) { + DLOG(INFO) << "Allocated media buffer pool on demand."; + return; + } + + TRACK_MEMORY_SCOPE("Media"); + +#if SB_API_VERSION >= 10 + // We cannot call SbMediaGetMaxBufferCapacity because |video_codec_| is not + // set yet. Use 0 (unbounded) until |video_codec_| is updated in + // UpdateVideoConfig(). + int max_capacity = 0; +#else // SB_API_VERSION >= 10 + int max_capacity = COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P; +#endif // SB_API_VERSION >= 10 + reuse_allocator_.reset(new ReuseAllocator( + &fallback_allocator_, initial_capacity_, allocation_unit_, max_capacity)); + DLOG(INFO) << "Allocated " << initial_capacity_ + << " bytes for media buffer pool as its initial buffer, with max" + << " capacity set to " << max_capacity; } DecoderBufferAllocator::~DecoderBufferAllocator() { -#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 - if (using_memory_pool_) { - TRACK_MEMORY_SCOPE("Media"); - - starboard::ScopedLock scoped_lock(mutex_); - - if (reuse_allocator_) { - DCHECK_EQ(reuse_allocator_->GetAllocated(), 0); - reuse_allocator_.reset(); - } + if (!using_memory_pool_) { + return; } -#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || - // SB_API_VERSION >= 10 + + TRACK_MEMORY_SCOPE("Media"); + + starboard::ScopedLock scoped_lock(mutex_); + + if (reuse_allocator_) { + DCHECK_EQ(reuse_allocator_->GetAllocated(), 0); + reuse_allocator_.reset(); + } } DecoderBuffer::Allocator::Allocations DecoderBufferAllocator::Allocate( size_t size, size_t alignment, intptr_t context) { TRACK_MEMORY_SCOPE("Media"); -#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 - if (using_memory_pool_) { - starboard::ScopedLock scoped_lock(mutex_); - - if (!reuse_allocator_) { -#if SB_API_VERSION >= 10 - int initial_capacity = SbMediaGetInitialBufferCapacity(); - int max_capacity = SbMediaGetMaxBufferCapacity( - video_codec_, resolution_width_, resolution_height_, bits_per_pixel_); - int allocation_unit = SbMediaGetBufferAllocationUnit(); -#else // SB_API_VERSION >= 10 - int initial_capacity = COBALT_MEDIA_BUFFER_INITIAL_CAPACITY; - int max_capacity = COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P; - int allocation_unit = COBALT_MEDIA_BUFFER_ALLOCATION_UNIT; -#endif // SB_API_VERSION >= 10 - reuse_allocator_.reset(new ReuseAllocator(&fallback_allocator_, - initial_capacity, - allocation_unit, max_capacity)); - DLOG(INFO) << "Returned " << initial_capacity - << " bytes from media buffer pool to system."; - } - - if (!kEnableMultiblockAllocate || kEnableAllocationLog) { - void* p = reuse_allocator_->Allocate(size, alignment); - if (!p) { - return Allocations(); - } - LOG_IF(INFO, kEnableAllocationLog) - << "Media Allocation Log " << p << " " << size << " " << alignment - << " " << context; - if (!UpdateAllocationRecord()) { - // UpdateAllocationRecord may fail with non-NULL p when capacity is - // exceeded. - reuse_allocator_->Free(p); - return Allocations(); - } - return Allocations(p, size); - } - - std::size_t allocated_size = size; - void* p = reuse_allocator_->AllocateBestBlock(alignment, context, - &allocated_size); - DCHECK_LE(allocated_size, size); - if (!p) { - return Allocations(); - } - if (allocated_size == size) { - if (!UpdateAllocationRecord()) { - // UpdateAllocationRecord may fail with non-NULL p when capacity is - // exceeded. - reuse_allocator_->Free(p); - return Allocations(); - } - return Allocations(p, size); - } - - std::vector<void*> buffers = {p}; - std::vector<int> buffer_sizes = {static_cast<int>(allocated_size)}; - size -= allocated_size; - - bool update_allocation_record_failed = false; - while (size > 0) { - allocated_size = size; - void* p = reuse_allocator_->AllocateBestBlock(alignment, context, - &allocated_size); - if (!p) { - return Allocations(); - } - if (!UpdateAllocationRecord()) { - update_allocation_record_failed = true; - reuse_allocator_->Free(p); - break; - } - DCHECK_LE(allocated_size, size); - buffers.push_back(p); - buffer_sizes.push_back(allocated_size); - - size -= allocated_size; - } - if (update_allocation_record_failed) { - for (auto& p : buffers) { - reuse_allocator_->Free(p); - } - return Allocations(); - } - return Allocations(static_cast<int>(buffers.size()), buffers.data(), - buffer_sizes.data()); + if (!using_memory_pool_) { + return Allocations(SbMemoryAllocateAligned(alignment, size), size); } -#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || - // SB_API_VERSION >= 10 - return Allocations(SbMemoryAllocateAligned(alignment, size), size); + + starboard::ScopedLock scoped_lock(mutex_); + + if (!reuse_allocator_) { + DCHECK(is_memory_pool_allocated_on_demand_); + +#if SB_API_VERSION >= 10 + int max_capacity = 0; + if (video_codec_ != kSbMediaVideoCodecNone) { + DCHECK_GT(resolution_width_, 0); + DCHECK_GT(resolution_height_, 0); + + max_capacity = SbMediaGetMaxBufferCapacity( + video_codec_, resolution_width_, resolution_height_, bits_per_pixel_); + } +#else // SB_API_VERSION >= 10 + VideoResolution resolution = + GetVideoResolution(math::Size(resolution_width_, resolution_height_)); + int max_capacity = resolution <= kVideoResolution1080p + ? COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P + : COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K; +#endif // SB_API_VERSION >= 10 + reuse_allocator_.reset(new ReuseAllocator(&fallback_allocator_, + initial_capacity_, + allocation_unit_, max_capacity)); + DLOG(INFO) << "Allocated " << initial_capacity_ + << " bytes for media buffer pool, with max capacity set to " + << max_capacity; + } + + void* p = reuse_allocator_->Allocate(size, alignment); + if (!p) { + return Allocations(); + } + LOG_IF(INFO, kEnableAllocationLog) + << "Media Allocation Log " << p << " " << size << " " << alignment << " " + << context; + if (!UpdateAllocationRecord()) { + // UpdateAllocationRecord may fail with non-NULL p when capacity is + // exceeded. + reuse_allocator_->Free(p); + return Allocations(); + } + return Allocations(p, size); } void DecoderBufferAllocator::Free(Allocations allocations) { TRACK_MEMORY_SCOPE("Media"); -#if SB_API_VERSION >= 10 - bool pool_allocate_on_demand = SbMediaIsBufferPoolAllocateOnDemand(); -#else // SB_API_VERSION >= 10 - bool pool_allocate_on_demand = COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND; -#endif // SB_API_VERSION >= 10 -#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 - if (using_memory_pool_) { - starboard::ScopedLock scoped_lock(mutex_); - - DCHECK(reuse_allocator_); - - if (kEnableAllocationLog) { - DCHECK_EQ(allocations.number_of_buffers(), 1); - LOG(INFO) << "Media Allocation Log " << allocations.buffers()[0]; - } + if (!using_memory_pool_) { for (int i = 0; i < allocations.number_of_buffers(); ++i) { - reuse_allocator_->Free(allocations.buffers()[i]); - } - if (pool_allocate_on_demand) { - if (reuse_allocator_->GetAllocated() == 0) { - DLOG(INFO) << "Freed " << reuse_allocator_->GetCapacity() - << " bytes of media buffer pool `on demand`."; - reuse_allocator_.reset(); - } + SbMemoryDeallocateAligned(allocations.buffers()[i]); } return; } -#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || - // SB_API_VERSION >= 10 + + starboard::ScopedLock scoped_lock(mutex_); + + DCHECK(reuse_allocator_); + + if (kEnableAllocationLog) { + DCHECK_EQ(allocations.number_of_buffers(), 1); + LOG(INFO) << "Media Allocation Log " << allocations.buffers()[0]; + } + for (int i = 0; i < allocations.number_of_buffers(); ++i) { - SbMemoryDeallocateAligned(allocations.buffers()[i]); + reuse_allocator_->Free(allocations.buffers()[i]); + } + + if (is_memory_pool_allocated_on_demand_) { + if (reuse_allocator_->GetAllocated() == 0) { + DLOG(INFO) << "Freed " << reuse_allocator_->GetCapacity() + << " bytes of media buffer pool `on demand`."; + reuse_allocator_.reset(); + } } } void DecoderBufferAllocator::UpdateVideoConfig( const VideoDecoderConfig& config) { -#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 - if (using_memory_pool_) { -#if SB_API_VERSION >= 10 - video_codec_ = MediaVideoCodecToSbMediaVideoCodec(config.codec()); - resolution_width_ = config.visible_rect().size().width(); - resolution_height_ = config.visible_rect().size().height(); - bits_per_pixel_ = config.webm_color_metadata().BitsPerChannel; -#endif // SB_API_VERSION >= 10 - if (!reuse_allocator_) { - return; - } -#if SB_API_VERSION >= 10 - reuse_allocator_->set_max_capacity(SbMediaGetMaxBufferCapacity( - video_codec_, resolution_width_, resolution_height_, bits_per_pixel_)); -#else // SB_API_VERSION >= 10 - VideoResolution resolution = - GetVideoResolution(config.visible_rect().size()); - if (reuse_allocator_->max_capacity() && - resolution > kVideoResolution1080p) { - reuse_allocator_->set_max_capacity(COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K); - } -#endif // SB_API_VERSION >= 10 + if (!using_memory_pool_) { + return; } -#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || - // SB_API_VERSION >= 10 + + starboard::ScopedLock scoped_lock(mutex_); + + video_codec_ = MediaVideoCodecToSbMediaVideoCodec(config.codec()); + resolution_width_ = config.visible_rect().size().width(); + resolution_height_ = config.visible_rect().size().height(); + bits_per_pixel_ = config.webm_color_metadata().BitsPerChannel; + + if (!reuse_allocator_) { + return; + } + +#if SB_API_VERSION >= 10 + reuse_allocator_->IncreaseMaxCapacityIfNecessary(SbMediaGetMaxBufferCapacity( + video_codec_, resolution_width_, resolution_height_, bits_per_pixel_)); +#else // SB_API_VERSION >= 10 + VideoResolution resolution = GetVideoResolution(config.visible_rect().size()); + if (reuse_allocator_->max_capacity() && resolution > kVideoResolution1080p) { + reuse_allocator_->IncreaseMaxCapacityIfNecessary( + COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K); + } +#endif // SB_API_VERSION >= 10 + DLOG(INFO) << "Max capacity of decoder buffer allocator after increasing is " + << reuse_allocator_->GetCapacity(); } -#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 DecoderBufferAllocator::ReuseAllocator::ReuseAllocator( Allocator* fallback_allocator, std::size_t initial_capacity, std::size_t allocation_increment, std::size_t max_capacity) @@ -272,7 +251,7 @@ std::size_t size, std::size_t alignment, intptr_t context, FreeBlockSet::iterator begin, FreeBlockSet::iterator end, bool* allocate_from_front) { - SB_DCHECK(allocate_from_front); + DCHECK(allocate_from_front); auto free_block_iter = FindFreeBlock(size, alignment, begin, end, allocate_from_front); @@ -302,19 +281,12 @@ return end; } -bool DecoderBufferAllocator::UpdateAllocationRecord( - std::size_t blocks /*= 1*/) const { +bool DecoderBufferAllocator::UpdateAllocationRecord() const { #if !defined(COBALT_BUILD_TYPE_GOLD) -// This code is not quite multi-thread safe but is safe enough for tracking -// purposes. -#if SB_API_VERSION >= 10 - int initial_capacity = SbMediaGetInitialBufferCapacity(); -#else // SB_API_VERSION >= 10 - int initial_capacity = COBALT_MEDIA_BUFFER_INITIAL_CAPACITY; -#endif // SB_API_VERSION >= 10 - static std::size_t max_allocated = initial_capacity / 2; - static std::size_t max_capacity = initial_capacity; - static std::size_t max_blocks = 1; + // This code is not quite multi-thread safe but is safe enough for tracking + // purposes. + static std::size_t max_allocated = initial_capacity_ / 2; + static std::size_t max_capacity = initial_capacity_; bool new_max_reached = false; if (reuse_allocator_->GetAllocated() > @@ -327,22 +299,16 @@ max_capacity = reuse_allocator_->GetCapacity(); new_max_reached = true; } - if (blocks > max_blocks) { - max_blocks = blocks; - new_max_reached = true; - } if (new_max_reached) { SB_LOG(ERROR) << "New Media Buffer Allocation Record: " << "Max Allocated: " << max_allocated - << " Max Capacity: " << max_capacity - << " Max Blocks: " << max_blocks; + << " Max Capacity: " << max_capacity; // TODO: Enable the following line once PrintAllocations() accepts max line // as a parameter. // reuse_allocator_->PrintAllocations(); } #endif // !defined(COBALT_BUILD_TYPE_GOLD) -#if COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P > 0 || \ - COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K > 0 || SB_API_VERSION >= 10 + if (reuse_allocator_->CapacityExceeded()) { SB_LOG(ERROR) << "Cobalt media buffer capacity " << reuse_allocator_->GetCapacity() @@ -350,10 +316,8 @@ << reuse_allocator_->max_capacity(); return false; } -#endif // COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P > 0 || - // COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K > 0 || SB_API_VERSION >= 10 return true; } -#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 + } // namespace media } // namespace cobalt
diff --git a/src/cobalt/media/decoder_buffer_allocator.h b/src/cobalt/media/decoder_buffer_allocator.h index fd1e19c..485efb7 100644 --- a/src/cobalt/media/decoder_buffer_allocator.h +++ b/src/cobalt/media/decoder_buffer_allocator.h
@@ -29,14 +29,6 @@ namespace cobalt { namespace media { -#if SB_API_VERSION < 10 -#if COBALT_MEDIA_BUFFER_INITIAL_CAPACITY > 0 || \ - COBALT_MEDIA_BUFFER_ALLOCATION_UNIT > 0 -#define COBALT_MEDIA_BUFFER_USING_MEMORY_POOL 1 -#endif // COBALT_MEDIA_BUFFER_INITIAL_CAPACITY == 0 && - // COBALT_MEDIA_BUFFER_ALLOCATION_UNIT == 0 -#endif // SB_API_VERSION < 10 - class DecoderBufferAllocator : public DecoderBuffer::Allocator { public: DecoderBufferAllocator(); @@ -48,7 +40,6 @@ void UpdateVideoConfig(const VideoDecoderConfig& video_config) override; private: -#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 class ReuseAllocator : public nb::BidirectionalFitReuseAllocator { public: ReuseAllocator(Allocator* fallback_allocator, std::size_t initial_capacity, @@ -62,19 +53,21 @@ // Update the Allocation record, and return false if allocation exceeds the // max buffer capacity, or true otherwise. - bool UpdateAllocationRecord(std::size_t blocks = 1) const; + bool UpdateAllocationRecord() const; + + const bool using_memory_pool_; + const bool is_memory_pool_allocated_on_demand_; + const int initial_capacity_; + const int allocation_unit_; starboard::Mutex mutex_; nb::StarboardMemoryAllocator fallback_allocator_; std::unique_ptr<ReuseAllocator> reuse_allocator_; - bool using_memory_pool_ = false; -#if SB_API_VERSION >= 10 + SbMediaVideoCodec video_codec_ = kSbMediaVideoCodecNone; - int resolution_width_ = kSbMediaVideoResolutionDimensionInvalid; - int resolution_height_ = kSbMediaVideoResolutionDimensionInvalid; - int bits_per_pixel_ = kSbMediaBitsPerPixelInvalid; -#endif // SB_API_VERSION >= 10 -#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL || SB_API_VERSION >= 10 + int resolution_width_ = -1; + int resolution_height_ = -1; + int bits_per_pixel_ = -1; }; } // namespace media
diff --git a/src/cobalt/media/fetcher_buffered_data_source.cc b/src/cobalt/media/fetcher_buffered_data_source.cc index 812c7e2..cbf6f41 100644 --- a/src/cobalt/media/fetcher_buffered_data_source.cc +++ b/src/cobalt/media/fetcher_buffered_data_source.cc
@@ -23,6 +23,7 @@ #include "base/strings/string_number_conversions.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/loader/cors_preflight.h" +#include "cobalt/loader/url_fetcher_string_writer.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" @@ -208,7 +209,7 @@ int64_t /*current_network_bytes*/) { DCHECK(task_runner_->BelongsToCurrentThread()); auto* download_data_writer = - base::polymorphic_downcast<CobaltURLFetcherStringWriter*>( + base::polymorphic_downcast<loader::URLFetcherStringWriter*>( source->GetResponseWriter()); std::unique_ptr<std::string> download_data = download_data_writer->data(); size_t size = download_data->size(); @@ -330,9 +331,9 @@ std::move(net::URLFetcher::Create(url_, net::URLFetcher::GET, this)); fetcher_->SetRequestContext( network_module_->url_request_context_getter().get()); - auto* download_data_writer = new CobaltURLFetcherStringWriter(); - fetcher_->SaveResponseWithWriter( - std::unique_ptr<CobaltURLFetcherStringWriter>(download_data_writer)); + std::unique_ptr<loader::URLFetcherStringWriter> download_data_writer( + new loader::URLFetcherStringWriter()); + fetcher_->SaveResponseWithWriter(std::move(download_data_writer)); std::string range_request = "Range: bytes=" + base::NumberToString(last_request_offset_) + "-" +
diff --git a/src/cobalt/media/fetcher_buffered_data_source.h b/src/cobalt/media/fetcher_buffered_data_source.h index 688bedb..6eca602 100644 --- a/src/cobalt/media/fetcher_buffered_data_source.h +++ b/src/cobalt/media/fetcher_buffered_data_source.h
@@ -26,7 +26,6 @@ #include "base/synchronization/lock.h" #include "cobalt/base/circular_buffer_shell.h" #include "cobalt/csp/content_security_policy.h" -#include "cobalt/loader/cobalt_url_fetcher_string_writer.h" #include "cobalt/loader/fetcher.h" #include "cobalt/loader/origin.h" #include "cobalt/media/player/buffered_data_source.h"
diff --git a/src/cobalt/media/formats/mp4/mp4_stream_parser.cc b/src/cobalt/media/formats/mp4/mp4_stream_parser.cc index e4d7754..391318b 100644 --- a/src/cobalt/media/formats/mp4/mp4_stream_parser.cc +++ b/src/cobalt/media/formats/mp4/mp4_stream_parser.cc
@@ -287,6 +287,8 @@ sample_format = kSampleFormatU8; } else if (entry.samplesize == 16) { sample_format = kSampleFormatS16; + } else if (entry.samplesize == 24) { + sample_format = kSampleFormatS24; } else if (entry.samplesize == 32) { sample_format = kSampleFormatS32; } else {
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc index 6185a52..2d91c81 100644 --- a/src/cobalt/media/player/web_media_player_impl.cc +++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -18,6 +18,7 @@ #include "base/strings/string_number_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/trace_event/trace_event.h" +#include "cobalt/base/instance_counter.h" #include "cobalt/media/base/bind_to_current_loop.h" #include "cobalt/media/base/drm_system.h" #include "cobalt/media/base/limits.h" @@ -66,6 +67,8 @@ // greater than or equal to duration() - kEndOfStreamEpsilonInSeconds". const double kEndOfStreamEpsilonInSeconds = 2.; +DECLARE_INSTANCE_COUNTER(WebMediaPlayerImpl); + bool IsNearTheEndOfStream(const WebMediaPlayerImpl* wmpi, double position) { float duration = wmpi->GetDuration(); if (SbDoubleIsFinite(duration)) { @@ -130,6 +133,8 @@ drm_system_(NULL) { TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::WebMediaPlayerImpl"); + ON_INSTANCE_CREATED(WebMediaPlayerImpl); + video_frame_provider_ = new VideoFrameProvider(); DLOG_IF(ERROR, s_instance) @@ -159,6 +164,8 @@ DCHECK(!main_loop_ || main_loop_ == base::MessageLoop::current()); + ON_INSTANCE_RELEASED(WebMediaPlayerImpl); + DLOG_IF(ERROR, s_instance != this) << "More than one WebMediaPlayerImpl has been created."; s_instance = NULL; @@ -646,7 +653,8 @@ // Any error that occurs before reaching ReadyStateHaveMetadata should // be considered a format error. SetNetworkError(WebMediaPlayer::kNetworkStateFormatError, - "Ready state have nothing."); + message.empty() ? "Ready state have nothing." + : "Ready state have nothing: " + message); return; }
diff --git a/src/cobalt/media/sandbox/format_guesstimator.cc b/src/cobalt/media/sandbox/format_guesstimator.cc index 0194787..06fe8a0 100644 --- a/src/cobalt/media/sandbox/format_guesstimator.cc +++ b/src/cobalt/media/sandbox/format_guesstimator.cc
@@ -17,7 +17,19 @@ #include <algorithm> #include <vector> +#include "base/bind.h" #include "base/path_service.h" +#include "base/time/time.h" +#include "cobalt/math/size.h" +#include "cobalt/media/base/audio_codecs.h" +#include "cobalt/media/base/audio_decoder_config.h" +#include "cobalt/media/base/demuxer_stream.h" +#include "cobalt/media/base/media_tracks.h" +#include "cobalt/media/base/video_codecs.h" +#include "cobalt/media/base/video_decoder_config.h" +#include "cobalt/media/filters/chunk_demuxer.h" +#include "cobalt/media/sandbox/web_media_player_helper.h" +#include "cobalt/render_tree/image.h" #include "net/base/filename_util.h" #include "net/base/url_util.h" #include "starboard/common/string.h" @@ -31,6 +43,22 @@ namespace { +// Container to organize the pairs of supported mime types and their codecs. +struct SupportedTypeCodecInfo { + std::string mime; + std::string codecs; +}; + +// The possible mime and codec configurations that are supported by cobalt. +const std::vector<SupportedTypeCodecInfo> kSupportedTypesAndCodecs = { + {"audio/mp4", "ac-3"}, {"audio/mp4", "ec-3"}, + {"audio/mp4", "mp4a.40.2"}, {"audio/webm", "opus"}, + + {"video/mp4", "av01.0.05M.08"}, {"video/mp4", "avc1.640028, mp4a.40.2"}, + {"video/mp4", "avc1.640028"}, {"video/mp4", "hvc1.1.6.H150.90"}, + {"video/webm", "vp9"}, +}; + // Can be called as: // IsFormat("https://example.com/audio.mp4", ".mp4") // IsFormat("cobalt/demos/video.webm", ".webm") @@ -45,7 +73,6 @@ if (!result.IsAbsolute()) { base::FilePath content_path; base::PathService::Get(base::DIR_TEST_DATA, &content_path); - CHECK(content_path.IsAbsolute()); result = content_path.Append(result); } if (SbFileCanOpen(result.value().c_str(), kSbFileOpenOnly | kSbFileRead)) { @@ -54,11 +81,12 @@ return base::FilePath(); } -// Read the first 4096 bytes of the local file specified by |path|. If the size -// of the size is less than 4096 bytes, the function reads all of its content. +// Read the first 256kb of the local file specified by |path|. If the size +// of the file is less than 256kb, the function reads all of its content. std::vector<uint8_t> ReadHeader(const base::FilePath& path) { - const int64_t kHeaderSize = 4096; - + // Size of the input file to be read into memory for checking the validity + // of ChunkDemuxer::AppendData() calls. + const int64_t kHeaderSize = 256 * 1024; // 256kb starboard::ScopedFile file(path.value().c_str(), kSbFileOpenOnly | kSbFileRead); int64_t bytes_to_read = std::min(kHeaderSize, file.GetSize()); @@ -71,21 +99,14 @@ return buffer; } -// Find the first occurrence of |str| in |data|. If there is no |str| contained -// inside |data|, it returns -1. -off_t FindString(const std::vector<uint8_t>& data, const char* str) { - size_t size_of_str = SbStringGetLength(str); - for (off_t offset = 0; offset + size_of_str < data.size(); ++offset) { - if (SbMemoryCompare(data.data() + offset, str, size_of_str) == 0) { - return offset; - } - } - return -1; +void OnInitSegmentReceived(std::unique_ptr<MediaTracks> tracks) { + SB_UNREFERENCED_PARAMETER(tracks); } } // namespace -FormatGuesstimator::FormatGuesstimator(const std::string& path_or_url) { +FormatGuesstimator::FormatGuesstimator(const std::string& path_or_url, + MediaModule* media_module) { GURL url(path_or_url); if (url.is_valid()) { // If it is a url, assume that it is a progressive video. @@ -96,11 +117,7 @@ if (path.empty() || !SbFileCanOpen(path.value().c_str(), kSbFileRead)) { return; } - if (IsFormat(path_or_url, ".mp4")) { - InitializeAsMp4(path); - } else if (IsFormat(path_or_url, ".webm")) { - InitializeAsWebM(path); - } + InitializeAsAdaptive(path, media_module); } void FormatGuesstimator::InitializeAsProgressive(const GURL& url) { @@ -113,49 +130,79 @@ codecs_ = "avc1.640028, mp4a.40.2"; } -void FormatGuesstimator::InitializeAsMp4(const base::FilePath& path) { +void FormatGuesstimator::InitializeAsAdaptive(const base::FilePath& path, + MediaModule* media_module) { std::vector<uint8_t> header = ReadHeader(path); - if (FindString(header, "ftyp") == -1) { - return; - } - if (FindString(header, "dash") == -1) { - progressive_url_ = net::FilePathToFileURL(path); - mime_ = "video/mp4"; - codecs_ = "avc1.640028, mp4a.40.2"; - return; - } - if (FindString(header, "vide") != -1) { - if (FindString(header, "avcC") != -1) { - adaptive_path_ = path; - mime_ = "video/mp4"; - codecs_ = "avc1.640028"; - return; - } - if (FindString(header, "hvcC") != -1) { - adaptive_path_ = path; - mime_ = "video/mp4"; - codecs_ = "hvc1.1.6.H150.90"; - return; - } - return; - } - if (FindString(header, "soun") != -1) { - adaptive_path_ = path; - mime_ = "audio/mp4"; - codecs_ = "mp4a.40.2"; - return; - } -} -void FormatGuesstimator::InitializeAsWebM(const base::FilePath& path) { - std::vector<uint8_t> header = ReadHeader(path); - adaptive_path_ = path; - if (FindString(header, "OpusHead") == -1) { - mime_ = "video/webm"; - codecs_ = "vp9"; - } else { - mime_ = "audio/webm"; - codecs_ = "opus"; + for (const auto& expected_supported_info : kSupportedTypesAndCodecs) { + DCHECK(mime_.empty()); + DCHECK(codecs_.empty()); + + ChunkDemuxer* chunk_demuxer = NULL; + WebMediaPlayerHelper::ChunkDemuxerOpenCB open_cb = base::Bind( + [](ChunkDemuxer** handle, ChunkDemuxer* chunk_demuxer) -> void { + *handle = chunk_demuxer; + }, + &chunk_demuxer); + // We create a new |web_media_player_helper| every iteration in order to + // obtain a handle to a new |ChunkDemuxer| without any accumulated state as + // a result of previous calls to |AddId| and |AppendData| methods. + WebMediaPlayerHelper web_media_player_helper(media_module, open_cb, + math::Size(1920, 1080)); + + // |chunk_demuxer| will be set when |open_cb| is called asynchronously + // during initialization of |web_media_player_helper|. Wait until it is set + // before proceeding. + while (!chunk_demuxer) { + base::RunLoop().RunUntilIdle(); + } + + const std::string id = "stream"; + if (chunk_demuxer->AddId(id, expected_supported_info.mime, + expected_supported_info.codecs) != + ChunkDemuxer::kOk) { + continue; + } + + chunk_demuxer->SetTracksWatcher(id, base::Bind(OnInitSegmentReceived)); + + base::TimeDelta unused_timestamp; + if (!chunk_demuxer->AppendData(id, header.data(), header.size(), + base::TimeDelta(), media::kInfiniteDuration, + &unused_timestamp)) { + // Failing to |AppendData()| means the chosen format is not the file's + // true format. + continue; + } + + // Succeeding |AppendData()| may be a false positive (i.e. the expected + // configuration does not match with the configuration determined by the + // ChunkDemuxer). To confirm, we check the decoder configuration determined + // by the ChunkDemuxer against the chosen format. + if (auto demuxer_stream = + chunk_demuxer->GetStream(DemuxerStream::Type::AUDIO)) { + const AudioDecoderConfig& decoder_config = + demuxer_stream->audio_decoder_config(); + if (StringToAudioCodec(expected_supported_info.codecs) == + decoder_config.codec()) { + adaptive_path_ = path; + mime_ = expected_supported_info.mime; + codecs_ = expected_supported_info.codecs; + break; + } + continue; + } + auto demuxer_stream = chunk_demuxer->GetStream(DemuxerStream::Type::VIDEO); + DCHECK(demuxer_stream); + const VideoDecoderConfig& decoder_config = + demuxer_stream->video_decoder_config(); + if (StringToVideoCodec(expected_supported_info.codecs) == + decoder_config.codec()) { + adaptive_path_ = path; + mime_ = expected_supported_info.mime; + codecs_ = expected_supported_info.codecs; + break; + } } }
diff --git a/src/cobalt/media/sandbox/format_guesstimator.h b/src/cobalt/media/sandbox/format_guesstimator.h index 4fe4568..dd95e9c 100644 --- a/src/cobalt/media/sandbox/format_guesstimator.h +++ b/src/cobalt/media/sandbox/format_guesstimator.h
@@ -19,6 +19,7 @@ #include "base/files/file_path.h" #include "base/logging.h" +#include "cobalt/media/media_module.h" #include "url/gurl.h" namespace cobalt { @@ -30,7 +31,7 @@ // will be identified as progressive mp4. class FormatGuesstimator { public: - explicit FormatGuesstimator(const std::string& path_or_url); + FormatGuesstimator(const std::string& path_or_url, MediaModule* media_module); bool is_valid() const { return is_progressive() || is_adaptive(); } bool is_progressive() const { return progressive_url_.is_valid(); } @@ -63,8 +64,8 @@ private: void InitializeAsProgressive(const GURL& url); - void InitializeAsMp4(const base::FilePath& path); - void InitializeAsWebM(const base::FilePath& path); + void InitializeAsAdaptive(const base::FilePath& path, + MediaModule* media_module); GURL progressive_url_; base::FilePath adaptive_path_;
diff --git a/src/cobalt/media/sandbox/media_sandbox.cc b/src/cobalt/media/sandbox/media_sandbox.cc index 19e91b0..e749322 100644 --- a/src/cobalt/media/sandbox/media_sandbox.cc +++ b/src/cobalt/media/sandbox/media_sandbox.cc
@@ -53,6 +53,9 @@ render_tree::ResourceProvider* GetResourceProvider() { return renderer_module_->pipeline()->GetResourceProvider(); } + math::Size GetViewportSize() const { + return math::Size(kViewportWidth, kViewportHeight); + } private: void SetupAndSubmitScene(); @@ -156,6 +159,11 @@ return impl_->GetResourceProvider(); } +math::Size MediaSandbox::GetViewportSize() const { + DCHECK(impl_); + return impl_->GetViewportSize(); +} + } // namespace sandbox } // namespace media } // namespace cobalt
diff --git a/src/cobalt/media/sandbox/media_sandbox.h b/src/cobalt/media/sandbox/media_sandbox.h index 881e9c5..22e3f7c 100644 --- a/src/cobalt/media/sandbox/media_sandbox.h +++ b/src/cobalt/media/sandbox/media_sandbox.h
@@ -21,6 +21,7 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cobalt/loader/fetcher_factory.h" +#include "cobalt/math/size.h" #include "cobalt/media/media_module.h" #include "cobalt/render_tree/image.h" #include "cobalt/render_tree/resource_provider.h" @@ -44,6 +45,7 @@ MediaModule* GetMediaModule(); loader::FetcherFactory* GetFetcherFactory(); render_tree::ResourceProvider* resource_provider(); + math::Size GetViewportSize() const; private: class Impl;
diff --git a/src/cobalt/media/sandbox/web_media_player_helper.cc b/src/cobalt/media/sandbox/web_media_player_helper.cc index abda99a..009cc19 100644 --- a/src/cobalt/media/sandbox/web_media_player_helper.cc +++ b/src/cobalt/media/sandbox/web_media_player_helper.cc
@@ -16,6 +16,7 @@ #include "cobalt/media/sandbox/web_media_player_helper.h" +#include "cobalt/math/rect.h" #include "cobalt/media/fetcher_buffered_data_source.h" namespace cobalt { @@ -51,7 +52,6 @@ } std::string SourceURL() const override { return ""; } std::string MaxVideoCapabilities() const override { return std::string(); }; - bool PreferDecodeToTexture() { return true; } void EncryptedMediaInitDataEncountered(EmeInitDataType, const unsigned char*, unsigned) override {} @@ -60,17 +60,23 @@ }; WebMediaPlayerHelper::WebMediaPlayerHelper(MediaModule* media_module, - const ChunkDemuxerOpenCB& open_cb) + const ChunkDemuxerOpenCB& open_cb, + const math::Size& viewport_size) : client_(new WebMediaPlayerClientStub(open_cb)), player_(media_module->CreateWebMediaPlayer(client_)) { player_->SetRate(1.0); player_->LoadMediaSource(); player_->Play(); + + auto set_bounds_cb = player_->GetSetBoundsCB(); + if (!set_bounds_cb.is_null()) { + set_bounds_cb.Run(math::Rect(viewport_size)); + } } WebMediaPlayerHelper::WebMediaPlayerHelper( MediaModule* media_module, loader::FetcherFactory* fetcher_factory, - const GURL& video_url) + const GURL& video_url, const math::Size& viewport_size) : client_(new WebMediaPlayerClientStub), player_(media_module->CreateWebMediaPlayer(client_)) { player_->SetRate(1.0); @@ -80,6 +86,11 @@ loader::kNoCORSMode, loader::Origin())); player_->LoadProgressive(video_url, std::move(data_source)); player_->Play(); + + auto set_bounds_cb = player_->GetSetBoundsCB(); + if (!set_bounds_cb.is_null()) { + set_bounds_cb.Run(math::Rect(viewport_size)); + } } WebMediaPlayerHelper::~WebMediaPlayerHelper() {
diff --git a/src/cobalt/media/sandbox/web_media_player_helper.h b/src/cobalt/media/sandbox/web_media_player_helper.h index 23d7607..62c98b4 100644 --- a/src/cobalt/media/sandbox/web_media_player_helper.h +++ b/src/cobalt/media/sandbox/web_media_player_helper.h
@@ -20,6 +20,7 @@ #include "base/callback.h" #include "cobalt/loader/fetcher_factory.h" +#include "cobalt/math/size.h" #include "cobalt/media/base/video_frame_provider.h" #include "cobalt/media/media_module.h" #include "cobalt/media/player/web_media_player.h" @@ -39,11 +40,12 @@ // Ctor to create an adaptive pipeline. |open_cb| will be called when the // ChunkDemuxer is ready to add source buffers. WebMediaPlayerHelper(MediaModule* media_module, - const ChunkDemuxerOpenCB& chunk_demuxer_open_cb); + const ChunkDemuxerOpenCB& chunk_demuxer_open_cb, + const math::Size& viewport_size); // Ctor to create a progressive pipeline. WebMediaPlayerHelper(MediaModule* media_module, loader::FetcherFactory* fetcher_factory, - const GURL& video_url); + const GURL& video_url, const math::Size& viewport_size); ~WebMediaPlayerHelper(); SbDecodeTarget GetCurrentDecodeTarget() const;
diff --git a/src/cobalt/media/sandbox/web_media_player_sandbox.cc b/src/cobalt/media/sandbox/web_media_player_sandbox.cc index ed0ca18..f50e862 100644 --- a/src/cobalt/media/sandbox/web_media_player_sandbox.cc +++ b/src/cobalt/media/sandbox/web_media_player_sandbox.cc
@@ -114,8 +114,10 @@ base::FilePath(FILE_PATH_LITERAL( "media_source_sandbox_trace.json"))) { if (argc > 1) { - FormatGuesstimator guesstimator1(argv[argc - 1]); - FormatGuesstimator guesstimator2(argv[argc - 2]); + FormatGuesstimator guesstimator1(argv[argc - 1], + media_sandbox_.GetMediaModule()); + FormatGuesstimator guesstimator2(argv[argc - 2], + media_sandbox_.GetMediaModule()); if (!guesstimator1.is_valid()) { SB_LOG(ERROR) << "Invalid path or url: " << argv[argc - 1]; @@ -165,10 +167,10 @@ return; } - player_helper_.reset( - new WebMediaPlayerHelper(media_sandbox_.GetMediaModule(), - base::Bind(&Application::OnChunkDemuxerOpened, - base::Unretained(this)))); + player_helper_.reset(new WebMediaPlayerHelper( + media_sandbox_.GetMediaModule(), + base::Bind(&Application::OnChunkDemuxerOpened, base::Unretained(this)), + media_sandbox_.GetViewportSize())); // |chunk_demuxer_| will be set inside OnChunkDemuxerOpened() // asynchronously during initialization of |player_helper_|. Wait until @@ -217,10 +219,10 @@ return; } - player_helper_.reset( - new WebMediaPlayerHelper(media_sandbox_.GetMediaModule(), - base::Bind(&Application::OnChunkDemuxerOpened, - base::Unretained(this)))); + player_helper_.reset(new WebMediaPlayerHelper( + media_sandbox_.GetMediaModule(), + base::Bind(&Application::OnChunkDemuxerOpened, base::Unretained(this)), + media_sandbox_.GetViewportSize())); // |chunk_demuxer_| will be set inside OnChunkDemuxerOpened() // asynchronously during initialization of |player_helper_|. Wait until @@ -261,7 +263,7 @@ player_helper_.reset(new WebMediaPlayerHelper( media_sandbox_.GetMediaModule(), media_sandbox_.GetFetcherFactory(), - guesstimator.progressive_url())); + guesstimator.progressive_url(), media_sandbox_.GetViewportSize())); player_ = player_helper_->player(); media_sandbox_.RegisterFrameCB(
diff --git a/src/cobalt/media_capture/get_user_media_test.cc b/src/cobalt/media_capture/get_user_media_test.cc index 277379e..a01532f 100644 --- a/src/cobalt/media_capture/get_user_media_test.cc +++ b/src/cobalt/media_capture/get_user_media_test.cc
@@ -14,10 +14,10 @@ #include <memory> -#include "cobalt/media_capture/media_devices.h" - #include "cobalt/dom/dom_settings.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/testing/stub_window.h" +#include "cobalt/media_capture/media_devices.h" #include "cobalt/media_stream/microphone_audio_source.h" #include "cobalt/media_stream/testing/mock_media_stream_audio_source.h" #include "cobalt/script/global_environment.h" @@ -25,8 +25,6 @@ namespace { -const int kMaxDomElementDepth = 8; - std::unique_ptr<cobalt::script::EnvironmentSettings> CreateDOMSettings() { cobalt::dom::DOMSettings::Options options; #if defined(ENABLE_FAKE_MICROPHONE) @@ -34,9 +32,7 @@ #endif // defined(ENABLE_FAKE_MICROPHONE) return std::unique_ptr<cobalt::script::EnvironmentSettings>( - new cobalt::dom::DOMSettings(kMaxDomElementDepth, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, options)); + new cobalt::dom::testing::StubEnvironmentSettings(options)); } } // namespace. @@ -49,9 +45,8 @@ GetUserMediaTest() : window_(CreateDOMSettings()), media_devices_(new MediaDevices( - window_.global_environment()->script_value_factory())) { - media_devices_->SetEnvironmentSettings(window_.environment_settings()); - } + window_.environment_settings(), + window_.global_environment()->script_value_factory())) {} media_stream::MicrophoneAudioSource* GetMicrophoneAudioSource() { return base::polymorphic_downcast<media_stream::MicrophoneAudioSource*>( @@ -131,5 +126,27 @@ media_stream_promise->State()); } +TEST_F(GetUserMediaTest, MultipleMicrophoneSuccessFulfilledPromise) { + media_stream::MediaStreamConstraints constraints; + constraints.set_audio(true); + std::vector<script::Handle<MediaDevices::MediaStreamPromise>> + media_stream_promises; + + for (size_t i = 0; i < 2; ++i) { + media_stream_promises.push_back(media_devices_->GetUserMedia(constraints)); + ASSERT_FALSE(media_stream_promises.back().IsEmpty()); + EXPECT_EQ(cobalt::script::PromiseState::kPending, + media_stream_promises.back()->State()); + media_devices_->OnMicrophoneSuccess(); + } + + media_devices_->audio_source_->StopSource(); + + for (size_t i = 0; i < media_stream_promises.size(); ++i) { + EXPECT_EQ(cobalt::script::PromiseState::kFulfilled, + media_stream_promises[i]->State()); + } +} + } // namespace media_capture } // namespace cobalt
diff --git a/src/cobalt/media_capture/media_devices.cc b/src/cobalt/media_capture/media_devices.cc index 8247a43..7be0d9a 100644 --- a/src/cobalt/media_capture/media_devices.cc +++ b/src/cobalt/media_capture/media_devices.cc
@@ -65,14 +65,18 @@ } // namespace. -MediaDevices::MediaDevices(script::ScriptValueFactory* script_value_factory) - : script_value_factory_(script_value_factory), +MediaDevices::MediaDevices(script::EnvironmentSettings* settings, + script::ScriptValueFactory* script_value_factory) + : dom::EventTarget(settings), + settings_(base::polymorphic_downcast<dom::DOMSettings*>(settings)), + script_value_factory_(script_value_factory), javascript_message_loop_(base::MessageLoop::current()), ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), weak_this_(weak_ptr_factory_.GetWeakPtr()) {} script::Handle<MediaDevices::MediaInfoSequencePromise> MediaDevices::EnumerateDevices() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(settings_); DCHECK(script_value_factory_); script::Handle<MediaInfoSequencePromise> promise = @@ -91,6 +95,7 @@ } script::Handle<MediaDevices::MediaStreamPromise> MediaDevices::GetUserMedia() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(script_value_factory_); script::Handle<MediaDevices::MediaStreamPromise> promise = script_value_factory_->CreateInterfacePromise< @@ -108,6 +113,7 @@ script::Handle<MediaDevices::MediaStreamPromise> MediaDevices::GetUserMedia( const media_stream::MediaStreamConstraints& constraints) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); script::Handle<MediaDevices::MediaStreamPromise> promise = script_value_factory_->CreateInterfacePromise< script::ScriptValueFactory::WrappablePromise>(); @@ -134,6 +140,8 @@ base::Bind(&MediaDevices::OnMicrophoneSuccess, weak_this_), base::Closure(), // TODO: remove this redundant callback. base::Bind(&MediaDevices::OnMicrophoneError, weak_this_)); + audio_source_->SetStopCallback( + base::Bind(&MediaDevices::OnMicrophoneStopped, weak_this_)); } std::unique_ptr<MediaStreamPromiseValue::Reference> promise_reference( @@ -141,13 +149,12 @@ pending_microphone_promises_.push_back(std::move(promise_reference)); if (!pending_microphone_track_) { - pending_microphone_track_ = new media_stream::MediaStreamAudioTrack(); + pending_microphone_track_ = + new media_stream::MediaStreamAudioTrack(settings_); // Starts the source, if needed. Also calls start on the audio track. audio_source_->ConnectToTrack( base::polymorphic_downcast<media_stream::MediaStreamAudioTrack*>( pending_microphone_track_.get())); - audio_source_->SetStopCallback( - base::Bind(&MediaDevices::OnMicrophoneStopped, weak_this_)); } // Step 10, return promise. @@ -156,24 +163,11 @@ void MediaDevices::OnMicrophoneError( speech::MicrophoneManager::MicrophoneError error, std::string message) { - if (javascript_message_loop_->task_runner() != - base::MessageLoop::current()->task_runner()) { - javascript_message_loop_->task_runner()->PostTask( - FROM_HERE, base::Bind(&MediaDevices::OnMicrophoneError, weak_this_, - error, message)); - return; - } - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DLOG(INFO) << "MediaDevices::OnMicrophoneError " << message; - pending_microphone_track_ = nullptr; - audio_source_ = nullptr; - for (auto& promise : pending_microphone_promises_) { - promise->value().Reject( - new dom::DOMException(dom::DOMException::kNotAllowedErr)); - } - pending_microphone_promises_.clear(); + // No special error handling logic besides logging the message above, so just + // delegate to the OnMicrophoneStopped() functionality. + OnMicrophoneStopped(); } void MediaDevices::OnMicrophoneStopped() { @@ -185,8 +179,9 @@ } DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - audio_source_ = nullptr; + DLOG(INFO) << "MediaDevices::OnMicrophoneStopped()"; pending_microphone_track_ = nullptr; + audio_source_ = nullptr; for (auto& promise : pending_microphone_promises_) { promise->value().Reject( @@ -213,7 +208,7 @@ for (auto& promise : pending_microphone_promises_) { promise->value().Resolve( - base::WrapRefCounted(new MediaStream(audio_tracks))); + base::WrapRefCounted(new MediaStream(settings_, audio_tracks))); } pending_microphone_promises_.clear(); }
diff --git a/src/cobalt/media_capture/media_devices.h b/src/cobalt/media_capture/media_devices.h index 8a0c84c..4ec1d39 100644 --- a/src/cobalt/media_capture/media_devices.h +++ b/src/cobalt/media_capture/media_devices.h
@@ -52,17 +52,14 @@ script::Promise<script::ScriptValueFactory::WrappablePromise>; using MediaStreamPromiseValue = script::ScriptValue<MediaStreamPromise>; - explicit MediaDevices(script::ScriptValueFactory* script_value_factory); + explicit MediaDevices(script::EnvironmentSettings* settings, + script::ScriptValueFactory* script_value_factory); script::Handle<MediaInfoSequencePromise> EnumerateDevices(); script::Handle<MediaStreamPromise> GetUserMedia(); script::Handle<MediaStreamPromise> GetUserMedia( const media_stream::MediaStreamConstraints& constraints); - void SetEnvironmentSettings(script::EnvironmentSettings* settings) { - settings_ = base::polymorphic_downcast<dom::DOMSettings*>(settings); - } - DEFINE_WRAPPABLE_TYPE(MediaDevices); private: @@ -71,10 +68,13 @@ FRIEND_TEST_ALL_PREFIXES(GetUserMediaTest, MicrophoneStoppedRejectedPromise); FRIEND_TEST_ALL_PREFIXES(GetUserMediaTest, MicrophoneErrorRejectedPromise); FRIEND_TEST_ALL_PREFIXES(GetUserMediaTest, MicrophoneSuccessFulfilledPromise); + FRIEND_TEST_ALL_PREFIXES(GetUserMediaTest, + MultipleMicrophoneSuccessFulfilledPromise); ~MediaDevices() override = default; - // Stop callback used with MediaStreamAudioSource. + // Stop callback used with MediaStreamAudioSource, and the OnMicrophoneError + // logic will also call in to this. void OnMicrophoneStopped(); // Callbacks used with MicrophoneManager. @@ -82,8 +82,8 @@ std::string message); void OnMicrophoneSuccess(); + dom::DOMSettings* settings_; script::ScriptValueFactory* script_value_factory_; - dom::DOMSettings* settings_ = nullptr; scoped_refptr<media_stream::MediaStreamAudioSource> audio_source_;
diff --git a/src/cobalt/media_capture/media_recorder.cc b/src/cobalt/media_capture/media_recorder.cc index 77455bf..3a015f0 100644 --- a/src/cobalt/media_capture/media_recorder.cc +++ b/src/cobalt/media_capture/media_recorder.cc
@@ -213,8 +213,10 @@ // Step 5.5 from start(), defined at: // https://www.w3.org/TR/mediastream-recording/#mediarecorder-methods if (new_state == media_stream::MediaStreamTrack::kReadyStateEnded) { - audio_encoder_->Finish(base::TimeTicks::Now()); - audio_encoder_.reset(); + if (audio_encoder_) { + audio_encoder_->Finish(base::TimeTicks::Now()); + audio_encoder_.reset(); + } StopRecording(); stream_ = nullptr; } @@ -225,7 +227,8 @@ const scoped_refptr<media_stream::MediaStream>& stream, const MediaRecorderOptions& options, script::ExceptionState* exception_state) - : settings_(settings), + : dom::EventTarget(settings), + settings_(settings), stream_(stream), javascript_message_loop_(base::MessageLoop::current()->task_runner()), ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
diff --git a/src/cobalt/media_capture/media_recorder_test.cc b/src/cobalt/media_capture/media_recorder_test.cc index 6a62f2c..6317bfa 100644 --- a/src/cobalt/media_capture/media_recorder_test.cc +++ b/src/cobalt/media_capture/media_recorder_test.cc
@@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/media_capture/media_recorder.h" +#include <memory> + #include "cobalt/dom/dom_exception.h" #include "cobalt/dom/testing/mock_event_listener.h" #include "cobalt/dom/testing/stub_window.h" @@ -28,20 +28,19 @@ #include "cobalt/script/testing/mock_exception_state.h" #include "testing/gtest/include/gtest/gtest.h" +using cobalt::dom::EventListener; +using cobalt::dom::testing::MockEventListener; +using cobalt::script::testing::FakeScriptValue; +using cobalt::script::testing::MockExceptionState; using ::testing::_; using ::testing::Eq; using ::testing::Pointee; using ::testing::Property; using ::testing::SaveArg; using ::testing::StrictMock; -using cobalt::dom::EventListener; -using cobalt::dom::testing::MockEventListener; -using cobalt::script::testing::MockExceptionState; -using cobalt::script::testing::FakeScriptValue; namespace { -void PushData( - const scoped_refptr<cobalt::media_capture::MediaRecorder>& media_recorder) { +void PushData(cobalt::media_capture::MediaRecorder* media_recorder) { const int kSampleRate = 16000; cobalt::media_stream::AudioParameters params(1, kSampleRate, 16); media_recorder->OnSetFormat(params); @@ -87,13 +86,14 @@ class MediaRecorderTest : public ::testing::Test { protected: MediaRecorderTest() { - audio_track_ = new StrictMock<media_stream::MockMediaStreamAudioTrack>(); + audio_track_ = new StrictMock<media_stream::MockMediaStreamAudioTrack>( + stub_window_.environment_settings()); auto audio_track = base::WrapRefCounted(audio_track_); media_stream::MediaStream::TrackSequences sequences; sequences.push_back(audio_track); audio_track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/))); - auto stream = - base::WrapRefCounted(new media_stream::MediaStream(sequences)); + auto stream = base::WrapRefCounted(new media_stream::MediaStream( + stub_window_.environment_settings(), sequences)); media_source_ = new StrictMock<media_stream::FakeMediaStreamAudioSource>(); EXPECT_CALL(*media_source_, EnsureSourceIsStarted()); EXPECT_CALL(*media_source_, EnsureSourceIsStopped()); @@ -228,9 +228,9 @@ // member functions with base::Unretained() or weak pointer. // Creates media_recorder_ref just to make it clear that no copy happened // during base::Bind(). - const scoped_refptr<MediaRecorder>& media_recorder_ref = media_recorder_; t.message_loop()->task_runner()->PostBlockingTask( - FROM_HERE, base::Bind(&PushData, media_recorder_ref)); + FROM_HERE, + base::Bind(&PushData, base::Unretained(media_recorder_.get()))); t.Stop(); base::RunLoop().RunUntilIdle();
diff --git a/src/cobalt/media_stream/media_stream.h b/src/cobalt/media_stream/media_stream.h index 13f9a44..b0c658c 100644 --- a/src/cobalt/media_stream/media_stream.h +++ b/src/cobalt/media_stream/media_stream.h
@@ -31,9 +31,11 @@ using TrackSequences = script::Sequence<scoped_refptr<MediaStreamTrack>>; // Constructors. - MediaStream() = default; + explicit MediaStream(script::EnvironmentSettings* settings) + : dom::EventTarget(settings) {} - explicit MediaStream(TrackSequences tracks) : tracks_(std::move(tracks)) {} + MediaStream(script::EnvironmentSettings* settings, TrackSequences tracks) + : dom::EventTarget(settings), tracks_(std::move(tracks)) {} // Functions. script::Sequence<scoped_refptr<MediaStreamTrack>>& GetAudioTracks() {
diff --git a/src/cobalt/media_stream/media_stream.idl b/src/cobalt/media_stream/media_stream.idl index 8170bd5..781af4d 100644 --- a/src/cobalt/media_stream/media_stream.idl +++ b/src/cobalt/media_stream/media_stream.idl
@@ -14,8 +14,10 @@ // Implements a subset of the specification at: // https://www.w3.org/TR/mediacapture-streams/#dom-mediastream -[Exposed=Window, - Constructor +[ + Exposed=Window, + Constructor, + ConstructorCallWith=EnvironmentSettings, ] interface MediaStream : EventTarget { sequence<MediaStreamTrack> getAudioTracks();
diff --git a/src/cobalt/media_stream/media_stream_audio_source.cc b/src/cobalt/media_stream/media_stream_audio_source.cc index b4d359d..6c20d49 100644 --- a/src/cobalt/media_stream/media_stream_audio_source.cc +++ b/src/cobalt/media_stream/media_stream_audio_source.cc
@@ -80,8 +80,11 @@ void MediaStreamAudioSource::DoStopSource() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - EnsureSourceIsStopped(); is_stopped_ = true; + + // This function might result in the destruction of this object, so be + // careful not to reference members after this call. + EnsureSourceIsStopped(); } void MediaStreamAudioSource::StopAudioDeliveryTo(MediaStreamAudioTrack* track) {
diff --git a/src/cobalt/media_stream/media_stream_audio_source_test.cc b/src/cobalt/media_stream/media_stream_audio_source_test.cc index 9f16c9d..f526bba 100644 --- a/src/cobalt/media_stream/media_stream_audio_source_test.cc +++ b/src/cobalt/media_stream/media_stream_audio_source_test.cc
@@ -16,12 +16,12 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "cobalt/dom/testing/stub_environment_settings.h" +#include "cobalt/media/base/shell_audio_bus.h" #include "cobalt/media_stream/media_stream_audio_track.h" #include "cobalt/media_stream/testing/mock_media_stream_audio_source.h" #include "testing/gtest/include/gtest/gtest.h" -#include "cobalt/media/base/shell_audio_bus.h" - using ::testing::_; using ::testing::Return; using ::testing::StrictMock; @@ -41,9 +41,10 @@ public: MediaStreamAudioSourceTest() : audio_source_(new StrictMock<MockMediaStreamAudioSource>()), - track_(new MediaStreamAudioTrack()) {} + track_(new MediaStreamAudioTrack(&environment_settings_)) {} protected: + dom::testing::StubEnvironmentSettings environment_settings_; scoped_refptr<StrictMock<MockMediaStreamAudioSource>> audio_source_; scoped_refptr<MediaStreamAudioTrack> track_; }; @@ -102,7 +103,8 @@ // Adding a track ensures that the source is started. audio_source_->ConnectToTrack(track_); - auto track2 = base::WrapRefCounted(new MediaStreamAudioTrack()); + auto track2 = + base::WrapRefCounted(new MediaStreamAudioTrack(&environment_settings_)); audio_source_->ConnectToTrack(track2); audio_source_->StopSource(); }
diff --git a/src/cobalt/media_stream/media_stream_audio_track.h b/src/cobalt/media_stream/media_stream_audio_track.h index 7a71011..b7d7708 100644 --- a/src/cobalt/media_stream/media_stream_audio_track.h +++ b/src/cobalt/media_stream/media_stream_audio_track.h
@@ -19,13 +19,13 @@ #include "base/strings/string_piece.h" #include "base/threading/thread_checker.h" #include "cobalt/dom/event_target.h" +#include "cobalt/media/base/shell_audio_bus.h" #include "cobalt/media_stream/audio_parameters.h" #include "cobalt/media_stream/media_stream_audio_deliverer.h" #include "cobalt/media_stream/media_stream_audio_sink.h" #include "cobalt/media_stream/media_stream_track.h" #include "cobalt/media_stream/media_track_settings.h" - -#include "cobalt/media/base/shell_audio_bus.h" +#include "cobalt/script/environment_settings.h" namespace cobalt { @@ -51,7 +51,8 @@ return settings; } typedef media::ShellAudioBus ShellAudioBus; - MediaStreamAudioTrack() = default; + explicit MediaStreamAudioTrack(script::EnvironmentSettings* settings) + : MediaStreamTrack(settings) {} ~MediaStreamAudioTrack() override { Stop(); }
diff --git a/src/cobalt/media_stream/media_stream_audio_track_test.cc b/src/cobalt/media_stream/media_stream_audio_track_test.cc index 1f7e052..8fc542a 100644 --- a/src/cobalt/media_stream/media_stream_audio_track_test.cc +++ b/src/cobalt/media_stream/media_stream_audio_track_test.cc
@@ -15,12 +15,12 @@ #include "cobalt/media_stream/media_stream_audio_track.h" #include "base/bind_helpers.h" +#include "cobalt/dom/testing/stub_environment_settings.h" +#include "cobalt/media/base/shell_audio_bus.h" #include "cobalt/media_stream/media_stream_audio_deliverer.h" #include "cobalt/media_stream/testing/mock_media_stream_audio_sink.h" #include "testing/gtest/include/gtest/gtest.h" -#include "cobalt/media/base/shell_audio_bus.h" - using ::testing::_; using ::testing::StrictMock; @@ -41,7 +41,13 @@ // This fixture is created, so it can be added as a friend to // |MediaStreamAudioTrack|. This enables calling a private method // called|Start()| on the track, without instantiating an audio source. -class MediaStreamAudioTrackTest : public testing::Test {}; +class MediaStreamAudioTrackTest : public testing::Test { + public: + MediaStreamAudioTrackTest() = default; + + protected: + dom::testing::StubEnvironmentSettings environment_settings_; +}; TEST_F(MediaStreamAudioTrackTest, OnSetFormatAndData) { media_stream::AudioParameters expected_params(kChannelCount, kSampleRate, @@ -55,7 +61,8 @@ EXPECT_CALL(mock_sink, OnReadyStateChanged( MediaStreamTrack::ReadyState::kReadyStateEnded)); - scoped_refptr<MediaStreamAudioTrack> track = new MediaStreamAudioTrack(); + scoped_refptr<MediaStreamAudioTrack> track = + new MediaStreamAudioTrack(&environment_settings_); track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/))); track->AddSink(&mock_sink); @@ -86,7 +93,8 @@ EXPECT_CALL(mock_sink2, OnReadyStateChanged( MediaStreamTrack::ReadyState::kReadyStateEnded)); - scoped_refptr<MediaStreamAudioTrack> track = new MediaStreamAudioTrack(); + scoped_refptr<MediaStreamAudioTrack> track = + new MediaStreamAudioTrack(&environment_settings_); track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/))); track->AddSink(&mock_sink1); track->AddSink(&mock_sink2); @@ -118,8 +126,10 @@ EXPECT_CALL(mock_sink2, OnReadyStateChanged( MediaStreamTrack::ReadyState::kReadyStateEnded)); - scoped_refptr<MediaStreamAudioTrack> track1 = new MediaStreamAudioTrack(); - scoped_refptr<MediaStreamAudioTrack> track2 = new MediaStreamAudioTrack(); + scoped_refptr<MediaStreamAudioTrack> track1 = + new MediaStreamAudioTrack(&environment_settings_); + scoped_refptr<MediaStreamAudioTrack> track2 = + new MediaStreamAudioTrack(&environment_settings_); track1->Start(base::Closure(base::Bind([]() {} /*Do nothing*/))); track2->Start(base::Closure(base::Bind([]() {} /*Do nothing*/))); track1->AddSink(&mock_sink1); @@ -146,7 +156,8 @@ // is delivered. StrictMock<MockMediaStreamAudioSink> mock_sink; - scoped_refptr<MediaStreamAudioTrack> track = new MediaStreamAudioTrack(); + scoped_refptr<MediaStreamAudioTrack> track = + new MediaStreamAudioTrack(&environment_settings_); track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/))); track->AddSink(&mock_sink); @@ -165,7 +176,8 @@ TEST_F(MediaStreamAudioTrackTest, Stop) { StrictMock<MockMediaStreamAudioSink> mock_sink; - scoped_refptr<MediaStreamAudioTrack> track = new MediaStreamAudioTrack(); + scoped_refptr<MediaStreamAudioTrack> track = + new MediaStreamAudioTrack(&environment_settings_); track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/))); track->AddSink(&mock_sink); @@ -184,7 +196,8 @@ } TEST_F(MediaStreamAudioTrackTest, ReadyStateEndedNotifyIfAlreadyStopped) { - scoped_refptr<MediaStreamAudioTrack> track = new MediaStreamAudioTrack(); + scoped_refptr<MediaStreamAudioTrack> track = + new MediaStreamAudioTrack(&environment_settings_); track->Start(base::Closure(base::Bind([]() {} /*Do nothing*/))); track->Stop(); @@ -195,7 +208,8 @@ } TEST_F(MediaStreamAudioTrackTest, ReadyStateEndedNotifyIfNeverStarted) { - scoped_refptr<MediaStreamAudioTrack> track = new MediaStreamAudioTrack(); + scoped_refptr<MediaStreamAudioTrack> track = + new MediaStreamAudioTrack(&environment_settings_); StrictMock<MockMediaStreamAudioSink> mock_sink; EXPECT_CALL(mock_sink, OnReadyStateChanged(
diff --git a/src/cobalt/media_stream/media_stream_test.cc b/src/cobalt/media_stream/media_stream_test.cc index e8e958c..1d09d37 100644 --- a/src/cobalt/media_stream/media_stream_test.cc +++ b/src/cobalt/media_stream/media_stream_test.cc
@@ -15,6 +15,7 @@ #include "cobalt/media_stream/media_stream.h" #include "base/memory/ref_counted.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "testing/gtest/include/gtest/gtest.h" namespace cobalt { @@ -22,9 +23,10 @@ class MediaStreamTest : public ::testing::Test { public: - MediaStreamTest() : media_stream_(new MediaStream()) {} + MediaStreamTest() : media_stream_(new MediaStream(&environment_settings_)) {} protected: + dom::testing::StubEnvironmentSettings environment_settings_; scoped_refptr<MediaStream> media_stream_; };
diff --git a/src/cobalt/media_stream/media_stream_track.h b/src/cobalt/media_stream/media_stream_track.h index 514d55d..8b27a6d 100644 --- a/src/cobalt/media_stream/media_stream_track.h +++ b/src/cobalt/media_stream/media_stream_track.h
@@ -19,6 +19,7 @@ #include "base/strings/string_piece.h" #include "cobalt/dom/event_target.h" #include "cobalt/media_stream/media_track_settings.h" +#include "cobalt/script/environment_settings.h" #include "starboard/common/mutex.h" namespace cobalt { @@ -33,7 +34,8 @@ kReadyStateEnded, }; - MediaStreamTrack() = default; + explicit MediaStreamTrack(script::EnvironmentSettings* settings) + : EventTarget(settings) {} // Function exposed to JavaScript via IDL. const MediaTrackSettings& GetSettings() const {
diff --git a/src/cobalt/media_stream/microphone_audio_source.cc b/src/cobalt/media_stream/microphone_audio_source.cc index 614e894..291acc5 100644 --- a/src/cobalt/media_stream/microphone_audio_source.cc +++ b/src/cobalt/media_stream/microphone_audio_source.cc
@@ -42,31 +42,35 @@ std::unique_ptr<cobalt::speech::Microphone> MicrophoneAudioSource::CreateMicrophone( const cobalt::speech::Microphone::Options& options, int buffer_size_bytes) { -#if defined(ENABLE_FAKE_MICROPHONE) +#if !defined(ENABLE_MICROPHONE_IDL) + SB_UNREFERENCED_PARAMETER(options); SB_UNREFERENCED_PARAMETER(buffer_size_bytes); + return std::unique_ptr<speech::Microphone>(); +#else + std::unique_ptr<speech::Microphone> mic; + +#if defined(ENABLE_FAKE_MICROPHONE) if (options.enable_fake_microphone) { - return std::unique_ptr<speech::Microphone>( - new speech::MicrophoneFake(options)); + mic.reset(new speech::MicrophoneFake(options)); } #else SB_UNREFERENCED_PARAMETER(options); #endif // defined(ENABLE_FAKE_MICROPHONE) - std::unique_ptr<speech::Microphone> mic; + if (!mic) { + mic.reset(new speech::MicrophoneStarboard( + speech::MicrophoneStarboard::kDefaultSampleRate, buffer_size_bytes)); + } -#if defined(ENABLE_MICROPHONE_IDL) - mic.reset(new speech::MicrophoneStarboard( - speech::MicrophoneStarboard::kDefaultSampleRate, buffer_size_bytes)); - - AudioParameters params( - 1, speech::MicrophoneStarboard::kDefaultSampleRate, - speech::MicrophoneStarboard::kSbMicrophoneSampleSizeInBytes * 8); - SetFormat(params); -#else - SB_UNREFERENCED_PARAMETER(buffer_size_bytes); -#endif // defined(ENABLE_MICROPHONE_IDL) + if (mic) { + AudioParameters params( + 1, speech::MicrophoneStarboard::kDefaultSampleRate, + speech::MicrophoneStarboard::kSbMicrophoneSampleSizeInBytes * 8); + SetFormat(params); + } return mic; +#endif // defined(ENABLE_MICROPHONE_IDL) } MicrophoneAudioSource::MicrophoneAudioSource(
diff --git a/src/cobalt/media_stream/testing/mock_media_stream_audio_track.h b/src/cobalt/media_stream/testing/mock_media_stream_audio_track.h index 8d4c6cb..5a80ab4 100644 --- a/src/cobalt/media_stream/testing/mock_media_stream_audio_track.h +++ b/src/cobalt/media_stream/testing/mock_media_stream_audio_track.h
@@ -16,7 +16,7 @@ #define COBALT_MEDIA_STREAM_TESTING_MOCK_MEDIA_STREAM_AUDIO_TRACK_H_ #include "cobalt/media_stream/media_stream_audio_track.h" - +#include "cobalt/script/environment_settings.h" #include "testing/gmock/include/gmock/gmock.h" namespace cobalt { @@ -24,6 +24,8 @@ class MockMediaStreamAudioTrack : public MediaStreamAudioTrack { public: + explicit MockMediaStreamAudioTrack(script::EnvironmentSettings* settings) + : MediaStreamAudioTrack(settings) {} MOCK_METHOD0(Stop, void()); };
diff --git a/src/cobalt/network/local_network.cc b/src/cobalt/network/local_network.cc index 279aa3b..862eb19 100644 --- a/src/cobalt/network/local_network.cc +++ b/src/cobalt/network/local_network.cc
@@ -46,12 +46,15 @@ return CompareNBytesOfAddress(ip, source_address, netmask, net::IPAddress::kIPv4AddressSize); case kSbSocketAddressTypeIpv6: -#if SB_HAS(IPV6) - return CompareNBytesOfAddress(ip, source_address, netmask, - net::IPAddress::kIPv6AddressSize); -#else // SB_HAS(IPV6) +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION || SB_HAS(IPV6) +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION + if (SbSocketIsIpv6Supported()) +#endif + return CompareNBytesOfAddress(ip, source_address, netmask, + net::IPAddress::kIPv6AddressSize); +#endif + default: NOTREACHED() << "Invalid IP type " << ip.type; -#endif // SB_HAS(IPV6) } return false; } @@ -85,7 +88,12 @@ return true; } } -#if SB_HAS(IPV6) +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION + if (!SbSocketIsIpv6Supported()) { + return false; + } +#endif +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION || SB_HAS(IPV6) if (ip.type == kSbSocketAddressTypeIpv6) { // Unique Local Addresses for IPv6 are _effectively_ fd00::/8. // See https://tools.ietf.org/html/rfc4193#section-3 for details.
diff --git a/src/cobalt/network/network_delegate.cc b/src/cobalt/network/network_delegate.cc index 739c873..79c1b3a 100644 --- a/src/cobalt/network/network_delegate.cc +++ b/src/cobalt/network/network_delegate.cc
@@ -59,11 +59,14 @@ const char* valid_spec_cstr = valid_spec.c_str(); std::string host; -#if SB_HAS(IPV6) - host = url.HostNoBrackets(); -#else + // This will be our host string if we are not using IPV6. host.append(valid_spec_cstr + parsed.host.begin, valid_spec_cstr + parsed.host.begin + parsed.host.len); +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION || SB_HAS(IPV6) +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION + if (SbSocketIsIpv6Supported()) +#endif + host = url.HostNoBrackets(); #endif if (net::HostStringIsLocalhost(host)) { return net::OK;
diff --git a/src/cobalt/network/socket_address_parser.cc b/src/cobalt/network/socket_address_parser.cc index 93de247..518d0a7 100644 --- a/src/cobalt/network/socket_address_parser.cc +++ b/src/cobalt/network/socket_address_parser.cc
@@ -54,7 +54,12 @@ return true; case url::CanonHostInfo::NEUTRAL: -#if SB_HAS(IPV6) +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION + if (!SbSocketIsIpv6Supported()) { + return false; + } +#endif +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION || SB_HAS(IPV6) unsigned char address_v6[net::IPAddress::kIPv6AddressSize]; if (!url::IPv6AddressToNumber(spec, host_component, address_v6)) { break;
diff --git a/src/cobalt/renderer/backend/blitter/blitter_backend.gyp b/src/cobalt/renderer/backend/blitter/blitter_backend.gyp new file mode 100644 index 0000000..d32ffbc --- /dev/null +++ b/src/cobalt/renderer/backend/blitter/blitter_backend.gyp
@@ -0,0 +1,39 @@ +# Copyright 2016 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. + +{ + 'targets': [ + { + 'target_name': 'blitter_backend', + 'type': 'static_library', + + # Sets up renderer::backend to use a Starboard Blitter API implementation. + 'sources': [ + 'display.cc', + 'display.h', + 'graphics_context.cc', + 'graphics_context.h', + 'graphics_system.cc', + 'graphics_system.h', + 'surface_render_target.cc', + 'surface_render_target.h', + 'render_target.h', + ], + + 'dependencies': [ + '<(DEPTH)/starboard/starboard.gyp:starboard', + ], + }, + ], +}
diff --git a/src/cobalt/renderer/backend/blitter/blitter_backend.gypi b/src/cobalt/renderer/backend/blitter/blitter_backend.gypi deleted file mode 100644 index de48561..0000000 --- a/src/cobalt/renderer/backend/blitter/blitter_backend.gypi +++ /dev/null
@@ -1,32 +0,0 @@ -# Copyright 2016 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. - -{ - # Sets up renderer::backend to use a Starboard Blitter API implementation. - 'sources': [ - 'display.cc', - 'display.h', - 'graphics_context.cc', - 'graphics_context.h', - 'graphics_system.cc', - 'graphics_system.h', - 'surface_render_target.cc', - 'surface_render_target.h', - 'render_target.h', - ], - - 'dependencies': [ - '<(DEPTH)/starboard/starboard.gyp:starboard', - ], -}
diff --git a/src/cobalt/renderer/backend/blitter/display.cc b/src/cobalt/renderer/backend/blitter/display.cc index b2f5ac2..2c98837 100644 --- a/src/cobalt/renderer/backend/blitter/display.cc +++ b/src/cobalt/renderer/backend/blitter/display.cc
@@ -19,7 +19,7 @@ #include "cobalt/renderer/backend/blitter/render_target.h" #include "cobalt/system_window/system_window.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -97,4 +97,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/backend/blitter/display.h b/src/cobalt/renderer/backend/blitter/display.h index f0bba18..f48b7b5 100644 --- a/src/cobalt/renderer/backend/blitter/display.h +++ b/src/cobalt/renderer/backend/blitter/display.h
@@ -21,7 +21,7 @@ #include "cobalt/renderer/backend/graphics_system.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -44,6 +44,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_BACKEND_BLITTER_DISPLAY_H_
diff --git a/src/cobalt/renderer/backend/blitter/graphics_context.cc b/src/cobalt/renderer/backend/blitter/graphics_context.cc index b7acfba..a762d69 100644 --- a/src/cobalt/renderer/backend/blitter/graphics_context.cc +++ b/src/cobalt/renderer/backend/blitter/graphics_context.cc
@@ -23,7 +23,7 @@ #include "cobalt/renderer/backend/blitter/surface_render_target.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -90,4 +90,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/backend/blitter/graphics_context.h b/src/cobalt/renderer/backend/blitter/graphics_context.h index b2a5189..4dee93f 100644 --- a/src/cobalt/renderer/backend/blitter/graphics_context.h +++ b/src/cobalt/renderer/backend/blitter/graphics_context.h
@@ -23,7 +23,7 @@ #include "cobalt/renderer/backend/graphics_context.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -52,6 +52,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_BACKEND_BLITTER_GRAPHICS_CONTEXT_H_
diff --git a/src/cobalt/renderer/backend/blitter/graphics_system.cc b/src/cobalt/renderer/backend/blitter/graphics_system.cc index 6ac4141..96938b3 100644 --- a/src/cobalt/renderer/backend/blitter/graphics_system.cc +++ b/src/cobalt/renderer/backend/blitter/graphics_system.cc
@@ -19,7 +19,7 @@ #include "cobalt/renderer/backend/blitter/display.h" #include "cobalt/renderer/backend/blitter/graphics_context.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -47,4 +47,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/backend/blitter/graphics_system.h b/src/cobalt/renderer/backend/blitter/graphics_system.h index 3a02412..636f676 100644 --- a/src/cobalt/renderer/backend/blitter/graphics_system.h +++ b/src/cobalt/renderer/backend/blitter/graphics_system.h
@@ -22,7 +22,7 @@ #include "starboard/blitter.h" #include "starboard/common/optional.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -50,6 +50,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_BACKEND_BLITTER_GRAPHICS_SYSTEM_H_
diff --git a/src/cobalt/renderer/backend/blitter/render_target.h b/src/cobalt/renderer/backend/blitter/render_target.h index 9efba08..2f2db2d 100644 --- a/src/cobalt/renderer/backend/blitter/render_target.h +++ b/src/cobalt/renderer/backend/blitter/render_target.h
@@ -18,7 +18,7 @@ #include "cobalt/renderer/backend/render_target.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -42,6 +42,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_BACKEND_BLITTER_RENDER_TARGET_H_
diff --git a/src/cobalt/renderer/backend/blitter/surface_render_target.cc b/src/cobalt/renderer/backend/blitter/surface_render_target.cc index 3f507d6..6cb8bab 100644 --- a/src/cobalt/renderer/backend/blitter/surface_render_target.cc +++ b/src/cobalt/renderer/backend/blitter/surface_render_target.cc
@@ -16,7 +16,7 @@ #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -59,4 +59,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/backend/blitter/surface_render_target.h b/src/cobalt/renderer/backend/blitter/surface_render_target.h index 3ed6093..920e948 100644 --- a/src/cobalt/renderer/backend/blitter/surface_render_target.h +++ b/src/cobalt/renderer/backend/blitter/surface_render_target.h
@@ -19,7 +19,7 @@ #include "cobalt/renderer/backend/blitter/render_target.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -62,6 +62,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_BACKEND_BLITTER_SURFACE_RENDER_TARGET_H_
diff --git a/src/cobalt/renderer/backend/egl/display.cc b/src/cobalt/renderer/backend/egl/display.cc index 3ce7aba..af436ad 100644 --- a/src/cobalt/renderer/backend/egl/display.cc +++ b/src/cobalt/renderer/backend/egl/display.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/backend/egl/display.h" #include "cobalt/renderer/backend/egl/render_target.h" @@ -87,3 +90,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/egl_backend.gyp b/src/cobalt/renderer/backend/egl/egl_backend.gyp new file mode 100644 index 0000000..5c90301 --- /dev/null +++ b/src/cobalt/renderer/backend/egl/egl_backend.gyp
@@ -0,0 +1,63 @@ +# Copyright 2014 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. + +{ + 'targets': [ + { + 'target_name': 'egl_backend', + 'type': 'static_library', + + 'sources': [ + 'display.cc', + 'display.h', + 'framebuffer.h', + 'framebuffer.cc', + 'framebuffer_render_target.h', + 'graphics_context.cc', + 'graphics_context.h', + 'graphics_system.cc', + 'graphics_system.h', + 'pbuffer_render_target.cc', + 'pbuffer_render_target.h', + 'render_target.h', + 'resource_context.cc', + 'resource_context.h', + 'texture.cc', + 'texture.h', + 'texture_data.cc', + 'texture_data.h', + 'texture_data_cpu.cc', + 'texture_data_cpu.h', + 'texture_data_pbo.cc', + 'texture_data_pbo.h', + 'utils.cc', + 'utils.h', + ], + 'defines': [ + 'COBALT_EGL_SWAP_INTERVAL=<(cobalt_egl_swap_interval)', + ], + 'dependencies': [ + '<(DEPTH)/starboard/starboard_headers_only.gyp:starboard_headers_only', + ], + + 'conditions': [ + ['render_dirty_region_only==1', { + 'defines': [ + 'COBALT_RENDER_DIRTY_REGION_ONLY', + ], + }], + ], + }, + ], +}
diff --git a/src/cobalt/renderer/backend/egl/egl_backend.gypi b/src/cobalt/renderer/backend/egl/egl_backend.gypi deleted file mode 100644 index 545a7ef..0000000 --- a/src/cobalt/renderer/backend/egl/egl_backend.gypi +++ /dev/null
@@ -1,56 +0,0 @@ -# Copyright 2014 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. - -{ - 'sources': [ - 'display.cc', - 'display.h', - 'framebuffer.h', - 'framebuffer.cc', - 'framebuffer_render_target.h', - 'graphics_context.cc', - 'graphics_context.h', - 'graphics_system.cc', - 'graphics_system.h', - 'pbuffer_render_target.cc', - 'pbuffer_render_target.h', - 'render_target.h', - 'resource_context.cc', - 'resource_context.h', - 'texture.cc', - 'texture.h', - 'texture_data.cc', - 'texture_data.h', - 'texture_data_cpu.cc', - 'texture_data_cpu.h', - 'texture_data_pbo.cc', - 'texture_data_pbo.h', - 'utils.cc', - 'utils.h', - ], - 'defines': [ - 'COBALT_EGL_SWAP_INTERVAL=<(cobalt_egl_swap_interval)', - ], - 'dependencies': [ - '<(DEPTH)/starboard/starboard_headers_only.gyp:starboard_headers_only', - ], - - 'conditions': [ - ['render_dirty_region_only==1', { - 'defines': [ - 'COBALT_RENDER_DIRTY_REGION_ONLY', - ], - }], - ], -}
diff --git a/src/cobalt/renderer/backend/egl/framebuffer.cc b/src/cobalt/renderer/backend/egl/framebuffer.cc index f613922..dd8c2d1 100644 --- a/src/cobalt/renderer/backend/egl/framebuffer.cc +++ b/src/cobalt/renderer/backend/egl/framebuffer.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/backend/egl/framebuffer.h" #include "base/logging.h" @@ -145,3 +148,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.cc b/src/cobalt/renderer/backend/egl/graphics_context.cc index b6bd72c..94a6269 100644 --- a/src/cobalt/renderer/backend/egl/graphics_context.cc +++ b/src/cobalt/renderer/backend/egl/graphics_context.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include <algorithm> #include <memory> @@ -560,3 +563,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/graphics_system.cc b/src/cobalt/renderer/backend/egl/graphics_system.cc index 8e48f7e..16e9633 100644 --- a/src/cobalt/renderer/backend/egl/graphics_system.cc +++ b/src/cobalt/renderer/backend/egl/graphics_system.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include <memory> #include "cobalt/renderer/backend/egl/graphics_system.h" @@ -276,3 +279,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc b/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc index 6cc0f59..50ff757 100644 --- a/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc +++ b/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/backend/egl/pbuffer_render_target.h" #include "cobalt/renderer/backend/egl/utils.h" @@ -63,3 +66,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/resource_context.cc b/src/cobalt/renderer/backend/egl/resource_context.cc index 329e0ca..b8286fd 100644 --- a/src/cobalt/renderer/backend/egl/resource_context.cc +++ b/src/cobalt/renderer/backend/egl/resource_context.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/backend/egl/resource_context.h" #include "base/bind.h" @@ -91,3 +94,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/texture.cc b/src/cobalt/renderer/backend/egl/texture.cc index 58cbf7a..32d40ce 100644 --- a/src/cobalt/renderer/backend/egl/texture.cc +++ b/src/cobalt/renderer/backend/egl/texture.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/backend/egl/texture.h" #include "base/bind.h" @@ -136,3 +139,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/texture_data.cc b/src/cobalt/renderer/backend/egl/texture_data.cc index 9613b0b..8d78f58 100644 --- a/src/cobalt/renderer/backend/egl/texture_data.cc +++ b/src/cobalt/renderer/backend/egl/texture_data.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/backend/egl/texture_data.h" #include "cobalt/renderer/backend/egl/utils.h" @@ -31,3 +34,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/texture_data_cpu.cc b/src/cobalt/renderer/backend/egl/texture_data_cpu.cc index b3e8ba2..0a72c2d 100644 --- a/src/cobalt/renderer/backend/egl/texture_data_cpu.cc +++ b/src/cobalt/renderer/backend/egl/texture_data_cpu.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/backend/egl/texture_data_cpu.h" #include "base/memory/aligned_memory.h" @@ -118,3 +121,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/egl/utils.cc b/src/cobalt/renderer/backend/egl/utils.cc index 0930103..a25f303 100644 --- a/src/cobalt/renderer/backend/egl/utils.cc +++ b/src/cobalt/renderer/backend/egl/utils.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/backend/egl/utils.h" #include "cobalt/renderer/egl_and_gles.h" @@ -64,3 +67,5 @@ } // namespace backend } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/backend/starboard/default_graphics_system.cc b/src/cobalt/renderer/backend/starboard/default_graphics_system.cc new file mode 100644 index 0000000..c561115 --- /dev/null +++ b/src/cobalt/renderer/backend/starboard/default_graphics_system.cc
@@ -0,0 +1,59 @@ +// Copyright 2019 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 <memory> + +#include "cobalt/renderer/backend/default_graphics_system.h" + +#include "cobalt/base/polymorphic_downcast.h" +#include "cobalt/renderer/backend/blitter/graphics_system.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) +#include "cobalt/renderer/backend/egl/graphics_system.h" +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) +#include "cobalt/renderer/backend/graphics_system_stub.h" +#include "cobalt/system_window/system_window.h" + +namespace cobalt { +namespace renderer { +namespace backend { + +std::unique_ptr<GraphicsSystem> CreateDefaultGraphicsSystem( + system_window::SystemWindow* system_window) { +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + if (SbGetGlesInterface()) { + return std::unique_ptr<GraphicsSystem>( + new GraphicsSystemEGL(system_window)); + } else if (SbBlitterIsBlitterSupported()) { + SB_UNREFERENCED_PARAMETER(system_window); + return std::unique_ptr<GraphicsSystem>(new GraphicsSystemBlitter()); + } else { + SB_UNREFERENCED_PARAMETER(system_window); + return std::unique_ptr<GraphicsSystem>(new GraphicsSystemStub()); + } +#else // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION +#if SB_HAS(GLES2) + return std::unique_ptr<GraphicsSystem>(new GraphicsSystemEGL(system_window)); +#elif SB_HAS(BLITTER) + SB_UNREFERENCED_PARAMETER(system_window); + return std::unique_ptr<GraphicsSystem>(new GraphicsSystemBlitter()); +#else + SB_UNREFERENCED_PARAMETER(system_window); + return std::unique_ptr<GraphicsSystem>(new GraphicsSystemStub()); +#endif +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION +} + +} // namespace backend +} // namespace renderer +} // namespace cobalt
diff --git a/src/cobalt/renderer/backend/starboard/platform_backend.gyp b/src/cobalt/renderer/backend/starboard/platform_backend.gyp index 9b53bfb..a10077c 100644 --- a/src/cobalt/renderer/backend/starboard/platform_backend.gyp +++ b/src/cobalt/renderer/backend/starboard/platform_backend.gyp
@@ -24,27 +24,18 @@ 'default_graphics_system_stub.cc', ], }, { - 'conditions': [ - ['gl_type == "none"', { - 'sources': [ - 'default_graphics_system_blitter.cc', - ], - - 'includes': [ - '../../renderer_parameters_setup.gypi', - '../blitter/blitter_backend.gypi', - ], - }, { - 'sources': [ - 'default_graphics_system_egl.cc', - ], - - 'includes': [ - '../../renderer_parameters_setup.gypi', - '../egl/egl_backend.gypi', - ], - }], + 'includes': [ + '../../renderer_parameters_setup.gypi', ], + + 'dependencies': [ + '../blitter/blitter_backend.gyp:blitter_backend', + '../egl/egl_backend.gyp:egl_backend', + ], + + 'sources': [ + 'default_graphics_system.cc', + ] }], ], },
diff --git a/src/cobalt/renderer/get_default_rasterizer_for_platform.cc b/src/cobalt/renderer/get_default_rasterizer_for_platform.cc index aae1913..879e38a 100644 --- a/src/cobalt/renderer/get_default_rasterizer_for_platform.cc +++ b/src/cobalt/renderer/get_default_rasterizer_for_platform.cc
@@ -25,6 +25,8 @@ #include "cobalt/renderer/rasterizer/stub/rasterizer.h" #include "cobalt/renderer/renderer_module.h" +#include "starboard/gles.h" + namespace cobalt { namespace renderer { @@ -40,7 +42,7 @@ } #endif // COBALT_FORCE_STUB_RASTERIZER -#if SB_HAS(GLES2) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) std::unique_ptr<rasterizer::Rasterizer> CreateGLESSoftwareRasterizer( backend::GraphicsContext* graphics_context, const RendererModule::Options& options) { @@ -75,9 +77,10 @@ options.purge_skia_font_caches_on_destruction, options.force_deterministic_rendering)); } -#endif // #if SB_HAS(GLES2) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(GLES2) -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) std::unique_ptr<rasterizer::Rasterizer> CreateBlitterSoftwareRasterizer( backend::GraphicsContext* graphics_context, const RendererModule::Options& options) { @@ -97,28 +100,38 @@ options.software_surface_cache_size_in_bytes, options.purge_skia_font_caches_on_destruction)); } -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) } // namespace RasterizerInfo GetDefaultRasterizerForPlatform() { #if COBALT_FORCE_STUB_RASTERIZER return {"stub", base::Bind(&CreateStubRasterizer)}; +#elif SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + if (SbGetGlesInterface()) { +#if defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER) + return {"gles", base::Bind(&CreateGLESHardwareRasterizer)}; #else + return {"skia", base::Bind(&CreateSkiaHardwareRasterizer)}; +#endif + } else if (SbBlitterIsBlitterSupported()) { + return {"blitter", base::Bind(&CreateBlitterHardwareRasterizer)}; + } else { + SB_LOG(ERROR) + << "Either GLES2 or the Starboard Blitter API must be available."; + SB_DCHECK(false); + return {}; + } +#else // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION #if SB_HAS(GLES2) -#if COBALT_FORCE_SOFTWARE_RASTERIZER - return {"gles-software", base::Bind(&CreateGLESSoftwareRasterizer)}; -#elif defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER) +#if defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER) return {"gles", base::Bind(&CreateGLESHardwareRasterizer)}; #else return {"skia", base::Bind(&CreateSkiaHardwareRasterizer)}; -#endif // COBALT_FORCE_SOFTWARE_RASTERIZER +#endif #elif SB_HAS(BLITTER) -#if COBALT_FORCE_SOFTWARE_RASTERIZER - return {"blitter-software", base::Bind(&CreateBlitterSoftwareRasterizer)}; -#else return {"blitter", base::Bind(&CreateBlitterHardwareRasterizer)}; -#endif // COBALT_FORCE_SOFTWARE_RASTERIZER #else #error "Either GLES2 or the Starboard Blitter API must be available." return {"", NULL};
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_circular_rrect_masked_clamped_texture.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_circular_rrect_masked_clamped_texture.glsl new file mode 100644 index 0000000..0f92eaa --- /dev/null +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_circular_rrect_masked_clamped_texture.glsl
@@ -0,0 +1,38 @@ +#version 100 + +uniform highp float u_skRTHeight; +precision mediump float; +uniform vec4 uTexDom_Stage1_c0; +uniform vec4 uinnerRect_Stage2; +uniform vec2 uradiusPlusHalf_Stage2; +uniform highp sampler2D uTextureSampler_0_Stage1; +varying mediump vec4 vcolor_Stage0; +varying highp vec2 vTransformedCoords_0_Stage0; + +void main() { + highp vec2 _sktmpCoord = gl_FragCoord.xy; + highp vec4 sk_FragCoord = vec4(_sktmpCoord.x, u_skRTHeight - _sktmpCoord.y, 1.0, 1.0); + vec4 outputColor_Stage0; + { + outputColor_Stage0 = vcolor_Stage0; + } + vec4 output_Stage1; + { + vec4 child; + { + child = texture2D(uTextureSampler_0_Stage1, clamp(vTransformedCoords_0_Stage0, uTexDom_Stage1_c0.xy, uTexDom_Stage1_c0.zw)); + } + output_Stage1 = child * outputColor_Stage0.w; + } + vec4 output_Stage2; + { + vec2 dxy0 = uinnerRect_Stage2.xy - sk_FragCoord.xy; + vec2 dxy1 = sk_FragCoord.xy - uinnerRect_Stage2.zw; + vec2 dxy = max(max(dxy0, dxy1), 0.0); + float alpha = clamp(uradiusPlusHalf_Stage2.x - length(dxy), 0.0, 1.0); + output_Stage2 = vec4(alpha); + } + { + gl_FragColor = output_Stage1 * output_Stage2; + } +}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_rgba.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_rgba.glsl index 4400f4b..04eaa9c 100644 --- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_rgba.glsl +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_rgba.glsl
@@ -1,9 +1,8 @@ precision mediump float; varying vec2 v_tex_coord_rgba; uniform sampler2D texture_rgba; -uniform mat4 to_rgb_color_matrix; void main() { vec4 untransformed_color = vec4(texture2D(texture_rgba, v_tex_coord_rgba).rgba); - gl_FragColor = untransformed_color * to_rgb_color_matrix; + gl_FragColor = untransformed_color; } \ No newline at end of file
diff --git a/src/cobalt/renderer/pipeline_test.cc b/src/cobalt/renderer/pipeline_test.cc index 87993f6..65e75cb 100644 --- a/src/cobalt/renderer/pipeline_test.cc +++ b/src/cobalt/renderer/pipeline_test.cc
@@ -166,7 +166,7 @@ // Wait a little bit to give the pipeline some time to rasterize the submitted // render tree. - const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(200); + const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(400); base::PlatformThread::Sleep(kDelay); // Shut down the pipeline so that Submit will no longer be called. @@ -187,7 +187,7 @@ // Here we repeatedly submit a new render tree to the pipeline as fast as // we can. Regardless of the rate that we submit to the pipeline, we expect // it to rate-limit its submissions to the rasterizer. - const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(200); + const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(400); while (true) { base::TimeDelta time_elapsed = base::TimeTicks::Now() - start_time_; // Stop after kDelay seconds have passed.
diff --git a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc index 518d7d0..0b8b31b 100644 --- a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
@@ -23,7 +23,7 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkImageInfo.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -256,4 +256,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h index 85420ad..a3540ed 100644 --- a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h +++ b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h
@@ -25,7 +25,7 @@ #include "net/base/linked_hash_map.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -150,6 +150,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_CACHED_SOFTWARE_RASTERIZER_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/cobalt_blitter_conversions.h b/src/cobalt/renderer/rasterizer/blitter/cobalt_blitter_conversions.h index ea1b86a..018dadf 100644 --- a/src/cobalt/renderer/rasterizer/blitter/cobalt_blitter_conversions.h +++ b/src/cobalt/renderer/rasterizer/blitter/cobalt_blitter_conversions.h
@@ -19,7 +19,7 @@ #include "cobalt/math/rect_f.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -39,6 +39,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_COBALT_BLITTER_CONVERSIONS_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc index 4dd9d1d..f0e3f37 100644 --- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
@@ -33,7 +33,7 @@ #include "cobalt/debug/console/command_manager.h" #endif -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -308,4 +308,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h index f890baf..4f2b7de 100644 --- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h +++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h
@@ -24,7 +24,7 @@ #include "cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h" #include "cobalt/renderer/rasterizer/rasterizer.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -65,6 +65,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_HARDWARE_RASTERIZER_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/image.cc b/src/cobalt/renderer/rasterizer/blitter/image.cc index 4604079..d8856f4 100644 --- a/src/cobalt/renderer/rasterizer/blitter/image.cc +++ b/src/cobalt/renderer/rasterizer/blitter/image.cc
@@ -24,7 +24,7 @@ #include "cobalt/renderer/rasterizer/skia/image.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -171,4 +171,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/image.h b/src/cobalt/renderer/rasterizer/blitter/image.h index 9e4095d..a0f1357 100644 --- a/src/cobalt/renderer/rasterizer/blitter/image.h +++ b/src/cobalt/renderer/rasterizer/blitter/image.h
@@ -30,7 +30,7 @@ #include "cobalt/renderer/rasterizer/skia/image.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -130,6 +130,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_IMAGE_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/linear_gradient.cc b/src/cobalt/renderer/rasterizer/blitter/linear_gradient.cc index be9b7a6..f02688e 100644 --- a/src/cobalt/renderer/rasterizer/blitter/linear_gradient.cc +++ b/src/cobalt/renderer/rasterizer/blitter/linear_gradient.cc
@@ -29,7 +29,7 @@ #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/effects/SkGradientShader.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace { @@ -410,4 +410,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/linear_gradient.h b/src/cobalt/renderer/rasterizer/blitter/linear_gradient.h index 16c5e86..49d7b7b 100644 --- a/src/cobalt/renderer/rasterizer/blitter/linear_gradient.h +++ b/src/cobalt/renderer/rasterizer/blitter/linear_gradient.h
@@ -21,7 +21,7 @@ #include "cobalt/renderer/rasterizer/blitter/render_state.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -38,6 +38,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_LINEAR_GRADIENT_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/linear_gradient_cache.cc b/src/cobalt/renderer/rasterizer/blitter/linear_gradient_cache.cc index 128624a..daa4e46 100644 --- a/src/cobalt/renderer/rasterizer/blitter/linear_gradient_cache.cc +++ b/src/cobalt/renderer/rasterizer/blitter/linear_gradient_cache.cc
@@ -21,7 +21,7 @@ #include "cobalt/render_tree/brush.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -53,4 +53,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/linear_gradient_cache.h b/src/cobalt/renderer/rasterizer/blitter/linear_gradient_cache.h index 59a34a5..0425d7e 100644 --- a/src/cobalt/renderer/rasterizer/blitter/linear_gradient_cache.h +++ b/src/cobalt/renderer/rasterizer/blitter/linear_gradient_cache.h
@@ -22,7 +22,7 @@ #include "cobalt/render_tree/brush.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -85,6 +85,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_LINEAR_GRADIENT_CACHE_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_state.cc b/src/cobalt/renderer/rasterizer/blitter/render_state.cc index cc33318..bdf92d0 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_state.cc +++ b/src/cobalt/renderer/rasterizer/blitter/render_state.cc
@@ -16,7 +16,7 @@ #include "cobalt/renderer/rasterizer/blitter/cobalt_blitter_conversions.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -55,4 +55,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_state.h b/src/cobalt/renderer/rasterizer/blitter/render_state.h index 0638b46..2ffe022 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_state.h +++ b/src/cobalt/renderer/rasterizer/blitter/render_state.h
@@ -26,7 +26,7 @@ #include "cobalt/render_tree/brush.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -144,6 +144,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_STATE_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.cc b/src/cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.cc index c813252..6feb80a 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.cc +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.cc
@@ -17,7 +17,7 @@ #include "cobalt/render_tree/image.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -52,4 +52,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.h b/src/cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.h index 7d837f2..a0910a9 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.h +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.h
@@ -18,7 +18,7 @@ #include "cobalt/render_tree/image.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -35,6 +35,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_TREE_BLITTER_CONVERSIONS_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc index e2a4b5c..6cc626e 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
@@ -33,7 +33,7 @@ #include "cobalt/renderer/rasterizer/common/utils.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) // This define exists so that developers can quickly toggle it temporarily and // obtain trace results for the render tree visit process here. In general @@ -582,4 +582,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h index 5b7080a..8a341b2 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h
@@ -41,7 +41,7 @@ #include "starboard/blitter.h" #include "third_party/skia/include/core/SkImageInfo.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { @@ -126,6 +126,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_TREE_NODE_VISITOR_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/resource_provider.cc b/src/cobalt/renderer/rasterizer/blitter/resource_provider.cc index 3c9210b..5142d9f 100644 --- a/src/cobalt/renderer/rasterizer/blitter/resource_provider.cc +++ b/src/cobalt/renderer/rasterizer/blitter/resource_provider.cc
@@ -20,7 +20,7 @@ #include "cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -205,4 +205,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/resource_provider.h b/src/cobalt/renderer/rasterizer/blitter/resource_provider.h index df2ec27..89dad0a 100644 --- a/src/cobalt/renderer/rasterizer/blitter/resource_provider.h +++ b/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
@@ -27,7 +27,7 @@ #include "starboard/blitter.h" #include "starboard/decode_target.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -130,6 +130,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_RESOURCE_PROVIDER_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.cc b/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.cc index e6721a1..bef9902 100644 --- a/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.cc +++ b/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.cc
@@ -17,7 +17,7 @@ #include "cobalt/base/polymorphic_downcast.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -95,4 +95,5 @@ } // namespace renderer } // namespace cobalt -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h b/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h index d8b359d..0272bee 100644 --- a/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h +++ b/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h
@@ -19,7 +19,7 @@ #include "cobalt/renderer/rasterizer/common/scratch_surface_cache.h" #include "starboard/blitter.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -82,6 +82,7 @@ } // namespace renderer } // namespace cobalt -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_SCRATCH_SURFACE_CACHE_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.cc b/src/cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.cc index f9cf238..d184ab9 100644 --- a/src/cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.cc +++ b/src/cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.cc
@@ -16,7 +16,7 @@ #include "base/logging.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -40,4 +40,5 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h b/src/cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h index 7831268..dd40a7d 100644 --- a/src/cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h +++ b/src/cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h
@@ -18,7 +18,7 @@ #include "starboard/blitter.h" #include "third_party/skia/include/core/SkImageInfo.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) namespace cobalt { namespace renderer { @@ -34,6 +34,7 @@ } // namespace renderer } // namespace cobalt -#endif // #if SB_HAS(BLITTER) +#endif // #if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_SKIA_BLITTER_CONVERSIONS_H_
diff --git a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc index 4acab3e..a9a721f 100644 --- a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc
@@ -14,7 +14,7 @@ #include "cobalt/renderer/rasterizer/blitter/software_rasterizer.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) #include "cobalt/renderer/backend/graphics_system.h" #include "cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h" @@ -106,4 +106,5 @@ } // namespace renderer } // namespace cobalt -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h index afa86b1..f53c403 100644 --- a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h +++ b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
@@ -17,7 +17,7 @@ #include "starboard/configuration.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) #include "base/memory/ref_counted.h" #include "cobalt/render_tree/resource_provider.h" @@ -59,6 +59,7 @@ } // namespace renderer } // namespace cobalt -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // COBALT_RENDERER_RASTERIZER_BLITTER_SOFTWARE_RASTERIZER_H_
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_callback.cc b/src/cobalt/renderer/rasterizer/egl/draw_callback.cc index 453454e..d1326c8 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_callback.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_callback.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_callback.h" #include "base/basictypes.h" @@ -51,3 +54,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_clear.cc b/src/cobalt/renderer/rasterizer/egl/draw_clear.cc index 2077000..4d7d5dc 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_clear.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_clear.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_clear.h" #include "cobalt/renderer/backend/egl/utils.h" @@ -52,3 +55,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_object.cc b/src/cobalt/renderer/rasterizer/egl/draw_object.cc index c8e7d89..e0f8e24 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_object.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_object.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_object.h" #include <algorithm> @@ -266,3 +269,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_object_manager.cc b/src/cobalt/renderer/rasterizer/egl/draw_object_manager.cc index fd3c443..8966932 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_object_manager.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_object_manager.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_object_manager.h" #include <algorithm> @@ -409,3 +412,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_poly_color.cc b/src/cobalt/renderer/rasterizer/egl/draw_poly_color.cc index d351805..407f63f 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_poly_color.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_poly_color.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_poly_color.h" #include <algorithm> @@ -210,3 +213,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_border.cc b/src/cobalt/renderer/rasterizer/egl/draw_rect_border.cc index d7a93a3..aac1ea6 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rect_border.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_border.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rect_border.h" #include "base/logging.h" @@ -248,3 +251,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_color_texture.cc b/src/cobalt/renderer/rasterizer/egl/draw_rect_color_texture.cc index 45404b2..b34c54a 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rect_color_texture.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_color_texture.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rect_color_texture.h" #include "base/basictypes.h" @@ -243,3 +246,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_linear_gradient.cc b/src/cobalt/renderer/rasterizer/egl/draw_rect_linear_gradient.cc index 7c05851..71b8bc0 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rect_linear_gradient.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_linear_gradient.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rect_linear_gradient.h" #include <algorithm> @@ -226,3 +229,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.cc b/src/cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.cc index 4b9235e..c547f53 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.h" #include <algorithm> @@ -223,3 +226,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_shadow_blur.cc b/src/cobalt/renderer/rasterizer/egl/draw_rect_shadow_blur.cc index dc7aea1..55bc8bb 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rect_shadow_blur.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_shadow_blur.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rect_shadow_blur.h" #include <algorithm> @@ -429,3 +432,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_shadow_spread.cc b/src/cobalt/renderer/rasterizer/egl/draw_rect_shadow_spread.cc index bc4316a..b3f371f 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rect_shadow_spread.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_shadow_spread.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rect_shadow_spread.h" #include <algorithm> @@ -261,3 +264,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_texture.cc b/src/cobalt/renderer/rasterizer/egl/draw_rect_texture.cc index c1a4829..4f4b8fd 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rect_texture.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_texture.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rect_texture.h" #include "base/basictypes.h" @@ -187,3 +190,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.cc b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.cc index fcbb6e1..8d7352d 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rrect_color.h" #include "cobalt/renderer/backend/egl/utils.h" @@ -118,3 +121,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.cc b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.cc index a9134fd..4a5d051 100644 --- a/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.cc +++ b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.h" #include "base/basictypes.h" @@ -278,3 +281,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/graphics_state.cc b/src/cobalt/renderer/rasterizer/egl/graphics_state.cc index 6de6e85..1b6e9ef 100644 --- a/src/cobalt/renderer/rasterizer/egl/graphics_state.cc +++ b/src/cobalt/renderer/rasterizer/egl/graphics_state.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/graphics_state.h" #include <algorithm> @@ -454,3 +457,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.cc index 4fa6d2e..4d4828a 100644 --- a/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/hardware_rasterizer.h" #include <memory> @@ -346,3 +349,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc index bd541ba..f541018 100644 --- a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc +++ b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/offscreen_target_manager.h" #include <algorithm> @@ -483,3 +486,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/rect_allocator.cc b/src/cobalt/renderer/rasterizer/egl/rect_allocator.cc index f5ca633..c6ec887 100644 --- a/src/cobalt/renderer/rasterizer/egl/rect_allocator.cc +++ b/src/cobalt/renderer/rasterizer/egl/rect_allocator.cc
@@ -22,14 +22,13 @@ namespace egl { namespace { -// Sort by descending area then width and height. This will place smaller -// blocks at the end of the free list. Allocations will use the block with -// the smallest area of sufficient dimensions in order to minimize waste. +// Sort by descending area. This will place smaller blocks at the end of the +// free list. Allocations will use the block with the smallest area of +// sufficient dimensions in order to minimize waste. bool FirstRectIsBigger(const math::Rect& a, const math::Rect& b) { const int area_a = a.width() * a.height(); const int area_b = b.width() * b.height(); - return (area_a > area_b) || (area_a == area_b && (a.width() > b.width() || - a.height() > b.height())); + return (area_a > area_b) || (area_a == area_b && (a.width() > b.width())); } } // namespace
diff --git a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc index 40c04a4..e830635 100644 --- a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc +++ b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/render_tree_node_visitor.h" #include <algorithm> @@ -109,8 +112,19 @@ } bool ImageNodeSupportedNatively(render_tree::ImageNode* image_node) { + // The image node may contain nothing. For example, when it represents a video + // element before any frame is decoded. + if (!image_node->data().source) { + return true; + } + + // Ensure any required backend processing is done to create the necessary + // GPU resource. This must be done to verify whether the GPU resource can + // be rendered by the shader. skia::Image* skia_image = base::polymorphic_downcast<skia::Image*>(image_node->data().source.get()); + skia_image->EnsureInitialized(); + if (skia_image->GetTypeId() == base::GetTypeId<skia::MultiPlaneImage>()) { skia::HardwareMultiPlaneImage* hardware_image = base::polymorphic_downcast<skia::HardwareMultiPlaneImage*>(skia_image); @@ -501,10 +515,6 @@ base::polymorphic_downcast<skia::Image*>(data.source.get()); bool is_opaque = skia_image->IsOpaque() && IsOpaque(draw_state_.opacity); - // Ensure any required backend processing is done to create the necessary - // GPU resource. - skia_image->EnsureInitialized(); - // Calculate matrix to transform texture coordinates according to the local // transform. math::Matrix3F texcoord_transform(math::Matrix3F::Identity()); @@ -1130,3 +1140,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/shader_base.cc b/src/cobalt/renderer/rasterizer/egl/shader_base.cc index 860798c..b57af79 100644 --- a/src/cobalt/renderer/rasterizer/egl/shader_base.cc +++ b/src/cobalt/renderer/rasterizer/egl/shader_base.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/shader_base.h" #include "base/logging.h" @@ -43,3 +46,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/shader_program.cc b/src/cobalt/renderer/rasterizer/egl/shader_program.cc index eacd65e..1b2d637 100644 --- a/src/cobalt/renderer/rasterizer/egl/shader_program.cc +++ b/src/cobalt/renderer/rasterizer/egl/shader_program.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/shader_program.h" #include "base/logging.h" @@ -97,3 +100,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/shader_program_manager.cc b/src/cobalt/renderer/rasterizer/egl/shader_program_manager.cc index 29e2c2d..155317c 100644 --- a/src/cobalt/renderer/rasterizer/egl/shader_program_manager.cc +++ b/src/cobalt/renderer/rasterizer/egl/shader_program_manager.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/shader_program_manager.h" #include "cobalt/renderer/backend/egl/utils.h" @@ -60,3 +63,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py b/src/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py index 16aa9d1..6e5a590 100644 --- a/src/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py +++ b/src/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py
@@ -149,6 +149,9 @@ // cobalt/renderer/rasterizer/egl/generate_shader_impl.py // Do not edit! +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "{header_filename}" namespace cobalt {{ @@ -160,6 +163,8 @@ }} // namespace rasterizer }} // namespace renderer }} // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) """
diff --git a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc index abc55e2..c512fe7 100644 --- a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/software_rasterizer.h" #include <memory> @@ -103,3 +106,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc index 696a733..b3e56b2 100644 --- a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc +++ b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/egl/textured_mesh_renderer.h" #include <string> @@ -71,11 +74,6 @@ out_vec4[3] = translate_y; } -// Used for RGB images. -const float kIdentityColorMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f}; - // Used for YUV images. const float kBT601FullRangeColorMatrix[16] = { 1.0f, 0.0f, 1.402f, -0.701, 1.0f, -0.34414f, -0.71414f, 0.529f, @@ -87,28 +85,18 @@ 1.164f, 2.112f, 0.0f, -1.12875f, 0.0f, 0.0f, 0.0f, 1.0f}; // Used for 10bit unnormalized YUV images. -const float k10BitBT2020ColorMatrix[16] = {64 * 1.163746465f, - -64 * 0.028815145f, - 64 * 2.823537589f, - -1.470095f, - 64 * 1.164383561f, - -64 * 0.258509894f, - 64 * 0.379693635f, - -0.133366f, - 64 * 1.164383561f, - 64 * 2.385315708f, - 64 * 0.021554502f, - -1.276209f, - 0.0f, - 0.0f, - 0.0f, - 1.0f}; +const float k10BitBT2020ColorMatrix[16] = { + 64 * 1.1678f, 0.0f, 64 * 1.6835f, -0.96925f, + 64 * 1.1678f, 64 * -0.1878f, 64 * -0.6522f, 0.30025f, + 64 * 1.1678f, 64 * 2.1479f, 0.0f, -1.12875f, + 0.0f, 0.0f, 0.0f, 1.0f}; const float* GetColorMatrixForImageType( TexturedMeshRenderer::Image::Type type) { switch (type) { case TexturedMeshRenderer::Image::RGBA: { - return kIdentityColorMatrix; + // No color matrix needed for RGBA to RGBA. + return nullptr; } break; case TexturedMeshRenderer::Image::YUV_3PLANE_BT601_FULL_RANGE: { return kBT601FullRangeColorMatrix; @@ -312,7 +300,8 @@ // static uint32 TexturedMeshRenderer::CreateFragmentShader( - uint32 texture_target, const std::vector<TextureInfo>& textures) { + uint32 texture_target, const std::vector<TextureInfo>& textures, + const float* color_matrix) { SamplerInfo sampler_info = GetSamplerInfo(texture_target); std::string blit_fragment_shader_source = sampler_info.preamble; @@ -327,8 +316,10 @@ base::StringPrintf("uniform %s texture_%s;", sampler_info.type.c_str(), textures[i].name.c_str()); } + if (color_matrix) { + blit_fragment_shader_source += "uniform mat4 to_rgb_color_matrix;"; + } blit_fragment_shader_source += - "uniform mat4 to_rgb_color_matrix;" "void main() {" " vec4 untransformed_color = vec4("; int components_used = 0; @@ -345,10 +336,17 @@ // Add an alpha component of 1. blit_fragment_shader_source += ", 1.0"; } - blit_fragment_shader_source += - ");" - " gl_FragColor = untransformed_color * to_rgb_color_matrix;" - "}"; + if (color_matrix) { + blit_fragment_shader_source += + ");" + " gl_FragColor = untransformed_color * to_rgb_color_matrix;" + "}"; + } else { + blit_fragment_shader_source += + ");" + " gl_FragColor = untransformed_color;" + "}"; + } return CompileShader(blit_fragment_shader_source); } @@ -475,11 +473,13 @@ } // Upload the color matrix right away since it won't change from draw to draw. - GL_CALL(glUseProgram(result.gl_program_id)); - uint32 to_rgb_color_matrix_uniform = GL_CALL_SIMPLE( - glGetUniformLocation(result.gl_program_id, "to_rgb_color_matrix")); - GL_CALL(glUniformMatrix4fv(to_rgb_color_matrix_uniform, 1, GL_FALSE, - color_matrix)); + if (color_matrix) { + GL_CALL(glUseProgram(result.gl_program_id)); + uint32 to_rgb_color_matrix_uniform = GL_CALL_SIMPLE( + glGetUniformLocation(result.gl_program_id, "to_rgb_color_matrix")); + GL_CALL(glUniformMatrix4fv(to_rgb_color_matrix_uniform, 1, GL_FALSE, + color_matrix)); + } GL_CALL(glUseProgram(0)); GL_CALL(glDeleteShader(blit_fragment_shader)); @@ -514,7 +514,7 @@ texture_infos.push_back(TextureInfo("rgba", "rgba")); result = MakeBlitProgram( color_matrix, texture_infos, - CreateFragmentShader(texture_target, texture_infos)); + CreateFragmentShader(texture_target, texture_infos, color_matrix)); } break; case Image::YUV_2PLANE_BT709: { std::vector<TextureInfo> texture_infos; @@ -549,7 +549,7 @@ #endif // SB_API_VERSION >= 7 result = MakeBlitProgram( color_matrix, texture_infos, - CreateFragmentShader(texture_target, texture_infos)); + CreateFragmentShader(texture_target, texture_infos, color_matrix)); } break; case Image::YUV_3PLANE_BT601_FULL_RANGE: case Image::YUV_3PLANE_BT709: @@ -578,7 +578,7 @@ #endif // SB_API_VERSION >= 7 && defined(GL_RED_EXT) result = MakeBlitProgram( color_matrix, texture_infos, - CreateFragmentShader(texture_target, texture_infos)); + CreateFragmentShader(texture_target, texture_infos, color_matrix)); } break; case Image::YUV_UYVY_422_BT709: { std::vector<TextureInfo> texture_infos; @@ -601,3 +601,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.h b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.h index 99abdd9..e607bd7 100644 --- a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.h +++ b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.h
@@ -134,7 +134,8 @@ uint32 blit_fragment_shader); static uint32 CreateFragmentShader(uint32 texture_target, - const std::vector<TextureInfo>& textures); + const std::vector<TextureInfo>& textures, + const float* color_matrix); static uint32 CreateVertexShader(const std::vector<TextureInfo>& textures); // UYVY textures need a special fragment shader to handle the unique aspect
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc index d6bf989..97e679e 100644 --- a/src/cobalt/renderer/rasterizer/pixel_test.cc +++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -574,6 +574,19 @@ TestTree(new CompositionNode(std::move(builder))); } +TEST_F(PixelTest, ScaledSingleRGBAImageWithAlphaFormatOpaqueAndRoundedCorners) { + scoped_refptr<Image> image = CreateColoredCheckersImageForAlphaFormat( + GetResourceProvider(), SizeF(150, 150), + render_tree::kAlphaFormatOpaque); + + TestTree(new FilterNode( + ViewportFilter(RectF(20, 20, 160, 160), RoundedCorners(10, 10)), + new ImageNode(image, RectF(160, 160), + Matrix3F::FromValues(1.1f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f)))); +} + TEST_F(PixelTest, RectWithRoundedCornersOnSolidColor) { CompositionNode::Builder builder; builder.AddChild(new RectNode(RectF(output_surface_size()), @@ -4003,6 +4016,12 @@ TestTree(new ImageNode(nullptr, math::RectF(output_surface_size()))); } +TEST_F(PixelTest, DrawNullImageInRoundedFilter) { + TestTree(new FilterNode( + ViewportFilter(RectF(25, 25, 150, 150), RoundedCorners(75, 75)), + new ImageNode(nullptr))); +} + TEST_F(PixelTest, ClearRectNodeTest) { CompositionNode::Builder composition_node_builder; composition_node_builder.AddChild(new RectNode(
diff --git a/src/cobalt/renderer/rasterizer/rasterizer.gyp b/src/cobalt/renderer/rasterizer/rasterizer.gyp index 03c32ea..2f0b2cf 100644 --- a/src/cobalt/renderer/rasterizer/rasterizer.gyp +++ b/src/cobalt/renderer/rasterizer/rasterizer.gyp
@@ -27,21 +27,13 @@ '<(DEPTH)/cobalt/renderer/rasterizer/stub/rasterizer.gyp:rasterizer', ], }, { - 'conditions': [ - ['gl_type != "none"', { - 'dependencies': [ - '<(DEPTH)/cobalt/renderer/rasterizer/skia/rasterizer.gyp:hardware_rasterizer', - '<(DEPTH)/cobalt/renderer/rasterizer/egl/rasterizer.gyp:software_rasterizer', - '<(DEPTH)/cobalt/renderer/rasterizer/egl/rasterizer.gyp:hardware_rasterizer', - ], - }], - ['OS=="starboard"', { - 'dependencies': [ - '<(DEPTH)/cobalt/renderer/rasterizer/blitter/rasterizer.gyp:hardware_rasterizer', - '<(DEPTH)/cobalt/renderer/rasterizer/blitter/rasterizer.gyp:software_rasterizer', - ], - }], - ], + 'dependencies': [ + '<(DEPTH)/cobalt/renderer/rasterizer/skia/rasterizer.gyp:hardware_rasterizer', + '<(DEPTH)/cobalt/renderer/rasterizer/egl/rasterizer.gyp:software_rasterizer', + '<(DEPTH)/cobalt/renderer/rasterizer/egl/rasterizer.gyp:hardware_rasterizer', + '<(DEPTH)/cobalt/renderer/rasterizer/blitter/rasterizer.gyp:hardware_rasterizer', + '<(DEPTH)/cobalt/renderer/rasterizer/blitter/rasterizer.gyp:software_rasterizer', + ] }], ], },
diff --git a/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc b/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc index 86aa548..e0b2c27 100644 --- a/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc +++ b/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/skia/gl_format_conversions.h" #include "cobalt/renderer/egl_and_gles.h" @@ -71,3 +74,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc index 46200db..4c6e7ad 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc +++ b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/skia/hardware_image.h" #include <memory> @@ -482,3 +485,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_mesh.cc b/src/cobalt/renderer/rasterizer/skia/hardware_mesh.cc index 3d2e2fc..ac7290c 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_mesh.cc +++ b/src/cobalt/renderer/rasterizer/skia/hardware_mesh.cc
@@ -14,6 +14,9 @@ * limitations under the License. */ +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/skia/hardware_mesh.h" #include <memory> @@ -78,3 +81,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc index f3fed1c..391bc47 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/skia/hardware_rasterizer.h" #include <algorithm> @@ -921,3 +924,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc index 165b21d..ee60da4 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc +++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/rasterizer/skia/hardware_resource_provider.h" #include <memory> @@ -560,3 +563,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi index c1688e9..163828b 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi +++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
@@ -23,6 +23,7 @@ 'src/effects/SkYUV2RGBShader.cc', 'src/effects/SkYUV2RGBShader.h', 'src/google_logging.cc', + 'src/gpu/gl/GrGLCreateNativeInterface_cobalt.cc', 'src/ports/SkFontConfigParser_cobalt.cc', 'src/ports/SkFontConfigParser_cobalt.h', 'src/ports/SkFontMgr_cobalt.cc', @@ -58,10 +59,5 @@ 'src/ports/SkMemory_starboard.cc', ], }], - ['gl_type != "none"', { - 'sources': [ - 'src/gpu/gl/GrGLCreateNativeInterface_cobalt.cc', - ], - }], ], }
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_common.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_common.gypi index bb48a69..6618d13 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/skia_common.gypi +++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_common.gypi
@@ -45,7 +45,9 @@ # This list will contain all defines that also need to be exported to # dependent components. - 'skia_export_defines': [], + 'skia_export_defines': [ + 'SK_SUPPORT_GPU=1' + ], # The |default_font_cache_limit| specifies the max size of the glyph cache, # which contains path and metrics information for glyphs, before it will @@ -55,20 +57,9 @@ }, 'conditions': [ ['gl_type != "none"', { - 'variables': { - 'skia_export_defines': [ - 'SK_SUPPORT_GPU=1', - ], - }, 'dependencies': [ '<(DEPTH)/starboard/starboard_headers_only.gyp:starboard_headers_only', ], - }, { - 'variables': { - 'skia_export_defines': [ - 'SK_SUPPORT_GPU=0', - ], - }, }], ['target_arch == "win"', { 'variables': {
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_library.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_library.gypi index c8e0036..47e338f 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/skia_library.gypi +++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_library.gypi
@@ -20,10 +20,13 @@ 'includes': [ '../../../../../third_party/skia/gyp/core.gypi', '../../../../../third_party/skia/gyp/effects.gypi', + '../../../../../third_party/skia/gyp/gpu.gypi', '../../../../../third_party/skia/gyp/utils.gypi', ], 'sources': [ + '<@(skia_gpu_sources)', + '<@(skia_native_gpu_sources)', '<(DEPTH)/third_party/skia/src/codec/SkBmpBaseCodec.cpp', '<(DEPTH)/third_party/skia/src/codec/SkBmpCodec.cpp', '<(DEPTH)/third_party/skia/src/codec/SkBmpMaskCodec.cpp', @@ -181,14 +184,5 @@ '<(DEPTH)/third_party/skia/src/ports/SkMemory_malloc.cpp', ], }], - ['gl_type != "none"', { - 'includes': [ - '../../../../../third_party/skia/gyp/gpu.gypi', - ], - 'sources': [ - '<@(skia_gpu_sources)', - '<@(skia_native_gpu_sources)', - ], - }], ], }
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/gpu/gl/GrGLCreateNativeInterface_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/gpu/gl/GrGLCreateNativeInterface_cobalt.cc index 60da51c..fafc653 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/src/gpu/gl/GrGLCreateNativeInterface_cobalt.cc +++ b/src/cobalt/renderer/rasterizer/skia/skia/src/gpu/gl/GrGLCreateNativeInterface_cobalt.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include "cobalt/renderer/egl_and_gles.h" #include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h" #include "third_party/skia/include/gpu/gl/GrGLInterface.h" @@ -138,3 +141,9 @@ const GrGLInterface* GrGLCreateNativeInterface() { return GrGLAssembleInterface(NULL, &GetGLProc); } +#else // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + +#include "third_party/skia/include/gpu/gl/GrGLInterface.h" +const GrGLInterface* GrGLCreateNativeInterface() { return nullptr; } + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/skia/vertex_buffer_object.cc b/src/cobalt/renderer/rasterizer/skia/vertex_buffer_object.cc index cd1f5c6..85dee99 100644 --- a/src/cobalt/renderer/rasterizer/skia/vertex_buffer_object.cc +++ b/src/cobalt/renderer/rasterizer/skia/vertex_buffer_object.cc
@@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #include <memory> #include <vector> @@ -63,3 +66,5 @@ } // namespace rasterizer } // namespace renderer } // namespace cobalt + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/cobalt/renderer/rasterizer/testdata/DrawNullImageInRoundedFilter-expected.png b/src/cobalt/renderer/rasterizer/testdata/DrawNullImageInRoundedFilter-expected.png new file mode 100644 index 0000000..7f0bfcf --- /dev/null +++ b/src/cobalt/renderer/rasterizer/testdata/DrawNullImageInRoundedFilter-expected.png Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/ScaledSingleRGBAImageWithAlphaFormatOpaqueAndRoundedCorners-expected.png b/src/cobalt/renderer/rasterizer/testdata/ScaledSingleRGBAImageWithAlphaFormatOpaqueAndRoundedCorners-expected.png new file mode 100644 index 0000000..fa51f6a --- /dev/null +++ b/src/cobalt/renderer/rasterizer/testdata/ScaledSingleRGBAImageWithAlphaFormatOpaqueAndRoundedCorners-expected.png Binary files differ
diff --git a/src/cobalt/renderer/renderer_module.cc b/src/cobalt/renderer/renderer_module.cc index 812d859..1fc8987 100644 --- a/src/cobalt/renderer/renderer_module.cc +++ b/src/cobalt/renderer/renderer_module.cc
@@ -92,7 +92,14 @@ base::Bind(options_.create_rasterizer_function, graphics_context_.get(), options_), display_->GetRenderTarget(), graphics_context_.get(), +#if SB_API_VERSION < SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION options_.submit_even_if_render_tree_is_unchanged, +#else + // SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is deprecated in + // favor of the usage of 'CobaltExtensionGraphicsApi', use 'false' to + // deprecate the submit_even_if_render_tree_is_unchanged. + false, +#endif renderer::Pipeline::kClearToBlack, pipeline_options)); } }
diff --git a/src/cobalt/renderer/renderer_module.h b/src/cobalt/renderer/renderer_module.h index 8cdf351..0fedad6 100644 --- a/src/cobalt/renderer/renderer_module.h +++ b/src/cobalt/renderer/renderer_module.h
@@ -84,11 +84,13 @@ // (e.g. screenshot diff tools). bool force_deterministic_rendering; +#if SB_API_VERSION < SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION // If this flag is set to true, the pipeline will not re-submit a render // tree if it has not changed from the previous submission. This can save // CPU time so long as there's no problem with the fact that the display // buffer will not be frequently swapped. bool submit_even_if_render_tree_is_unchanged; +#endif // If this flag is set to true, which is the default value, then all of // Skia's font caches are purged during destruction. These caches have
diff --git a/src/cobalt/renderer/renderer_module_default_options.cc b/src/cobalt/renderer/renderer_module_default_options.cc index 41b83f9..9f45690 100644 --- a/src/cobalt/renderer/renderer_module_default_options.cc +++ b/src/cobalt/renderer/renderer_module_default_options.cc
@@ -21,11 +21,13 @@ namespace renderer { void RendererModule::Options::SetPerPlatformDefaultOptions() { +#if SB_API_VERSION < SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION // If there is no need to frequently flip the display buffer, then enable // support for an optimization where the scene is not re-rasterized each frame // if it has not changed from the last frame. submit_even_if_render_tree_is_unchanged = SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER; +#endif create_rasterizer_function = GetDefaultRasterizerForPlatform().create_rasterizer_callback;
diff --git a/src/cobalt/renderer/renderer_parameters_setup.gypi b/src/cobalt/renderer/renderer_parameters_setup.gypi index f22806f..9be6e33 100644 --- a/src/cobalt/renderer/renderer_parameters_setup.gypi +++ b/src/cobalt/renderer/renderer_parameters_setup.gypi
@@ -17,11 +17,6 @@ 'COBALT_SCRATCH_SURFACE_CACHE_SIZE_IN_BYTES=<(scratch_surface_cache_size_in_bytes)', ], 'conditions': [ - ['rasterizer_type == "software"', { - 'defines': [ - 'COBALT_FORCE_SOFTWARE_RASTERIZER', - ], - }], ['rasterizer_type == "stub"', { 'defines': [ 'COBALT_FORCE_STUB_RASTERIZER',
diff --git a/src/cobalt/script/array_buffer.h b/src/cobalt/script/array_buffer.h index 6934198..850fc52 100644 --- a/src/cobalt/script/array_buffer.h +++ b/src/cobalt/script/array_buffer.h
@@ -17,6 +17,7 @@ #include <memory> +#include "base/logging.h" #include "base/memory/ref_counted.h" #include "cobalt/script/exception_message.h" #include "cobalt/script/script_exception.h" @@ -87,14 +88,20 @@ PreallocatedArrayBufferData& operator=(PreallocatedArrayBufferData&& other) = default; - void* data() const { return data_; } + void* data() { return data_; } size_t byte_length() const { return byte_length_; } private: PreallocatedArrayBufferData(const PreallocatedArrayBufferData&) = delete; void operator=(const PreallocatedArrayBufferData&) = delete; - void Release() { + void Detach(void** data, size_t* byte_length) { + DCHECK(data); + DCHECK(byte_length); + + *data = data_; + *byte_length = byte_length_; + data_ = nullptr; byte_length_ = 0u; }
diff --git a/src/cobalt/script/mozjs-45/mozjs_array_buffer.cc b/src/cobalt/script/mozjs-45/mozjs_array_buffer.cc index cd49993..1fa7a43 100644 --- a/src/cobalt/script/mozjs-45/mozjs_array_buffer.cc +++ b/src/cobalt/script/mozjs-45/mozjs_array_buffer.cc
@@ -69,10 +69,16 @@ JSAutoCompartment auto_compartment(context, global_object); JS::RootedValue array_buffer(context); - array_buffer.setObjectOrNull(JS_NewArrayBufferWithContents( - context, data->byte_length(), data->data())); + + void* buffer; + size_t byte_length; + + data->Detach(&buffer, &byte_length); + + array_buffer.setObjectOrNull( + JS_NewArrayBufferWithContents(context, byte_length, buffer)); DCHECK(array_buffer.isObject()); - data->Release(); + return Handle<ArrayBuffer>( new mozjs::MozjsUserObjectHolder<mozjs::MozjsArrayBuffer>(context, array_buffer));
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.h b/src/cobalt/script/mozjs-45/mozjs_global_environment.h index 0bc4428..0aa069d 100644 --- a/src/cobalt/script/mozjs-45/mozjs_global_environment.h +++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
@@ -185,14 +185,17 @@ JSContext* context_; int garbage_collection_count_; WeakHeapObjectManager weak_object_manager_; - std::unordered_map<Wrappable*, CountedHeapObject> kept_alive_objects_; std::unique_ptr<ReferencedObjectMap> referenced_objects_; - std::vector<InterfaceData> cached_interface_data_; + // Beware the order of destruction. Anything which references the JSContext + // should be destroyed before ~ContextDestructor. ContextDestructor context_destructor_; + + JS::Heap<JSObject*> global_object_proxy_; std::unique_ptr<WrapperFactory> wrapper_factory_; std::unique_ptr<MozjsScriptValueFactory> script_value_factory_; - JS::Heap<JSObject*> global_object_proxy_; + std::vector<InterfaceData> cached_interface_data_; + std::unordered_map<Wrappable*, CountedHeapObject> kept_alive_objects_; EnvironmentSettings* environment_settings_; // TODO: Should be |std::unordered_set| once C++11 is enabled. base::hash_set<Traceable*> visited_traceables_;
diff --git a/src/cobalt/script/mozjs-45/referenced_object_map.cc b/src/cobalt/script/mozjs-45/referenced_object_map.cc index bceb6c4..b822336 100644 --- a/src/cobalt/script/mozjs-45/referenced_object_map.cc +++ b/src/cobalt/script/mozjs-45/referenced_object_map.cc
@@ -29,6 +29,10 @@ ReferencedObjectMap::ReferencedObjectMap(JSContext* context) : context_(context) {} +ReferencedObjectMap::~ReferencedObjectMap() { + DCHECK(referenced_objects_.empty()); +} + // Add/Remove a reference from a WrapperPrivate to a JSValue. void ReferencedObjectMap::AddReferencedObject(Wrappable* wrappable, JS::HandleValue referee) {
diff --git a/src/cobalt/script/mozjs-45/referenced_object_map.h b/src/cobalt/script/mozjs-45/referenced_object_map.h index 487f2db..134c515 100644 --- a/src/cobalt/script/mozjs-45/referenced_object_map.h +++ b/src/cobalt/script/mozjs-45/referenced_object_map.h
@@ -32,6 +32,7 @@ class ReferencedObjectMap { public: explicit ReferencedObjectMap(JSContext* context); + ~ReferencedObjectMap(); void AddReferencedObject(Wrappable* wrappable, JS::HandleValue referee); void RemoveReferencedObject(Wrappable* wrappable, JS::HandleValue referee);
diff --git a/src/cobalt/script/script_debugger.h b/src/cobalt/script/script_debugger.h index 716e798..eefe991 100644 --- a/src/cobalt/script/script_debugger.h +++ b/src/cobalt/script/script_debugger.h
@@ -131,18 +131,18 @@ // Record the JavaScript stack on the WebModule thread at the point a task is // initiated that will run at a later time (on the same thread), allowing it // to be seen as the originator when breaking in the asynchronous task. - virtual void AsyncTaskScheduled(void* task, const std::string& name, + virtual void AsyncTaskScheduled(const void* task, const std::string& name, bool recurring) = 0; // A scheduled task is starting to run. - virtual void AsyncTaskStarted(void* task) = 0; + virtual void AsyncTaskStarted(const void* task) = 0; // A scheduled task has finished running. - virtual void AsyncTaskFinished(void* task) = 0; + virtual void AsyncTaskFinished(const void* task) = 0; // A scheduled task will no longer be run, and resources associated with it // may be released. - virtual void AsyncTaskCanceled(void* task) = 0; + virtual void AsyncTaskCanceled(const void* task) = 0; // All scheduled tasks will no longer be run, and resources associated with // them may be released.
diff --git a/src/cobalt/script/shared/stub_script_debugger.cc b/src/cobalt/script/shared/stub_script_debugger.cc index c2a145d..9dd59d6 100644 --- a/src/cobalt/script/shared/stub_script_debugger.cc +++ b/src/cobalt/script/shared/stub_script_debugger.cc
@@ -75,11 +75,11 @@ // The AsyncTask functions will be called regardless whether there's a // functioning debugger, so don't call NOTIMPLEMENTED() to avoid log spam. - void AsyncTaskScheduled(void* task, const std::string& name, + void AsyncTaskScheduled(const void* task, const std::string& name, bool recurring) override {} - void AsyncTaskStarted(void* task) override {} - void AsyncTaskFinished(void* task) override {} - void AsyncTaskCanceled(void* task) override {} + void AsyncTaskStarted(const void* task) override {} + void AsyncTaskFinished(const void* task) override {} + void AsyncTaskCanceled(const void* task) override {} void AllAsyncTasksCanceled() override {} private:
diff --git a/src/cobalt/script/v8c/cobalt_platform.cc b/src/cobalt/script/v8c/cobalt_platform.cc index b524088..1060596 100644 --- a/src/cobalt/script/v8c/cobalt_platform.cc +++ b/src/cobalt/script/v8c/cobalt_platform.cc
@@ -14,6 +14,7 @@ #include <memory> +#include "cobalt/base/polymorphic_downcast.h" #include "cobalt/script/v8c/cobalt_platform.h" #include "base/logging.h" @@ -22,90 +23,98 @@ namespace script { namespace v8c { -CobaltPlatform::MessageLoopMapEntry* CobaltPlatform::FindOrAddMapEntry( - v8::Isolate* isolate) { - auto iter = message_loop_map_.find(isolate); - // Because of the member unique_ptr, we need explicit creation. - if (iter == message_loop_map_.end()) { - auto new_entry = std::unique_ptr<CobaltPlatform::MessageLoopMapEntry>( - new CobaltPlatform::MessageLoopMapEntry()); - message_loop_map_.emplace(std::make_pair(isolate, std::move(new_entry))); +CobaltPlatform::CobaltV8TaskRunner::CobaltV8TaskRunner() + : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {} + +void CobaltPlatform::CobaltV8TaskRunner::PostTask( + std::unique_ptr<v8::Task> task) { + PostDelayedTask(std::move(task), 0); +} + +void CobaltPlatform::CobaltV8TaskRunner::PostDelayedTask( + std::unique_ptr<v8::Task> task, double delay_in_seconds) { + base::AutoLock auto_lock(lock_); + if (task_runner_) { + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&CobaltPlatform::CobaltV8TaskRunner::RunV8Task, + weak_ptr_factory_.GetWeakPtr(), base::Passed(&task)), + base::TimeDelta::FromSecondsD(delay_in_seconds)); + } else { + tasks_before_registration_.push_back( + std::unique_ptr<TaskBeforeRegistration>( + new TaskBeforeRegistration(delay_in_seconds, std::move(task)))); } - DCHECK(message_loop_map_[isolate]); - return message_loop_map_[isolate].get(); +} + +void CobaltPlatform::CobaltV8TaskRunner::SetTaskRunner( + base::SingleThreadTaskRunner* task_runner) { + base::AutoLock auto_lock(lock_); + task_runner_ = task_runner; + DCHECK(task_runner); + for (unsigned int i = 0; i < tasks_before_registration_.size(); ++i) { + std::unique_ptr<v8::Task> scoped_task = + std::move(tasks_before_registration_[i]->task); + base::TimeDelta delay = std::max( + tasks_before_registration_[i]->target_time - base::TimeTicks::Now(), + base::TimeDelta::FromSeconds(0)); + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&CobaltPlatform::CobaltV8TaskRunner::RunV8Task, + weak_ptr_factory_.GetWeakPtr(), base::Passed(&scoped_task)), + delay); + } + tasks_before_registration_.clear(); +} + +void CobaltPlatform::CobaltV8TaskRunner::RunV8Task( + std::unique_ptr<v8::Task> task) { + task->Run(); +} + +std::shared_ptr<v8::TaskRunner> CobaltPlatform::GetForegroundTaskRunner( + v8::Isolate* isolate) { + base::AutoLock auto_lock(lock_); + std::shared_ptr<CobaltPlatform::CobaltV8TaskRunner> task_runner; + if (v8_task_runner_map_.find(isolate) == v8_task_runner_map_.end()) { + task_runner = std::make_shared<CobaltPlatform::CobaltV8TaskRunner>(); + v8_task_runner_map_.emplace(isolate, task_runner); + } else { + task_runner = v8_task_runner_map_[isolate]; + } + DCHECK(task_runner); + return task_runner; } void CobaltPlatform::RegisterIsolateOnThread(v8::Isolate* isolate, base::MessageLoop* message_loop) { - base::AutoLock auto_lock(lock_); - auto* message_loop_entry = FindOrAddMapEntry(isolate); - message_loop_entry->message_loop = message_loop; - if (!message_loop) { - DLOG(WARNING) << "Isolate is registered without a valid message loop!"; - return; - } - std::vector<std::unique_ptr<TaskBeforeRegistration>> task_vec; - task_vec.swap(message_loop_entry->tasks_before_registration); - DCHECK(message_loop_entry->tasks_before_registration.empty()); - for (unsigned int i = 0; i < task_vec.size(); ++i) { - std::unique_ptr<v8::Task> scoped_task(task_vec[i]->task.release()); - base::TimeDelta delay = - std::max(task_vec[i]->target_time - base::TimeTicks::Now(), - base::TimeDelta::FromSeconds(0)); - message_loop->task_runner()->PostDelayedTask( - FROM_HERE, - base::Bind(&CobaltPlatform::RunV8Task, base::Unretained(this), isolate, - base::Passed(&scoped_task)), - delay); - } + auto task_runner = GetForegroundTaskRunner(isolate); + CobaltPlatform::CobaltV8TaskRunner* cobalt_v8_task_runner = + base::polymorphic_downcast<CobaltPlatform::CobaltV8TaskRunner*>( + task_runner.get()); + cobalt_v8_task_runner->SetTaskRunner(message_loop->task_runner().get()); } void CobaltPlatform::UnregisterIsolateOnThread(v8::Isolate* isolate) { base::AutoLock auto_lock(lock_); - MessageLoopMap::iterator iter = message_loop_map_.find(isolate); - if (iter != message_loop_map_.end()) { - message_loop_map_.erase(iter); + auto iter = v8_task_runner_map_.find(isolate); + if (iter != v8_task_runner_map_.end()) { + v8_task_runner_map_.erase(iter); } else { DLOG(WARNING) << "Isolate is not in the map and can not be unregistered."; } } -void CobaltPlatform::RunV8Task(v8::Isolate* isolate, - std::unique_ptr<v8::Task> task) { - { - base::AutoLock auto_lock(lock_); - MessageLoopMap::iterator iter = message_loop_map_.find(isolate); - if (iter == message_loop_map_.end() || !iter->second->message_loop) { - DLOG(WARNING) << "V8 foreground task executes after isolate " - "unregistered, aborting."; - return; - } - } - task->Run(); -} - void CobaltPlatform::CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) { - CallDelayedOnForegroundThread(isolate, task, 0); + GetForegroundTaskRunner(isolate)->PostTask(std::unique_ptr<v8::Task>(task)); } void CobaltPlatform::CallDelayedOnForegroundThread(v8::Isolate* isolate, v8::Task* task, double delay_in_seconds) { - base::AutoLock auto_lock(lock_); - auto* message_loop_entry = FindOrAddMapEntry(isolate); - if (message_loop_entry->message_loop != NULL) { - std::unique_ptr<v8::Task> scoped_task(task); - message_loop_entry->message_loop->task_runner()->PostDelayedTask( - FROM_HERE, - base::Bind(&CobaltPlatform::RunV8Task, base::Unretained(this), isolate, - base::Passed(&scoped_task)), - base::TimeDelta::FromSecondsD(delay_in_seconds)); - } else { - message_loop_map_[isolate]->tasks_before_registration.push_back( - std::unique_ptr<TaskBeforeRegistration>( - new TaskBeforeRegistration(delay_in_seconds, task))); - } + GetForegroundTaskRunner(isolate)->PostDelayedTask( + std::unique_ptr<v8::Task>(task), delay_in_seconds); } } // namespace v8c
diff --git a/src/cobalt/script/v8c/cobalt_platform.h b/src/cobalt/script/v8c/cobalt_platform.h index 5c623ae..ff2a522 100644 --- a/src/cobalt/script/v8c/cobalt_platform.h +++ b/src/cobalt/script/v8c/cobalt_platform.h
@@ -21,6 +21,7 @@ #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_task_runner_handle.h" #include "v8/include/libplatform/libplatform.h" #include "v8/include/v8-platform.h" #include "v8/include/v8.h" @@ -45,7 +46,6 @@ void RegisterIsolateOnThread(v8::Isolate* isolate, base::MessageLoop* message_loop); void UnregisterIsolateOnThread(v8::Isolate* isolate); - void RunV8Task(v8::Isolate* isolate, std::unique_ptr<v8::Task> task); // v8::Platform APIs. v8::PageAllocator* GetPageAllocator() override { @@ -60,21 +60,21 @@ return default_platform_->OnCriticalMemoryPressure(length); } + int NumberOfWorkerThreads() { + return default_platform_->NumberOfWorkerThreads(); + } + std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner( - v8::Isolate* isolate) override { - return default_platform_->GetForegroundTaskRunner(isolate); + v8::Isolate* isolate) override; + + void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override { + default_platform_->CallOnWorkerThread(std::move(task)); } - std::shared_ptr<v8::TaskRunner> GetBackgroundTaskRunner( - v8::Isolate* isolate) override { - return default_platform_->GetBackgroundTaskRunner(isolate); - } - - void CallOnBackgroundThread(v8::Task* task, - ExpectedRuntime expected_runtime) override { - // DefaultPlatform initializes threads running in the background to do - // requested background work. - default_platform_->CallOnBackgroundThread(task, expected_runtime); + virtual void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task, + double delay_in_seconds) { + default_platform_->CallDelayedOnWorkerThread(std::move(task), + delay_in_seconds); } // Post task on the message loop of the isolate's corresponding @@ -109,27 +109,48 @@ std::unique_ptr<v8::Platform> default_platform_; struct TaskBeforeRegistration { - TaskBeforeRegistration(double delay_in_seconds, v8::Task* task) + TaskBeforeRegistration(double delay_in_seconds, + std::unique_ptr<v8::Task> task) : target_time(base::TimeTicks::Now() + base::TimeDelta::FromSecondsD(delay_in_seconds)), - task(task) {} + task(std::move(task)) {} base::TimeTicks target_time; std::unique_ptr<v8::Task> task; }; - struct MessageLoopMapEntry { - // If tasks are posted before isolate is registered, we record their delay - // and post them when isolate is registered. - std::vector<std::unique_ptr<TaskBeforeRegistration>> - tasks_before_registration; - base::MessageLoop* message_loop = NULL; - }; - typedef std::map<v8::Isolate*, std::unique_ptr<MessageLoopMapEntry>> - MessageLoopMap; + class CobaltV8TaskRunner : public v8::TaskRunner { + public: + CobaltV8TaskRunner(); + // v8::TaskRunner API + void PostTask(std::unique_ptr<v8::Task> task) override; + void PostDelayedTask(std::unique_ptr<v8::Task> task, + double delay_in_seconds) override; + void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override {} + // TODO: Investigate if we want to enable Idle task and/or non-netable + // tasks. + bool IdleTasksEnabled() override { return false; } - MessageLoopMapEntry* FindOrAddMapEntry(v8::Isolate* isolate); + // custom helper methods + void SetTaskRunner(base::SingleThreadTaskRunner* task_runner); + void RunV8Task(std::unique_ptr<v8::Task> task); + + private: + // We keep raw pointer instead of scoped_refptr because this class can be + // posted with refptr and keeping a reference to task_runner_ might create + // reference cycle. Also this class should be guaranteed to live shorter + // than the thread. + base::SingleThreadTaskRunner* task_runner_; + base::WeakPtrFactory<CobaltV8TaskRunner> weak_ptr_factory_; + // If tasks are posted before isolate is registered, we record their delay + // and post them when isolate is registered to a thread. + std::vector<std::unique_ptr<TaskBeforeRegistration>> + tasks_before_registration_; + base::Lock lock_; + }; + typedef std::map<v8::Isolate*, std::shared_ptr<CobaltV8TaskRunner>> + TaskRunnerMap; // A lookup table of isolate to its main thread's task runner. - MessageLoopMap message_loop_map_; + TaskRunnerMap v8_task_runner_map_; base::Lock lock_; DISALLOW_COPY_AND_ASSIGN(CobaltPlatform);
diff --git a/src/cobalt/script/v8c/conversion_helpers.h b/src/cobalt/script/v8c/conversion_helpers.h index 456152b..0655f9e 100644 --- a/src/cobalt/script/v8c/conversion_helpers.h +++ b/src/cobalt/script/v8c/conversion_helpers.h
@@ -135,8 +135,7 @@ DCHECK_EQ(conversion_flags, kNoConversionFlags) << "No conversion flags supported."; DCHECK(out_boolean); - v8::MaybeLocal<v8::Boolean> maybe_boolean = - value->ToBoolean(isolate->GetCurrentContext()); + v8::MaybeLocal<v8::Boolean> maybe_boolean = value->ToBoolean(isolate); v8::Local<v8::Boolean> boolean; if (!maybe_boolean.ToLocal(&boolean)) { // TODO: Handle this failure case. It apparently can't happen in @@ -674,11 +673,7 @@ return; } - bool done_as_bool; - if (!done->BooleanValue(context).To(&done_as_bool)) { - return; - } - if (done_as_bool) { + if (done->BooleanValue(isolate)) { break; }
diff --git a/src/cobalt/script/v8c/scoped_persistent.h b/src/cobalt/script/v8c/scoped_persistent.h index 28d7da3..bbabd9e 100644 --- a/src/cobalt/script/v8c/scoped_persistent.h +++ b/src/cobalt/script/v8c/scoped_persistent.h
@@ -27,12 +27,13 @@ ScopedPersistent() {} ScopedPersistent(v8::Isolate* isolate, v8::Local<T> handle) - : handle_(isolate, handle) {} + : handle_(isolate, handle), traced_global_(isolate, handle) {} ScopedPersistent(v8::Isolate* isolate, v8::MaybeLocal<T> maybe) { v8::Local<T> local; if (maybe.ToLocal(&local)) { handle_.Reset(isolate, local); + traced_global_.Reset(isolate, local); } } @@ -72,9 +73,14 @@ v8::Persistent<T>& Get() { return handle_; } const v8::Persistent<T>& Get() const { return handle_; } + const v8::TracedGlobal<T>& traced_global() const { + DCHECK(!handle_.IsEmpty()); + return traced_global_; + } private: v8::Persistent<T> handle_; + v8::TracedGlobal<T> traced_global_; }; } // namespace v8c
diff --git a/src/cobalt/script/v8c/v8c.gyp b/src/cobalt/script/v8c/v8c.gyp index 9951691..e570dcb 100644 --- a/src/cobalt/script/v8c/v8c.gyp +++ b/src/cobalt/script/v8c/v8c.gyp
@@ -170,7 +170,7 @@ 'type': 'none', 'hard_dependency': 1, 'dependencies': [ - '<(DEPTH)/v8/src/v8.gyp:v8_base', + '<(DEPTH)/v8/src/v8.gyp:v8', '<(DEPTH)/v8/src/v8.gyp:v8_initializers', '<(DEPTH)/v8/src/v8.gyp:v8_libplatform', ], @@ -184,7 +184,6 @@ 'action_name': 'update_snapshot_time', 'inputs': [ '<(touch_script_path)', - '<(PRODUCT_DIR)/obj/v8/src/<(STATIC_LIB_PREFIX)v8_base<(STATIC_LIB_SUFFIX)', '<(PRODUCT_DIR)/obj/v8/src/<(STATIC_LIB_PREFIX)v8_initializers<(STATIC_LIB_SUFFIX)', '<(PRODUCT_DIR)/obj/v8/src/<(STATIC_LIB_PREFIX)v8_libplatform<(STATIC_LIB_SUFFIX)', ],
diff --git a/src/cobalt/script/v8c/v8c_array_buffer.cc b/src/cobalt/script/v8c/v8c_array_buffer.cc index f41bc18..13087af 100644 --- a/src/cobalt/script/v8c/v8c_array_buffer.cc +++ b/src/cobalt/script/v8c/v8c_array_buffer.cc
@@ -57,10 +57,15 @@ global_environment); v8::Isolate* isolate = v8c_global_environment->isolate(); v8c::EntryScope entry_scope(isolate); - v8::Local<v8::ArrayBuffer> array_buffer = - v8::ArrayBuffer::New(isolate, data->data(), data->byte_length(), - v8::ArrayBufferCreationMode::kInternalized); - data->Release(); + + void* buffer; + size_t byte_length; + + data->Detach(&buffer, &byte_length); + + v8::Local<v8::ArrayBuffer> array_buffer = v8::ArrayBuffer::New( + isolate, buffer, byte_length, v8::ArrayBufferCreationMode::kInternalized); + return Handle<ArrayBuffer>( new v8c::V8cUserObjectHolder<v8c::V8cArrayBuffer>(isolate, array_buffer)); }
diff --git a/src/cobalt/script/v8c/v8c_engine.cc b/src/cobalt/script/v8c/v8c_engine.cc index 046b48f..866b39f 100644 --- a/src/cobalt/script/v8c/v8c_engine.cc +++ b/src/cobalt/script/v8c/v8c_engine.cc
@@ -36,18 +36,6 @@ namespace { -void VisitWeakHandlesForMinorGC(v8::Isolate* isolate) { - class V8cPersistentHandleVisitor : public v8::PersistentHandleVisitor { - public: - void VisitPersistentHandle(v8::Persistent<v8::Value>* value, - uint16_t class_id) override { - DCHECK(value); - value->MarkActive(); - } - } visitor; - isolate->VisitWeakHandles(&visitor); -} - size_t UsedHeapSize(v8::Isolate* isolate) { v8::HeapStatistics heap_statistics; isolate->GetHeapStatistics(&heap_statistics); @@ -60,7 +48,6 @@ case v8::kGCTypeScavenge: TRACE_EVENT_BEGIN1("cobalt::script", "MinorGC", "usedHeapSizeBefore", UsedHeapSize(isolate)); - VisitWeakHandlesForMinorGC(isolate); break; case v8::kGCTypeMarkSweepCompact: TRACE_EVENT_BEGIN2("cobalt::script", "MajorGC", "usedHeapSizeBefore",
diff --git a/src/cobalt/script/v8c/v8c_global_environment.cc b/src/cobalt/script/v8c/v8c_global_environment.cc index d31d4fe..c23949f 100644 --- a/src/cobalt/script/v8c/v8c_global_environment.cc +++ b/src/cobalt/script/v8c/v8c_global_environment.cc
@@ -39,31 +39,36 @@ namespace { -std::string ExceptionToString(const v8::TryCatch& try_catch) { - v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - v8::String::Utf8Value exception(try_catch.Exception()); +std::string ExceptionToString(v8::Isolate* isolate, + const v8::TryCatch& try_catch) { + v8::HandleScope handle_scope(isolate); + v8::String::Utf8Value exception(isolate, try_catch.Exception()); v8::Local<v8::Message> message(try_catch.Message()); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); std::string string; if (message.IsEmpty()) { string.append(base::StringPrintf("%s\n", *exception)); } else { - v8::String::Utf8Value filename(message->GetScriptOrigin().ResourceName()); - int linenum = message->GetLineNumber(); + v8::String::Utf8Value filename(isolate, + message->GetScriptOrigin().ResourceName()); + int linenum; + linenum = message->GetLineNumber(context).To(&linenum) ? linenum : -1; int colnum = message->GetStartColumn(); string.append(base::StringPrintf("%s:%i:%i %s\n", *filename, linenum, colnum, *exception)); - v8::String::Utf8Value sourceline(message->GetSourceLine()); + v8::String::Utf8Value sourceline( + isolate, message->GetSourceLine(context).ToLocalChecked()); string.append(base::StringPrintf("%s\n", *sourceline)); } return string; } -std::string ToStringOrNull(v8::Local<v8::Value> value) { +std::string ToStringOrNull(v8::Isolate* isolate, v8::Local<v8::Value> value) { if (value.IsEmpty() || !value->IsString()) { return ""; } - return *v8::String::Utf8Value(value.As<v8::String>()); + return *v8::String::Utf8Value(isolate, value.As<v8::String>()); } } // namespace @@ -139,7 +144,7 @@ // it to the MessageHandler. MessageHandler(try_catch.Message(), try_catch.Exception()); if (out_result_utf8) { - *out_result_utf8 = ExceptionToString(try_catch); + *out_result_utf8 = ExceptionToString(isolate_, try_catch); } return false; } @@ -201,7 +206,7 @@ std::vector<StackFrame> result; for (int i = 0; i < stack_trace->GetFrameCount(); i++) { - v8::Local<v8::StackFrame> stack_frame = stack_trace->GetFrame(i); + v8::Local<v8::StackFrame> stack_frame = stack_trace->GetFrame(isolate_, i); v8::String::Utf8Value function_name(isolate_, stack_frame->GetFunctionName()); v8::String::Utf8Value script_name(isolate_, stack_frame->GetScriptName()); @@ -381,8 +386,9 @@ v8::Local<v8::Context> context = isolate->GetEnteredContext(); ErrorReport error_report; - error_report.message = *v8::String::Utf8Value(message->Get()); - error_report.filename = ToStringOrNull(message->GetScriptResourceName()); + error_report.message = *v8::String::Utf8Value(isolate, message->Get()); + error_report.filename = + ToStringOrNull(isolate, message->GetScriptResourceName()); int line_number = 0; int column_number = 0; if (message->GetLineNumber(context).To(&line_number) &&
diff --git a/src/cobalt/script/v8c/v8c_heap_tracer.cc b/src/cobalt/script/v8c/v8c_heap_tracer.cc index ec7ce0b..c3e9bf5 100644 --- a/src/cobalt/script/v8c/v8c_heap_tracer.cc +++ b/src/cobalt/script/v8c/v8c_heap_tracer.cc
@@ -55,13 +55,12 @@ } } -bool V8cHeapTracer::AdvanceTracing(double deadline_in_ms, - AdvanceTracingActions actions) { +bool V8cHeapTracer::AdvanceTracing(double deadline_in_ms) { TRACE_EVENT0("cobalt::script", "V8cHeapTracer::AdvanceTracing"); - while (actions.force_completion == - v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION || - platform_->MonotonicallyIncreasingTime() < deadline_in_ms) { + double start_time = platform_->MonotonicallyIncreasingTime(); + while (platform_->MonotonicallyIncreasingTime() - start_time < + deadline_in_ms) { if (frontier_.empty()) { return false; } @@ -74,7 +73,8 @@ Wrappable* wrappable = base::polymorphic_downcast<Wrappable*>(traceable); auto pair_range = reference_map_.equal_range(wrappable); for (auto it = pair_range.first; it != pair_range.second; ++it) { - it->second->Get().RegisterExternalReference(isolate_); + // Tell v8 this object is referenced on Cobalt heap. + RegisterEmbedderReference(it->second->traced_global()); } WrapperFactory* wrapper_factory = V8cGlobalEnvironment::GetFromIsolate(isolate_)->wrapper_factory(); @@ -82,7 +82,7 @@ wrapper_factory->MaybeGetWrapperPrivate( static_cast<Wrappable*>(traceable)); if (maybe_wrapper_private) { - maybe_wrapper_private->Mark(); + RegisterEmbedderReference(maybe_wrapper_private->traced_global()); } } @@ -92,6 +92,8 @@ return true; } +bool V8cHeapTracer::IsTracingDone() { return frontier_.empty(); } + void V8cHeapTracer::TraceEpilogue() { TRACE_EVENT0("cobalt::script", "V8cHeapTracer::TraceEpilogue"); @@ -99,20 +101,10 @@ visited_.clear(); } -void V8cHeapTracer::EnterFinalPause() { +void V8cHeapTracer::EnterFinalPause(EmbedderStackState stack_state) { TRACE_EVENT0("cobalt::script", "V8cHeapTracer::EnterFinalPause"); } -void V8cHeapTracer::AbortTracing() { - TRACE_EVENT0("cobalt::script", "V8cHeapTracer::AbortTracing"); - - LOG(WARNING) << "Tracing aborted."; - frontier_.clear(); - visited_.clear(); -} - -size_t V8cHeapTracer::NumberOfWrappersToTrace() { return frontier_.size(); } - void V8cHeapTracer::Trace(Traceable* traceable) { MaybeAddToFrontier(traceable); }
diff --git a/src/cobalt/script/v8c/v8c_heap_tracer.h b/src/cobalt/script/v8c/v8c_heap_tracer.h index 111986d..152227c 100644 --- a/src/cobalt/script/v8c/v8c_heap_tracer.h +++ b/src/cobalt/script/v8c/v8c_heap_tracer.h
@@ -35,16 +35,25 @@ public: explicit V8cHeapTracer(v8::Isolate* isolate) : isolate_(isolate) {} + // V8 EmbedderHeapTracer API void RegisterV8References( const std::vector<std::pair<void*, void*>>& embedder_fields) override; void TracePrologue() override; - bool AdvanceTracing(double deadline_in_ms, - AdvanceTracingActions actions) override; + bool AdvanceTracing(double deadline_in_ms) override; + bool IsTracingDone() override; void TraceEpilogue() override; - void EnterFinalPause() override; - void AbortTracing() override; - size_t NumberOfWrappersToTrace() override; + void EnterFinalPause(EmbedderStackState stack_state) override; + // IsRootForNonTracingGC provides an opportunity for us to get quickly + // perished reference deleted in scavenger GCs. But that requires the ability + // to determine whether a v8 object is reference by anything in Cobalt heap. + // Cobalt does have the reference_map_ that tracks all ScriptValues but Cobalt + // does not track referencers of all wrappables yet. So we don't have the + // ability to exploit this feature yet. + // bool IsRootForNonTracingGC(const v8::TracedGlobal<v8::Value>& handle) + // override + + // Cobalt Tracer API void Trace(Traceable* traceable) override; void AddReferencedObject(Wrappable* owner,
diff --git a/src/cobalt/script/v8c/v8c_property_enumerator.h b/src/cobalt/script/v8c/v8c_property_enumerator.h index a11f36c..fdeec2c 100644 --- a/src/cobalt/script/v8c/v8c_property_enumerator.h +++ b/src/cobalt/script/v8c/v8c_property_enumerator.h
@@ -40,7 +40,10 @@ v8::String::NewFromUtf8(isolate_, property_name.c_str(), v8::NewStringType::kNormal) .ToLocalChecked(); - (*array_)->Set(i, property_name_as_string); + auto maybe_bool = (*array_)->Set(isolate_->GetCurrentContext(), i, + property_name_as_string); + // Ensure the Set operation succeeds. + DCHECK(maybe_bool.ToChecked()); } private:
diff --git a/src/cobalt/script/v8c/v8c_script_debugger.cc b/src/cobalt/script/v8c/v8c_script_debugger.cc index a698db7..11a4f1d 100644 --- a/src/cobalt/script/v8c/v8c_script_debugger.cc +++ b/src/cobalt/script/v8c/v8c_script_debugger.cc
@@ -19,6 +19,7 @@ #include <string> #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "base/trace_event/trace_event.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/script/v8c/conversion_helpers.h" @@ -27,6 +28,7 @@ #include "nb/memory_scope.h" #include "v8/include/libplatform/v8-tracing.h" #include "v8/include/v8-inspector.h" +#include "v8/third_party/inspector_protocol/encoding/encoding.h" namespace cobalt { namespace script { @@ -42,6 +44,22 @@ constexpr int kContextGroupId = 1; constexpr char kContextName[] = "Cobalt"; +// The following implementation is based on Platform in V8's encoding_test.cc. +class CobaltJsonPlatform + : public v8_inspector_protocol_encoding::json::Platform { + bool StrToD(const char* str, double* result) const override { + return base::StringToDouble(std::string(str), result); + } + std::unique_ptr<char[]> DToStr(double value) const override { + std::string str = base::NumberToString(value); + if (str.empty()) return nullptr; + std::unique_ptr<char[]> result(new char[str.length() + 1]); + SbMemoryCopy(result.get(), str.data(), str.length() + 1); + DCHECK_EQ(0, result[str.length()]); + return result; + } +}; + V8cTracingController* GetTracingController() { return base::polymorphic_downcast<V8cTracingController*>( IsolateFellowship::GetInstance()->platform->GetTracingController()); @@ -111,10 +129,17 @@ // If/when we re-atttach we'll connect a new session and the V8 inspector will // then inform the frontend about the sources, etc. in the new context. DCHECK(inspector_session_); - std::unique_ptr<v8_inspector::StringBuffer> state = - inspector_session_->stateJSON(); + std::vector<uint8_t> state = inspector_session_->state(); inspector_session_.reset(); - return FromStringView(state->string()); + CobaltJsonPlatform platform; + std::string state_str; + // TODO: there might be an opportunity to utilize the already encoded json to + // reduce network traffic size on the wire. + v8_inspector_protocol_encoding::json::ConvertCBORToJSON( + platform, + v8_inspector_protocol_encoding::span<uint8_t>(state.data(), state.size()), + &state_str); + return state_str; } bool V8cScriptDebugger::EvaluateDebuggerScript(const std::string& js_code, @@ -140,7 +165,7 @@ v8::Local<v8::Value> result; if (!inspector_->compileAndRunInternalScript(context, source) .ToLocal(&result)) { - v8::String::Utf8Value exception(try_catch.Exception()); + v8::String::Utf8Value exception(isolate, try_catch.Exception()); std::string string(*exception, exception.length()); if (string.empty()) string.assign("Unknown error"); LOG(ERROR) << "Debugger script error: " << string; @@ -241,21 +266,23 @@ tracing_controller->StopTracing(); } -void V8cScriptDebugger::AsyncTaskScheduled(void* task, const std::string& name, +void V8cScriptDebugger::AsyncTaskScheduled(const void* task, + const std::string& name, bool recurring) { - inspector_->asyncTaskScheduled(ToStringView(name), task, recurring); + inspector_->asyncTaskScheduled(ToStringView(name), const_cast<void*>(task), + recurring); } -void V8cScriptDebugger::AsyncTaskStarted(void* task) { - inspector_->asyncTaskStarted(task); +void V8cScriptDebugger::AsyncTaskStarted(const void* task) { + inspector_->asyncTaskStarted(const_cast<void*>(task)); } -void V8cScriptDebugger::AsyncTaskFinished(void* task) { - inspector_->asyncTaskFinished(task); +void V8cScriptDebugger::AsyncTaskFinished(const void* task) { + inspector_->asyncTaskFinished(const_cast<void*>(task)); } -void V8cScriptDebugger::AsyncTaskCanceled(void* task) { - inspector_->asyncTaskCanceled(task); +void V8cScriptDebugger::AsyncTaskCanceled(const void* task) { + inspector_->asyncTaskCanceled(const_cast<void*>(task)); } void V8cScriptDebugger::AllAsyncTasksCanceled() {
diff --git a/src/cobalt/script/v8c/v8c_script_debugger.h b/src/cobalt/script/v8c/v8c_script_debugger.h index f7c342c..d242c3f 100644 --- a/src/cobalt/script/v8c/v8c_script_debugger.h +++ b/src/cobalt/script/v8c/v8c_script_debugger.h
@@ -60,11 +60,11 @@ PauseOnExceptionsState SetPauseOnExceptions( PauseOnExceptionsState state) override; - void AsyncTaskScheduled(void* task, const std::string& name, + void AsyncTaskScheduled(const void* task, const std::string& name, bool recurring) override; - void AsyncTaskStarted(void* task) override; - void AsyncTaskFinished(void* task) override; - void AsyncTaskCanceled(void* task) override; + void AsyncTaskStarted(const void* task) override; + void AsyncTaskFinished(const void* task) override; + void AsyncTaskCanceled(const void* task) override; void AllAsyncTasksCanceled() override; // v8_inspector::V8InspectorClient implementation.
diff --git a/src/cobalt/script/v8c/wrapper_private.h b/src/cobalt/script/v8c/wrapper_private.h index 28b93f2..2e1c33d 100644 --- a/src/cobalt/script/v8c/wrapper_private.h +++ b/src/cobalt/script/v8c/wrapper_private.h
@@ -62,7 +62,10 @@ WrapperPrivate(v8::Isolate* isolate, const scoped_refptr<Wrappable>& wrappable, v8::Local<v8::Object> wrapper) - : isolate_(isolate), wrappable_(wrappable), wrapper_(isolate, wrapper) { + : isolate_(isolate), + wrappable_(wrappable), + wrapper_(isolate, wrapper), + traced_global_(isolate, wrapper) { wrapper->SetAlignedPointerInInternalField(kInternalFieldDataIndex, this); wrapper->SetAlignedPointerInInternalField(kInternalFieldDummyIndex, nullptr); @@ -71,16 +74,11 @@ wrapper_.SetWrapperClassId(kClassId); } ~WrapperPrivate() { - DCHECK(wrapper_.IsNearDeath()); DCHECK_EQ(ref_count_, 0); wrapper_.ClearWeak(); wrapper_.Reset(); } - // Mark |wrapper_| as reachable from other |Traceable|s. This will be - // called by |V8cHeapTracer| during tracing. - void Mark() { wrapper_.RegisterExternalReference(isolate_); } - template <typename T> scoped_refptr<T> wrappable() const { return base::polymorphic_downcast<T*>(wrappable_.get()); @@ -110,8 +108,15 @@ ref_count_ = 0; wrapper_.SetWeak(this, &WrapperPrivate::Callback, v8::WeakCallbackType::kParameter); + // There is no guarantee that the finalization callback provided to SetWeak + // will be called, so release the wrappable's reference now. This will help + // ensure the wrappable is destroyed before the GlobalEnvironment is + // destroyed. + wrappable_ = nullptr; } + const v8::TracedGlobal<v8::Value>& traced_global() { return traced_global_; } + private: // For the time being, we only use a single internal field, which stores a // pointer back to us (us being the |WrapperPrivate|). @@ -132,6 +137,7 @@ v8::Isolate* isolate_; scoped_refptr<Wrappable> wrappable_; v8::Global<v8::Object> wrapper_; + v8::TracedGlobal<v8::Value> traced_global_; int ref_count_ = 0; DISALLOW_COPY_AND_ASSIGN(WrapperPrivate);
diff --git a/src/cobalt/site/docs/development/setup-linux.md b/src/cobalt/site/docs/development/setup-linux.md index ed5aff6..e67b94c 100644 --- a/src/cobalt/site/docs/development/setup-linux.md +++ b/src/cobalt/site/docs/development/setup-linux.md
@@ -62,7 +62,7 @@ 1. Build the code by navigating to the `src` directory in your new `cobalt` directory and running the following command. You must - specify a platform when running this command. On goobuntu, the + specify a platform when running this command. On Ubuntu Linux, the canonical platform is `linux-x64x11`. You can also use the `-C` command-line flag to specify a `build_type`.
diff --git a/src/cobalt/speech/google_speech_service.cc b/src/cobalt/speech/google_speech_service.cc index 550b541..231bf06 100644 --- a/src/cobalt/speech/google_speech_service.cc +++ b/src/cobalt/speech/google_speech_service.cc
@@ -317,9 +317,9 @@ downstream_fetcher_ = fetcher_creator_.Run(down_url, net::URLFetcher::GET, this); - download_data_writer_ = new CobaltURLFetcherStringWriter(); + download_data_writer_ = new loader::URLFetcherStringWriter(); downstream_fetcher_->SaveResponseWithWriter( - std::unique_ptr<CobaltURLFetcherStringWriter>(download_data_writer_)); + std::unique_ptr<loader::URLFetcherStringWriter>(download_data_writer_)); downstream_fetcher_->SetRequestContext( network_module_->url_request_context_getter()); downstream_fetcher_->Start();
diff --git a/src/cobalt/speech/google_speech_service.h b/src/cobalt/speech/google_speech_service.h index 20179c6..a69ff9d 100644 --- a/src/cobalt/speech/google_speech_service.h +++ b/src/cobalt/speech/google_speech_service.h
@@ -20,7 +20,7 @@ #include <vector> #include "base/threading/thread.h" -#include "cobalt/loader/cobalt_url_fetcher_string_writer.h" +#include "cobalt/loader/url_fetcher_string_writer.h" #include "cobalt/media/base/shell_audio_bus.h" #include "cobalt/network/network_module.h" #include "cobalt/speech/audio_encoder_flac.h" @@ -108,7 +108,7 @@ // Speech recognizer is operating in its own thread. base::Thread thread_; // Stores fetched response. - CobaltURLFetcherStringWriter* download_data_writer_ = nullptr; + loader::URLFetcherStringWriter* download_data_writer_ = nullptr; // Use a task runner to deal with all wrappables. base::WeakPtrFactory<GoogleSpeechService> weak_ptr_factory_;
diff --git a/src/cobalt/speech/speech_configuration.h b/src/cobalt/speech/speech_configuration.h index e7268e8..af6bce7 100644 --- a/src/cobalt/speech/speech_configuration.h +++ b/src/cobalt/speech/speech_configuration.h
@@ -18,12 +18,16 @@ #include "build/build_config.h" #include "starboard/configuration.h" -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) #define SB_USE_SB_MICROPHONE 1 -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 #define SB_USE_SB_SPEECH_RECOGNIZER 1 -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5 #endif // COBALT_SPEECH_SPEECH_CONFIGURATION_H_
diff --git a/src/cobalt/speech/speech_recognition.cc b/src/cobalt/speech/speech_recognition.cc index cafcb19..8957d0a 100644 --- a/src/cobalt/speech/speech_recognition.cc +++ b/src/cobalt/speech/speech_recognition.cc
@@ -25,7 +25,8 @@ // interim results: false. // max alternatives: 1. SpeechRecognition::SpeechRecognition(script::EnvironmentSettings* settings) - : ALLOW_THIS_IN_INITIALIZER_LIST( + : dom::EventTarget(settings), + ALLOW_THIS_IN_INITIALIZER_LIST( manager_(base::polymorphic_downcast<dom::DOMSettings*>(settings) ->network_module(), base::Bind(&SpeechRecognition::OnEventAvailable,
diff --git a/src/cobalt/speech/speech_recognition_error.cc b/src/cobalt/speech/speech_recognition_error.cc index b3bc92c..9089823 100644 --- a/src/cobalt/speech/speech_recognition_error.cc +++ b/src/cobalt/speech/speech_recognition_error.cc
@@ -23,7 +23,10 @@ SpeechRecognitionErrorCode error_code, const std::string& message) : dom::Event(base::Tokens::error()), error_code_(error_code), - message_(message) {} + message_(message) { + LOG(ERROR) << "Created SpeechRecognitionError code " << error_code + << " with message: " << message; +} } // namespace speech } // namespace cobalt
diff --git a/src/cobalt/speech/speech_recognition_manager.cc b/src/cobalt/speech/speech_recognition_manager.cc index 27d7d58..0175ed2 100644 --- a/src/cobalt/speech/speech_recognition_manager.cc +++ b/src/cobalt/speech/speech_recognition_manager.cc
@@ -20,9 +20,8 @@ #include "cobalt/speech/speech_recognition_error.h" #if defined(SB_USE_SB_SPEECH_RECOGNIZER) #include "cobalt/speech/starboard_speech_recognizer.h" -#else +#endif #include "cobalt/speech/cobalt_speech_recognizer.h" -#endif // defined(SB_USE_SB_SPEECH_RECOGNIZER) namespace cobalt { namespace speech { @@ -37,18 +36,20 @@ event_callback_(event_callback), state_(kStopped) { #if defined(SB_USE_SB_SPEECH_RECOGNIZER) - SB_UNREFERENCED_PARAMETER(network_module); - SB_UNREFERENCED_PARAMETER(microphone_options); - recognizer_.reset(new StarboardSpeechRecognizer(base::Bind( - &SpeechRecognitionManager::OnEventAvailable, base::Unretained(this)))); -#else + if (StarboardSpeechRecognizer::IsSupported()) { + SB_UNREFERENCED_PARAMETER(network_module); + SB_UNREFERENCED_PARAMETER(microphone_options); + recognizer_.reset(new StarboardSpeechRecognizer(base::Bind( + &SpeechRecognitionManager::OnEventAvailable, base::Unretained(this)))); + return; + } +#endif // defined(SB_USE_SB_SPEECH_RECOGNIZER) if (GoogleSpeechService::GetSpeechAPIKey()) { recognizer_.reset(new CobaltSpeechRecognizer( network_module, microphone_options, base::Bind(&SpeechRecognitionManager::OnEventAvailable, base::Unretained(this)))); } -#endif // defined(SB_USE_SB_SPEECH_RECOGNIZER) } SpeechRecognitionManager::~SpeechRecognitionManager() { Abort(); }
diff --git a/src/cobalt/speech/speech_synthesis.cc b/src/cobalt/speech/speech_synthesis.cc index 2e7fce1..838134a 100644 --- a/src/cobalt/speech/speech_synthesis.cc +++ b/src/cobalt/speech/speech_synthesis.cc
@@ -22,17 +22,32 @@ namespace cobalt { namespace speech { -SpeechSynthesis::SpeechSynthesis(const scoped_refptr<dom::Navigator>& navigator, +bool SpeechSynthesis::SpeechSynthesisIsSupported() { +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION + return SbSpeechSynthesisIsSupported(); +#else + return true; +#endif +} + +SpeechSynthesis::SpeechSynthesis(script::EnvironmentSettings* settings, + const scoped_refptr<dom::Navigator>& navigator, bool log_output) - : log_output_(log_output), paused_(false), navigator_(navigator) { -#if SB_HAS(SPEECH_SYNTHESIS) - const char* kVoiceName = "Cobalt"; - std::string voice_urn(kVoiceName); - std::string voice_lang(navigator_->language()); - voice_urn.append(" "); - voice_urn.append(voice_lang); - voices_.push_back( - new SpeechSynthesisVoice(voice_urn, kVoiceName, voice_lang, false, true)); + : dom::EventTarget(settings), + log_output_(log_output), + paused_(false), + navigator_(navigator) { +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \ + SB_HAS(SPEECH_SYNTHESIS) + if (SpeechSynthesis::SpeechSynthesisIsSupported()) { + const char* kVoiceName = "Cobalt"; + std::string voice_urn(kVoiceName); + std::string voice_lang(navigator_->language()); + voice_urn.append(" "); + voice_urn.append(voice_lang); + voices_.push_back(new SpeechSynthesisVoice(voice_urn, kVoiceName, + voice_lang, false, true)); + } #endif } @@ -51,8 +66,11 @@ (*utterance_iterator)->DispatchErrorCancelledEvent(); } utterances_.clear(); -#if SB_HAS(SPEECH_SYNTHESIS) - SbSpeechSynthesisCancel(); +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \ + SB_HAS(SPEECH_SYNTHESIS) + if (SpeechSynthesis::SpeechSynthesisIsSupported()) { + SbSpeechSynthesisCancel(); + } #endif } @@ -99,26 +117,30 @@ return; } utterance->SignalPendingSpeak(); -#if SB_HAS(SPEECH_SYNTHESIS) - if (!utterance->lang().empty() && - utterance->lang() != navigator_->language()) { - DispatchErrorEvent(utterance, kSpeechSynthesisErrorCodeLanguageUnavailable); - return; - } - if ((utterance->volume() != 1.0f) || (utterance->rate() != 1.0f) || - (utterance->pitch() != 1.0f)) { - DispatchErrorEvent(utterance, kSpeechSynthesisErrorCodeInvalidArgument); - return; - } +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \ + SB_HAS(SPEECH_SYNTHESIS) + if (SpeechSynthesis::SpeechSynthesisIsSupported()) { + if (!utterance->lang().empty() && + utterance->lang() != navigator_->language()) { + DispatchErrorEvent(utterance, + kSpeechSynthesisErrorCodeLanguageUnavailable); + return; + } + if ((utterance->volume() != 1.0f) || (utterance->rate() != 1.0f) || + (utterance->pitch() != 1.0f)) { + DispatchErrorEvent(utterance, kSpeechSynthesisErrorCodeInvalidArgument); + return; + } - SB_DLOG(INFO) << "Speaking: \"" << utterance->text() << "\" " - << utterance->lang(); - SbSpeechSynthesisSpeak(utterance->text().c_str()); - utterance->DispatchStartEvent(); - utterance->DispatchEndEvent(); -#else - DispatchErrorEvent(utterance, kSpeechSynthesisErrorCodeSynthesisUnavailable); + SB_DLOG(INFO) << "Speaking: \"" << utterance->text() << "\" " + << utterance->lang(); + SbSpeechSynthesisSpeak(utterance->text().c_str()); + utterance->DispatchStartEvent(); + utterance->DispatchEndEvent(); + return; + } #endif + DispatchErrorEvent(utterance, kSpeechSynthesisErrorCodeSynthesisUnavailable); } } // namespace speech
diff --git a/src/cobalt/speech/speech_synthesis.h b/src/cobalt/speech/speech_synthesis.h index 610e973..3ff910c 100644 --- a/src/cobalt/speech/speech_synthesis.h +++ b/src/cobalt/speech/speech_synthesis.h
@@ -20,6 +20,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "cobalt/dom/event_target.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/sequence.h" #include "cobalt/script/wrappable.h" #include "cobalt/speech/speech_synthesis_utterance.h" @@ -44,8 +45,9 @@ typedef script::Sequence<scoped_refptr<SpeechSynthesisVoice> > SpeechSynthesisVoiceSequence; - explicit SpeechSynthesis(const scoped_refptr<dom::Navigator>& navigator, - bool log_output); + SpeechSynthesis(script::EnvironmentSettings* settings, + const scoped_refptr<dom::Navigator>& navigator, + bool log_output); // Readonly Attributes. bool pending() const { return !utterances_.empty(); } @@ -72,6 +74,7 @@ private: ~SpeechSynthesis() override; + bool SpeechSynthesisIsSupported(); void DispatchErrorEvent( const scoped_refptr<SpeechSynthesisUtterance>& utterance, SpeechSynthesisErrorCode error_code);
diff --git a/src/cobalt/speech/speech_synthesis_utterance.cc b/src/cobalt/speech/speech_synthesis_utterance.cc index a032c58..62c024e 100644 --- a/src/cobalt/speech/speech_synthesis_utterance.cc +++ b/src/cobalt/speech/speech_synthesis_utterance.cc
@@ -17,10 +17,19 @@ namespace cobalt { namespace speech { -SpeechSynthesisUtterance::SpeechSynthesisUtterance() - : volume_(1.0f), rate_(1.0f), pitch_(1.0f), pending_speak_(false) {} -SpeechSynthesisUtterance::SpeechSynthesisUtterance(const std::string& text) - : text_(text), +SpeechSynthesisUtterance::SpeechSynthesisUtterance( + script::EnvironmentSettings* settings) + : dom::EventTarget(settings), + settings_(settings), + volume_(1.0f), + rate_(1.0f), + pitch_(1.0f), + pending_speak_(false) {} +SpeechSynthesisUtterance::SpeechSynthesisUtterance( + script::EnvironmentSettings* settings, const std::string& text) + : dom::EventTarget(settings), + settings_(settings), + text_(text), volume_(1.0f), rate_(1.0f), pitch_(1.0f), @@ -28,7 +37,8 @@ SpeechSynthesisUtterance::SpeechSynthesisUtterance( const scoped_refptr<SpeechSynthesisUtterance>& utterance) - : text_(utterance->text_), + : dom::EventTarget(utterance->settings_), + text_(utterance->text_), lang_(utterance->lang_), voice_(utterance->voice_), volume_(utterance->volume_),
diff --git a/src/cobalt/speech/speech_synthesis_utterance.h b/src/cobalt/speech/speech_synthesis_utterance.h index 2f7247a..aaec826 100644 --- a/src/cobalt/speech/speech_synthesis_utterance.h +++ b/src/cobalt/speech/speech_synthesis_utterance.h
@@ -18,6 +18,7 @@ #include <string> #include "cobalt/dom/event_target.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/wrappable.h" #include "cobalt/speech/speech_synthesis_error_event.h" #include "cobalt/speech/speech_synthesis_voice.h" @@ -30,10 +31,11 @@ // https://dvcs.w3.org/hg/speech-api/raw-file/4f41ea1126bb/webspeechapi.html#speechsynthesisvoice class SpeechSynthesisUtterance : public dom::EventTarget { public: - SpeechSynthesisUtterance(); + explicit SpeechSynthesisUtterance(script::EnvironmentSettings* settings); SpeechSynthesisUtterance( const scoped_refptr<SpeechSynthesisUtterance>& utterance); - explicit SpeechSynthesisUtterance(const std::string& text); + SpeechSynthesisUtterance(script::EnvironmentSettings* settings, + const std::string& text); // Web API: SpeechSynthesisUtterance // @@ -131,6 +133,8 @@ private: ~SpeechSynthesisUtterance() override; + script::EnvironmentSettings* settings_; + std::string text_; std::string lang_; scoped_refptr<SpeechSynthesisVoice> voice_;
diff --git a/src/cobalt/speech/speech_synthesis_utterance.idl b/src/cobalt/speech/speech_synthesis_utterance.idl index e5b29a3..9de4a71 100644 --- a/src/cobalt/speech/speech_synthesis_utterance.idl +++ b/src/cobalt/speech/speech_synthesis_utterance.idl
@@ -16,7 +16,8 @@ [ Constructor, - Constructor(DOMString text) + Constructor(DOMString text), + ConstructorCallWith=EnvironmentSettings, ] interface SpeechSynthesisUtterance : EventTarget { attribute DOMString text;
diff --git a/src/cobalt/speech/starboard_speech_recognizer.cc b/src/cobalt/speech/starboard_speech_recognizer.cc index 61f0791..c52ee27 100644 --- a/src/cobalt/speech/starboard_speech_recognizer.cc +++ b/src/cobalt/speech/starboard_speech_recognizer.cc
@@ -26,6 +26,15 @@ namespace speech { // static +bool StarboardSpeechRecognizer::IsSupported() { +#if SB_API_VERSION >= 12 + return SbSpeechRecognizerIsSupported(); +#else + return true; +#endif +} + +// static void StarboardSpeechRecognizer::OnSpeechDetected(void* context, bool detected) { StarboardSpeechRecognizer* recognizer = static_cast<StarboardSpeechRecognizer*>(context);
diff --git a/src/cobalt/speech/starboard_speech_recognizer.h b/src/cobalt/speech/starboard_speech_recognizer.h index 6ca2af1..055da4a 100644 --- a/src/cobalt/speech/starboard_speech_recognizer.h +++ b/src/cobalt/speech/starboard_speech_recognizer.h
@@ -38,6 +38,8 @@ explicit StarboardSpeechRecognizer(const EventCallback& event_callback); ~StarboardSpeechRecognizer(); + static bool IsSupported(); + void Start(const SpeechRecognitionConfig& config) override; void Stop() override;
diff --git a/src/cobalt/storage/store/store.gyp b/src/cobalt/storage/store/store.gyp index 07c0e18..d80a876 100644 --- a/src/cobalt/storage/store/store.gyp +++ b/src/cobalt/storage/store/store.gyp
@@ -30,19 +30,6 @@ '<(DEPTH)/net/net.gyp:net', '<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_lite', ], - 'include_dirs': [ - # Get protobuf headers from the chromium tree. - '<(DEPTH)/third_party/protobuf/src', - ], - 'defines': [ - # The generated code needs to be compiled with the same flags as the protobuf library. - # Otherwise we get static initializers which are not thread safe. - # This macro must be defined to suppress the use of dynamic_cast<>, - # which requires RTTI. - 'GOOGLE_PROTOBUF_NO_RTTI', - 'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER', - 'HAVE_PTHREAD', - ], }, { 'target_name': 'memory_store_test', @@ -57,19 +44,6 @@ '<(DEPTH)/testing/gtest.gyp:gtest', 'memory_store', ], - 'include_dirs': [ - # Get protobuf headers from the chromium tree. - '<(DEPTH)/third_party/protobuf/src', - ], - 'defines': [ - # The generated code needs to be compiled with the same flags as the protobuf library. - # Otherwise we get static initializers which are not thread safe. - # This macro must be defined to suppress the use of dynamic_cast<>, - # which requires RTTI. - 'GOOGLE_PROTOBUF_NO_RTTI', - 'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER', - 'HAVE_PTHREAD', - ], }, { 'target_name': 'memory_store_test_deploy',
diff --git a/src/cobalt/storage/store_upgrade/upgrade.gyp b/src/cobalt/storage/store_upgrade/upgrade.gyp index ca1b3c2..1066f1a 100644 --- a/src/cobalt/storage/store_upgrade/upgrade.gyp +++ b/src/cobalt/storage/store_upgrade/upgrade.gyp
@@ -36,15 +36,6 @@ '<(DEPTH)/sql/sql.gyp:sql', '<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_lite', ], - 'defines': [ - 'GOOGLE_PROTOBUF_NO_RTTI', - 'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER', - 'HAVE_PTHREAD', - ], - 'include_dirs': [ - # Get protobuf headers from the chromium tree. - '<(DEPTH)/third_party/protobuf/src', - ], }, { 'target_name': 'storage_upgrade_test', @@ -62,15 +53,6 @@ '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_lite', ], - 'defines': [ - 'GOOGLE_PROTOBUF_NO_RTTI', - 'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER', - 'HAVE_PTHREAD', - ], - 'include_dirs': [ - # Get protobuf headers from the chromium tree. - '<(DEPTH)/third_party/protobuf/src', - ], }, { 'target_name': 'storage_upgrade_test_deploy',
diff --git a/src/cobalt/system_window/input_event.h b/src/cobalt/system_window/input_event.h index da7ddb1..8926ea8 100644 --- a/src/cobalt/system_window/input_event.h +++ b/src/cobalt/system_window/input_event.h
@@ -62,13 +62,15 @@ InputEvent(SbTimeMonotonic timestamp, Type type, int device_id, int key_code, uint32 modifiers, bool is_repeat, const math::PointF& position = math::PointF(), - const math::PointF& delta = math::PointF(), - float pressure = 0, const math::PointF& size = math::PointF(), + const math::PointF& delta = math::PointF(), float pressure = 0, + const math::PointF& size = math::PointF(), const math::PointF& tilt = math::PointF() -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) , const std::string& input_text = "", bool is_composing = false -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) ) : timestamp_(timestamp), type_(type), @@ -81,11 +83,13 @@ pressure_(pressure), size_(size), tilt_(tilt) -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) , input_text_(input_text), is_composing_(is_composing) -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) { } @@ -102,10 +106,12 @@ float pressure() const { return pressure_; } const math::PointF& size() const { return size_; } const math::PointF& tilt() const { return tilt_; } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) const std::string& input_text() const { return input_text_; } bool is_composing() const { return is_composing_; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) BASE_EVENT_SUBCLASS(InputEvent); @@ -121,10 +127,12 @@ float pressure_; math::PointF size_; math::PointF tilt_; -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) std::string input_text_; bool is_composing_; -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) }; // The Starboard Event handler SbHandleEvent should call this function on
diff --git a/src/cobalt/system_window/system_window.cc b/src/cobalt/system_window/system_window.cc index 82b5158..40eb174 100644 --- a/src/cobalt/system_window/system_window.cc +++ b/src/cobalt/system_window/system_window.cc
@@ -156,7 +156,8 @@ } } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) std::unique_ptr<InputEvent> input_event( new InputEvent(timestamp, type, data.device_id, key_code, modifiers, is_repeat, math::PointF(data.position.x, data.position.y), @@ -165,14 +166,16 @@ math::PointF(data.tilt.x, data.tilt.y), data.input_text ? data.input_text : "", data.is_composing ? data.is_composing : false)); -#else // SB_HAS(ON_SCREEN_KEYBOARD) +#else // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) std::unique_ptr<InputEvent> input_event( new InputEvent(timestamp, type, data.device_id, key_code, modifiers, is_repeat, math::PointF(data.position.x, data.position.y), math::PointF(data.delta.x, data.delta.y), pressure, math::PointF(data.size.x, data.size.y), math::PointF(data.tilt.x, data.tilt.y))); -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) event_dispatcher()->DispatchEvent( std::unique_ptr<base::Event>(input_event.release())); } @@ -249,12 +252,14 @@ DispatchInputEvent(data, InputEvent::kKeyMove, false /* is_repeat */); break; } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) case kSbInputEventTypeInput: { DispatchInputEvent(data, InputEvent::kInput, false /* is_repeat */); break; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) default: break; }
diff --git a/src/cobalt/test/document_loader.h b/src/cobalt/test/document_loader.h index 0b031e0..0e2730b 100644 --- a/src/cobalt/test/document_loader.h +++ b/src/cobalt/test/document_loader.h
@@ -29,6 +29,7 @@ #include "cobalt/dom/dom_parser.h" #include "cobalt/dom/dom_stat_tracker.h" #include "cobalt/dom/html_element_context.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom_parser/parser.h" #include "cobalt/loader/fetcher_factory.h" #include "cobalt/loader/image/image_cache.h" @@ -60,8 +61,9 @@ dom_stat_tracker_(new dom::DomStatTracker("IsDisplayedTest")), resource_provider_(resource_provider_stub_.get()), html_element_context_( - &fetcher_factory_, loader_factory_.get(), css_parser_.get(), - dom_parser_.get(), NULL /* can_play_type_handler */, + &environment_settings_, &fetcher_factory_, loader_factory_.get(), + css_parser_.get(), dom_parser_.get(), + NULL /* can_play_type_handler */, NULL /* web_media_player_factory */, &script_runner_, NULL /* script_value_factory */, NULL /* media_source_registry */, &resource_provider_, NULL /* animated_image_tracker */, @@ -105,6 +107,7 @@ // Nested message loop on which the document loading will occur. base::RunLoop nested_loop_; + dom::testing::StubEnvironmentSettings environment_settings_; script::FakeScriptRunner script_runner_; loader::FetcherFactory fetcher_factory_; std::unique_ptr<css_parser::Parser> css_parser_;
diff --git a/src/cobalt/test/empty_document.h b/src/cobalt/test/empty_document.h index b39b942..6d1342f 100644 --- a/src/cobalt/test/empty_document.h +++ b/src/cobalt/test/empty_document.h
@@ -22,6 +22,7 @@ #include "cobalt/dom/document.h" #include "cobalt/dom/dom_stat_tracker.h" #include "cobalt/dom/html_element_context.h" +#include "cobalt/dom/testing/stub_environment_settings.h" namespace cobalt { namespace test { @@ -33,15 +34,16 @@ EmptyDocument() : css_parser_(css_parser::Parser::Create()), dom_stat_tracker_(new dom::DomStatTracker("EmptyDocument")), - html_element_context_(NULL, NULL, css_parser_.get(), NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, dom_stat_tracker_.get(), "", - base::kApplicationStateStarted, NULL), + html_element_context_( + &environment_settings_, NULL, NULL, css_parser_.get(), NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + dom_stat_tracker_.get(), "", base::kApplicationStateStarted, NULL), document_(new dom::Document(&html_element_context_)) {} dom::Document* document() { return document_.get(); } private: + dom::testing::StubEnvironmentSettings environment_settings_; std::unique_ptr<css_parser::Parser> css_parser_; std::unique_ptr<dom::DomStatTracker> dom_stat_tracker_; dom::HTMLElementContext html_element_context_;
diff --git a/src/cobalt/test/mock_debugger_hooks.h b/src/cobalt/test/mock_debugger_hooks.h new file mode 100644 index 0000000..bbd8adc --- /dev/null +++ b/src/cobalt/test/mock_debugger_hooks.h
@@ -0,0 +1,39 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COBALT_TEST_MOCK_DEBUGGER_HOOKS_H_ +#define COBALT_TEST_MOCK_DEBUGGER_HOOKS_H_ + +#include <string> + +#include "cobalt/base/debugger_hooks.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace cobalt { +namespace test { + +class MockDebuggerHooks : public base::DebuggerHooks { + public: + MOCK_CONST_METHOD3(AsyncTaskScheduled, + void(const void* task, const std::string& name, + AsyncTaskFrequency frequency)); + MOCK_CONST_METHOD1(AsyncTaskStarted, void(const void* task)); + MOCK_CONST_METHOD1(AsyncTaskFinished, void(const void* task)); + MOCK_CONST_METHOD1(AsyncTaskCanceled, void(const void* task)); +}; + +} // namespace test +} // namespace cobalt + +#endif // COBALT_TEST_MOCK_DEBUGGER_HOOKS_H_
diff --git a/src/cobalt/tools/automated_testing/cobalt_runner.py b/src/cobalt/tools/automated_testing/cobalt_runner.py index 8e3d6b0..3f392c9 100644 --- a/src/cobalt/tools/automated_testing/cobalt_runner.py +++ b/src/cobalt/tools/automated_testing/cobalt_runner.py
@@ -21,6 +21,8 @@ # Pattern to match Cobalt log line for when the WebDriver port has been # opened. RE_WEBDRIVER_LISTEN = re.compile(r'Starting WebDriver server on port (\d+)') +# Pattern to match Cobalt log line if WebDriver server fails to start. +RE_WEBDRIVER_FAILED = re.compile(r'Could not start WebDriver server') # Pattern to match Cobalt log line for when a WindowDriver has been created. RE_WINDOWDRIVER_CREATED = re.compile( r'^\[[\d:]+/[\d.]+:INFO:browser_module\.cc\(\d+\)\] Created WindowDriver: ID=\S+' @@ -176,6 +178,12 @@ if self.test_script_started.is_set(): continue + # Bail out immediately if the Cobalt WebDriver server doesn't start. + if RE_WEBDRIVER_FAILED.search(line): + print('\nCobalt WebDriver server not started.' + '\nIs another instance of Cobalt running?') + self.launcher.Kill() + match = RE_WEBDRIVER_LISTEN.search(line) if not match: continue @@ -185,7 +193,6 @@ self._StartWebdriver(port) def __enter__(self): - self.Run() return self
diff --git a/src/cobalt/tools/cobalt_archive_runner.py b/src/cobalt/tools/cobalt_archive_runner.py deleted file mode 100644 index a2238f1..0000000 --- a/src/cobalt/tools/cobalt_archive_runner.py +++ /dev/null
@@ -1,225 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""Runs a cobalt archive without any dependencies on external code.""" - - -import argparse -import json -import logging -import os -import shutil -import subprocess -import sys -import tempfile -import zipfile - - -# pylint: disable=bad-continuation -_HELP_MSG = ( -""" -Loads & Runs a Cobalt Archive. - -Example 1: Prints the archive metadata. - python cobalt_archive_runner.py <ARCHIVE.ZIP> - -Example 2: - python cobalt_archive_runner.py <ARCHIVE.ZIP> -- run_tests nplb - -Example 3: - python cobalt_archive_runner.py <ARCHIVE.ZIP> -- run cobalt - -Example 4: - python cobalt_archive_runner.py --temp_dir <temp/path> <ARCHIVE.ZIP> -- run_tests nplb - -Example 5: - python cobalt_archive_runner.py --temp_dir <temp/path> <ARCHIVE.ZIP> -- python starboard/tools/testing/test_runner.py <args...> -""" -) - -# Suffix path for metadata inside the archive, unix style paths required. -_METADATA_JSON_SUFFIX = '__cobalt_archive/metadata.json' - -# Use unix-style paths needed for zip and win32 seems to handle unix style paths -# just fine. -_DECOMPRESS_PY_SUFFIX = '__cobalt_archive/finalize_decompression/decompress.py' - - -def _Print(s): - """Unix style end-lines.""" - sys.stdout.write(s + '\n') - - -def _CallShell(cmd_str, cwd=None): - p = subprocess.Popen(cmd_str, cwd=cwd, shell=True, universal_newlines=True) - try: - return p.wait() - except KeyboardInterrupt as kerr: - p.terminate() - raise kerr - return 1 - - -def _ReadMetadataFromArchive(zip_path): - if not os.path.isfile(zip_path): - raise IOError('%s does not exist.' % zip_path) - with zipfile.ZipFile(zip_path, 'r', allowZip64=True) as zf: - return json.loads(zf.read(_METADATA_JSON_SUFFIX)) - - -def _GetBaseTempDir(): - base_dir = os.path.join(tempfile.gettempdir(), 'car_tmp') - if not os.path.exists(base_dir): - os.makedirs(base_dir) - return base_dir - - -def _MakeOutputPath(): - base_dir = _GetBaseTempDir() - return tempfile.mkdtemp(prefix='', dir=base_dir) - - -def _MetadataToPrettyPrintString(metadata): - strings = [] - for key, val in sorted(metadata.items(), key=lambda x: x[0]): - strings.append(' %s: %s' % (key, val)) - return '\n'.join(strings) - - -def _TryGetTrampoline(unpack_dir, command): - """Returns a valid tranpoline from the given input, else None.""" - trampoline_target = os.path.join( - unpack_dir, '__cobalt_archive', 'run', command + '.py') - if os.path.isfile(trampoline_target): - return trampoline_target - else: - return None - - -def _UnpackArchive(archive, unpack_dir): - """Unpacks archive into the unpack_dir.""" - if not os.path.isfile(archive): - raise IOError('%s does not exist.' % archive) - unpack_dir = os.path.abspath(unpack_dir) - _Print('Unzipping %s -> %s' % (archive, unpack_dir)) - # First pass, unzip all files. - with zipfile.ZipFile(archive, 'r', allowZip64=True) as zf: - for zinfo in zf.infolist(): - try: - zf.extract(zinfo, path=unpack_dir) - except Exception as err: # pylint: disable=broad-except - msg = ( - 'Exception happend during extraction of %s because of error %s' - % (zinfo.filename, err) - ) - _Print(msg) - # Second pass, execute the final decompress, which expands symlinks and other - # file system operations. - decomp_py = os.path.abspath(os.path.join(unpack_dir, _DECOMPRESS_PY_SUFFIX)) - cmd = 'python "%s"' % decomp_py - _Print(cmd) - if _CallShell(cmd) != 0: - raise IOError('Failed to unzip %s' % archive) - with open(os.path.join(unpack_dir, _METADATA_JSON_SUFFIX)) as fd: - return json.loads(fd.read()) - - -def _RunTrampoline(unpack_dir, trampoline, args): - trampoline_target = _TryGetTrampoline(unpack_dir, trampoline) - if trampoline_target is None: - raise IOError('Trampoline %s does not exist.' % trampoline) - if args: - _Print('Invoking trampoline %s with args %s' % (trampoline, args)) - else: - _Print('Invoking trampoline %s' % trampoline) - trampoline = ['python', trampoline_target] + args - cmd_str = ' '.join(trampoline) - _CallShell(cmd_str, cwd=unpack_dir) - - -def _RunCommand(unpack_dir, command, args): - cmd_str = ' '.join([command] + args) - _CallShell(cmd_str, cwd=unpack_dir) - - -def _Clean(d): - _Print('Deleting: {}'.format(d)) - shutil.rmtree(d) - - -def _ParseArgs(argv): - """Parses the argument array and returns it as a namespace.""" - - class MyParser(argparse.ArgumentParser): - - def error(self, message): - self.print_help() - sys.stderr.write('\n\nerror: %s\n' % message) - sys.exit(2) - # Enables new lines in the description and epilog. - formatter_class = argparse.RawDescriptionHelpFormatter - parser = MyParser(epilog=_HELP_MSG, formatter_class=formatter_class) - parser.add_argument('archive') - parser.add_argument('command', nargs='?') - parser.add_argument('--temp_dir', '-t') - parser.add_argument('--keep', '-k', action='store_true') - parser.add_argument('command_arg', nargs='*') - args = parser.parse_args(argv) - if args.temp_dir: - args.keep = True - return args - - -def main(): - """Parses input executes proper actions.""" - fmt = '[%(filename)s:%(lineno)s:%(levelname)s] %(message)s' - logging.basicConfig(format=fmt, level=logging.INFO) - args = _ParseArgs(sys.argv[1:]) - if args.archive: - metadata = _ReadMetadataFromArchive(args.archive) - metadata_str = _MetadataToPrettyPrintString(metadata) - _Print('Archive %s\n%s' % (args.archive, metadata_str)) - cleanup_fcn = [] - if args.command: - if args.temp_dir: - temp_dir = args.temp_dir - else: - temp_dir = _MakeOutputPath() - _Print('Using %s' % temp_dir) - if not args.keep: - cleanup_fcn.append(lambda: _Clean(temp_dir)) - try: - if args.command: - _UnpackArchive(args.archive, temp_dir) - # Try to resolve the command arguments as a trampoline first. - if _TryGetTrampoline(temp_dir, args.command): - _RunTrampoline(temp_dir, args.command, args.command_arg) - else: - # Otherwise attempt to run the command as a normal command rooted at - # the cobalt archive unpacked directory. - _RunCommand(temp_dir, args.command, args.command_arg) - finally: - [f() for f in cleanup_fcn] - - -if __name__ == '__main__': - try: - main() - sys.exit(0) - except Exception as err: # pylint: disable=broad-except - logging.exception(err) - sys.exit(1)
diff --git a/src/cobalt/tools/cobalt_archive_runner_test.py b/src/cobalt/tools/cobalt_archive_runner_test.py deleted file mode 100644 index b93e326..0000000 --- a/src/cobalt/tools/cobalt_archive_runner_test.py +++ /dev/null
@@ -1,76 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""Runs a cobalt archive without any dependencies on external code.""" - - -import sys -import unittest - - -import _env # pylint: disable=relative-import,unused-import -import cobalt.tools.cobalt_archive_runner as car_runner - - -class CobaltArchiveRunnerArgTest(unittest.TestCase): - - def testArchiveOnly(self): - input_args = ['ARCHIVE.ZIP'] - args = car_runner._ParseArgs(input_args) - self.assertEqual('ARCHIVE.ZIP', args.archive) - self.assertEqual(None, args.temp_dir) - self.assertEqual(False, args.keep) - self.assertEqual(None, args.command) - self.assertEqual([], args.command_arg) - - def testTrampoline(self): - input_args = ['ARCHIVE.ZIP', '--', 'run_tests', '-t', 'nplb'] - args = car_runner._ParseArgs(input_args) - self.assertEqual('ARCHIVE.ZIP', args.archive) - self.assertEqual('run_tests', args.command) - self.assertEqual(None, args.temp_dir) - self.assertEqual(False, args.keep) - self.assertEqual('run_tests', args.command) - self.assertEqual(['-t', 'nplb'], args.command_arg) - - def testKeep(self): - input_args = ['--keep', 'ARCHIVE.ZIP'] - args = car_runner._ParseArgs(input_args) - self.assertEqual('ARCHIVE.ZIP', args.archive) - self.assertEqual(None, args.command) - self.assertEqual(None, args.temp_dir) - self.assertEqual(True, args.keep) - self.assertEqual(None, args.command) - self.assertEqual([], args.command_arg) - - def testBasicKeepSetWhenTempDirIsUsed(self): - input_args = [ - '--temp_dir', 'temp/path', 'ARCHIVE.ZIP', '--', - 'run_tests', '-t', 'nplb' - ] - args = car_runner._ParseArgs(input_args) - self.assertEqual('ARCHIVE.ZIP', args.archive) - self.assertEqual('run_tests', args.command) - self.assertEqual('temp/path', args.temp_dir) - self.assertEqual(True, args.keep) - self.assertEqual('run_tests', args.command) - self.assertEqual(['-t', 'nplb'], args.command_arg) - - -if __name__ == '__main__': - unittest.main() - sys.exit(0)
diff --git a/src/cobalt/tools/collectd/README.md b/src/cobalt/tools/collectd/README.md index 9148e19..d30698a 100644 --- a/src/cobalt/tools/collectd/README.md +++ b/src/cobalt/tools/collectd/README.md
@@ -28,10 +28,6 @@ data streams are sent to a host in a [networked configuration](https://collectd.org/wiki/index.php/Networking_introduction) and not detailed here. -Cobalt DevTools service currently does not listen on localhost or 127.0.0.1 -address, so you'll need to manually edit cobalt.conf with your local machine -network adapter IP address, or to target IP address. - **Note**: The script also enables RRD and CSV data outputs, RRD is required for CGP to display the data and CSV is useful for post-processing.
diff --git a/src/cobalt/updater/BRANDING b/src/cobalt/updater/BRANDING deleted file mode 100644 index 49eb4d5..0000000 --- a/src/cobalt/updater/BRANDING +++ /dev/null
@@ -1,4 +0,0 @@ -COMPANY_FULLNAME=Google LLC -COMPANY_SHORTNAME=Google -PRODUCT_FULLNAME=GoogleUpdater -COPYRIGHT=Copyright 2019 The Chromium Authors. All rights reserved.
diff --git a/src/cobalt/updater/BUILD.gn b/src/cobalt/updater/BUILD.gn deleted file mode 100644 index 6de5b53..0000000 --- a/src/cobalt/updater/BUILD.gn +++ /dev/null
@@ -1,102 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/chrome_build.gni") -import("//build/config/sanitizers/sanitizers.gni") -import("//build/util/process_version.gni") -import("//testing/test.gni") - -group("updater") { - if (is_win) { - deps = [ - "//chrome/updater/win", - ] - } - if (is_mac) { - deps = [ - "//chrome/updater/mac", - ] - } -} - -# Conditional build is needed, otherwise the analyze script on Linux -# requires all targets and it is going to include the targets below. -if (is_win || is_mac) { - source_set("common") { - sources = [ - "configurator.cc", - "configurator.h", - "crash_client.cc", - "crash_client.h", - "crash_reporter.cc", - "crash_reporter.h", - "installer.cc", - "installer.h", - "patcher.cc", - "patcher.h", - "prefs.cc", - "prefs.h", - "unzipper.cc", - "unzipper.h", - "updater.cc", - "updater.h", - "updater_constants.cc", - "updater_constants.h", - "util.cc", - "util.h", - ] - - deps = [ - ":version_header", - "//base", - "//components/crash/core/common:crash_key", - "//components/prefs", - "//components/update_client", - "//components/version_info", - "//courgette", - "//third_party/crashpad/crashpad/client", - "//third_party/crashpad/crashpad/handler", - "//third_party/zlib/google:zip", - "//url", - ] - } - - process_version("version_header") { - sources = [ - "//chrome/VERSION", - "BRANDING", - ] - template_file = "updater_version.h.in" - output = "$target_gen_dir/updater_version.h" - } - - source_set("updater_tests") { - testonly = true - - sources = [ - "updater_unittest.cc", - ] - - deps = [ - ":common", - ":updater", - "//base/test:test_support", - "//testing/gtest", - ] - - if (is_win) { - deps += [ "//chrome/updater/win:updater_tests" ] - - data_deps = [ - "//chrome/updater/win:updater", - ] - } - - if (is_mac) { - data_deps = [ - "//chrome/updater/mac:updater", - ] - } - } -}
diff --git a/src/cobalt/updater/README.md b/src/cobalt/updater/README.md deleted file mode 100644 index 67d0c46..0000000 --- a/src/cobalt/updater/README.md +++ /dev/null
@@ -1,4 +0,0 @@ -This is the code for the client updater that will soon be used by -desktop Chrome, on macOS and Windows. - -Please join chrome-updates-dev@chromium.org for topics related to this project.
diff --git a/src/cobalt/updater/configurator.cc b/src/cobalt/updater/configurator.cc deleted file mode 100644 index 8e372ad..0000000 --- a/src/cobalt/updater/configurator.cc +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/configurator.h" - -#include <utility> -#include "base/version.h" -#include "build/build_config.h" -#include "chrome/updater/patcher.h" -#include "chrome/updater/prefs.h" -#include "chrome/updater/unzipper.h" -#include "chrome/updater/updater_constants.h" -#include "components/prefs/pref_service.h" -#include "components/update_client/network.h" -#include "components/update_client/patcher.h" -#include "components/update_client/protocol_handler.h" -#include "components/update_client/unzipper.h" -#include "components/version_info/version_info.h" -#include "url/gurl.h" - -#if defined(OS_WIN) -#include "chrome/updater/win/net/network.h" -#endif - -namespace { - -// Default time constants. -const int kDelayOneMinute = 60; -const int kDelayOneHour = kDelayOneMinute * 60; - -} // namespace - -namespace updater { - -Configurator::Configurator() - : pref_service_(CreatePrefService()), - unzip_factory_(base::MakeRefCounted<UnzipperFactory>()), - patch_factory_(base::MakeRefCounted<PatcherFactory>()) {} -Configurator::~Configurator() = default; - -int Configurator::InitialDelay() const { - return 0; -} - -int Configurator::NextCheckDelay() const { - return 5 * kDelayOneHour; -} - -int Configurator::OnDemandDelay() const { - return 0; -} - -int Configurator::UpdateDelay() const { - return 0; -} - -std::vector<GURL> Configurator::UpdateUrl() const { - return std::vector<GURL>{GURL(kUpdaterJSONDefaultUrl)}; -} - -std::vector<GURL> Configurator::PingUrl() const { - return UpdateUrl(); -} - -std::string Configurator::GetProdId() const { - return "updater"; -} - -base::Version Configurator::GetBrowserVersion() const { - return version_info::GetVersion(); -} - -std::string Configurator::GetChannel() const { - return {}; -} - -std::string Configurator::GetBrand() const { - return {}; -} - -std::string Configurator::GetLang() const { - return "en-US"; -} - -std::string Configurator::GetOSLongName() const { - return version_info::GetOSType(); -} - -base::flat_map<std::string, std::string> Configurator::ExtraRequestParams() - const { - return {{"testrequest", "1"}, {"testsource", "dev"}}; -} - -std::string Configurator::GetDownloadPreference() const { - return {}; -} - -scoped_refptr<update_client::NetworkFetcherFactory> -Configurator::GetNetworkFetcherFactory() { -#if defined(OS_WIN) - if (!network_fetcher_factory_) { - network_fetcher_factory_ = base::MakeRefCounted<NetworkFetcherFactory>(); - } - return network_fetcher_factory_; -#else - return nullptr; -#endif -} - -scoped_refptr<update_client::UnzipperFactory> -Configurator::GetUnzipperFactory() { - return unzip_factory_; -} - -scoped_refptr<update_client::PatcherFactory> Configurator::GetPatcherFactory() { - return patch_factory_; -} - -bool Configurator::EnabledDeltas() const { - return false; -} - -bool Configurator::EnabledComponentUpdates() const { - return false; -} - -bool Configurator::EnabledBackgroundDownloader() const { - return false; -} - -bool Configurator::EnabledCupSigning() const { - return true; -} - -PrefService* Configurator::GetPrefService() const { - return pref_service_.get(); -} - -update_client::ActivityDataService* Configurator::GetActivityDataService() - const { - return nullptr; -} - -bool Configurator::IsPerUserInstall() const { - return true; -} - -std::vector<uint8_t> Configurator::GetRunActionKeyHash() const { - return {}; -} - -std::string Configurator::GetAppGuid() const { - return {}; -} - -std::unique_ptr<update_client::ProtocolHandlerFactory> -Configurator::GetProtocolHandlerFactory() const { - return std::make_unique<update_client::ProtocolHandlerFactoryJSON>(); -} - -update_client::RecoveryCRXElevator Configurator::GetRecoveryCRXElevator() - const { - return {}; -} - -} // namespace updater
diff --git a/src/cobalt/updater/configurator.h b/src/cobalt/updater/configurator.h deleted file mode 100644 index d5bbd3c..0000000 --- a/src/cobalt/updater/configurator.h +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_CONFIGURATOR_H_ -#define CHROME_UPDATER_CONFIGURATOR_H_ - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "components/update_client/configurator.h" - -class GURL; -class PrefService; - -namespace base { -class Version; -} // namespace base - -namespace update_client { -class ActivityDataService; -class NetworkFetcherFactory; -class ProtocolHandlerFactory; -} // namespace update_client - -namespace updater { - -class Configurator : public update_client::Configurator { - public: - Configurator(); - - // Configurator for update_client::Configurator. - int InitialDelay() const override; - int NextCheckDelay() const override; - int OnDemandDelay() const override; - int UpdateDelay() const override; - std::vector<GURL> UpdateUrl() const override; - std::vector<GURL> PingUrl() const override; - std::string GetProdId() const override; - base::Version GetBrowserVersion() const override; - std::string GetChannel() const override; - std::string GetBrand() const override; - std::string GetLang() const override; - std::string GetOSLongName() const override; - base::flat_map<std::string, std::string> ExtraRequestParams() const override; - std::string GetDownloadPreference() const override; - scoped_refptr<update_client::NetworkFetcherFactory> GetNetworkFetcherFactory() - override; - scoped_refptr<update_client::UnzipperFactory> GetUnzipperFactory() override; - scoped_refptr<update_client::PatcherFactory> GetPatcherFactory() override; - bool EnabledDeltas() const override; - bool EnabledComponentUpdates() const override; - bool EnabledBackgroundDownloader() const override; - bool EnabledCupSigning() const override; - PrefService* GetPrefService() const override; - update_client::ActivityDataService* GetActivityDataService() const override; - bool IsPerUserInstall() const override; - std::vector<uint8_t> GetRunActionKeyHash() const override; - std::string GetAppGuid() const override; - std::unique_ptr<update_client::ProtocolHandlerFactory> - GetProtocolHandlerFactory() const override; - update_client::RecoveryCRXElevator GetRecoveryCRXElevator() const override; - - private: - friend class base::RefCountedThreadSafe<Configurator>; - ~Configurator() override; - - std::unique_ptr<PrefService> pref_service_; - scoped_refptr<update_client::NetworkFetcherFactory> network_fetcher_factory_; - scoped_refptr<update_client::UnzipperFactory> unzip_factory_; - scoped_refptr<update_client::PatcherFactory> patch_factory_; - DISALLOW_COPY_AND_ASSIGN(Configurator); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_CONFIGURATOR_H_
diff --git a/src/cobalt/updater/crash_client.cc b/src/cobalt/updater/crash_client.cc deleted file mode 100644 index d1d9fc0..0000000 --- a/src/cobalt/updater/crash_client.cc +++ /dev/null
@@ -1,159 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/crash_client.h" - -#include <algorithm> -#include <vector> - -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/no_destructor.h" -#include "base/path_service.h" -#include "base/strings/string_util.h" -#include "build/build_config.h" -#include "chrome/updater/util.h" -#include "third_party/crashpad/crashpad/client/crash_report_database.h" -#include "third_party/crashpad/crashpad/client/crashpad_client.h" -#include "third_party/crashpad/crashpad/client/prune_crash_reports.h" -#include "third_party/crashpad/crashpad/client/settings.h" - -#if defined(OS_WIN) -#include <windows.h> -#include "base/win/wrapped_window_proc.h" -#endif - -namespace { - -#if defined(OS_WIN) - -int __cdecl HandleWinProcException(EXCEPTION_POINTERS* exception_pointers) { - crashpad::CrashpadClient::DumpAndCrash(exception_pointers); - return EXCEPTION_CONTINUE_SEARCH; -} - -#endif - -} // namespace - -namespace updater { - -CrashClient::CrashClient() = default; -CrashClient::~CrashClient() = default; - -// static -CrashClient* CrashClient::GetInstance() { - static base::NoDestructor<CrashClient> crash_client; - return crash_client.get(); -} - -bool CrashClient::InitializeDatabaseOnly() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - base::FilePath handler_path; - base::PathService::Get(base::FILE_EXE, &handler_path); - - base::FilePath database_path; - if (!GetProductDirectory(&database_path)) { - LOG(ERROR) << "Failed to get the database path."; - return false; - } - - database_ = crashpad::CrashReportDatabase::Initialize(database_path); - if (!database_) { - LOG(ERROR) << "Failed to initialize Crashpad database."; - return false; - } - - return true; -} - -bool CrashClient::InitializeCrashReporting() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!InitializeDatabaseOnly()) - return false; - -#if defined(OS_WIN) - // Catch exceptions thrown from a window procedure. - base::win::WinProcExceptionFilter exception_filter = - base::win::SetWinProcExceptionFilter(&HandleWinProcException); - LOG_IF(DFATAL, exception_filter) << "Exception filter already present"; -#endif // OS_WIN - - std::vector<crashpad::CrashReportDatabase::Report> reports_completed; - const crashpad::CrashReportDatabase::OperationStatus status_completed = - database_->GetCompletedReports(&reports_completed); - if (status_completed == crashpad::CrashReportDatabase::kNoError) { - VLOG(1) << "Found " << reports_completed.size() - << " completed crash reports"; - for (const auto& report : reports_completed) { - VLOG(1) << "Crash since last run: ID \"" << report.id << "\", created at " - << report.creation_time << ", " << report.upload_attempts - << " upload attempts, file path \"" << report.file_path - << "\", unique ID \"" << report.uuid.ToString() - << "\"; uploaded: " << (report.uploaded ? "yes" : "no"); - } - } else { - LOG(ERROR) << "Failed to fetch completed crash reports: " - << status_completed; - } - - std::vector<crashpad::CrashReportDatabase::Report> reports_pending; - const crashpad::CrashReportDatabase::OperationStatus status_pending = - database_->GetPendingReports(&reports_pending); - if (status_pending == crashpad::CrashReportDatabase::kNoError) { - VLOG(1) << "Found " << reports_pending.size() << " pending crash reports"; - for (const auto& report : reports_pending) { - VLOG(1) << "Crash since last run: (pending), created at " - << report.creation_time << ", " << report.upload_attempts - << " upload attempts, file path \"" << report.file_path - << "\", unique ID \"" << report.uuid.ToString() << "\""; - } - } else { - LOG(ERROR) << "Failed to fetch pending crash reports: " << status_pending; - } - - // TODO(sorin): fix before shipping to users, crbug.com/940098. - crashpad::Settings* crashpad_settings = database_->GetSettings(); - DCHECK(crashpad_settings); - crashpad_settings->SetUploadsEnabled(true); - - return true; -} - -// static -std::string CrashClient::GetClientId() { - DCHECK_CALLED_ON_VALID_SEQUENCE(GetInstance()->sequence_checker_); - DCHECK(GetInstance()->database_) << "Crash reporting not initialized"; - crashpad::Settings* settings = GetInstance()->database_->GetSettings(); - DCHECK(settings); - - crashpad::UUID uuid; - if (!settings->GetClientID(&uuid)) { - LOG(ERROR) << "Unable to retrieve client ID from Crashpad database"; - return {}; - } - - std::string uuid_string = uuid.ToString(); - base::ReplaceSubstringsAfterOffset(&uuid_string, 0, "-", ""); - return uuid_string; -} - -// static -bool CrashClient::IsUploadEnabled() { - DCHECK_CALLED_ON_VALID_SEQUENCE(GetInstance()->sequence_checker_); - DCHECK(GetInstance()->database_) << "Crash reporting not initialized"; - crashpad::Settings* settings = GetInstance()->database_->GetSettings(); - DCHECK(settings); - - bool upload_enabled = false; - if (!settings->GetUploadsEnabled(&upload_enabled)) { - LOG(ERROR) << "Unable to verify if crash uploads are enabled or not"; - return false; - } - return upload_enabled; -} - -} // namespace updater
diff --git a/src/cobalt/updater/crash_client.h b/src/cobalt/updater/crash_client.h deleted file mode 100644 index c5fc117..0000000 --- a/src/cobalt/updater/crash_client.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_CRASH_CLIENT_H_ -#define CHROME_UPDATER_CRASH_CLIENT_H_ - -#include <memory> -#include <string> - -#include "base/macros.h" -#include "base/sequence_checker.h" - -namespace base { -template <typename T> -class NoDestructor; -} // namespace base - -namespace crashpad { -class CrashReportDatabase; -} // namespace crashpad - -namespace updater { - -// This class manages interaction with the crash reporter. -class CrashClient { - public: - static CrashClient* GetInstance(); - - // Retrieves the current guid associated with crashes. The value may be empty - // if no guid is associated. - static std::string GetClientId(); - - // Returns true if the upload of crashes is enabled. - static bool IsUploadEnabled(); - - // Initializes collection and upload of crash reports. - bool InitializeCrashReporting(); - - // Initializes the crash database only. Used in the crash reporter, which - // cannot connect to itself to upload its own crashes. - bool InitializeDatabaseOnly(); - - crashpad::CrashReportDatabase* database() { return database_.get(); } - - private: - friend class base::NoDestructor<CrashClient>; - - CrashClient(); - ~CrashClient(); - - SEQUENCE_CHECKER(sequence_checker_); - std::unique_ptr<crashpad::CrashReportDatabase> database_; - - DISALLOW_COPY_AND_ASSIGN(CrashClient); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_CRASH_CLIENT_H_
diff --git a/src/cobalt/updater/crash_reporter.cc b/src/cobalt/updater/crash_reporter.cc deleted file mode 100644 index 41d7138..0000000 --- a/src/cobalt/updater/crash_reporter.cc +++ /dev/null
@@ -1,146 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/crash_reporter.h" - -#include <map> -#include <memory> -#include <vector> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/stl_util.h" -#include "base/strings/strcat.h" -#include "base/strings/string16.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/updater/updater_constants.h" -#include "chrome/updater/updater_version.h" -#include "chrome/updater/util.h" -#include "third_party/crashpad/crashpad/client/crashpad_client.h" -#include "third_party/crashpad/crashpad/handler/handler_main.h" - -namespace { - -// True if the current process is connected to a crash handler process. -bool g_is_connected_to_crash_handler = false; - -crashpad::CrashpadClient* GetCrashpadClient() { - static auto* crashpad_client = new crashpad::CrashpadClient(); - return crashpad_client; -} - -void RemoveSwitchIfExisting(const char* switch_to_remove, - std::vector<base::CommandLine::StringType>* argv) { - const std::string pattern = base::StrCat({"--", switch_to_remove}); - auto matches_switch = - [&pattern](const base::CommandLine::StringType& argument) -> bool { -#if defined(OS_WIN) - return base::StartsWith(argument, base::UTF8ToUTF16(pattern), - base::CompareCase::SENSITIVE); -#else - return base::StartsWith(argument, pattern, base::CompareCase::SENSITIVE); -#endif // OS_WIN - }; - base::EraseIf(*argv, matches_switch); -} - -} // namespace - -namespace updater { - -void StartCrashReporter(const std::string& version) { - static bool started = false; - DCHECK(!started); - started = true; - - base::FilePath handler_path; - base::PathService::Get(base::FILE_EXE, &handler_path); - - base::FilePath database_path; - if (!GetProductDirectory(&database_path)) { - LOG(DFATAL) << "Failed to get the database path."; - return; - } - - std::map<std::string, std::string> annotations; // Crash keys. - annotations["ver"] = version; - annotations["prod"] = PRODUCT_FULLNAME_STRING; - - std::vector<std::string> arguments; - arguments.push_back(base::StrCat({"--", kCrashHandlerSwitch})); - - crashpad::CrashpadClient* client = GetCrashpadClient(); - if (!client->StartHandler(handler_path, database_path, - /*metrics_dir=*/base::FilePath(), - kCrashStagingUploadURL, annotations, arguments, - /*restartable=*/true, - /*asynchronous_start=*/false)) { - LOG(DFATAL) << "Failed to start handler."; - return; - } - - g_is_connected_to_crash_handler = true; - VLOG(1) << "Crash handler launched and ready."; -} - -int CrashReporterMain() { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - DCHECK(command_line->HasSwitch(kCrashHandlerSwitch)); - - // Disable rate-limiting until this is fixed: - // https://bugs.chromium.org/p/crashpad/issues/detail?id=23 - command_line->AppendSwitch(kNoRateLimitSwitch); - - std::vector<base::CommandLine::StringType> argv = command_line->argv(); - - // Because of https://bugs.chromium.org/p/crashpad/issues/detail?id=82, - // Crashpad fails on the presence of flags it doesn't handle. - RemoveSwitchIfExisting(kCrashHandlerSwitch, &argv); - - // |storage| must be declared before |argv_as_utf8|, to ensure it outlives - // |argv_as_utf8|, which will hold pointers into |storage|. - std::vector<std::string> storage; - std::unique_ptr<char*[]> argv_as_utf8(new char*[argv.size() + 1]); - storage.reserve(argv.size()); - for (size_t i = 0; i < argv.size(); ++i) { -#if defined(OS_WIN) - storage.push_back(base::UTF16ToUTF8(argv[i])); -#else - storage.push_back(argv[i]); -#endif - argv_as_utf8[i] = &storage[i][0]; - } - argv_as_utf8[argv.size()] = nullptr; - - return crashpad::HandlerMain(static_cast<int>(argv.size()), - argv_as_utf8.get(), - /*user_stream_sources=*/nullptr); -} - -#if defined(OS_WIN) - -base::string16 GetCrashReporterIPCPipeName() { - return g_is_connected_to_crash_handler - ? GetCrashpadClient()->GetHandlerIPCPipe() - : base::string16(); -} - -void UseCrashReporter(const base::string16& ipc_pipe_name) { - DCHECK(!ipc_pipe_name.empty()); - crashpad::CrashpadClient* crashpad_client = GetCrashpadClient(); - if (!crashpad_client->SetHandlerIPCPipe(ipc_pipe_name)) { - LOG(DFATAL) << "Failed to set handler IPC pipe name: " << ipc_pipe_name; - return; - } - - g_is_connected_to_crash_handler = true; - VLOG(1) << "Crash handler is ready."; -} - -#endif // OS_WIN - -} // namespace updater
diff --git a/src/cobalt/updater/crash_reporter.h b/src/cobalt/updater/crash_reporter.h deleted file mode 100644 index 82b53fd..0000000 --- a/src/cobalt/updater/crash_reporter.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_CRASH_REPORTER_H_ -#define CHROME_UPDATER_CRASH_REPORTER_H_ - -#include <string> - -#include "base/strings/string16.h" -#include "build/build_config.h" - -namespace updater { - -// Starts a new instance of this executable running as the crash reporter -// process. -void StartCrashReporter(const std::string& version); - -// Runs the crash reporter message loop within the current process. On return, -// the current process should exit. -int CrashReporterMain(); - -#if defined(OS_WIN) - -// Returns the name of the IPC pipe that is used to communicate with the -// crash reporter process, or an empty string if the current process is -// not connected to a crash reporter process. -base::string16 GetCrashReporterIPCPipeName(); - -// Uses the crash reporter with the specified |ipc_pipe_name|, instead of -// starting a new crash reporter process. -void UseCrashReporter(const base::string16& ipc_pipe_name); - -#endif // OS_WIN - -} // namespace updater - -#endif // CHROME_UPDATER_CRASH_REPORTER_H_
diff --git a/src/cobalt/updater/installer.cc b/src/cobalt/updater/installer.cc deleted file mode 100644 index 904c9ed..0000000 --- a/src/cobalt/updater/installer.cc +++ /dev/null
@@ -1,189 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/installer.h" - -#include <utility> - -#include "base/callback.h" -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "chrome/updater/updater_constants.h" -#include "chrome/updater/util.h" -#include "components/crx_file/crx_verifier.h" -#include "components/update_client/update_client_errors.h" -#include "components/update_client/utils.h" - -namespace updater { - -namespace { - -// Version "0" corresponds to no installed version. -const char kNullVersion[] = "0.0.0.0"; - -// Returns the full path to the installation directory for the application -// identified by the |crx_id|. -base::FilePath GetAppInstallDir(const std::string& crx_id) { - base::FilePath app_install_dir; - if (GetProductDirectory(&app_install_dir)) { - app_install_dir = app_install_dir.AppendASCII(kAppsDir); - app_install_dir = app_install_dir.AppendASCII(crx_id); - } - return app_install_dir; -} - -} // namespace - -Installer::InstallInfo::InstallInfo() : version(kNullVersion) {} -Installer::InstallInfo::~InstallInfo() = default; - -Installer::Installer(const std::vector<uint8_t>& pk_hash) - : pk_hash_(pk_hash), - crx_id_(update_client::GetCrxIdFromPublicKeyHash(pk_hash)), - install_info_(std::make_unique<InstallInfo>()) {} - -Installer::~Installer() = default; - -update_client::CrxComponent Installer::MakeCrxComponent() { - update_client::CrxComponent component; - component.installer = scoped_refptr<Installer>(this); - component.requires_network_encryption = false; - component.crx_format_requirement = - crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF; - component.pk_hash = pk_hash_; - component.name = crx_id_; - component.version = install_info_->version; - component.fingerprint = install_info_->fingerprint; - return component; -} - -void Installer::FindInstallOfApp() { - VLOG(1) << __func__ << " for " << crx_id_; - - const base::FilePath app_install_dir = GetAppInstallDir(crx_id_); - if (app_install_dir.empty() || !base::PathExists(app_install_dir)) { - install_info_ = std::make_unique<InstallInfo>(); - return; - } - - base::Version latest_version(kNullVersion); - base::FilePath latest_path; - std::vector<base::FilePath> older_paths; - base::FileEnumerator file_enumerator(app_install_dir, false, - base::FileEnumerator::DIRECTORIES); - for (auto path = file_enumerator.Next(); !path.value().empty(); - path = file_enumerator.Next()) { - const base::Version version(path.BaseName().MaybeAsASCII()); - - // Ignore folders that don't have valid version names. - if (!version.IsValid()) - continue; - - // The |version| not newer than the latest found version is marked for - // removal. |kNullVersion| is also removed. - if (version.CompareTo(latest_version) <= 0) { - older_paths.push_back(path); - continue; - } - - // New valid |version| folder found. - if (!latest_path.empty()) - older_paths.push_back(latest_path); - - latest_version = version; - latest_path = path; - } - - install_info_->version = latest_version; - install_info_->install_dir = latest_path; - install_info_->manifest = update_client::ReadManifest(latest_path); - base::ReadFileToString(latest_path.AppendASCII("manifest.fingerprint"), - &install_info_->fingerprint); - - for (const auto& older_path : older_paths) - base::DeleteFile(older_path, true); -} - -Installer::Result Installer::InstallHelper(const base::FilePath& unpack_path) { - auto local_manifest = update_client::ReadManifest(unpack_path); - if (!local_manifest) - return Result(update_client::InstallError::BAD_MANIFEST); - - std::string version_ascii; - local_manifest->GetStringASCII("version", &version_ascii); - const base::Version manifest_version(version_ascii); - - VLOG(1) << "Installed version=" << install_info_->version.GetString() - << ", installing version=" << manifest_version.GetString(); - - if (!manifest_version.IsValid()) - return Result(update_client::InstallError::INVALID_VERSION); - - if (install_info_->version.CompareTo(manifest_version) > 0) - return Result(update_client::InstallError::VERSION_NOT_UPGRADED); - - const base::FilePath app_install_dir = GetAppInstallDir(crx_id_); - if (app_install_dir.empty()) - return Result(update_client::InstallError::NO_DIR_COMPONENT_USER); - if (!base::CreateDirectory(app_install_dir)) { - return Result( - static_cast<int>(update_client::InstallError::CUSTOM_ERROR_BASE) + - kCustomInstallErrorCreateAppInstallDirectory); - } - - const auto versioned_install_dir = - app_install_dir.AppendASCII(manifest_version.GetString()); - if (base::PathExists(versioned_install_dir)) { - if (!base::DeleteFile(versioned_install_dir, true)) - return Result(update_client::InstallError::CLEAN_INSTALL_DIR_FAILED); - } - - VLOG(1) << "Install_path=" << versioned_install_dir.AsUTF8Unsafe(); - - if (!base::Move(unpack_path, versioned_install_dir)) { - PLOG(ERROR) << "Move failed."; - base::DeleteFile(versioned_install_dir, true); - return Result(update_client::InstallError::MOVE_FILES_ERROR); - } - - DCHECK(!base::PathExists(unpack_path)); - DCHECK(base::PathExists(versioned_install_dir)); - - install_info_->manifest = std::move(local_manifest); - install_info_->version = manifest_version; - install_info_->install_dir = versioned_install_dir; - base::ReadFileToString( - versioned_install_dir.AppendASCII("manifest.fingerprint"), - &install_info_->fingerprint); - - return Result(update_client::InstallError::NONE); -} - -void Installer::OnUpdateError(int error) { - LOG(ERROR) << "updater error: " << error << " for " << crx_id_; -} - -void Installer::Install(const base::FilePath& unpack_path, - const std::string& public_key, - Callback callback) { - std::unique_ptr<base::DictionaryValue> manifest; - base::Version version; - base::FilePath install_path; - - const auto result = InstallHelper(unpack_path); - base::DeleteFile(unpack_path, true); - std::move(callback).Run(result); -} - -bool Installer::GetInstalledFile(const std::string& file, - base::FilePath* installed_file) { - return false; -} - -bool Installer::Uninstall() { - return false; -} - -} // namespace updater
diff --git a/src/cobalt/updater/installer.h b/src/cobalt/updater/installer.h deleted file mode 100644 index ef97e84..0000000 --- a/src/cobalt/updater/installer.h +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_INSTALLER_H_ -#define CHROME_UPDATER_INSTALLER_H_ - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/callback_forward.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/values.h" -#include "base/version.h" -#include "components/update_client/update_client.h" - -namespace updater { - -class Installer final : public update_client::CrxInstaller { - public: - struct InstallInfo { - InstallInfo(); - ~InstallInfo(); - - base::FilePath install_dir; - base::Version version; - std::string fingerprint; - std::unique_ptr<base::DictionaryValue> manifest; - - private: - DISALLOW_COPY_AND_ASSIGN(InstallInfo); - }; - - explicit Installer(const std::vector<uint8_t>& pk_hash); - - const std::string crx_id() const { return crx_id_; } - - // Finds the highest version install of the app, and updates the install - // info for this installer instance. - void FindInstallOfApp(); - - // Returns a CrxComponent instance that describes the current install - // state of the app. - update_client::CrxComponent MakeCrxComponent(); - - private: - ~Installer() override; - - // Overrides from update_client::CrxInstaller. - void OnUpdateError(int error) override; - void Install(const base::FilePath& unpack_path, - const std::string& public_key, - Callback callback) override; - bool GetInstalledFile(const std::string& file, - base::FilePath* installed_file) override; - bool Uninstall() override; - - Result InstallHelper(const base::FilePath& unpack_path); - - const std::vector<uint8_t> pk_hash_; - const std::string crx_id_; - std::unique_ptr<InstallInfo> install_info_; - - DISALLOW_COPY_AND_ASSIGN(Installer); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_INSTALLER_H_
diff --git a/src/cobalt/updater/mac/BUILD.gn b/src/cobalt/updater/mac/BUILD.gn deleted file mode 100644 index cb2dcb5..0000000 --- a/src/cobalt/updater/mac/BUILD.gn +++ /dev/null
@@ -1,19 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -group("mac") { - deps = [ - ":updater", - ] -} - -executable("updater") { - sources = [ - "main.cc", - ] - - deps = [ - "//chrome/updater:common", - ] -}
diff --git a/src/cobalt/updater/mac/main.cc b/src/cobalt/updater/mac/main.cc deleted file mode 100644 index 7473bdb..0000000 --- a/src/cobalt/updater/mac/main.cc +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/updater.h" - -int main(int argc, const char* argv[]) { - return updater::UpdaterMain(argc, argv); -}
diff --git a/src/cobalt/updater/patcher.cc b/src/cobalt/updater/patcher.cc deleted file mode 100644 index cfff4d9..0000000 --- a/src/cobalt/updater/patcher.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/patcher.h" - -#include <utility> -#include "base/callback.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "courgette/courgette.h" -#include "courgette/third_party/bsdiff/bsdiff.h" - -namespace updater { - -namespace { - -class PatcherImpl : public update_client::Patcher { - public: - PatcherImpl() = default; - - void PatchBsdiff(const base::FilePath& input_path, - const base::FilePath& patch_path, - const base::FilePath& output_path, - PatchCompleteCallback callback) const override { - base::File input_file(input_path, - base::File::FLAG_OPEN | base::File::FLAG_READ); - base::File patch_file(patch_path, - base::File::FLAG_OPEN | base::File::FLAG_READ); - base::File output_file(output_path, base::File::FLAG_CREATE | - base::File::FLAG_WRITE | - base::File::FLAG_EXCLUSIVE_WRITE); - if (!input_file.IsValid() || !patch_file.IsValid() || - !output_file.IsValid()) { - std::move(callback).Run(-1); - return; - } - std::move(callback).Run(bsdiff::ApplyBinaryPatch( - std::move(input_file), std::move(patch_file), std::move(output_file))); - } - - void PatchCourgette(const base::FilePath& input_path, - const base::FilePath& patch_path, - const base::FilePath& output_path, - PatchCompleteCallback callback) const override { - base::File input_file(input_path, - base::File::FLAG_OPEN | base::File::FLAG_READ); - base::File patch_file(patch_path, - base::File::FLAG_OPEN | base::File::FLAG_READ); - base::File output_file(output_path, base::File::FLAG_CREATE | - base::File::FLAG_WRITE | - base::File::FLAG_EXCLUSIVE_WRITE); - if (!input_file.IsValid() || !patch_file.IsValid() || - !output_file.IsValid()) { - std::move(callback).Run(-1); - return; - } - std::move(callback).Run(courgette::ApplyEnsemblePatch( - std::move(input_file), std::move(patch_file), std::move(output_file))); - } - - protected: - ~PatcherImpl() override = default; -}; - -} // namespace - -PatcherFactory::PatcherFactory() = default; - -scoped_refptr<update_client::Patcher> PatcherFactory::Create() const { - return base::MakeRefCounted<PatcherImpl>(); -} - -PatcherFactory::~PatcherFactory() = default; - -} // namespace updater
diff --git a/src/cobalt/updater/patcher.h b/src/cobalt/updater/patcher.h deleted file mode 100644 index 9af8c27..0000000 --- a/src/cobalt/updater/patcher.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_PATCHER_H_ -#define CHROME_UPDATER_PATCHER_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "components/update_client/patcher.h" - -namespace updater { - -class PatcherFactory : public update_client::PatcherFactory { - public: - PatcherFactory(); - - scoped_refptr<update_client::Patcher> Create() const override; - - protected: - ~PatcherFactory() override; - - private: - DISALLOW_COPY_AND_ASSIGN(PatcherFactory); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_PATCHER_H_
diff --git a/src/cobalt/updater/prefs.cc b/src/cobalt/updater/prefs.cc deleted file mode 100644 index eb9f6b4..0000000 --- a/src/cobalt/updater/prefs.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/prefs.h" - -#include "base/files/file_path.h" -#include "base/memory/scoped_refptr.h" -#include "chrome/updater/util.h" -#include "components/prefs/json_pref_store.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/pref_service.h" -#include "components/prefs/pref_service_factory.h" -#include "components/update_client/update_client.h" - -namespace updater { - -std::unique_ptr<PrefService> CreatePrefService() { - base::FilePath product_data_dir; - if (!GetProductDirectory(&product_data_dir)) - return nullptr; - - PrefServiceFactory pref_service_factory; - pref_service_factory.set_user_prefs(base::MakeRefCounted<JsonPrefStore>( - product_data_dir.Append(FILE_PATH_LITERAL("prefs.json")))); - - auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>(); - update_client::RegisterPrefs(pref_registry.get()); - - return pref_service_factory.Create(pref_registry); -} - -} // namespace updater
diff --git a/src/cobalt/updater/prefs.h b/src/cobalt/updater/prefs.h deleted file mode 100644 index 9a08eae..0000000 --- a/src/cobalt/updater/prefs.h +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_PREFS_H_ -#define CHROME_UPDATER_PREFS_H_ - -#include <memory> - -class PrefService; - -namespace updater { - -std::unique_ptr<PrefService> CreatePrefService(); - -} // namespace updater - -#endif // CHROME_UPDATER_PREFS_H_
diff --git a/src/cobalt/updater/unzipper.cc b/src/cobalt/updater/unzipper.cc deleted file mode 100644 index b218965..0000000 --- a/src/cobalt/updater/unzipper.cc +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/unzipper.h" - -#include <utility> -#include "base/files/file_path.h" -#include "third_party/zlib/google/zip.h" - -namespace updater { - -namespace { - -class UnzipperImpl : public update_client::Unzipper { - public: - UnzipperImpl() = default; - - void Unzip(const base::FilePath& zip_path, - const base::FilePath& output_path, - UnzipCompleteCallback callback) override { - std::move(callback).Run(zip::Unzip(zip_path, output_path)); - } -}; - -} // namespace - -UnzipperFactory::UnzipperFactory() = default; - -std::unique_ptr<update_client::Unzipper> UnzipperFactory::Create() const { - return std::make_unique<UnzipperImpl>(); -} - -UnzipperFactory::~UnzipperFactory() = default; - -} // namespace updater
diff --git a/src/cobalt/updater/unzipper.h b/src/cobalt/updater/unzipper.h deleted file mode 100644 index 2b63d8e..0000000 --- a/src/cobalt/updater/unzipper.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_UNZIPPER_H_ -#define CHROME_UPDATER_UNZIPPER_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "components/update_client/unzipper.h" - -namespace updater { - -class UnzipperFactory : public update_client::UnzipperFactory { - public: - UnzipperFactory(); - - std::unique_ptr<update_client::Unzipper> Create() const override; - - protected: - ~UnzipperFactory() override; - - private: - DISALLOW_COPY_AND_ASSIGN(UnzipperFactory); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_UNZIPPER_H_
diff --git a/src/cobalt/updater/updater.cc b/src/cobalt/updater/updater.cc deleted file mode 100644 index 18fa3c5..0000000 --- a/src/cobalt/updater/updater.cc +++ /dev/null
@@ -1,270 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/updater.h" - -#include <stdint.h> - -#include <iterator> -#include <memory> -#include <string> -#include <utility> -#include <vector> - -#include "base/at_exit.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/memory/scoped_refptr.h" -#include "base/message_loop/message_pump_type.h" -#include "base/optional.h" -#include "base/run_loop.h" -#include "base/stl_util.h" -#include "base/task/post_task.h" -#include "base/task/single_thread_task_executor.h" -#include "base/task/thread_pool/thread_pool.h" -#include "base/task_runner.h" -#include "base/threading/platform_thread.h" -#include "base/threading/thread_restrictions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "chrome/updater/configurator.h" -#include "chrome/updater/crash_client.h" -#include "chrome/updater/crash_reporter.h" -#include "chrome/updater/installer.h" -#include "chrome/updater/updater_constants.h" -#include "chrome/updater/updater_version.h" -#include "chrome/updater/util.h" -#include "components/crash/core/common/crash_key.h" -#include "components/prefs/pref_service.h" -#include "components/update_client/crx_update_item.h" -#include "components/update_client/update_client.h" - -#if defined(OS_WIN) -#include "chrome/updater/win/setup/setup.h" -#include "chrome/updater/win/setup/uninstall.h" -#endif - -// To install the updater, run: -// "updater.exe --install --enable-logging --v=1 --vmodule=*/chrome/updater/*" -// from the build directory. The program needs a number of dependencies which -// are available in the build out directory. -// To uninstall, run "updater.exe --uninstall" from its install directory or -// from the build out directory. Doing this will make the program delete its -// install directory using a shim cmd script. -namespace updater { - -namespace { - -// For now, use the Flash CRX for testing. -// CRX id is mimojjlkmoijpicakmndhoigimigcmbb. -const uint8_t mimo_hash[] = {0xc8, 0xce, 0x99, 0xba, 0xce, 0x89, 0xf8, 0x20, - 0xac, 0xd3, 0x7e, 0x86, 0x8c, 0x86, 0x2c, 0x11, - 0xb9, 0x40, 0xc5, 0x55, 0xaf, 0x08, 0x63, 0x70, - 0x54, 0xf9, 0x56, 0xd3, 0xe7, 0x88, 0xba, 0x8c}; - -void ThreadPoolStart() { - base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Updater"); -} - -void ThreadPoolStop() { - base::ThreadPoolInstance::Get()->Shutdown(); -} - -void QuitLoop(base::OnceClosure quit_closure) { - std::move(quit_closure).Run(); -} - -class Observer : public update_client::UpdateClient::Observer { - public: - explicit Observer(scoped_refptr<update_client::UpdateClient> update_client) - : update_client_(update_client) {} - - // Overrides for update_client::UpdateClient::Observer. - void OnEvent(Events event, const std::string& id) override { - update_client_->GetCrxUpdateState(id, &crx_update_item_); - } - - const update_client::CrxUpdateItem& crx_update_item() const { - return crx_update_item_; - } - - private: - scoped_refptr<update_client::UpdateClient> update_client_; - update_client::CrxUpdateItem crx_update_item_; - DISALLOW_COPY_AND_ASSIGN(Observer); -}; - -// The log file is created in DIR_LOCAL_APP_DATA or DIR_APP_DATA. -void InitLogging(const base::CommandLine& command_line) { - logging::LoggingSettings settings; - base::FilePath log_dir; - GetProductDirectory(&log_dir); - const auto log_file = log_dir.Append(FILE_PATH_LITERAL("updater.log")); - settings.log_file_path = log_file.value().c_str(); - settings.logging_dest = logging::LOG_TO_ALL; - logging::InitLogging(settings); - logging::SetLogItems(true, // enable_process_id - true, // enable_thread_id - true, // enable_timestamp - false); // enable_tickcount - VLOG(1) << "Log file " << settings.log_file_path; -} - -void InitializeUpdaterMain() { - crash_reporter::InitializeCrashKeys(); - - static crash_reporter::CrashKeyString<16> crash_key_process_type( - "process_type"); - crash_key_process_type.Set("updater"); - - if (CrashClient::GetInstance()->InitializeCrashReporting()) - VLOG(1) << "Crash reporting initialized."; - else - VLOG(1) << "Crash reporting is not available."; - - StartCrashReporter(UPDATER_VERSION_STRING); - - ThreadPoolStart(); -} - -void TerminateUpdaterMain() { - ThreadPoolStop(); -} - -int UpdaterInstall() { -#if defined(OS_WIN) - return Setup(); -#else - return -1; -#endif -} - -int UpdaterUninstall() { -#if defined(OS_WIN) - return Uninstall(); -#else - return -1; -#endif -} - -int UpdaterUpdateApps() { - auto installer = base::MakeRefCounted<Installer>( - std::vector<uint8_t>(std::cbegin(mimo_hash), std::cend(mimo_hash))); - installer->FindInstallOfApp(); - const auto component = installer->MakeCrxComponent(); - - base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI); - base::RunLoop runloop; - DCHECK(base::ThreadTaskRunnerHandle::IsSet()); - - auto config = base::MakeRefCounted<Configurator>(); - { - base::ScopedDisallowBlocking no_blocking_allowed; - - auto update_client = update_client::UpdateClientFactory(config); - - Observer observer(update_client); - update_client->AddObserver(&observer); - - const std::vector<std::string> ids = {installer->crx_id()}; - update_client->Update( - ids, - base::BindOnce( - [](const update_client::CrxComponent& component, - const std::vector<std::string>& ids) - -> std::vector<base::Optional<update_client::CrxComponent>> { - DCHECK_EQ(1u, ids.size()); - return {component}; - }, - component), - true, - base::BindOnce( - [](base::OnceClosure closure, update_client::Error error) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&QuitLoop, std::move(closure))); - }, - runloop.QuitWhenIdleClosure())); - - runloop.Run(); - - const auto& update_item = observer.crx_update_item(); - switch (update_item.state) { - case update_client::ComponentState::kUpdated: - VLOG(1) << "Update success."; - break; - case update_client::ComponentState::kUpToDate: - VLOG(1) << "No updates."; - break; - case update_client::ComponentState::kUpdateError: - VLOG(1) << "Updater error: " << update_item.error_code << "."; - break; - default: - NOTREACHED(); - break; - } - update_client->RemoveObserver(&observer); - update_client = nullptr; - } - - { - base::RunLoop runloop; - config->GetPrefService()->CommitPendingWrite(base::BindOnce( - [](base::OnceClosure quit_closure) { std::move(quit_closure).Run(); }, - runloop.QuitWhenIdleClosure())); - runloop.Run(); - } - - return 0; -} - -} // namespace - -int HandleUpdaterCommands(const base::CommandLine* command_line) { - DCHECK(!command_line->HasSwitch(kCrashHandlerSwitch)); - - if (command_line->HasSwitch(kCrashMeSwitch)) { - int* ptr = nullptr; - return *ptr; - } - - if (command_line->HasSwitch(kInstallSwitch)) { - return UpdaterInstall(); - } - - if (command_line->HasSwitch(kUninstallSwitch)) { - return UpdaterUninstall(); - } - - if (command_line->HasSwitch(kUpdateAppsSwitch)) { - return UpdaterUpdateApps(); - } - - VLOG(1) << "Unknown command line switch."; - return -1; -} - -int UpdaterMain(int argc, const char* const* argv) { - base::PlatformThread::SetName("UpdaterMain"); - base::AtExitManager exit_manager; - - base::CommandLine::Init(argc, argv); - const auto* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(kTestSwitch)) - return 0; - - InitLogging(*command_line); - - if (command_line->HasSwitch(kCrashHandlerSwitch)) - return CrashReporterMain(); - - InitializeUpdaterMain(); - const auto result = HandleUpdaterCommands(command_line); - TerminateUpdaterMain(); - return result; -} - -} // namespace updater
diff --git a/src/cobalt/updater/updater.h b/src/cobalt/updater/updater.h deleted file mode 100644 index 1c96663..0000000 --- a/src/cobalt/updater/updater.h +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_UPDATER_H_ -#define CHROME_UPDATER_UPDATER_H_ - -namespace updater { - -int UpdaterMain(int argc, const char* const* argv); - -} // namespace updater - -#endif // CHROME_UPDATER_UPDATER_H_
diff --git a/src/cobalt/updater/updater_constants.cc b/src/cobalt/updater/updater_constants.cc deleted file mode 100644 index d726e79..0000000 --- a/src/cobalt/updater/updater_constants.cc +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/updater_constants.h" - -namespace updater { - -const char kCrashMeSwitch[] = "crash-me"; -const char kCrashHandlerSwitch[] = "crash-handler"; -const char kInstallSwitch[] = "install"; -const char kUninstallSwitch[] = "uninstall"; -const char kUpdateAppsSwitch[] = "ua"; -const char kTestSwitch[] = "test"; -const char kInitDoneNotifierSwitch[] = "init-done-notifier"; -const char kNoRateLimitSwitch[] = "no-rate-limit"; -const char kEnableLoggingSwitch[] = "enable-logging"; -const char kLoggingLevelSwitch[] = "v"; -const char kLoggingModuleSwitch[] = "vmodule"; - -const char kUpdaterJSONDefaultUrl[] = - "https://update.googleapis.com/service/update2/json"; -const char kCrashUploadURL[] = "https://clients2.google.com/cr/report"; -const char kCrashStagingUploadURL[] = - "https://clients2.google.com/cr/staging_report"; - -extern const char kAppsDir[] = "apps"; -extern const char kUninstallScript[] = "uninstall.cmd"; - -} // namespace updater
diff --git a/src/cobalt/updater/updater_constants.h b/src/cobalt/updater/updater_constants.h deleted file mode 100644 index 5f47325..0000000 --- a/src/cobalt/updater/updater_constants.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_UPDATER_CONSTANTS_H_ -#define CHROME_UPDATER_UPDATER_CONSTANTS_H_ - -namespace updater { - -// Command line switches. -// -// Crash the program for testing purposes. -extern const char kCrashMeSwitch[]; - -// Runs as the Crashpad handler. -extern const char kCrashHandlerSwitch[]; - -// Installs the updater. -extern const char kInstallSwitch[]; - -// Uninstalls the updater. -extern const char kUninstallSwitch[]; - -// Updates all apps registered with the updater. -extern const char kUpdateAppsSwitch[]; - -// Runs in test mode. Currently, it exits right away. -extern const char kTestSwitch[]; - -// Disables throttling for the crash reported until the following bug is fixed: -// https://bugs.chromium.org/p/crashpad/issues/detail?id=23 -extern const char kNoRateLimitSwitch[]; - -// The handle of an event to signal when the initialization of the main process -// is complete. -extern const char kInitDoneNotifierSwitch[]; - -// Enables logging. -extern const char kEnableLoggingSwitch[]; - -// Specifies the logging level. -extern const char kLoggingLevelSwitch[]; - -// Specifies the logging module filter. -extern const char kLoggingModuleSwitch[]; - -// URLs. -// -// Omaha server end point. -extern const char kUpdaterJSONDefaultUrl[]; - -// The URL where crash reports are uploaded. -extern const char kCrashUploadURL[]; -extern const char kCrashStagingUploadURL[]; - -// Paths. -// -// The directory name where CRX apps get installed. This is provided for demo -// purposes, since products installed by this updater will be installed in -// their specific locations. -extern const char kAppsDir[]; - -// The name of the uninstall script which is invoked by the --uninstall switch. -extern const char kUninstallScript[]; - -// Errors. -// -// The install directory for the application could not be created. -const int kCustomInstallErrorCreateAppInstallDirectory = 0; - -} // namespace updater - -#endif // CHROME_UPDATER_UPDATER_CONSTANTS_H_
diff --git a/src/cobalt/updater/updater_unittest.cc b/src/cobalt/updater/updater_unittest.cc deleted file mode 100644 index fd2d7dd..0000000 --- a/src/cobalt/updater/updater_unittest.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/path_service.h" -#include "base/process/launch.h" -#include "base/process/process.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#define EXECUTABLE_EXTENSION ".exe" -#else -#define EXECUTABLE_EXTENSION "" -#endif - -// Tests the updater process returns 0 when run with --test argument. -TEST(UpdaterTest, UpdaterExitCode) { - base::FilePath this_executable_path; - ASSERT_TRUE(base::PathService::Get(base::FILE_EXE, &this_executable_path)); - const base::FilePath updater = this_executable_path.DirName().Append( - FILE_PATH_LITERAL("updater" EXECUTABLE_EXTENSION)); - base::LaunchOptions options; -#if defined(OS_WIN) - options.start_hidden = true; -#endif - base::CommandLine command_line(updater); - command_line.AppendSwitch("test"); - auto process = base::LaunchProcess(command_line, options); - ASSERT_TRUE(process.IsValid()); - int exit_code = -1; - EXPECT_TRUE(process.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(60), - &exit_code)); - EXPECT_EQ(0, exit_code); -}
diff --git a/src/cobalt/updater/updater_version.h.in b/src/cobalt/updater/updater_version.h.in deleted file mode 100644 index 242c533..0000000 --- a/src/cobalt/updater/updater_version.h.in +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Version Information - -#define UPDATER_VERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@ -#define UPDATER_VERSION_STRING "@MAJOR@.@MINOR@.@BUILD@.@PATCH@" - -// Branding Information -#define COMPANY_FULLNAME_STRING "@COMPANY_FULLNAME@" -#define COMPANY_SHORTNAME_STRING "@COMPANY_SHORTNAME@" -#define PRODUCT_FULLNAME_STRING "@PRODUCT_FULLNAME@" -#define OFFICIAL_BUILD_STRING "@OFFICIAL_BUILD@"
diff --git a/src/cobalt/updater/util.cc b/src/cobalt/updater/util.cc deleted file mode 100644 index ced4a55..0000000 --- a/src/cobalt/updater/util.cc +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/util.h" - -#include "base/base_paths.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "build/build_config.h" -#include "chrome/updater/updater_version.h" - -namespace updater { - -bool GetProductDirectory(base::FilePath* path) { - constexpr int kPathKey = -#if defined(OS_WIN) - base::DIR_LOCAL_APP_DATA; -#elif defined(OS_MACOSX) - base::DIR_APP_DATA; -#endif - - base::FilePath app_data_dir; - if (!base::PathService::Get(kPathKey, &app_data_dir)) { - LOG(ERROR) << "Can't retrieve local app data directory."; - return false; - } - - const auto product_data_dir = - app_data_dir.AppendASCII(COMPANY_SHORTNAME_STRING) - .AppendASCII(PRODUCT_FULLNAME_STRING); - if (!base::CreateDirectory(product_data_dir)) { - LOG(ERROR) << "Can't create product directory."; - return false; - } - - *path = product_data_dir; - return true; -} - -} // namespace updater
diff --git a/src/cobalt/updater/util.h b/src/cobalt/updater/util.h deleted file mode 100644 index da5861e..0000000 --- a/src/cobalt/updater/util.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_UTIL_H_ -#define CHROME_UPDATER_UTIL_H_ - -namespace base { -class FilePath; -} - -namespace updater { - -// Returns a directory where updater files or its data is stored. -bool GetProductDirectory(base::FilePath* path); - -} // namespace updater - -#endif // CHROME_UPDATER_UTIL_H_
diff --git a/src/cobalt/updater/win/BUILD.gn b/src/cobalt/updater/win/BUILD.gn deleted file mode 100644 index d3c9fd2..0000000 --- a/src/cobalt/updater/win/BUILD.gn +++ /dev/null
@@ -1,125 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//chrome/process_version_rc_template.gni") -import("//testing/test.gni") - -# This target builds the updater executable, its installer, and unittests. -group("win") { - deps = [ - ":updater", - "//chrome/updater/win/installer:installer", - ] -} - -executable("updater") { - sources = [ - "main.cc", - "updater.rc", - ] - - configs += [ "//build/config/win:windowed" ] - - libs = [ "winhttp.lib" ] - deps = [ - ":code", - ":version_resources", - "//build/win:default_exe_manifest", - "//chrome/updater:common", - ] -} - -copy("uninstall.cmd") { - sources = [ - "setup/uninstall.cmd", - ] - outputs = [ - "$target_gen_dir/uninstall.cmd", - ] -} - -process_version_rc_template("version_resources") { - sources = [ - "updater.ver", - ] - output = "$target_gen_dir/updater_exe.rc" -} - -source_set("code") { - sources = [ - "net/net_util.cc", - "net/net_util.h", - "net/network.h", - "net/network_fetcher.cc", - "net/network_fetcher.h", - "net/network_winhttp.cc", - "net/network_winhttp.h", - "net/scoped_hinternet.h", - "setup/setup.cc", - "setup/setup.h", - "setup/setup_util.cc", - "setup/setup_util.h", - "setup/uninstall.cc", - "setup/uninstall.h", - "task_scheduler.cc", - "task_scheduler.h", - "util.cc", - "util.h", - ] - - defines = [ "SECURITY_WIN32" ] - - libs = [ - "secur32.lib", - "taskschd.lib", - ] - - deps = [ - "//base", - "//chrome/installer/util:with_no_strings", - "//chrome/updater:common", - "//components/update_client", - ] -} - -# Tests built into Chrome's unit_tests.exe. -source_set("updater_tests") { - testonly = true - - sources = [ - "net/network_unittest.cc", - "util_unittest.cc", - ] - - deps = [ - ":code", - "//base/test:test_support", - "//testing/gtest", - ] - - data_deps = [ - ":updater_unittests", - "//chrome/updater/win/installer:installer_unittest", - ] -} - -# Specific tests which must run in their own process due to COM, security, or -# test isolation requirements. -test("updater_unittests") { - testonly = true - - sources = [ - "//chrome/updater/win/test/test_main.cc", - "task_scheduler_unittest.cc", - ] - - deps = [ - ":code", - "//base", - "//base/test:test_support", - "//chrome/updater/win/test:test_executables", - "//chrome/updater/win/test:test_strings", - "//testing/gtest", - ] -}
diff --git a/src/cobalt/updater/win/installer/BUILD.gn b/src/cobalt/updater/win/installer/BUILD.gn deleted file mode 100644 index b7ae096..0000000 --- a/src/cobalt/updater/win/installer/BUILD.gn +++ /dev/null
@@ -1,143 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//chrome/process_version_rc_template.gni") -import("//testing/test.gni") - -source_set("lib") { - sources = [ - "configuration.cc", - "configuration.h", - "exit_code.h", - "installer.cc", - "installer.h", - "installer.rc", - "installer_constants.cc", - "installer_constants.h", - "installer_resource.h", - "pe_resource.cc", - "pe_resource.h", - "regkey.cc", - "regkey.h", - "string.cc", - "string.h", - ] - - deps = [ - "//base", - ] -} - -process_version_rc_template("version") { - template_file = "installer_version.rc.version" - output = "$root_out_dir/installer_version.rc" -} - -# This target creats a list of runtime dependencies for the component -# builds. This list is parsed by the |create_installer_archive| script, the -# DLL paths extracted out from the list, and included in the archive. -updater_runtime_deps = "$root_gen_dir/updater.runtime_deps" -group("updater_runtime_deps") { - write_runtime_deps = updater_runtime_deps - data_deps = [ - "//chrome/updater/win:updater", - ] -} - -template("generate_installer") { - output_dir = invoker.out_dir - packed_files_rc_file = "$target_gen_dir/$target_name/packed_files.rc" - archive_name = target_name + "_archive" - staging_dir = "$target_gen_dir/$target_name" - - action(archive_name) { - script = "create_installer_archive.py" - - release_file = "updater.release" - - inputs = [ - release_file, - ] - - outputs = [ - "$output_dir/updater.packed.7z", - packed_files_rc_file, - ] - - args = [ - "--build_dir", - rebase_path(root_out_dir, root_build_dir), - "--staging_dir", - rebase_path(staging_dir, root_build_dir), - "--input_file", - rebase_path(release_file, root_build_dir), - "--resource_file_path", - rebase_path(packed_files_rc_file, root_build_dir), - "--output_dir", - rebase_path(output_dir, root_build_dir), - "--setup_runtime_deps", - rebase_path(updater_runtime_deps, root_build_dir), - "--output_name=updater", - "--verbose", - ] - - deps = [ - ":updater_runtime_deps", - "//chrome/updater/win:uninstall.cmd", - "//chrome/updater/win:updater", - ] - - if (is_component_build) { - args += [ "--component_build=1" ] - } - } - - executable(target_name) { - output_name = invoker.output_name - - sources = [ - "installer_main.cc", - packed_files_rc_file, - ] - - configs += [ "//build/config/win:windowed" ] - - libs = [ "setupapi.lib" ] - - deps = [ - ":$archive_name", - ":lib", - ":version", - "//build/win:default_exe_manifest", - "//chrome/installer/util:with_no_strings", - ] - } -} - -generate_installer("installer") { - out_dir = root_out_dir - output_name = "UpdaterSetup" -} - -test("installer_unittest") { - testonly = true - - output_name = "updater_installer_unittest" - - sources = [ - "configuration_unittest.cc", - "run_all_unittests.cc", - "string_unittest.cc", - ] - - public_deps = [ - ":lib", - ] - deps = [ - "//base", - "//base/test:test_support", - "//chrome/installer/util:with_no_strings", - "//testing/gtest", - ] -}
diff --git a/src/cobalt/updater/win/installer/configuration.cc b/src/cobalt/updater/win/installer/configuration.cc deleted file mode 100644 index 9059273..0000000 --- a/src/cobalt/updater/win/installer/configuration.cc +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/installer/configuration.h" -#include <shellapi.h> -#include "chrome/updater/win/installer/string.h" - -namespace updater { - -namespace { - -// Returns true if GoogleUpdateIsMachine=1 is present in the environment. -bool GetGoogleUpdateIsMachineEnvVar() { - constexpr DWORD kBufferSize = 2; - StackString<kBufferSize> value; - const auto length = ::GetEnvironmentVariableW(L"GoogleUpdateIsMachine", - value.get(), kBufferSize); - return length == 1 && *value.get() == L'1'; -} - -} // namespace - -Configuration::Configuration() { - Clear(); -} - -Configuration::~Configuration() { - Clear(); -} - -bool Configuration::Initialize(HMODULE module) { - Clear(); - return ParseCommandLine(::GetCommandLine()); -} - -void Configuration::Clear() { - if (args_ != nullptr) { - ::LocalFree(args_); - args_ = nullptr; - } - command_line_ = nullptr; - operation_ = INSTALL_PRODUCT; - argument_count_ = 0; - is_system_level_ = false; - has_invalid_switch_ = false; -} - -// |command_line| is shared with this instance in the sense that this -// instance may refer to it at will throughout its lifetime, yet it will -// not release it. -bool Configuration::ParseCommandLine(const wchar_t* command_line) { - command_line_ = command_line; - args_ = ::CommandLineToArgvW(command_line_, &argument_count_); - if (!args_) - return false; - - for (int i = 1; i < argument_count_; ++i) { - if (0 == ::lstrcmpi(args_[i], L"--system-level")) - is_system_level_ = true; - else if (0 == ::lstrcmpi(args_[i], L"--cleanup")) - operation_ = CLEANUP; - } - - if (!is_system_level_) - is_system_level_ = GetGoogleUpdateIsMachineEnvVar(); - - return true; -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/installer/configuration.h b/src/cobalt/updater/win/installer/configuration.h deleted file mode 100644 index c47a00d..0000000 --- a/src/cobalt/updater/win/installer/configuration.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright (c) 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_INSTALLER_CONFIGURATION_H_ -#define CHROME_UPDATER_WIN_INSTALLER_CONFIGURATION_H_ - -#include <windows.h> - -namespace updater { - -// A simple container of the updater's configuration, as defined by the -// command line used to invoke it. -class Configuration { - public: - enum Operation { - INSTALL_PRODUCT, - CLEANUP, - }; - - Configuration(); - ~Configuration(); - - // Initializes this instance on the basis of the process's command line. - bool Initialize(HMODULE module); - - // Returns the desired operation dictated by the command line options. - Operation operation() const { return operation_; } - - // Returns true if --system-level is on the command line or if - // GoogleUpdateIsMachine=1 is set in the process's environment. - bool is_system_level() const { return is_system_level_; } - - // Returns true if any invalid switch is found on the command line. - bool has_invalid_switch() const { return has_invalid_switch_; } - - protected: - void Clear(); - bool ParseCommandLine(const wchar_t* command_line); - - wchar_t** args_ = nullptr; - const wchar_t* command_line_ = nullptr; - int argument_count_ = 0; - Operation operation_ = INSTALL_PRODUCT; - bool is_system_level_ = false; - bool has_invalid_switch_ = false; - - private: - Configuration(const Configuration&) = delete; - Configuration& operator=(const Configuration&) = delete; -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_INSTALLER_CONFIGURATION_H_
diff --git a/src/cobalt/updater/win/installer/configuration_unittest.cc b/src/cobalt/updater/win/installer/configuration_unittest.cc deleted file mode 100644 index 54ec28b1..0000000 --- a/src/cobalt/updater/win/installer/configuration_unittest.cc +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright (c) 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/installer/configuration.h" - -#include <stddef.h> -#include <stdlib.h> - -#include <memory> - -#include "base/environment.h" -#include "base/macros.h" -#include "base/test/test_reg_util_win.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace updater { - -namespace { - -// A helper class to set the "GoogleUpdateIsMachine" environment variable. -class ScopedGoogleUpdateIsMachine { - public: - explicit ScopedGoogleUpdateIsMachine(bool value) - : env_(base::Environment::Create()) { - env_->SetVar("GoogleUpdateIsMachine", value ? "1" : "0"); - } - - ~ScopedGoogleUpdateIsMachine() { env_->UnSetVar("GoogleUpdateIsMachine"); } - - private: - std::unique_ptr<base::Environment> env_; -}; - -class TestConfiguration : public Configuration { - public: - explicit TestConfiguration(const wchar_t* command_line) { - EXPECT_TRUE(ParseCommandLine(command_line)); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TestConfiguration); -}; - -} // namespace - -class UpdaterInstallerConfigurationTest : public ::testing::Test { - protected: - UpdaterInstallerConfigurationTest() = default; - - private: - DISALLOW_COPY_AND_ASSIGN(UpdaterInstallerConfigurationTest); -}; - -// Test that the operation type is CLEANUP iff --cleanup is on the cmdline. -TEST_F(UpdaterInstallerConfigurationTest, Operation) { - EXPECT_EQ(Configuration::INSTALL_PRODUCT, - TestConfiguration(L"spam.exe").operation()); - EXPECT_EQ(Configuration::INSTALL_PRODUCT, - TestConfiguration(L"spam.exe --clean").operation()); - EXPECT_EQ(Configuration::INSTALL_PRODUCT, - TestConfiguration(L"spam.exe --cleanupthis").operation()); - - EXPECT_EQ(Configuration::CLEANUP, - TestConfiguration(L"spam.exe --cleanup").operation()); - EXPECT_EQ(Configuration::CLEANUP, - TestConfiguration(L"spam.exe --cleanup now").operation()); -} - -TEST_F(UpdaterInstallerConfigurationTest, IsSystemLevel) { - EXPECT_FALSE(TestConfiguration(L"spam.exe").is_system_level()); - EXPECT_FALSE(TestConfiguration(L"spam.exe --chrome").is_system_level()); - EXPECT_TRUE(TestConfiguration(L"spam.exe --system-level").is_system_level()); - - { - ScopedGoogleUpdateIsMachine env_setter(false); - EXPECT_FALSE(TestConfiguration(L"spam.exe").is_system_level()); - } - - { - ScopedGoogleUpdateIsMachine env_setter(true); - EXPECT_TRUE(TestConfiguration(L"spam.exe").is_system_level()); - } -} - -TEST_F(UpdaterInstallerConfigurationTest, HasInvalidSwitch) { - EXPECT_FALSE(TestConfiguration(L"spam.exe").has_invalid_switch()); - EXPECT_TRUE( - TestConfiguration(L"spam.exe --chrome-frame").has_invalid_switch()); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/installer/create_installer_archive.py b/src/cobalt/updater/win/installer/create_installer_archive.py deleted file mode 100644 index c8dbb9c..0000000 --- a/src/cobalt/updater/win/installer/create_installer_archive.py +++ /dev/null
@@ -1,341 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Script to create the Chrome Updater Installer archive. - - This script is used to create an archive of all the files required for a - Chrome Updater install in appropriate directory structure. It reads - updater.release file as input, creates updater.7z ucompressed archive, and - generates the updater.packed.7z compressed archive. - -""" - -import ConfigParser -import glob -import optparse -import os -import shutil -import subprocess -import sys - -# Directory name inside the uncompressed archive where all the files are. -UPDATER_DIR = "bin" - -# Suffix to uncompressed full archive file, appended to options.output_name. -ARCHIVE_SUFFIX = ".7z" - -# compressed full archive suffix, will be prefixed by options.output_name. -COMPRESSED_ARCHIVE_SUFFIX = ".packed.7z" -TEMP_ARCHIVE_DIR = "temp_installer_archive" - -g_archive_inputs = [] - -def CompressUsingLZMA(build_dir, compressed_file, input_file, verbose): - lzma_exec = GetLZMAExec(build_dir) - cmd = [lzma_exec, - 'a', '-t7z', - # Flags equivalent to -mx9 (ultra) but with the bcj2 turned on (exe - # pre-filter). These arguments are the similar to what the Chrome mini - # installer is using. - '-m0=BCJ2', - '-m1=LZMA:d27:fb128', - '-m2=LZMA:d22:fb128:mf=bt2', - '-m3=LZMA:d22:fb128:mf=bt2', - '-mb0:1', - '-mb0s1:2', - '-mb0s2:3', - os.path.abspath(compressed_file), - os.path.abspath(input_file),] - if os.path.exists(compressed_file): - os.remove(compressed_file) - RunSystemCommand(cmd, verbose) - - -def CopyAllFilesToStagingDir(config, staging_dir, build_dir): - """Copies the files required for installer archive. - """ - CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, build_dir) - - -def CopySectionFilesToStagingDir(config, section, staging_dir, src_dir): - """Copies installer archive files specified in section from src_dir to - staging_dir. This method reads section from config and copies all the - files specified from src_dir to staging dir. - """ - for option in config.options(section): - src_subdir = option.replace('\\', os.sep) - dst_dir = os.path.join(staging_dir, config.get(section, option)) - dst_dir = dst_dir.replace('\\', os.sep) - src_paths = glob.glob(os.path.join(src_dir, src_subdir)) - if src_paths and not os.path.exists(dst_dir): - os.makedirs(dst_dir) - for src_path in src_paths: - print(src_path) - dst_path = os.path.join(dst_dir, os.path.basename(src_path)) - if not os.path.exists(dst_path): - g_archive_inputs.append(src_path) - print('paths src_path={0}, dest_dir={1}'.format(src_path, dst_dir)) - shutil.copy(src_path, dst_dir) - -def GetLZMAExec(build_dir): - if sys.platform == 'win32': - lzma_exec = os.path.join(build_dir, "..", "..", "third_party", - "lzma_sdk", "Executable", "7za.exe") - else: - lzma_exec = '7zr' # Use system 7zr. - return lzma_exec - -def MakeStagingDirectory(staging_dir): - """Creates a staging path for installer archive. If directory exists already, - deletes the existing directory. - """ - file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR) - if os.path.exists(file_path): - shutil.rmtree(file_path) - os.makedirs(file_path) - return file_path - -def Readconfig(input_file): - """Reads config information from input file after setting default value of - global variables. - """ - variables = {} - variables['UpdaterDir'] = UPDATER_DIR - config = ConfigParser.SafeConfigParser(variables) - config.read(input_file) - return config - -def RunSystemCommand(cmd, verbose): - """Runs |cmd|, prints the |cmd| and its output if |verbose|; otherwise - captures its output and only emits it on failure. - """ - if verbose: - print 'Running', cmd - - try: - # Run |cmd|, redirecting stderr to stdout in order for captured errors to be - # inline with corresponding stdout. - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - if verbose: - print output - except subprocess.CalledProcessError as e: - raise Exception("Error while running cmd: %s\n" - "Exit code: %s\n" - "Command output:\n%s" % - (e.cmd, e.returncode, e.output)) - -def CreateArchiveFile(options, staging_dir): - """Creates a new installer archive file after deleting any existing old file. - """ - # First create an uncompressed archive file for the current build (updater.7z) - lzma_exec = GetLZMAExec(options.build_dir) - archive_file = os.path.join(options.output_dir, - options.output_name + ARCHIVE_SUFFIX) - - if options.depfile: - # If a depfile was requested, do the glob of the staging dir and generate - # a list of dependencies in .d format. We list the files that were copied - # into the staging dir, not the files that are actually in the staging dir - # because the ones in the staging dir will never be edited, and we want - # to have the build be triggered when the thing-that-was-copied-there - # changes. - - def PathFixup(path): - """Fixes path for depfile format: backslash to forward slash, and - backslash escaping for spaces.""" - return path.replace('\\', '/').replace(' ', '\\ ') - - # Gather the list of files in the staging dir that will be zipped up. We - # only gather this list to make sure that g_archive_inputs is complete (i.e. - # that there's not file copies that got missed). - staging_contents = [] - for root, files in os.walk(os.path.join(staging_dir, UPDATER_DIR)): - for filename in files: - staging_contents.append(PathFixup(os.path.join(root, filename))) - - # Make sure there's an archive_input for each staging dir file. - for staging_file in staging_contents: - for archive_input in g_archive_inputs: - archive_rel = PathFixup(archive_input) - if (os.path.basename(staging_file).lower() == - os.path.basename(archive_rel).lower()): - break - else: - raise Exception('Did not find an archive input file for "%s"' % - staging_file) - - # Finally, write the depfile referencing the inputs. - with open(options.depfile, 'wb') as f: - f.write(PathFixup(os.path.relpath(archive_file, options.build_dir)) + - ': \\\n') - f.write(' ' + ' \\\n '.join(PathFixup(x) for x in g_archive_inputs)) - - # It is important to use abspath to create the path to the directory because - # if you use a relative path without any .. sequences then 7za.exe uses the - # entire relative path as part of the file paths in the archive. If you have - # a .. sequence or an absolute path then only the last directory is stored as - # part of the file paths in the archive, which is what we want. - cmd = [lzma_exec, - 'a', - '-t7z', - archive_file, - os.path.abspath(os.path.join(staging_dir, UPDATER_DIR)), - '-mx0',] - # There does not seem to be any way in 7za.exe to override existing file so - # we always delete before creating a new one. - if not os.path.exists(archive_file): - RunSystemCommand(cmd, options.verbose) - elif options.skip_rebuild_archive != "true": - os.remove(archive_file) - RunSystemCommand(cmd, options.verbose) - - # Do not compress the archive when skip_archive_compression is specified. - if options.skip_archive_compression: - compressed_file = os.path.join( - options.output_dir, options.output_name + COMPRESSED_ARCHIVE_SUFFIX) - if os.path.exists(compressed_file): - os.remove(compressed_file) - return os.path.basename(archive_file) - - compressed_archive_file = options.output_name + COMPRESSED_ARCHIVE_SUFFIX - compressed_archive_file_path = os.path.join(options.output_dir, - compressed_archive_file) - CompressUsingLZMA(options.build_dir, compressed_archive_file_path, - archive_file, options.verbose) - - return compressed_archive_file - - -_RESOURCE_FILE_HEADER = """\ -// This file is automatically generated by create_installer_archive.py. -// It contains the resource entries that are going to be linked inside the exe. -// For each file to be linked there should be two lines: -// - The first line contains the output filename (without path) and the -// type of the resource ('BN' - not compressed , 'BL' - LZ compressed, -// 'B7' - LZMA compressed) -// - The second line contains the path to the input file. Uses '/' to -// separate path components. -""" - -def CreateResourceInputFile( - output_dir, archive_file, resource_file_path, - component_build, staging_dir): - """Creates resource input file for installer target.""" - - # An array of (file, type, path) tuples of the files to be included. - resources = [(archive_file, 'B7', - os.path.join(output_dir, archive_file))] - - with open(resource_file_path, 'w') as f: - f.write(_RESOURCE_FILE_HEADER) - for (file, type, path) in resources: - f.write('\n%s %s\n "%s"\n' % (file, type, path.replace("\\","/"))) - - -def ParseDLLsFromDeps(build_dir, runtime_deps_file): - """Parses the runtime_deps file and returns the set of DLLs in it, relative - to build_dir.""" - build_dlls = set() - args = open(runtime_deps_file).read() - for l in args.splitlines(): - if os.path.splitext(l)[1] == ".dll": - build_dlls.add(os.path.join(build_dir, l)) - return build_dlls - -# Copies component build DLLs for the setup to be able to find those DLLs at -# run-time. -# This is meant for developer builds only and should never be used to package -# an official build. -def DoComponentBuildTasks(staging_dir, build_dir, setup_runtime_deps): - installer_dir = os.path.join(staging_dir, UPDATER_DIR) - if not os.path.exists(installer_dir): - os.mkdir(installer_dir) - - setup_component_dlls = ParseDLLsFromDeps(build_dir, setup_runtime_deps) - - for setup_component_dll in setup_component_dlls: - g_archive_inputs.append(setup_component_dll) - shutil.copy(setup_component_dll, installer_dir) - -def main(options): - """Main method that reads input file, creates archive file and writes - resource input file. - """ - config = Readconfig(options.input_file) - - staging_dir = MakeStagingDirectory(options.staging_dir) - - # Copy the files from the build dir. - CopyAllFilesToStagingDir(config, staging_dir, options.build_dir) - - if options.component_build == '1': - DoComponentBuildTasks(staging_dir, options.build_dir, - options.setup_runtime_deps) - - # Name of the archive file built (for example - updater.7z) - archive_file = CreateArchiveFile(options, staging_dir) - CreateResourceInputFile(options.output_dir, - archive_file, options.resource_file_path, - options.component_build == '1', staging_dir) - -def _ParseOptions(): - parser = optparse.OptionParser() - parser.add_option('-i', '--input_file', - help='Input file describing which files to archive.') - parser.add_option('-b', '--build_dir', - help='Build directory. The paths in input_file are relative to this.') - parser.add_option('--staging_dir', - help='Staging directory where intermediate files and directories ' - 'will be created') - parser.add_option('-o', '--output_dir', - help='The output directory where the archives will be written. ' - 'Defaults to the build_dir.') - parser.add_option('--resource_file_path', - help='The path where the resource file will be output. ') - parser.add_option('-s', '--skip_rebuild_archive', - default="False", help='Skip re-building updater.7z archive if it exists.') - parser.add_option('-n', '--output_name', default='updater', - help='Name used to prefix names of generated archives.') - parser.add_option('--component_build', default='0', - help='Whether this archive is packaging a component build.') - parser.add_option('--skip_archive_compression', - action='store_true', default=False, - help='Turn off compression of updater.7z into updater.packed.7z and ' - 'helpfully delete any old updater.packed.7z in |output_dir|.') - parser.add_option('--depfile', - help='Generate a depfile with the given name listing the implicit inputs ' - 'to the archive process that can be used with a build system.') - parser.add_option('--setup_runtime_deps', - help='A file listing runtime dependencies for setup.exe. This will be ' - 'used to get a list of DLLs to archive in a component build.') - parser.add_option('-v', '--verbose', action='store_true', dest='verbose', - default=False) - - options, _ = parser.parse_args() - if not options.build_dir: - parser.error('You must provide a build dir.') - - options.build_dir = os.path.normpath(options.build_dir) - - if not options.staging_dir: - parser.error('You must provide a staging dir.') - - if not options.input_file: - parser.error('You must provide an input file') - - is_component_build = options.component_build == '1' - if is_component_build and not options.setup_runtime_deps: - parser.error("updater_runtime_deps must be specified for a component build") - - if not options.output_dir: - options.output_dir = options.build_dir - - return options - - -if '__main__' == __name__: - options = _ParseOptions() - if options.verbose: - print sys.argv - sys.exit(main(options))
diff --git a/src/cobalt/updater/win/installer/exit_code.h b/src/cobalt/updater/win/installer/exit_code.h deleted file mode 100644 index a970400..0000000 --- a/src/cobalt/updater/win/installer/exit_code.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_INSTALLER_EXIT_CODE_H_ -#define CHROME_UPDATER_WIN_INSTALLER_EXIT_CODE_H_ - -namespace updater { - -// Installer process exit codes (the underlying type is uint32_t). -enum ExitCode { - SUCCESS_EXIT_CODE = 0, - GENERIC_INITIALIZATION_FAILURE = 101, - COMMAND_STRING_OVERFLOW = 105, - WAIT_FOR_PROCESS_FAILED = 107, - PATH_STRING_OVERFLOW = 108, - UNABLE_TO_GET_WORK_DIRECTORY = 109, - UNABLE_TO_EXTRACT_ARCHIVE = 112, - UNABLE_TO_SET_DIRECTORY_ACL = 117, - INVALID_OPTION = 118, - RUN_SETUP_FAILED_FILE_NOT_FOUND = 122, // ERROR_FILE_NOT_FOUND. - RUN_SETUP_FAILED_PATH_NOT_FOUND = 123, // ERROR_PATH_NOT_FOUND. - RUN_SETUP_FAILED_COULD_NOT_CREATE_PROCESS = 124, // All other errors. -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_INSTALLER_EXIT_CODE_H_
diff --git a/src/cobalt/updater/win/installer/installer.cc b/src/cobalt/updater/win/installer/installer.cc deleted file mode 100644 index 787a3da..0000000 --- a/src/cobalt/updater/win/installer/installer.cc +++ /dev/null
@@ -1,460 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// GoogleUpdateSetup.exe is the first exe that is run when chrome is being -// installed. It has two main jobs: -// 1) unpack the resources (possibly decompressing some) -// 2) run the real installer (updater.exe) with appropriate flags (--install). -// -// All files needed by the updater are archived together as an uncompressed -// LZMA file, which is further compressed as one file, and inserted as a -// binary resource in the resource section of the setup program. - -#include "chrome/updater/win/installer/installer.h" - -// #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the -// "Community Additions" comment on MSDN here: -// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx -#define SystemFunction036 NTAPI SystemFunction036 -#include <NTSecAPI.h> -#undef SystemFunction036 - -#include <sddl.h> -#include <shellapi.h> -#include <stddef.h> -#include <stdlib.h> - -#include <initializer_list> - -// TODO(sorin): remove the dependecies on //base/ to reduce the code size. -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/path_service.h" -#include "chrome/installer/util/lzma_util.h" -#include "chrome/installer/util/self_cleaning_temp_dir.h" -#include "chrome/installer/util/util_constants.h" -#include "chrome/updater/win/installer/configuration.h" -#include "chrome/updater/win/installer/installer_constants.h" -#include "chrome/updater/win/installer/pe_resource.h" -#include "chrome/updater/win/installer/regkey.h" - -namespace updater { - -namespace { - -// Initializes |temp_path| to "Temp" within the target directory, and -// |unpack_path| to a random directory beginning with "source" within -// |temp_path|. Returns false on error. -bool CreateTemporaryAndUnpackDirectories( - installer::SelfCleaningTempDir* temp_path, - base::FilePath* unpack_path) { - DCHECK(temp_path && unpack_path); - - base::FilePath temp_dir; - if (!base::PathService::Get(base::DIR_TEMP, &temp_dir)) - return false; - - if (!temp_path->Initialize(temp_dir, kTempPrefix)) { - PLOG(ERROR) << "Could not create temporary path."; - return false; - } - VLOG(1) << "Created path " << temp_path->path().value(); - - if (!base::CreateTemporaryDirInDir(temp_path->path(), L"source", - unpack_path)) { - PLOG(ERROR) << "Could not create temporary path for unpacked archive."; - return false; - } - - return true; -} - -} // namespace - -using PathString = StackString<MAX_PATH>; - -// This structure passes data back and forth for the processing -// of resource callbacks. -struct Context { - // Input to the call back method. Specifies the dir to save resources into. - const wchar_t* base_path = nullptr; - - // First output from call back method. Specifies the path of resource archive. - PathString* updater_resource_path = nullptr; -}; - -// Calls CreateProcess with good default parameters and waits for the process to -// terminate returning the process exit code. In case of CreateProcess failure, -// returns a results object with the provided codes as follows: -// - ERROR_FILE_NOT_FOUND: (file_not_found_code, attributes of setup.exe). -// - ERROR_PATH_NOT_FOUND: (path_not_found_code, attributes of setup.exe). -// - Otherwise: (generic_failure_code, CreateProcess error code). -// In case of error waiting for the process to exit, returns a results object -// with (WAIT_FOR_PROCESS_FAILED, last error code). Otherwise, returns a results -// object with the subprocess's exit code. -ProcessExitResult RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline) { - STARTUPINFOW si = {sizeof(si)}; - PROCESS_INFORMATION pi = {0}; - if (!::CreateProcess(exe_path, cmdline, nullptr, nullptr, FALSE, - CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi)) { - // Split specific failure modes. If the process couldn't be launched because - // its file/path couldn't be found, report its attributes in ExtraCode1. - // This will help diagnose the prevalence of launch failures due to Image - // File Execution Options tampering. See https://crbug.com/672813 for more - // details. - const DWORD last_error = ::GetLastError(); - const DWORD attributes = ::GetFileAttributes(exe_path); - switch (last_error) { - case ERROR_FILE_NOT_FOUND: - return ProcessExitResult(RUN_SETUP_FAILED_FILE_NOT_FOUND, attributes); - case ERROR_PATH_NOT_FOUND: - return ProcessExitResult(RUN_SETUP_FAILED_PATH_NOT_FOUND, attributes); - default: - break; - } - // Lump all other errors into a distinct failure bucket. - return ProcessExitResult(RUN_SETUP_FAILED_COULD_NOT_CREATE_PROCESS, - last_error); - } - - ::CloseHandle(pi.hThread); - - DWORD exit_code = SUCCESS_EXIT_CODE; - DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE); - if (WAIT_OBJECT_0 != wr || !::GetExitCodeProcess(pi.hProcess, &exit_code)) { - // Note: We've assumed that WAIT_OBJCT_0 != wr means a failure. The call - // could return a different object but since we never spawn more than one - // sub-process at a time that case should never happen. - return ProcessExitResult(WAIT_FOR_PROCESS_FAILED, ::GetLastError()); - } - - ::CloseHandle(pi.hProcess); - - return ProcessExitResult(exit_code); -} - -// Windows defined callback used in the EnumResourceNames call. For each -// matching resource found, the callback is invoked and at this point we write -// it to disk. We expect resource names to start with the 'updater' prefix. -// Any other name is treated as an error. -BOOL CALLBACK OnResourceFound(HMODULE module, - const wchar_t* type, - wchar_t* name, - LONG_PTR context) { - Context* ctx = reinterpret_cast<Context*>(context); - if (!ctx) - return FALSE; - - if (!StrStartsWith(name, kUpdaterArchivePrefix)) - return FALSE; - - PEResource resource(name, type, module); - if (!resource.IsValid() || resource.Size() < 1) - return FALSE; - - PathString full_path; - if (!full_path.assign(ctx->base_path) || !full_path.append(name) || - !resource.WriteToDisk(full_path.get())) { - return FALSE; - } - - if (!ctx->updater_resource_path->assign(full_path.get())) - return FALSE; - - return TRUE; -} - -// Finds and writes to disk resources of type 'B7' (7zip archive). Returns false -// if there is a problem in writing any resource to disk. -ProcessExitResult UnpackBinaryResources(const Configuration& configuration, - HMODULE module, - const wchar_t* base_path, - PathString* archive_path) { - // Prepare the input to OnResourceFound method that needs a location where - // it will write all the resources. - Context context = {base_path, archive_path}; - - // Get the resources of type 'B7' (7zip archive). - if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound, - reinterpret_cast<LONG_PTR>(&context))) { - return ProcessExitResult(UNABLE_TO_EXTRACT_ARCHIVE, ::GetLastError()); - } - - if (archive_path->length() == 0) - return ProcessExitResult(UNABLE_TO_EXTRACT_ARCHIVE); - - ProcessExitResult exit_code = ProcessExitResult(SUCCESS_EXIT_CODE); - - return exit_code; -} - -// Executes updater.exe, waits for it to finish and returns the exit code. -ProcessExitResult RunSetup(const Configuration& configuration, - const wchar_t* setup_path) { - PathString setup_exe; - - if (*setup_path != L'\0') { - if (!setup_exe.assign(setup_path)) - return ProcessExitResult(COMMAND_STRING_OVERFLOW); - } - - CommandString cmd_line; - - // Put the quoted path to setup.exe in cmd_line first. - if (!cmd_line.assign(L"\"") || !cmd_line.append(setup_exe.get()) || - !cmd_line.append(L"\"")) { - return ProcessExitResult(COMMAND_STRING_OVERFLOW); - } - - if (!cmd_line.append(L" --install --enable-logging --v=1")) - return ProcessExitResult(COMMAND_STRING_OVERFLOW); - - return RunProcessAndWait(setup_exe.get(), cmd_line.get()); -} - -// Returns true if the supplied path supports ACLs. -bool IsAclSupportedForPath(const wchar_t* path) { - PathString volume; - DWORD flags = 0; - return ::GetVolumePathName(path, volume.get(), - static_cast<DWORD>(volume.capacity())) && - ::GetVolumeInformation(volume.get(), nullptr, 0, nullptr, nullptr, - &flags, nullptr, 0) && - (flags & FILE_PERSISTENT_ACLS); -} - -// Retrieves the SID of the default owner for objects created by this user -// token (accounting for different behavior under UAC elevation, etc.). -// NOTE: On success the |sid| parameter must be freed with LocalFree(). -bool GetCurrentOwnerSid(wchar_t** sid) { - HANDLE token; - if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token)) - return false; - - DWORD size = 0; - bool result = false; - // We get the TokenOwner rather than the TokenUser because e.g. under UAC - // elevation we want the admin to own the directory rather than the user. - ::GetTokenInformation(token, TokenOwner, nullptr, 0, &size); - if (size && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - if (TOKEN_OWNER* owner = - reinterpret_cast<TOKEN_OWNER*>(::LocalAlloc(LPTR, size))) { - if (::GetTokenInformation(token, TokenOwner, owner, size, &size)) - result = !!::ConvertSidToStringSid(owner->Owner, sid); - ::LocalFree(owner); - } - } - ::CloseHandle(token); - return result; -} - -// Populates |sd| suitable for use when creating directories within |path| with -// ACLs allowing access to only the current owner, admin, and system. -// NOTE: On success the |sd| parameter must be freed with LocalFree(). -bool SetSecurityDescriptor(const wchar_t* path, PSECURITY_DESCRIPTOR* sd) { - *sd = nullptr; - // We succeed without doing anything if ACLs aren't supported. - if (!IsAclSupportedForPath(path)) - return true; - - wchar_t* sid = nullptr; - if (!GetCurrentOwnerSid(&sid)) - return false; - - // The largest SID is under 200 characters, so 300 should give enough slack. - StackString<300> sddl; - bool result = sddl.append( - L"D:PAI" // Protected, auto-inherited DACL. - L"(A;;FA;;;BA)" // Admin: Full control. - L"(A;OIIOCI;GA;;;BA)" - L"(A;;FA;;;SY)" // System: Full control. - L"(A;OIIOCI;GA;;;SY)" - L"(A;OIIOCI;GA;;;CO)" // Owner: Full control. - L"(A;;FA;;;") && - sddl.append(sid) && sddl.append(L")"); - if (result) { - result = !!::ConvertStringSecurityDescriptorToSecurityDescriptor( - sddl.get(), SDDL_REVISION_1, sd, nullptr); - } - - ::LocalFree(sid); - return result; -} - -// Creates a temporary directory under |base_path| and returns the full path -// of created directory in |work_dir|. If successful return true, otherwise -// false. When successful, the returned |work_dir| will always have a trailing -// backslash and this function requires that |base_path| always includes a -// trailing backslash as well. -// We do not use GetTempFileName here to avoid running into AV software that -// might hold on to the temp file as soon as we create it and then we can't -// delete it and create a directory in its place. So, we use our own mechanism -// for creating a directory with a hopefully-unique name. In the case of a -// collision, we retry a few times with a new name before failing. -bool CreateWorkDir(const wchar_t* base_path, - PathString* work_dir, - ProcessExitResult* exit_code) { - *exit_code = ProcessExitResult(PATH_STRING_OVERFLOW); - if (!work_dir->assign(base_path) || !work_dir->append(kTempPrefix)) - return false; - - // Store the location where we'll append the id. - size_t end = work_dir->length(); - - // Check if we'll have enough buffer space to continue. - // The name of the directory will use up 11 chars and then we need to append - // the trailing backslash and a terminator. We've already added the prefix - // to the buffer, so let's just make sure we've got enough space for the rest. - if ((work_dir->capacity() - end) < (_countof("fffff.tmp") + 1)) - return false; - - // Add an ACL if supported by the filesystem. Otherwise system-level installs - // are potentially vulnerable to file squatting attacks. - SECURITY_ATTRIBUTES sa = {}; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - if (!SetSecurityDescriptor(base_path, &sa.lpSecurityDescriptor)) { - *exit_code = - ProcessExitResult(UNABLE_TO_SET_DIRECTORY_ACL, ::GetLastError()); - return false; - } - - unsigned int id; - *exit_code = ProcessExitResult(UNABLE_TO_GET_WORK_DIRECTORY); - for (int max_attempts = 10; max_attempts; --max_attempts) { - ::RtlGenRandom(&id, sizeof(id)); // Try a different name. - - // This converts 'id' to a string in the format "78563412" on windows - // because of little endianness, but we don't care since it's just - // a name. Since we checked capaity at the front end, we don't need to - // duplicate it here. - HexEncode(&id, sizeof(id), work_dir->get() + end, - work_dir->capacity() - end); - - // We only want the first 5 digits to remain within the 8.3 file name - // format (compliant with previous implementation). - work_dir->truncate_at(end + 5); - - // for consistency with the previous implementation which relied on - // GetTempFileName, we append the .tmp extension. - work_dir->append(L".tmp"); - - if (::CreateDirectory(work_dir->get(), - sa.lpSecurityDescriptor ? &sa : nullptr)) { - // Yay! Now let's just append the backslash and we're done. - work_dir->append(L"\\"); - *exit_code = ProcessExitResult(SUCCESS_EXIT_CODE); - break; - } - } - - if (sa.lpSecurityDescriptor) - LocalFree(sa.lpSecurityDescriptor); - return exit_code->IsSuccess(); -} - -// Creates and returns a temporary directory in |work_dir| that can be used to -// extract updater payload. |work_dir| ends with a path separator. -bool GetWorkDir(HMODULE module, - PathString* work_dir, - ProcessExitResult* exit_code) { - PathString base_path; - DWORD len = - ::GetTempPath(static_cast<DWORD>(base_path.capacity()), base_path.get()); - if (!len || len >= base_path.capacity() || - !CreateWorkDir(base_path.get(), work_dir, exit_code)) { - // Problem creating the work dir under TEMP path, so try using the - // current directory as the base path. - len = ::GetModuleFileName(module, base_path.get(), - static_cast<DWORD>(base_path.capacity())); - if (len >= base_path.capacity() || !len) - return false; // Can't even get current directory? Return an error. - - wchar_t* name = GetNameFromPathExt(base_path.get(), len); - if (name == base_path.get()) - return false; // There was no directory in the string! Bail out. - - *name = L'\0'; - - *exit_code = ProcessExitResult(SUCCESS_EXIT_CODE); - return CreateWorkDir(base_path.get(), work_dir, exit_code); - } - return true; -} - -// Returns true for ".." and "." directories. -bool IsCurrentOrParentDirectory(const wchar_t* dir) { - return dir && dir[0] == L'.' && - (dir[1] == L'\0' || (dir[1] == L'.' && dir[2] == L'\0')); -} - -ProcessExitResult WMain(HMODULE module) { - ProcessExitResult exit_code = ProcessExitResult(SUCCESS_EXIT_CODE); - - // Parse configuration from the command line and resources. - Configuration configuration; - if (!configuration.Initialize(module)) - return ProcessExitResult(GENERIC_INITIALIZATION_FAILURE, ::GetLastError()); - - // Exit early if an invalid switch was found on the command line. - if (configuration.has_invalid_switch()) - return ProcessExitResult(INVALID_OPTION); - - // First get a path where we can extract the resource payload, which is - // a compressed LZMA archive of a single file. - base::ScopedTempDir base_path_owner; - PathString base_path; - if (!GetWorkDir(module, &base_path, &exit_code)) - return exit_code; - if (!base_path_owner.Set(base::FilePath(base_path.get()))) { - ::DeleteFile(base_path.get()); - return ProcessExitResult(static_cast<DWORD>(installer::TEMP_DIR_FAILED)); - } - - PathString compressed_archive; - exit_code = UnpackBinaryResources(configuration, module, base_path.get(), - &compressed_archive); - - // Create a temp folder where the archives are unpacked. - base::FilePath unpack_path; - installer::SelfCleaningTempDir temp_path; - if (!CreateTemporaryAndUnpackDirectories(&temp_path, &unpack_path)) - return ProcessExitResult(static_cast<DWORD>(installer::TEMP_DIR_FAILED)); - - // Unpack the compressed archive to extract the uncompressed archive file. - UnPackStatus unpack_status = UNPACK_NO_ERROR; - int32_t ntstatus = 0; - auto lzma_result = - UnPackArchive(base::FilePath(compressed_archive.get()), unpack_path, - nullptr, &unpack_status, &ntstatus); - if (lzma_result) - return ProcessExitResult(static_cast<DWORD>(installer::UNPACKING_FAILED)); - - // Unpack the uncompressed archive to extract the updater files. - base::FilePath uncompressed_archive = - unpack_path.Append(FILE_PATH_LITERAL("updater.7z")); - lzma_result = UnPackArchive(uncompressed_archive, unpack_path, nullptr, - &unpack_status, &ntstatus); - if (lzma_result) - return ProcessExitResult(static_cast<DWORD>(installer::UNPACKING_FAILED)); - - // While unpacking the binaries, we paged in a whole bunch of memory that - // we don't need anymore. Let's give it back to the pool before running - // setup. - ::SetProcessWorkingSetSize(::GetCurrentProcess(), static_cast<SIZE_T>(-1), - static_cast<SIZE_T>(-1)); - - PathString setup_path; - if (!setup_path.assign(unpack_path.value().c_str()) || - !setup_path.append(L"\\bin\\updater.exe")) { - exit_code = ProcessExitResult(PATH_STRING_OVERFLOW); - } - - if (exit_code.IsSuccess()) - exit_code = RunSetup(configuration, setup_path.get()); - - return exit_code; -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/installer/installer.exe.manifest b/src/cobalt/updater/win/installer/installer.exe.manifest deleted file mode 100644 index c7ac2fa..0000000 --- a/src/cobalt/updater/win/installer/installer.exe.manifest +++ /dev/null
@@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> - <!-- - Have compatibility section here instead of using - build/win/compatibility.manifest - to work around crbug.com/272660. - TODO(yukawa): Use build/win/compatibility.manifest again. - --> - <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> - <application> - <!--The ID below indicates application support for Windows Vista --> - <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> - <!--The ID below indicates application support for Windows 7 --> - <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> - <!--The ID below indicates application support for Windows 8 --> - <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> - <!--The ID below indicates application support for Windows 8.1 --> - <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> - <!--The ID below indicates application support for Windows 10 --> - <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> - </application> - </compatibility> - <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2"> - <ms_asmv2:security> - <ms_asmv2:requestedPrivileges> - <ms_asmv2:requestedExecutionLevel level="asInvoker" /> - </ms_asmv2:requestedPrivileges> - </ms_asmv2:security> - </ms_asmv2:trustInfo> -</assembly>
diff --git a/src/cobalt/updater/win/installer/installer.h b/src/cobalt/updater/win/installer/installer.h deleted file mode 100644 index 0a7b75e..0000000 --- a/src/cobalt/updater/win/installer/installer.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_INSTALLER_INSTALLER_H_ -#define CHROME_UPDATER_WIN_INSTALLER_INSTALLER_H_ - -#include <windows.h> - -#include "chrome/updater/win/installer/exit_code.h" -#include "chrome/updater/win/installer/string.h" - -namespace updater { - -// A container of a process exit code (eventually passed to ExitProcess) and -// a Windows error code for cases where the exit code is non-zero. -struct ProcessExitResult { - DWORD exit_code; - DWORD windows_error; - - explicit ProcessExitResult(DWORD exit) : exit_code(exit), windows_error(0) {} - ProcessExitResult(DWORD exit, DWORD win) - : exit_code(exit), windows_error(win) {} - - bool IsSuccess() const { return exit_code == SUCCESS_EXIT_CODE; } -}; - -// A stack-based string large enough to hold an executable to run -// (which is a path), plus a few extra arguments. -using CommandString = StackString<MAX_PATH * 4>; - -// Main function for the installer. -ProcessExitResult WMain(HMODULE module); - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_INSTALLER_INSTALLER_H_
diff --git a/src/cobalt/updater/win/installer/installer.ico b/src/cobalt/updater/win/installer/installer.ico deleted file mode 100644 index 5ecfcbd..0000000 --- a/src/cobalt/updater/win/installer/installer.ico +++ /dev/null Binary files differ
diff --git a/src/cobalt/updater/win/installer/installer.rc b/src/cobalt/updater/win/installer/installer.rc deleted file mode 100644 index 76cb035..0000000 --- a/src/cobalt/updater/win/installer/installer.rc +++ /dev/null
@@ -1,55 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "installer_resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_MINI_INSTALLER ICON "installer.ico" - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "installer_resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOL\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -/////////////////////////////////////////////////////////////////////////////
diff --git a/src/cobalt/updater/win/installer/installer_constants.cc b/src/cobalt/updater/win/installer/installer_constants.cc deleted file mode 100644 index f102f7a..0000000 --- a/src/cobalt/updater/win/installer/installer_constants.cc +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/installer/installer_constants.h" - -namespace updater { - -// The prefix of the updater archive resource. -const wchar_t kUpdaterArchivePrefix[] = L"updater"; - -// Temp directory prefix that this process creates. -const wchar_t kTempPrefix[] = L"UPDATER"; - -// 7zip archive. -const wchar_t kLZMAResourceType[] = L"B7"; - -} // namespace updater
diff --git a/src/cobalt/updater/win/installer/installer_constants.h b/src/cobalt/updater/win/installer/installer_constants.h deleted file mode 100644 index fc0bf77..0000000 --- a/src/cobalt/updater/win/installer/installer_constants.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_INSTALLER_INSTALLER_CONSTANTS_H_ -#define CHROME_UPDATER_WIN_INSTALLER_INSTALLER_CONSTANTS_H_ - -namespace updater { - -// Various filenames and prefixes. -extern const wchar_t kUpdaterArchivePrefix[]; -extern const wchar_t kTempPrefix[]; - -// The resource types that would be unpacked from the mini installer. -extern const wchar_t kLZMAResourceType[]; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_INSTALLER_INSTALLER_CONSTANTS_H_
diff --git a/src/cobalt/updater/win/installer/installer_main.cc b/src/cobalt/updater/win/installer/installer_main.cc deleted file mode 100644 index 8c181ca..0000000 --- a/src/cobalt/updater/win/installer/installer_main.cc +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <windows.h> - -#include "chrome/updater/win/installer/installer.h" - -// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx -extern "C" IMAGE_DOS_HEADER __ImageBase; - -int WINAPI wWinMain(HINSTANCE /* instance */, - HINSTANCE /* previous_instance */, - LPWSTR /* command_line */, - int /* command_show */) { - updater::ProcessExitResult result = - updater::WMain(reinterpret_cast<HMODULE>(&__ImageBase)); - - return result.exit_code; -}
diff --git a/src/cobalt/updater/win/installer/installer_resource.h b/src/cobalt/updater/win/installer/installer_resource.h deleted file mode 100644 index 2bf5e97..0000000 --- a/src/cobalt/updater/win/installer/installer_resource.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright (c) 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_INSTALLER_INSTALLER_RESOURCE_H_ -#define CHROME_UPDATER_WIN_INSTALLER_INSTALLER_RESOURCE_H_ - -#define IDC_STATIC -1 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 129 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 110 -#endif -#endif - -#endif // CHROME_UPDATER_WIN_INSTALLER_INSTALLER_RESOURCE_H_
diff --git a/src/cobalt/updater/win/installer/installer_version.rc.version b/src/cobalt/updater/win/installer/installer_version.rc.version deleted file mode 100644 index bbe41b4..0000000 --- a/src/cobalt/updater/win/installer/installer_version.rc.version +++ /dev/null
@@ -1,44 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -// Use the ordinal 1 here, to avoid needing to #include a header file -// to use the VS_VERSION_INFO macro. This header file changes with different -// SDK versions which causes headaches building in some environments. The -// VERSIONINFO resource will always be at index 1. -1 VERSIONINFO - FILEVERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@ - PRODUCTVERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@ - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "@COMPANY_FULLNAME@" - VALUE "FileDescription", "@PRODUCT_INSTALLER_FULLNAME@" - VALUE "FileVersion", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@" - VALUE "InternalName", "Chrome Updater" - VALUE "LegalCopyright", "@COPYRIGHT@" - VALUE "ProductName", "@PRODUCT_INSTALLER_FULLNAME@" - VALUE "ProductVersion", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@" - VALUE "CompanyShortName", "@COMPANY_SHORTNAME@" - VALUE "ProductShortName", "@PRODUCT_INSTALLER_SHORTNAME@" - VALUE "LastChange", "@LASTCHANGE@" - VALUE "Official Build", "@OFFICIAL_BUILD@" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END
diff --git a/src/cobalt/updater/win/installer/pe_resource.cc b/src/cobalt/updater/win/installer/pe_resource.cc deleted file mode 100644 index 248a133..0000000 --- a/src/cobalt/updater/win/installer/pe_resource.cc +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/installer/pe_resource.h" - -namespace updater { - -PEResource::PEResource(const wchar_t* name, const wchar_t* type, HMODULE module) - : resource_(nullptr), module_(module) { - resource_ = ::FindResource(module, name, type); -} - -bool PEResource::IsValid() { - return nullptr != resource_; -} - -size_t PEResource::Size() { - return ::SizeofResource(module_, resource_); -} - -bool PEResource::WriteToDisk(const wchar_t* full_path) { - // Resource handles are not real HGLOBALs so do not attempt to close them. - // Windows frees them whenever there is memory pressure. - HGLOBAL data_handle = ::LoadResource(module_, resource_); - if (nullptr == data_handle) - return false; - - void* data = ::LockResource(data_handle); - if (nullptr == data) - return false; - - size_t resource_size = Size(); - HANDLE out_file = ::CreateFile(full_path, GENERIC_WRITE, 0, nullptr, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (INVALID_HANDLE_VALUE == out_file) - return false; - - DWORD written = 0; - if (!::WriteFile(out_file, data, static_cast<DWORD>(resource_size), &written, - nullptr)) { - ::CloseHandle(out_file); - return false; - } - return ::CloseHandle(out_file) ? true : false; -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/installer/pe_resource.h b/src/cobalt/updater/win/installer/pe_resource.h deleted file mode 100644 index e19531a..0000000 --- a/src/cobalt/updater/win/installer/pe_resource.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_INSTALLER_PE_RESOURCE_H_ -#define CHROME_UPDATER_WIN_INSTALLER_PE_RESOURCE_H_ - -#include <stddef.h> -#include <windows.h> - -namespace updater { - -// This class models a windows PE resource. It does not pretend to be a full -// API wrapper and it is just concerned with loading it to memory and writing -// it to disk. Each resource is unique only in the context of a loaded module, -// that is why you need to specify one on each constructor. -class PEResource { - public: - // Takes the resource name, the resource type, and the module where - // to look for the resource. If the resource is found IsValid() returns true. - PEResource(const wchar_t* name, const wchar_t* type, HMODULE module); - - // Returns true if the resource is valid. - bool IsValid(); - - // Returns the size in bytes of the resource. Returns zero if the resource is - // not valid. - size_t Size(); - - // Creates a file in |path| with a copy of the resource. If the resource can - // not be loaded into memory or if it cannot be written to disk it returns - // false. - bool WriteToDisk(const wchar_t* path); - - private: - HRSRC resource_ = nullptr; - HMODULE module_ = nullptr; -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_INSTALLER_PE_RESOURCE_H_
diff --git a/src/cobalt/updater/win/installer/regkey.cc b/src/cobalt/updater/win/installer/regkey.cc deleted file mode 100644 index 62b622d..0000000 --- a/src/cobalt/updater/win/installer/regkey.cc +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/installer/regkey.h" - -#include "chrome/updater/win/installer/installer_constants.h" -#include "chrome/updater/win/installer/string.h" - -namespace updater { - -LONG RegKey::Open(HKEY key, const wchar_t* sub_key, REGSAM access) { - Close(); - return ::RegOpenKeyEx(key, sub_key, 0, access, &key_); -} - -LONG RegKey::ReadSZValue(const wchar_t* value_name, - wchar_t* value, - size_t value_size) const { - DWORD type = 0; - DWORD byte_length = static_cast<DWORD>(value_size * sizeof(wchar_t)); - LONG result = ::RegQueryValueEx(key_, value_name, nullptr, &type, - reinterpret_cast<BYTE*>(value), &byte_length); - if (result == ERROR_SUCCESS) { - if (type != REG_SZ) { - result = ERROR_NOT_SUPPORTED; - } else if (byte_length < 2) { - *value = L'\0'; - } else if (value[byte_length / sizeof(wchar_t) - 1] != L'\0') { - if ((byte_length / sizeof(wchar_t)) < value_size) - value[byte_length / sizeof(wchar_t)] = L'\0'; - else - result = ERROR_MORE_DATA; - } - } - return result; -} - -LONG RegKey::ReadDWValue(const wchar_t* value_name, DWORD* value) const { - DWORD type = 0; - DWORD byte_length = sizeof(*value); - LONG result = ::RegQueryValueEx(key_, value_name, nullptr, &type, - reinterpret_cast<BYTE*>(value), &byte_length); - if (result == ERROR_SUCCESS) { - if (type != REG_DWORD) { - result = ERROR_NOT_SUPPORTED; - } else if (byte_length != sizeof(*value)) { - result = ERROR_NO_DATA; - } - } - return result; -} - -LONG RegKey::WriteSZValue(const wchar_t* value_name, const wchar_t* value) { - return ::RegSetValueEx(key_, value_name, 0, REG_SZ, - reinterpret_cast<const BYTE*>(value), - (lstrlen(value) + 1) * sizeof(wchar_t)); -} - -LONG RegKey::WriteDWValue(const wchar_t* value_name, DWORD value) { - return ::RegSetValueEx(key_, value_name, 0, REG_DWORD, - reinterpret_cast<const BYTE*>(&value), sizeof(value)); -} - -void RegKey::Close() { - if (key_ != nullptr) { - ::RegCloseKey(key_); - key_ = nullptr; - } -} - -// static -bool RegKey::ReadSZValue(HKEY root_key, - const wchar_t* sub_key, - const wchar_t* value_name, - wchar_t* value, - size_t size) { - RegKey key; - return (key.Open(root_key, sub_key, KEY_QUERY_VALUE) == ERROR_SUCCESS && - key.ReadSZValue(value_name, value, size) == ERROR_SUCCESS); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/installer/regkey.h b/src/cobalt/updater/win/installer/regkey.h deleted file mode 100644 index 5dd7c40..0000000 --- a/src/cobalt/updater/win/installer/regkey.h +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_INSTALLER_REGKEY_H_ -#define CHROME_UPDATER_WIN_INSTALLER_REGKEY_H_ - -#include <stddef.h> -#include <windows.h> - -namespace updater { - -// A helper class used to manipulate the Windows registry. -class RegKey { - public: - RegKey() : key_(nullptr) {} - ~RegKey() { Close(); } - - // Opens the key named |sub_key| with given |access| rights. Returns - // ERROR_SUCCESS or some other error. - LONG Open(HKEY key, const wchar_t* sub_key, REGSAM access); - - // Returns true if a key is open. - bool is_valid() const { return key_ != nullptr; } - - // Read a value from the registry into the memory indicated by |value| - // (of |value_size| wchar_t units). Returns ERROR_SUCCESS, - // ERROR_FILE_NOT_FOUND, ERROR_MORE_DATA, or some other error. |value| is - // guaranteed to be null-terminated on success. - LONG ReadSZValue(const wchar_t* value_name, - wchar_t* value, - size_t value_size) const; - LONG ReadDWValue(const wchar_t* value_name, DWORD* value) const; - - // Write a value to the registry. SZ |value| must be null-terminated. - // Returns ERROR_SUCCESS or an error code. - LONG WriteSZValue(const wchar_t* value_name, const wchar_t* value); - LONG WriteDWValue(const wchar_t* value_name, DWORD value); - - // Closes the key if it was open. - void Close(); - - // Helper function to read a value from registry. Returns true if value - // is read successfully and stored in parameter value. Returns false - // otherwise. |size| is measured in wchar_t units. - static bool ReadSZValue(HKEY root_key, - const wchar_t* sub_key, - const wchar_t* value_name, - wchar_t* value, - size_t value_size); - - private: - RegKey(const RegKey&); - RegKey& operator=(const RegKey&); - - HKEY key_; -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_INSTALLER_REGKEY_H_
diff --git a/src/cobalt/updater/win/installer/run_all_unittests.cc b/src/cobalt/updater/win/installer/run_all_unittests.cc deleted file mode 100644 index 875ccb9..0000000 --- a/src/cobalt/updater/win/installer/run_all_unittests.cc +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright (c) 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" - -int main(int argc, char** argv) { - base::TestSuite test_suite(argc, argv); - - return base::LaunchUnitTestsSerially( - argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); -}
diff --git a/src/cobalt/updater/win/installer/string.cc b/src/cobalt/updater/win/installer/string.cc deleted file mode 100644 index 61120a1..0000000 --- a/src/cobalt/updater/win/installer/string.cc +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/installer/string.h" - -#include <windows.h> - -namespace { - -// Returns true if the given two ASCII characters are same (ignoring case). -bool EqualASCIICharI(wchar_t a, wchar_t b) { - if (a >= L'A' && a <= L'Z') - a += (L'a' - L'A'); - if (b >= L'A' && b <= L'Z') - b += (L'a' - L'A'); - return (a == b); -} - -} // namespace - -namespace updater { - -// Formats a sequence of |bytes| as hex. The |str| buffer must have room for -// at least 2*|size| + 1. -bool HexEncode(const void* bytes, size_t size, wchar_t* str, size_t str_size) { - if (str_size <= (size * 2)) - return false; - - static const wchar_t kHexChars[] = L"0123456789ABCDEF"; - - str[size * 2] = L'\0'; - - for (size_t i = 0; i < size; ++i) { - char b = reinterpret_cast<const char*>(bytes)[i]; - str[(i * 2)] = kHexChars[(b >> 4) & 0xf]; - str[(i * 2) + 1] = kHexChars[b & 0xf]; - } - - return true; -} - -size_t SafeStrLen(const wchar_t* str, size_t alloc_size) { - if (!str || !alloc_size) - return 0; - size_t len = 0; - while (--alloc_size && str[len] != L'\0') - ++len; - return len; -} - -bool SafeStrCopy(wchar_t* dest, size_t dest_size, const wchar_t* src) { - if (!dest || !dest_size) - return false; - - wchar_t* write = dest; - for (size_t remaining = dest_size; remaining != 0; --remaining) { - if ((*write++ = *src++) == L'\0') - return true; - } - - // If we fail, we do not want to leave the string with partially copied - // contents. The reason for this is that we use these strings mostly for - // named objects such as files. If we copy a partial name, then that could - // match with something we do not want it to match with. - // Furthermore, since SafeStrCopy is called from SafeStrCat, we do not - // want to mutate the string in case the caller handles the error of a - // failed concatenation. For example: - // - // wchar_t buf[5] = {0}; - // if (!SafeStrCat(buf, _countof(buf), kLongName)) - // SafeStrCat(buf, _countof(buf), kShortName); - // - // If we were to return false in the first call to SafeStrCat but still - // mutate the buffer, the buffer will be in an unexpected state. - *dest = L'\0'; - return false; -} - -// Safer replacement for lstrcat function. -bool SafeStrCat(wchar_t* dest, size_t dest_size, const wchar_t* src) { - // Use SafeStrLen instead of lstrlen just in case the |dest| buffer isn't - // terminated. - size_t str_len = SafeStrLen(dest, dest_size); - return SafeStrCopy(dest + str_len, dest_size - str_len, src); -} - -bool StrStartsWith(const wchar_t* str, const wchar_t* start_str) { - if (str == nullptr || start_str == nullptr) - return false; - - for (int i = 0; start_str[i] != L'\0'; ++i) { - if (!EqualASCIICharI(str[i], start_str[i])) - return false; - } - - return true; -} - -const wchar_t* GetNameFromPathExt(const wchar_t* path, size_t size) { - if (!size) - return path; - - const wchar_t* current = &path[size - 1]; - while (current != path && L'\\' != *current) - --current; - - // If no path separator found, just return |path|. - // Otherwise, return a pointer right after the separator. - return ((current == path) && (L'\\' != *current)) ? current : (current + 1); -} - -wchar_t* GetNameFromPathExt(wchar_t* path, size_t size) { - return const_cast<wchar_t*>( - GetNameFromPathExt(const_cast<const wchar_t*>(path), size)); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/installer/string.h b/src/cobalt/updater/win/installer/string.h deleted file mode 100644 index a04e7f7..0000000 --- a/src/cobalt/updater/win/installer/string.h +++ /dev/null
@@ -1,117 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_INSTALLER_STRING_H_ -#define CHROME_UPDATER_WIN_INSTALLER_STRING_H_ - -#include <stddef.h> - -namespace updater { - -// NOTE: Do not assume that these string functions support UTF encoding. -// This is fine for the purposes of the mini_installer, but you have -// been warned! - -// Formats a sequence of |bytes| as hex. The |str| buffer must have room for -// at least 2*|size| + 1. -bool HexEncode(const void* bytes, size_t size, wchar_t* str, size_t str_size); - -// Counts the number of characters in the string up to a maximum of -// alloc_size. The highest return value from this function can therefore be -// alloc_size - 1 since |alloc_size| includes the \0 terminator. -size_t SafeStrLen(const wchar_t* str, size_t alloc_size); - -// Simple replacement for CRT string copy method that does not overflow. -// Returns true if the source was copied successfully otherwise returns false. -// Parameter src is assumed to be nullptr terminated and the nullptr character -// is copied over to string dest. -bool SafeStrCopy(wchar_t* dest, size_t dest_size, const wchar_t* src); - -// Simple replacement for CRT string copy method that does not overflow. -// Returns true if the source was copied successfully otherwise returns false. -// Parameter src is assumed to be nullptr terminated and the nullptr character -// is copied over to string dest. If the return value is false, the |dest| -// string should be the same as it was before. -bool SafeStrCat(wchar_t* dest, size_t dest_size, const wchar_t* src); - -// Function to check if a string (specified by str) starts with another string -// (specified by start_str). The comparison is string insensitive. -bool StrStartsWith(const wchar_t* str, const wchar_t* start_str); - -// Takes the path to file and returns a pointer to the basename component. -// Example input -> output: -// c:\full\path\to\file.ext -> file.ext -// file.ext -> file.ext -// Note: |size| is the number of characters in |path| not including the string -// terminator. -const wchar_t* GetNameFromPathExt(const wchar_t* path, size_t size); -wchar_t* GetNameFromPathExt(wchar_t* path, size_t size); - -// A string class that manages a fixed size buffer on the stack. -// The methods in the class are based on the above string methods and the -// class additionally is careful about proper buffer termination. -template <size_t kCapacity> -class StackString { - public: - StackString() { - static_assert(kCapacity != 0, "invalid buffer size"); - buffer_[kCapacity] = L'\0'; // We always reserve 1 more than asked for. - clear(); - } - - // We do not expose a constructor that accepts a string pointer on purpose. - // We expect the caller to call assign() and handle failures. - - // Returns the number of reserved characters in this buffer, _including_ - // the reserved char for the terminator. - size_t capacity() const { return kCapacity; } - - wchar_t* get() { return buffer_; } - - bool assign(const wchar_t* str) { - return SafeStrCopy(buffer_, kCapacity, str); - } - - bool append(const wchar_t* str) { - return SafeStrCat(buffer_, kCapacity, str); - } - - void clear() { buffer_[0] = L'\0'; } - - size_t length() const { return SafeStrLen(buffer_, kCapacity); } - - // Does a case insensitive search for a substring. - const wchar_t* findi(const wchar_t* find) const { - return SearchStringI(buffer_, find); - } - - // Case insensitive string compare. - int comparei(const wchar_t* str) const { return lstrcmpiW(buffer_, str); } - - // Case sensitive string compare. - int compare(const wchar_t* str) const { return lstrcmpW(buffer_, str); } - - // Terminates the string at the specified location. - // Note: this method has no effect if this object's length is less than - // |location|. - bool truncate_at(size_t location) { - if (location >= kCapacity) - return false; - buffer_[location] = L'\0'; - return true; - } - - protected: - // We reserve 1 more than what is asked for as a safeguard against - // off-by-one errors. - wchar_t buffer_[kCapacity + 1]; - - private: - StackString(const StackString&); - StackString& operator=(const StackString&); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_INSTALLER_STRING_H_
diff --git a/src/cobalt/updater/win/installer/string_unittest.cc b/src/cobalt/updater/win/installer/string_unittest.cc deleted file mode 100644 index d36b3a0..0000000 --- a/src/cobalt/updater/win/installer/string_unittest.cc +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdlib.h> -#include <windows.h> - -#include <string> - -#include "chrome/updater/win/installer/string.h" -#include "testing/gtest/include/gtest/gtest.h" - -using updater::StackString; - -namespace { -class InstallerStringTest : public testing::Test { - protected: - void SetUp() override {} - void TearDown() override {} -}; -} // namespace - -// Tests the strcat/strcpy/length support of the StackString class. -TEST_F(InstallerStringTest, StackStringOverflow) { - static const wchar_t kTestString[] = L"1234567890"; - - StackString<MAX_PATH> str; - EXPECT_EQ(static_cast<size_t>(MAX_PATH), str.capacity()); - - std::wstring compare_str; - - EXPECT_EQ(str.length(), compare_str.length()); - EXPECT_EQ(0, compare_str.compare(str.get())); - - size_t max_chars = str.capacity() - 1; - - while ((str.length() + (_countof(kTestString) - 1)) <= max_chars) { - EXPECT_TRUE(str.append(kTestString)); - compare_str.append(kTestString); - EXPECT_EQ(str.length(), compare_str.length()); - EXPECT_EQ(0, compare_str.compare(str.get())); - } - - EXPECT_GT(static_cast<size_t>(MAX_PATH), str.length()); - - // Now we've exhausted the space we allocated for the string, - // so append should fail. - EXPECT_FALSE(str.append(kTestString)); - - // ...and remain unchanged. - EXPECT_EQ(0, compare_str.compare(str.get())); - EXPECT_EQ(str.length(), compare_str.length()); - - // Last test for fun. - str.clear(); - compare_str.clear(); - EXPECT_EQ(0, compare_str.compare(str.get())); - EXPECT_EQ(str.length(), compare_str.length()); -}
diff --git a/src/cobalt/updater/win/installer/updater.release b/src/cobalt/updater/win/installer/updater.release deleted file mode 100644 index 9d20d88..0000000 --- a/src/cobalt/updater/win/installer/updater.release +++ /dev/null
@@ -1,3 +0,0 @@ -[GENERAL] -updater.exe: %(UpdaterDir)s\ -gen\chrome\updater\win\uninstall.cmd: %(UpdaterDir)s\
diff --git a/src/cobalt/updater/win/main.cc b/src/cobalt/updater/win/main.cc deleted file mode 100644 index 59bbc94..0000000 --- a/src/cobalt/updater/win/main.cc +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <windows.h> - -#include "chrome/updater/updater.h" - -int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) { - return updater::UpdaterMain(0, nullptr); -}
diff --git a/src/cobalt/updater/win/net/net_util.cc b/src/cobalt/updater/win/net/net_util.cc deleted file mode 100644 index ba26d4b..0000000 --- a/src/cobalt/updater/win/net/net_util.cc +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/net/net_util.h" - -#include <vector> -#include "base/strings/string_piece.h" - -namespace updater { - -HRESULT QueryHeadersString(HINTERNET request_handle, - uint32_t info_level, - base::StringPiece16 name, - base::string16* value) { - DWORD num_bytes = 0; - ::WinHttpQueryHeaders(request_handle, info_level, name.data(), - WINHTTP_NO_OUTPUT_BUFFER, &num_bytes, - WINHTTP_NO_HEADER_INDEX); - auto hr = HRESULTFromLastError(); - if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) - return hr; - std::vector<base::char16> buffer(num_bytes / sizeof(base::char16)); - if (!::WinHttpQueryHeaders(request_handle, info_level, name.data(), - &buffer.front(), &num_bytes, - WINHTTP_NO_HEADER_INDEX)) { - return HRESULTFromLastError(); - } - DCHECK_EQ(0u, num_bytes % sizeof(base::char16)); - buffer.resize(num_bytes / sizeof(base::char16)); - value->assign(buffer.begin(), buffer.end()); - return S_OK; -} - -HRESULT QueryHeadersInt(HINTERNET request_handle, - uint32_t info_level, - base::StringPiece16 name, - int* value) { - info_level |= WINHTTP_QUERY_FLAG_NUMBER; - DWORD num_bytes = sizeof(*value); - if (!::WinHttpQueryHeaders(request_handle, info_level, name.data(), value, - &num_bytes, WINHTTP_NO_HEADER_INDEX)) { - return HRESULTFromLastError(); - } - - return S_OK; -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/net/net_util.h b/src/cobalt/updater/win/net/net_util.h deleted file mode 100644 index cf0d309..0000000 --- a/src/cobalt/updater/win/net/net_util.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_NET_NET_UTIL_H_ -#define CHROME_UPDATER_WIN_NET_NET_UTIL_H_ - -#include <windows.h> -#include <winhttp.h> - -#include <stdint.h> - -#include <string> - -#include "base/logging.h" -#include "base/strings/string_piece_forward.h" -#include "chrome/updater/win/util.h" - -namespace updater { - -HRESULT QueryHeadersString(HINTERNET request_handle, - uint32_t info_level, - base::StringPiece16 name, - base::string16* value); - -HRESULT QueryHeadersInt(HINTERNET request_handle, - uint32_t info_level, - base::StringPiece16 name, - int* value); - -// Queries WinHTTP options for the given |handle|. Returns S_OK if the call -// is successful. -template <typename T> -HRESULT QueryOption(HINTERNET handle, uint32_t option, T* value) { - auto num_bytes = sizeof(*value); - if (!::WinHttpQueryOption(handle, option, value, &num_bytes)) { - DCHECK_EQ(sizeof(*value), num_bytes); - return HRESULTFromLastError(); - } - return S_OK; -} - -// Sets WinHTTP options for the given |handle|. Returns S_OK if the call -// is successful. -template <typename T> -HRESULT SetOption(HINTERNET handle, uint32_t option, T value) { - if (!::WinHttpSetOption(handle, option, &value, sizeof(value))) - return HRESULTFromLastError(); - return S_OK; -} - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_NET_NET_UTIL_H_
diff --git a/src/cobalt/updater/win/net/network.h b/src/cobalt/updater/win/net/network.h deleted file mode 100644 index 6dbd601..0000000 --- a/src/cobalt/updater/win/net/network.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_NET_NETWORK_H_ -#define CHROME_UPDATER_WIN_NET_NETWORK_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread_checker.h" -#include "chrome/updater/win/net/scoped_hinternet.h" -#include "components/update_client/network.h" - -namespace updater { - -// Network fetcher factory for WinHTTP. -class NetworkFetcherFactory : public update_client::NetworkFetcherFactory { - public: - NetworkFetcherFactory(); - - std::unique_ptr<update_client::NetworkFetcher> Create() const override; - - protected: - ~NetworkFetcherFactory() override; - - private: - static scoped_hinternet CreateSessionHandle(); - - THREAD_CHECKER(thread_checker_); - scoped_hinternet session_handle_; - - DISALLOW_COPY_AND_ASSIGN(NetworkFetcherFactory); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_NET_NETWORK_H_
diff --git a/src/cobalt/updater/win/net/network_fetcher.cc b/src/cobalt/updater/win/net/network_fetcher.cc deleted file mode 100644 index 1ca27e1..0000000 --- a/src/cobalt/updater/win/net/network_fetcher.cc +++ /dev/null
@@ -1,98 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/net/network_fetcher.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/win/windows_version.h" -#include "chrome/updater/win/net/network.h" -#include "chrome/updater/win/net/network_winhttp.h" - -namespace updater { - -NetworkFetcher::NetworkFetcher(const HINTERNET& session_handle) - : network_fetcher_( - base::MakeRefCounted<NetworkFetcherWinHTTP>(session_handle)), - main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} - -NetworkFetcher::~NetworkFetcher() { - network_fetcher_->Close(); -} - -void NetworkFetcher::PostRequest( - const GURL& url, - const std::string& post_data, - const base::flat_map<std::string, std::string>& post_additional_headers, - ResponseStartedCallback response_started_callback, - ProgressCallback progress_callback, - PostRequestCompleteCallback post_request_complete_callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - post_request_complete_callback_ = std::move(post_request_complete_callback); - network_fetcher_->PostRequest( - url, post_data, post_additional_headers, - std::move(response_started_callback), std::move(progress_callback), - base::BindOnce(&NetworkFetcher::PostRequestComplete, - base::Unretained(this))); -} - -void NetworkFetcher::DownloadToFile( - const GURL& url, - const base::FilePath& file_path, - ResponseStartedCallback response_started_callback, - ProgressCallback progress_callback, - DownloadToFileCompleteCallback download_to_file_complete_callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - download_to_file_complete_callback_ = - std::move(download_to_file_complete_callback); - network_fetcher_->DownloadToFile( - url, file_path, std::move(response_started_callback), - std::move(progress_callback), - base::BindOnce(&NetworkFetcher::DownloadToFileComplete, - base::Unretained(this))); -} - -void NetworkFetcher::PostRequestComplete() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - std::move(post_request_complete_callback_) - .Run(std::make_unique<std::string>(network_fetcher_->GetResponseBody()), - network_fetcher_->GetNetError(), network_fetcher_->GetHeaderETag(), - network_fetcher_->GetXHeaderRetryAfterSec()); -} - -void NetworkFetcher::DownloadToFileComplete() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - std::move(download_to_file_complete_callback_) - .Run(network_fetcher_->GetFilePath(), network_fetcher_->GetNetError(), - network_fetcher_->GetContentSize()); -} - -NetworkFetcherFactory::NetworkFetcherFactory() - : session_handle_(CreateSessionHandle()) {} -NetworkFetcherFactory::~NetworkFetcherFactory() = default; - -scoped_hinternet NetworkFetcherFactory::CreateSessionHandle() { - const auto* os_info = base::win::OSInfo::GetInstance(); - const uint32_t access_type = os_info->version() >= base::win::Version::WIN8_1 - ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY - : WINHTTP_ACCESS_TYPE_NO_PROXY; - return scoped_hinternet( - ::WinHttpOpen(L"Chrome Updater", access_type, WINHTTP_NO_PROXY_NAME, - WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC)); -} - -std::unique_ptr<update_client::NetworkFetcher> NetworkFetcherFactory::Create() - const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return session_handle_.get() - ? std::make_unique<NetworkFetcher>(session_handle_.get()) - : nullptr; -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/net/network_fetcher.h b/src/cobalt/updater/win/net/network_fetcher.h deleted file mode 100644 index ca83807..0000000 --- a/src/cobalt/updater/win/net/network_fetcher.h +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_NET_NETWORK_FETCHER_H_ -#define CHROME_UPDATER_WIN_NET_NETWORK_FETCHER_H_ - -#include <windows.h> - -#include <stdint.h> - -#include <string> - -#include "base/callback.h" -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread_checker.h" -#include "components/update_client/network.h" -#include "url/gurl.h" - -namespace base { -class FilePath; -class SingleThreadTaskRunner; -} // namespace base - -namespace updater { - -class NetworkFetcherWinHTTP; - -class NetworkFetcher : public update_client::NetworkFetcher { - public: - using ResponseStartedCallback = - update_client::NetworkFetcher::ResponseStartedCallback; - using ProgressCallback = update_client::NetworkFetcher::ProgressCallback; - using PostRequestCompleteCallback = - update_client::NetworkFetcher::PostRequestCompleteCallback; - using DownloadToFileCompleteCallback = - update_client::NetworkFetcher::DownloadToFileCompleteCallback; - - explicit NetworkFetcher(const HINTERNET& session_handle_); - ~NetworkFetcher() override; - - // NetworkFetcher overrides. - void PostRequest( - const GURL& url, - const std::string& post_data, - const base::flat_map<std::string, std::string>& post_additional_headers, - ResponseStartedCallback response_started_callback, - ProgressCallback progress_callback, - PostRequestCompleteCallback post_request_complete_callback) override; - void DownloadToFile(const GURL& url, - const base::FilePath& file_path, - ResponseStartedCallback response_started_callback, - ProgressCallback progress_callback, - DownloadToFileCompleteCallback - download_to_file_complete_callback) override; - - private: - THREAD_CHECKER(thread_checker_); - - void PostRequestComplete(); - void DownloadToFileComplete(); - - scoped_refptr<NetworkFetcherWinHTTP> network_fetcher_; - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - - DownloadToFileCompleteCallback download_to_file_complete_callback_; - PostRequestCompleteCallback post_request_complete_callback_; - - DISALLOW_COPY_AND_ASSIGN(NetworkFetcher); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_NET_NETWORK_FETCHER_H_
diff --git a/src/cobalt/updater/win/net/network_unittest.cc b/src/cobalt/updater/win/net/network_unittest.cc deleted file mode 100644 index b6854fc..0000000 --- a/src/cobalt/updater/win/net/network_unittest.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/net/network.h" - -#include "base/memory/ref_counted.h" -#include "base/run_loop.h" -#include "base/test/task_environment.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace updater { - -TEST(UpdaterTestNetwork, NetworkFetcherWinHTTPFactory) { - base::test::TaskEnvironment task_environment( - base::test::TaskEnvironment::MainThreadType::UI); - auto fetcher = base::MakeRefCounted<NetworkFetcherFactory>()->Create(); - EXPECT_NE(nullptr, fetcher.get()); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/net/network_winhttp.cc b/src/cobalt/updater/win/net/network_winhttp.cc deleted file mode 100644 index c029453..0000000 --- a/src/cobalt/updater/win/net/network_winhttp.cc +++ /dev/null
@@ -1,553 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/net/network_winhttp.h" - -#include <limits> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/files/file.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/numerics/safe_math.h" -#include "base/strings/strcat.h" -#include "base/strings/string16.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "base/strings/stringprintf.h" -#include "base/strings/sys_string_conversions.h" -#include "base/task/post_task.h" -#include "base/threading/thread_task_runner_handle.h" -#include "chrome/updater/win/net/net_util.h" -#include "chrome/updater/win/net/network.h" -#include "chrome/updater/win/net/scoped_hinternet.h" -#include "chrome/updater/win/util.h" -#include "url/url_constants.h" - -namespace updater { - -namespace { - -void CrackUrl(const GURL& url, - bool* is_https, - std::string* host, - int* port, - std::string* path_for_request) { - if (is_https) - *is_https = url.SchemeIs(url::kHttpsScheme); - if (host) - *host = url.host(); - if (port) - *port = url.EffectiveIntPort(); - if (path_for_request) - *path_for_request = url.PathForRequest(); -} - -} // namespace - -NetworkFetcherWinHTTP::NetworkFetcherWinHTTP(const HINTERNET& session_handle) - : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), - session_handle_(session_handle) {} - -NetworkFetcherWinHTTP::~NetworkFetcherWinHTTP() {} - -void NetworkFetcherWinHTTP::Close() { - request_handle_.reset(); -} - -std::string NetworkFetcherWinHTTP::GetResponseBody() const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return post_response_body_; -} - -HRESULT NetworkFetcherWinHTTP::GetNetError() const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return net_error_; -} - -std::string NetworkFetcherWinHTTP::GetHeaderETag() const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return etag_; -} - -int64_t NetworkFetcherWinHTTP::GetXHeaderRetryAfterSec() const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return xheader_retry_after_sec_; -} - -base::FilePath NetworkFetcherWinHTTP::GetFilePath() const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return file_path_; -} - -int64_t NetworkFetcherWinHTTP::GetContentSize() const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return content_size_; -} - -void NetworkFetcherWinHTTP::PostRequest( - const GURL& url, - const std::string& post_data, - const base::flat_map<std::string, std::string>& post_additional_headers, - FetchStartedCallback fetch_started_callback, - FetchProgressCallback fetch_progress_callback, - FetchCompleteCallback fetch_complete_callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - url_ = url; - fetch_started_callback_ = std::move(fetch_started_callback); - fetch_progress_callback_ = std::move(fetch_progress_callback); - fetch_complete_callback_ = std::move(fetch_complete_callback); - - DCHECK(url.SchemeIsHTTPOrHTTPS()); - CrackUrl(url, &is_https_, &host_, &port_, &path_for_request_); - - verb_ = L"POST"; - content_type_ = L"Content-Type: application/json\r\n"; - write_data_callback_ = base::BindRepeating( - &NetworkFetcherWinHTTP::WriteDataToMemory, base::Unretained(this)); - - net_error_ = BeginFetch(post_data, post_additional_headers); - if (FAILED(net_error_)) - std::move(fetch_complete_callback_).Run(); -} - -void NetworkFetcherWinHTTP::DownloadToFile( - const GURL& url, - const base::FilePath& file_path, - FetchStartedCallback fetch_started_callback, - FetchProgressCallback fetch_progress_callback, - FetchCompleteCallback fetch_complete_callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - url_ = url; - file_path_ = file_path; - fetch_started_callback_ = std::move(fetch_started_callback); - fetch_progress_callback_ = std::move(fetch_progress_callback); - fetch_complete_callback_ = std::move(fetch_complete_callback); - - DCHECK(url.SchemeIsHTTPOrHTTPS()); - CrackUrl(url, &is_https_, &host_, &port_, &path_for_request_); - - verb_ = L"GET"; - write_data_callback_ = base::BindRepeating( - &NetworkFetcherWinHTTP::WriteDataToFile, base::Unretained(this)); - - net_error_ = BeginFetch({}, {}); - if (FAILED(net_error_)) - std::move(fetch_complete_callback_).Run(); -} - -HRESULT NetworkFetcherWinHTTP::BeginFetch( - const std::string& data, - const base::flat_map<std::string, std::string>& additional_headers) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - connect_handle_ = Connect(); - if (!connect_handle_.get()) - return HRESULTFromLastError(); - - request_handle_ = OpenRequest(); - if (!request_handle_.get()) - return HRESULTFromLastError(); - - const auto winhttp_callback = ::WinHttpSetStatusCallback( - request_handle_.get(), &NetworkFetcherWinHTTP::WinHttpStatusCallback, - WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0); - if (winhttp_callback == WINHTTP_INVALID_STATUS_CALLBACK) - return HRESULTFromLastError(); - - auto hr = - SetOption(request_handle_.get(), WINHTTP_OPTION_CONTEXT_VALUE, context()); - if (FAILED(hr)) - return hr; - - self_ = this; - - // Disables both saving and sending cookies. - hr = SetOption(request_handle_.get(), WINHTTP_OPTION_DISABLE_FEATURE, - WINHTTP_DISABLE_COOKIES); - if (FAILED(hr)) - return hr; - - if (!content_type_.empty()) { - ::WinHttpAddRequestHeaders( - request_handle_.get(), content_type_.data(), content_type_.size(), - WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE); - } - for (const auto& header : additional_headers) { - const auto raw_header = base::SysUTF8ToWide( - base::StrCat({header.first, ": ", header.second, "\r\n"})); - ::WinHttpAddRequestHeaders( - request_handle_.get(), raw_header.c_str(), raw_header.size(), - WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE); - } - - hr = SendRequest(data); - if (FAILED(hr)) - return hr; - - return S_OK; -} - -scoped_hinternet NetworkFetcherWinHTTP::Connect() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return scoped_hinternet(::WinHttpConnect( - session_handle_, base::SysUTF8ToWide(host_).c_str(), port_, 0)); -} - -scoped_hinternet NetworkFetcherWinHTTP::OpenRequest() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - uint32_t flags = WINHTTP_FLAG_REFRESH; - if (is_https_) - flags |= WINHTTP_FLAG_SECURE; - return scoped_hinternet(::WinHttpOpenRequest( - connect_handle_.get(), verb_.data(), - base::SysUTF8ToWide(path_for_request_).c_str(), nullptr, - WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, flags)); -} - -HRESULT NetworkFetcherWinHTTP::SendRequest(const std::string& data) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - const uint32_t bytes_to_send = base::saturated_cast<uint32_t>(data.size()); - void* request_body = - bytes_to_send ? const_cast<char*>(data.c_str()) : WINHTTP_NO_REQUEST_DATA; - if (!::WinHttpSendRequest(request_handle_.get(), - WINHTTP_NO_ADDITIONAL_HEADERS, 0, request_body, - bytes_to_send, bytes_to_send, context())) { - return HRESULTFromLastError(); - } - - return S_OK; -} - -void NetworkFetcherWinHTTP::SendRequestComplete() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - base::string16 all; - QueryHeadersString( - request_handle_.get(), - WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS, - WINHTTP_HEADER_NAME_BY_INDEX, &all); - VLOG(2) << "request headers: " << all; - - net_error_ = ReceiveResponse(); - if (FAILED(net_error_)) - std::move(fetch_complete_callback_).Run(); -} - -HRESULT NetworkFetcherWinHTTP::ReceiveResponse() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!::WinHttpReceiveResponse(request_handle_.get(), nullptr)) - return HRESULTFromLastError(); - return S_OK; -} - -void NetworkFetcherWinHTTP::ReceiveResponseComplete() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - base::string16 all; - QueryHeadersString(request_handle_.get(), WINHTTP_QUERY_RAW_HEADERS_CRLF, - WINHTTP_HEADER_NAME_BY_INDEX, &all); - VLOG(2) << "response headers: " << all; - - int response_code = 0; - net_error_ = QueryHeadersInt(request_handle_.get(), WINHTTP_QUERY_STATUS_CODE, - WINHTTP_HEADER_NAME_BY_INDEX, &response_code); - if (FAILED(net_error_)) { - std::move(fetch_complete_callback_).Run(); - return; - } - - int content_length = 0; - net_error_ = - QueryHeadersInt(request_handle_.get(), WINHTTP_QUERY_CONTENT_LENGTH, - WINHTTP_HEADER_NAME_BY_INDEX, &content_length); - if (FAILED(net_error_)) { - std::move(fetch_complete_callback_).Run(); - return; - } - - base::string16 etag; - if (SUCCEEDED(QueryHeadersString(request_handle_.get(), WINHTTP_QUERY_ETAG, - WINHTTP_HEADER_NAME_BY_INDEX, &etag))) { - etag_ = base::SysWideToUTF8(etag); - } - - int xheader_retry_after_sec = 0; - if (SUCCEEDED(QueryHeadersInt( - request_handle_.get(), WINHTTP_QUERY_CUSTOM, - base::SysUTF8ToWide( - update_client::NetworkFetcher::kHeaderXRetryAfter), - &xheader_retry_after_sec))) { - xheader_retry_after_sec_ = xheader_retry_after_sec; - } - - std::move(fetch_started_callback_) - .Run(final_url_.is_valid() ? final_url_ : url_, response_code, - content_length); - - net_error_ = QueryDataAvailable(); - if (FAILED(net_error_)) - std::move(fetch_complete_callback_).Run(); -} - -HRESULT NetworkFetcherWinHTTP::QueryDataAvailable() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!::WinHttpQueryDataAvailable(request_handle_.get(), nullptr)) - return HRESULTFromLastError(); - return S_OK; -} - -void NetworkFetcherWinHTTP::QueryDataAvailableComplete( - size_t num_bytes_available) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - net_error_ = ReadData(num_bytes_available); - if (FAILED(net_error_)) - std::move(fetch_complete_callback_).Run(); -} - -HRESULT NetworkFetcherWinHTTP::ReadData(size_t num_bytes_available) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - const int num_bytes_to_read = base::saturated_cast<int>(num_bytes_available); - read_buffer_.resize(num_bytes_to_read); - - if (!::WinHttpReadData(request_handle_.get(), &read_buffer_.front(), - read_buffer_.size(), nullptr)) { - return HRESULTFromLastError(); - } - return S_OK; -} - -void NetworkFetcherWinHTTP::ReadDataComplete(size_t num_bytes_read) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - fetch_progress_callback_.Run(base::saturated_cast<int64_t>(num_bytes_read)); - - read_buffer_.resize(num_bytes_read); - write_data_callback_.Run(); -} - -void NetworkFetcherWinHTTP::RequestError(const WINHTTP_ASYNC_RESULT* result) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - net_error_ = HRESULTFromUpdaterError(result->dwError); - std::move(fetch_complete_callback_).Run(); -} - -void NetworkFetcherWinHTTP::WriteDataToFile() { - constexpr base::TaskTraits kTaskTraits = { - base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}; - - base::PostTaskAndReplyWithResult( - FROM_HERE, kTaskTraits, - base::BindOnce(&NetworkFetcherWinHTTP::WriteDataToFileBlocking, - base::Unretained(this)), - base::BindOnce(&NetworkFetcherWinHTTP::WriteDataToFileComplete, - base::Unretained(this))); -} - -bool NetworkFetcherWinHTTP::WriteDataToFileBlocking() { - if (read_buffer_.empty()) { - file_.Close(); - net_error_ = S_OK; - return true; - } - - if (!file_.IsValid()) { - file_.Initialize(file_path_, base::File::Flags::FLAG_CREATE_ALWAYS | - base::File::Flags::FLAG_WRITE | - base::File::Flags::FLAG_SEQUENTIAL_SCAN); - if (!file_.IsValid()) { - net_error_ = HRESULTFromUpdaterError(file_.error_details()); - return false; - } - } - - DCHECK(file_.IsValid()); - if (file_.WriteAtCurrentPos(&read_buffer_.front(), read_buffer_.size()) == - -1) { - net_error_ = HRESULTFromUpdaterError(base::File::GetLastFileError()); - file_.Close(); - base::DeleteFile(file_path_, false); - return false; - } - - content_size_ += read_buffer_.size(); - return false; -} - -void NetworkFetcherWinHTTP::WriteDataToFileComplete(bool is_eof) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - if (is_eof || FAILED(net_error_)) { - std::move(fetch_complete_callback_).Run(); - return; - } - - net_error_ = QueryDataAvailable(); - if (FAILED(net_error_)) - std::move(fetch_complete_callback_).Run(); -} - -void NetworkFetcherWinHTTP::WriteDataToMemory() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - if (read_buffer_.empty()) { - VLOG(2) << post_response_body_; - net_error_ = S_OK; - std::move(fetch_complete_callback_).Run(); - return; - } - - post_response_body_.append(read_buffer_.begin(), read_buffer_.end()); - content_size_ += read_buffer_.size(); - - net_error_ = QueryDataAvailable(); - if (FAILED(net_error_)) - std::move(fetch_complete_callback_).Run(); -} - -void __stdcall NetworkFetcherWinHTTP::WinHttpStatusCallback(HINTERNET handle, - DWORD_PTR context, - DWORD status, - void* info, - DWORD info_len) { - DCHECK(handle); - DCHECK(context); - NetworkFetcherWinHTTP* network_fetcher = - reinterpret_cast<NetworkFetcherWinHTTP*>(context); - network_fetcher->main_thread_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&NetworkFetcherWinHTTP::StatusCallback, - base::Unretained(network_fetcher), handle, - status, info, info_len)); -} - -void NetworkFetcherWinHTTP::StatusCallback(HINTERNET handle, - uint32_t status, - void* info, - uint32_t info_len) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - base::StringPiece status_string; - base::string16 info_string; - switch (status) { - case WINHTTP_CALLBACK_STATUS_HANDLE_CREATED: - status_string = "handle created"; - break; - case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING: - status_string = "handle closing"; - break; - case WINHTTP_CALLBACK_STATUS_RESOLVING_NAME: - status_string = "resolving"; - info_string.assign(static_cast<base::char16*>(info), info_len); // host. - break; - case WINHTTP_CALLBACK_STATUS_NAME_RESOLVED: - status_string = "resolved"; - break; - case WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER: - status_string = "connecting"; - info_string.assign(static_cast<base::char16*>(info), info_len); // IP. - break; - case WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER: - status_string = "connected"; - break; - case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST: - status_string = "sending"; - break; - case WINHTTP_CALLBACK_STATUS_REQUEST_SENT: - status_string = "sent"; - break; - case WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE: - status_string = "receiving response"; - break; - case WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED: - status_string = "response received"; - break; - case WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION: - status_string = "connection closing"; - break; - case WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED: - status_string = "connection closed"; - break; - case WINHTTP_CALLBACK_STATUS_REDIRECT: - status_string = "redirect"; - info_string.assign(static_cast<base::char16*>(info), info_len); // URL. - break; - case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE: - status_string = "data available"; - DCHECK_EQ(info_len, sizeof(uint32_t)); - info_string = base::StringPrintf(L"%lu", *static_cast<uint32_t*>(info)); - break; - case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: - status_string = "headers available"; - break; - case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: - status_string = "read complete"; - info_string = base::StringPrintf(L"%lu", info_len); - break; - case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: - status_string = "send request complete"; - break; - case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE: - status_string = "write complete"; - break; - case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: - status_string = "request error"; - break; - case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE: - status_string = "https failure"; - DCHECK(info); - DCHECK_EQ(info_len, sizeof(uint32_t)); - info_string = base::StringPrintf(L"%#x", *static_cast<uint32_t*>(info)); - break; - default: - status_string = "unknown callback"; - break; - } - - std::string msg; - if (!status_string.empty()) - base::StringAppendF(&msg, "status=%s", status_string.data()); - else - base::StringAppendF(&msg, "status=%#x", status); - if (!info_string.empty()) - base::StringAppendF(&msg, ", info=%s", - base::SysWideToUTF8(info_string).c_str()); - - VLOG(2) << "WinHttp status callback:" - << " handle=" << handle << ", " << msg; - - switch (status) { - case WINHTTP_CALLBACK_STATUS_REDIRECT: - final_url_ = GURL(static_cast<base::char16*>(info)); - break; - case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING: - self_ = nullptr; - break; - case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: - SendRequestComplete(); - break; - case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: - ReceiveResponseComplete(); - break; - case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE: - DCHECK_EQ(info_len, sizeof(uint32_t)); - QueryDataAvailableComplete(*static_cast<uint32_t*>(info)); - break; - case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: - DCHECK_EQ(info, &read_buffer_.front()); - ReadDataComplete(info_len); - break; - case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: - RequestError(static_cast<const WINHTTP_ASYNC_RESULT*>(info)); - break; - default: - break; - } -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/net/network_winhttp.h b/src/cobalt/updater/win/net/network_winhttp.h deleted file mode 100644 index c34b602..0000000 --- a/src/cobalt/updater/win/net/network_winhttp.h +++ /dev/null
@@ -1,149 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_NET_NETWORK_WINHTTP_H_ -#define CHROME_UPDATER_WIN_NET_NETWORK_WINHTTP_H_ - -#include <windows.h> - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/strings/string_piece_forward.h" -#include "base/threading/thread_checker.h" -#include "chrome/updater/win/net/scoped_hinternet.h" -#include "components/update_client/network.h" -#include "url/gurl.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace updater { - -// Implements a network fetcher in terms of WinHTTP. The class is ref-counted -// as it is accessed from both the main thread and the worker threads in -// WinHTTP. -class NetworkFetcherWinHTTP - : public base::RefCountedThreadSafe<NetworkFetcherWinHTTP> { - public: - using FetchCompleteCallback = base::OnceCallback<void()>; - using FetchStartedCallback = - update_client::NetworkFetcher::ResponseStartedCallback; - using FetchProgressCallback = update_client::NetworkFetcher::ProgressCallback; - - explicit NetworkFetcherWinHTTP(const HINTERNET& session_handle_); - - void Close(); - - void PostRequest( - const GURL& url, - const std::string& post_data, - const base::flat_map<std::string, std::string>& post_additional_headers, - FetchStartedCallback fetch_started_callback, - FetchProgressCallback fetch_progress_callback, - FetchCompleteCallback fetch_complete_callback); - void DownloadToFile(const GURL& url, - const base::FilePath& file_path, - FetchStartedCallback fetch_started_callback, - FetchProgressCallback fetch_progress_callback, - FetchCompleteCallback fetch_complete_callback); - - std::string GetResponseBody() const; - HRESULT GetNetError() const; - std::string GetHeaderETag() const; - int64_t GetXHeaderRetryAfterSec() const; - base::FilePath GetFilePath() const; - int64_t GetContentSize() const; - - private: - friend class base::RefCountedThreadSafe<NetworkFetcherWinHTTP>; - using WriteDataCallback = base::RepeatingCallback<void()>; - - ~NetworkFetcherWinHTTP(); - - static void __stdcall WinHttpStatusCallback(HINTERNET handle, - DWORD_PTR context, - DWORD status, - void* info, - DWORD info_len); - - DWORD_PTR context() const { return reinterpret_cast<DWORD_PTR>(this); } - - void StatusCallback(HINTERNET handle, - uint32_t status, - void* info, - uint32_t info_len); - - HRESULT BeginFetch( - const std::string& data, - const base::flat_map<std::string, std::string>& additional_headers); - scoped_hinternet Connect(); - scoped_hinternet OpenRequest(); - HRESULT SendRequest(const std::string& data); - void SendRequestComplete(); - HRESULT ReceiveResponse(); - void ReceiveResponseComplete(); - HRESULT QueryDataAvailable(); - void QueryDataAvailableComplete(size_t num_bytes_available); - HRESULT ReadData(size_t num_bytes_available); - void ReadDataComplete(size_t num_bytes_read); - void RequestError(const WINHTTP_ASYNC_RESULT* result); - - void WriteDataToMemory(); - void WriteDataToFile(); - bool WriteDataToFileBlocking(); - void WriteDataToFileComplete(bool is_eof); - - THREAD_CHECKER(thread_checker_); - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - - const HINTERNET& session_handle_; // Owned by NetworkFetcherWinHTTPFactory. - scoped_hinternet connect_handle_; - scoped_hinternet request_handle_; - - // Keeps an outstanding reference count on itself as long as there is a - // valid request handle and the context for the handle is set to this - // instance. - scoped_refptr<NetworkFetcherWinHTTP> self_; - - GURL url_; - bool is_https_ = false; - std::string host_; - int port_ = 0; - std::string path_for_request_; - - GURL final_url_; - base::StringPiece16 verb_; - base::StringPiece16 content_type_; - WriteDataCallback write_data_callback_; - HRESULT net_error_ = S_OK; - std::string etag_; - int64_t xheader_retry_after_sec_ = -1; - std::vector<char> read_buffer_; - std::string post_response_body_; - base::FilePath file_path_; - base::File file_; - int64_t content_size_ = 0; - - FetchStartedCallback fetch_started_callback_; - FetchProgressCallback fetch_progress_callback_; - FetchCompleteCallback fetch_complete_callback_; - - scoped_refptr<update_client::NetworkFetcherFactory> network_fetcher_factory_; - - DISALLOW_COPY_AND_ASSIGN(NetworkFetcherWinHTTP); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_NET_NETWORK_WINHTTP_H_
diff --git a/src/cobalt/updater/win/net/scoped_hinternet.h b/src/cobalt/updater/win/net/scoped_hinternet.h deleted file mode 100644 index 235547e..0000000 --- a/src/cobalt/updater/win/net/scoped_hinternet.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_NET_SCOPED_HINTERNET_H_ -#define CHROME_UPDATER_WIN_NET_SCOPED_HINTERNET_H_ - -#include <windows.h> -#include <winhttp.h> - -#include "base/scoped_generic.h" - -namespace updater { - -namespace internal { - -struct ScopedHInternetTraits { - static HINTERNET InvalidValue() { return nullptr; } - static void Free(HINTERNET handle) { - if (handle != InvalidValue()) - WinHttpCloseHandle(handle); - } -}; - -} // namespace internal - -// Manages the lifetime of HINTERNET handles allocated by WinHTTP. -using scoped_hinternet = - base::ScopedGeneric<HINTERNET, updater::internal::ScopedHInternetTraits>; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_NET_SCOPED_HINTERNET_H_
diff --git a/src/cobalt/updater/win/setup/setup.cc b/src/cobalt/updater/win/setup/setup.cc deleted file mode 100644 index 2848c5c..0000000 --- a/src/cobalt/updater/win/setup/setup.cc +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/setup/setup.h" - -#include <memory> -#include <vector> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/strings/string16.h" -#include "base/win/scoped_com_initializer.h" -#include "chrome/installer/util/copy_tree_work_item.h" -#include "chrome/installer/util/self_cleaning_temp_dir.h" -#include "chrome/installer/util/work_item_list.h" -#include "chrome/updater/updater_constants.h" -#include "chrome/updater/util.h" -#include "chrome/updater/win/setup/setup_util.h" -#include "chrome/updater/win/task_scheduler.h" - -namespace updater { - -namespace { - -const base::char16* kUpdaterFiles[] = { - L"updater.exe", - L"uninstall.cmd", -#if defined(COMPONENT_BUILD) - // TODO(sorin): get the list of component dependencies from a build-time - // file instead of hardcoding the names of the components here. - L"base.dll", - L"boringssl.dll", - L"crcrypto.dll", - L"icuuc.dll", - L"libc++.dll", - L"prefs.dll", - L"protobuf_lite.dll", - L"url_lib.dll", - L"zlib.dll", -#endif -}; - -} // namespace - -int Setup() { - VLOG(1) << __func__; - - auto scoped_com_initializer = - std::make_unique<base::win::ScopedCOMInitializer>( - base::win::ScopedCOMInitializer::kMTA); - - if (!TaskScheduler::Initialize()) { - LOG(ERROR) << "Failed to initialize the scheduler."; - return -1; - } - base::ScopedClosureRunner task_scheduler_terminate_caller( - base::BindOnce([]() { TaskScheduler::Terminate(); })); - - base::FilePath temp_dir; - if (!base::GetTempDir(&temp_dir)) { - LOG(ERROR) << "GetTempDir failed."; - return -1; - } - base::FilePath product_dir; - if (!GetProductDirectory(&product_dir)) { - LOG(ERROR) << "GetProductDirectory failed."; - return -1; - } - base::FilePath exe_path; - if (!base::PathService::Get(base::FILE_EXE, &exe_path)) { - LOG(ERROR) << "PathService failed."; - return -1; - } - - installer::SelfCleaningTempDir backup_dir; - if (!backup_dir.Initialize(temp_dir, L"updater-backup")) { - LOG(ERROR) << "Failed to initialize the backup dir."; - return -1; - } - - const base::FilePath source_dir = exe_path.DirName(); - - std::unique_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); - for (const auto* file : kUpdaterFiles) { - const base::FilePath target_path = product_dir.Append(file); - const base::FilePath source_path = source_dir.Append(file); - install_list->AddWorkItem( - WorkItem::CreateCopyTreeWorkItem(source_path, target_path, temp_dir, - WorkItem::ALWAYS, base::FilePath())); - } - - base::CommandLine run_updater_ua_command(product_dir.Append(L"updater.exe")); - run_updater_ua_command.AppendSwitch(kUpdateAppsSwitch); -#if !defined(NDEBUG) - run_updater_ua_command.AppendSwitch(kEnableLoggingSwitch); - run_updater_ua_command.AppendSwitchASCII(kLoggingLevelSwitch, "1"); - run_updater_ua_command.AppendSwitchASCII(kLoggingModuleSwitch, - "*/chrome/updater/*"); -#endif - if (!install_list->Do() || !RegisterUpdateAppsTask(run_updater_ua_command)) { - LOG(ERROR) << "Install failed, rolling back..."; - install_list->Rollback(); - UnregisterUpdateAppsTask(); - LOG(ERROR) << "Rollback complete."; - return -1; - } - - VLOG(1) << "Setup succeeded."; - return 0; -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/setup/setup.h b/src/cobalt/updater/win/setup/setup.h deleted file mode 100644 index 2a306ba..0000000 --- a/src/cobalt/updater/win/setup/setup.h +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_SETUP_SETUP_H_ -#define CHROME_UPDATER_WIN_SETUP_SETUP_H_ - -namespace updater { - -int Setup(); - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_SETUP_SETUP_H_
diff --git a/src/cobalt/updater/win/setup/setup_util.cc b/src/cobalt/updater/win/setup/setup_util.cc deleted file mode 100644 index fff30e8..0000000 --- a/src/cobalt/updater/win/setup/setup_util.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/setup/setup_util.h" - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/strings/string16.h" -#include "chrome/updater/win/task_scheduler.h" - -namespace updater { - -namespace { - -constexpr base::char16 kTaskName[] = L"GoogleUpdaterUA"; -constexpr base::char16 kTaskDescription[] = L"Update all applications."; - -} // namespace - -bool RegisterUpdateAppsTask(const base::CommandLine& run_command) { - auto task_scheduler = TaskScheduler::CreateInstance(); - if (!task_scheduler->RegisterTask( - kTaskName, kTaskDescription, run_command, - TaskScheduler::TriggerType::TRIGGER_TYPE_HOURLY, true)) { - LOG(ERROR) << "RegisterUpdateAppsTask failed."; - return false; - } - VLOG(1) << "RegisterUpdateAppsTask succeeded."; - return true; -} - -void UnregisterUpdateAppsTask() { - auto task_scheduler = TaskScheduler::CreateInstance(); - task_scheduler->DeleteTask(kTaskName); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/setup/setup_util.h b/src/cobalt/updater/win/setup/setup_util.h deleted file mode 100644 index 4a57f32..0000000 --- a/src/cobalt/updater/win/setup/setup_util.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_SETUP_SETUP_UTIL_H_ -#define CHROME_UPDATER_WIN_SETUP_SETUP_UTIL_H_ - -namespace base { -class CommandLine; -} // namespace base - -#include "base/win/windows_types.h" - -namespace updater { - -bool RegisterUpdateAppsTask(const base::CommandLine& run_command); -void UnregisterUpdateAppsTask(); - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_SETUP_SETUP_UTIL_H_
diff --git a/src/cobalt/updater/win/setup/uninstall.cc b/src/cobalt/updater/win/setup/uninstall.cc deleted file mode 100644 index 8767e26..0000000 --- a/src/cobalt/updater/win/setup/uninstall.cc +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/setup/uninstall.h" - -#include <windows.h> -#include <memory> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/process/launch.h" -#include "base/process/process.h" -#include "base/stl_util.h" -#include "base/strings/string16.h" -#include "base/strings/stringprintf.h" -#include "base/win/scoped_com_initializer.h" -#include "chrome/updater/updater_constants.h" -#include "chrome/updater/util.h" -#include "chrome/updater/win/setup/setup_util.h" -#include "chrome/updater/win/task_scheduler.h" - -namespace updater { - -// Reverses the changes made by setup. This is a best effort uninstall: -// 1. deletes the scheduled task. -// 2. runs the uninstall script in the install directory of the updater. -// The execution of this function and the script race each other but the script -// loops and waits in between iterations trying to delete the install directory. -int Uninstall() { - VLOG(1) << __func__; - - auto scoped_com_initializer = - std::make_unique<base::win::ScopedCOMInitializer>( - base::win::ScopedCOMInitializer::kMTA); - - if (!TaskScheduler::Initialize()) { - LOG(ERROR) << "Failed to initialize the scheduler."; - return -1; - } - base::ScopedClosureRunner task_scheduler_terminate_caller( - base::BindOnce([]() { TaskScheduler::Terminate(); })); - - updater::UnregisterUpdateAppsTask(); - - base::FilePath product_dir; - if (!GetProductDirectory(&product_dir)) { - LOG(ERROR) << "GetProductDirectory failed."; - return -1; - } - - base::char16 cmd_path[MAX_PATH] = {0}; - auto size = ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\cmd.exe", - cmd_path, base::size(cmd_path)); - if (!size || size >= MAX_PATH) - return -1; - - base::FilePath script_path = product_dir.AppendASCII(kUninstallScript); - - base::string16 cmdline = cmd_path; - base::StringAppendF(&cmdline, L" /Q /C \"%ls\"", - script_path.AsUTF16Unsafe().c_str()); - base::LaunchOptions options; - options.start_hidden = true; - - VLOG(1) << "Running " << cmdline; - - auto process = base::LaunchProcess(cmdline, options); - if (!process.IsValid()) { - LOG(ERROR) << "Failed to create process " << cmdline; - return -1; - } - - return 0; -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/setup/uninstall.cmd b/src/cobalt/updater/win/setup/uninstall.cmd deleted file mode 100644 index bbaf5ce..0000000 --- a/src/cobalt/updater/win/setup/uninstall.cmd +++ /dev/null
@@ -1,13 +0,0 @@ -rem Deletes the script's parent directory if \AppData\Local\ChromeUpdater\ is -rem anywhere in the directory path. Sleeps 3 seconds and tries 3 times to -rem delete the directory. -@echo off -set Directory=%~dp0 -@echo %Directory% | FindStr /R \\AppData\\Local\\Google\\GoogleUpdater\\ > nul -IF %ERRORLEVEL% NEQ 0 exit 1 -@echo Deleting "%Directory%"... -for /L %%G IN (1,1,3) do ( - rmdir "%Directory%" /s /q > nul - if not exist "%Directory%" exit 0 - ping -n 3 127.0.0.1 > nul -)
diff --git a/src/cobalt/updater/win/setup/uninstall.h b/src/cobalt/updater/win/setup/uninstall.h deleted file mode 100644 index 1080629..0000000 --- a/src/cobalt/updater/win/setup/uninstall.h +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_SETUP_UNINSTALL_H_ -#define CHROME_UPDATER_WIN_SETUP_UNINSTALL_H_ - -namespace updater { - -int Uninstall(); - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_SETUP_UNINSTALL_H_
diff --git a/src/cobalt/updater/win/task_scheduler.cc b/src/cobalt/updater/win/task_scheduler.cc deleted file mode 100644 index bdbc206..0000000 --- a/src/cobalt/updater/win/task_scheduler.cc +++ /dev/null
@@ -1,961 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/task_scheduler.h" - -#include <mstask.h> -#include <oleauto.h> -#include <security.h> -#include <taskschd.h> -#include <wrl/client.h> - -#include <utility> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/native_library.h" -#include "base/path_service.h" -#include "base/strings/strcat.h" -#include "base/strings/string16.h" -#include "base/strings/stringprintf.h" -#include "base/time/time.h" -#include "base/win/scoped_bstr.h" -#include "base/win/scoped_co_mem.h" -#include "base/win/scoped_handle.h" -#include "base/win/scoped_variant.h" -#include "base/win/windows_version.h" -#include "chrome/updater/win/util.h" - -namespace updater { - -namespace { - -// Names of the TaskSchedulerV2 libraries so we can pin them below. -const wchar_t kV2Library[] = L"taskschd.dll"; - -// Text for times used in the V2 API of the Task Scheduler. -const wchar_t kOneHourText[] = L"PT1H"; -const wchar_t kFiveHoursText[] = L"PT5H"; -const wchar_t kZeroMinuteText[] = L"PT0M"; -const wchar_t kFifteenMinutesText[] = L"PT15M"; -const wchar_t kTwentyFourHoursText[] = L"PT24H"; - -// Most of the users with pending logs succeeds within 7 days, so no need to -// try for longer than that, especially for those who keep crashing. -const int kNumDaysBeforeExpiry = 7; -const size_t kNumDeleteTaskRetry = 3; -const size_t kDeleteRetryDelayInMs = 100; - -// Return |timestamp| in the following string format YYYY-MM-DDTHH:MM:SS. -base::string16 GetTimestampString(const base::Time& timestamp) { - base::Time::Exploded exploded_time; - // The Z timezone info at the end of the string means UTC. - timestamp.UTCExplode(&exploded_time); - return base::StringPrintf(L"%04d-%02d-%02dT%02d:%02d:%02dZ", - exploded_time.year, exploded_time.month, - exploded_time.day_of_month, exploded_time.hour, - exploded_time.minute, exploded_time.second); -} - -bool LocalSystemTimeToUTCFileTime(const SYSTEMTIME& system_time_local, - FILETIME* file_time_utc) { - DCHECK(file_time_utc); - SYSTEMTIME system_time_utc = {}; - if (!::TzSpecificLocalTimeToSystemTime(nullptr, &system_time_local, - &system_time_utc) || - !::SystemTimeToFileTime(&system_time_utc, file_time_utc)) { - PLOG(ERROR) << "Failed to convert local system time to UTC file time."; - return false; - } - return true; -} - -bool UTCFileTimeToLocalSystemTime(const FILETIME& file_time_utc, - SYSTEMTIME* system_time_local) { - DCHECK(system_time_local); - SYSTEMTIME system_time_utc = {}; - if (!::FileTimeToSystemTime(&file_time_utc, &system_time_utc) || - !::SystemTimeToTzSpecificLocalTime(nullptr, &system_time_utc, - system_time_local)) { - PLOG(ERROR) << "Failed to convert file time to UTC local system."; - return false; - } - return true; -} - -bool GetCurrentUser(base::win::ScopedBstr* user_name) { - DCHECK(user_name); - ULONG user_name_size = 256; - // Paranoia... ;-) - DCHECK_EQ(sizeof(OLECHAR), sizeof(WCHAR)); - if (!::GetUserNameExW( - NameSamCompatible, - user_name->AllocateBytes(user_name_size * sizeof(OLECHAR)), - &user_name_size)) { - if (::GetLastError() != ERROR_MORE_DATA) { - PLOG(ERROR) << "GetUserNameEx failed."; - return false; - } - if (!::GetUserNameExW( - NameSamCompatible, - user_name->AllocateBytes(user_name_size * sizeof(OLECHAR)), - &user_name_size)) { - DCHECK_NE(static_cast<DWORD>(ERROR_MORE_DATA), ::GetLastError()); - PLOG(ERROR) << "GetUserNameEx failed."; - return false; - } - } - return true; -} - -void PinModule(const wchar_t* module_name) { - // Force the DLL to stay loaded until program termination. We have seen - // cases where it gets unloaded even though we still have references to - // the objects we just CoCreated. - base::NativeLibrary module_handle = nullptr; - if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, module_name, - &module_handle)) { - PLOG(ERROR) << "Failed to pin '" << module_name << "'."; - } -} - -// A task scheduler class uses the V2 API of the task scheduler. -class TaskSchedulerV2 final : public TaskScheduler { - public: - static bool Initialize() { - DCHECK(!task_service_); - DCHECK(!root_task_folder_); - - HRESULT hr = - ::CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&task_service_)); - if (FAILED(hr)) { - PLOG(ERROR) << "CreateInstance failed for CLSID_TaskScheduler. " - << std::hex << hr; - return false; - } - hr = task_service_->Connect(base::win::ScopedVariant::kEmptyVariant, - base::win::ScopedVariant::kEmptyVariant, - base::win::ScopedVariant::kEmptyVariant, - base::win::ScopedVariant::kEmptyVariant); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to connect to task service. " << std::hex << hr; - return false; - } - hr = task_service_->GetFolder(base::win::ScopedBstr(L"\\"), - &root_task_folder_); - if (FAILED(hr)) { - LOG(ERROR) << "Can't get task service folder. " << std::hex << hr; - return false; - } - PinModule(kV2Library); - return true; - } - - static void Terminate() { - root_task_folder_.Reset(); - task_service_.Reset(); - } - - TaskSchedulerV2() { - DCHECK(task_service_); - DCHECK(root_task_folder_); - } - - // TaskScheduler overrides. - bool IsTaskRegistered(const wchar_t* task_name) override { - DCHECK(task_name); - if (!root_task_folder_) - return false; - - return GetTask(task_name, nullptr); - } - - bool GetNextTaskRunTime(const wchar_t* task_name, - base::Time* next_run_time) override { - DCHECK(task_name); - DCHECK(next_run_time); - if (!root_task_folder_) - return false; - - Microsoft::WRL::ComPtr<IRegisteredTask> registered_task; - if (!GetTask(task_name, ®istered_task)) - return false; - - // We unfortunately can't use get_NextRunTime because of a known bug which - // requires hotfix: http://support.microsoft.com/kb/2495489/en-us. So fetch - // one of the run times in the next day. - // Also, although it's not obvious from MSDN, IRegisteredTask::GetRunTimes - // expects local time. - SYSTEMTIME start_system_time = {}; - GetLocalTime(&start_system_time); - - base::Time tomorrow(base::Time::NowFromSystemTime() + - base::TimeDelta::FromDays(1)); - SYSTEMTIME end_system_time = {}; - if (!UTCFileTimeToLocalSystemTime(tomorrow.ToFileTime(), &end_system_time)) - return false; - - DWORD num_run_times = 1; - SYSTEMTIME* raw_run_times = nullptr; - HRESULT hr = registered_task->GetRunTimes( - &start_system_time, &end_system_time, &num_run_times, &raw_run_times); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to GetRunTimes, " << std::hex << hr; - return false; - } - - if (num_run_times == 0) - return false; - - base::win::ScopedCoMem<SYSTEMTIME> run_times; - run_times.Reset(raw_run_times); - // Again, although unclear from MSDN, IRegisteredTask::GetRunTimes returns - // local times. - FILETIME file_time = {}; - if (!LocalSystemTimeToUTCFileTime(run_times[0], &file_time)) - return false; - *next_run_time = base::Time::FromFileTime(file_time); - return true; - } - - bool SetTaskEnabled(const wchar_t* task_name, bool enabled) override { - DCHECK(task_name); - if (!root_task_folder_) - return false; - - Microsoft::WRL::ComPtr<IRegisteredTask> registered_task; - if (!GetTask(task_name, ®istered_task)) { - LOG(ERROR) << "Failed to find the task " << task_name - << " to enable/disable"; - return false; - } - - HRESULT hr; - hr = registered_task->put_Enabled(enabled ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to set enabled status of task named " << task_name - << ". " << std::hex << hr; - return false; - } - return true; - } - - bool IsTaskEnabled(const wchar_t* task_name) override { - DCHECK(task_name); - if (!root_task_folder_) - return false; - - Microsoft::WRL::ComPtr<IRegisteredTask> registered_task; - if (!GetTask(task_name, ®istered_task)) - return false; - - HRESULT hr; - VARIANT_BOOL is_enabled; - hr = registered_task->get_Enabled(&is_enabled); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get enabled status for task named " << task_name - << ". " << std::hex << hr << ": " - << logging::SystemErrorCodeToString(hr); - return false; - } - - return is_enabled == VARIANT_TRUE; - } - - bool GetTaskNameList(std::vector<base::string16>* task_names) override { - DCHECK(task_names); - if (!root_task_folder_) - return false; - - for (TaskIterator it(root_task_folder_.Get()); !it.done(); it.Next()) - task_names->push_back(it.name()); - return true; - } - - bool GetTaskInfo(const wchar_t* task_name, TaskInfo* info) override { - DCHECK(task_name); - DCHECK(info); - if (!root_task_folder_) - return false; - - Microsoft::WRL::ComPtr<IRegisteredTask> registered_task; - if (!GetTask(task_name, ®istered_task)) - return false; - - // Collect information into internal storage to ensure that we start with - // a clean slate and don't return partial results on error. - TaskInfo info_storage; - HRESULT hr = - GetTaskDescription(registered_task.Get(), &info_storage.description); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get description for task '" << task_name << "'. " - << std::hex << hr << ": " - << logging::SystemErrorCodeToString(hr); - return false; - } - - if (!GetTaskExecActions(registered_task.Get(), - &info_storage.exec_actions)) { - LOG(ERROR) << "Failed to get actions for task '" << task_name << "'"; - return false; - } - - hr = GetTaskLogonType(registered_task.Get(), &info_storage.logon_type); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get logon type for task '" << task_name << "'. " - << std::hex << hr << ": " - << logging::SystemErrorCodeToString(hr); - return false; - } - info_storage.name = task_name; - std::swap(*info, info_storage); - return true; - } - - bool DeleteTask(const wchar_t* task_name) override { - DCHECK(task_name); - if (!root_task_folder_) - return false; - - VLOG(1) << "Delete Task '" << task_name << "'."; - - HRESULT hr = - root_task_folder_->DeleteTask(base::win::ScopedBstr(task_name), 0); - // This can happen, e.g., while running tests, when the file system stresses - // quite a lot. Give it a few more chances to succeed. - size_t num_retries_left = kNumDeleteTaskRetry; - - if (FAILED(hr)) { - while ((hr == HRESULT_FROM_WIN32(ERROR_TRANSACTION_NOT_ACTIVE) || - hr == HRESULT_FROM_WIN32(ERROR_TRANSACTION_ALREADY_ABORTED)) && - --num_retries_left && IsTaskRegistered(task_name)) { - LOG(WARNING) << "Retrying delete task because transaction not active, " - << std::hex << hr << "."; - hr = root_task_folder_->DeleteTask(base::win::ScopedBstr(task_name), 0); - ::Sleep(kDeleteRetryDelayInMs); - } - if (!IsTaskRegistered(task_name)) - hr = S_OK; - } - - if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { - PLOG(ERROR) << "Can't delete task. " << std::hex << hr; - return false; - } - - DCHECK(!IsTaskRegistered(task_name)); - return true; - } - - bool RegisterTask(const wchar_t* task_name, - const wchar_t* task_description, - const base::CommandLine& run_command, - TriggerType trigger_type, - bool hidden) override { - DCHECK(task_name); - DCHECK(task_description); - if (!DeleteTask(task_name)) - return false; - - // Create the task definition object to create the task. - Microsoft::WRL::ComPtr<ITaskDefinition> task; - DCHECK(task_service_); - HRESULT hr = task_service_->NewTask(0, &task); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't create new task. " << std::hex << hr; - return false; - } - - base::win::ScopedBstr user_name; - if (!GetCurrentUser(&user_name)) - return false; - - if (trigger_type != TRIGGER_TYPE_NOW) { - // Allow the task to run elevated on startup. - Microsoft::WRL::ComPtr<IPrincipal> principal; - hr = task->get_Principal(&principal); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't get principal. " << std::hex << hr; - return false; - } - - hr = principal->put_UserId(user_name); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put user id. " << std::hex << hr; - return false; - } - - hr = principal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put logon type. " << std::hex << hr; - return false; - } - } - - Microsoft::WRL::ComPtr<IRegistrationInfo> registration_info; - hr = task->get_RegistrationInfo(®istration_info); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't get registration info. " << std::hex << hr; - return false; - } - - hr = registration_info->put_Author(user_name); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't set registration info author. " << std::hex << hr; - return false; - } - - base::win::ScopedBstr description(task_description); - hr = registration_info->put_Description(description); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't set description. " << std::hex << hr; - return false; - } - - Microsoft::WRL::ComPtr<ITaskSettings> task_settings; - hr = task->get_Settings(&task_settings); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't get task settings. " << std::hex << hr; - return false; - } - - hr = task_settings->put_StartWhenAvailable(VARIANT_TRUE); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'StartWhenAvailable' to true. " << std::hex - << hr; - return false; - } - - // TODO(csharp): Find a way to only set this for log upload retry. - hr = task_settings->put_DeleteExpiredTaskAfter( - base::win::ScopedBstr(kZeroMinuteText)); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'DeleteExpiredTaskAfter'. " << std::hex << hr; - return false; - } - - hr = task_settings->put_DisallowStartIfOnBatteries(VARIANT_FALSE); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'DisallowStartIfOnBatteries' to false. " - << std::hex << hr; - return false; - } - - hr = task_settings->put_StopIfGoingOnBatteries(VARIANT_FALSE); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'StopIfGoingOnBatteries' to false. " << std::hex - << hr; - return false; - } - - if (hidden) { - hr = task_settings->put_Hidden(VARIANT_TRUE); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'Hidden' to true. " << std::hex << hr; - return false; - } - } - - Microsoft::WRL::ComPtr<ITriggerCollection> trigger_collection; - hr = task->get_Triggers(&trigger_collection); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't get trigger collection. " << std::hex << hr; - return false; - } - - TASK_TRIGGER_TYPE2 task_trigger_type = TASK_TRIGGER_EVENT; - base::win::ScopedBstr repetition_interval; - switch (trigger_type) { - case TRIGGER_TYPE_POST_REBOOT: - task_trigger_type = TASK_TRIGGER_LOGON; - break; - case TRIGGER_TYPE_NOW: - task_trigger_type = TASK_TRIGGER_REGISTRATION; - break; - case TRIGGER_TYPE_HOURLY: - case TRIGGER_TYPE_EVERY_FIVE_HOURS: - task_trigger_type = TASK_TRIGGER_DAILY; - if (trigger_type == TRIGGER_TYPE_EVERY_FIVE_HOURS) { - repetition_interval.Reset(::SysAllocString(kFiveHoursText)); - } else if (trigger_type == TRIGGER_TYPE_HOURLY) { - repetition_interval.Reset(::SysAllocString(kOneHourText)); - } else { - NOTREACHED() << "Unknown TriggerType?"; - } - break; - default: - NOTREACHED() << "Unknown TriggerType?"; - } - - Microsoft::WRL::ComPtr<ITrigger> trigger; - hr = trigger_collection->Create(task_trigger_type, &trigger); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't create trigger of type " << task_trigger_type - << ". " << std::hex << hr; - return false; - } - - if (trigger_type == TRIGGER_TYPE_HOURLY || - trigger_type == TRIGGER_TYPE_EVERY_FIVE_HOURS) { - Microsoft::WRL::ComPtr<IDailyTrigger> daily_trigger; - hr = trigger.As(&daily_trigger); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't Query for registration trigger. " << std::hex - << hr; - return false; - } - - hr = daily_trigger->put_DaysInterval(1); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'DaysInterval' to 1, " << std::hex << hr; - return false; - } - - Microsoft::WRL::ComPtr<IRepetitionPattern> repetition_pattern; - hr = trigger->get_Repetition(&repetition_pattern); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't get 'Repetition'. " << std::hex << hr; - return false; - } - - // The duration is the time to keep repeating until the next daily - // trigger. - hr = repetition_pattern->put_Duration( - base::win::ScopedBstr(kTwentyFourHoursText)); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'Duration' to " << kTwentyFourHoursText - << ". " << std::hex << hr; - return false; - } - - hr = repetition_pattern->put_Interval(repetition_interval); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'Interval' to " << repetition_interval << ". " - << std::hex << hr; - return false; - } - - // Start now. - base::Time now(base::Time::NowFromSystemTime()); - base::win::ScopedBstr start_boundary(GetTimestampString(now)); - hr = trigger->put_StartBoundary(start_boundary); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'StartBoundary' to " << start_boundary << ". " - << std::hex << hr; - return false; - } - } - - if (trigger_type == TRIGGER_TYPE_POST_REBOOT) { - Microsoft::WRL::ComPtr<ILogonTrigger> logon_trigger; - hr = trigger.As(&logon_trigger); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't query trigger for 'ILogonTrigger'. " << std::hex - << hr; - return false; - } - - hr = logon_trigger->put_Delay(base::win::ScopedBstr(kFifteenMinutesText)); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'Delay'. " << std::hex << hr; - return false; - } - } - - // None of the triggers should go beyond kNumDaysBeforeExpiry. - base::Time expiry_date(base::Time::NowFromSystemTime() + - base::TimeDelta::FromDays(kNumDaysBeforeExpiry)); - base::win::ScopedBstr end_boundary(GetTimestampString(expiry_date)); - hr = trigger->put_EndBoundary(end_boundary); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't put 'EndBoundary' to " << end_boundary << ". " - << std::hex << hr; - return false; - } - - Microsoft::WRL::ComPtr<IActionCollection> actions; - hr = task->get_Actions(&actions); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't get actions collection. " << std::hex << hr; - return false; - } - - Microsoft::WRL::ComPtr<IAction> action; - hr = actions->Create(TASK_ACTION_EXEC, &action); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't create exec action. " << std::hex << hr; - return false; - } - - Microsoft::WRL::ComPtr<IExecAction> exec_action; - hr = action.As(&exec_action); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't query for exec action. " << std::hex << hr; - return false; - } - - base::win::ScopedBstr path(run_command.GetProgram().value()); - hr = exec_action->put_Path(path); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't set path of exec action. " << std::hex << hr; - return false; - } - - base::win::ScopedBstr args(run_command.GetArgumentsString()); - hr = exec_action->put_Arguments(args); - if (FAILED(hr)) { - PLOG(ERROR) << "Can't set arguments of exec action. " << std::hex << hr; - return false; - } - - Microsoft::WRL::ComPtr<IRegisteredTask> registered_task; - base::win::ScopedVariant user(user_name); - - DCHECK(root_task_folder_); - hr = root_task_folder_->RegisterTaskDefinition( - base::win::ScopedBstr(task_name), task.Get(), TASK_CREATE, - *user.AsInput(), // Not really input, but API expect non-const. - base::win::ScopedVariant::kEmptyVariant, TASK_LOGON_NONE, - base::win::ScopedVariant::kEmptyVariant, ®istered_task); - if (FAILED(hr)) { - LOG(ERROR) << "RegisterTaskDefinition failed. " << std::hex << hr << ": " - << logging::SystemErrorCodeToString(hr); - return false; - } - - DCHECK(IsTaskRegistered(task_name)); - - VLOG(1) << "Successfully registered: " - << run_command.GetCommandLineString(); - return true; - } - - private: - // Helper class that lets us iterate over all registered tasks. - class TaskIterator { - public: - explicit TaskIterator(ITaskFolder* task_folder) { - DCHECK(task_folder); - HRESULT hr = task_folder->GetTasks(TASK_ENUM_HIDDEN, &tasks_); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get registered tasks from folder. " - << std::hex << hr; - done_ = true; - return; - } - hr = tasks_->get_Count(&num_tasks_); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get registered tasks count. " << std::hex - << hr; - done_ = true; - return; - } - Next(); - } - - // Increment to the next valid item in the task list. Skip entries for - // which we cannot retrieve a name. - void Next() { - DCHECK(!done_); - task_.Reset(); - name_.clear(); - if (++task_index_ >= num_tasks_) { - done_ = true; - return; - } - - // Note: get_Item uses 1 based indices. - HRESULT hr = - tasks_->get_Item(base::win::ScopedVariant(task_index_ + 1), &task_); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get task at index: " << task_index_ << ". " - << std::hex << hr; - Next(); - return; - } - - base::win::ScopedBstr task_name_bstr; - hr = task_->get_Name(task_name_bstr.Receive()); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get name at index: " << task_index_ << ". " - << std::hex << hr; - Next(); - return; - } - name_ = base::string16(task_name_bstr ? task_name_bstr : L""); - } - - // Detach the currently active task and pass ownership to the caller. - // After this method has been called, the -> operator must no longer be - // used. - IRegisteredTask* Detach() { return task_.Detach(); } - - // Provide access to the current task. - IRegisteredTask* operator->() const { - IRegisteredTask* result = task_.Get(); - DCHECK(result); - return result; - } - - const base::string16& name() const { return name_; } - bool done() const { return done_; } - - private: - Microsoft::WRL::ComPtr<IRegisteredTaskCollection> tasks_; - Microsoft::WRL::ComPtr<IRegisteredTask> task_; - base::string16 name_; - long task_index_ = -1; // NOLINT, API requires a long. - long num_tasks_ = 0; // NOLINT, API requires a long. - bool done_ = false; - }; - - // Return the task with |task_name| and false if not found. |task| can be null - // when only interested in task's existence. - bool GetTask(const wchar_t* task_name, IRegisteredTask** task) { - for (TaskIterator it(root_task_folder_.Get()); !it.done(); it.Next()) { - if (::_wcsicmp(it.name().c_str(), task_name) == 0) { - if (task) - *task = it.Detach(); - return true; - } - } - return false; - } - - // Return the description of the task. - HRESULT GetTaskDescription(IRegisteredTask* task, - base::string16* description) { - DCHECK(task); - DCHECK(description); - - base::win::ScopedBstr task_name_bstr; - HRESULT hr = task->get_Name(task_name_bstr.Receive()); - base::string16 task_name = - base::string16(task_name_bstr ? task_name_bstr : L""); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get task name"; - } - - Microsoft::WRL::ComPtr<ITaskDefinition> task_info; - hr = task->get_Definition(&task_info); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get definition for task, " << task_name << ": " - << logging::SystemErrorCodeToString(hr); - return hr; - } - - Microsoft::WRL::ComPtr<IRegistrationInfo> reg_info; - hr = task_info->get_RegistrationInfo(®_info); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get registration info, " << task_name << ": " - << logging::SystemErrorCodeToString(hr); - return hr; - } - - base::win::ScopedBstr raw_description; - hr = reg_info->get_Description(raw_description.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get description, " << task_name << ": " - << logging::SystemErrorCodeToString(hr); - return hr; - } - *description = base::string16(raw_description ? raw_description : L""); - return ERROR_SUCCESS; - } - - // Return all executable actions associated with the given task. Non-exec - // actions are silently ignored. - bool GetTaskExecActions(IRegisteredTask* task, - std::vector<TaskExecAction>* actions) { - DCHECK(task); - DCHECK(actions); - Microsoft::WRL::ComPtr<ITaskDefinition> task_definition; - HRESULT hr = task->get_Definition(&task_definition); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get definition of task, " << std::hex << hr; - return false; - } - - Microsoft::WRL::ComPtr<IActionCollection> action_collection; - hr = task_definition->get_Actions(&action_collection); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get action collection, " << std::hex << hr; - return false; - } - - long actions_count = 0; // NOLINT, API requires a long. - hr = action_collection->get_Count(&actions_count); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get number of actions, " << std::hex << hr; - return false; - } - - // Find and return as many exec actions as possible in |actions| and return - // false if there were any errors on the way. Note that the indexing of - // actions is 1-based. - bool success = true; - for (long action_index = 1; // NOLINT - action_index <= actions_count; ++action_index) { - Microsoft::WRL::ComPtr<IAction> action; - hr = action_collection->get_Item(action_index, &action); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get action at index " << action_index << ", " - << std::hex << hr; - success = false; - continue; - } - - ::TASK_ACTION_TYPE action_type; - hr = action->get_Type(&action_type); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get the type of action at index " - << action_index << ", " << std::hex << hr; - success = false; - continue; - } - - // We only care about exec actions for now. The other types are - // TASK_ACTION_COM_HANDLER, TASK_ACTION_SEND_EMAIL, - // TASK_ACTION_SHOW_MESSAGE. The latter two are marked as deprecated in - // the Task Scheduler's GUI. - if (action_type != ::TASK_ACTION_EXEC) - continue; - - Microsoft::WRL::ComPtr<IExecAction> exec_action; - hr = action.As(&exec_action); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to query from action, " << std::hex << hr; - success = false; - continue; - } - - base::win::ScopedBstr application_path; - hr = exec_action->get_Path(application_path.Receive()); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get path from action, " << std::hex << hr; - success = false; - continue; - } - - base::win::ScopedBstr working_dir; - hr = exec_action->get_WorkingDirectory(working_dir.Receive()); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get working directory for action, " - << std::hex << hr; - success = false; - continue; - } - - base::win::ScopedBstr parameters; - hr = exec_action->get_Arguments(parameters.Receive()); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to get arguments from action of task, " - << std::hex << hr; - success = false; - continue; - } - - actions->push_back( - {base::FilePath(application_path ? application_path : L""), - base::FilePath(working_dir ? working_dir : L""), - base::string16(parameters ? parameters : L"")}); - } - return success; - } - - // Return the log-on type required for the task's actions to be run. - HRESULT GetTaskLogonType(IRegisteredTask* task, uint32_t* logon_type) { - DCHECK(task); - DCHECK(logon_type); - Microsoft::WRL::ComPtr<ITaskDefinition> task_info; - HRESULT hr = task->get_Definition(&task_info); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get definition, " << std::hex << hr << ": " - << logging::SystemErrorCodeToString(hr); - return hr; - } - - Microsoft::WRL::ComPtr<IPrincipal> principal; - hr = task_info->get_Principal(&principal); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get principal info, " << std::hex << hr << ": " - << logging::SystemErrorCodeToString(hr); - return hr; - } - - TASK_LOGON_TYPE raw_logon_type; - hr = principal->get_LogonType(&raw_logon_type); - if (FAILED(hr)) { - LOG(ERROR) << "Failed to get logon type info, " << std::hex << hr << ": " - << logging::SystemErrorCodeToString(hr); - return hr; - } - - switch (raw_logon_type) { - case TASK_LOGON_INTERACTIVE_TOKEN: - *logon_type = LOGON_INTERACTIVE; - break; - case TASK_LOGON_GROUP: // fall-thru - case TASK_LOGON_PASSWORD: // fall-thru - case TASK_LOGON_SERVICE_ACCOUNT: - *logon_type = LOGON_SERVICE; - break; - case TASK_LOGON_S4U: - *logon_type = LOGON_SERVICE | LOGON_S4U; - break; - case TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD: - *logon_type = LOGON_INTERACTIVE | LOGON_SERVICE; - break; - default: - *logon_type = LOGON_UNKNOWN; - break; - } - return ERROR_SUCCESS; - } - - static Microsoft::WRL::ComPtr<ITaskService> task_service_; - static Microsoft::WRL::ComPtr<ITaskFolder> root_task_folder_; - - DISALLOW_COPY_AND_ASSIGN(TaskSchedulerV2); -}; - -Microsoft::WRL::ComPtr<ITaskService> TaskSchedulerV2::task_service_; -Microsoft::WRL::ComPtr<ITaskFolder> TaskSchedulerV2::root_task_folder_; - -} // namespace - -TaskScheduler::TaskInfo::TaskInfo() = default; - -TaskScheduler::TaskInfo::TaskInfo(const TaskScheduler::TaskInfo&) = default; - -TaskScheduler::TaskInfo::TaskInfo(TaskScheduler::TaskInfo&&) = default; - -TaskScheduler::TaskInfo& TaskScheduler::TaskInfo::operator=( - const TaskScheduler::TaskInfo&) = default; - -TaskScheduler::TaskInfo& TaskScheduler::TaskInfo::operator=( - TaskScheduler::TaskInfo&&) = default; - -TaskScheduler::TaskInfo::~TaskInfo() = default; - -// static. -bool TaskScheduler::Initialize() { - return TaskSchedulerV2::Initialize(); -} - -// static. -void TaskScheduler::Terminate() { - TaskSchedulerV2::Terminate(); -} - -// static. -std::unique_ptr<TaskScheduler> TaskScheduler::CreateInstance() { - return std::make_unique<TaskSchedulerV2>(); -} - -TaskScheduler::TaskScheduler() = default; - -} // namespace updater
diff --git a/src/cobalt/updater/win/task_scheduler.h b/src/cobalt/updater/win/task_scheduler.h deleted file mode 100644 index 2708621..0000000 --- a/src/cobalt/updater/win/task_scheduler.h +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_TASK_SCHEDULER_H_ -#define CHROME_UPDATER_WIN_TASK_SCHEDULER_H_ - -#include <stdint.h> - -#include <memory> -#include <vector> - -#include "base/files/file_path.h" -#include "base/macros.h" - -namespace base { -class CommandLine; -class Time; -} // namespace base - -namespace updater { - -// This class wraps a scheduled task and expose an API to parametrize a task -// before calling |Register|, or to verify its existence, or delete it. -class TaskScheduler { - public: - // The type of trigger to register for this task. - enum TriggerType { - TRIGGER_TYPE_POST_REBOOT = 0, // Only run once post-reboot. - TRIGGER_TYPE_NOW = 1, // Run right now (mainly for tests). - TRIGGER_TYPE_HOURLY = 2, // Run every hour. - TRIGGER_TYPE_EVERY_FIVE_HOURS = 3, - TRIGGER_TYPE_MAX, - }; - - // The log-on requirements for a task to be scheduled. Note that a task can - // have both the interactive and service bit set. In that case the - // interactive token will be used when available, and a stored password - // otherwise. - enum LogonType { - LOGON_UNKNOWN = 0, - - // Run the task with the user's interactive token when logged in. - LOGON_INTERACTIVE = 1 << 0, - - // The task will run whether the user is logged in or not using either a - // user/password specified at registration time, a service account or a - // service for user (S4U). - LOGON_SERVICE = 1 << 1, - - // The task is run as a service for user and as such will be on an - // invisible desktop. - LOGON_S4U = 1 << 2, - }; - - // Struct representing a single scheduled task action. - struct TaskExecAction { - base::FilePath application_path; - base::FilePath working_dir; - base::string16 arguments; - }; - - // Detailed description of a scheduled task. This type is returned by the - // GetTaskInfo() method. - struct TaskInfo { - TaskInfo(); - TaskInfo(const TaskInfo&); - TaskInfo(TaskInfo&&); - ~TaskInfo(); - TaskInfo& operator=(const TaskInfo&); - TaskInfo& operator=(TaskInfo&&); - - base::string16 name; - - // Description of the task. - base::string16 description; - - // A scheduled task can have more than one action associated with it and - // actions can be of types other than executables (for example, sending - // emails). This list however contains only the execution actions. - std::vector<TaskExecAction> exec_actions; - - // The log-on requirements for the task's actions to be run. A bit mask with - // the mapping defined by LogonType. - uint32_t logon_type = 0; - }; - - // Control the lifespan of static data for the TaskScheduler. |Initialize| - // must be called before the first call to |CreateInstance|, and not other - // methods can be called after |Terminate| was called (unless |Initialize| is - // called again). |Initialize| can't be called out of balance with - // |Terminate|. |Terminate| can be called any number of times. - static bool Initialize(); - static void Terminate(); - - static std::unique_ptr<TaskScheduler> CreateInstance(); - virtual ~TaskScheduler() {} - - // Identify whether the task is registered or not. - virtual bool IsTaskRegistered(const wchar_t* task_name) = 0; - - // Return the time of the next schedule run for the given task name. Return - // false on failure. - virtual bool GetNextTaskRunTime(const wchar_t* task_name, - base::Time* next_run_time) = 0; - - // Delete the task if it exists. No-op if the task doesn't exist. Return false - // on failure to delete an existing task. - virtual bool DeleteTask(const wchar_t* task_name) = 0; - - // Enable or disable task based on the value of |enabled|. Return true if the - // task exists and the operation succeeded. - virtual bool SetTaskEnabled(const wchar_t* task_name, bool enabled) = 0; - - // Return true if task exists and is enabled. - virtual bool IsTaskEnabled(const wchar_t* task_name) = 0; - - // List all currently registered scheduled tasks. - virtual bool GetTaskNameList(std::vector<base::string16>* task_names) = 0; - - // Return detailed information about a task. Return true if no errors were - // encountered. On error, the struct is left unmodified. - virtual bool GetTaskInfo(const wchar_t* task_name, TaskInfo* info) = 0; - - // Register the task to run the specified application and using the given - // |trigger_type|. - virtual bool RegisterTask(const wchar_t* task_name, - const wchar_t* task_description, - const base::CommandLine& run_command, - TriggerType trigger_type, - bool hidden) = 0; - - protected: - TaskScheduler(); - - DISALLOW_COPY_AND_ASSIGN(TaskScheduler); -}; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_TASK_SCHEDULER_H_
diff --git a/src/cobalt/updater/win/task_scheduler_unittest.cc b/src/cobalt/updater/win/task_scheduler_unittest.cc deleted file mode 100644 index 3b20a78..0000000 --- a/src/cobalt/updater/win/task_scheduler_unittest.cc +++ /dev/null
@@ -1,319 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/task_scheduler.h" - -#include <taskschd.h> - -#include <memory> -#include <vector> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/path_service.h" -#include "base/stl_util.h" -#include "base/strings/strcat.h" -#include "base/strings/string16.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/test_timeouts.h" -#include "base/time/time.h" -#include "base/win/scoped_bstr.h" -#include "base/win/scoped_variant.h" -#include "base/win/windows_version.h" -#include "chrome/updater/win/test/test_executables.h" -#include "chrome/updater/win/test/test_strings.h" -#include "chrome/updater/win/util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace updater { - -namespace { - -// The name of the tasks as will be visible in the scheduler so we know we can -// safely delete them if they get stuck for whatever reason. -const wchar_t kTaskName1[] = L"Chrome Updater Test task 1 (delete me)"; -const wchar_t kTaskName2[] = L"Chrome Updater Test task 2 (delete me)"; -// Optional descriptions for the above tasks. -const wchar_t kTaskDescription1[] = - L"Task 1 used only for Chrome Updater unit testing."; -const wchar_t kTaskDescription2[] = - L"Task 2 used only for Chrome Updater unit testing."; -// A command-line switch used in testing. -const char kTestSwitch[] = "a_switch"; - -class TaskSchedulerTests : public testing::Test { - public: - void SetUp() override { - task_scheduler_ = TaskScheduler::CreateInstance(); - // In case previous tests failed and left these tasks in the scheduler. - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName2)); - ASSERT_FALSE(IsProcessRunning(kTestProcessExecutableName)); - } - - void TearDown() override { - // Make sure to not leave tasks behind. - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName2)); - // Make sure every processes launched with scheduled task are completed. - ASSERT_TRUE(WaitForProcessesStopped(kTestProcessExecutableName)); - } - - protected: - std::unique_ptr<TaskScheduler> task_scheduler_; -}; - -} // namespace - -TEST_F(TaskSchedulerTests, DeleteAndIsRegistered) { - EXPECT_FALSE(task_scheduler_->IsTaskRegistered(kTaskName1)); - - // Construct the full-path of the test executable. - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line( - executable_path.Append(kTestProcessExecutableName)); - - // Validate that the task is properly seen as registered when it is. - EXPECT_TRUE( - task_scheduler_->RegisterTask(kTaskName1, kTaskDescription1, command_line, - TaskScheduler::TRIGGER_TYPE_NOW, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - - // Validate that a task with a similar name is not seen as registered. - EXPECT_FALSE(task_scheduler_->IsTaskRegistered(kTaskName2)); - - // While the first one is still seen as registered, until it gets deleted. - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); - EXPECT_FALSE(task_scheduler_->IsTaskRegistered(kTaskName1)); - // The other task should still not be registered. - EXPECT_FALSE(task_scheduler_->IsTaskRegistered(kTaskName2)); -} - -TEST_F(TaskSchedulerTests, RunAProgramNow) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line( - executable_path.Append(kTestProcessExecutableName)); - - // Create a unique name for a shared event to be waited for in this process - // and signaled in the test process to confirm it was scheduled and ran. - const base::string16 event_name = - base::StrCat({kTestProcessExecutableName, L"-", - base::NumberToString16(::GetCurrentProcessId())}); - base::WaitableEvent event(base::win::ScopedHandle( - ::CreateEvent(nullptr, FALSE, FALSE, event_name.c_str()))); - ASSERT_NE(event.handle(), nullptr); - - command_line.AppendSwitchNative(kTestEventToSignal, event_name); - EXPECT_TRUE( - task_scheduler_->RegisterTask(kTaskName1, kTaskDescription1, command_line, - TaskScheduler::TRIGGER_TYPE_NOW, false)); - EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout())); - base::Time next_run_time; - EXPECT_FALSE(task_scheduler_->GetNextTaskRunTime(kTaskName1, &next_run_time)); - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); -} - -TEST_F(TaskSchedulerTests, Hourly) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line( - executable_path.Append(kTestProcessExecutableName)); - - base::Time now(base::Time::NowFromSystemTime()); - EXPECT_TRUE( - task_scheduler_->RegisterTask(kTaskName1, kTaskDescription1, command_line, - TaskScheduler::TRIGGER_TYPE_HOURLY, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - - base::TimeDelta one_hour(base::TimeDelta::FromHours(1)); - base::TimeDelta one_minute(base::TimeDelta::FromMinutes(1)); - - base::Time next_run_time; - EXPECT_TRUE(task_scheduler_->GetNextTaskRunTime(kTaskName1, &next_run_time)); - EXPECT_LT(next_run_time, now + one_hour + one_minute); - EXPECT_GT(next_run_time, now + one_hour - one_minute); - - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); - EXPECT_FALSE(task_scheduler_->IsTaskRegistered(kTaskName1)); - EXPECT_FALSE(task_scheduler_->GetNextTaskRunTime(kTaskName1, &next_run_time)); -} - -TEST_F(TaskSchedulerTests, EveryFiveHours) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line( - executable_path.Append(kTestProcessExecutableName)); - - base::Time now(base::Time::NowFromSystemTime()); - EXPECT_TRUE(task_scheduler_->RegisterTask( - kTaskName1, kTaskDescription1, command_line, - TaskScheduler::TRIGGER_TYPE_EVERY_FIVE_HOURS, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - - base::TimeDelta six_hours(base::TimeDelta::FromHours(5)); - base::TimeDelta one_minute(base::TimeDelta::FromMinutes(1)); - - base::Time next_run_time; - EXPECT_TRUE(task_scheduler_->GetNextTaskRunTime(kTaskName1, &next_run_time)); - EXPECT_LT(next_run_time, now + six_hours + one_minute); - EXPECT_GT(next_run_time, now + six_hours - one_minute); - - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); - EXPECT_FALSE(task_scheduler_->IsTaskRegistered(kTaskName1)); - EXPECT_FALSE(task_scheduler_->GetNextTaskRunTime(kTaskName1, &next_run_time)); -} - -TEST_F(TaskSchedulerTests, SetTaskEnabled) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line( - executable_path.Append(kTestProcessExecutableName)); - - EXPECT_TRUE( - task_scheduler_->RegisterTask(kTaskName1, kTaskDescription1, command_line, - TaskScheduler::TRIGGER_TYPE_HOURLY, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - EXPECT_TRUE(task_scheduler_->IsTaskEnabled(kTaskName1)); - - EXPECT_TRUE(task_scheduler_->SetTaskEnabled(kTaskName1, true)); - EXPECT_TRUE(task_scheduler_->IsTaskEnabled(kTaskName1)); - EXPECT_TRUE(task_scheduler_->SetTaskEnabled(kTaskName1, false)); - EXPECT_FALSE(task_scheduler_->IsTaskEnabled(kTaskName1)); - EXPECT_TRUE(task_scheduler_->SetTaskEnabled(kTaskName1, true)); - EXPECT_TRUE(task_scheduler_->IsTaskEnabled(kTaskName1)); - - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); -} - -TEST_F(TaskSchedulerTests, GetTaskNameList) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line( - executable_path.Append(kTestProcessExecutableName)); - - EXPECT_TRUE( - task_scheduler_->RegisterTask(kTaskName1, kTaskDescription1, command_line, - TaskScheduler::TRIGGER_TYPE_HOURLY, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - EXPECT_TRUE( - task_scheduler_->RegisterTask(kTaskName2, kTaskDescription2, command_line, - TaskScheduler::TRIGGER_TYPE_HOURLY, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName2)); - - std::vector<base::string16> task_names; - EXPECT_TRUE(task_scheduler_->GetTaskNameList(&task_names)); - EXPECT_TRUE(base::Contains(task_names, kTaskName1)); - EXPECT_TRUE(base::Contains(task_names, kTaskName2)); - - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName2)); -} - -TEST_F(TaskSchedulerTests, GetTasksIncludesHidden) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line( - executable_path.Append(kTestProcessExecutableName)); - - EXPECT_TRUE( - task_scheduler_->RegisterTask(kTaskName1, kTaskDescription1, command_line, - TaskScheduler::TRIGGER_TYPE_HOURLY, true)); - - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - - std::vector<base::string16> task_names; - EXPECT_TRUE(task_scheduler_->GetTaskNameList(&task_names)); - EXPECT_TRUE(base::Contains(task_names, kTaskName1)); - - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); -} - -TEST_F(TaskSchedulerTests, GetTaskInfoExecActions) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line1( - executable_path.Append(kTestProcessExecutableName)); - - EXPECT_TRUE(task_scheduler_->RegisterTask( - kTaskName1, kTaskDescription1, command_line1, - TaskScheduler::TRIGGER_TYPE_HOURLY, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - - TaskScheduler::TaskInfo info; - EXPECT_FALSE(task_scheduler_->GetTaskInfo(kTaskName2, &info)); - EXPECT_EQ(0UL, info.exec_actions.size()); - EXPECT_TRUE(task_scheduler_->GetTaskInfo(kTaskName1, &info)); - ASSERT_EQ(1UL, info.exec_actions.size()); - EXPECT_EQ(command_line1.GetProgram(), info.exec_actions[0].application_path); - EXPECT_EQ(command_line1.GetArgumentsString(), info.exec_actions[0].arguments); - - base::CommandLine command_line2( - executable_path.Append(kTestProcessExecutableName)); - command_line2.AppendSwitch(kTestSwitch); - EXPECT_TRUE(task_scheduler_->RegisterTask( - kTaskName2, kTaskDescription2, command_line2, - TaskScheduler::TRIGGER_TYPE_HOURLY, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName2)); - - // The |info| struct is re-used to ensure that new task information overwrites - // the previous contents of the struct. - EXPECT_TRUE(task_scheduler_->GetTaskInfo(kTaskName2, &info)); - ASSERT_EQ(1UL, info.exec_actions.size()); - EXPECT_EQ(command_line2.GetProgram(), info.exec_actions[0].application_path); - EXPECT_EQ(command_line2.GetArgumentsString(), info.exec_actions[0].arguments); - - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName2)); -} - -TEST_F(TaskSchedulerTests, GetTaskInfoNameAndDescription) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line1( - executable_path.Append(kTestProcessExecutableName)); - - EXPECT_TRUE(task_scheduler_->RegisterTask( - kTaskName1, kTaskDescription1, command_line1, - TaskScheduler::TRIGGER_TYPE_HOURLY, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - - TaskScheduler::TaskInfo info; - EXPECT_FALSE(task_scheduler_->GetTaskInfo(kTaskName2, &info)); - EXPECT_EQ(L"", info.description); - EXPECT_EQ(L"", info.name); - - EXPECT_TRUE(task_scheduler_->GetTaskInfo(kTaskName1, &info)); - EXPECT_EQ(kTaskDescription1, info.description); - EXPECT_EQ(kTaskName1, info.name); - - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); -} - -TEST_F(TaskSchedulerTests, GetTaskInfoLogonType) { - base::FilePath executable_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path)); - base::CommandLine command_line1( - executable_path.Append(kTestProcessExecutableName)); - - EXPECT_TRUE(task_scheduler_->RegisterTask( - kTaskName1, kTaskDescription1, command_line1, - TaskScheduler::TRIGGER_TYPE_HOURLY, false)); - EXPECT_TRUE(task_scheduler_->IsTaskRegistered(kTaskName1)); - - TaskScheduler::TaskInfo info; - EXPECT_FALSE(task_scheduler_->GetTaskInfo(kTaskName2, &info)); - EXPECT_EQ(0U, info.logon_type); - EXPECT_TRUE(task_scheduler_->GetTaskInfo(kTaskName1, &info)); - EXPECT_TRUE(info.logon_type & TaskScheduler::LOGON_INTERACTIVE); - EXPECT_FALSE(info.logon_type & TaskScheduler::LOGON_SERVICE); - EXPECT_FALSE(info.logon_type & TaskScheduler::LOGON_S4U); - - EXPECT_TRUE(task_scheduler_->DeleteTask(kTaskName1)); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/test/BUILD.gn b/src/cobalt/updater/win/test/BUILD.gn deleted file mode 100644 index e290745..0000000 --- a/src/cobalt/updater/win/test/BUILD.gn +++ /dev/null
@@ -1,66 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//testing/test.gni") - -source_set("test_strings") { - testonly = true - - sources = [ - "test_strings.cc", - "test_strings.h", - ] -} - -source_set("test_common") { - testonly = true - - sources = [ - "test_inheritable_event.cc", - "test_inheritable_event.h", - "test_initializer.cc", - "test_initializer.h", - ] - - deps = [ - "//base", - "//chrome/updater:common", - ] -} - -source_set("test_executables") { - testonly = true - - sources = [ - "test_executables.cc", - "test_executables.h", - ] - - data_deps = [ - ":updater_test_process", - ] - - deps = [ - ":test_common", - ":test_strings", - "//base", - ] -} - -executable("updater_test_process") { - testonly = true - - sources = [ - "test_process_main.cc", - ] - - deps = [ - ":test_common", - ":test_strings", - "//base", - "//base/test:test_support", - "//build/win:default_exe_manifest", - "//chrome/updater/win:code", - ] -}
diff --git a/src/cobalt/updater/win/test/test_executables.cc b/src/cobalt/updater/win/test/test_executables.cc deleted file mode 100644 index 8f4e38e..0000000 --- a/src/cobalt/updater/win/test/test_executables.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/test/test_executables.h" - -#include <memory> - -#include "base/base_paths.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/process/launch.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/waitable_event.h" -#include "base/win/win_util.h" -#include "chrome/updater/updater_constants.h" -#include "chrome/updater/win/test/test_inheritable_event.h" -#include "chrome/updater/win/test/test_strings.h" - -namespace updater { - -// If you add another test executable here, also add it to the data_deps in -// the "test_executables" target of updater/win/test/BUILD.gn. -const base::char16 kTestProcessExecutableName[] = L"updater_test_process.exe"; - -base::Process LongRunningProcess(base::CommandLine* cmd) { - base::FilePath exe_dir; - if (!base::PathService::Get(base::DIR_EXE, &exe_dir)) { - LOG(ERROR) << "Failed to get the executable path, unable to create always " - "running process"; - return base::Process(); - } - - base::FilePath exe_path = exe_dir.Append(updater::kTestProcessExecutableName); - base::CommandLine command_line(exe_path); - - // This will ensure this new process will run for one minute before dying. - command_line.AppendSwitchASCII(updater::kTestSleepMinutesSwitch, "1"); - - auto init_done_event = updater::CreateInheritableEvent( - base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED); - command_line.AppendSwitchNative( - updater::kInitDoneNotifierSwitch, - base::NumberToString16( - base::win::HandleToUint32(init_done_event->handle()))); - - if (cmd) - *cmd = command_line; - - base::LaunchOptions launch_options; - launch_options.handles_to_inherit.push_back(init_done_event->handle()); - base::Process result = base::LaunchProcess(command_line, launch_options); - - if (!init_done_event->TimedWait(base::TimeDelta::FromSeconds(10))) { - LOG(ERROR) << "Process did not signal"; - result.Terminate(/*exit_code=*/1, /*wait=*/false); - return base::Process(); - } - - return result; -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/test/test_executables.h b/src/cobalt/updater/win/test/test_executables.h deleted file mode 100644 index 1ebe8b3..0000000 --- a/src/cobalt/updater/win/test/test_executables.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_TEST_TEST_EXECUTABLES_H_ -#define CHROME_UPDATER_WIN_TEST_TEST_EXECUTABLES_H_ - -#include "base/process/process.h" -#include "base/strings/string16.h" - -namespace base { -class CommandLine; -} // namespace base - -namespace updater { - -// The name of the service executable used for tests. -extern const base::char16 kTestServiceExecutableName[]; - -// The name of the executable used for tests. -extern const base::char16 kTestProcessExecutableName[]; - -// Creates a process that will run for a minute, which is long enough to be -// killed by a reasonably fast unit or integration test. -// Populates |command_line| with the used command line if it is not nullptr. -base::Process LongRunningProcess(base::CommandLine* command_line); - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_TEST_TEST_EXECUTABLES_H_
diff --git a/src/cobalt/updater/win/test/test_inheritable_event.cc b/src/cobalt/updater/win/test/test_inheritable_event.cc deleted file mode 100644 index 1866165..0000000 --- a/src/cobalt/updater/win/test/test_inheritable_event.cc +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/test/test_inheritable_event.h" - -#include <windows.h> - -#include <utility> - -#include "base/logging.h" - -namespace updater { - -std::unique_ptr<base::WaitableEvent> CreateInheritableEvent( - base::WaitableEvent::ResetPolicy reset_policy, - base::WaitableEvent::InitialState initial_state) { - SECURITY_ATTRIBUTES attributes = {sizeof(SECURITY_ATTRIBUTES)}; - attributes.bInheritHandle = true; - - HANDLE handle = ::CreateEvent( - &attributes, reset_policy == base::WaitableEvent::ResetPolicy::MANUAL, - initial_state == base::WaitableEvent::InitialState::SIGNALED, nullptr); - if (handle == nullptr || handle == INVALID_HANDLE_VALUE) { - PLOG(ERROR) << "Could not create inheritable event"; - return nullptr; - } - base::win::ScopedHandle event_handle(handle); - return std::make_unique<base::WaitableEvent>(std::move(event_handle)); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/test/test_inheritable_event.h b/src/cobalt/updater/win/test/test_inheritable_event.h deleted file mode 100644 index 3912f9d..0000000 --- a/src/cobalt/updater/win/test/test_inheritable_event.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_TEST_TEST_INHERITABLE_EVENT_H_ -#define CHROME_UPDATER_WIN_TEST_TEST_INHERITABLE_EVENT_H_ - -#include <memory> - -#include "base/synchronization/waitable_event.h" - -namespace updater { - -std::unique_ptr<base::WaitableEvent> CreateInheritableEvent( - base::WaitableEvent::ResetPolicy reset_policy, - base::WaitableEvent::InitialState initial_state); - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_TEST_TEST_INHERITABLE_EVENT_H_
diff --git a/src/cobalt/updater/win/test/test_initializer.cc b/src/cobalt/updater/win/test/test_initializer.cc deleted file mode 100644 index e84914b..0000000 --- a/src/cobalt/updater/win/test/test_initializer.cc +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/test/test_initializer.h" - -#include <memory> -#include <utility> - -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/waitable_event.h" -#include "base/time/time.h" -#include "base/win/scoped_handle.h" -#include "base/win/win_util.h" -#include "chrome/updater/updater_constants.h" - -namespace updater { - -namespace { - -std::unique_ptr<base::WaitableEvent> SignalInitializationDone() { - base::win::ScopedHandle init_done_notifier; - - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - uint32_t handle = 0; - if (command_line->HasSwitch(kInitDoneNotifierSwitch) && - base::StringToUint( - command_line->GetSwitchValueNative(kInitDoneNotifierSwitch), - &handle)) { - init_done_notifier.Set(base::win::Uint32ToHandle(handle)); - } - - std::unique_ptr<base::WaitableEvent> notifier_event; - if (init_done_notifier.IsValid()) { - notifier_event = - std::make_unique<base::WaitableEvent>(std::move(init_done_notifier)); - notifier_event->Signal(); - } - - return notifier_event; -} - -} // namespace - -void NotifyInitializationDoneForTesting() { - auto notifier_event = SignalInitializationDone(); - - // The event has ResetPolicy AUTOMATIC, so after the test is woken up it is - // immediately reset. Wait at most 5 seconds for the test to signal that - // it's ready using the same event before continuing. If the test takes - // longer than that stop waiting to prevent hangs. - if (notifier_event) - notifier_event->TimedWait(base::TimeDelta::FromSeconds(5)); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/test/test_initializer.h b/src/cobalt/updater/win/test/test_initializer.h deleted file mode 100644 index 8c38625..0000000 --- a/src/cobalt/updater/win/test/test_initializer.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_TEST_TEST_INITIALIZER_H_ -#define CHROME_UPDATER_WIN_TEST_TEST_INITIALIZER_H_ - -namespace updater { - -// Signals the event handle that was passed on the command line with -// --init-done-notifier, if it exists. Then waits for the event to be signalled -// again before continuing. This allows a test harness to pause the binary's -// execution, do some extra setup, and resume it. -// Note, this means the event must be AUTOMATIC. -void NotifyInitializationDoneForTesting(); - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_TEST_TEST_INITIALIZER_H_
diff --git a/src/cobalt/updater/win/test/test_main.cc b/src/cobalt/updater/win/test/test_main.cc deleted file mode 100644 index edeb235..0000000 --- a/src/cobalt/updater/win/test/test_main.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "base/win/scoped_com_initializer.h" -#include "chrome/updater/win/task_scheduler.h" -#include "chrome/updater/win/util.h" - -int main(int argc, char** argv) { - // ScopedCOMInitializer keeps COM initialized in a specific scope. We don't - // want to initialize it for sandboxed processes, so manage its lifetime with - // a unique_ptr, which will call ScopedCOMInitializer's destructor when it - // goes out of scope below. - auto scoped_com_initializer = - std::make_unique<base::win::ScopedCOMInitializer>( - base::win::ScopedCOMInitializer::kMTA); - bool success = updater::InitializeCOMSecurity(); - DCHECK(success) << "InitializeCOMSecurity() failed."; - - success = updater::TaskScheduler::Initialize(); - DCHECK(success) << "TaskScheduler::Initialize() failed."; - - // Some tests will fail if two tests try to launch test_process.exe - // simultaneously, so run the tests serially. This will still shard them and - // distribute the shards to different swarming bots, but tests will run - // serially on each bot. - base::TestSuite test_suite(argc, argv); - const int result = base::LaunchUnitTestsWithOptions( - argc, argv, - /*parallel_jobs=*/1U, // Like LaunchUnitTestsSerially - /*default_batch_limit=*/10, // Like LaunchUnitTestsSerially - false, - base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite))); - - updater::TaskScheduler::Terminate(); - - return result; -}
diff --git a/src/cobalt/updater/win/test/test_process_main.cc b/src/cobalt/updater/win/test/test_process_main.cc deleted file mode 100644 index 32f34b4..0000000 --- a/src/cobalt/updater/win/test/test_process_main.cc +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <windows.h> - -#include <string> - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/strings/string16.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/waitable_event.h" -#include "base/time/time.h" -#include "chrome/updater/win/test/test_initializer.h" -#include "chrome/updater/win/test/test_strings.h" - -int main(int, char**) { - bool success = base::CommandLine::Init(0, nullptr); - DCHECK(success); - - updater::NotifyInitializationDoneForTesting(); - - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(updater::kTestSleepMinutesSwitch)) { - std::string value = - command_line->GetSwitchValueASCII(updater::kTestSleepMinutesSwitch); - int sleep_minutes = 0; - if (base::StringToInt(value, &sleep_minutes) && sleep_minutes > 0) { - VLOG(1) << "Process is sleeping for " << sleep_minutes << " minutes"; - ::Sleep(base::TimeDelta::FromMinutes(sleep_minutes).InMilliseconds()); - } else { - LOG(ERROR) << "Invalid sleep delay value " << value; - } - NOTREACHED(); - return 1; - } - - if (command_line->HasSwitch(updater::kTestEventToSignal)) { - VLOG(1) << "Process is signaling event '" << updater::kTestEventToSignal - << "'"; - base::string16 event_name = - command_line->GetSwitchValueNative(updater::kTestEventToSignal); - base::win::ScopedHandle handle( - ::OpenEvent(EVENT_ALL_ACCESS, TRUE, event_name.c_str())); - PLOG_IF(ERROR, !handle.IsValid()) - << "Cannot create event '" << updater::kTestEventToSignal << "'"; - base::WaitableEvent event(std::move(handle)); - event.Signal(); - } - - VLOG(1) << "Process ended."; - return 0; -}
diff --git a/src/cobalt/updater/win/test/test_strings.cc b/src/cobalt/updater/win/test/test_strings.cc deleted file mode 100644 index 031003f..0000000 --- a/src/cobalt/updater/win/test/test_strings.cc +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/test/test_strings.h" - -namespace updater { - -// Command line switches. -const char kTestSleepMinutesSwitch[] = "test-sleep-minutes"; -const char kTestEventToSignal[] = "test-event-to-signal"; - -} // namespace updater
diff --git a/src/cobalt/updater/win/test/test_strings.h b/src/cobalt/updater/win/test/test_strings.h deleted file mode 100644 index ac95ff9..0000000 --- a/src/cobalt/updater/win/test/test_strings.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_TEST_TEST_STRINGS_H_ -#define CHROME_UPDATER_WIN_TEST_TEST_STRINGS_H_ - -#include <windows.h> - -namespace updater { - -// Command line switches. - -// The switch to activate the sleeping action for specified delay in minutes -// before killing the process. -extern const char kTestSleepMinutesSwitch[]; - -// The switch to signal the event with the name given as a switch value. -extern const char kTestEventToSignal[]; - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_TEST_TEST_STRINGS_H_
diff --git a/src/cobalt/updater/win/updater.rc b/src/cobalt/updater/win/updater.rc deleted file mode 100644 index b53c04b..0000000 --- a/src/cobalt/updater/win/updater.rc +++ /dev/null
@@ -1,38 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" -#include "verrsrc.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "#include ""verrsrc.h""\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (United States) resources - -/////////////////////////////////////////////////////////////////////////////
diff --git a/src/cobalt/updater/win/updater.ver b/src/cobalt/updater/win/updater.ver deleted file mode 100644 index bb2b1d6..0000000 --- a/src/cobalt/updater/win/updater.ver +++ /dev/null
@@ -1,3 +0,0 @@ -INTERNAL_NAME=updater_exe -ORIGINAL_FILENAME=updater.exe -PRODUCT_FULLNAME=updater
diff --git a/src/cobalt/updater/win/util.cc b/src/cobalt/updater/win/util.cc deleted file mode 100644 index c7bf448..0000000 --- a/src/cobalt/updater/win/util.cc +++ /dev/null
@@ -1,144 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/util.h" - -#include <aclapi.h> -#include <shlobj.h> -#include <windows.h> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/process/process_iterator.h" - -namespace updater { - -namespace { - -// The number of iterations to poll if a process is stopped correctly. -const unsigned int kMaxProcessQueryIterations = 50; - -// The sleep time in ms between each poll. -const unsigned int kProcessQueryWaitTimeMs = 100; - -} // namespace - -HRESULT HRESULTFromLastError() { - const auto error_code = ::GetLastError(); - return (error_code != NO_ERROR) ? HRESULT_FROM_WIN32(error_code) : E_FAIL; -} - -bool IsProcessRunning(const wchar_t* executable) { - base::NamedProcessIterator iter(executable, nullptr); - const base::ProcessEntry* entry = iter.NextProcessEntry(); - return entry != nullptr; -} - -bool WaitForProcessesStopped(const wchar_t* executable) { - DCHECK(executable); - VLOG(1) << "Wait for processes '" << executable << "'."; - - // Wait until the process is completely stopped. - for (unsigned int iteration = 0; iteration < kMaxProcessQueryIterations; - ++iteration) { - if (!IsProcessRunning(executable)) - return true; - ::Sleep(kProcessQueryWaitTimeMs); - } - - // The process didn't terminate. - LOG(ERROR) << "Cannot stop process '" << executable << "', timeout."; - return false; -} - -// This sets up COM security to allow NetworkService, LocalService, and System -// to call back into the process. It is largely inspired by -// http://msdn.microsoft.com/en-us/library/windows/desktop/aa378987.aspx -// static -bool InitializeCOMSecurity() { - // Create the security descriptor explicitly as follows because - // CoInitializeSecurity() will not accept the relative security descriptors - // returned by ConvertStringSecurityDescriptorToSecurityDescriptor(). - const size_t kSidCount = 5; - uint64_t* sids[kSidCount][(SECURITY_MAX_SID_SIZE + sizeof(uint64_t) - 1) / - sizeof(uint64_t)] = { - {}, {}, {}, {}, {}, - }; - - // These are ordered by most interesting ones to try first. - WELL_KNOWN_SID_TYPE sid_types[kSidCount] = { - WinBuiltinAdministratorsSid, // administrator group security identifier - WinLocalServiceSid, // local service security identifier - WinNetworkServiceSid, // network service security identifier - WinSelfSid, // personal account security identifier - WinLocalSystemSid, // local system security identifier - }; - - // This creates a security descriptor that is equivalent to the following - // security descriptor definition language (SDDL) string: - // O:BAG:BAD:(A;;0x1;;;LS)(A;;0x1;;;NS)(A;;0x1;;;PS) - // (A;;0x1;;;SY)(A;;0x1;;;BA) - - // Initialize the security descriptor. - SECURITY_DESCRIPTOR security_desc = {}; - if (!::InitializeSecurityDescriptor(&security_desc, - SECURITY_DESCRIPTOR_REVISION)) - return false; - - DCHECK_EQ(kSidCount, base::size(sids)); - DCHECK_EQ(kSidCount, base::size(sid_types)); - for (size_t i = 0; i < kSidCount; ++i) { - DWORD sid_bytes = sizeof(sids[i]); - if (!::CreateWellKnownSid(sid_types[i], nullptr, sids[i], &sid_bytes)) - return false; - } - - // Setup the access control entries (ACE) for COM. You may need to modify - // the access permissions for your application. COM_RIGHTS_EXECUTE and - // COM_RIGHTS_EXECUTE_LOCAL are the minimum access rights required. - EXPLICIT_ACCESS explicit_access[kSidCount] = {}; - DCHECK_EQ(kSidCount, base::size(sids)); - DCHECK_EQ(kSidCount, base::size(explicit_access)); - for (size_t i = 0; i < kSidCount; ++i) { - explicit_access[i].grfAccessPermissions = - COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL; - explicit_access[i].grfAccessMode = SET_ACCESS; - explicit_access[i].grfInheritance = NO_INHERITANCE; - explicit_access[i].Trustee.pMultipleTrustee = nullptr; - explicit_access[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - explicit_access[i].Trustee.TrusteeForm = TRUSTEE_IS_SID; - explicit_access[i].Trustee.TrusteeType = TRUSTEE_IS_GROUP; - explicit_access[i].Trustee.ptstrName = reinterpret_cast<LPTSTR>(sids[i]); - } - - // Create an access control list (ACL) using this ACE list, if this succeeds - // make sure to ::LocalFree(acl). - ACL* acl = nullptr; - DWORD acl_result = ::SetEntriesInAcl(base::size(explicit_access), - explicit_access, nullptr, &acl); - if (acl_result != ERROR_SUCCESS || acl == nullptr) - return false; - - HRESULT hr = E_FAIL; - - // Set the security descriptor owner and group to Administrators and set the - // discretionary access control list (DACL) to the ACL. - if (::SetSecurityDescriptorOwner(&security_desc, sids[0], FALSE) && - ::SetSecurityDescriptorGroup(&security_desc, sids[0], FALSE) && - ::SetSecurityDescriptorDacl(&security_desc, TRUE, acl, FALSE)) { - // Initialize COM. You may need to modify the parameters of - // CoInitializeSecurity() for your application. Note that an - // explicit security descriptor is being passed down. - hr = ::CoInitializeSecurity( - &security_desc, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, - RPC_C_IMP_LEVEL_IDENTIFY, nullptr, - EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL, nullptr); - } - - ::LocalFree(acl); - return SUCCEEDED(hr); -} - -} // namespace updater
diff --git a/src/cobalt/updater/win/util.h b/src/cobalt/updater/win/util.h deleted file mode 100644 index 257c677..0000000 --- a/src/cobalt/updater/win/util.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UPDATER_WIN_UTIL_H_ -#define CHROME_UPDATER_WIN_UTIL_H_ - -#include <winerror.h> - -#include "base/win/windows_types.h" - -namespace updater { - -// Returns the last error as an HRESULT or E_FAIL if last error is NO_ERROR. -// This is not a drop in replacement for the HRESULT_FROM_WIN32 macro. -// The macro maps a NO_ERROR to S_OK, whereas the HRESULTFromLastError maps a -// NO_ERROR to E_FAIL. -HRESULT HRESULTFromLastError(); - -// Returns an HRESULT with a custom facility code representing an updater error. -template <typename Error> -HRESULT HRESULTFromUpdaterError(Error error) { - constexpr ULONG kCustomerBit = 0x20000000; - constexpr ULONG kFacilityOmaha = 67; - return static_cast<HRESULT>(static_cast<ULONG>(SEVERITY_ERROR) | - kCustomerBit | (kFacilityOmaha << 16) | - static_cast<ULONG>(error)); -} - -// Checks whether a process is running with the image |executable|. Returns true -// if a process is found. -bool IsProcessRunning(const wchar_t* executable); - -// Waits until every running instance of |executable| is stopped. -// Returns true if every running processes are stopped. -bool WaitForProcessesStopped(const wchar_t* executable); - -bool InitializeCOMSecurity(); - -} // namespace updater - -#endif // CHROME_UPDATER_WIN_UTIL_H_
diff --git a/src/cobalt/updater/win/util_unittest.cc b/src/cobalt/updater/win/util_unittest.cc deleted file mode 100644 index e62b1b4..0000000 --- a/src/cobalt/updater/win/util_unittest.cc +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/win/util.h" - -#include <windows.h> - -#include "testing/gtest/include/gtest/gtest.h" - -namespace updater { - -TEST(UpdaterTestUtil, HRESULTFromLastError) { - ::SetLastError(ERROR_ACCESS_DENIED); - EXPECT_EQ(E_ACCESSDENIED, HRESULTFromLastError()); - ::SetLastError(ERROR_SUCCESS); - EXPECT_EQ(E_FAIL, HRESULTFromLastError()); -} - -} // namespace updater
diff --git a/src/cobalt/webdriver/get_element_text_test.cc b/src/cobalt/webdriver/get_element_text_test.cc index 362fafc..8725037 100644 --- a/src/cobalt/webdriver/get_element_text_test.cc +++ b/src/cobalt/webdriver/get_element_text_test.cc
@@ -28,6 +28,7 @@ #include "cobalt/dom/html_head_element.h" #include "cobalt/dom/html_html_element.h" #include "cobalt/dom/html_paragraph_element.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/text.h" #include "cobalt/webdriver/algorithms.h" #include "testing/gmock/include/gmock/gmock.h" @@ -46,10 +47,11 @@ GetElementTextTest() : css_parser_(css_parser::Parser::Create()), dom_stat_tracker_(new dom::DomStatTracker("GetElementTextTest")), - html_element_context_(NULL, NULL, css_parser_.get(), NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, dom_stat_tracker_.get(), "", - base::kApplicationStateStarted, NULL) {} + html_element_context_( + &environment_settings_, NULL, NULL, css_parser_.get(), NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + dom_stat_tracker_.get(), "", base::kApplicationStateStarted, NULL) { + } void SetUp() override { dom::Document::Options options; @@ -81,6 +83,7 @@ div_->AppendChild(p); } + dom::testing::StubEnvironmentSettings environment_settings_; std::unique_ptr<css_parser::Parser> css_parser_; std::unique_ptr<dom::DomStatTracker> dom_stat_tracker_; dom::HTMLElementContext html_element_context_;
diff --git a/src/cobalt/webdriver/server.cc b/src/cobalt/webdriver/server.cc index 33eb1e6..35795ca 100644 --- a/src/cobalt/webdriver/server.cc +++ b/src/cobalt/webdriver/server.cc
@@ -198,11 +198,11 @@ std::make_unique<net::TCPServerSocket>(nullptr, net::NetLogSource()); server_socket->ListenWithAddressAndPort(listen_ip, port, 1 /*backlog*/); server_ = std::make_unique<net::HttpServer>(std::move(server_socket), this); - GURL address; - int result = GetLocalAddress(&address); + net::IPEndPoint ip_addr; + int result = server_->GetLocalInterfaceAddress(&ip_addr); if (result == net::OK) { LOG(INFO) << "Starting WebDriver server on port " << port; - server_address_ = address.spec(); + server_address_ = "http://" + ip_addr.ToString(); } else { LOG(WARNING) << "Could not start WebDriver server"; server_address_ = "<NOT RUNNING>"; @@ -246,14 +246,5 @@ std::move(response_handler)); } -int WebDriverServer::GetLocalAddress(GURL* out) const { - net::IPEndPoint ip_addr; - int result = server_->GetLocalAddress(&ip_addr); - if (result == net::OK) { - *out = GURL("http://" + ip_addr.ToString()); - } - return result; -} - } // namespace webdriver } // namespace cobalt
diff --git a/src/cobalt/webdriver/server.h b/src/cobalt/webdriver/server.h index 1140cf3..92200cd 100644 --- a/src/cobalt/webdriver/server.h +++ b/src/cobalt/webdriver/server.h
@@ -26,7 +26,6 @@ #include "cobalt/webdriver/protocol/server_status.h" #include "net/server/http_server.h" #include "net/socket/tcp_server_socket.h" -#include "url/gurl.h" namespace cobalt { namespace webdriver { @@ -102,8 +101,6 @@ void OnClose(int) override {} // NOLINT(readability/casting) private: - int GetLocalAddress(GURL* out) const; - THREAD_CHECKER(thread_checker_); HandleRequestCallback handle_request_callback_; std::unique_ptr<net::HttpServer> server_;
diff --git a/src/cobalt/webdriver/web_driver_module.cc b/src/cobalt/webdriver/web_driver_module.cc index f7d2887..68a82d6 100644 --- a/src/cobalt/webdriver/web_driver_module.cc +++ b/src/cobalt/webdriver/web_driver_module.cc
@@ -148,19 +148,14 @@ } // namespace -#if SB_HAS(IPV6) -const char WebDriverModule::kDefaultListenIp[] = "::"; -#else -const char WebDriverModule::kDefaultListenIp[] = "0.0.0.0"; -#endif - WebDriverModule::WebDriverModule( int server_port, const std::string& listen_ip, const CreateSessionDriverCB& create_session_driver_cb, const GetScreenshotFunction& get_screenshot_function, const SetProxyFunction& set_proxy_function, const base::Closure& shutdown_cb) - : webdriver_thread_("WebDriver thread"), + : listen_ip_(listen_ip), + webdriver_thread_("WebDriver thread"), create_session_driver_cb_(create_session_driver_cb), get_screenshot_function_(get_screenshot_function), set_proxy_function_(set_proxy_function), @@ -603,8 +598,7 @@ int port = 3003; screencast_driver_module_.reset(new screencast::ScreencastModule( - port, webdriver::WebDriverModule::kDefaultListenIp, - get_screenshot_function_)); + port, listen_ip_, get_screenshot_function_)); CommandResult result = util::CommandResult<std::string>(std::to_string(port));
diff --git a/src/cobalt/webdriver/web_driver_module.h b/src/cobalt/webdriver/web_driver_module.h index 5a07dc6..ed6123b 100644 --- a/src/cobalt/webdriver/web_driver_module.h +++ b/src/cobalt/webdriver/web_driver_module.h
@@ -49,9 +49,7 @@ CreateSessionDriverCB; typedef Screenshot::GetScreenshotFunction GetScreenshotFunction; typedef base::Callback<void(const std::string&)> SetProxyFunction; - // Use this as the default listen_ip. It means "any interface on the local - // machine" eg INADDR_ANY. - static const char kDefaultListenIp[]; + WebDriverModule(int server_port, const std::string& listen_ip, const CreateSessionDriverCB& create_session_driver_cb, const GetScreenshotFunction& get_screenshot_function, @@ -149,6 +147,9 @@ THREAD_CHECKER(thread_checker_); + // The IP address of the interface WebDriver is listening to. + std::string listen_ip_; + // All WebDriver operations including HTTP server will occur on this thread. base::Thread webdriver_thread_;
diff --git a/src/cobalt/websocket/web_socket.cc b/src/cobalt/websocket/web_socket.cc index 9a04a4d..5af463f 100644 --- a/src/cobalt/websocket/web_socket.cc +++ b/src/cobalt/websocket/web_socket.cc
@@ -170,7 +170,7 @@ WebSocket::WebSocket(script::EnvironmentSettings* settings, const std::string& url, script::ExceptionState* exception_state) - : require_network_module_(true) { + : dom::EventTarget(settings), require_network_module_(true) { const std::vector<std::string> empty; Initialize(settings, url, empty, exception_state); } @@ -179,7 +179,7 @@ const std::string& url, const std::vector<std::string>& sub_protocols, script::ExceptionState* exception_state) - : require_network_module_(true) { + : dom::EventTarget(settings), require_network_module_(true) { Initialize(settings, url, sub_protocols, exception_state); } @@ -203,7 +203,7 @@ const std::string& url, const std::string& sub_protocol_list, script::ExceptionState* exception_state) - : require_network_module_(true) { + : dom::EventTarget(settings), require_network_module_(true) { std::vector<std::string> sub_protocols = base::SplitString(sub_protocol_list, kComma, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); @@ -588,7 +588,8 @@ const std::string& url, script::ExceptionState* exception_state, const bool require_network_module) - : require_network_module_(require_network_module) { + : dom::EventTarget(settings), + require_network_module_(require_network_module) { const std::vector<std::string> empty; Initialize(settings, url, empty, exception_state); } @@ -597,7 +598,8 @@ const std::string& url, const std::string& sub_protocol, script::ExceptionState* exception_state, const bool require_network_module) - : require_network_module_(require_network_module) { + : dom::EventTarget(settings), + require_network_module_(require_network_module) { std::vector<std::string> sub_protocols; sub_protocols.push_back(sub_protocol); Initialize(settings, url, sub_protocols, exception_state); @@ -608,7 +610,8 @@ const std::vector<std::string>& sub_protocols, script::ExceptionState* exception_state, const bool require_network_module) - : require_network_module_(require_network_module) { + : dom::EventTarget(settings), + require_network_module_(require_network_module) { Initialize(settings, url, sub_protocols, exception_state); }
diff --git a/src/cobalt/websocket/web_socket.h b/src/cobalt/websocket/web_socket.h index 2bed313..39ef2ec 100644 --- a/src/cobalt/websocket/web_socket.h +++ b/src/cobalt/websocket/web_socket.h
@@ -32,6 +32,7 @@ #include "cobalt/dom/message_event.h" #include "cobalt/script/array_buffer.h" #include "cobalt/script/array_buffer_view.h" +#include "cobalt/script/environment_settings.h" #include "cobalt/script/global_environment.h" #include "cobalt/script/wrappable.h" #include "cobalt/websocket/web_socket_impl.h" @@ -165,7 +166,6 @@ script::ExceptionState* exception_state, const bool require_network_module); - void Initialize(script::EnvironmentSettings* settings, const std::string& url, const std::vector<std::string>& sub_protocols, script::ExceptionState* exception_state);
diff --git a/src/cobalt/websocket/web_socket_test.cc b/src/cobalt/websocket/web_socket_test.cc index f17c28f..575b46c 100644 --- a/src/cobalt/websocket/web_socket_test.cc +++ b/src/cobalt/websocket/web_socket_test.cc
@@ -18,9 +18,10 @@ #include <vector> #include "base/memory/ref_counted.h" +#include "base/test/scoped_task_environment.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/dom/dom_exception.h" -#include "cobalt/dom/dom_settings.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/window.h" #include "cobalt/network/network_module.h" #include "cobalt/script/script_exception.h" @@ -35,18 +36,17 @@ namespace cobalt { namespace websocket { -class FakeSettings : public dom::DOMSettings { +class FakeSettings : public dom::testing::StubEnvironmentSettings { public: - FakeSettings() - : dom::DOMSettings(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL), - base_("https://example.com") { - this->set_network_module(NULL); + FakeSettings() : base_("https://example.com") { + network_module_.reset(new network::NetworkModule()); + this->set_network_module(network_module_.get()); } const GURL& base_url() const override { return base_; } // public members, so that they're easier for testing. GURL base_; + std::unique_ptr<network::NetworkModule> network_module_; }; class WebSocketTest : public ::testing::Test { @@ -56,8 +56,7 @@ protected: WebSocketTest() : settings_(new FakeSettings()) {} - // A nested message loop needs a non-nested message loop to exist. - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment env_; std::unique_ptr<FakeSettings> settings_; StrictMock<MockExceptionState> exception_state_;
diff --git a/src/cobalt/websocket/websocket.gyp b/src/cobalt/websocket/websocket.gyp index bd7033d..88e2bad 100644 --- a/src/cobalt/websocket/websocket.gyp +++ b/src/cobalt/websocket/websocket.gyp
@@ -36,6 +36,7 @@ '<(DEPTH)/cobalt/base/base.gyp:base', '<(DEPTH)/cobalt/browser/browser_bindings_gen.gyp:generated_types', '<(DEPTH)/cobalt/dom/dom.gyp:dom', + '<(DEPTH)/cobalt/network/network.gyp:network', '<(DEPTH)/net/net.gyp:net', '<(DEPTH)/url/url.gyp:url', ], @@ -59,6 +60,14 @@ # ScriptValueFactory has non-virtual method CreatePromise(). '<(DEPTH)/cobalt/script/engine.gyp:engine', ], + 'conditions': [ + # The network gyp targets depends on 'debug' in unit test builds. + ['enable_debugger == 1', { + 'dependencies': [ + '<(DEPTH)/cobalt/debug/debug.gyp:debug', + ], + }], + ], }, {
diff --git a/src/cobalt/xhr/xml_http_request.cc b/src/cobalt/xhr/xml_http_request.cc index ed7f026..de95cc4 100644 --- a/src/cobalt/xhr/xml_http_request.cc +++ b/src/cobalt/xhr/xml_http_request.cc
@@ -34,6 +34,7 @@ #include "cobalt/dom_parser/xml_decoder.h" #include "cobalt/loader/cors_preflight.h" #include "cobalt/loader/fetcher_factory.h" +#include "cobalt/loader/url_fetcher_string_writer.h" #include "cobalt/script/global_environment.h" #include "cobalt/script/javascript_engine.h" #include "cobalt/xhr/xhr_modify_headers.h" @@ -166,7 +167,8 @@ bool XMLHttpRequest::verbose_ = false; XMLHttpRequest::XMLHttpRequest(script::EnvironmentSettings* settings) - : settings_(base::polymorphic_downcast<dom::DOMSettings*>(settings)), + : XMLHttpRequestEventTarget(settings), + settings_(base::polymorphic_downcast<dom::DOMSettings*>(settings)), state_(kUnsent), response_type_(kDefault), timeout_ms_(0), @@ -611,7 +613,7 @@ scoped_refptr<XMLHttpRequestUpload> XMLHttpRequest::upload() { if (!upload_) { - upload_ = new XMLHttpRequestUpload(); + upload_ = new XMLHttpRequestUpload(settings_); } return upload_; } @@ -716,7 +718,7 @@ DCHECK_NE(state_, kDone); auto* download_data_writer = - base::polymorphic_downcast<CobaltURLFetcherStringWriter*>( + base::polymorphic_downcast<loader::URLFetcherStringWriter*>( source->GetResponseWriter()); std::unique_ptr<std::string> download_data = download_data_writer->data(); if (!download_data.get() || download_data->empty()) { @@ -760,17 +762,22 @@ return; } } - // Ensure all fetched data is read and transfered to this XHR. - OnURLFetchDownloadProgress(source, 0, 0, 0); - fetch_callback_.reset(); - fetch_mode_callback_.reset(); + const net::URLRequestStatus& status = source->GetStatus(); if (status.is_success()) { stop_timeout_ = true; if (error_) { + // Ensure the fetch callbacks are reset when URL fetch is complete, + // regardless of error status. + fetch_callback_.reset(); + fetch_mode_callback_.reset(); return; } + // Ensure all fetched data is read and transfered to this XHR. This should + // only be done for successful and error-free fetches. + OnURLFetchDownloadProgress(source, 0, 0, 0); + // The request may have completed too quickly, before URLFetcher's upload // progress timer had a chance to inform us upload is finished. if (!upload_complete_ && upload_listener_) { @@ -786,6 +793,9 @@ } else { HandleRequestError(kNetworkError); } + + fetch_callback_.reset(); + fetch_mode_callback_.reset(); } // Reset some variables in case the XHR object is reused. @@ -979,6 +989,7 @@ FireProgressEvent(this, base::Tokens::loadend()); fetch_callback_.reset(); + fetch_mode_callback_.reset(); DecrementActiveRequests(); } @@ -1107,9 +1118,9 @@ settings_->fetcher_factory()->network_module(); url_fetcher_ = net::URLFetcher::Create(request_url_, method_, this); url_fetcher_->SetRequestContext(network_module->url_request_context_getter()); - auto* download_data_writer = new CobaltURLFetcherStringWriter(); - url_fetcher_->SaveResponseWithWriter( - std::unique_ptr<net::URLFetcherResponseWriter>(download_data_writer)); + std::unique_ptr<net::URLFetcherResponseWriter> download_data_writer( + new loader::URLFetcherStringWriter()); + url_fetcher_->SaveResponseWithWriter(std::move(download_data_writer)); // Don't retry, let the caller deal with it. url_fetcher_->SetAutomaticallyRetryOn5xx(false); url_fetcher_->SetExtraRequestHeaders(request_headers_.ToString());
diff --git a/src/cobalt/xhr/xml_http_request_event_target.cc b/src/cobalt/xhr/xml_http_request_event_target.cc index f3fb550..526d8cd 100644 --- a/src/cobalt/xhr/xml_http_request_event_target.cc +++ b/src/cobalt/xhr/xml_http_request_event_target.cc
@@ -19,7 +19,9 @@ namespace cobalt { namespace xhr { -XMLHttpRequestEventTarget::XMLHttpRequestEventTarget() {} +XMLHttpRequestEventTarget::XMLHttpRequestEventTarget( + script::EnvironmentSettings* settings) + : EventTarget(settings) {} XMLHttpRequestEventTarget::~XMLHttpRequestEventTarget() {} const dom::EventTarget::EventListenerScriptValue*
diff --git a/src/cobalt/xhr/xml_http_request_event_target.h b/src/cobalt/xhr/xml_http_request_event_target.h index ef76e2b..ab82bbd 100644 --- a/src/cobalt/xhr/xml_http_request_event_target.h +++ b/src/cobalt/xhr/xml_http_request_event_target.h
@@ -19,13 +19,14 @@ #include "base/optional.h" #include "cobalt/dom/event_target.h" +#include "cobalt/script/environment_settings.h" namespace cobalt { namespace xhr { class XMLHttpRequestEventTarget : public dom::EventTarget { public: - XMLHttpRequestEventTarget(); + explicit XMLHttpRequestEventTarget(script::EnvironmentSettings* settings); const EventListenerScriptValue* onabort() const; const EventListenerScriptValue* onerror() const;
diff --git a/src/cobalt/xhr/xml_http_request_test.cc b/src/cobalt/xhr/xml_http_request_test.cc index 39582d8..149a0ae 100644 --- a/src/cobalt/xhr/xml_http_request_test.cc +++ b/src/cobalt/xhr/xml_http_request_test.cc
@@ -12,19 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include <memory> - #include "cobalt/xhr/xml_http_request.h" +#include <memory> + #include "base/logging.h" #include "cobalt/dom/dom_exception.h" -#include "cobalt/dom/dom_settings.h" #include "cobalt/dom/testing/mock_event_listener.h" +#include "cobalt/dom/testing/stub_environment_settings.h" #include "cobalt/dom/window.h" #include "cobalt/script/testing/fake_script_value.h" #include "cobalt/script/testing/mock_exception_state.h" #include "testing/gtest/include/gtest/gtest.h" +using cobalt::dom::EventListener; +using cobalt::dom::testing::MockEventListener; +using cobalt::script::testing::FakeScriptValue; +using cobalt::script::testing::MockExceptionState; using ::testing::_; using ::testing::Eq; using ::testing::HasSubstr; @@ -33,10 +37,6 @@ using ::testing::Return; using ::testing::SaveArg; using ::testing::StrictMock; -using cobalt::dom::EventListener; -using cobalt::dom::testing::MockEventListener; -using cobalt::script::testing::FakeScriptValue; -using cobalt::script::testing::MockExceptionState; namespace cobalt { namespace xhr { @@ -92,12 +92,9 @@ ScopedLogInterceptor* ScopedLogInterceptor::log_interceptor_; -class FakeSettings : public dom::DOMSettings { +class FakeSettings : public dom::testing::StubEnvironmentSettings { public: - FakeSettings() - : dom::DOMSettings(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL), - example_("http://example.com") {} + FakeSettings() : example_("http://example.com") {} const GURL& base_url() const override { return example_; } private: @@ -157,11 +154,11 @@ std::unique_ptr<MockEventListener> listener = MockEventListener::Create(); FakeScriptValue<EventListener> script_object(listener.get()); xhr_->set_onreadystatechange(script_object); - EXPECT_CALL( - *listener, - HandleEvent(Eq(xhr_), Pointee(Property(&dom::Event::type, - base::Token("readystatechange"))), - _)) + EXPECT_CALL(*listener, + HandleEvent(Eq(xhr_), + Pointee(Property(&dom::Event::type, + base::Token("readystatechange"))), + _)) .Times(1); xhr_->Open("GET", "https://www.google.com", &exception_state_);
diff --git a/src/cobalt/xhr/xml_http_request_upload.h b/src/cobalt/xhr/xml_http_request_upload.h index 0acd3ca..9ef1ba1 100644 --- a/src/cobalt/xhr/xml_http_request_upload.h +++ b/src/cobalt/xhr/xml_http_request_upload.h
@@ -20,9 +20,10 @@ namespace cobalt { namespace xhr { -class XMLHttpRequestUpload : public xhr::XMLHttpRequestEventTarget { +class XMLHttpRequestUpload : public XMLHttpRequestEventTarget { public: - XMLHttpRequestUpload() {} + explicit XMLHttpRequestUpload(script::EnvironmentSettings* settings) + : XMLHttpRequestEventTarget(settings) {} DEFINE_WRAPPABLE_TYPE(XMLHttpRequestUpload);
diff --git a/src/glimp/glimp.gyp b/src/glimp/glimp.gyp index fcafa2c..4fcf214 100644 --- a/src/glimp/glimp.gyp +++ b/src/glimp/glimp.gyp
@@ -20,7 +20,7 @@ 'dependencies': [ # Forward-depend on the platform-specific glimp implementation. - '<(DEPTH)/glimp/<(target_arch)/glimp_platform.gyp:glimp_platform', + '<(DEPTH)/glimp/<(sb_target_platform)/glimp_platform.gyp:glimp_platform', ], 'direct_dependent_settings': {
diff --git a/src/glimp/glimp_settings.gypi b/src/glimp/glimp_settings.gypi index 7ea4b74..02ea659 100644 --- a/src/glimp/glimp_settings.gypi +++ b/src/glimp/glimp_settings.gypi
@@ -24,8 +24,8 @@ # the preprocessor to assemble an include file path, so we have to do # the concatenation here in GYP. # http://stackoverflow.com/questions/29601786/c-preprocessor-building-a-path-string - 'GLIMP_EGLPLATFORM_INCLUDE="../../<(target_arch)/eglplatform_public.h"', - 'GLIMP_KHRPLATFORM_INCLUDE="../../<(target_arch)/khrplatform_public.h"', + 'GLIMP_EGLPLATFORM_INCLUDE="../../<(sb_target_platform)/eglplatform_public.h"', + 'GLIMP_KHRPLATFORM_INCLUDE="../../<(sb_target_platform)/khrplatform_public.h"', # Uncomment the define below to enable and use tracing inside glimp. # 'ENABLE_GLIMP_TRACING', ],
diff --git a/src/glimp/include/quad_drawer/helper.h b/src/glimp/include/quad_drawer/helper.h deleted file mode 100644 index 7749fac..0000000 --- a/src/glimp/include/quad_drawer/helper.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2019 Google Inc. 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. - -// The QuadDrawer interface implementation. - -#ifndef GLIMP_INCLUDE_QUAD_DRAWER_HELPER_H_ -#define GLIMP_INCLUDE_QUAD_DRAWER_HELPER_H_ - -#include "starboard/ps4/singleton.h" - -class QuadDrawerHelper : public starboard::ps4::Singleton<QuadDrawerHelper> { - public: - typedef enum color_range { - kStudioRange = 0, // Y [16..235], UV [16..240] - kFullRange = 1 // YUV/RGB [0..255] - } color_range_t; - - typedef enum primary_id { - kPrimaryBt709 = 0, - kPrimaryBt2020 = 1 - } primary_id_t; - - struct QuadDrawerTarget { - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int height; - unsigned int display_width; - unsigned int display_height; - unsigned char* planes[3]; - int stride[3]; - unsigned int bit_depth; - color_range_t color_range; - primary_id_t primary; - }; - - using QuadDrawerCallBack = void(void* context, void* target); - - void SetCallBack(void* context, QuadDrawerCallBack* quad_drawer_callback); - QuadDrawerTarget* GetTarget(); - - private: - QuadDrawerTarget quad_drawer_target_ = {}; - QuadDrawerCallBack* quad_drawer_callback_ = nullptr; - void* context_ = nullptr; -}; - -#endif // GLIMP_INCLUDE_QUAD_DRAWER_HELPER_H_
diff --git a/src/nb/nb.gyp b/src/nb/nb.gyp index 9e94b09..64d4f2d 100644 --- a/src/nb/nb.gyp +++ b/src/nb/nb.gyp
@@ -74,7 +74,7 @@ '<(DEPTH)/starboard/starboard_headers_only.gyp:starboard_headers_only', ], }], - ['target_arch == "ps4"', { + ['sb_target_platform == "ps4"', { 'sources': [ 'kernel_contiguous_allocator_ps4.cc', 'kernel_contiguous_allocator_ps4.h',
diff --git a/src/nb/reuse_allocator_base.cc b/src/nb/reuse_allocator_base.cc index cc2bfe4..03e9903 100644 --- a/src/nb/reuse_allocator_base.cc +++ b/src/nb/reuse_allocator_base.cc
@@ -327,30 +327,33 @@ std::size_t alignment) { void* ptr = NULL; std::size_t size_to_try = 0; + // We try to allocate in unit of |allocation_increment_| to minimize + // fragmentation. if (allocation_increment_ > size) { - size_to_try = std::max(size, allocation_increment_); - if (max_capacity_ && capacity_ + size_to_try > max_capacity_) { - return free_blocks_.end(); + size_to_try = allocation_increment_; + if (!max_capacity_ || capacity_ + size_to_try <= max_capacity_) { + ptr = fallback_allocator_->AllocateForAlignment(&size_to_try, alignment); } - ptr = fallback_allocator_->AllocateForAlignment(&size_to_try, alignment); } + // |ptr| being null indicates the above allocation failed, or in the rare case + // |size| is larger than |allocation_increment_|. Try to allocate a block of + // |size| instead for both cases. if (ptr == NULL) { size_to_try = size; - if (max_capacity_ && capacity_ + size_to_try > max_capacity_) { - return free_blocks_.end(); + if (!max_capacity_ || capacity_ + size_to_try <= max_capacity_) { + ptr = fallback_allocator_->AllocateForAlignment(&size_to_try, alignment); } - ptr = fallback_allocator_->AllocateForAlignment(&size_to_try, alignment); } if (ptr != NULL) { fallback_allocations_.push_back(ptr); capacity_ += size_to_try; return AddFreeBlock(MemoryBlock(ptr, size_to_try)); } - if (free_blocks_.empty()) { return free_blocks_.end(); } + // If control reaches here, then the prior allocation attempts have failed. // We failed to allocate for |size| from the fallback allocator, try to // allocate the difference between |size| and the size of the right most block // in the hope that they are continuous and can be connect to a block that is
diff --git a/src/nb/reuse_allocator_base.h b/src/nb/reuse_allocator_base.h index 0e4f935..79462fc 100644 --- a/src/nb/reuse_allocator_base.h +++ b/src/nb/reuse_allocator_base.h
@@ -66,9 +66,7 @@ std::size_t* size_hint); std::size_t max_capacity() const { return max_capacity_; } - void set_max_capacity(std::size_t max_capacity) { - // TODO: Properly implement decreasing the max capacity so that the - // capacity is not suddenly exceeded. + void IncreaseMaxCapacityIfNecessary(std::size_t max_capacity) { max_capacity_ = std::max(max_capacity, max_capacity_); }
diff --git a/src/nb/reuse_allocator_benchmark.cc b/src/nb/reuse_allocator_benchmark.cc index 86d82e2..4d93203 100644 --- a/src/nb/reuse_allocator_benchmark.cc +++ b/src/nb/reuse_allocator_benchmark.cc
@@ -58,7 +58,7 @@ SB_DCHECK(result); std::vector<char> buffer(file_info.size); - int bytes_read = SbFileRead(file, &buffer[0], buffer.size()); + int bytes_read = SbFileReadAll(file, &buffer[0], buffer.size()); SB_DCHECK(bytes_read == file_info.size); SbFileClose(file);
diff --git a/src/net/cert/ev_root_ca_metadata.cc b/src/net/cert/ev_root_ca_metadata.cc index ab44cc4..1a195ef 100644 --- a/src/net/cert/ev_root_ca_metadata.cc +++ b/src/net/cert/ev_root_ca_metadata.cc
@@ -1047,37 +1047,61 @@ // bool EVRootCAMetadata::IsEVPolicyOID(PolicyOID policy_oid) const { +#if defined(STARBOARD) + NOTIMPLEMENTED_LOG_ONCE(); +#else LOG(WARNING) << "Not implemented"; +#endif return false; } bool EVRootCAMetadata::IsEVPolicyOIDGivenBytes( const der::Input& policy_oid) const { +#if defined(STARBOARD) + NOTIMPLEMENTED_LOG_ONCE(); +#else LOG(WARNING) << "Not implemented"; +#endif return false; } bool EVRootCAMetadata::HasEVPolicyOID(const SHA256HashValue& fingerprint, PolicyOID policy_oid) const { +#if defined(STARBOARD) + NOTIMPLEMENTED_LOG_ONCE(); +#else LOG(WARNING) << "Not implemented"; +#endif return false; } bool EVRootCAMetadata::HasEVPolicyOIDGivenBytes( const SHA256HashValue& fingerprint, const der::Input& policy_oid) const { +#if defined(STARBOARD) + NOTIMPLEMENTED_LOG_ONCE(); +#else LOG(WARNING) << "Not implemented"; +#endif return false; } bool EVRootCAMetadata::AddEVCA(const SHA256HashValue& fingerprint, const char* policy) { +#if defined(STARBOARD) + NOTIMPLEMENTED_LOG_ONCE(); +#else LOG(WARNING) << "Not implemented"; +#endif return true; } bool EVRootCAMetadata::RemoveEVCA(const SHA256HashValue& fingerprint) { +#if defined(STARBOARD) + NOTIMPLEMENTED_LOG_ONCE(); +#else LOG(WARNING) << "Not implemented"; +#endif return true; }
diff --git a/src/net/dial/dial_udp_server.cc b/src/net/dial/dial_udp_server.cc index a963728..affd934 100644 --- a/src/net/dial/dial_udp_server.cc +++ b/src/net/dial/dial_udp_server.cc
@@ -147,12 +147,14 @@ // After optimization, some compiler will dereference and get response size // later than passing response. auto response_size = response->size(); - auto sent_num = socket_->SendTo( + auto result = socket_->SendTo( fake_buffer.get(), response_size, client_address_, base::Bind([](scoped_refptr<WrappedIOBuffer>, std::unique_ptr<std::string>, int /*rv*/) {}, fake_buffer, base::Passed(&response))); - DCHECK_EQ(sent_num, response_size); + if (result < 0) { + DLOG(WARNING) << "Socket SentTo error code: " << result; + } } // Register a watcher on the message loop and wait for the next dial message.
diff --git a/src/net/net.gyp b/src/net/net.gyp index 8ee6a5b..35fceaf 100644 --- a/src/net/net.gyp +++ b/src/net/net.gyp
@@ -433,8 +433,6 @@ 'cert/cert_net_fetcher.h', 'cert/cert_verify_proc.cc', 'cert/cert_verify_proc.h', - # TODO[johnx]: Investigate why net deprecated openssl verifier and - # if justified switch back to builtin verifier. 'cert/cert_verify_proc_builtin.cc', 'cert/cert_verify_proc_builtin.h', 'cert/ct_log_response_parser.cc',
diff --git a/src/net/server/http_server.cc b/src/net/server/http_server.cc index 49a3196..1aa19db 100644 --- a/src/net/server/http_server.cc +++ b/src/net/server/http_server.cc
@@ -24,6 +24,7 @@ #include "net/socket/server_socket.h" #include "net/socket/stream_socket.h" #include "net/socket/tcp_server_socket.h" +#include "starboard/common/socket.h" namespace net { @@ -160,6 +161,39 @@ return server_socket_->GetLocalAddress(address); } +#if defined(STARBOARD) +int HttpServer::GetLocalInterfaceAddress(IPEndPoint* address) { + int result = GetLocalAddress(address); + if (result != net::OK) { + DLOG(ERROR) << "Error getting server local address."; + return result; + } + + // If listening to INADDR_ANY get an interface IP address. + if (address->address().IsZero()) { + SbSocketAddress any_ip; + memset(&(any_ip.address), 0, sizeof(any_ip.address)); + SbSocketAddress interface_address; + // Prefer to report the interface's IPv4 address. + any_ip.type = kSbSocketAddressTypeIpv4; + if (!SbSocketGetInterfaceAddress(&any_ip, &interface_address, nullptr)) { + any_ip.type = kSbSocketAddressTypeIpv6; + if (!SbSocketGetInterfaceAddress(&any_ip, &interface_address, nullptr)) { + DLOG(ERROR) << "Error getting interface address."; + return ERR_FAILED; + } + } + interface_address.port = address->port(); + if (!address->FromSbSocketAddress(&interface_address)) { + DLOG(ERROR) << "Error converting socket address."; + return ERR_FAILED; + } + } + + return OK; +} +#endif // defined(STARBOARD) + void HttpServer::SetReceiveBufferSize(int connection_id, int32_t size) { HttpConnection* connection = FindConnection(connection_id); if (connection)
diff --git a/src/net/server/http_server.h b/src/net/server/http_server.h index 080e41f..ced3bd4 100644 --- a/src/net/server/http_server.h +++ b/src/net/server/http_server.h
@@ -90,6 +90,10 @@ int GetLocalAddress(IPEndPoint* address); #if defined(STARBOARD) + // Like GetLocalAddress(), but if listening to IPADDR_ANY returns the local + // address of an arbitrary interface (choosing IPv4 address over IPv6). + int GetLocalInterfaceAddress(IPEndPoint* address); + bool static ParseHeaders(const std::string& request, HttpServerRequestInfo* info) { size_t pos = 0;
diff --git a/src/net/socket/tcp_socket_starboard.cc b/src/net/socket/tcp_socket_starboard.cc index 829a279..5964db6 100644 --- a/src/net/socket/tcp_socket_starboard.cc +++ b/src/net/socket/tcp_socket_starboard.cc
@@ -198,7 +198,7 @@ // waiting for Accept() to succeed and 2. Peer address is unused in // most use cases. Chromium implementations get the address from accept() // directly, but Starboard API is incapable of that. - LOG(WARNING) << "Could not get peer address for the server socket."; + DVLOG(1) << "Could not get peer address for the server socket."; } }
diff --git a/src/net/spdy/spdy_proxy_client_socket_unittest.cc b/src/net/spdy/spdy_proxy_client_socket_unittest.cc index 8952ca8..3b7a5b1 100644 --- a/src/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/src/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -880,11 +880,7 @@ AssertSyncReadEquals(kMsg2, kLen2); } -#if defined(STARBOARD) -TEST_P(SpdyProxyClientSocketTest, FLAKY_ReadErrorResponseBody) { -#else TEST_P(SpdyProxyClientSocketTest, ReadErrorResponseBody) { -#endif spdy::SpdySerializedFrame conn(ConstructConnectRequestFrame()); MockWrite writes[] = { CreateMockWrite(conn, 0, SYNCHRONOUS),
diff --git a/src/net/third_party/quic/platform/impl/quic_logging_impl.h b/src/net/third_party/quic/platform/impl/quic_logging_impl.h index 4d2bc0d..0e7c18d 100644 --- a/src/net/third_party/quic/platform/impl/quic_logging_impl.h +++ b/src/net/third_party/quic/platform/impl/quic_logging_impl.h
@@ -18,41 +18,25 @@ #define QUIC_LOG_IF_IMPL(severity, condition) \ QUIC_CHROMIUM_LOG_IF_##severity(condition) -#if defined(STARBOARD) -#define QUIC_CHROMIUM_LOG_INFO DLOG(INFO) -#else #define QUIC_CHROMIUM_LOG_INFO VLOG(1) -#endif #define QUIC_CHROMIUM_LOG_WARNING DLOG(WARNING) #define QUIC_CHROMIUM_LOG_ERROR DLOG(ERROR) #define QUIC_CHROMIUM_LOG_FATAL LOG(FATAL) #define QUIC_CHROMIUM_LOG_DFATAL LOG(DFATAL) -#if defined(STARBOARD) -#define QUIC_CHROMIUM_DLOG_INFO DLOG(INFO) -#else #define QUIC_CHROMIUM_DLOG_INFO DVLOG(1) -#endif #define QUIC_CHROMIUM_DLOG_WARNING DLOG(WARNING) #define QUIC_CHROMIUM_DLOG_ERROR DLOG(ERROR) #define QUIC_CHROMIUM_DLOG_FATAL DLOG(FATAL) #define QUIC_CHROMIUM_DLOG_DFATAL DLOG(DFATAL) -#if defined(STARBOARD) -#define QUIC_CHROMIUM_LOG_IF_INFO(condition) DLOG_IF(INFO, condition) -#else #define QUIC_CHROMIUM_LOG_IF_INFO(condition) VLOG_IF(1, condition) -#endif #define QUIC_CHROMIUM_LOG_IF_WARNING(condition) DLOG_IF(WARNING, condition) #define QUIC_CHROMIUM_LOG_IF_ERROR(condition) DLOG_IF(ERROR, condition) #define QUIC_CHROMIUM_LOG_IF_FATAL(condition) LOG_IF(FATAL, condition) #define QUIC_CHROMIUM_LOG_IF_DFATAL(condition) LOG_IF(DFATAL, condition) -#if defined(STARBOARD) -#define QUIC_CHROMIUM_DLOG_IF_INFO(condition) DLOG_IF(INFO, condition) -#else #define QUIC_CHROMIUM_DLOG_IF_INFO(condition) DVLOG_IF(1, condition) -#endif #define QUIC_CHROMIUM_DLOG_IF_WARNING(condition) DLOG_IF(WARNING, condition) #define QUIC_CHROMIUM_DLOG_IF_ERROR(condition) DLOG_IF(ERROR, condition) #define QUIC_CHROMIUM_DLOG_IF_FATAL(condition) DLOG_IF(FATAL, condition) @@ -70,11 +54,7 @@ #define QUIC_LOG_WARNING_IS_ON_IMPL() 1 #define QUIC_LOG_ERROR_IS_ON_IMPL() 1 #endif -#if defined(STARBOARD) && !defined(NDEBUG) -#define QUIC_DLOG_INFO_IS_ON_IMPL() 1 -#else #define QUIC_DLOG_INFO_IS_ON_IMPL() 0 -#endif #if defined(OS_WIN) // wingdi.h defines ERROR to be 0. When we call QUIC_DLOG(ERROR), it gets
diff --git a/src/starboard/accessibility.h b/src/starboard/accessibility.h index 211b257..f270a6c 100644 --- a/src/starboard/accessibility.h +++ b/src/starboard/accessibility.h
@@ -63,7 +63,7 @@ SB_EXPORT bool SbAccessibilityGetDisplaySettings( SbAccessibilityDisplaySettings* out_settings); -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) // Enum for possible closed captioning character edge styles. typedef enum SbAccessibilityCaptionCharacterEdgeStyle { kSbAccessibilityCaptionCharacterEdgeStyleNone, @@ -224,7 +224,7 @@ // or off (false). SB_EXPORT bool SbAccessibilitySetCaptionsEnabled(bool enabled); -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) #ifdef __cplusplus } // extern "C"
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltService.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltService.java index 65e6dc8..e5a4254 100644 --- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltService.java +++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltService.java
@@ -26,6 +26,9 @@ /** Get the name of the service. */ public String getServiceName(); } + /** Take in a reference to StarboardBridge & use it as needed. Default behavior is no-op. */ + public void receiveStarboardBridge(StarboardBridge bridge) {} + // Lifecycle /** Prepare service for start or resume. */ public abstract void beforeStartOrResume();
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java index 49b37c0..85c7c56 100644 --- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java +++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
@@ -525,6 +525,11 @@ return false; } + /** Return the CobaltMediaSession. */ + public CobaltMediaSession cobaltMediaSession() { + return cobaltMediaSession; + } + public void registerCobaltService(CobaltService.Factory factory) { cobaltServiceFactories.put(factory.getServiceName(), factory); } @@ -550,6 +555,7 @@ } CobaltService service = factory.createCobaltService(nativeService); if (service != null) { + service.receiveStarboardBridge(this); cobaltServices.put(serviceName, service); } return service;
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/VoiceRecognizer.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/VoiceRecognizer.java index d9aba31..06cc02f 100644 --- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/VoiceRecognizer.java +++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/VoiceRecognizer.java
@@ -14,6 +14,8 @@ package dev.cobalt.coat; +import static dev.cobalt.util.Log.TAG; + import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -24,6 +26,7 @@ import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; import dev.cobalt.util.Holder; +import dev.cobalt.util.Log; import dev.cobalt.util.UsedByNative; import java.util.ArrayList; @@ -175,7 +178,12 @@ } private void reset() { - speechRecognizer.destroy(); + try { + speechRecognizer.destroy(); + } catch (IllegalArgumentException ex) { + // Soft handling + Log.e(TAG, "Error in speechRecognizer.destroy()!", ex); + } speechRecognizer = null; nativeSpeechRecognizerImpl = 0;
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java index fcc31b1..ae511c9 100644 --- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java +++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java
@@ -84,9 +84,17 @@ private static final String[] PLAYBACK_STATE_NAME = {"playing", "paused", "none"}; // Accessed on the main looper thread only. - private int playbackState = PLAYBACK_STATE_NONE; + private int currentPlaybackState = PLAYBACK_STATE_NONE; private boolean transientPause = false; private boolean suspended = true; + private boolean explicitUserActionRequired = false; + + /** LifecycleCallback to notify listeners when |mediaSession| becomes active or inactive. */ + public interface LifecycleCallback { + void onMediaSessionLifecycle(boolean isActive, MediaSessionCompat.Token token); + } + + private LifecycleCallback lifecycleCallback = null; public CobaltMediaSession( Context context, Holder<Activity> activityHolder, UpdateVolumeListener volumeListener) { @@ -98,7 +106,16 @@ setMediaSession(); } + public void setLifecycleCallback(LifecycleCallback lifecycleCallback) { + this.lifecycleCallback = lifecycleCallback; + if (lifecycleCallback != null) { + lifecycleCallback.onMediaSessionLifecycle( + this.mediaSession.isActive(), this.mediaSession.getSessionToken()); + } + } + private void setMediaSession() { + Log.i(TAG, "MediaSession new"); mediaSession = new MediaSessionCompat(context, TAG); mediaSession.setFlags(MEDIA_SESSION_FLAG_HANDLES_TRANSPORT_CONTROLS); mediaSession.setCallback( @@ -106,6 +123,7 @@ @Override public void onFastForward() { Log.i(TAG, "MediaSession action: FAST FORWARD"); + explicitUserActionRequired = false; nativeInvokeAction(PlaybackStateCompat.ACTION_FAST_FORWARD); } @@ -118,30 +136,35 @@ @Override public void onPlay() { Log.i(TAG, "MediaSession action: PLAY"); + explicitUserActionRequired = false; nativeInvokeAction(PlaybackStateCompat.ACTION_PLAY); } @Override public void onRewind() { Log.i(TAG, "MediaSession action: REWIND"); + explicitUserActionRequired = false; nativeInvokeAction(PlaybackStateCompat.ACTION_REWIND); } @Override public void onSkipToNext() { Log.i(TAG, "MediaSession action: SKIP NEXT"); + explicitUserActionRequired = false; nativeInvokeAction(PlaybackStateCompat.ACTION_SKIP_TO_NEXT); } @Override public void onSkipToPrevious() { Log.i(TAG, "MediaSession action: SKIP PREVIOUS"); + explicitUserActionRequired = false; nativeInvokeAction(PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS); } @Override public void onSeekTo(long pos) { Log.i(TAG, "MediaSession action: SEEK " + pos); + explicitUserActionRequired = false; nativeInvokeAction(PlaybackStateCompat.ACTION_SEEK_TO, pos); } @@ -164,8 +187,10 @@ } /** - * Sets system media resources active or not according to whether media is playing. This is - * idempotent as it may be called multiple times during the course of a media session. + * Sets system media resources active or not according to whether media is playing. The concept of + * "media focus" encapsulates wake lock, audio focus and active media session so that all three + * are set together to stay coherent as playback state changes. This is idempotent as it may be + * called multiple times during the course of a media session. */ private void configureMediaFocus(int playbackState) { checkMainLooperThread(); @@ -186,8 +211,13 @@ setMediaSession(); } mediaSession.setActive(playbackState != PLAYBACK_STATE_NONE); + if (lifecycleCallback != null) { + lifecycleCallback.onMediaSessionLifecycle( + this.mediaSession.isActive(), this.mediaSession.getSessionToken()); + } if (deactivating) { // Suspending lands here. + Log.i(TAG, "MediaSession release"); mediaSession.release(); } } @@ -268,7 +298,7 @@ // fall through case AudioManager.AUDIOFOCUS_LOSS: Log.i(TAG, "Audiofocus loss" + logExtra); - if (playbackState == PLAYBACK_STATE_PLAYING) { + if (currentPlaybackState == PLAYBACK_STATE_PLAYING) { Log.i(TAG, "Audiofocus action: PAUSE"); nativeInvokeAction(PlaybackStateCompat.ACTION_PAUSE); } @@ -285,7 +315,7 @@ // The app has been granted audio focus (again). Raise volume to normal, // restart playback if necessary. volumeListener.onUpdateVolume(1.0f); - if (transientPause && playbackState == PLAYBACK_STATE_PAUSED) { + if (transientPause && currentPlaybackState == PLAYBACK_STATE_PAUSED) { Log.i(TAG, "Audiofocus action: PLAY"); nativeInvokeAction(PlaybackStateCompat.ACTION_PLAY); } @@ -295,6 +325,9 @@ // Keep track of whether we're currently paused because of a transient loss of audiofocus. transientPause = (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT); + // To restart playback after permanent loss, the user must take an explicit action. + // See: https://developer.android.com/guide/topics/media-apps/audio-focus + explicitUserActionRequired = (focusChange == AudioManager.AUDIOFOCUS_LOSS); } private AudioManager getAudioManager() { @@ -315,17 +348,21 @@ checkMainLooperThread(); suspended = false; // Undoing what may have been done in suspendInternal(). - configureMediaFocus(playbackState); + configureMediaFocus(currentPlaybackState); } public void suspend() { - mainHandler.post( - new Runnable() { - @Override - public void run() { - suspendInternal(); - } - }); + if (Looper.getMainLooper() == Looper.myLooper()) { + suspendInternal(); + } else { + mainHandler.post( + new Runnable() { + @Override + public void run() { + suspendInternal(); + } + }); + } } private void suspendInternal() { @@ -339,9 +376,9 @@ // it's in a playing state. We'll configure it again in resumeInternal() and the HTML5 app will // be none the wiser. playbackStateBuilder.setState( - playbackState, + currentPlaybackState, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, - playbackState == PLAYBACK_STATE_PLAYING ? 1.0f : 0.0f); + currentPlaybackState == PLAYBACK_STATE_PLAYING ? 1.0f : 0.0f); configureMediaFocus(PLAYBACK_STATE_NONE); } @@ -384,9 +421,10 @@ final long duration) { checkMainLooperThread(); + boolean hasStateChange = this.currentPlaybackState != playbackState; // Always keep track of what the HTML5 app thinks the playback state is so we can configure the // media focus correctly, either immediately or when resuming from being suspended. - this.playbackState = playbackState; + this.currentPlaybackState = playbackState; // Don't update anything while suspended. if (suspended) { @@ -394,7 +432,25 @@ return; } - configureMediaFocus(playbackState); + if (hasStateChange) { + if (playbackState == PLAYBACK_STATE_PLAYING) { + // We don't want to request media focus if |explicitUserActionRequired| is true when we + // don't have window focus. Ideally, we should recognize user action to re-request audio + // focus if |explicitUserActionRequired| is true. Currently we're not able to recognize + // it. But if we don't have window focus, we know the user is not interacting with our app + // and we should not request media focus. + if (!explicitUserActionRequired || activityHolder.get().hasWindowFocus()) { + explicitUserActionRequired = false; + configureMediaFocus(playbackState); + } else { + Log.w(TAG, "Audiofocus action: PAUSE (explicit user action required)"); + nativeInvokeAction(PlaybackStateCompat.ACTION_PAUSE); + } + } else { + // It's fine to abandon media focus anytime. + configureMediaFocus(playbackState); + } + } // Ignore updates to the MediaSession metadata if playback is stopped. if (playbackState == PLAYBACK_STATE_NONE) {
diff --git a/src/starboard/android/arm/gyp_configuration.py b/src/starboard/android/arm/gyp_configuration.py index b804d2f..ca56491 100644 --- a/src/starboard/android/arm/gyp_configuration.py +++ b/src/starboard/android/arm/gyp_configuration.py
@@ -17,4 +17,7 @@ def CreatePlatformConfig(): - return shared_configuration.AndroidConfiguration('android-arm', 'armeabi-v7a') + return shared_configuration.AndroidConfiguration( + 'android-arm', + 'armeabi-v7a', + sabi_json_path='starboard/sabi/arm/softfp/sabi.json')
diff --git a/src/starboard/android/arm64/gyp_configuration.py b/src/starboard/android/arm64/gyp_configuration.py index 215dc50..243d3a1 100644 --- a/src/starboard/android/arm64/gyp_configuration.py +++ b/src/starboard/android/arm64/gyp_configuration.py
@@ -17,4 +17,7 @@ def CreatePlatformConfig(): - return shared_configuration.AndroidConfiguration('android-arm64', 'arm64-v8a') + return shared_configuration.AndroidConfiguration( + 'android-arm64', + 'arm64-v8a', + sabi_json_path='starboard/sabi/arm64/sabi.json')
diff --git a/src/starboard/android/shared/application_android.cc b/src/starboard/android/shared/application_android.cc index 8b411b0..5048e4d 100644 --- a/src/starboard/android/shared/application_android.cc +++ b/src/starboard/android/shared/application_android.cc
@@ -249,7 +249,8 @@ } break; case AndroidCommand::kNativeWindowDestroyed: - env->CallStarboardVoidMethodOrAbort("beforeSuspend", "()V"); + // No need to JNI call StarboardBridge.beforeSuspend() since we did it + // early in SendAndroidCommand(). { ScopedLock lock(android_command_mutex_); // Cobalt can't keep running without a window, even if the Activity @@ -331,6 +332,14 @@ void ApplicationAndroid::SendAndroidCommand(AndroidCommand::CommandType type, void* data) { SB_LOG(INFO) << "Send Android command: " << AndroidCommandName(type); + if (type == AndroidCommand::kNativeWindowDestroyed) { + // When this command is processed it will suspend Cobalt, so make the JNI + // call to StarboardBridge.beforeSuspend() early while still here on the + // Android main thread. This lets the MediaSession get released now without + // having to wait to bounce between threads. + JniEnvExt* env = JniEnvExt::Get(); + env->CallStarboardVoidMethodOrAbort("beforeSuspend", "()V"); + } AndroidCommand cmd {type, data}; ScopedLock lock(android_command_mutex_); write(android_command_writefd_, &cmd, sizeof(cmd)); @@ -353,7 +362,6 @@ } void ApplicationAndroid::ProcessAndroidInput() { - SB_DCHECK(input_events_generator_); AInputEvent* android_event = NULL; while (AInputQueue_getEvent(input_queue_, &android_event) >= 0) { SB_LOG(INFO) << "Android input: type=" @@ -361,6 +369,11 @@ if (AInputQueue_preDispatchEvent(input_queue_, android_event)) { continue; } + if (!input_events_generator_) { + SB_DLOG(WARNING) << "Android input event ignored without an SbWindow."; + AInputQueue_finishEvent(input_queue_, android_event, false); + continue; + } InputEventsGenerator::Events app_events; bool handled = input_events_generator_->CreateInputEventsFromAndroidEvent( android_event, &app_events); @@ -376,7 +389,10 @@ int err = read(keyboard_inject_readfd_, &key, sizeof(key)); SB_DCHECK(err >= 0) << "Keyboard inject read failed: errno=" << errno; SB_LOG(INFO) << "Keyboard inject: " << key; - + if (!input_events_generator_) { + SB_DLOG(WARNING) << "Injected input event ignored without an SbWindow."; + return; + } InputEventsGenerator::Events app_events; input_events_generator_->CreateInputEventsFromSbKey(key, &app_events); for (int i = 0; i < app_events.size(); ++i) { @@ -399,14 +415,17 @@ Java_dev_cobalt_coat_KeyboardInputConnection_nativeHasOnScreenKeyboard( JniEnvExt* env, jobject unused_this) { -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + return SbWindowOnScreenKeyboardIsSupported() ? JNI_TRUE : JNI_FALSE; +#elif SB_HAS(ON_SCREEN_KEYBOARD) return JNI_TRUE; -#else // SB_HAS(ON_SCREEN_KEYBOARD) +#else return JNI_FALSE; -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif } -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void ApplicationAndroid::SbWindowShowOnScreenKeyboard(SbWindow window, const char* input_text, @@ -499,7 +518,8 @@ return; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) bool ApplicationAndroid::OnSearchRequested() { for (int i = 0; i < 2; i++) {
diff --git a/src/starboard/android/shared/audio_decoder.cc b/src/starboard/android/shared/audio_decoder.cc index 9f82a9e..e42874b 100644 --- a/src/starboard/android/shared/audio_decoder.cc +++ b/src/starboard/android/shared/audio_decoder.cc
@@ -124,7 +124,8 @@ media_decoder_->WriteEndOfStream(); } -scoped_refptr<AudioDecoder::DecodedAudio> AudioDecoder::Read() { +scoped_refptr<AudioDecoder::DecodedAudio> AudioDecoder::Read( + int* samples_per_second) { SB_DCHECK(BelongsToCurrentThread()); SB_DCHECK(output_cb_); @@ -143,6 +144,7 @@ Schedule(consumed_cb_); consumed_cb_ = nullptr; } + *samples_per_second = audio_sample_info_.samples_per_second; return result; } @@ -207,9 +209,9 @@ } scoped_refptr<DecodedAudio> decoded_audio = new DecodedAudio( - audio_sample_info_.number_of_channels, GetSampleType(), - GetStorageType(), dequeue_output_result.presentation_time_microseconds, - size); + audio_sample_info_.number_of_channels, sample_type_, + kSbMediaAudioFrameStorageTypeInterleaved, + dequeue_output_result.presentation_time_microseconds, size); SbMemoryCopy(decoded_audio->buffer(), data, size);
diff --git a/src/starboard/android/shared/audio_decoder.h b/src/starboard/android/shared/audio_decoder.h index 6935cfd..b5f874c 100644 --- a/src/starboard/android/shared/audio_decoder.h +++ b/src/starboard/android/shared/audio_decoder.h
@@ -47,19 +47,9 @@ void Decode(const scoped_refptr<InputBuffer>& input_buffer, const ConsumedCB& consumed_cb) override; void WriteEndOfStream() override; - scoped_refptr<DecodedAudio> Read() override; + scoped_refptr<DecodedAudio> Read(int* samples_per_second) override; void Reset() override; - SbMediaAudioSampleType GetSampleType() const override { - return sample_type_; - } - SbMediaAudioFrameStorageType GetStorageType() const override { - return kSbMediaAudioFrameStorageTypeInterleaved; - } - int GetSamplesPerSecond() const override { - return audio_sample_info_.samples_per_second; - } - bool is_valid() const { return media_decoder_ != NULL; } private:
diff --git a/src/starboard/android/shared/configuration_public.h b/src/starboard/android/shared/configuration_public.h index 0b8e0dc..7abc208 100644 --- a/src/starboard/android/shared/configuration_public.h +++ b/src/starboard/android/shared/configuration_public.h
@@ -23,59 +23,14 @@ #ifndef STARBOARD_ANDROID_SHARED_CONFIGURATION_PUBLIC_H_ #define STARBOARD_ANDROID_SHARED_CONFIGURATION_PUBLIC_H_ -// The API version implemented by this platform. -#define SB_API_VERSION SB_EXPERIMENTAL_API_VERSION +#if SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION +#error \ + "This platform's sabi.json file is expected to track the experimental " \ +"Starboard API version." +#endif // SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION // --- Architecture Configuration -------------------------------------------- -// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be -// automatically set based on this. -#define SB_IS_BIG_ENDIAN 0 - -// Whether the current platform is a MIPS architecture. -#define SB_IS_ARCH_MIPS 0 - -// Whether the current platform is a PPC architecture. -#define SB_IS_ARCH_PPC 0 - -// The current platform CPU architecture architecture. -#if defined(__arm__) || defined(__aarch64__) -#define SB_IS_ARCH_ARM 1 -#define SB_IS_ARCH_X86 0 -#elif defined(__i386__) || defined(__x86_64__) -#define SB_IS_ARCH_ARM 0 -#define SB_IS_ARCH_X86 1 -#endif - -// Whether the current platform is 32-bit or 64-bit architecture. -#if defined(__aarch64__) || defined(__x86_64__) -#define SB_IS_32_BIT 0 -#define SB_IS_64_BIT 1 -#else -#define SB_IS_32_BIT 1 -#define SB_IS_64_BIT 0 -#endif - -// Whether the current platform's pointers are 32-bit. -// Whether the current platform's longs are 32-bit. -#if SB_IS(32_BIT) -#define SB_HAS_32_BIT_POINTERS 1 -#define SB_HAS_32_BIT_LONG 1 -#else -#define SB_HAS_32_BIT_POINTERS 0 -#define SB_HAS_32_BIT_LONG 0 -#endif - -// Whether the current platform's pointers are 64-bit. -// Whether the current platform's longs are 64-bit. -#if SB_IS(64_BIT) -#define SB_HAS_64_BIT_POINTERS 1 -#define SB_HAS_64_BIT_LONG 1 -#else -#define SB_HAS_64_BIT_POINTERS 0 -#define SB_HAS_64_BIT_LONG 0 -#endif - // Configuration parameters that allow the application to make some general // compile-time decisions with respect to the the number of cores likely to be // available on this platform. For a definitive measure, the application should @@ -259,29 +214,12 @@ // textures. These textures typically originate from video decoders. #define SB_HAS_NV12_TEXTURE_SUPPORT 1 -// Whether the current platform should frequently flip their display buffer. -// If this is not required (e.g. SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is set -// to 0), then optimizations where the display buffer is not flipped if the -// scene hasn't changed are enabled. -#define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER 0 - // --- I/O Configuration ----------------------------------------------------- - -// Whether the current platform implements the on screen keyboard interface. -#define SB_HAS_ON_SCREEN_KEYBOARD 0 - -// Whether the current platform has speech recognizer. -#define SB_HAS_SPEECH_RECOGNIZER 1 - // Whether the current platform has speech synthesis. #define SB_HAS_SPEECH_SYNTHESIS 1 // --- Media Configuration --------------------------------------------------- -// Specifies whether this platform supports retrieving system-level closed -// caption settings -#define SB_HAS_CAPTIONS 1 - // The maximum audio bitrate the platform can decode. The following value // equals to 5M bytes per seconds which is more than enough for compressed // audio. @@ -340,12 +278,8 @@ // it. #define SB_MEMORY_PAGE_SIZE 4096 -// Whether this platform has and should use an MMAP function to map physical -// memory to the virtual address space. -#define SB_HAS_MMAP 1 - -// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is -// required for platforms that want to JIT. +// Whether this platform can map executable memory. Implies the platform can map +// memory. This is required for platforms that want to JIT. #define SB_CAN_MAP_EXECUTABLE_MEMORY 1 // Whether this platform has and should use an growable heap (e.g. with sbrk())
diff --git a/src/starboard/android/shared/drm_system.cc b/src/starboard/android/shared/drm_system.cc index 87845d1..984fe64 100644 --- a/src/starboard/android/shared/drm_system.cc +++ b/src/starboard/android/shared/drm_system.cc
@@ -17,6 +17,7 @@ #include "starboard/android/shared/jni_env_ext.h" #include "starboard/android/shared/jni_utils.h" #include "starboard/android/shared/media_common.h" +#include "starboard/common/instance_counter.h" namespace { @@ -41,6 +42,8 @@ const jint REQUEST_TYPE_RENEWAL = 1; const jint REQUEST_TYPE_RELEASE = 2; +DECLARE_INSTANCE_COUNTER(AndroidDrmSystem) + SbDrmSessionRequestType SbDrmSessionRequestTypeFromMediaDrmKeyRequestType( jint request_type) { if (request_type == REQUEST_TYPE_INITIAL) { @@ -180,6 +183,8 @@ j_media_drm_bridge_(NULL), j_media_crypto_(NULL), hdcp_lost_(false) { + ON_INSTANCE_CREATED(AndroidDrmSystem); + JniEnvExt* env = JniEnvExt::Get(); j_media_drm_bridge_ = env->CallStaticObjectMethodOrAbort( "dev/cobalt/media/MediaDrmBridge", "create", @@ -199,6 +204,8 @@ } DrmSystem::~DrmSystem() { + ON_INSTANCE_RELEASED(AndroidDrmSystem); + JniEnvExt* env = JniEnvExt::Get(); if (j_media_crypto_) { env->DeleteGlobalRef(j_media_crypto_);
diff --git a/src/starboard/android/shared/gyp_configuration.gypi b/src/starboard/android/shared/gyp_configuration.gypi index 12dd798..c06cc60 100644 --- a/src/starboard/android/shared/gyp_configuration.gypi +++ b/src/starboard/android/shared/gyp_configuration.gypi
@@ -153,4 +153,8 @@ }], ], }, # end of target_defaults + + 'includes': [ + '<(DEPTH)/starboard/sabi/sabi.gypi', + ], }
diff --git a/src/starboard/android/shared/gyp_configuration.py b/src/starboard/android/shared/gyp_configuration.py index 2948b8f..e8ff171 100644 --- a/src/starboard/android/shared/gyp_configuration.py +++ b/src/starboard/android/shared/gyp_configuration.py
@@ -66,7 +66,11 @@ """Starboard Android platform configuration.""" # TODO: make ASAN work with NDK tools and enable it by default - def __init__(self, platform, android_abi, asan_enabled_by_default=False): + def __init__(self, + platform, + android_abi, + asan_enabled_by_default=False, + sabi_json_path=None): super(AndroidConfiguration, self).__init__(platform, asan_enabled_by_default) self._target_toolchain = None @@ -75,6 +79,7 @@ self.AppendApplicationConfigurationPath(os.path.dirname(__file__)) self.android_abi = android_abi + self.sabi_json_path = sabi_json_path self.android_home = sdk_utils.GetSdkPath() self.android_ndk_home = sdk_utils.GetNdkPath() @@ -298,3 +303,6 @@ 'SbSocketAddressTypes/SbSocketResolveTest.Localhost/1', ], } + + def GetPathToSabiJsonFile(self): + return self.sabi_json_path
diff --git a/src/starboard/android/shared/log.cc b/src/starboard/android/shared/log.cc index 35ed73d..6cbc17f 100644 --- a/src/starboard/android/shared/log.cc +++ b/src/starboard/android/shared/log.cc
@@ -25,11 +25,8 @@ #include "starboard/common/log.h" #include "starboard/common/string.h" #include "starboard/configuration.h" -#include "starboard/thread.h" - -#if SB_API_VERSION >= 11 #include "starboard/shared/starboard/log_mutex.h" -#endif // SB_API_VERSION >= 11 +#include "starboard/thread.h" using starboard::android::shared::JniEnvExt; using starboard::android::shared::ScopedLocalJavaRef;
diff --git a/src/starboard/android/shared/media_codec_bridge.cc b/src/starboard/android/shared/media_codec_bridge.cc index 01ed2e3..398f3b5 100644 --- a/src/starboard/android/shared/media_codec_bridge.cc +++ b/src/starboard/android/shared/media_codec_bridge.cc
@@ -245,14 +245,6 @@ env->DeleteGlobalRef(j_media_codec_bridge_); j_media_codec_bridge_ = NULL; - SB_DCHECK(j_reused_dequeue_input_result_); - env->DeleteGlobalRef(j_reused_dequeue_input_result_); - j_reused_dequeue_input_result_ = NULL; - - SB_DCHECK(j_reused_dequeue_output_result_); - env->DeleteGlobalRef(j_reused_dequeue_output_result_); - j_reused_dequeue_output_result_ = NULL; - SB_DCHECK(j_reused_get_output_format_result_); env->DeleteGlobalRef(j_reused_get_output_format_result_); j_reused_get_output_format_result_ = NULL; @@ -402,17 +394,6 @@ JniEnvExt* env = JniEnvExt::Get(); SB_DCHECK(env->GetObjectRefType(j_media_codec_bridge_) == JNIGlobalRefType); - j_reused_dequeue_input_result_ = env->NewObjectOrAbort( - "dev/cobalt/media/MediaCodecBridge$DequeueInputResult", "()V"); - SB_DCHECK(j_reused_dequeue_input_result_); - j_reused_dequeue_input_result_ = - env->ConvertLocalRefToGlobalRef(j_reused_dequeue_input_result_); - - j_reused_dequeue_output_result_ = env->NewObjectOrAbort( - "dev/cobalt/media/MediaCodecBridge$DequeueOutputResult", "()V"); - SB_DCHECK(j_reused_dequeue_output_result_); - j_reused_dequeue_output_result_ = - env->ConvertLocalRefToGlobalRef(j_reused_dequeue_output_result_); j_reused_get_output_format_result_ = env->NewObjectOrAbort( "dev/cobalt/media/MediaCodecBridge$GetOutputFormatResult", "()V");
diff --git a/src/starboard/android/shared/media_codec_bridge.h b/src/starboard/android/shared/media_codec_bridge.h index 23ddf8a..0329f06 100644 --- a/src/starboard/android/shared/media_codec_bridge.h +++ b/src/starboard/android/shared/media_codec_bridge.h
@@ -110,7 +110,6 @@ ~MediaCodecBridge(); - DequeueInputResult DequeueInputBuffer(jlong timeout_us); // It is the responsibility of the client to manage the lifetime of the // jobject that |GetInputBuffer| returns. jobject GetInputBuffer(jint index); @@ -124,7 +123,6 @@ const SbDrmSampleInfo& drm_sample_info, jlong presentation_time_microseconds); - DequeueOutputResult DequeueOutputBuffer(jlong timeout_us); // It is the responsibility of the client to manage the lifetime of the // jobject that |GetOutputBuffer| returns. jobject GetOutputBuffer(jint index); @@ -159,8 +157,6 @@ // playback. We mitigate this by reusing these output objects between calls // to |DequeueInputBuffer|, |DequeueOutputBuffer|, and // |GetOutputDimensions|. - jobject j_reused_dequeue_input_result_ = NULL; - jobject j_reused_dequeue_output_result_ = NULL; jobject j_reused_get_output_format_result_ = NULL; SB_DISALLOW_COPY_AND_ASSIGN(MediaCodecBridge);
diff --git a/src/starboard/android/shared/media_common.h b/src/starboard/android/shared/media_common.h index 9e47335..189c902 100644 --- a/src/starboard/android/shared/media_common.h +++ b/src/starboard/android/shared/media_common.h
@@ -59,6 +59,8 @@ return "video/x-vnd.on2.vp9"; } else if (video_codec == kSbMediaVideoCodecH264) { return "video/avc"; + } else if (video_codec == kSbMediaVideoCodecH265) { + return "video/hevc"; } return NULL; }
diff --git a/src/starboard/android/shared/media_decoder.cc b/src/starboard/android/shared/media_decoder.cc index fe757cc..f1a3dfb 100644 --- a/src/starboard/android/shared/media_decoder.cc +++ b/src/starboard/android/shared/media_decoder.cc
@@ -18,11 +18,9 @@ #include "starboard/android/shared/jni_utils.h" #include "starboard/android/shared/media_common.h" #include "starboard/audio_sink.h" -#if SB_API_VERSION >= 11 -#include "starboard/format_string.h" -#endif // SB_API_VERSION >= 11 #include "starboard/common/log.h" #include "starboard/common/string.h" +#include "starboard/format_string.h" #include "starboard/shared/pthread/thread_create_priority.h" namespace starboard { @@ -466,8 +464,15 @@ is_output_restricted_ = true; drm_system_->OnInsufficientOutputProtection(); } else { - error_cb_(kSbPlayerErrorDecode, - FormatString("%s failed with status %d.", action_name, status)); + if (media_type_ == kSbMediaTypeAudio) { + error_cb_(kSbPlayerErrorDecode, + FormatString("%s failed with status %d (audio).", action_name, + status)); + } else { + error_cb_(kSbPlayerErrorDecode, + FormatString("%s failed with status %d (video).", action_name, + status)); + } } if (retry) { @@ -489,7 +494,15 @@ << " error with message: " << diagnostic_info; if (!is_transient) { - error_cb_(kSbPlayerErrorDecode, "OnMediaCodecError"); + if (media_type_ == kSbMediaTypeAudio) { + error_cb_(kSbPlayerErrorDecode, + "OnMediaCodecError (audio): " + diagnostic_info + + (is_recoverable ? ", recoverable " : ", unrecoverable ")); + } else { + error_cb_(kSbPlayerErrorDecode, + "OnMediaCodecError (video): " + diagnostic_info + + (is_recoverable ? ", recoverable " : ", unrecoverable ")); + } } }
diff --git a/src/starboard/android/shared/media_is_audio_supported.cc b/src/starboard/android/shared/media_is_audio_supported.cc index 227865d..679d02d 100644 --- a/src/starboard/android/shared/media_is_audio_supported.cc +++ b/src/starboard/android/shared/media_is_audio_supported.cc
@@ -23,8 +23,7 @@ using starboard::android::shared::ScopedLocalJavaRef; using starboard::android::shared::SupportedAudioCodecToMimeType; -SB_EXPORT bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - int64_t bitrate) { +bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate) { // Android now uses libopus based opus decoder. if (audio_codec == kSbMediaAudioCodecOpus && bitrate < SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND) {
diff --git a/src/starboard/android/shared/media_is_supported.cc b/src/starboard/android/shared/media_is_supported.cc index 4dd0d82..26d1e19 100644 --- a/src/starboard/android/shared/media_is_supported.cc +++ b/src/starboard/android/shared/media_is_supported.cc
@@ -17,9 +17,9 @@ #include "starboard/android/shared/jni_env_ext.h" #include "starboard/android/shared/media_common.h" -SB_EXPORT bool SbMediaIsSupported(SbMediaVideoCodec video_codec, - SbMediaAudioCodec audio_codec, - const char* key_system) { +bool SbMediaIsSupported(SbMediaVideoCodec video_codec, + SbMediaAudioCodec audio_codec, + const char* key_system) { using starboard::android::shared::IsWidevineL1; using starboard::android::shared::JniEnvExt; // Filter anything other then aac as we only support paid content on aac.
diff --git a/src/starboard/android/shared/media_is_video_supported.cc b/src/starboard/android/shared/media_is_video_supported.cc index 239130a..15ff35b 100644 --- a/src/starboard/android/shared/media_is_video_supported.cc +++ b/src/starboard/android/shared/media_is_video_supported.cc
@@ -62,18 +62,18 @@ } // namespace -SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, - int frame_width, - int frame_height, - int64_t bitrate, - int fps, - bool decode_to_texture_required) { +bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required) { if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) { if (!IsHDRTransferCharacteristicsSupported(transfer_id)) { return false;
diff --git a/src/starboard/android/shared/player_create.cc b/src/starboard/android/shared/player_create.cc index ffa2260..3682e03 100644 --- a/src/starboard/android/shared/player_create.cc +++ b/src/starboard/android/shared/player_create.cc
@@ -32,9 +32,6 @@ SbPlayer SbPlayerCreate(SbWindow window, SbMediaVideoCodec video_codec, SbMediaAudioCodec audio_codec, -#if SB_API_VERSION < 10 - SbMediaTime duration_pts, -#endif // SB_API_VERSION < 10 SbDrmSystem drm_system, const SbMediaAudioSampleInfo* audio_sample_info, const char* max_video_capabilities, @@ -48,9 +45,6 @@ SB_UNREFERENCED_PARAMETER(window); SB_UNREFERENCED_PARAMETER(max_video_capabilities); SB_UNREFERENCED_PARAMETER(provider); -#if SB_API_VERSION < 10 - SB_UNREFERENCED_PARAMETER(duration_pts); -#endif // SB_API_VERSION < 10 if (!sample_deallocate_func || !decoder_status_func || !player_status_func #if SB_HAS(PLAYER_ERROR_MESSAGE) @@ -76,6 +70,7 @@ if (video_codec != kSbMediaVideoCodecNone && video_codec != kSbMediaVideoCodecH264 && + video_codec != kSbMediaVideoCodecH265 && video_codec != kSbMediaVideoCodecVp9) { SB_LOG(ERROR) << "Unsupported video codec " << video_codec; return kSbPlayerInvalid;
diff --git a/src/starboard/android/shared/speech_synthesis_is_supported.cc b/src/starboard/android/shared/speech_synthesis_is_supported.cc new file mode 100644 index 0000000..1364fbc --- /dev/null +++ b/src/starboard/android/shared/speech_synthesis_is_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/speech_synthesis.h" + +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION + +bool SbSpeechSynthesisIsSupported() { + return true; +} + +#endif
diff --git a/src/starboard/android/shared/starboard_platform.gypi b/src/starboard/android/shared/starboard_platform.gypi index 2401618..ad89435 100644 --- a/src/starboard/android/shared/starboard_platform.gypi +++ b/src/starboard/android/shared/starboard_platform.gypi
@@ -18,6 +18,7 @@ }, 'includes': [ '<(DEPTH)/starboard/shared/starboard/player/filter/player_filter.gypi', + '<(DEPTH)/starboard/stub/blitter_stub_sources.gypi', ], 'targets': [ { @@ -49,6 +50,7 @@ '<(DEPTH)/starboard/android/shared/bionic', ], 'sources': [ + '<@(blitter_stub_sources)', '<@(filter_based_player_sources)', 'accessibility_get_caption_settings.cc', 'accessibility_get_display_settings.cc', @@ -140,6 +142,7 @@ 'sanitizer_options.cc', 'speech_recognizer_impl.cc', 'speech_synthesis_cancel.cc', + 'speech_synthesis_is_supported.cc', 'speech_synthesis_speak.cc', 'system_get_connection_type.cc', 'system_get_device_type.cc', @@ -150,7 +153,6 @@ 'system_has_capability.cc', 'system_platform_error.cc', 'system_request_stop.cc', - 'system_request_suspend.cc', 'thread_create.cc', 'thread_create_priority.cc', 'thread_get_name.cc', @@ -176,6 +178,7 @@ '<(DEPTH)/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc', '<(DEPTH)/starboard/android/shared/window_hide_on_screen_keyboard.cc', '<(DEPTH)/starboard/android/shared/window_is_on_screen_keyboard_shown.cc', + '<(DEPTH)/starboard/android/shared/window_on_screen_keyboard_is_supported.cc', '<(DEPTH)/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc', '<(DEPTH)/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc', '<(DEPTH)/starboard/android/shared/window_show_on_screen_keyboard.cc', @@ -252,6 +255,7 @@ '<(DEPTH)/starboard/shared/opus/opus_audio_decoder.cc', '<(DEPTH)/starboard/shared/opus/opus_audio_decoder.h', '<(DEPTH)/starboard/shared/posix/directory_create.cc', + '<(DEPTH)/starboard/shared/posix/file_atomic_replace.cc', '<(DEPTH)/starboard/shared/posix/impl/file_can_open.h', '<(DEPTH)/starboard/shared/posix/impl/file_close.h', '<(DEPTH)/starboard/shared/posix/impl/file_delete.h', @@ -279,6 +283,7 @@ '<(DEPTH)/starboard/shared/posix/socket_internal.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected_and_idle.cc', + '<(DEPTH)/starboard/shared/posix/socket_is_ipv6_supported.cc', '<(DEPTH)/starboard/shared/posix/socket_join_multicast_group.cc', '<(DEPTH)/starboard/shared/posix/socket_listen.cc', '<(DEPTH)/starboard/shared/posix/socket_receive_from.cc', @@ -306,6 +311,7 @@ '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_now.cc', + '<(DEPTH)/starboard/shared/posix/time_is_time_thread_now_supported.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc', '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc', '<(DEPTH)/starboard/shared/pthread/condition_variable_create.cc', @@ -334,6 +340,7 @@ '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc', '<(DEPTH)/starboard/shared/signal/suspend_signals.cc', '<(DEPTH)/starboard/shared/signal/suspend_signals.h', + '<(DEPTH)/starboard/shared/signal/system_request_suspend.cc', '<(DEPTH)/starboard/shared/starboard/application.cc', '<(DEPTH)/starboard/shared/starboard/application.h', '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc', @@ -355,6 +362,8 @@ '<(DEPTH)/starboard/shared/starboard/drm/drm_update_session.cc', '<(DEPTH)/starboard/shared/starboard/event_cancel.cc', '<(DEPTH)/starboard/shared/starboard/event_schedule.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.h', '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc', @@ -421,6 +430,7 @@ '<(DEPTH)/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc', '<(DEPTH)/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc', '<(DEPTH)/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h', + '<(DEPTH)/starboard/shared/starboard/speech_recognizer/speech_recognizer_is_supported.cc', '<(DEPTH)/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc', '<(DEPTH)/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc', '<(DEPTH)/starboard/shared/starboard/string_concat.cc',
diff --git a/src/starboard/android/shared/window_blur_on_screen_keyboard.cc b/src/starboard/android/shared/window_blur_on_screen_keyboard.cc index fe84c62..88e6107 100644 --- a/src/starboard/android/shared/window_blur_on_screen_keyboard.cc +++ b/src/starboard/android/shared/window_blur_on_screen_keyboard.cc
@@ -14,9 +14,11 @@ #include "starboard/window.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void SbWindowBlurOnScreenKeyboard(SbWindow window, int ticket) { // Stub. return; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_focus_on_screen_keyboard.cc b/src/starboard/android/shared/window_focus_on_screen_keyboard.cc index 00dea03..31fbde3 100644 --- a/src/starboard/android/shared/window_focus_on_screen_keyboard.cc +++ b/src/starboard/android/shared/window_focus_on_screen_keyboard.cc
@@ -14,9 +14,11 @@ #include "starboard/window.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void SbWindowFocusOnScreenKeyboard(SbWindow window, int ticket) { // Stub. return; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc b/src/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc index 90bcf2f..242a2ac 100644 --- a/src/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc +++ b/src/starboard/android/shared/window_get_on_screen_keyboard_bounding_rect.cc
@@ -14,10 +14,12 @@ #include "starboard/window.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) bool SbWindowGetOnScreenKeyboardBoundingRect(SbWindow window, SbWindowRect* bounding_rect) { // Stub. return true; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_hide_on_screen_keyboard.cc b/src/starboard/android/shared/window_hide_on_screen_keyboard.cc index 4ecb6e8..8163e62 100644 --- a/src/starboard/android/shared/window_hide_on_screen_keyboard.cc +++ b/src/starboard/android/shared/window_hide_on_screen_keyboard.cc
@@ -16,10 +16,12 @@ #include "starboard/android/shared/application_android.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void SbWindowHideOnScreenKeyboard(SbWindow window, int ticket) { starboard::android::shared::ApplicationAndroid::Get() ->SbWindowHideOnScreenKeyboard(window, ticket); return; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_is_on_screen_keyboard_shown.cc b/src/starboard/android/shared/window_is_on_screen_keyboard_shown.cc index 7aff011..61f80d2 100644 --- a/src/starboard/android/shared/window_is_on_screen_keyboard_shown.cc +++ b/src/starboard/android/shared/window_is_on_screen_keyboard_shown.cc
@@ -15,14 +15,22 @@ #include "starboard/window.h" #include "starboard/android/shared/jni_env_ext.h" +#include "starboard/android/shared/jni_utils.h" using starboard::android::shared::JniEnvExt; +using starboard::android::shared::ScopedLocalJavaRef; -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) bool SbWindowIsOnScreenKeyboardShown(SbWindow window) { JniEnvExt* env = JniEnvExt::Get(); - jboolean is_keyboard_shown = - env->CallStarboardBooleanMethodOrAbort("isKeyboardShowing", "()Z"); + + ScopedLocalJavaRef<jobject> j_keyboard_editor( + env->CallStarboardObjectMethodOrAbort( + "getKeyboardEditor", "()Ldev/cobalt/coat/KeyboardEditor;")); + jboolean is_keyboard_shown = env->CallBooleanMethodOrAbort( + j_keyboard_editor.Get(), "isKeyboardShowing", "()Z"); return is_keyboard_shown; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_on_screen_keyboard_is_supported.cc b/src/starboard/android/shared/window_on_screen_keyboard_is_supported.cc new file mode 100644 index 0000000..b9eb7e8 --- /dev/null +++ b/src/starboard/android/shared/window_on_screen_keyboard_is_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2018 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +bool SbWindowOnScreenKeyboardIsSupported() { + return false; +} + +#endif
diff --git a/src/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc b/src/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc index 992e15e..b2e51d1 100644 --- a/src/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc +++ b/src/starboard/android/shared/window_on_screen_keyboard_suggestions_supported.cc
@@ -14,10 +14,10 @@ #include "starboard/window.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_API_VERSION >= 11 +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) bool SbWindowOnScreenKeyboardSuggestionsSupported(SbWindow window) { return true; } -#endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc b/src/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc index 24d95eb..c6c08fd 100644 --- a/src/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc +++ b/src/starboard/android/shared/window_set_on_screen_keyboard_keep_focus.cc
@@ -18,7 +18,8 @@ using starboard::android::shared::JniEnvExt; -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void SbWindowSetOnScreenKeyboardKeepFocus(SbWindow window, bool keep_focus) { JniEnvExt* env = JniEnvExt::Get(); jobject j_keyboard_editor = env->CallStarboardObjectMethodOrAbort( @@ -27,4 +28,5 @@ keep_focus); return; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_show_on_screen_keyboard.cc b/src/starboard/android/shared/window_show_on_screen_keyboard.cc index d5be7c8..aa5afee 100644 --- a/src/starboard/android/shared/window_show_on_screen_keyboard.cc +++ b/src/starboard/android/shared/window_show_on_screen_keyboard.cc
@@ -16,7 +16,8 @@ #include "starboard/android/shared/application_android.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void SbWindowShowOnScreenKeyboard(SbWindow window, const char* input_text, int ticket) { @@ -24,4 +25,5 @@ ->SbWindowShowOnScreenKeyboard(window, input_text, ticket); return; } -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/shared/window_update_on_screen_keyboard_suggestions.cc b/src/starboard/android/shared/window_update_on_screen_keyboard_suggestions.cc index 24f0925..86b2c13 100644 --- a/src/starboard/android/shared/window_update_on_screen_keyboard_suggestions.cc +++ b/src/starboard/android/shared/window_update_on_screen_keyboard_suggestions.cc
@@ -16,8 +16,8 @@ #include "starboard/android/shared/application_android.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_API_VERSION >= 11 +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) void SbWindowUpdateOnScreenKeyboardSuggestions(SbWindow window, const char* suggestions[], int num_suggestions, @@ -31,5 +31,5 @@ ticket); return; } -#endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/android/x86/gyp_configuration.py b/src/starboard/android/x86/gyp_configuration.py index f31ab4b..ff02424 100644 --- a/src/starboard/android/x86/gyp_configuration.py +++ b/src/starboard/android/x86/gyp_configuration.py
@@ -17,4 +17,5 @@ def CreatePlatformConfig(): - return shared_configuration.AndroidConfiguration('android-x86', 'x86') + return shared_configuration.AndroidConfiguration( + 'android-x86', 'x86', sabi_json_path='starboard/sabi/ia32/sabi.json')
diff --git a/src/starboard/blitter.h b/src/starboard/blitter.h index 5ddf928..bdbc88c 100644 --- a/src/starboard/blitter.h +++ b/src/starboard/blitter.h
@@ -55,7 +55,7 @@ #include "starboard/types.h" #include "starboard/window.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) #ifdef __cplusplus extern "C" { @@ -304,6 +304,11 @@ return context != kSbBlitterInvalidContext; } +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION +// Returns whether the platform supports blitter. +SB_EXPORT bool SbBlitterIsBlitterSupported(); +#endif + // Creates and returns an |SbBlitterDevice| based on the Blitter API // implementation's decision of which device should be the default. The returned // |SbBlitterDevice| represents a connection to a device (like a GPU). @@ -760,6 +765,7 @@ } // extern "C" #endif -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #endif // STARBOARD_BLITTER_H_
diff --git a/src/starboard/build/base_configuration.gypi b/src/starboard/build/base_configuration.gypi index 1d405d5..38b074f 100644 --- a/src/starboard/build/base_configuration.gypi +++ b/src/starboard/build/base_configuration.gypi
@@ -32,8 +32,9 @@ # a top level scope. 'variables': { 'sb_enable_lib%': 0, - 'sb_static_contents_output_base_dir%': '<(PRODUCT_DIR)/content', + # TODO: Remove the "data" subdirectory. 'sb_static_contents_output_data_dir%': '<(PRODUCT_DIR)/content/data', + 'sb_deploy_output_dir%': '<(PRODUCT_DIR)/deploy', }, # Enables the yasm compiler to be used to compile .asm files. @@ -54,12 +55,14 @@ # are disabled 'sb_disable_microphone_idl%': 0, - # Directory path to static contents. - 'sb_static_contents_output_base_dir%': '<(sb_static_contents_output_base_dir)', - # Directory path to static contents' data. 'sb_static_contents_output_data_dir%': '<(sb_static_contents_output_data_dir)', + # Top-level directory for staging deploy build output. Platform deploy + # actions should use <(target_deploy_dir) defined in deploy.gypi to place + # artifacts for each deploy target in its own subdirectoy. + 'sb_deploy_output_dir%': '<(sb_deploy_output_dir)', + # Contains the name of the hosting OS. The value is defined by the gyp # wrapper script. 'host_os%': 'win',
diff --git a/src/starboard/build/clang.py b/src/starboard/build/clang.py index b47fb18..5e35ed0 100644 --- a/src/starboard/build/clang.py +++ b/src/starboard/build/clang.py
@@ -19,4 +19,4 @@ def GetClangSpecification(): """Gets the ClangSpecification instance for this project.""" - return ClangSpecification('298539-1', '5.0.0') + return ClangSpecification('365097-f7e52fbd-8', '9.0.0')
diff --git a/src/starboard/build/collect_deploy_content.gypi b/src/starboard/build/collect_deploy_content.gypi index 3069675..86848ba 100644 --- a/src/starboard/build/collect_deploy_content.gypi +++ b/src/starboard/build/collect_deploy_content.gypi
@@ -21,9 +21,9 @@ { 'variables': { # Root of the content tree that should be deployed with a given target. - 'content_deploy_dir': '<(sb_static_contents_output_base_dir)/deploy/<(executable_name)', + 'content_deploy_dir': '<(target_deploy_dir)/content', - # Stamp file that will be updated after the symlink farm is built. + # Stamp file that will be updated after the content symlink farm is built. 'content_deploy_stamp_file': '<(content_deploy_dir).stamp', # This is a list of relative paths within both input_dir and output_dir, @@ -53,8 +53,12 @@ 'input_dir': '<(sb_static_contents_output_data_dir)', 'output_dir': '<(content_deploy_dir)', }, - # Re-collect the content whenever the executable is rebuilt. - 'inputs': [ '<(executable_file)'], + # Re-collect the content whenever the executable is rebuilt, but wait until + # cleaning the deploy dir is done. + 'inputs': [ + '<(executable_file)', + '<(target_deploy_stamp_file)', + ], 'outputs': [ '<(content_deploy_stamp_file)' ], 'action': [ 'python', @@ -65,6 +69,6 @@ '<@(collect_deploy_content_extra_args)', '>@(content_deploy_subdirs)', ], - 'message': 'Collect content: <(executable_name)', + 'message': 'Collect content: <(content_deploy_dir)', }], }
diff --git a/src/starboard/build/collect_deploy_content.py b/src/starboard/build/collect_deploy_content.py index be07a5e..9f97896 100644 --- a/src/starboard/build/collect_deploy_content.py +++ b/src/starboard/build/collect_deploy_content.py
@@ -22,7 +22,7 @@ import sys import _env # pylint: disable=unused-import -import starboard.build.port_symlink as port_symlink +import starboard.tools.port_symlink as port_symlink # The name of an environment variable that when set to |'1'|, signals to us that
diff --git a/src/starboard/build/config/base.gni b/src/starboard/build/config/base.gni index 1b2a23a..41e0b08 100644 --- a/src/starboard/build/config/base.gni +++ b/src/starboard/build/config/base.gni
@@ -23,11 +23,6 @@ sb_enable_lib = false } -# Directory path to static contents. -if (!defined(sb_static_contents_output_base_dir)) { - sb_static_contents_output_base_dir = "$root_out_dir/content" -} - # Directory path to static contents' data. if (!defined(sb_static_contents_output_data_dir)) { sb_static_contents_output_data_dir = "$root_out_dir/content/data"
diff --git a/src/starboard/build/convert_i18n_data.gypi b/src/starboard/build/convert_i18n_data.gypi index 97aad81..695d49b 100644 --- a/src/starboard/build/convert_i18n_data.gypi +++ b/src/starboard/build/convert_i18n_data.gypi
@@ -27,7 +27,7 @@ { 'variables': { - 'output_dir': '<(sb_static_contents_output_base_dir)/data/i18n' + 'output_dir': '<(sb_static_contents_output_data_dir)/i18n' }, 'targets': [ {
diff --git a/src/starboard/build/deploy.gypi b/src/starboard/build/deploy.gypi index d074f37..450e280 100644 --- a/src/starboard/build/deploy.gypi +++ b/src/starboard/build/deploy.gypi
@@ -56,12 +56,41 @@ { - # Flag that will instruct gyp to create a special target in IDEs such as - # Visual Studio that can be used for launching a target. 'variables' : { + # Flag that will instruct gyp to create a special target in IDEs such as + # Visual Studio that can be used for launching a target. 'ide_deploy_target': 1, + + # Directory in which the platform deploy action should stage its results + # to to separate them from other targets. + 'target_deploy_dir': '<(sb_deploy_output_dir)/<(executable_name)', + + # Stamp file that will be updated after the deploy dir is created/cleaned. + 'target_deploy_stamp_file': '<(target_deploy_dir).stamp', + + 'make_dirs': '<(DEPTH)/starboard/build/make_dirs.py', }, + 'actions': [ + { + 'action_name': 'clean_deploy_dir', + 'message': 'Clean deploy dir: <(target_deploy_dir)', + 'inputs': [ + '<(make_dirs)', + ], + 'outputs': [ + '<(target_deploy_stamp_file)', + ], + 'action': [ + 'python', + '<(make_dirs)', + '--clean', + '--stamp=<(target_deploy_stamp_file)', + '<(target_deploy_dir)', + ], + }, + ], + # Include the platform specific gypi file include. Note that the # expanded value will default to # "starboard/build/default_no_deploy.gypi"
diff --git a/src/starboard/build/filelist.py b/src/starboard/build/filelist.py deleted file mode 100644 index c42f2f9..0000000 --- a/src/starboard/build/filelist.py +++ /dev/null
@@ -1,155 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""A utility for generating a file list. - -Each entry in the FileList contains the file path and a path relative to the -root directory that can be used for creating archives. - -""" - -import logging -import os - -import _env # pylint: disable=relative-import,unused-import - -from starboard.build import port_symlink - - -class FileList(object): - """Makes it easy to include files for things like archive operations.""" - - def __init__(self): - self.file_list = [] # List of (file_path, archive_path) - self.symlink_dir_list = [] # List of (file_path, link_path, target_path) - - def AddAllFilesInPath(self, root_dir, sub_path): - """Starting at the root path, the sub_paths are searched for files.""" - all_files = [] - all_symlinks = [] - if os.path.isfile(sub_path): - self.AddFile(root_dir, sub_path) - elif not os.path.isdir(sub_path): - raise IOError('Expected root directory to exist: %s' % sub_path) - cwd = os.getcwd() - for root, dirs, files in port_symlink.OsWalk(sub_path): - # Do not use os.path.abspath as it does not work on Win for long paths. - if not os.path.isabs(root): - root = os.path.join(cwd, root) - for f in files: - full_path = os.path.join(root, f) - all_files.append(full_path) - for dir_name in dirs: - full_path = os.path.join(root, dir_name) - if port_symlink.IsSymLink(full_path): - all_symlinks.append(full_path) - for f in all_files + all_symlinks: - self.AddFile(root_dir, f) - - def AddAllFilesInPaths(self, root_dir, sub_paths): - if not os.path.isdir(root_dir): - raise IOError('Expected root directory to exist: ' + str(root_dir)) - for p in sub_paths: - self.AddAllFilesInPath(root_dir=root_dir, sub_path=p) - - def AddFile(self, root_path, file_path): - if port_symlink.IsSymLink(file_path): - self.AddSymLink(root_path, file_path) - else: - archive_name = _OsGetRelpath(file_path, root_path) - self.file_list.append([file_path, archive_name]) - - def AddSymLink(self, relative_dir, link_file): - rel_link_path = _OsGetRelpath(link_file, relative_dir) - target_path = _ResolveSymLink(link_file) - assert os.path.exists(target_path) - rel_target_path = _OsGetRelpath(target_path, relative_dir) - self.symlink_dir_list.append([relative_dir, rel_link_path, rel_target_path]) - - def Print(self): - for f in self.file_list: - print 'File: %s' % f - for s in self.symlink_dir_list: - print 'Symlink: %s' % s - - -def _ResolveSymLink(link_file): - """Returns the absolute path of the resolved link. This path should exist.""" - target_path = port_symlink.ReadSymLink(link_file) - if os.path.isabs(target_path): # Absolute path - assert os.path.exists(target_path), ( - 'Path {} does not exist.'.format(target_path)) - return target_path - else: # Relative path from link_file. - abs_path = os.path.normpath( - os.path.join(os.path.dirname(link_file), target_path)) - assert os.path.exists(abs_path), ( - 'Path {} does not exist (link file: {}, target_path: {})'.format( - abs_path, link_file, target_path)) - return abs_path - - -def _FallbackOsGetRelPath(path, start_dir): - path = os.path.normpath(path) - start_dir = os.path.normpath(start_dir) - common_prefix = os.path.commonprefix([path, start_dir]) - split_list = common_prefix.split(os.sep) - path_parts = path.split(os.sep) - for _ in range(len(split_list)): - path_parts = path_parts[1:] - return os.path.normpath(os.path.join(*path_parts)) - - -def _OsGetRelpath(path, start_dir): - path = os.path.normpath(path) - start_dir = os.path.normpath(start_dir) - # Use absolute paths for Windows (nt paths checks the drive specifier). - # Do not use os.path.abspath as it does not work on Win for long paths. - if not os.path.isabs(path): - path = os.path.join(os.getcwd(), path) - if not os.path.isabs(start_dir): - start_dir = os.path.join(os.getcwd(), start_dir) - try: - return os.path.relpath(path, start_dir) - except ValueError: - try: - # Do a string comparison to get relative path. - rel_path = _FallbackOsGetRelPath(path, start_dir) - if not os.path.exists(os.path.join(start_dir, rel_path)): - raise ValueError('%s does not exist.' % os.path.abspath(rel_path)) - return rel_path - except ValueError as err: - logging.exception('Error %s while calling os.path.relpath(%s, %s)', - err, path, start_dir) - - -TYPE_NONE = 'NONE' -TYPE_SYMLINK_DIR = 'SYMLINK DIR' -TYPE_DIRECTORY = 'DIR' -TYPE_FILE = 'FILE' - - -def GetFileType(f): - if not os.path.exists(f): - return TYPE_NONE - elif port_symlink.IsSymLink(f): - return TYPE_SYMLINK_DIR - elif os.path.isdir(f): - return TYPE_DIRECTORY - else: - assert os.path.isfile(f) - return TYPE_FILE
diff --git a/src/starboard/build/filelist_test.py b/src/starboard/build/filelist_test.py deleted file mode 100644 index 34fc71b..0000000 --- a/src/starboard/build/filelist_test.py +++ /dev/null
@@ -1,189 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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 os -import tempfile -import unittest - -import _env # pylint: disable=relative-import,unused-import - -from cobalt.build import cobalt_archive_extract -from starboard.build import filelist -from starboard.build import port_symlink -from starboard.tools import util - - -LONG_DIR_NAME_1 = 'really_l' + 'o' * 120 + 'ng_dir_name' -LONG_DIR_NAME_2 = 'another_really_l' + 'o' * 120 + 'ng_dir_name' -LONG_SUB_DIRS = os.path.join(LONG_DIR_NAME_1, LONG_DIR_NAME_2) - - -def _MakeDirs(path): - if not os.path.isdir(path): - os.makedirs(path) - - -class TempFileSystem(object): - """Generates a test file structure with file/dir/symlink for testing. - - <temp_dir> - |-> <root_sub_dir> - | |-> in - | | |-> from_dir - | | | |-> test.txt - | | |-> from_dir_lnk -> <temp_dir>/<root_sub_dir>/in/from_dir - """ - - def __init__(self, root_sub_dir='bundler'): - root_sub_dir = os.path.normpath(root_sub_dir) - self.root_tmp = os.path.join(tempfile.gettempdir(), root_sub_dir) - if os.path.exists(self.root_tmp): - port_symlink.Rmtree(self.root_tmp) - self.root_in_tmp = os.path.join(self.root_tmp, 'in') - self.sym_dir = os.path.join(self.root_in_tmp, 'from_dir_lnk') - self.from_dir = os.path.join(self.root_in_tmp, 'from_dir') - self.test_txt = os.path.join(self.from_dir, 'test.txt') - - def Make(self): - _MakeDirs(self.root_in_tmp) - _MakeDirs(os.path.dirname(self.test_txt)) - port_symlink.MakeSymLink(self.from_dir, self.sym_dir) - with open(self.test_txt, 'w') as fd: - fd.write('TEST') - - def MakeLongPathFile(self): - long_path_txt = os.path.join(self.from_dir, LONG_SUB_DIRS, 'test2.txt') - self.long_path_txt = long_path_txt - if port_symlink.IsWindows(): - long_path_txt = cobalt_archive_extract.ToWinUncPath(long_path_txt) - _MakeDirs(os.path.dirname(long_path_txt)) - with open(long_path_txt, 'w') as fd: - fd.write('TEST BIS') - - def Clear(self): - port_symlink.Rmtree(self.root_tmp) - - def Print(self): - def P(f): - t = filelist.GetFileType(f) - print '{:<13} {}'.format(t, f) - P(self.root_tmp) - P(self.root_in_tmp) - P(self.test_txt) - P(self.from_dir) - P(self.sym_dir) - - -class FileListTest(unittest.TestCase): - - def testTempFileSystem(self): - """Sanity test to ensure TempFileSystem works correctly on the platform.""" - tf = TempFileSystem() - tf.Clear() - self.assertEqual(filelist.GetFileType(tf.sym_dir), filelist.TYPE_NONE) - self.assertEqual(filelist.GetFileType(tf.root_tmp), filelist.TYPE_NONE) - self.assertEqual(filelist.GetFileType(tf.root_in_tmp), filelist.TYPE_NONE) - self.assertEqual(filelist.GetFileType(tf.from_dir), filelist.TYPE_NONE) - self.assertEqual(filelist.GetFileType(tf.test_txt), filelist.TYPE_NONE) - tf.Make() - self.assertEqual(filelist.GetFileType(tf.sym_dir), - filelist.TYPE_SYMLINK_DIR) - self.assertEqual(filelist.GetFileType(tf.root_tmp), filelist.TYPE_DIRECTORY) - self.assertEqual(filelist.GetFileType(tf.root_in_tmp), - filelist.TYPE_DIRECTORY) - self.assertEqual(filelist.GetFileType(tf.from_dir), filelist.TYPE_DIRECTORY) - self.assertEqual(filelist.GetFileType(tf.test_txt), filelist.TYPE_FILE) - tf.Clear() - self.assertEqual(filelist.GetFileType(tf.sym_dir), filelist.TYPE_NONE) - self.assertEqual(filelist.GetFileType(tf.root_tmp), filelist.TYPE_NONE) - self.assertEqual(filelist.GetFileType(tf.root_in_tmp), filelist.TYPE_NONE) - self.assertEqual(filelist.GetFileType(tf.from_dir), filelist.TYPE_NONE) - self.assertEqual(filelist.GetFileType(tf.test_txt), filelist.TYPE_NONE) - - def testAddFile(self): - flist = filelist.FileList() - flist.AddFile(root_path=r'd1/d2', file_path=r'd1/d2/test.txt') - self.assertEqual(flist.file_list, [['d1/d2/test.txt', 'test.txt']]) - - def testAddAllFilesInPath(self): - tf = TempFileSystem() - tf.Make() - tf.MakeLongPathFile() - flist = filelist.FileList() - flist.AddAllFilesInPath(tf.root_in_tmp, tf.root_in_tmp) - self.assertTrue(flist.symlink_dir_list) - expected_file_list = [ - [tf.test_txt, os.path.join('from_dir', 'test.txt')], - [tf.long_path_txt, - os.path.join('from_dir', LONG_SUB_DIRS , 'test2.txt')]] - self.assertEqual(flist.file_list, expected_file_list) - - def testAddSymlink(self): - tf = TempFileSystem() - tf.Make() - flist = filelist.FileList() - flist.AddFile(tf.root_tmp, tf.sym_dir) - flist.Print() - self.assertTrue(flist.symlink_dir_list) - self.assertFalse(flist.file_list) - - def testAddRelativeSymlink(self): - """Tests that adding a relative symlink works as expected.""" - tf = TempFileSystem() - tf.Make() - flist = filelist.FileList() - in2 = os.path.join(tf.root_in_tmp, 'subdir', 'in2') - target_path = os.path.relpath(tf.from_dir, os.path.dirname(in2)) - # Sanity check that target_path is relative. - self.assertEqual(target_path, os.path.join('..', 'from_dir')) - # Create the link and check that it points to the correct folder. - port_symlink.MakeSymLink(target_path, in2) - self.assertTrue(port_symlink.IsSymLink(in2)) - self.assertEqual(port_symlink.ReadSymLink(in2), target_path) - self.assertEqual(os.listdir(in2), ['test.txt']) - # Add the symlink to flist and check its content. - flist.AddFile(tf.root_tmp, in2) - flist.Print() - self.assertTrue(flist.symlink_dir_list) - expected = [ - tf.root_tmp, - os.path.join('in', 'subdir', 'in2'), - os.path.join('in', 'from_dir')] - self.assertEqual(flist.symlink_dir_list[0], expected) - - def testOsGetRelpathFallback(self): - path = ( - 'src/out/tmp/cobalt_archive/archive/____app_launcher/third_party/' - 'web_platform_tests/custom-elements/registering-custom-elements/' - 'unresolved-element-pseudoclass/' - 'unresolved-element-pseudoclass-css-test-registered-type-extension-ref' - '.html').replace('/', os.sep) - root = ( - 'src/out/tmp/cobalt_archive/archive/____app_launcher' - ).replace('/', os.sep) - expected_result = ( - 'third_party/web_platform_tests/custom-elements/' - 'registering-custom-elements/unresolved-element-pseudoclass/' - 'unresolved-element-pseudoclass-css-test-registered-type-extension-ref' - '.html').replace('/', os.sep) - rel_path = filelist._FallbackOsGetRelPath(path, start_dir=root) - self.assertEqual(expected_result, rel_path) - - -if __name__ == '__main__': - util.SetupDefaultLoggingConfig() - unittest.main(verbosity=2)
diff --git a/src/starboard/build/make_dirs.py b/src/starboard/build/make_dirs.py new file mode 100755 index 0000000..f777c03 --- /dev/null +++ b/src/starboard/build/make_dirs.py
@@ -0,0 +1,49 @@ +#!/usr/bin/python +# Copyright 2019 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. +"""Ensures a directory exists, similar to 'mkdir -p'.""" + +import argparse +import os +import sys + +import _env # pylint: disable=unused-import, relative-import +from starboard.tools import port_symlink + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '-c', '--clean', + action='store_true', + help='Delete the contents of any existing directory.') + parser.add_argument( + '-s', '--stamp_file', + type=str, + help='Path to the stamp file to touch after making the directory.') + parser.add_argument('directory', help='Path to the directory to be created.') + arguments = parser.parse_args() + + if arguments.clean: + port_symlink.Rmtree(arguments.directory) + + if not os.path.isdir(arguments.directory): + os.makedirs(arguments.directory) + + if arguments.stamp_file: + open(arguments.stamp_file, 'a').close() + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/src/starboard/build/platform_configuration.py b/src/starboard/build/platform_configuration.py index 9cd2ac1..6372476 100644 --- a/src/starboard/build/platform_configuration.py +++ b/src/starboard/build/platform_configuration.py
@@ -207,25 +207,49 @@ """ use_asan = 0 use_tsan = 0 - if use_clang: - use_tsan = int(os.environ.get('USE_TSAN', 0)) - # Enable ASAN by default for debug and devel builds only if USE_TSAN was - # not set to 1 in the environment. - use_asan_default = self._asan_default if not use_tsan and config_name in ( - Config.DEBUG, Config.DEVEL) else 0 - use_asan = int(os.environ.get('USE_ASAN', use_asan_default)) + use_source_code_coverage = 0 + sabi_json_path = self.GetPathToSabiJsonFile() + if use_clang: + # Enable source coverage instrumentation if USE_SOURCE_CODE_COVERAGE + # was set to 1 in the environment. + use_source_code_coverage = int( + os.environ.get('USE_SOURCE_CODE_COVERAGE', 0)) + + # Enable TSAN if USE_TSAN was set to 1 in the environment, unless + # use_source_code_coverage is set. + use_tsan = int(os.environ.get('USE_TSAN', + 0)) if not use_source_code_coverage else 0 + + # Enable ASAN by default for debug and devel builds only if neither + # use_tsan nor use_source_code_coverage is set. + use_asan_default = self._asan_default if ( + not use_tsan and not use_source_code_coverage and + config_name in (Config.DEBUG, Config.DEVEL)) else 0 + use_asan = int(os.environ.get('USE_ASAN', use_asan_default)) if use_asan == 1 and use_tsan == 1: raise RuntimeError('ASAN and TSAN are mutually exclusive') + if use_source_code_coverage: + logging.info('Using Source-Based Code Coverage') + if use_asan: logging.info('Using Address Sanitizer') if use_tsan: logging.info('Using Thread Sanitizer') + if not sabi_json_path: + sabi_json_path = 'starboard/sabi/default/sabi.json' + variables = { 'clang': use_clang, + + # Whether to build with clang's Source Based Code Coverage + # instrumentation. + # See https://clang.llvm.org/docs/SourceBasedCodeCoverage.html + 'use_source_code_coverage': use_source_code_coverage, + # Whether to build with clang's Address Sanitizer instrumentation. 'use_asan': use_asan, # Whether to build with clang's Thread Sanitizer instrumentation. @@ -243,6 +267,7 @@ # requires JIT, or 1 on a platform that does not support JIT, is a # usage error. 'cobalt_enable_jit': 1, + 'sabi_json_path': sabi_json_path, # TODO: Remove these compatibility variables. 'cobalt_config': config_name, @@ -321,19 +346,32 @@ """ raise NotImplementedError() + def GetPathToSabiJsonFile(self): + """Gets the path to the JSON file with Starboard ABI information for the build. + + Returns: + A string path to the appropriate Starboard ABI JSON file. This file is + required for a variety of definitions and variables pertaining to the ABI. + """ + return None + def GetTestTargets(self): """Gets all tests to be run in a unit test run. Returns: A list of strings of test target names. """ - return [ - 'elf_loader_test', + tests = [ 'nplb', 'nplb_blitter_pixel_tests', 'player_filter_tests', 'starboard_platform_tests', ] + if os.path.exists(os.path.join(paths.STARBOARD_ROOT, 'elf_loader')): + tests.append('elf_loader_test') + if os.path.exists(os.path.join(paths.STARBOARD_ROOT, 'loader_app')): + tests.append('installation_manager_test') + return tests def GetDefaultTargetBuildFile(self): """Gets the build file to build by default."""
diff --git a/src/starboard/build/port_symlink.py b/src/starboard/build/port_symlink.py deleted file mode 100644 index ec9f46c..0000000 --- a/src/starboard/build/port_symlink.py +++ /dev/null
@@ -1,194 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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. - - -"""A portable interface for symlinking.""" - - -import argparse -import logging -import os -import shutil -import sys - -import _env # pylint: disable=relative-import,unused-import - -from starboard.tools import util - - -################################################################################ -# API # -################################################################################ - - -def IsWindows(): - return _IsWindows() - - -# Platform neutral version os os.path.islink() -def IsSymLink(path): - return _IsSymLink(path=path) - - -def MakeSymLink(from_folder, link_folder): - """Makes a symlink. - - Args: - from_folder: Path to the actual folder - link_folder: Path to the link - - Returns: - None - """ - _MakeSymLink(from_folder=from_folder, link_folder=link_folder) - - -def ReadSymLink(link_path): - return _ReadSymLink(link_path=link_path) - - -def DelSymLink(link_path): - return _DelSymLink(link_path=link_path) - - -def Rmtree(path): - return _Rmtree(path=path) - - -def OsWalk(root_dir, topdown=True, onerror=None, followlinks=False): - return _OsWalk(root_dir=root_dir, - topdown=topdown, - onerror=onerror, - followlinks=followlinks) - - -################################################################################ -# IMPL # -################################################################################ - - -def _IsWindows(): - return sys.platform in ['win32', 'cygwin'] - - -def _IsSymLink(path): - if _IsWindows(): - # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink - return win_symlink.IsReparsePoint(path) - else: - return os.path.islink(path) - - -def _MakeSymLink(from_folder, link_folder): - if _IsWindows(): - # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink - win_symlink.CreateReparsePoint(from_folder, link_folder) - else: - util.MakeDirs(os.path.dirname(link_folder)) - os.symlink(from_folder, link_folder) - - -def _ReadSymLink(link_path): - """Returns the path (abs. or rel.) to the folder referred to by link_path.""" - if IsWindows(): - # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink - path = win_symlink.ReadReparsePoint(link_path) - else: - try: - path = os.readlink(link_path) - except OSError: - path = None - return path - - -def _DelSymLink(link_path): - if IsWindows(): - # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink - win_symlink.UnlinkReparsePoint(link_path) - else: - os.unlink(link_path) - - -def _Rmtree(path): - """See Rmtree() for documentation of this function.""" - if not os.path.exists(path): - return - if _IsWindows(): - # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink - win_symlink.RmtreeShallow(path) - else: - if os.path.islink(path): - os.unlink(path) - else: - shutil.rmtree(path) - - -def _OsWalk(root_dir, topdown=True, onerror=None, followlinks=False): - if IsWindows(): - # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink - return win_symlink.OsWalk(root_dir, topdown, onerror, followlinks) - else: - return os.walk(root_dir, topdown, onerror, followlinks) - - -def _CreateArgumentParser(): - """Creates an argument parser for port_symlink.""" - - class MyParser(argparse.ArgumentParser): - - def error(self, message): - sys.stderr.write('error: %s\n' % message) - self.print_help() - sys.exit(2) - help_msg = ( - 'Example 1:\n' - ' python port_link.py --link "actual_folder_path" "link_path"\n\n' - 'Example 2:\n' - ' python port_link.py --link "../actual_folder_path" "link_path"\n\n') - # Enables new lines in the description and epilog. - formatter_class = argparse.RawDescriptionHelpFormatter - parser = MyParser(epilog=help_msg, formatter_class=formatter_class) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('--link', - help='Issues an scp command to upload src to remote_dst', - metavar='"path"', - nargs=2) - return parser - - -def main(): - util.SetupDefaultLoggingConfig() - parser = _CreateArgumentParser() - args = parser.parse_args() - - folder_path, link_path = args.link - if '.' in folder_path: - d1 = os.path.abspath(folder_path) - else: - d1 = os.path.abspath(os.path.join(link_path, folder_path)) - if not os.path.isdir(d1): - logging.warning('%s is not a directory.', d1) - MakeSymLink(from_folder=folder_path, link_folder=link_path) - - -if __name__ == '__main__': - main()
diff --git a/src/starboard/build/port_symlink_test.py b/src/starboard/build/port_symlink_test.py deleted file mode 100644 index 8831e64..0000000 --- a/src/starboard/build/port_symlink_test.py +++ /dev/null
@@ -1,189 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 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 os -import shutil -import tempfile -import unittest - -import _env # pylint: disable=relative-import,unused-import - -from starboard.build import port_symlink -from starboard.tools import util - - -# Replace this function signature for other implementations of symlink -# functions. -def MakeSymLink(*args, **kwargs): - return port_symlink.MakeSymLink(*args, **kwargs) - - -def IsSymLink(*args, **kwargs): - return port_symlink.IsSymLink(*args, **kwargs) - - -def ReadSymLink(*args, **kwargs): - return port_symlink.ReadSymLink(*args, **kwargs) - - -def Rmtree(*args, **kwargs): - return port_symlink.Rmtree(*args, **kwargs) - - -def OsWalk(*args, **kwargs): - return port_symlink.OsWalk(*args, **kwargs) - - -class PortSymlinkTest(unittest.TestCase): - - def setUp(self): - super(PortSymlinkTest, self).setUp() - self.tmp_dir = os.path.join(tempfile.gettempdir(), 'port_symlink') - if os.path.exists(self.tmp_dir): - Rmtree(self.tmp_dir) - self.from_dir = os.path.join(self.tmp_dir, 'from_dir') - self.test_txt = os.path.join(self.from_dir, 'test.txt') - self.inner_dir = os.path.join(self.from_dir, 'inner_dir') - self.link_dir = os.path.join(self.tmp_dir, 'link') - _MakeDirs(self.tmp_dir) - _MakeDirs(self.from_dir) - _MakeDirs(self.inner_dir) - MakeSymLink(self.from_dir, self.link_dir) - with open(self.test_txt, 'w') as fd: - fd.write('hello world') - - def tearDown(self): - Rmtree(self.tmp_dir) - super(PortSymlinkTest, self).tearDown() - - def testSanity(self): - self.assertTrue(os.path.isdir(self.tmp_dir)) - self.assertTrue(os.path.isdir(self.from_dir)) - self.assertTrue(os.path.isdir(self.inner_dir)) - - def testReadSymlinkNormalDirectory(self): - self.assertIsNone(ReadSymLink(self.from_dir)) - - def testReadSymlinkNormalFile(self): - self.assertIsNone(ReadSymLink(self.test_txt)) - - def testSymlinkDir(self): - self.assertTrue(os.path.exists(self.link_dir)) - self.assertTrue(IsSymLink(self.link_dir)) - from_dir_2 = ReadSymLink(self.link_dir) - self.assertTrue(_IsSamePath(from_dir_2, self.from_dir)) - - def testRelativeSymlinkDir(self): - rel_link_dir = os.path.join(self.tmp_dir, 'foo', 'rel_link') - rel_dir_path = os.path.relpath(self.from_dir, rel_link_dir) - MakeSymLink(rel_dir_path, rel_link_dir) - self.assertTrue(IsSymLink(rel_link_dir)) - link_value = ReadSymLink(rel_link_dir) - self.assertIn('..', link_value, - msg='Expected ".." in relative path %s' % link_value) - - def testDelSymlink(self): - link_dir2 = os.path.join(self.tmp_dir, 'link2') - MakeSymLink(self.from_dir, link_dir2) - self.assertTrue(IsSymLink(link_dir2)) - port_symlink.DelSymLink(link_dir2) - self.assertFalse(os.path.exists(link_dir2)) - - def testRmtreeRemovesLink(self): - Rmtree(self.link_dir) - self.assertFalse(os.path.exists(self.link_dir)) - self.assertTrue(os.path.exists(self.from_dir)) - - def testRmtreeDoesNotFollowSymlinks(self): - """Tests that Rmtree(...) will delete the symlink and not the target.""" - external_temp_dir = tempfile.mkdtemp() - try: - external_temp_file = os.path.join(external_temp_dir, 'test.txt') - with open(external_temp_file, 'w') as fd: - fd.write('HI') - link_dir = os.path.join(self.tmp_dir, 'foo', 'link_dir') - MakeSymLink(external_temp_file, link_dir) - Rmtree(self.tmp_dir) - # The target file should still exist - self.assertTrue(os.path.isfile(external_temp_file)) - finally: - shutil.rmtree(external_temp_file, ignore_errors=True) - - def testOsWalk(self): - paths_nofollow_links = _GetAllPaths(self.tmp_dir, followlinks=False) - paths_follow_links = _GetAllPaths(self.tmp_dir, followlinks=True) - print '\nOsWalk Follow links:' - for path in paths_follow_links: - print ' ' + path + ' (' + _PathTypeToString(path) + ')' - print '\nOsWalk No-Follow links:' - for path in paths_nofollow_links: - print ' ' + path + ' (' + _PathTypeToString(path) + ')' - print '' - self.assertIn(self.link_dir, paths_nofollow_links) - self.assertIn(self.link_dir, paths_follow_links) - self.assertIn(os.path.join(self.link_dir, 'test.txt'), - paths_follow_links) - self.assertNotIn(os.path.join(self.link_dir, 'test.txt'), - paths_nofollow_links) - - -def _MakeDirs(path): - if not os.path.isdir(path): - os.makedirs(path) - - -def _PathTypeToString(path): - if IsSymLink(path): - return 'link' - if os.path.isdir(path): - return 'dir' - return 'file' - - -def _GetAllPaths(start_dir, followlinks): - paths = [] - for root, dirs, files in OsWalk(start_dir, followlinks=followlinks): - for name in files: - path = os.path.join(root, name) - paths.append(path) - for name in dirs: - path = os.path.join(root, name) - paths.append(path) - return paths - - -def _IsSamePath(p1, p2): - if not p1: - p1 = None - if not p2: - p2 = None - if p1 == p2: - return True - if (not p1) or (not p2): - return False - p1 = os.path.abspath(os.path.normpath(p1)) - p2 = os.path.abspath(os.path.normpath(p2)) - if p1 == p2: - return True - try: - return os.stat(p1) == os.stat(p2) - except Exception: # pylint: disable=broad-except - return False - - -if __name__ == '__main__': - util.SetupDefaultLoggingConfig() - unittest.main(verbosity=2)
diff --git a/src/starboard/build/win_symlink.py b/src/starboard/build/win_symlink.py deleted file mode 100644 index 1992561..0000000 --- a/src/starboard/build/win_symlink.py +++ /dev/null
@@ -1,308 +0,0 @@ -#!/usr/bin/python -# Copyright 2018 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. - -"""Provides functions for symlinking on Windows. - -Reparse points: Are os-level symlinks for folders which can be created without -admin access. Symlinks for folders are supported using this mechanism. Note -that reparse points require special care for traversal, because reparse points -are often skipped or treated as files by the various python path manipulation -functions in os and shutil modules. rmtree() as a replacement for -shutil.rmtree() is provided. - -""" - -import logging -import os -import shutil -import stat -import subprocess -import time - -from cobalt.build import cobalt_archive_extract - - -################################################################################ -# API # -################################################################################ - - -def CreateReparsePoint(from_folder, link_folder): - """Mimics os.symlink for usage. - - Args: - from_folder: Path of target directory. - link_folder: Path to create link. - - Returns: - None. - - Raises: - OSError if link cannot be created - """ - return _CreateReparsePoint(from_folder, link_folder) - - -def ReadReparsePoint(path): - """Mimics os.readlink for usage.""" - return _ReadReparsePoint(path) - - -def IsReparsePoint(path): - """Mimics os.islink for usage.""" - return _IsReparsePoint(path) - - -def UnlinkReparsePoint(link_dir): - """Mimics os.unlink for usage. The sym link_dir is removed.""" - return _UnlinkReparsePoint(link_dir) - - -def RmtreeShallow(dirpath): - """Emulates shutil.rmtree on linux. - - Will delete symlinks but doesn't follow them. Note that shutil.rmtree on - windows will follow the symlink and delete the files in the original - directory! - - Args: - dirpath: The start path to delete files. - """ - return _RmtreeShallow(dirpath) - - -def OsWalk(top, topdown=True, onerror=None, followlinks=False): - """Emulates os.walk() on linux. - - Args: - top: see os.walk(...) - topdown: see os.walk(...) - onerror: see os.walk(...) - followlinks: see os.walk(...) - - Returns: - see os.walk(...) - - Correctly handles windows reparse points as symlinks. - All symlink directories are returned in the directory list and the caller must - call IsReparsePoint() on the path to determine whether the directory is - real or a symlink. - """ - return _OsWalk(top, topdown, onerror, followlinks) - - -################################################################################ -# IMPL # -################################################################################ - - -_RETRY_TIMES = 10 - - -def _RemoveEmptyDirectory(path): - """Removes a directory with retry amounts.""" - for i in range(0, _RETRY_TIMES): - try: - os.chmod(path, stat.S_IWRITE) - os.rmdir(path) - return - except Exception: # pylint: disable=broad-except - if i == _RETRY_TIMES-1: - raise - else: - time.sleep(.1) - - -def _RmtreeOsWalk(root_dir): - """Walks the directory structure to delete directories and files.""" - del_dirs = [] # Defer deletion of directories. - if _IsReparsePoint(root_dir): - _UnlinkReparsePoint(root_dir) - return - for root, dirs, files in OsWalk(root_dir, followlinks=False): - for name in files: - path = os.path.join(root, name) - os.remove(path) - for name in dirs: - path = os.path.join(root, name) - if _IsReparsePoint(path): - _UnlinkReparsePoint(path) - else: - del_dirs.append(path) - # At this point, all files should be deleted and all symlinks should be - # unlinked. - for d in del_dirs + [root_dir]: - try: - if os.path.isdir(d): - shutil.rmtree(d) - except Exception as err: # pylint: disable=broad-except - logging.exception('Error while deleting: %s', err) - - -def _RmtreeShellCmd(root_dir): - subprocess.call(['cmd', '/c', 'rmdir', '/S', '/Q', root_dir]) - - -def _RmtreeShallow(root_dir): - """See RmtreeShallow() for documentation.""" - try: - # This can fail if there are very long file names. - _RmtreeOsWalk(root_dir) - except OSError: - # This fallback will handle very long file. Note that it is VERY slow - # in comparison to the _RmtreeOsWalk() version. - _RmtreeShellCmd(root_dir) - if os.path.isdir(root_dir): - logging.error('Directory %s still exists.', root_dir) - - -def _ReadReparsePointShell(path): - """Implements reading a reparse point via a shell command.""" - cmd_parts = ['fsutil', 'reparsepoint', 'query', path] - try: - out = subprocess.check_output(cmd_parts) - except subprocess.CalledProcessError: - # Expected if the link doesn't exist. - return None - try: - lines = out.splitlines() - lines = [l for l in lines if 'Print Name:' in l] - if not lines: - return None - out = lines[0].split() - return out[2] - except Exception as err: # pylint: disable=broad-except - logging.exception(err) - return None - - -def _ReadReparsePoint(path): - try: - # pylint: disable=g-import-not-at-top - import win_symlink_fast - return win_symlink_fast.FastReadReparseLink(path) - except Exception as err: # pylint: disable=broad-except - logging.exception(' error: %s, falling back to command line version.', err) - return _ReadReparsePointShell(path) - - -def _IsReparsePoint(path): - try: - # pylint: disable=g-import-not-at-top - import win_symlink_fast - return win_symlink_fast.FastIsReparseLink(path) - except Exception as err: # pylint: disable=broad-except - logging.exception(' error: %s, falling back to command line version.', err) - return None is not _ReadReparsePointShell(path) - - -def _CreateReparsePoint(from_folder, link_folder): - """See api version above for doc string.""" - if os.path.isdir(link_folder): - _RemoveEmptyDirectory(link_folder) - else: - _UnlinkReparsePoint(link_folder) # Deletes if it exists. - try: - # pylint: disable=g-import-not-at-top - import win_symlink_fast - win_symlink_fast.FastCreateReparseLink(from_folder, link_folder) - return - except OSError: - pass - except Exception as err: # pylint: disable=broad-except - logging.exception('unexpected error: %s, from=%s, link=%s, falling back to ' - 'command line version.', err, from_folder, link_folder) - par_dir = os.path.dirname(link_folder) - if not os.path.isdir(par_dir): - os.makedirs(par_dir) - try: - subprocess.check_output( - ['cmd', '/c', 'mklink', '/d', link_folder, from_folder], - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError: - # Fallback to junction points, which require less privileges to create. - subprocess.check_output( - ['cmd', '/c', 'mklink', '/j', link_folder, from_folder]) - if not _IsReparsePoint(link_folder): - raise OSError('Could not create sym link %s to %s' % - (link_folder, from_folder)) - - -def _UnlinkReparsePoint(link_dir): - """See api above for docstring.""" - if not _IsReparsePoint(link_dir): - return - cmd_parts = ['fsutil', 'reparsepoint', 'delete', link_dir] - subprocess.check_output(cmd_parts) - # The folder will now be unlinked, but will still exist. - if os.path.isdir(link_dir): - try: - _RemoveEmptyDirectory(link_dir) - except Exception as err: # pylint: disable=broad-except - logging.exception('could not remove %s because of %s', link_dir, err) - if _IsReparsePoint(link_dir): - raise IOError('Link still exists: %s' % _ReadReparsePoint(link_dir)) - if os.path.isdir(link_dir): - logging.info('WARNING - Link as folder still exists: %s', link_dir) - - -def _IsSamePath(p1, p2): - """Returns true if p1 and p2 represent the same path.""" - if not p1: - p1 = None - if not p2: - p2 = None - if p1 == p2: - return True - if (not p1) or (not p2): - return False - p1 = os.path.abspath(os.path.normpath(p1)) - p2 = os.path.abspath(os.path.normpath(p2)) - if p1 == p2: - return True - try: - return os.stat(p1) == os.stat(p2) - except Exception: # pylint: disable=broad-except - return False - - -def _OsWalk(top, topdown, onerror, followlinks): - """See api version of OsWalk above, for docstring.""" - # Need an absolute path to use listdir and isdir with long paths. - top_abs_path = top - if not os.path.isabs(top_abs_path): - top_abs_path = os.path.join(os.getcwd(), top_abs_path) - top_abs_path = cobalt_archive_extract.ToWinUncPath(top) - try: - names = os.listdir(top_abs_path) - except OSError as err: - if onerror is not None: - onerror(err) - return - dirs, nondirs = [], [] - for name in names: - if os.path.isdir(os.path.join(top_abs_path, name)): - dirs.append(name) - else: - nondirs.append(name) - if topdown: - yield top, dirs, nondirs - for name in dirs: - new_path = os.path.join(top, name) - if followlinks or not _IsReparsePoint(new_path): - for x in _OsWalk(new_path, topdown, onerror, followlinks): - yield x - if not topdown: - yield top, dirs, nondirs
diff --git a/src/starboard/build/win_symlink_fast.py b/src/starboard/build/win_symlink_fast.py deleted file mode 100644 index 7e8942f..0000000 --- a/src/starboard/build/win_symlink_fast.py +++ /dev/null
@@ -1,266 +0,0 @@ -#!/usr/bin/python -# Copyright 2019 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. - - -"""Provides functions for symlinking on Windows.""" - - -import ctypes -from ctypes import wintypes -import os - - -################################################################################ -# API # -################################################################################ - - -def FastIsReparseLink(path): - return _FastIsReparseLink(path) - - -def FastReadReparseLink(path): - return _FastReadReparseLink(path) - - -def FastCreateReparseLink(from_folder, link_folder): - """Creates a reparse link. - - Args: - from_folder: The folder that the link will point to. - link_folder: The path of the link to be created. - - Returns: - None - - If the operation fails to create the link due to the operating system not - supporting it then an OSError is raised. - """ - _FastCreateReparseLink(from_folder, link_folder) - - -################################################################################ -# IMPL # -################################################################################ - - -DWORD = wintypes.DWORD -LPCWSTR = wintypes.LPCWSTR -HANDLE = wintypes.HANDLE -LPVOID = wintypes.LPVOID -BOOL = wintypes.BOOL -USHORT = wintypes.USHORT -ULONG = wintypes.ULONG -WCHAR = wintypes.WCHAR - - -kernel32 = wintypes.WinDLL('kernel32') -LPDWORD = ctypes.POINTER(DWORD) -UCHAR = ctypes.c_ubyte - - -GetFileAttributesW = kernel32.GetFileAttributesW -GetFileAttributesW.restype = DWORD -GetFileAttributesW.argtypes = (LPCWSTR,) # lpFileName In - - -INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF -FILE_ATTRIBUTE_REPARSE_POINT = 0x00400 - - -CreateFileW = kernel32.CreateFileW -CreateFileW.restype = HANDLE -CreateFileW.argtypes = (LPCWSTR, # lpFileName In - DWORD, # dwDesiredAccess In - DWORD, # dwShareMode In - LPVOID, # lpSecurityAttributes In_opt - DWORD, # dwCreationDisposition In - DWORD, # dwFlagsAndAttributes In - HANDLE) # hTemplateFile In_opt - - -CloseHandle = kernel32.CloseHandle -CloseHandle.restype = BOOL -CloseHandle.argtypes = (HANDLE,) # hObject In - - -INVALID_HANDLE_VALUE = HANDLE(-1).value -OPEN_EXISTING = 3 -FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 -FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 - - -DeviceIoControl = kernel32.DeviceIoControl -DeviceIoControl.restype = BOOL -DeviceIoControl.argtypes = (HANDLE, # hDevice In - DWORD, # dwIoControlCode In - LPVOID, # lpInBuffer In_opt - DWORD, # nInBufferSize In - LPVOID, # lpOutBuffer Out_opt - DWORD, # nOutBufferSize In - LPDWORD, # lpBytesReturned Out_opt - LPVOID) # lpOverlapped Inout_opt - - -FSCTL_GET_REPARSE_POINT = 0x000900A8 -IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 -IO_REPARSE_TAG_SYMLINK = 0xA000000C -MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 0x4000 -SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1 -# Developer Mode must be enabled in order to use the following flag. -SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2 -SYMLINK_FLAG_RELATIVE = 0x1 - - -class GenericReparseBuffer(ctypes.Structure): - """Win32 api data structure.""" - _fields_ = (('DataBuffer', UCHAR * 1),) - - -class SymbolicLinkReparseBuffer(ctypes.Structure): - """Win32 api data structure.""" - - _fields_ = (('SubstituteNameOffset', USHORT), - ('SubstituteNameLength', USHORT), - ('PrintNameOffset', USHORT), - ('PrintNameLength', USHORT), - ('Flags', ULONG), - ('PathBuffer', WCHAR * 1)) - - @property - def print_name(self): - arrayt = WCHAR * (self.PrintNameLength // 2) - offset = type(self).PathBuffer.offset + self.PrintNameOffset - return arrayt.from_address(ctypes.addressof(self) + offset).value - - @property - def substitute_name(self): - arrayt = WCHAR * (self.SubstituteNameLength // 2) - offset = type(self).PathBuffer.offset + self.SubstituteNameOffset - return arrayt.from_address(ctypes.addressof(self) + offset).value - - @property - def is_relative_path(self): - return bool(self.Flags & SYMLINK_FLAG_RELATIVE) - - -class MountPointReparseBuffer(ctypes.Structure): - """Win32 api data structure.""" - _fields_ = (('SubstituteNameOffset', USHORT), - ('SubstituteNameLength', USHORT), - ('PrintNameOffset', USHORT), - ('PrintNameLength', USHORT), - ('PathBuffer', WCHAR * 1)) - - @property - def print_name(self): - arrayt = WCHAR * (self.PrintNameLength // 2) - offset = type(self).PathBuffer.offset + self.PrintNameOffset - return arrayt.from_address(ctypes.addressof(self) + offset).value - - @property - def substitute_name(self): - arrayt = WCHAR * (self.SubstituteNameLength // 2) - offset = type(self).PathBuffer.offset + self.SubstituteNameOffset - return arrayt.from_address(ctypes.addressof(self) + offset).value - - -class ReparseDataBuffer(ctypes.Structure): - """Win32 api data structure.""" - - class ReparseBuffer(ctypes.Union): - """Win32 api data structure.""" - _fields_ = (('SymbolicLinkReparseBuffer', SymbolicLinkReparseBuffer), - ('MountPointReparseBuffer', MountPointReparseBuffer), - ('GenericReparseBuffer', GenericReparseBuffer)) - _fields_ = (('ReparseTag', ULONG), - ('ReparseDataLength', USHORT), - ('Reserved', USHORT), - ('ReparseBuffer', ReparseBuffer)) - _anonymous_ = ('ReparseBuffer',) - - -def _ToUnicode(s): - return s.decode('utf-8') - - -_kdll = None - - -def _GetKernel32Dll(): - global _kdll - if _kdll: - return _kdll - _kdll = ctypes.windll.LoadLibrary('kernel32.dll') - return _kdll - - -def _FastCreateReparseLink(from_folder, link_folder): - """See api docstring, above.""" - from_folder = _ToUnicode(from_folder) - link_folder = _ToUnicode(link_folder) - par_dir = os.path.dirname(link_folder) - if not os.path.isdir(par_dir): - os.makedirs(par_dir) - kdll = _GetKernel32Dll() - # Only supported from Windows 10 Insiders build 14972 - flags = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE | \ - SYMBOLIC_LINK_FLAG_DIRECTORY - ok = kdll.CreateSymbolicLinkW(link_folder, from_folder, flags) - if not ok or not _FastIsReparseLink(link_folder): - raise OSError('Could not create sym link ' + link_folder + ' to ' + - from_folder) - - -def _FastIsReparseLink(path): - path = _ToUnicode(path) - result = GetFileAttributesW(path) - if result == INVALID_FILE_ATTRIBUTES: - return False - return bool(result & FILE_ATTRIBUTE_REPARSE_POINT) - - -def _FastReadReparseLink(path): - """See api docstring, above.""" - path = _ToUnicode(path) - reparse_point_handle = CreateFileW(path, - 0, - 0, - None, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | - FILE_FLAG_BACKUP_SEMANTICS, - None) - if reparse_point_handle == INVALID_HANDLE_VALUE: - return None - # Remove false positive below. - # pylint: disable=deprecated-method - target_buffer = ctypes.c_buffer(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) - n_bytes_returned = DWORD() - io_result = DeviceIoControl(reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - None, 0, - target_buffer, len(target_buffer), - ctypes.byref(n_bytes_returned), - None) - CloseHandle(reparse_point_handle) - if not io_result: - return None - rdb = ReparseDataBuffer.from_buffer(target_buffer) - if rdb.ReparseTag == IO_REPARSE_TAG_SYMLINK: - return rdb.SymbolicLinkReparseBuffer.print_name - elif rdb.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT: - return rdb.MountPointReparseBuffer.print_name - return None
diff --git a/src/starboard/build/win_symlink_fast_test.py b/src/starboard/build/win_symlink_fast_test.py deleted file mode 100644 index eac6bb9..0000000 --- a/src/starboard/build/win_symlink_fast_test.py +++ /dev/null
@@ -1,59 +0,0 @@ -#!/usr/bin/python -# Copyright 2019 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 the win_symlink_fast functionality.""" - -import sys -import unittest - - -import _env # pylint: disable=relative-import,unused-import - - -if __name__ == '__main__' and sys.platform == 'win32': - from starboard.build import port_symlink_test # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink_fast # pylint: disable=g-import-not-at-top - from starboard.tools import util # pylint: disable=g-import-not-at-top - - # Override the port_symlink_test symlink functions to point to our win_symlink - # and win_symlink_fast versions. - def MakeSymLink(*args, **kwargs): - return win_symlink_fast.FastCreateReparseLink(*args, **kwargs) - - def IsSymLink(*args, **kwargs): - return win_symlink_fast.FastIsReparseLink(*args, **kwargs) - - def ReadSymLink(*args, **kwargs): - return win_symlink_fast.FastReadReparseLink(*args, **kwargs) - - def Rmtree(*args, **kwargs): - return win_symlink.RmtreeShallow(*args, **kwargs) - - def OsWalk(*args, **kwargs): - return win_symlink.OsWalk(*args, **kwargs) - - port_symlink_test.MakeSymLink = MakeSymLink - port_symlink_test.IsSymLink = IsSymLink - port_symlink_test.ReadSymLink = ReadSymLink - port_symlink_test.Rmtree = Rmtree - port_symlink_test.OsWalk = OsWalk - - # Makes a unit test available to the unittest.main (through magic). - class WinSymlinkTest(port_symlink_test.PortSymlinkTest): - pass - - util.SetupDefaultLoggingConfig() - unittest.main(verbosity=2)
diff --git a/src/starboard/build/win_symlink_test.py b/src/starboard/build/win_symlink_test.py deleted file mode 100644 index 670e2ad..0000000 --- a/src/starboard/build/win_symlink_test.py +++ /dev/null
@@ -1,91 +0,0 @@ -#!/usr/bin/python -# Copyright 2018 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 win_symlink.""" - -import os -import shutil -import sys -import tempfile -import unittest - - -import _env # pylint: disable=relative-import,unused-import - - -if __name__ == '__main__' and sys.platform == 'win32': - from starboard.build import port_symlink_test # pylint: disable=g-import-not-at-top - from starboard.build import win_symlink # pylint: disable=g-import-not-at-top - from starboard.tools import util # pylint: disable=g-import-not-at-top - - # Override the port_symlink_test symlink functions to point to our win_symlink - # versions. - def MakeSymLink(*args, **kwargs): - return win_symlink.CreateReparsePoint(*args, **kwargs) - - def IsSymLink(*args, **kwargs): - return win_symlink.IsReparsePoint(*args, **kwargs) - - def ReadSymLink(*args, **kwargs): - return win_symlink.ReadReparsePoint(*args, **kwargs) - - def Rmtree(*args, **kwargs): - return win_symlink.RmtreeShallow(*args, **kwargs) - - def OsWalk(*args, **kwargs): - return win_symlink.OsWalk(*args, **kwargs) - - port_symlink_test.MakeSymLink = MakeSymLink - port_symlink_test.IsSymLink = IsSymLink - port_symlink_test.ReadSymLink = ReadSymLink - port_symlink_test.Rmtree = Rmtree - port_symlink_test.OsWalk = OsWalk - - # Makes a unit test available to the unittest.main (through magic). - class WinSymlinkTest(port_symlink_test.PortSymlinkTest): - - def testRmtreeOsWalkDoesNotFollowSymlinks(self): - """_RmtreeOsWalk(...) will delete the symlink and not the target.""" - external_temp_dir = tempfile.mkdtemp() - try: - external_temp_file = os.path.join(external_temp_dir, 'test.txt') - with open(external_temp_file, 'w') as fd: - fd.write('HI') - link_dir = os.path.join(self.tmp_dir, 'foo', 'link_dir') - MakeSymLink(external_temp_file, link_dir) - win_symlink._RmtreeOsWalk(self.tmp_dir) - # The target file should still exist - self.assertTrue(os.path.isfile(external_temp_file)) - finally: - shutil.rmtree(external_temp_dir, ignore_errors=True) - - def testRmtreeCmdShellDoesNotFollowSymlinks(self): - """_RmtreeShellCmd(...) will delete the symlink and not the target.""" - external_temp_dir = tempfile.mkdtemp() - try: - external_temp_file = os.path.join(external_temp_dir, 'test.txt') - with open(external_temp_file, 'w') as fd: - fd.write('HI') - link_dir = os.path.join(self.tmp_dir, 'foo', 'link_dir') - MakeSymLink(external_temp_file, link_dir) - win_symlink._RmtreeShellCmd(self.tmp_dir) - # The target file should still exist - self.assertTrue(os.path.isfile(external_temp_file)) - finally: - shutil.rmtree(external_temp_dir, ignore_errors=True) - - - util.SetupDefaultLoggingConfig() - unittest.main(verbosity=2)
diff --git a/src/starboard/common/instance_counter.h b/src/starboard/common/instance_counter.h new file mode 100644 index 0000000..0e4d6e8 --- /dev/null +++ b/src/starboard/common/instance_counter.h
@@ -0,0 +1,52 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_COMMON_INSTANCE_COUNTER_H_ +#define STARBOARD_COMMON_INSTANCE_COUNTER_H_ + +#include "starboard/atomic.h" +#include "starboard/common/log.h" + +#if defined(COBALT_BUILD_TYPE_GOLD) + +#define DECLARE_INSTANCE_COUNTER(class_name) +#define ON_INSTANCE_CREATED(class_name) +#define ON_INSTANCE_RELEASED(class_name) + +#else // defined(COBALT_BUILD_TYPE_GOLD) + +#define DECLARE_INSTANCE_COUNTER(class_name) \ + namespace { \ + SbAtomic32 s_##class_name##_instance_count = 0; \ + } + +#define ON_INSTANCE_CREATED(class_name) \ + { \ + SB_LOG(INFO) << "New instance of " << #class_name \ + << " is created. We have " \ + << (SbAtomicNoBarrier_Increment( \ + &s_##class_name##_instance_count, 1)) \ + << " instances in total."; \ + } + +#define ON_INSTANCE_RELEASED(class_name) \ + { \ + SB_LOG(INFO) << "Instance of " << #class_name << " is released. We have " \ + << (SbAtomicNoBarrier_Increment( \ + &s_##class_name##_instance_count, -1)) \ + << " instances in total."; \ + } +#endif // defined(COBALT_BUILD_TYPE_GOLD) + +#endif // STARBOARD_COMMON_INSTANCE_COUNTER_H_
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h index c123d6d..d650414 100644 --- a/src/starboard/configuration.h +++ b/src/starboard/configuration.h
@@ -76,6 +76,110 @@ // parameters are. #define SB_UI_NAVIGATION_VERSION SB_EXPERIMENTAL_API_VERSION +// Require the OpenGL, Blitter, and Skia renderers on all platforms. +// The system must implement `SbGetGlesInterface()` in `starboard/gles.h` +// or use the provided stub implementation, and must do the same for +// the blitter functions in `starboad/blitter.h`. The provided blitter stubs +// will return responses that denote failures. The system should implement +// `SbGetGlesInterface()` to return `nullptr` when OpenGL is not supported and +// implement `SbBlitterIsBlitterSupported()` to return false when blitter is +// not supported, as the stubs do. +#define SB_ALL_RENDERERS_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Require the captions API. +// The system must implement the captions functions in +// `starboard/accessibility.h` or use the provided stub implementations. +// System caption can be disabled by implementing the function +// `SbAccessibilityGetCaptionSettings(SbAccessibilityCaptionSettings* +// caption_settings)` to return false as the stub implementation does. +// This change also deprecates the SB_HAS_CAPTIONS flag. +#define SB_CAPTIONS_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Require compilation with Ipv6. +// Cobalt must be able to determine at runtime if the system supportes Ipv6. +// Ipv6 can be disabled by defining SB_HAS_IPV6 to 0. +#define SB_IPV6_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Require the microphone API. +// The system must implement the microphone functions in +// `starboard/microphone.h` or use the provided stub functions. +// The microphone can be disabled by having `SbMicrophoneCreate()` return +// |kSbMicrophoneInvalid|. +// This change also deprecates the SB_HAS_MICROPHONE flag. +#define SB_MICROPHONE_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Require the memory mapping API. +// The system must implement the memory mapping functions in +// `starboard/memory.h` and `starboard/shared/dlmalloc.h` or use the provided +// stub implementations. +// This change also deprecates the SB_HAS_MMAP flag. +#define SB_MMAP_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Require the on screen keyboard API. +// The system must implement the on screen keyboard functions in +// `starboard/window.h` or use the provided stub implementations. +// The on screen keyboard can be disabled by implementing the function +// `SbWindowOnScreenKeyboardIsSupported()` to return false +// as the stub implementation does. +#define SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Require speech recognizer API. +// The system must implement the functions in `starboard/speech_recognizer.h` +// or use the provided stub implementations. +// The speech recognizer can be disabled by implementing the function +// `SbSpeechRecognizerIsSupported()` to return `false` as the stub +// implementation does. +#define SB_SPEECH_RECOGNIZER_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Require the speech synthesis API. +// The system must implement the speech synthesis function in +// `starboard/speech_synthesis.h` or use the provided stub implementations. +// Speech synthesis can be disabled by implementing the function +// `SbSpeechSynthesisIsSupported()` to return false as the stub +// implementation does. +#define SB_SPEECH_SYNTHESIS_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Require the time thread now API. +// The system must implement the time thread now functions in +// `starboard/time.h` or use the provided stub implementations. +// Time thread now can be disabled by implementing the function +// `SbTimeIsTimeThreadNowSupported()` to return false as the stub +// implementation does. +#define SB_TIME_THREAD_NOW_REQUIRED_VERSION SB_EXPERIMENTAL_API_VERSION + +// Introduce the Starboard function SbFileAtomicReplace() to provide the ability +// to atomically replace the content of a file. +#define SB_FILE_ATOMIC_REPLACE_VERSION SB_EXPERIMENTAL_API_VERSION + +// Introduces new system property kSbSystemPathStorageDirectory. +// Path to directory for permanent storage. Both read and write +// access are required. +#define SB_STORAGE_PATH_VERSION SB_EXPERIMENTAL_API_VERSION + +// Deprecate the usage of SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER. +#define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION \ + SB_EXPERIMENTAL_API_VERSION + +// Introduce Starboard Application Binary Interface (SABI) files. +// SABI files are used to describe the configuration for targets such that two +// targets, built with the same SABI file and varying toolchains, have +// compatible Starboard APIs and ABIs. +// +// With this define, we have: +// 1) Moved architecture specific defines and configurations from +// configuration_public.h and *.gyp[i] files into SABI files. +// 2) Included the appropriate SABI file in each platform configuration. +// 3) Included the //starboard/sabi/sabi.gypi file in each platform +// configuration which consumes SABI file fields and defines a set of +// constants that are accessible when building. +// 4) Provided a set of tests that ensure the toolchain being used produces +// an executable or shared library that conforms to the included SABI +// file. +// +// For further information on what is provided by SABI files, or how these +// values are consumed, take a look at //starboard/sabi. +#define SB_SABI_FILE_VERSION SB_EXPERIMENTAL_API_VERSION + // --- Release Candidate Feature Defines ------------------------------------- // --- Common Detected Features ---------------------------------------------- @@ -491,8 +595,10 @@ "Your platform must define SB_HAS_MICROPHONE in API versions 11 or earlier." #endif -#if !defined(SB_HAS_TIME_THREAD_NOW) -#error "Your platform must define SB_HAS_TIME_THREAD_NOW in API 3 or later." +#if SB_API_VERSION < SB_TIME_THREAD_NOW_REQUIRED_VERSION && \ + !defined(SB_HAS_TIME_THREAD_NOW) +#error \ + "Your platform must define SB_HAS_TIME_THREAD_NOW in API versions 3 to 11." #endif #if defined(SB_IS_PLAYER_COMPOSITED) || defined(SB_IS_PLAYER_PUNCHED_OUT) || \ @@ -526,9 +632,17 @@ #error "Your platform must define SB_HAS_NV12_TEXTURE_SUPPORT." #endif +#if SB_API_VERSION >= SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION +#if defined(SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER) +#error "SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is deprecated." +#error "Use `CobaltExtensionGraphicsApi` instead." +#error "See [`CobaltExtensionGraphicsApi`](../extension/graphics.h)." +#endif +#else #if !defined(SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER) #error "Your platform must define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER." #endif +#endif #if !defined(SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND) #error \ @@ -581,17 +695,20 @@ #endif // defined(SB_HAS_DRM_SESSION_CLOSED) #endif // SB_API_VERSION >= 10 -#if SB_API_VERSION >= 5 +#if SB_API_VERSION < SB_SPEECH_RECOGNIZER_IS_REQUIRED && SB_API_VERSION >= 5 #if !defined(SB_HAS_SPEECH_RECOGNIZER) #error "Your platform must define SB_HAS_SPEECH_RECOGNIZER." #endif // !defined(SB_HAS_SPEECH_RECOGNIZER) -#endif // SB_API_VERSION >= 5 +#endif // SB_API_VERSION < SB_SPEECH_RECOGNIZER_IS_REQUIRED && SB_API_VERSION + // >= 5 -#if SB_API_VERSION >= 8 +#if SB_API_VERSION < SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION && \ + SB_API_VERSION >= 8 #if !defined(SB_HAS_ON_SCREEN_KEYBOARD) #error "Your platform must define SB_HAS_ON_SCREEN_KEYBOARD." #endif // !defined(SB_HAS_ON_SCREEN_KEYBOARD) -#endif // SB_API_VERSION >= 8 +#endif // SB_API_VERSION < SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION && + // SB_API_VERSION >= 8 #if SB_HAS(ON_SCREEN_KEYBOARD) && (SB_API_VERSION < 8) #error "SB_HAS_ON_SCREEN_KEYBOARD not supported in this API version." @@ -671,7 +788,8 @@ // Specifies whether this platform has any kind of supported graphics system. #if !defined(SB_HAS_GRAPHICS) -#if SB_HAS(GLES2) || SB_HAS(BLITTER) +#if SB_HAS(GLES2) || SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || \ + SB_HAS(BLITTER) #define SB_HAS_GRAPHICS 1 #else #define SB_HAS_GRAPHICS 0
diff --git a/src/starboard/contrib/creator/shared/configuration_public.h b/src/starboard/contrib/creator/shared/configuration_public.h index 7291ee3..ec1364b 100644 --- a/src/starboard/contrib/creator/shared/configuration_public.h +++ b/src/starboard/contrib/creator/shared/configuration_public.h
@@ -333,7 +333,9 @@ // Whether this platform has and should use an MMAP function to map physical // memory to the virtual address space. +#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION #define SB_HAS_MMAP 1 +#endif // Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is // required for platforms that want to JIT.
diff --git a/src/starboard/contrib/creator/shared/gyp_configuration.gypi b/src/starboard/contrib/creator/shared/gyp_configuration.gypi index afd5ae0..68b7775 100644 --- a/src/starboard/contrib/creator/shared/gyp_configuration.gypi +++ b/src/starboard/contrib/creator/shared/gyp_configuration.gypi
@@ -14,6 +14,10 @@ { 'variables': { + # Override that omits the "data" subdirectory. + # TODO: Remove when omitted for all platforms in base_configuration.gypi. + 'sb_static_contents_output_data_dir': '<(PRODUCT_DIR)/content', + 'target_arch': 'mips', 'target_os': 'linux',
diff --git a/src/starboard/contrib/creator/shared/media_is_video_supported.cc b/src/starboard/contrib/creator/shared/media_is_video_supported.cc index be16c90..0084e56 100644 --- a/src/starboard/contrib/creator/shared/media_is_video_supported.cc +++ b/src/starboard/contrib/creator/shared/media_is_video_supported.cc
@@ -18,18 +18,18 @@ #include "starboard/media.h" #include "starboard/shared/starboard/media/media_util.h" -SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, - int frame_width, - int frame_height, - int64_t bitrate, - int fps, - bool decode_to_texture_required) { +bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required) { SB_UNREFERENCED_PARAMETER(profile); SB_UNREFERENCED_PARAMETER(level);
diff --git a/src/starboard/contrib/creator/shared/starboard_platform.gypi b/src/starboard/contrib/creator/shared/starboard_platform.gypi index e33ae3d..49e7b4c 100644 --- a/src/starboard/contrib/creator/shared/starboard_platform.gypi +++ b/src/starboard/contrib/creator/shared/starboard_platform.gypi
@@ -14,9 +14,11 @@ { 'includes': [ '<(DEPTH)/starboard/shared/starboard/player/filter/player_filter.gypi', + '<(DEPTH)/starboard/stub/blitter_stub_sources.gypi', ], 'variables': { 'starboard_platform_sources': [ + '<@(blitter_stub_sources)', '<@(filter_based_player_sources)', '<(DEPTH)/starboard/contrib/creator/shared/media_is_video_supported.cc', '<(DEPTH)/starboard/contrib/creator/shared/player_components_impl.cc', @@ -106,6 +108,7 @@ '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc', '<(DEPTH)/starboard/shared/nouser/user_internal.cc', '<(DEPTH)/starboard/shared/posix/directory_create.cc', + '<(DEPTH)/starboard/shared/posix/file_atomic_replace.cc', '<(DEPTH)/starboard/shared/posix/file_can_open.cc', '<(DEPTH)/starboard/shared/posix/file_close.cc', '<(DEPTH)/starboard/shared/posix/file_delete.cc', @@ -137,6 +140,7 @@ '<(DEPTH)/starboard/shared/posix/socket_internal.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected_and_idle.cc', + '<(DEPTH)/starboard/shared/posix/socket_is_ipv6_supportec.cc', '<(DEPTH)/starboard/shared/posix/socket_join_multicast_group.cc', '<(DEPTH)/starboard/shared/posix/socket_listen.cc', '<(DEPTH)/starboard/shared/posix/socket_receive_from.cc', @@ -165,6 +169,7 @@ '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_now.cc', + '<(DEPTH)/starboard/shared/posix/time_is_time_thread_now_supported.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_name.cc', '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc', @@ -207,6 +212,8 @@ '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc', '<(DEPTH)/starboard/shared/starboard/event_cancel.cc', '<(DEPTH)/starboard/shared/starboard/event_schedule.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.h', '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc', @@ -288,6 +295,7 @@ '<(DEPTH)/starboard/shared/starboard/system_request_unpause.cc', '<(DEPTH)/starboard/shared/starboard/system_supports_resume.cc', '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc', + '<(DEPTH)/starboard/shared/stub/accessibility_get_caption_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_display_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc', '<(DEPTH)/starboard/shared/stub/cpu_features_get.cc',
diff --git a/src/starboard/contrib/tizen/shared/configuration_public.h b/src/starboard/contrib/tizen/shared/configuration_public.h index 4d103b2..7ccf2cb 100644 --- a/src/starboard/contrib/tizen/shared/configuration_public.h +++ b/src/starboard/contrib/tizen/shared/configuration_public.h
@@ -180,7 +180,9 @@ // Whether this platform has and should use an MMAP function to map physical // memory to the virtual address space. +#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION #define SB_HAS_MMAP 1 +#endif // Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is // required for platforms that want to JIT.
diff --git a/src/starboard/contrib/tizen/shared/starboard_common.gyp b/src/starboard/contrib/tizen/shared/starboard_common.gyp index fff2b96..653099d 100644 --- a/src/starboard/contrib/tizen/shared/starboard_common.gyp +++ b/src/starboard/contrib/tizen/shared/starboard_common.gyp
@@ -98,6 +98,7 @@ '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc', '<(DEPTH)/starboard/shared/nouser/user_internal.cc', '<(DEPTH)/starboard/shared/posix/directory_create.cc', + '<(DEPTH)/starboard/shared/posix/file_atomic_replace.cc', '<(DEPTH)/starboard/shared/posix/file_can_open.cc', '<(DEPTH)/starboard/shared/posix/file_close.cc', '<(DEPTH)/starboard/shared/posix/file_delete.cc', @@ -155,6 +156,7 @@ '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_now.cc', + '<(DEPTH)/starboard/shared/posix/time_is_time_thread_now_supported.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_name.cc', '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc', @@ -187,6 +189,8 @@ '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc', '<(DEPTH)/starboard/shared/starboard/event_cancel.cc', '<(DEPTH)/starboard/shared/starboard/event_schedule.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.h', '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc',
diff --git a/src/starboard/contrib/tizen/shared/starboard_platform.gypi b/src/starboard/contrib/tizen/shared/starboard_platform.gypi index f5bd53d..ca4802d 100644 --- a/src/starboard/contrib/tizen/shared/starboard_platform.gypi +++ b/src/starboard/contrib/tizen/shared/starboard_platform.gypi
@@ -14,6 +14,7 @@ { 'includes': [ '<(DEPTH)/starboard/shared/starboard/player/filter/player_filter.gypi', + '<(DEPTH)/starboard/stub/blitter_stub_sources.gypi', ], 'variables': { 'variables': { @@ -24,6 +25,7 @@ 'has_cdm%': '<(has_cdm)', 'starboard_platform_sources': [ '<@(filter_based_player_sources)', + '<@(blitter_stub_sources)', '<(DEPTH)/starboard/contrib/tizen/shared/atomic_public.h', '<(DEPTH)/starboard/contrib/tizen/shared/configuration_public.h', '<(DEPTH)/starboard/contrib/tizen/shared/get_home_directory.cc', @@ -137,6 +139,7 @@ '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc', '<(DEPTH)/starboard/shared/nouser/user_internal.cc', '<(DEPTH)/starboard/shared/posix/directory_create.cc', + '<(DEPTH)/starboard/shared/posix/file_atomic_replace.cc', '<(DEPTH)/starboard/shared/posix/file_can_open.cc', '<(DEPTH)/starboard/shared/posix/file_close.cc', '<(DEPTH)/starboard/shared/posix/file_delete.cc', @@ -168,6 +171,7 @@ '<(DEPTH)/starboard/shared/posix/socket_internal.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected_and_idle.cc', + '<(DEPTH)/starboard/shared/posix/socket_is_ipv6_supported.cc', '<(DEPTH)/starboard/shared/posix/socket_join_multicast_group.cc', '<(DEPTH)/starboard/shared/posix/socket_listen.cc', '<(DEPTH)/starboard/shared/posix/socket_receive_from.cc', @@ -196,6 +200,7 @@ '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_now.cc', + '<(DEPTH)/starboard/shared/posix/time_is_time_thread_now_supported.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_name.cc', '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc', @@ -255,6 +260,8 @@ '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc', '<(DEPTH)/starboard/shared/starboard/event_cancel.cc', '<(DEPTH)/starboard/shared/starboard/event_schedule.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.h', '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc', @@ -330,6 +337,7 @@ '<(DEPTH)/starboard/shared/starboard/system_request_unpause.cc', '<(DEPTH)/starboard/shared/starboard/system_supports_resume.cc', '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc', + '<(DEPTH)/starboard/shared/stub/accessibility_get_caption_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_display_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc', '<(DEPTH)/starboard/shared/stub/cpu_features_get.cc',
diff --git a/src/starboard/decode_target.h b/src/starboard/decode_target.h index 535f160..2b09430 100644 --- a/src/starboard/decode_target.h +++ b/src/starboard/decode_target.h
@@ -96,9 +96,10 @@ #include "starboard/export.h" #include "starboard/types.h" -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) #include "starboard/blitter.h" -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) #ifdef __cplusplus extern "C" { @@ -177,7 +178,7 @@ kSbDecodeTargetPlaneV = 2, } SbDecodeTargetPlane; -#if SB_HAS(GLES2) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) struct SbDecodeTargetGraphicsContextProvider; // Signature for a Starboard implementaion function that is to be run by a @@ -193,7 +194,7 @@ struct SbDecodeTargetGraphicsContextProvider* graphics_context_provider, SbDecodeTargetGlesContextRunnerTarget target_function, void* target_function_context); -#endif // SB_HAS(GLES2) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) // In general, the SbDecodeTargetGraphicsContextProvider structure provides // information about the graphics context that will be used to render @@ -203,11 +204,12 @@ // should be provided to all Starboard functions that might create // SbDecodeTargets (e.g. SbImageDecode()). typedef struct SbDecodeTargetGraphicsContextProvider { -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) // The SbBlitterDevice object that will be used to render any produced // SbDecodeTargets. SbBlitterDevice device; -#elif SB_HAS(GLES2) +#endif +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) // A reference to the EGLDisplay object that hosts the EGLContext that will // be used to render any produced SbDecodeTargets. Note that it has the // type |void*| in order to avoid #including the EGL header files here. @@ -226,10 +228,10 @@ // Context data that is to be passed in to |gles_context_runner| when it is // invoked. void* gles_context_runner_context; -#else // SB_HAS(BLITTER) +#elif !(SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER)) // Some compilers complain about empty structures, this is to appease them. char dummy; -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) } SbDecodeTargetGraphicsContextProvider; // Defines a rectangular content region within a SbDecodeTargetInfoPlane @@ -257,10 +259,12 @@ // Defines an image plane within a SbDecodeTargetInfo object. typedef struct SbDecodeTargetInfoPlane { -#if SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(BLITTER) // A handle to the Blitter surface that can be used for rendering. SbBlitterSurface surface; -#elif SB_HAS(GLES2) // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || + // SB_HAS(BLITTER) +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) // A handle to the GL texture that can be used for rendering. uint32_t texture; @@ -278,7 +282,7 @@ uint32_t gl_texture_format; #endif // SB_API_VERSION >= 7 -#endif // SB_HAS(BLITTER) +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) // The width of the texture/surface for this particular plane. int width;
diff --git a/src/starboard/egl.h b/src/starboard/egl.h index 7503691..1a1165f 100644 --- a/src/starboard/egl.h +++ b/src/starboard/egl.h
@@ -36,6 +36,8 @@ #include "starboard/log.h" #include "starboard/types.h" +#if SB_API_VERSION >= 11 + #ifdef __cplusplus extern "C" { #endif @@ -366,4 +368,6 @@ } // extern "C" #endif +#endif // SB_API_VERSION >= 11 + #endif // STARBOARD_EGL_H_
diff --git a/src/starboard/elf_loader/dynamic_section.cc b/src/starboard/elf_loader/dynamic_section.cc deleted file mode 100644 index b4d9422..0000000 --- a/src/starboard/elf_loader/dynamic_section.cc +++ /dev/null
@@ -1,203 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/dynamic_section.h" - -#include "starboard/common/log.h" - -namespace starboard { -namespace elf_loader { - -DynamicSection::DynamicSection(Addr base_memory_address, - Dyn* dynamic, - size_t dynamic_count, - Word dynamic_flags) - : base_memory_address_(base_memory_address), - soname_(NULL), - dynamic_(dynamic), - dynamic_count_(dynamic_count), - dynamic_flags_(dynamic_flags), - has_DT_SYMBOLIC_(false), - symbol_table_(NULL), - string_table_(NULL), - preinit_array_(NULL), - preinit_array_count_(0), - init_array_(NULL), - init_array_count_(0), - fini_array_(NULL), - fini_array_count_(0), - init_func_(NULL), - fini_func_(NULL) {} - -bool DynamicSection::InitDynamicSection() { - SB_LOG(INFO) << "Dynamic section count=" << dynamic_count_; - for (int i = 0; i < dynamic_count_; i++) { - Addr dyn_value = dynamic_[i].d_un.d_val; - uintptr_t dyn_addr = base_memory_address_ + dynamic_[i].d_un.d_ptr; - SB_LOG(INFO) << "Dynamic tag=" << dynamic_[i].d_tag; - switch (dynamic_[i].d_tag) { - case DT_DEBUG: - // TODO: implement. - break; - case DT_INIT: - SB_LOG(INFO) << " DT_INIT addr=0x" << std::hex << dyn_addr; - init_func_ = reinterpret_cast<linker_function_t>(dyn_addr); - break; - case DT_FINI: - SB_LOG(INFO) << " DT_FINI addr=0x" << std::hex << dyn_addr; - fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr); - break; - case DT_INIT_ARRAY: - SB_LOG(INFO) << " DT_INIT_ARRAY addr=0x" << std::hex << dyn_addr; - init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); - break; - case DT_INIT_ARRAYSZ: - init_array_count_ = dyn_value / sizeof(Addr); - SB_LOG(INFO) << " DT_INIT_ARRAYSZ value=0x" << std::hex << dyn_value - << " count=" << std::dec << init_array_count_; - break; - case DT_FINI_ARRAY: - SB_LOG(INFO) << " DT_FINI_ARRAY addr=0x" << std::hex << dyn_addr; - fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); - break; - case DT_FINI_ARRAYSZ: - fini_array_count_ = dyn_value / sizeof(Addr); - SB_LOG(INFO) << " DT_FINI_ARRAYSZ value=0x" << std::hex << dyn_value - << " count=" << fini_array_count_; - break; - case DT_PREINIT_ARRAY: - SB_LOG(INFO) << " DT_PREINIT_ARRAY addr=0x" << std::hex << dyn_addr; - preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr); - break; - case DT_PREINIT_ARRAYSZ: - preinit_array_count_ = dyn_value / sizeof(Addr); - SB_LOG(INFO) << " DT_PREINIT_ARRAYSZ addr=" << dyn_addr - << " count=" << preinit_array_count_; - break; - case DT_SYMBOLIC: - SB_LOG(INFO) << " DT_SYMBOLIC"; - has_DT_SYMBOLIC_ = true; - break; - case DT_FLAGS: - if (dyn_value & DF_SYMBOLIC) - has_DT_SYMBOLIC_ = true; - break; - case DT_SONAME: - soname_ = string_table_ + dyn_value; - break; - default: - break; - } - } - return true; -} - -bool DynamicSection::InitDynamicSymbols() { - for (int i = 0; i < dynamic_count_; i++) { - Addr dyn_value = dynamic_[i].d_un.d_val; - uintptr_t dyn_addr = base_memory_address_ + dynamic_[i].d_un.d_ptr; - switch (dynamic_[i].d_tag) { - case DT_HASH: - SB_LOG(INFO) << " DT_HASH addr=0x" << std::hex << dyn_addr; - elf_hash_.Init(dyn_addr); - break; - case DT_GNU_HASH: - SB_LOG(INFO) << " DT_GNU_HASH addr=0x" << std::hex << dyn_addr; - gnu_hash_.Init(dyn_addr); - break; - case DT_STRTAB: - SB_LOG(INFO) << " DT_STRTAB addr=0x" << std::hex << dyn_addr; - string_table_ = reinterpret_cast<const char*>(dyn_addr); - break; - case DT_SYMTAB: - SB_LOG(INFO) << " DT_SYMTAB addr=0x" << std::hex << dyn_addr; - symbol_table_ = reinterpret_cast<Sym*>(dyn_addr); - break; - default: - break; - } - } - return true; -} - -const Dyn* DynamicSection::GetDynamicTable() { - return dynamic_; -} - -size_t DynamicSection::GetDynamicTableSize() { - return dynamic_count_; -} - -void DynamicSection::CallConstructors() { - CallFunction(init_func_, "DT_INIT"); - for (size_t n = 0; n < init_array_count_; ++n) - CallFunction(init_array_[n], "DT_INIT_ARRAY"); -} - -void DynamicSection::CallDestructors() { - for (size_t n = fini_array_count_; n > 0; --n) { - CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY"); - } - CallFunction(fini_func_, "DT_FINI"); -} - -void DynamicSection::CallFunction(linker_function_t func, - const char* func_type) { - uintptr_t func_address = reinterpret_cast<uintptr_t>(func); - - // On some platforms the entries in the array can be 0 or -1, - // and should be ignored e.g. Android: - // https://android.googlesource.com/platform/bionic/+/android-4.2_r1/linker/README.TXT - if (func_address != 0 && func_address != uintptr_t(-1)) { - func(); - } -} - -const Sym* DynamicSection::LookupById(size_t symbol_id) const { - // TODO: Calculated the symbol_table size and validation check. - return &symbol_table_[symbol_id]; -} - -bool DynamicSection::IsWeakById(size_t symbol_id) const { - // TODO: Calculated the symbol_table size and validation check. - return ELF_ST_BIND(symbol_table_[symbol_id].st_info) == STB_WEAK; -} - -const char* DynamicSection::LookupNameById(size_t symbol_id) const { - const Sym* sym = LookupById(symbol_id); - // TODO: Confirm that LookupById actually can return NULL. - if (!sym) - return NULL; - return string_table_ + sym->st_name; -} - -const Sym* DynamicSection::LookupByName(const char* symbol_name) const { - const Sym* sym = - gnu_hash_.IsValid() - ? gnu_hash_.LookupByName(symbol_name, symbol_table_, string_table_) - : elf_hash_.LookupByName(symbol_name, symbol_table_, string_table_); - - // Ignore undefined symbols or those that are not global or weak definitions. - if (!sym || sym->st_shndx == SHN_UNDEF) - return NULL; - - uint8_t info = ELF_ST_BIND(sym->st_info); - if (info != STB_GLOBAL && info != STB_WEAK) - return NULL; - - return sym; -} - -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/dynamic_section.h b/src/starboard/elf_loader/dynamic_section.h deleted file mode 100644 index eec44c2..0000000 --- a/src/starboard/elf_loader/dynamic_section.h +++ /dev/null
@@ -1,106 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_ -#define STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_ - -#include "starboard/elf_loader/elf.h" -#include "starboard/elf_loader/elf_hash_table.h" -#include "starboard/elf_loader/exported_symbols.h" -#include "starboard/elf_loader/gnu_hash_table.h" -#include "starboard/elf_loader/program_table.h" - -namespace starboard { -namespace elf_loader { - -typedef void (*linker_function_t)(); - -// class representing the ELF dynamic -// section with dynamic symbols and a -// string tables. - -// The initialization requires calling: -// 1. InitDynamicSection() -// 2. InitDynamicSymbols() -// -class DynamicSection { - public: - DynamicSection(Addr base_memory_address, - Dyn* dynamic, - size_t dynamic_count, - Word dynamic_flags); - - // Initialize the dynamic section. - bool InitDynamicSection(); - - // Initialize all the dynamic symbol tables. - bool InitDynamicSymbols(); - - // Get pointer to the dynamic table. - const Dyn* GetDynamicTable(); - - // Get the size of the dynamic table - size_t GetDynamicTableSize(); - - // Call all the global constructors. - void CallConstructors(); - - // Call all the global destructors. - void CallDestructors(); - - // Call a function. - void CallFunction(linker_function_t func, const char* func_type); - - // Lookup a symbol using its name. - const Sym* LookupByName(const char* symbol_name) const; - - // Lookup a symbol using its id. - const Sym* LookupById(size_t symbol_id) const; - - // Checks if a symbols is weak. - bool IsWeakById(size_t symbol_id) const; - - // Lookup the name of a symbol by using its id. - const char* LookupNameById(size_t symbol_id) const; - - private: - Addr base_memory_address_; - const char* soname_; - - Dyn* dynamic_; - size_t dynamic_count_; - Word dynamic_flags_; - bool has_DT_SYMBOLIC_; - - Sym* symbol_table_; - const char* string_table_; - ElfHashTable elf_hash_; - GnuHashTable gnu_hash_; - - linker_function_t* preinit_array_; - size_t preinit_array_count_; - linker_function_t* init_array_; - size_t init_array_count_; - linker_function_t* fini_array_; - size_t fini_array_count_; - linker_function_t init_func_; - linker_function_t fini_func_; - - SB_DISALLOW_COPY_AND_ASSIGN(DynamicSection); -}; - -} // namespace elf_loader -} // namespace starboard - -#endif // STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_
diff --git a/src/starboard/elf_loader/dynamic_section_test.cc b/src/starboard/elf_loader/dynamic_section_test.cc deleted file mode 100644 index 8ee45bf..0000000 --- a/src/starboard/elf_loader/dynamic_section_test.cc +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/elf_loader_impl.h" - -#include "starboard/common/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) -namespace starboard { -namespace elf_loader { - -namespace { - -// TODO: implement -class DynamicSection : public ::testing::Test { - protected: - DynamicSection() {} - ~DynamicSection() {} -}; - -TEST_F(DynamicSection, Initialize) { - EXPECT_TRUE(true); -} - -} // namespace -} // namespace elf_loader -} // namespace starboard -#endif // SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/elf.h b/src/starboard/elf_loader/elf.h deleted file mode 100644 index 1ecd908..0000000 --- a/src/starboard/elf_loader/elf.h +++ /dev/null
@@ -1,651 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_ELF_H_ -#define STARBOARD_ELF_LOADER_ELF_H_ - -// Subset of the ELF specification for loading Dynamic Shared Libraries. -// System V Application Binary Interface - DRAFT - 10 June 2013 -// http://www.sco.com/developers/gabi/latest/contents.html - -#ifndef __cplusplus -#error "Only C++ files can include this header." -#endif - -#include "starboard/types.h" - -namespace starboard { -namespace elf_loader { - -// 32 bit data types - -// Unsigned program address - 4 bytes. -typedef uint32_t Elf32_Addr; - -// Unsigned medium integer - 2 bytes. -typedef uint16_t Elf32_Half; - -// Unsigned file offset - 4 bytes. -typedef uint32_t Elf32_Off; - -// Signed large integer - 4 bytes. -typedef int32_t Elf32_Sword; - -// Unsigned large integer - 4 bytes. -typedef uint32_t Elf32_Word; - -// 64 bit data types - -// Unsigned program address - 8 bytes. -typedef uint64_t Elf64_Addr; - -// Unsigned file offset - 8 bytes. -typedef uint64_t Elf64_Off; - -// Unsigned medium intege 2 - bytes. -typedef uint16_t Elf64_Half; - -// Unsigned integer - 4 bytes. -typedef uint32_t Elf64_Word; - -// Signed integer - 4 bytes. -typedef int32_t Elf64_Sword; - -// Unsigned long integer - 8 bytes. -typedef uint64_t Elf64_Xword; - -// Signed long integer - 8 bytes. -typedef int64_t Elf64_Sxword; - -#define EI_NIDENT (16) - -// Pack all the structs at 1 byte alignment. -#pragma pack(push) -#pragma pack(1) - -// 32 bit ELF file header. -typedef struct { - // The initial bytes mark the file as an object file and provide - // machine-independent data. - unsigned char e_ident[EI_NIDENT]; - - // The object file type. We support only ET_DYN. - Elf32_Half e_type; - - // Architecture of the file. - Elf32_Half e_machine; - - // Object file version. The value should be 1. - Elf32_Word e_version; - - // Virtual address to which the system first transfers - // control, thus starting the process. - Elf32_Addr e_entry; - - // Program header table's file offset in bytes. - Elf32_Off e_phoff; - - // Section header table's file offset in bytes. - Elf32_Off e_shoff; - - // Processor-specific flags associated with the file. - Elf32_Word e_flags; - - // ELF header's size in bytes. - Elf32_Half e_ehsize; - - // Size in bytes of one entry in the file's program header table - Elf32_Half e_phentsize; - - // The number of entries in the program header table. - Elf32_Half e_phnum; - - // Section header's size in bytes. - Elf32_Half e_shentsize; - - // The number of entries in the section header table. - Elf32_Half e_shnum; - - // The section header table index of the entry associated - // with the section name string table. - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -// 64 bit ELF file header. -typedef struct { - // The initial bytes mark the file as an object file and provide - // machine-independent data. - unsigned char e_ident[EI_NIDENT]; - - // The object file type. We support only ET_DYN. - Elf64_Half e_type; - - // Architecture of the file. - Elf64_Half e_machine; - - // Object file version. The value should be 1. - Elf64_Word e_version; - - // Virtual address to which the system first transfers - // control, thus starting the process. - Elf64_Addr e_entry; - - // Program header table's file offset in bytes. - Elf64_Off e_phoff; - - // Section header table's file offset in bytes. - Elf64_Off e_shoff; - - // Processor-specific flags associated with the file. - Elf64_Word e_flags; - - // This member holds the ELF header's size in bytes. - Elf64_Half e_ehsize; - - // Size in bytes of one entry in the file's program header table - Elf64_Half e_phentsize; - - // The number of entries in the section header table. - Elf64_Half e_phnum; - - // Section header's size in bytes. - Elf64_Half e_shentsize; - - // The number of entries in the section header table. - Elf64_Half e_shnum; - - // The section header table index of the entry associated - // with the section name string table. - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -// 32 bit Program header. -typedef struct { - // The kind of segment this array element describes. - Elf32_Word p_type; - - // The offset from the beginning of the file at which the - // first byte of the segment resides. - Elf32_Off p_offset; - - // The virtual address at which the first byte of the - // segment resides in memory. - Elf32_Addr p_vaddr; - - // Segment's physical address. Unused for shared libraries. - Elf32_Addr p_paddr; - - // The number of bytes in the file image of the segment. May be zero. - Elf32_Word p_filesz; - - // The number of bytes in the memory image of the segment. May be zero. - Elf32_Word p_memsz; - - // Segment flags - Elf32_Word p_flags; - - // Segment alignment constraint. - Elf32_Word p_align; -} Elf32_Phdr; - -// 64 bit Program header. -typedef struct { - // The kind of segment this array element describes. - Elf64_Word p_type; - - // Segment flags - Elf64_Word p_flags; - - // The offset from the beginning of the file at which the - // first byte of the segment resides. - Elf64_Off p_offset; - - // The virtual address at which the first byte of the - // segment resides in memory. - Elf64_Addr p_vaddr; - - // Segment's physical address. Unused for shared libraries. - Elf64_Addr p_paddr; - - // The number of bytes in the file image of the segment. May be zero. - Elf64_Xword p_filesz; - - // The number of bytes in the memory image of the segment. May be zero. - Elf64_Xword p_memsz; - - // Segment alignment constraint - Elf64_Xword p_align; -} Elf64_Phdr; - -// 32 bit Dynamic Section Entry -typedef struct { - // Controls the interpretation of d_un. - Elf32_Sword d_tag; - union { - // These objects represent integer values with various interpretations. - Elf32_Word d_val; - // These objects represent program virtual addresses. - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; - -// 64 bit Dynamic Section Entry -typedef struct { - // Controls the interpretation of d_un. - Elf64_Sxword d_tag; - union { - // These objects represent integer values with various interpretations. - Elf64_Xword d_val; - // These objects represent program virtual addresses. - Elf64_Addr d_ptr; - } d_un; -} Elf64_Dyn; - -// 32 bit Symbol Table Entry -typedef struct { - // An index into the object file's symbol string table, - // which holds the character representations of the symbol names. If the value - // is non-zero, it represents a string table index that gives the symbol name. - // Otherwise, the symbol table entry has no name. - Elf32_Word st_name; - - // The value of the associated symbol. Depending on the - // context, this may be an absolute value, an address, and so on; - Elf32_Addr st_value; - - // Many symbols have associated sizes. For example, a data object's size is - // the number of bytes contained in the object. - Elf32_Word st_size; - - // The symbol's type and binding attributes. - unsigned char st_info; - - // Symbol's visibility. - unsigned char st_other; - - // Every symbol table entry is defined in relation to some section. This - // member holds the relevant section header table index. - Elf32_Half st_shndx; -} Elf32_Sym; - -// 64 bit Symbol Table Entry -typedef struct { - // An index into the object file's symbol string table, - // which holds the character representations of the symbol names. If the value - // is non-zero, it represents a string table index that gives the symbol name. - // Otherwise, the symbol table entry has no name. - Elf64_Word st_name; - - // The symbol's type and binding attributes. - unsigned char st_info; - - // Symbol's visibility. - unsigned char st_other; - - // Every symbol table entry is defined in relation to some section. This - // member holds the relevant section header table index. - Elf64_Half st_shndx; - - // The value of the associated symbol. Depending on the - // context, this may be an absolute value, an address, and so on; - Elf64_Addr st_value; - - // Many symbols have associated sizes. For example, a data object's size is - // the number of bytes contained in the object. - Elf64_Xword st_size; -} Elf64_Sym; - -// 32 bit Relocation Entry -typedef struct { - // The location at which to apply the relocation action. For a relocatable - // file, the value is the byte offset from the beginning of the section to - // the storage unit affected by the relocation. For an executable file or a - // shared object, the value is the virtual address of the storage unit - // affected by the relocation. - Elf32_Addr r_offset; - // The symbol table index with respect to which the - // relocation must be made, and the type of relocation to apply. - Elf32_Word r_info; -} Elf32_Rel; - -// 64 bit Relocation Entry -typedef struct { - // The location at which to apply the relocation action. For - // a relocatable file, the value is the byte offset from the beginning of the - // section to the storage unit affected by the relocation. For an executable - // file or a shared object, the value is the virtual address of the storage - // unit affected by the relocation. - Elf64_Addr r_offset; - - // The symbol table index with respect to which the - // relocation must be made, and the type of relocation to apply. - Elf64_Xword r_info; -} Elf64_Rel; - -// 32 bit Relocation Entry with Addend. -typedef struct { - // The location at which to apply the relocation action. For - // a relocatable file, the value is the byte offset from the beginning of the - // section to the storage unit affected by the relocation. For an executable - // file or a shared object, the value is the virtual address of the storage - // unit affected by the relocation. - Elf32_Addr r_offset; - - // The symbol table index with respect to which the - // relocation must be made, and the type of relocation to apply. - Elf32_Word r_info; - - // A constant addend used to compute the value to be stored into the - // relocatable field. - Elf32_Sword r_addend; -} Elf32_Rela; - -// 64 bit Relocation Entry with Addend. -typedef struct { - // The location at which to apply the relocation action. For a relocatable - // file, the value is the byte offset from the beginning of the section to the - // storage unit affected by the relocation. For an executable file or a shared - // object, the value is the virtual address of the storage unit affected by - // the relocation. - Elf64_Addr r_offset; - - // The symbol table index with respect to which the - // relocation must be made, and the type of relocation to apply. - Elf64_Xword r_info; - - // A constant addend used to compute the value to be stored into the - // relocatable field. - Elf64_Sxword r_addend; -} Elf64_Rela; - -#pragma pack(pop) - -#define EI_CLASS 4 -#define ELFCLASS32 1 -#define ELFCLASS64 2 -#define EI_DATA 5 -#define ELFDATA2LSB 1 -#define ET_DYN 3 -#define EV_CURRENT 1 - -#if SB_HAS(32_BIT_POINTERS) -typedef Elf32_Ehdr Ehdr; -typedef Elf32_Phdr Phdr; -typedef Elf32_Addr Addr; -typedef Elf32_Dyn Dyn; -typedef Elf32_Word Word; -typedef Elf32_Sym Sym; -typedef Elf32_Rel Rel; -typedef Elf32_Rela Rela; -typedef Elf32_Word Relr; -typedef Elf32_Sword Sword; -#define ELF_BITS 32 -#define ELF_R_TYPE ELF32_R_TYPE -#define ELF_R_SYM ELF32_R_SYM -#define ELF_CLASS_VALUE ELFCLASS32 -#elif SB_HAS(64_BIT_POINTERS) -typedef Elf64_Ehdr Ehdr; -typedef Elf64_Phdr Phdr; -typedef Elf64_Addr Addr; -typedef Elf64_Dyn Dyn; -typedef Elf64_Word Word; -typedef Elf64_Sym Sym; -typedef Elf64_Rel Rel; -typedef Elf64_Rela Rela; -typedef Elf64_Word Relr; -typedef Elf64_Sword Sword; -#define ELF_BITS 64 -#define ELF_R_TYPE ELF64_R_TYPE -#define ELF_R_SYM ELF64_R_SYM -#define ELF_CLASS_VALUE ELFCLASS64 -#else -#error "Unsupported pointer size" -#endif - -#define ELF32_R_SYM(val) ((val) >> 8) -#define ELF32_R_TYPE(val) ((val)&0xff) -#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type)&0xff)) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i)&0xffffffff) -#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)(sym)) << 32) + (type)) - -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -// TODO: Refactor the code to detect it at runtime -// using DT_PLTREL. -#if (SB_IS(ARCH_ARM) || SB_IS(ARCH_X86)) && SB_IS(64_BIT) -#define USE_RELA -#endif - -#if defined(USE_RELA) -typedef Rela rel_t; -#else -typedef Rel rel_t; -#endif - -#if SB_IS(ARCH_ARM) && SB_IS(32_BIT) -#define ELF_MACHINE 40 -#elif SB_IS(ARCH_X86) && SB_IS(32_BIT) -#define ELF_MACHINE 3 -#elif SB_IS(ARCH_X86) && SB_IS(64_BIT) -#define ELF_MACHINE 62 -#elif SB_IS(ARCH_ARM) && SB_IS(64_BIT) -#define ELF_MACHINE 183 -#else -#error "Unsupported target CPU architecture" -#endif - -// Segment types. -typedef enum SegmentTypes { - // Unused segment. - PT_NULL = 0, - - // Loadable segment. - PT_LOAD = 1, - - // Dynamic linking information. - PT_DYNAMIC = 2, - - // Interpreter pathname. - PT_INTERP = 3, - - // Auxiliary information. - PT_NOTE = 4, - - // Reserved. - PT_SHLIB = 5, - - // The program header table itself. - PT_PHDR = 6, - - // The thread-local storage template. - PT_TLS = 7 -} SegmentTypes; - -// Symbol bindings. -typedef enum SymbolBindings { - // Local symbol, not visible outside obj file containing def - STB_LOCAL = 0, - - // Global symbol, visible to all object files being combined - STB_GLOBAL = 1, - - // Weak symbol, like global but lower-precedence - STB_WEAK = 2, - - STB_GNU_UNIQUE = 10, - - // Lowest operating system-specific binding type - STB_LOOS = 10, - - // Highest operating system-specific binding type - STB_HIOS = 12, - - // Lowest processor-specific binding type - STB_LOPROC = 13, - - // Highest processor-specific binding type - STB_HIPROC = 15 -} SymbolBindings; - -#define ELF_ST_BIND(x) ((x) >> 4) -#define ELF32_ST_BIND(x) ELF_ST_BIND(x) -#define ELF64_ST_BIND(x) ELF_ST_BIND(x) - -#define PF_X (1 << 0) -#define PF_W (1 << 1) -#define PF_R (1 << 2) -#define PF_MASKOS 0x0ff00000 -#define PF_MASKPROC 0xf0000000 - -// Dynamic table tags. -typedef enum DynamicTags { - DT_NULL = 0, - DT_NEEDED = 1, - DT_PLTRELSZ = 2, - DT_PLTGOT = 3, - DT_HASH = 4, - DT_STRTAB = 5, - DT_SYMTAB = 6, - DT_RELA = 7, - DT_RELASZ = 8, - DT_RELAENT = 9, - DT_STRSZ = 10, - DT_SYMENT = 11, - DT_INIT = 12, - DT_FINI = 13, - DT_SONAME = 14, - DT_RPATH = 15, - DT_SYMBOLIC = 16, - DT_REL = 17, - DT_RELSZ = 18, - DT_RELENT = 19, - DT_PLTREL = 20, - DT_DEBUG = 21, - DT_TEXTREL = 22, - DT_JMPREL = 23, - DT_BIND_NOW = 24, - DT_INIT_ARRAY = 25, - DT_FINI_ARRAY = 26, - DT_INIT_ARRAYSZ = 27, - DT_FINI_ARRAYSZ = 28, - DT_RUNPATH = 29, - DT_FLAGS = 30, - DT_ENCODING = 32, - DT_PREINIT_ARRAY = 32, - DT_PREINIT_ARRAYSZ = 33, - DT_SYMTAB_SHNDX = 34, - DT_RELRSZ = 35, - DT_RELR = 36, - DT_RELRENT = 37, - DT_LOOS = 0x6000000D, - DT_ANDROID_REL = 0x6000000F, - DT_ANDROID_RELSZ = 0x60000010, - DT_ANDROID_RELA = 0x60000011, - DT_ANDROID_RELASZ = 0x60000012, - DT_HIOS = 0x6ffff000, - DT_ANDROID_RELR = 0x6fffe000, - DT_ANDROID_RELRSZ = 0x6fffe001, - DT_ANDROID_RELRENT = 0x6fffe003, - DT_GNU_HASH = 0x6ffffef5, - DT_LOPROC = 0x70000000, - DT_HIPROC = 0x7fffffff, -} DynamicTags; - -typedef enum DynamicFlags { - // This flag signifies that the object being loaded may make reference to the - DF_ORIGIN = 0x00000001, - - // If this flag is set in a shared object library, the dynamic linker's symbol - // resolution algorithm for references within the library is changed. Instead - // of starting a symbol search with the executable file, the dynamic linker - // starts from the shared object itself. If the shared object fails to supply - // the referenced symbol, the dynamic linker then searches the executable file - // and other shared objects as usual. - DF_SYMBOLIC = 0x00000002, - - // This flag is not set, no relocation entry should cause a modification to a - // non-writable segment, as specified by the segment permissions in the - // program header table. - DF_TEXTREL = 0x00000004, - - // If set in a shared object or executable, this flag instructs the dynamic - // linker to process all relocations for the object containing this entry - // before transferring control to the program. - DF_BIND_NOW = 0x00000008, - - // If set in a shared object or executable, this flag instructs the dynamic - // linker to reject attempts to load this file dynamically. It indicates that - // the shared object or executable contains code using a static thread-local - // storage scheme. Implementations need not support any form of thread-local - // storage. - DF_STATIC_TLS = 0x00000010, -} DynamicFalgs; - -// Relocation types per CPU architecture -#if SB_IS(ARCH_ARM) && SB_IS(32_BIT) -typedef enum RelocationTypes { - R_ARM_ABS32 = 2, - R_ARM_REL32 = 3, - R_ARM_GLOB_DAT = 21, - R_ARM_JUMP_SLOT = 22, - R_ARM_COPY = 20, - R_ARM_RELATIVE = 23, -} RelocationTypes; -#elif SB_IS(ARCH_ARM) && SB_IS(64_BIT) -typedef enum RelocationTypes { - R_AARCH64_ABS64 = 257, - R_AARCH64_COPY = 1024, - R_AARCH64_GLOB_DAT = 1025, - R_AARCH64_JUMP_SLOT = 1026, - R_AARCH64_RELATIVE = 1027, -} RelocationTypes; -#elif SB_IS(ARCH_X86) && SB_IS(32_BIT) -typedef enum RelocationTypes { - R_386_32 = 1, - R_386_PC32 = 2, - R_386_GLOB_DAT = 6, - R_386_JMP_SLOT = 7, - R_386_RELATIVE = 8, -} RelocationTypes; -#elif SB_IS(ARCH_X86) && SB_IS(64_BIT) -typedef enum RelocationTypes { - R_X86_64_64 = 1, - R_X86_64_PC32 = 2, - R_X86_64_GLOB_DAT = 6, - R_X86_64_JMP_SLOT = 7, - R_X86_64_RELATIVE = 8, -} RelocationTypes; -#else -#error "Unsupported architecture for relocations." -#endif - -// Helper macros for memory page computations. -#ifndef PAGE_SIZE -#define PAGE_SHIFT 12 -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE - 1)) -#endif - -#define PAGE_START(x) ((x)&PAGE_MASK) -#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK) -#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE - 1)) - -#define SHN_UNDEF 0 - -} // namespace elf_loader -} // namespace starboard -#endif // STARBOARD_ELF_LOADER_ELF_H_
diff --git a/src/starboard/elf_loader/elf_hash_table.cc b/src/starboard/elf_loader/elf_hash_table.cc deleted file mode 100644 index b6b6c70..0000000 --- a/src/starboard/elf_loader/elf_hash_table.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/elf_hash_table.h" -#include "starboard/string.h" - -namespace starboard { -namespace elf_loader { - -// Compute the ELF hash of a given symbol. -// Defined in -// https://refspecs.linuxfoundation.org/elf/gabi4+/ch5.dynamic.html#hash -static unsigned ElfHash(const char* name) { - const uint8_t* ptr = reinterpret_cast<const uint8_t*>(name); - unsigned h = 0; - while (*ptr) { - h = (h << 4) + *ptr++; - unsigned g = h & 0xf0000000; - h ^= g; - h ^= g >> 24; - } - return h; -} - -ElfHashTable::ElfHashTable() - : hash_bucket_(NULL), - hash_bucket_size_(0), - hash_chain_(NULL), - hash_chain_size_(0) {} -void ElfHashTable::Init(uintptr_t dt_elf_hash) { - const Word* data = reinterpret_cast<const Word*>(dt_elf_hash); - hash_bucket_size_ = data[0]; - hash_bucket_ = data + 2; - hash_chain_size_ = data[1]; - hash_chain_ = hash_bucket_ + hash_bucket_size_; -} - -bool ElfHashTable::IsValid() const { - return hash_bucket_size_ > 0; -} - -const Sym* ElfHashTable::LookupByName(const char* symbol_name, - const Sym* symbol_table, - const char* string_table) const { - unsigned hash = ElfHash(symbol_name); - - for (unsigned n = hash_bucket_[hash % hash_bucket_size_]; n != 0; - n = hash_chain_[n]) { - const Sym* symbol = &symbol_table[n]; - // Check that the symbol has the appropriate name. - if (!SbStringCompareAll(string_table + symbol->st_name, symbol_name)) - return symbol; - } - return NULL; -} - -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_hash_table.h b/src/starboard/elf_loader/elf_hash_table.h deleted file mode 100644 index 14bb9ca..0000000 --- a/src/starboard/elf_loader/elf_hash_table.h +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_ -#define STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_ - -#include <stddef.h> -#include "starboard/elf_loader/elf.h" - -namespace starboard { -namespace elf_loader { - -// Models the hash table used to map symbol names to symbol entries using -// the standard ELF format. -class ElfHashTable { - public: - ElfHashTable(); - // Initialize instance. |dt_elf_hash| should be the address that the - // DT_HASH entry points to in the input ELF dynamic section. Call IsValid() - // to determine whether the table was well-formed. - void Init(uintptr_t dt_elf_hash); - - // Returns true iff the content of the table is valid. - bool IsValid() const; - - // Index of the first dynamic symbol within the ELF symbol table. - size_t dyn_symbols_offset() const { return 1; } - - // Number of dynamic symbols in the ELF symbol table. - size_t dyn_symbols_count() const { return hash_chain_size_ - 1; } - - // Lookup |symbol_name| in the table. |symbol_table| should point to the - // ELF symbol table, and |string_table| to the start of its string table. - // Returns NULL on failure. - const Sym* LookupByName(const char* symbol_name, - const Sym* symbol_table, - const char* string_table) const; - - private: - const Word* hash_bucket_; - size_t hash_bucket_size_; - const Word* hash_chain_; - size_t hash_chain_size_; - - SB_DISALLOW_COPY_AND_ASSIGN(ElfHashTable); -}; - -} // namespace elf_loader -} // namespace starboard - -#endif // STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_
diff --git a/src/starboard/elf_loader/elf_header.cc b/src/starboard/elf_loader/elf_header.cc deleted file mode 100644 index bb3c07b..0000000 --- a/src/starboard/elf_loader/elf_header.cc +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/elf_header.h" - -#include "starboard/common/log.h" -#include "starboard/memory.h" - -namespace starboard { -namespace elf_loader { - -ElfHeader::ElfHeader() { - elf_header_.reset(new Ehdr()); -} - -bool ElfHeader::LoadElfHeader(File* file) { - SB_LOG(INFO) << "LoadElfHeader"; - if (!file->ReadFromOffset(0, reinterpret_cast<char*>(elf_header_.get()), - sizeof(Ehdr))) { - SB_LOG(ERROR) << "Failed to read file"; - return false; - } - - if (SbMemoryCompare(elf_header_->e_ident, ELFMAG, SELFMAG) != 0) { - SB_LOG(ERROR) << "Bad ELF magic: " << elf_header_->e_ident; - return false; - } - - if (elf_header_->e_ident[EI_CLASS] != ELF_CLASS_VALUE) { - SB_LOG(ERROR) << "Not a " << ELF_BITS - << "-bit class: " << elf_header_->e_ident[EI_CLASS]; - return false; - } - if (elf_header_->e_ident[EI_DATA] != ELFDATA2LSB) { - SB_LOG(ERROR) << "Not little-endian class" << elf_header_->e_ident[EI_DATA]; - return false; - } - - if (elf_header_->e_type != ET_DYN) { - SB_LOG(ERROR) << "Not a shared library type:" << std::hex - << elf_header_->e_type; - return false; - } - - if (elf_header_->e_version != EV_CURRENT) { - SB_LOG(ERROR) << "Unexpected ELF version: " << elf_header_->e_version; - return false; - } - - if (elf_header_->e_machine != ELF_MACHINE) { - SB_LOG(ERROR) << "Unexpected ELF machine type: " << std::hex - << elf_header_->e_machine; - return false; - } - - return true; -} - -const Ehdr* ElfHeader::GetHeader() { - return elf_header_.get(); -} - -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_header.h b/src/starboard/elf_loader/elf_header.h deleted file mode 100644 index a8b666c..0000000 --- a/src/starboard/elf_loader/elf_header.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_ELF_HEADER_H_ -#define STARBOARD_ELF_LOADER_ELF_HEADER_H_ - -#include "starboard/elf_loader/elf.h" - -#include "starboard/common/scoped_ptr.h" -#include "starboard/elf_loader/file.h" - -namespace starboard { -namespace elf_loader { - -// Class for loading, parsing and validating the ELF header section. -class ElfHeader { - public: - ElfHeader(); - - // Load, parse and validate the ELF header. - bool LoadElfHeader(File* file); - - // Get the actual header data. - const Ehdr* GetHeader(); - - private: - scoped_ptr<Ehdr> elf_header_; - SB_DISALLOW_COPY_AND_ASSIGN(ElfHeader); -}; - -} // namespace elf_loader -} // namespace starboard - -#endif // STARBOARD_ELF_LOADER_ELF_HEADER_H_
diff --git a/src/starboard/elf_loader/elf_header_test.cc b/src/starboard/elf_loader/elf_header_test.cc deleted file mode 100644 index e9dbc49..0000000 --- a/src/starboard/elf_loader/elf_header_test.cc +++ /dev/null
@@ -1,127 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/elf_header.h" - -#include "starboard/common/scoped_ptr.h" -#include "starboard/elf_loader/file.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) -namespace starboard { -namespace elf_loader { - -namespace { - -class DummyFile : public File { - public: - DummyFile(const char* buffer, int size) : buffer_(buffer), size_(size) {} - - bool Open(const char* name) { return true; } - bool ReadFromOffset(int64_t offset, char* buffer, int size) { - SB_LOG(INFO) << "ReadFromOffset"; - if (offset != 0) { - SB_LOG(ERROR) << "ReadFromOffset: Invalid offset " << offset; - return false; - } - if (size < size_) { - SB_LOG(ERROR) << "ReadFromOffset: Invalid size " << size; - return false; - } - SbMemoryCopy(buffer, buffer_, size); - return true; - } - void Close() {} - - private: - const char* buffer_; - int size_; -}; - -class ElfHeaderTest : public ::testing::Test { - protected: - ElfHeaderTest() { - elf_header_.reset(new ElfHeader()); - SbMemorySet(reinterpret_cast<char*>(&ehdr_data_), 0, sizeof(ehdr_data_)); - ehdr_data_.e_machine = ELF_MACHINE; - ehdr_data_.e_ident[0] = 0x7F; - ehdr_data_.e_ident[1] = 'E'; - ehdr_data_.e_ident[2] = 'L'; - ehdr_data_.e_ident[3] = 'F'; - ehdr_data_.e_ident[EI_CLASS] = ELF_CLASS_VALUE; - ehdr_data_.e_ident[EI_DATA] = ELFDATA2LSB; - ehdr_data_.e_type = ET_DYN; - ehdr_data_.e_version = EV_CURRENT; - ehdr_data_.e_machine = ELF_MACHINE; - - dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), - sizeof(ehdr_data_))); - } - ~ElfHeaderTest() {} - - scoped_ptr<ElfHeader> elf_header_; - Ehdr ehdr_data_; - scoped_ptr<DummyFile> dummy_file_; -}; - -TEST_F(ElfHeaderTest, Initialize) { - EXPECT_TRUE(elf_header_->LoadElfHeader(dummy_file_.get())); -} - -TEST_F(ElfHeaderTest, NegativeBadImage) { - ehdr_data_.e_ident[1] = 'F'; - dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), - sizeof(ehdr_data_))); - EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); -} - -TEST_F(ElfHeaderTest, NegativeBadClass) { - ehdr_data_.e_ident[EI_CLASS] = 0; - dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), - sizeof(ehdr_data_))); - EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); -} - -TEST_F(ElfHeaderTest, NegativeWrongGulliverLilliput) { - ehdr_data_.e_type = 2; - dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), - sizeof(ehdr_data_))); - EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); -} - -TEST_F(ElfHeaderTest, NegativeBadType) { - ehdr_data_.e_type = 2; - dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), - sizeof(ehdr_data_))); - EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); -} - -TEST_F(ElfHeaderTest, NegativeBadVersion) { - ehdr_data_.e_version = 2; - dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), - sizeof(ehdr_data_))); - EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); -} - -TEST_F(ElfHeaderTest, NegativeBadMachine) { - ehdr_data_.e_machine = 0; - dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_), - sizeof(ehdr_data_))); - EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get())); -} -} // namespace -} // namespace elf_loader -} // namespace starboard -#endif // SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/elf_loader.cc b/src/starboard/elf_loader/elf_loader.cc deleted file mode 100644 index d62d07a..0000000 --- a/src/starboard/elf_loader/elf_loader.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/elf_loader.h" -#include "starboard/common/log.h" -#include "starboard/elf_loader/elf_loader_impl.h" -#include "starboard/elf_loader/file_impl.h" - -namespace starboard { -namespace elf_loader { - -ElfLoader::~ElfLoader() {} - -bool ElfLoader::Load(const char* file_name) { - return impl_->Load(file_name); -} - -void* ElfLoader::LookupSymbol(const char* symbol) { - return impl_->LookupSymbol(symbol); -} - -ElfLoader::ElfLoader() { - impl_.reset(new ElfLoaderImpl()); -} - -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader.gyp b/src/starboard/elf_loader/elf_loader.gyp deleted file mode 100644 index 18529c2..0000000 --- a/src/starboard/elf_loader/elf_loader.gyp +++ /dev/null
@@ -1,167 +0,0 @@ -# Copyright 2019 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. - -{ - 'variables': { - 'common_elf_loader_sources': [ - 'elf_header.h', - 'elf_header.cc', - 'elf_hash_table.h', - 'elf_hash_table.cc', - 'elf_loader.h', - 'elf_loader.cc', - 'exported_symbols.cc', - 'file.h', - 'file_impl.h', - 'file_impl.cc', - 'gnu_hash_table.h', - 'gnu_hash_table.cc', - 'dynamic_section.h', - 'dynamic_section.cc', - 'program_table.h', - 'program_table.cc', - 'relocations.h', - 'relocations.cc', - ], - 'elf_loader_impl_sources': [ - 'elf_loader_impl.h', - 'elf_loader_impl.cc', - ], - 'elf_loader_sys_sources': [ - 'elf_loader_sys_impl.h', - 'elf_loader_sys_impl.cc', - ] - }, - 'targets': [ - { - 'target_name': 'elf_loader', - 'type': 'static_library', - 'include_dirs': [ - 'src/include', - 'src/src/', - ], - 'dependencies': [ - '<(DEPTH)/starboard/starboard.gyp:starboard', - ], - 'sources': [ - '<@(common_elf_loader_sources)', - '<@(elf_loader_impl_sources)', - ], - }, - { - # System loader based on dlopen/dlsym. - # Should be used only for debugging/troubleshooting. - 'target_name': 'elf_loader_sys', - 'type': 'static_library', - 'include_dirs': [ - 'src/include', - 'src/src/', - ], - 'dependencies': [ - '<(DEPTH)/starboard/starboard.gyp:starboard', - ], - 'sources': [ - '<@(common_elf_loader_sources)', - '<@(elf_loader_sys_sources)', - ], - }, - { - 'target_name': 'elf_loader_sandbox', - 'type': '<(final_executable_type)', - 'include_dirs': [ - 'src/include', - 'src/src/', - ], - 'dependencies': [ - 'elf_loader', - '<(DEPTH)/starboard/starboard.gyp:starboard_full', - ], - 'sources': [ - 'sandbox.cc', - ], - 'conditions': [ - # TODO: Remove this dependency once MediaSession is migrated to use CobaltExtensions. - ['target_os == "android"', { - 'dependencies': [ - '<(DEPTH)/starboard/android/shared/cobalt/cobalt_platform.gyp:cobalt_platform', - ], - }], - ], - }, - { - # To properly function the system loader requires the starboard - # symbols to be exported from the binary. - # To allow symbols to be exported remove the '-fvisibility=hidden' flag - # from your compiler_flags.gypi. - # Example run: - # export LD_LIBRARY_PATH=. - # out/linux-x64x11_qa/elf_loader_sys_sandbox out/evergreen-x64-sbversion-12_qa/lib/libcobalt_evergreen.so - # - 'target_name': 'elf_loader_sys_sandbox', - 'type': '<(final_executable_type)', - 'include_dirs': [ - 'src/include', - 'src/src/', - ], - 'dependencies': [ - 'elf_loader_sys', - '<(DEPTH)/starboard/starboard.gyp:starboard_full', - ], - 'sources': [ - 'sandbox.cc', - ], - 'ldflags': [ - '-Wl,--dynamic-list=<(DEPTH)/starboard/starboard.syms', - '-ldl' , - ], - }, - { - 'target_name': 'elf_loader_test', - 'type': '<(gtest_target_type)', - 'sources': [ - '<(DEPTH)/starboard/common/test_main.cc', - ], - 'dependencies': [ - '<(DEPTH)/starboard/starboard.gyp:starboard_full', - '<(DEPTH)/testing/gmock.gyp:gmock', - '<(DEPTH)/testing/gtest.gyp:gtest', - ], - 'conditions': [ - ['target_arch in ["x86", "x64", "arm", "arm64"] and target_os in ["linux", "android" ] ', { - 'sources': [ - 'elf_loader_test.cc', - 'elf_header_test.cc', - 'dynamic_section_test.cc', - 'program_table_test.cc', - 'relocations_test.cc', - ], - 'dependencies': [ - 'elf_loader', - ], - }], - ], - }, - { - 'target_name': 'elf_loader_test_deploy', - 'type': 'none', - 'dependencies': [ - 'elf_loader_test', - ], - 'variables': { - 'executable_name': 'elf_loader_test', - }, - 'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ], - }, - ] -}
diff --git a/src/starboard/elf_loader/elf_loader.h b/src/starboard/elf_loader/elf_loader.h deleted file mode 100644 index 7bda25d..0000000 --- a/src/starboard/elf_loader/elf_loader.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_H_ -#define STARBOARD_ELF_LOADER_ELF_LOADER_H_ - -#include "starboard/common/scoped_ptr.h" - -namespace starboard { -namespace elf_loader { - -class ElfLoaderImpl; - -// A loader for ELF dynamic shared library. -class ElfLoader { - public: - ElfLoader(); - - // Loads the shared library - bool Load(const char* file_name); - - // Looks up the symbol address in the - // shared library. - void* LookupSymbol(const char* symbol); - - ~ElfLoader(); - - private: - scoped_ptr<ElfLoaderImpl> impl_; - - SB_DISALLOW_COPY_AND_ASSIGN(ElfLoader); -}; - -} // namespace elf_loader -} // namespace starboard -#endif // STARBOARD_ELF_LOADER_ELF_LOADER_H_
diff --git a/src/starboard/elf_loader/elf_loader_impl.cc b/src/starboard/elf_loader/elf_loader_impl.cc deleted file mode 100644 index 733da88..0000000 --- a/src/starboard/elf_loader/elf_loader_impl.cc +++ /dev/null
@@ -1,145 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/elf_loader_impl.h" -#include "starboard/common/log.h" -#include "starboard/elf_loader/elf.h" -#include "starboard/elf_loader/file_impl.h" -#include "starboard/memory.h" -#include "starboard/string.h" - -namespace starboard { -namespace elf_loader { - -ElfLoaderImpl::ElfLoaderImpl() { -#if SB_API_VERSION < 12 || !SB_HAS(MMAP) || !SB_CAN(MAP_EXECUTABLE_MEMORY) - SB_CHECK(false) << "The elf_loader requires SB_API_VERSION >= 12 with " - "executable memory map support!"; -#endif -} - -bool ElfLoaderImpl::Load(const char* name) { - SB_LOG(INFO) << "Loading: " << name; - elf_file_.reset(new FileImpl()); - elf_file_->Open(name); - - elf_header_loader_.reset(new ElfHeader()); - if (!elf_header_loader_->LoadElfHeader(elf_file_.get())) { - SB_LOG(ERROR) << "Failed to loaded ELF header"; - return false; - } - - SB_LOG(INFO) << "Loaded ELF header"; - - program_table_.reset(new ProgramTable()); - program_table_->LoadProgramHeader(elf_header_loader_->GetHeader(), - elf_file_.get()); - - SB_LOG(INFO) << "Loaded Program header"; - - if (!program_table_->ReserveLoadMemory()) { - SB_LOG(ERROR) << "Failed to reserve memory space"; - return false; - } - - SB_LOG(INFO) << "Reserved address space"; - - if (!program_table_->LoadSegments(elf_file_.get())) { - SB_LOG(ERROR) << "Failed to load segments"; - return false; - } - SB_LOG(INFO) << "Loaded segments"; - - Dyn* dynamic = NULL; - size_t dynamic_count = 0; - Word dynamic_flags = 0; - program_table_->GetDynamicSection(&dynamic, &dynamic_count, &dynamic_flags); - if (!dynamic) { - SB_LOG(ERROR) << "No PT_DYNAMIC section!"; - return false; - } - dynamic_section_.reset( - new DynamicSection(program_table_->GetBaseMemoryAddress(), dynamic, - dynamic_count, dynamic_flags)); - if (!dynamic_section_->InitDynamicSection()) { - SB_LOG(ERROR) << "Failed to initialize dynamic section"; - return false; - } - SB_LOG(INFO) << "Initialized dynamic section"; - if (!dynamic_section_->InitDynamicSymbols()) { - SB_LOG(ERROR) << "Failed to load dynamic symbols"; - return false; - } - SB_LOG(INFO) << "Initialized dynamic symbols"; - - exported_symbols_.reset(new ExportedSymbols()); - relocations_.reset(new Relocations(program_table_->GetBaseMemoryAddress(), - dynamic_section_.get(), - exported_symbols_.get())); - if (!relocations_->InitRelocations()) { - SB_LOG(ERROR) << "Failed to initialize relocations"; - return false; - } - if (relocations_->HasTextRelocations()) { - SB_LOG(INFO) << "HasTextRelocations"; - // Adjust the memory protection to its to allow modifications. - if (program_table_->AdjustMemoryProtectionOfReadOnlySegments( - kSbMemoryMapProtectWrite) < 0) { - SB_LOG(ERROR) << "Unable to make segments writable"; - return false; - } - } - SB_LOG(INFO) << "Loaded relocations"; - if (!relocations_->ApplyAllRelocations()) { - SB_LOG(ERROR) << "Failed to apply relocations"; - return false; - } - - if (relocations_->HasTextRelocations()) { - // Restores the memory protection to its original state. -#if SB_API_VERSION >= 10 && SB_HAS(MMAP) - if (program_table_->AdjustMemoryProtectionOfReadOnlySegments( - kSbMemoryMapProtectReserved) < 0) { - SB_LOG(ERROR) << "Unable to restore segment protection"; - return false; - } -#else - SB_CHECK(false); -#endif - } - - SB_LOG(INFO) << "Applied relocations"; - - SB_LOG(INFO) << "Call constructors"; - dynamic_section_->CallConstructors(); - - SB_LOG(INFO) << "Finished loading"; - - return true; -} -void* ElfLoaderImpl::LookupSymbol(const char* symbol) { - const Sym* sym = dynamic_section_->LookupByName(symbol); - void* address = NULL; - if (sym) { - address = reinterpret_cast<void*>(program_table_->GetBaseMemoryAddress() + - sym->st_value); - } - return address; -} - -ElfLoaderImpl::~ElfLoaderImpl() { - dynamic_section_->CallDestructors(); -} -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader_impl.h b/src/starboard/elf_loader/elf_loader_impl.h deleted file mode 100644 index b317ecf..0000000 --- a/src/starboard/elf_loader/elf_loader_impl.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_ -#define STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_ - -#include "starboard/common/scoped_ptr.h" -#include "starboard/elf_loader/dynamic_section.h" -#include "starboard/elf_loader/elf.h" -#include "starboard/elf_loader/elf_hash_table.h" -#include "starboard/elf_loader/elf_header.h" -#include "starboard/elf_loader/exported_symbols.h" -#include "starboard/elf_loader/file.h" -#include "starboard/elf_loader/gnu_hash_table.h" -#include "starboard/elf_loader/program_table.h" -#include "starboard/elf_loader/relocations.h" - -namespace starboard { -namespace elf_loader { - -// Implementation of the elf loader. -class ElfLoaderImpl { - public: - ElfLoaderImpl(); - bool Load(const char* file_name); - void* LookupSymbol(const char* symbol); - ~ElfLoaderImpl(); - - private: - scoped_ptr<File> elf_file_; - scoped_ptr<ElfHeader> elf_header_loader_; - scoped_ptr<ProgramTable> program_table_; - scoped_ptr<DynamicSection> dynamic_section_; - scoped_ptr<ExportedSymbols> exported_symbols_; - scoped_ptr<Relocations> relocations_; - - SB_DISALLOW_COPY_AND_ASSIGN(ElfLoaderImpl); -}; - -} // namespace elf_loader -} // namespace starboard -#endif // STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_
diff --git a/src/starboard/elf_loader/elf_loader_sys_impl.cc b/src/starboard/elf_loader/elf_loader_sys_impl.cc deleted file mode 100644 index 40fa30b..0000000 --- a/src/starboard/elf_loader/elf_loader_sys_impl.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/elf_loader_sys_impl.h" - -#include <dlfcn.h> - -#include "starboard/common/log.h" -#include "starboard/elf_loader/exported_symbols.h" - -namespace starboard { -namespace elf_loader { - -ElfLoaderImpl::ElfLoaderImpl() {} - -bool ElfLoaderImpl::Load(const char* name) { - SB_LOG(INFO) << "Loading: " << name; - - // Creating the instance forces the binary to keep all the symbols. - ExportedSymbols symbols; - - handle_ = dlopen(name, RTLD_NOW); - if (!handle_) { - SB_LOG(ERROR) << "dlopen failure: " << dlerror(); - return false; - } - return true; -} - -void* ElfLoaderImpl::LookupSymbol(const char* symbol) { - if (handle_) { - void* p = dlsym(handle_, symbol); - if (!p) { - SB_LOG(ERROR) << "dlsym failure: " << dlerror(); - } - return p; - } - return NULL; -} - -ElfLoaderImpl::~ElfLoaderImpl() { - if (handle_) { - dlclose(handle_); - } -} -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader_sys_impl.h b/src/starboard/elf_loader/elf_loader_sys_impl.h deleted file mode 100644 index d8118c5..0000000 --- a/src/starboard/elf_loader/elf_loader_sys_impl.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_SYS_IMPL_H_ -#define STARBOARD_ELF_LOADER_ELF_LOADER_SYS_IMPL_H_ - -#include "starboard/common/scoped_ptr.h" - -namespace starboard { -namespace elf_loader { - -// Implementation of the elf loader. -class ElfLoaderImpl { - public: - ElfLoaderImpl(); - bool Load(const char* file_name); - void* LookupSymbol(const char* symbol); - ~ElfLoaderImpl(); - - private: - void* handle_; - - SB_DISALLOW_COPY_AND_ASSIGN(ElfLoaderImpl); -}; - -} // namespace elf_loader -} // namespace starboard -#endif // STARBOARD_ELF_LOADER_ELF_LOADER_SYS_IMPL_H_
diff --git a/src/starboard/elf_loader/elf_loader_test.cc b/src/starboard/elf_loader/elf_loader_test.cc deleted file mode 100644 index 6b6c3d8..0000000 --- a/src/starboard/elf_loader/elf_loader_test.cc +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/elf_loader_impl.h" - -#include "starboard/common/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) -namespace starboard { -namespace elf_loader { - -namespace { - -// TODO: implement using real shared library fro the file system. -class ElfLoaderTest : public ::testing::Test { - protected: - ElfLoaderTest() {} - ~ElfLoaderTest() {} -}; - -TEST_F(ElfLoaderTest, Initialize) { - EXPECT_TRUE(true); -} - -} // namespace -} // namespace elf_loader -} // namespace starboard -#endif // SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/exported_symbols.cc b/src/starboard/elf_loader/exported_symbols.cc deleted file mode 100644 index 56a9c0e..0000000 --- a/src/starboard/elf_loader/exported_symbols.cc +++ /dev/null
@@ -1,371 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/exported_symbols.h" - -#include "starboard/accessibility.h" -#include "starboard/audio_sink.h" -#include "starboard/byte_swap.h" -#include "starboard/character.h" -#include "starboard/condition_variable.h" -#include "starboard/configuration.h" -#include "starboard/cpu_features.h" -#include "starboard/cryptography.h" -#include "starboard/decode_target.h" -#include "starboard/directory.h" -#include "starboard/double.h" -#include "starboard/egl.h" -#include "starboard/event.h" -#include "starboard/file.h" -#include "starboard/gles.h" -#include "starboard/image.h" -#include "starboard/log.h" -#include "starboard/memory.h" -#include "starboard/microphone.h" -#include "starboard/mutex.h" -#include "starboard/once.h" -#include "starboard/player.h" -#include "starboard/socket.h" -#include "starboard/socket_waiter.h" -#include "starboard/speech_recognizer.h" -#include "starboard/speech_synthesis.h" -#include "starboard/storage.h" -#include "starboard/string.h" -#include "starboard/system.h" -#include "starboard/thread.h" -#include "starboard/time_zone.h" -#include "starboard/ui_navigation.h" - -#define REGISTER_SYMBOL(s) REGISTER_SYMBOL_AS(s, s) -#define REGISTER_SYMBOL_AS(k, v) \ - do { \ - map_[#k] = reinterpret_cast<const void*>(&v); \ - } while (0) - -namespace starboard { -namespace elf_loader { - -ExportedSymbols::ExportedSymbols() { - REGISTER_SYMBOL(SbAccessibilityGetDisplaySettings); - REGISTER_SYMBOL(SbAccessibilityGetTextToSpeechSettings); - REGISTER_SYMBOL(SbAudioSinkCreate); - REGISTER_SYMBOL(SbAudioSinkDestroy); - REGISTER_SYMBOL(SbAudioSinkGetMaxChannels); - REGISTER_SYMBOL(SbAudioSinkGetNearestSupportedSampleFrequency); - REGISTER_SYMBOL(SbAudioSinkIsAudioFrameStorageTypeSupported); - REGISTER_SYMBOL(SbAudioSinkIsAudioSampleTypeSupported); - REGISTER_SYMBOL(SbAudioSinkIsValid); - REGISTER_SYMBOL(SbByteSwapS16); - REGISTER_SYMBOL(SbByteSwapS32); - REGISTER_SYMBOL(SbByteSwapS64); - REGISTER_SYMBOL(SbByteSwapU16); - REGISTER_SYMBOL(SbByteSwapU32); - REGISTER_SYMBOL(SbByteSwapU64); - REGISTER_SYMBOL(SbCharacterIsAlphanumeric); - REGISTER_SYMBOL(SbCharacterIsDigit); - REGISTER_SYMBOL(SbCharacterIsHexDigit); - REGISTER_SYMBOL(SbCharacterIsSpace); - REGISTER_SYMBOL(SbCharacterIsUpper); - REGISTER_SYMBOL(SbCharacterToLower); - REGISTER_SYMBOL(SbCharacterToUpper); - REGISTER_SYMBOL(SbConditionVariableBroadcast); - REGISTER_SYMBOL(SbConditionVariableCreate); - REGISTER_SYMBOL(SbConditionVariableDestroy); - REGISTER_SYMBOL(SbConditionVariableSignal); - REGISTER_SYMBOL(SbConditionVariableWait); - REGISTER_SYMBOL(SbConditionVariableWaitTimed); - REGISTER_SYMBOL(SbCryptographyCreateTransformer); - REGISTER_SYMBOL(SbCryptographyDestroyTransformer); - REGISTER_SYMBOL(SbCryptographyGetTag); - REGISTER_SYMBOL(SbCryptographySetAuthenticatedData); - REGISTER_SYMBOL(SbCryptographySetInitializationVector); - REGISTER_SYMBOL(SbCryptographyTransform); - REGISTER_SYMBOL(SbDecodeTargetGetInfo); - REGISTER_SYMBOL(SbDecodeTargetRelease); - REGISTER_SYMBOL(SbDirectoryCanOpen); - REGISTER_SYMBOL(SbDirectoryClose); - REGISTER_SYMBOL(SbDirectoryCreate); - REGISTER_SYMBOL(SbDirectoryGetNext); - REGISTER_SYMBOL(SbDirectoryOpen); - REGISTER_SYMBOL(SbDoubleAbsolute); - REGISTER_SYMBOL(SbDoubleExponent); - REGISTER_SYMBOL(SbDoubleFloor); - REGISTER_SYMBOL(SbDoubleIsFinite); - REGISTER_SYMBOL(SbDoubleIsNan); - REGISTER_SYMBOL(SbDrmCloseSession); - REGISTER_SYMBOL(SbDrmCreateSystem); - REGISTER_SYMBOL(SbDrmDestroySystem); - REGISTER_SYMBOL(SbDrmGenerateSessionUpdateRequest); - REGISTER_SYMBOL(SbDrmUpdateSession); - REGISTER_SYMBOL(SbEventCancel); - REGISTER_SYMBOL(SbEventSchedule); - REGISTER_SYMBOL(SbFileCanOpen); - REGISTER_SYMBOL(SbFileClose); - REGISTER_SYMBOL(SbFileDelete); - REGISTER_SYMBOL(SbFileExists); - REGISTER_SYMBOL(SbFileFlush); - REGISTER_SYMBOL(SbFileGetInfo); - REGISTER_SYMBOL(SbFileGetPathInfo); - REGISTER_SYMBOL(SbFileModeStringToFlags); - REGISTER_SYMBOL(SbFileOpen); - REGISTER_SYMBOL(SbFileRead); - REGISTER_SYMBOL(SbFileSeek); - REGISTER_SYMBOL(SbFileTruncate); - REGISTER_SYMBOL(SbFileWrite); - REGISTER_SYMBOL(SbGetEglInterface); - REGISTER_SYMBOL(SbGetGlesInterface); - REGISTER_SYMBOL(SbImageDecode); - REGISTER_SYMBOL(SbImageIsDecodeSupported); - REGISTER_SYMBOL(SbLog); - REGISTER_SYMBOL(SbLogFlush); - REGISTER_SYMBOL(SbLogFormat); - REGISTER_SYMBOL(SbLogIsTty); - REGISTER_SYMBOL(SbLogRaw); - REGISTER_SYMBOL(SbLogRawDumpStack); - REGISTER_SYMBOL(SbLogRawFormat); - REGISTER_SYMBOL(SbMediaCanPlayMimeAndKeySystem); - REGISTER_SYMBOL(SbMemoryAllocateAlignedUnchecked); - REGISTER_SYMBOL(SbMemoryAllocateUnchecked); - REGISTER_SYMBOL(SbMemoryCompare); - REGISTER_SYMBOL(SbMemoryCopy); - REGISTER_SYMBOL(SbMemoryFindByte); - REGISTER_SYMBOL(SbMemoryFree); - REGISTER_SYMBOL(SbMemoryFreeAligned); - REGISTER_SYMBOL(SbMemoryGetStackBounds); - REGISTER_SYMBOL(SbMemoryMove); - REGISTER_SYMBOL(SbMemoryReallocateUnchecked); - REGISTER_SYMBOL(SbMemorySet); - REGISTER_SYMBOL(SbMutexAcquire); - REGISTER_SYMBOL(SbMutexAcquireTry); - REGISTER_SYMBOL(SbMutexCreate); - REGISTER_SYMBOL(SbMutexDestroy); - REGISTER_SYMBOL(SbMutexRelease); - REGISTER_SYMBOL(SbOnce); - REGISTER_SYMBOL(SbPlayerCreate); - REGISTER_SYMBOL(SbPlayerDestroy); - REGISTER_SYMBOL(SbPlayerGetCurrentFrame); - REGISTER_SYMBOL(SbPlayerOutputModeSupported); - REGISTER_SYMBOL(SbPlayerSetBounds); - REGISTER_SYMBOL(SbPlayerSetPlaybackRate); - REGISTER_SYMBOL(SbPlayerSetVolume); - REGISTER_SYMBOL(SbPlayerWriteEndOfStream); - REGISTER_SYMBOL(SbSocketAccept); - REGISTER_SYMBOL(SbSocketBind); - REGISTER_SYMBOL(SbSocketClearLastError); - REGISTER_SYMBOL(SbSocketConnect); - REGISTER_SYMBOL(SbSocketCreate); - REGISTER_SYMBOL(SbSocketDestroy); - REGISTER_SYMBOL(SbSocketFreeResolution); - REGISTER_SYMBOL(SbSocketGetInterfaceAddress); - REGISTER_SYMBOL(SbSocketGetLastError); - REGISTER_SYMBOL(SbSocketGetLocalAddress); - REGISTER_SYMBOL(SbSocketIsConnected); - REGISTER_SYMBOL(SbSocketIsConnectedAndIdle); - REGISTER_SYMBOL(SbSocketJoinMulticastGroup); - REGISTER_SYMBOL(SbSocketListen); - REGISTER_SYMBOL(SbSocketReceiveFrom); - REGISTER_SYMBOL(SbSocketResolve); - REGISTER_SYMBOL(SbSocketSendTo); - REGISTER_SYMBOL(SbSocketSetBroadcast); - REGISTER_SYMBOL(SbSocketSetReceiveBufferSize); - REGISTER_SYMBOL(SbSocketSetReuseAddress); - REGISTER_SYMBOL(SbSocketSetSendBufferSize); - REGISTER_SYMBOL(SbSocketSetTcpKeepAlive); - REGISTER_SYMBOL(SbSocketSetTcpNoDelay); - REGISTER_SYMBOL(SbSocketSetTcpWindowScaling); - REGISTER_SYMBOL(SbSocketWaiterAdd); - REGISTER_SYMBOL(SbSocketWaiterCreate); - REGISTER_SYMBOL(SbSocketWaiterDestroy); - REGISTER_SYMBOL(SbSocketWaiterRemove); - REGISTER_SYMBOL(SbSocketWaiterWait); - REGISTER_SYMBOL(SbSocketWaiterWaitTimed); - REGISTER_SYMBOL(SbSocketWaiterWakeUp); - REGISTER_SYMBOL(SbStorageCloseRecord); - REGISTER_SYMBOL(SbStorageDeleteRecord); - REGISTER_SYMBOL(SbStorageGetRecordSize); - REGISTER_SYMBOL(SbStorageOpenRecord); - REGISTER_SYMBOL(SbStorageReadRecord); - REGISTER_SYMBOL(SbStorageWriteRecord); - REGISTER_SYMBOL(SbStringCompare); - REGISTER_SYMBOL(SbStringCompareAll); - REGISTER_SYMBOL(SbStringCompareNoCase); - REGISTER_SYMBOL(SbStringCompareNoCaseN); - REGISTER_SYMBOL(SbStringCompareWide); - REGISTER_SYMBOL(SbStringConcat); - REGISTER_SYMBOL(SbStringConcatWide); - REGISTER_SYMBOL(SbStringCopy); - REGISTER_SYMBOL(SbStringCopyWide); - REGISTER_SYMBOL(SbStringDuplicate); - REGISTER_SYMBOL(SbStringFindCharacter); - REGISTER_SYMBOL(SbStringFindLastCharacter); - REGISTER_SYMBOL(SbStringFindString); - REGISTER_SYMBOL(SbStringFormat); - REGISTER_SYMBOL(SbStringFormatWide); - REGISTER_SYMBOL(SbStringGetLength); - REGISTER_SYMBOL(SbStringGetLengthWide); - REGISTER_SYMBOL(SbStringParseDouble); - REGISTER_SYMBOL(SbStringParseSignedInteger); - REGISTER_SYMBOL(SbStringParseUInt64); - REGISTER_SYMBOL(SbStringParseUnsignedInteger); - REGISTER_SYMBOL(SbStringScan); - REGISTER_SYMBOL(SbSystemBinarySearch); - REGISTER_SYMBOL(SbSystemBreakIntoDebugger); - REGISTER_SYMBOL(SbSystemClearLastError); - REGISTER_SYMBOL(SbSystemGetConnectionType); - REGISTER_SYMBOL(SbSystemGetDeviceType); - REGISTER_SYMBOL(SbSystemGetErrorString); - REGISTER_SYMBOL(SbSystemGetLastError); - REGISTER_SYMBOL(SbSystemGetLocaleId); - REGISTER_SYMBOL(SbSystemGetNumberOfProcessors); - REGISTER_SYMBOL(SbSystemGetPath); - REGISTER_SYMBOL(SbSystemGetProperty); - REGISTER_SYMBOL(SbSystemGetRandomData); - REGISTER_SYMBOL(SbSystemGetRandomUInt64); - REGISTER_SYMBOL(SbSystemGetStack); - REGISTER_SYMBOL(SbSystemGetTotalCPUMemory); - REGISTER_SYMBOL(SbSystemGetTotalGPUMemory); - REGISTER_SYMBOL(SbSystemGetUsedCPUMemory); - REGISTER_SYMBOL(SbSystemGetUsedGPUMemory); - REGISTER_SYMBOL(SbSystemHasCapability); - REGISTER_SYMBOL(SbSystemHideSplashScreen); - REGISTER_SYMBOL(SbSystemIsDebuggerAttached); - REGISTER_SYMBOL(SbSystemRaisePlatformError); - REGISTER_SYMBOL(SbSystemRequestPause); - REGISTER_SYMBOL(SbSystemRequestStop); - REGISTER_SYMBOL(SbSystemRequestSuspend); - REGISTER_SYMBOL(SbSystemRequestUnpause); - REGISTER_SYMBOL(SbSystemSort); - REGISTER_SYMBOL(SbSystemSymbolize); - REGISTER_SYMBOL(SbThreadCreate); - REGISTER_SYMBOL(SbThreadCreateLocalKey); - REGISTER_SYMBOL(SbThreadDestroyLocalKey); - REGISTER_SYMBOL(SbThreadDetach); - REGISTER_SYMBOL(SbThreadGetCurrent); - REGISTER_SYMBOL(SbThreadGetId); - REGISTER_SYMBOL(SbThreadGetLocalValue); - REGISTER_SYMBOL(SbThreadGetName); - REGISTER_SYMBOL(SbThreadIsEqual); - REGISTER_SYMBOL(SbThreadJoin); - REGISTER_SYMBOL(SbThreadSetLocalValue); - REGISTER_SYMBOL(SbThreadSetName); - REGISTER_SYMBOL(SbThreadSleep); - REGISTER_SYMBOL(SbThreadYield); - REGISTER_SYMBOL(SbTimeGetMonotonicNow); - REGISTER_SYMBOL(SbTimeGetNow); - REGISTER_SYMBOL(SbTimeZoneGetCurrent); - REGISTER_SYMBOL(SbTimeZoneGetName); - REGISTER_SYMBOL(SbUserGetCurrent); - REGISTER_SYMBOL(SbUserGetProperty); - REGISTER_SYMBOL(SbUserGetPropertySize); - REGISTER_SYMBOL(SbUserGetSignedIn); - REGISTER_SYMBOL(SbWindowCreate); - REGISTER_SYMBOL(SbWindowDestroy); - REGISTER_SYMBOL(SbWindowGetPlatformHandle); - REGISTER_SYMBOL(SbWindowGetSize); - REGISTER_SYMBOL(SbWindowSetDefaultOptions); - -#if SB_HAS(CAPTIONS) - REGISTER_SYMBOL(SbAccessibilityGetCaptionSettings); -#endif // SB_HAS(CAPTIONS) - -#if SB_CAN(MAP_EXECUTABLE_MEMORY) - REGISTER_SYMBOL(SbMemoryFlush); -#endif // SB_CAN(MAP_EXECUTABLE_MEMORY) - -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) - REGISTER_SYMBOL(SbMicrophoneClose); - REGISTER_SYMBOL(SbMicrophoneCreate); - REGISTER_SYMBOL(SbMicrophoneDestroy); - REGISTER_SYMBOL(SbMicrophoneGetAvailable); - REGISTER_SYMBOL(SbMicrophoneIsSampleRateSupported); - REGISTER_SYMBOL(SbMicrophoneOpen); - REGISTER_SYMBOL(SbMicrophoneRead); -#endif - -#if SB_HAS(MMAP) - REGISTER_SYMBOL(SbMemoryMap); - REGISTER_SYMBOL(SbMemoryUnmap); -#endif - -#if SB_HAS(SPEECH_SYNTHESIS) - REGISTER_SYMBOL(SbSpeechSynthesisCancel); - REGISTER_SYMBOL(SbSpeechSynthesisSpeak); -#endif - -#if SB_HAS(TIME_THREAD_NOW) - REGISTER_SYMBOL(SbTimeGetMonotonicThreadNow); -#endif - -#if SB_API_VERSION >= SB_UI_NAVIGATION_VERSION - REGISTER_SYMBOL(SbUiNavGetInterface); -#endif - -#if SB_API_VERSION >= 5 -#if SB_HAS(SPEECH_RECOGNIZER) - REGISTER_SYMBOL(SbSpeechRecognizerCreate); - REGISTER_SYMBOL(SbSpeechRecognizerDestroy); - REGISTER_SYMBOL(SbSpeechRecognizerStart); - REGISTER_SYMBOL(SbSpeechRecognizerStop); -#endif -#endif - -#if SB_API_VERSION >= 10 -#if SB_HAS(MMAP) - REGISTER_SYMBOL(SbMemoryProtect); -#endif - REGISTER_SYMBOL(SbDrmIsServerCertificateUpdatable); - REGISTER_SYMBOL(SbDrmUpdateServerCertificate); - REGISTER_SYMBOL(SbMediaGetAudioBufferBudget); - REGISTER_SYMBOL(SbMediaGetBufferAlignment); - REGISTER_SYMBOL(SbMediaGetBufferAllocationUnit); - REGISTER_SYMBOL(SbMediaGetBufferGarbageCollectionDurationThreshold); - REGISTER_SYMBOL(SbMediaGetBufferPadding); - REGISTER_SYMBOL(SbMediaGetBufferStorageType); - REGISTER_SYMBOL(SbMediaGetInitialBufferCapacity); - REGISTER_SYMBOL(SbMediaGetMaxBufferCapacity); - REGISTER_SYMBOL(SbMediaGetProgressiveBufferBudget); - REGISTER_SYMBOL(SbMediaGetVideoBufferBudget); - REGISTER_SYMBOL(SbMediaIsBufferPoolAllocateOnDemand); - REGISTER_SYMBOL(SbMediaIsBufferUsingMemoryPool); - REGISTER_SYMBOL(SbPlayerGetInfo2); - REGISTER_SYMBOL(SbPlayerGetMaximumNumberOfSamplesPerWrite); - REGISTER_SYMBOL(SbPlayerSeek2); - REGISTER_SYMBOL(SbPlayerWriteSample2); - REGISTER_SYMBOL(SbSystemSupportsResume); -#endif - -#if SB_API_VERSION >= 11 - REGISTER_SYMBOL(SbAudioSinkGetMinBufferSizeInFrames); - REGISTER_SYMBOL(SbCPUFeaturesGet); - REGISTER_SYMBOL(SbMediaSetAudioWriteDuration); - REGISTER_SYMBOL(SbSystemGetExtension); - REGISTER_SYMBOL(SbSystemSignWithCertificationSecretKey); - REGISTER_SYMBOL(SbThreadContextGetPointer); - REGISTER_SYMBOL(SbThreadSamplerCreate); - REGISTER_SYMBOL(SbThreadSamplerDestroy); - REGISTER_SYMBOL(SbThreadSamplerFreeze); - REGISTER_SYMBOL(SbThreadSamplerIsSupported); - REGISTER_SYMBOL(SbThreadSamplerThaw); - REGISTER_SYMBOL(SbWindowGetDiagonalSizeInInches); -#endif -} - -const void* ExportedSymbols::Lookup(const char* name) { - const void* ret = map_[name]; - SB_CHECK(ret) << name; - return ret; -} - -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/exported_symbols.h b/src/starboard/elf_loader/exported_symbols.h deleted file mode 100644 index a28c583..0000000 --- a/src/starboard/elf_loader/exported_symbols.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_ -#define STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_ - -#include <map> -#include <string> - -#include "starboard/elf_loader/elf_hash_table.h" -#include "starboard/elf_loader/gnu_hash_table.h" -#include "starboard/file.h" - -namespace starboard { -namespace elf_loader { - -// class representing all exported symbols -// by the starboard layer. - -// The elf_loader will not use any other symbols -// outside of the set represented in this class. -class ExportedSymbols { - public: - ExportedSymbols(); - const void* Lookup(const char* name); - - private: - std::map<std::string, const void*> map_; - - SB_DISALLOW_COPY_AND_ASSIGN(ExportedSymbols); -}; - -} // namespace elf_loader -} // namespace starboard -#endif // STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_
diff --git a/src/starboard/elf_loader/file.h b/src/starboard/elf_loader/file.h deleted file mode 100644 index 90296e7..0000000 --- a/src/starboard/elf_loader/file.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_FILE_H_ -#define STARBOARD_ELF_LOADER_FILE_H_ - -#include "starboard/elf_loader/elf.h" - -namespace starboard { -namespace elf_loader { - -// File abstraction to be used by the ELF loader. -// The main reason to introduce this class is to allow for -// easy testing. -class File { - public: - // Opens the file specified for reading. - virtual bool Open(const char* name) = 0; - - // Reads a buffer from the file using the specified offset from the beginning - // of the file. - virtual bool ReadFromOffset(int64_t offset, char* buffer, int size) = 0; - - // Closes the underlying file. - virtual void Close() = 0; - - virtual ~File() {} -}; - -} // namespace elf_loader -} // namespace starboard - -#endif // STARBOARD_ELF_LOADER_FILE_H_
diff --git a/src/starboard/elf_loader/file_impl.cc b/src/starboard/elf_loader/file_impl.cc deleted file mode 100644 index 8250e8f..0000000 --- a/src/starboard/elf_loader/file_impl.cc +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/file_impl.h" - -#include "starboard/common/log.h" - -namespace { -void LogLastError(const char* msg) { - const int kErrorMessageBufferSize = 256; - char msgbuf[kErrorMessageBufferSize]; - SbSystemError error_code = SbSystemGetLastError(); - if (SbSystemGetErrorString(error_code, msgbuf, kErrorMessageBufferSize) > 0) { - SB_LOG(ERROR) << msg << ": " << msgbuf; - } -} -} // namespace - -namespace starboard { -namespace elf_loader { - -FileImpl::FileImpl() : file_(NULL) {} - -bool FileImpl::Open(const char* name) { - SB_LOG(INFO) << "Loading: " << name; - file_ = SbFileOpen(name, kSbFileOpenOnly | kSbFileRead, NULL, NULL); - if (!file_) { - return false; - } - return true; -} - -bool FileImpl::ReadFromOffset(int64_t offset, char* buffer, int size) { - if (!file_) { - return false; - } - int64_t ret = SbFileSeek(file_, kSbFileFromBegin, offset); - SB_LOG(INFO) << "SbFileSeek: ret=" << ret; - if (ret == -1) { - SB_LOG(INFO) << "SbFileSeek: failed"; - return false; - } - - int count = SbFileReadAll(file_, buffer, size); - SB_LOG(INFO) << "SbFileReadAll: count=" << count; - if (count == -1) { - LogLastError("SbFileReadAll failed"); - return false; - } - return true; -} - -void FileImpl::Close() { - if (file_) { - SbFileClose(file_); - } -} - -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/file_impl.h b/src/starboard/elf_loader/file_impl.h deleted file mode 100644 index 2a923be..0000000 --- a/src/starboard/elf_loader/file_impl.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_FILE_IMPL_H_ -#define STARBOARD_ELF_LOADER_FILE_IMPL_H_ - -#include "starboard/elf_loader/elf.h" - -#include "starboard/elf_loader/file.h" -#include "starboard/file.h" - -namespace starboard { -namespace elf_loader { - -// Starboard implementation for reading a file. -class FileImpl : public File { - public: - FileImpl(); - bool Open(const char* name); - bool ReadFromOffset(int64_t offset, char* buffer, int size); - void Close(); - - private: - SbFile file_; - - SB_DISALLOW_COPY_AND_ASSIGN(FileImpl); -}; - -} // namespace elf_loader -} // namespace starboard - -#endif // STARBOARD_ELF_LOADER_FILE_IMPL_H_
diff --git a/src/starboard/elf_loader/gnu_hash_table.cc b/src/starboard/elf_loader/gnu_hash_table.cc deleted file mode 100644 index 37db118..0000000 --- a/src/starboard/elf_loader/gnu_hash_table.cc +++ /dev/null
@@ -1,142 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/gnu_hash_table.h" -#include "starboard/common/log.h" -#include "starboard/string.h" - -namespace starboard { -namespace elf_loader { - -// Compute the GNU hash of a given symbol. -// For more details on the hash function: -// https://blogs.oracle.com/solaris/gnu-hash-elf-sections-v2 -static uint32_t GnuHash(const char* name) { - uint32_t h = 5381; - const uint8_t* ptr = reinterpret_cast<const uint8_t*>(name); - while (*ptr) { - h = h * 33 + *ptr++; - } - return h; -} - -GnuHashTable::GnuHashTable() - : num_buckets_(0), - sym_offset_(0), - sym_count_(0), - bloom_word_mask_(0), - bloom_shift_(0), - bloom_filter_(NULL), - buckets_(NULL), - chain_(NULL) {} -void GnuHashTable::Init(uintptr_t dt_gnu_hash) { - SB_LOG(INFO) << "GnuHashTable::Init 0x" << std::hex << dt_gnu_hash; - sym_count_ = 0; - - const uint32_t* data = reinterpret_cast<const uint32_t*>(dt_gnu_hash); - num_buckets_ = data[0]; - sym_offset_ = data[1]; - - SB_LOG(INFO) << "GnuHashTable::Init num_buckets_=" << num_buckets_ - << " sym_offset_" << sym_offset_; - if (!num_buckets_) - return; - - const uint32_t bloom_size = data[2]; - SB_LOG(INFO) << "GnuHashTable::Init bloom_size=" << bloom_size; - if ((bloom_size & (bloom_size - 1U)) != 0) // must be a power of 2 - return; - - bloom_word_mask_ = bloom_size - 1U; - bloom_shift_ = data[3]; - - SB_LOG(INFO) << "GnuHashTable::Init bloom_word_mask_=" << bloom_word_mask_; - SB_LOG(INFO) << "GnuHashTable::Init bloom_shift_=" << bloom_shift_; - bloom_filter_ = reinterpret_cast<const Addr*>(data + 4); - SB_LOG(INFO) << "GnuHashTable::Init bloom_filter_=0x" << std::hex - << bloom_filter_; - buckets_ = reinterpret_cast<const uint32_t*>(bloom_filter_ + bloom_size); - - SB_LOG(INFO) << "GnuHashTable::Init buckets_=0x" << std::hex << buckets_; - chain_ = buckets_ + num_buckets_; - - // Compute number of dynamic symbols by parsing the table. - if (num_buckets_ > 0) { - // First find the maximum index in the buckets table. - uint32_t max_index = buckets_[0]; - for (size_t n = 1; n < num_buckets_; ++n) { - uint32_t sym_index = buckets_[n]; - if (sym_index > max_index) - max_index = sym_index; - } - // Now start to look at the chain_ table from (max_index - sym_offset_) - // until there is a value with LSB set to 1, indicating the end of the - // last chain. - while ((chain_[max_index - sym_offset_] & 1) == 0) - max_index++; - - sym_count_ = (max_index - sym_offset_) + 1; - } -} - -bool GnuHashTable::IsValid() const { - return sym_count_ > 0; -} - -const Sym* GnuHashTable::LookupByName(const char* symbol_name, - const Sym* symbol_table, - const char* string_table) const { - SB_LOG(INFO) << "GnuHashTable::LookupByName: " << symbol_name; - uint32_t hash = GnuHash(symbol_name); - - SB_LOG(INFO) << "GnuHashTable::LookupByName: hash=" << hash; - SB_LOG(INFO) << "GnuHashTable::LookupByName: ELF_BITS=" << ELF_BITS; - - // First, bloom filter test. - Addr word = bloom_filter_[(hash / ELF_BITS) & bloom_word_mask_]; - - SB_LOG(INFO) << "GnuHashTable::LookupByName: word=" << word; - Addr mask = (Addr(1) << (hash % ELF_BITS)) | - (Addr(1) << ((hash >> bloom_shift_) % ELF_BITS)); - - SB_LOG(INFO) << "GnuHashTable::LookupByName: mask=" << mask; - if ((word & mask) != mask) - return NULL; - - uint32_t sym_index = buckets_[hash % num_buckets_]; - if (sym_index < sym_offset_) - return NULL; - - // TODO: add validations of the syn_index - while (true) { - const Sym* sym = symbol_table + sym_index; - const uint32_t sym_hash = chain_[sym_index - sym_offset_]; - const char* sym_name = string_table + sym->st_name; - - if ((sym_hash | 1) == (hash | 1) && - !SbStringCompareAll(sym_name, symbol_name)) { - return sym; - } - - if (sym_hash & 1) - break; - - sym_index++; - } - - return NULL; -} - -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/gnu_hash_table.h b/src/starboard/elf_loader/gnu_hash_table.h deleted file mode 100644 index 5bdf199..0000000 --- a/src/starboard/elf_loader/gnu_hash_table.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_ -#define STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_ - -#include <stddef.h> -#include "starboard/elf_loader/elf.h" - -namespace starboard { -namespace elf_loader { - -// Models the hash table used to map symbol names to symbol entries using -// the GNU format. This one is smaller and faster than the standard ELF one. -class GnuHashTable { - public: - GnuHashTable(); - // Initialize instance. |dt_gnu_hash| should be the address that the - // DT_GNU_HASH entry points to in the input ELF dynamic section. Call - // IsValid() to determine whether the table was well-formed. - void Init(uintptr_t dt_gnu_hash); - - // Returns true iff the content of the table is valid. - bool IsValid() const; - - // Return the index of the first dynamic symbol within the ELF symbol table. - size_t dyn_symbols_offset() const { return sym_offset_; } - - // Number of dynamic symbols in the ELF symbol table. - size_t dyn_symbols_count() const { return sym_count_; } - - // Lookup |symbol_name| in the table. |symbol_table| should point to the - // ELF symbol table, and |string_table| to the start of its string table. - // Returns NULL on failure. - const Sym* LookupByName(const char* symbol_name, - const Sym* symbol_table, - const char* string_table) const; - - private: - uint32_t num_buckets_; - uint32_t sym_offset_; - uint32_t sym_count_; - uint32_t bloom_word_mask_; - uint32_t bloom_shift_; - const Addr* bloom_filter_; - const uint32_t* buckets_; - const uint32_t* chain_; - - SB_DISALLOW_COPY_AND_ASSIGN(GnuHashTable); -}; - -} // namespace elf_loader -} // namespace starboard - -#endif // STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_
diff --git a/src/starboard/elf_loader/program_table.cc b/src/starboard/elf_loader/program_table.cc deleted file mode 100644 index 7b48e3c..0000000 --- a/src/starboard/elf_loader/program_table.cc +++ /dev/null
@@ -1,361 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/program_table.h" - -#include "starboard/common/log.h" -#include "starboard/memory.h" - -#define MAYBE_MAP_FLAG(x, from, to) (((x) & (from)) ? (to) : 0) - -#if SB_CAN(MAP_EXECUTABLE_MEMORY) -#define PFLAGS_TO_PROT(x) \ - (MAYBE_MAP_FLAG((x), PF_X, kSbMemoryMapProtectExec) | \ - MAYBE_MAP_FLAG((x), PF_R, kSbMemoryMapProtectRead) | \ - MAYBE_MAP_FLAG((x), PF_W, kSbMemoryMapProtectWrite)) -#endif - -#define MAP_FAILED ((void*)-1) - -namespace starboard { -namespace elf_loader { - -ProgramTable::ProgramTable() - : phdr_num_(0), - phdr_mmap_(NULL), - phdr_table_(NULL), - phdr_size_(0), - load_start_(NULL), - load_size_(0), - base_memory_address_(0) {} - -bool ProgramTable::LoadProgramHeader(const Ehdr* elf_header, File* elf_file) { - if (!elf_header) { - SB_LOG(ERROR) << "Ehdr is required"; - return false; - } - if (!elf_file) { - SB_LOG(ERROR) << "File is required"; - return false; - } - phdr_num_ = elf_header->e_phnum; - - SB_LOG(INFO) << "Program Header count=" << phdr_num_; - // Like the kernel, only accept program header tables smaller than 64 KB. - if (phdr_num_ < 1 || phdr_num_ > 65536 / elf_header->e_phentsize) { - SB_LOG(ERROR) << "Invalid program header count: " << phdr_num_; - return false; - } - - SB_LOG(INFO) << "elf_header->e_phoff=" << elf_header->e_phoff; - SB_LOG(INFO) << "elf_header->e_phnum=" << elf_header->e_phnum; - - Addr page_min = PAGE_START(elf_header->e_phoff); - Addr page_max = PAGE_END(elf_header->e_phoff + (phdr_num_ * elf_header->e_phentsize)); - Addr page_offset = PAGE_OFFSET(elf_header->e_phoff); - - SB_LOG(INFO) << "page_min=" << page_min; - SB_LOG(INFO) << "page_max=" << page_max; - - phdr_size_ = page_max - page_min; - - SB_LOG(INFO) << "page_max - page_min=" << page_max - page_min; - -#if SB_HAS(MMAP) - phdr_mmap_ = - SbMemoryMap(phdr_size_, kSbMemoryMapProtectWrite, "program_header"); - if (!phdr_mmap_) { - SB_LOG(ERROR) << "Failed to allocate memory"; - return false; - } - - SB_LOG(INFO) << "Allocated address=" << phdr_mmap_; -#else - SB_CHECK(false); -#endif - if (!elf_file->ReadFromOffset(page_min, reinterpret_cast<char*>(phdr_mmap_), - phdr_size_)) { - SB_LOG(ERROR) << "Failed to read program header from file offset: " - << page_min; - return false; - } -#if SB_API_VERSION >= 10 && SB_HAS(MMAP) - bool mp_result = - SbMemoryProtect(phdr_mmap_, phdr_size_, kSbMemoryMapProtectRead); - SB_LOG(INFO) << "mp_result=" << mp_result; - if (!mp_result) { - SB_LOG(ERROR) << "Failed to protect program header"; - return false; - } -#else - SB_CHECK(false); -#endif - - phdr_table_ = reinterpret_cast<Phdr*>(reinterpret_cast<char*>(phdr_mmap_) + - page_offset); - - return true; -} - -bool ProgramTable::LoadSegments(File* elf_file) { - for (size_t i = 0; i < phdr_num_; ++i) { - const Phdr* phdr = &phdr_table_[i]; - - if (phdr->p_type != PT_LOAD) { - continue; - } - - // Segment byte addresses in memory. - Addr seg_start = phdr->p_vaddr + base_memory_address_; - Addr seg_end = seg_start + phdr->p_memsz; - - // Segment page addresses in memory. - Addr seg_page_start = PAGE_START(seg_start); - Addr seg_page_end = PAGE_END(seg_end); - - // File offsets. - Addr seg_file_end = seg_start + phdr->p_filesz; - Addr file_start = phdr->p_offset; - Addr file_end = file_start + phdr->p_filesz; - - SB_LOG(INFO) << " phdr->p_offset=" << phdr->p_offset - << " phdr->p_filesz=" << phdr->p_filesz; - - Addr file_page_start = PAGE_START(file_start); - Addr file_length = file_end - file_page_start; - - SB_LOG(INFO) << "Mapping segment: " - << " file_page_start=" << file_page_start - << " file_length=" << file_length << " seg_page_start=0x" - << std::hex << seg_page_start; - -#if SB_API_VERSION >= 10 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) - if (file_length != 0) { - const int prot_flags = PFLAGS_TO_PROT(phdr->p_flags); - SB_LOG(INFO) << "segment prot_flags=" << std::hex << prot_flags; - - void* seg_addr = reinterpret_cast<void*>(seg_page_start); - bool mp_ret = - SbMemoryProtect(seg_addr, file_length, kSbMemoryMapProtectWrite); - SB_LOG(INFO) << "segment vaddress=" << seg_addr; - - if (!mp_ret) { - SB_LOG(ERROR) << "Failed to unprotect segment"; - return false; - } - if (!elf_file->ReadFromOffset(file_page_start, - reinterpret_cast<char*>(seg_addr), - file_length)) { - SB_LOG(INFO) << "Failed to read segment from file offset: " - << file_page_start; - return false; - } - mp_ret = SbMemoryProtect(seg_addr, file_length, prot_flags); - SB_LOG(INFO) << "mp_ret=" << mp_ret; - if (!mp_ret) { - SB_LOG(ERROR) << "Failed to protect segment"; - return false; - } - if (!seg_addr) { - SB_LOG(ERROR) << "Could not map segment " << i; - return false; - } - } -#else - SB_CHECK(false); -#endif - - // if the segment is writable, and does not end on a page boundary, - // zero-fill it until the page limit. - if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) { - SbMemorySet(reinterpret_cast<void*>(seg_file_end), 0, - PAGE_SIZE - PAGE_OFFSET(seg_file_end)); - } - - seg_file_end = PAGE_END(seg_file_end); - - // seg_file_end is now the first page address after the file - // content. If seg_page_end is larger, we need to zero anything - // between them. This is done by using a private anonymous - // map for all extra pages. - if (seg_page_end > seg_file_end) { -#if SB_API_VERSION >= 10 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) - bool mprotect_fix = SbMemoryProtect(reinterpret_cast<void*>(seg_file_end), - seg_page_end - seg_file_end, - kSbMemoryMapProtectWrite); - SB_LOG(INFO) << "mprotect_fix=" << mprotect_fix; - if (!mprotect_fix) { - SB_LOG(ERROR) << "Failed to unprotect end of segment"; - return false; - } -#else - SB_CHECK(false); -#endif - - SbMemorySet(reinterpret_cast<void*>(seg_file_end), 0, - seg_page_end - seg_file_end); -#if SB_API_VERSION >= 10 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) - SbMemoryProtect(reinterpret_cast<void*>(seg_file_end), - seg_page_end - seg_file_end, - PFLAGS_TO_PROT(phdr->p_flags)); - SB_LOG(INFO) << "mprotect_fix=" << mprotect_fix; - if (!mprotect_fix) { - SB_LOG(ERROR) << "Failed to protect end of segment"; - return false; - } -#else - SB_CHECK(false); -#endif - } - } - return true; -} - -size_t ProgramTable::GetLoadMemorySize() { - Addr min_vaddr = ~static_cast<Addr>(0); - Addr max_vaddr = 0x00000000U; - - bool found_pt_load = false; - for (size_t i = 0; i < phdr_num_; ++i) { - const Phdr* phdr = &phdr_table_[i]; - - if (phdr->p_type != PT_LOAD) { - SB_LOG(INFO) << "GetLoadMemorySize: ignoring segment with type: " - << phdr->p_type; - continue; - } - found_pt_load = true; - - if (phdr->p_vaddr < min_vaddr) { - SB_LOG(INFO) << "p_vaddr=" << std::hex << phdr->p_vaddr; - min_vaddr = phdr->p_vaddr; - } - - if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) { - max_vaddr = phdr->p_vaddr + phdr->p_memsz; - SB_LOG(INFO) << "phdr->p_vaddr=" << phdr->p_vaddr - << " phdr->p_memsz=" << phdr->p_memsz; - SB_LOG(INFO) << " max_vaddr=0x" << std::hex << max_vaddr; - } - } - if (!found_pt_load) { - min_vaddr = 0x00000000U; - } - - min_vaddr = PAGE_START(min_vaddr); - max_vaddr = PAGE_END(max_vaddr); - - return max_vaddr - min_vaddr; -} - -void ProgramTable::GetDynamicSection(Dyn** dynamic, - size_t* dynamic_count, - Word* dynamic_flags) { - const Phdr* phdr = phdr_table_; - const Phdr* phdr_limit = phdr + phdr_num_; - - for (phdr = phdr_table_; phdr < phdr_limit; phdr++) { - if (phdr->p_type != PT_DYNAMIC) { - SB_LOG(INFO) << "Ignore section with type: " << phdr->p_type; - continue; - } - - SB_LOG(INFO) << "Reading at vaddr: " << phdr->p_vaddr; - *dynamic = reinterpret_cast<Dyn*>(base_memory_address_ + phdr->p_vaddr); - if (dynamic_count) { - *dynamic_count = (size_t)(phdr->p_memsz / sizeof(Dyn)); - } - if (dynamic_flags) { - *dynamic_flags = phdr->p_flags; - } - return; - } - *dynamic = NULL; - if (dynamic_count) { - *dynamic_count = 0; - } -} - -int ProgramTable::AdjustMemoryProtectionOfReadOnlySegments( - int extra_prot_flags) { - const Phdr* phdr = phdr_table_; - const Phdr* phdr_limit = phdr + phdr_num_; - - for (; phdr < phdr_limit; phdr++) { - if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) - continue; - - Addr seg_page_start = PAGE_START(phdr->p_vaddr) + base_memory_address_; - Addr seg_page_end = - PAGE_END(phdr->p_vaddr + phdr->p_memsz) + base_memory_address_; -#if SB_API_VERSION >= 10 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) - int ret = SbMemoryProtect(reinterpret_cast<void*>(seg_page_start), - seg_page_end - seg_page_start, - PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags); - if (ret < 0) { - return -1; - } -#else - SB_CHECK(false); -#endif - } - return 0; -} - -bool ProgramTable::ReserveLoadMemory() { - load_size_ = GetLoadMemorySize(); - if (load_size_ == 0) { - SB_LOG(ERROR) << "No loadable segments"; - return false; - } - - SB_LOG(INFO) << "Load size=" << load_size_; - -#if SB_API_VERSION >= 10 && SB_HAS(MMAP) - load_start_ = - SbMemoryMap(load_size_, kSbMemoryMapProtectReserved, "reserved_mem"); - if (load_start_ == MAP_FAILED) { - SB_LOG(ERROR) << "Could not reserve " << load_size_ - << " bytes of address space"; - return false; - } -#else - SB_CHECK(false); -#endif - base_memory_address_ = reinterpret_cast<Addr>(load_start_); - - SB_LOG(INFO) << "Load start=" << std::hex << load_start_ - << " base_memory_address=0x" << base_memory_address_; - return true; -} - -Addr ProgramTable::GetBaseMemoryAddress() { - return base_memory_address_; -} - -ProgramTable::~ProgramTable() { -#if SB_HAS(MMAP) - if (load_start_) { - SbMemoryUnmap(load_start_, load_size_); - } - if (phdr_mmap_) { - SbMemoryUnmap(phdr_mmap_, phdr_size_); - } -#else - SB_CHECK(false); -#endif -} - -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/program_table.h b/src/starboard/elf_loader/program_table.h deleted file mode 100644 index c4229e7..0000000 --- a/src/starboard/elf_loader/program_table.h +++ /dev/null
@@ -1,91 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_ -#define STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_ - -#include "starboard/elf_loader/elf.h" -#include "starboard/elf_loader/file.h" - -namespace starboard { -namespace elf_loader { - -// Loads the ELF's binary program table and memory maps -// the loadable segments. -// -// To properly initialize the program table and the segments -// the following calls are required: -// 1. LoadProgramHeader() -// 2. LoadSegments() -// -// After those calls the ProgramTable class is fully functional and -// the segments properly loaded. - -class ProgramTable { - public: - ProgramTable(); - - // Loads the program header. - bool LoadProgramHeader(const Ehdr* elf_header, File* elf_file); - - // Loads the segments. - bool LoadSegments(File* elf_file); - - // Retrieves the dynamic section table. - void GetDynamicSection(Dyn** dynamic, - size_t* dynamic_count, - Word* dynamic_flags); - - // Adjusts the memory protection of read only segments. - // This call is used to make text segments writable in order - // to apply relocations. After the relocations are done the - // protection is restored to its original read only state. - int AdjustMemoryProtectionOfReadOnlySegments(int extra_prot_flags); - - // Reserves a contiguous block of memory, page aligned for mapping all - // the segments of the binary. - bool ReserveLoadMemory(); - - // Retrieves the base load address for the binary. - Addr GetBaseMemoryAddress(); - - ~ProgramTable(); - - private: - // Calculates the memory size of the binary. - size_t GetLoadMemorySize(); - - private: - size_t phdr_num_; - void* phdr_mmap_; - Phdr* phdr_table_; - Addr phdr_size_; - - // First page of reserved address space. - void* load_start_; - - // Size in bytes of reserved address space. - Addr load_size_; - - // The base memory address. All virtual addresses - // from the ELF file are offsets from this address. - Addr base_memory_address_; - - SB_DISALLOW_COPY_AND_ASSIGN(ProgramTable); -}; - -} // namespace elf_loader -} // namespace starboard - -#endif // STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_
diff --git a/src/starboard/elf_loader/program_table_test.cc b/src/starboard/elf_loader/program_table_test.cc deleted file mode 100644 index b5a9e50..0000000 --- a/src/starboard/elf_loader/program_table_test.cc +++ /dev/null
@@ -1,185 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/program_table.h" - -#include <vector> - -#include "starboard/common/scoped_ptr.h" -#include "starboard/elf_loader/file.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) -namespace starboard { -namespace elf_loader { - -namespace { - -class DummyFile : public File { - public: - typedef struct FileChunk { - FileChunk(int file_offset, const char* buffer, int size) - : file_offset_(file_offset), buffer_(buffer), size_(size) {} - int file_offset_; - const char* buffer_; - int size_; - } FileChunk; - - explicit DummyFile(const std::vector<FileChunk>& file_chunks) - : file_chunks_(file_chunks), read_index_(0) {} - - bool Open(const char* name) { return true; } - bool ReadFromOffset(int64_t offset, char* buffer, int size) { - SB_LOG(INFO) << "ReadFromOffset offset=" << offset << " size=" << size - << " read_index_=" << read_index_; - if (read_index_ >= file_chunks_.size()) { - SB_LOG(INFO) << "ReadFromOffset EOF"; - return false; - } - const FileChunk& file_chunk = file_chunks_[read_index_++]; - if (offset != file_chunk.file_offset_) { - SB_LOG(ERROR) << "ReadFromOffset: Invalid offset " << offset - << " expected " << file_chunk.file_offset_; - return false; - } - if (size > file_chunk.size_) { - SB_LOG(ERROR) << "ReadFromOffset: Invalid size " << size << " expected < " - << file_chunk.size_; - return false; - } - SbMemoryCopy(buffer, file_chunk.buffer_, size); - return true; - } - void Close() {} - - private: - int file_offset_; - const char* buffer_; - int size_; - std::vector<FileChunk> file_chunks_; - int read_index_; -}; - -class ProgramTableTest : public ::testing::Test { - protected: - ProgramTableTest() { program_table_.reset(new ProgramTable()); } - ~ProgramTableTest() {} - - void HelperMethod() {} - - protected: - scoped_ptr<ProgramTable> program_table_; -}; - -TEST_F(ProgramTableTest, LoadSegments) { - // File structure - // [Phdr1] - // [Phdr2] - // [200, 300) sement for phdr1 - // [250, 300) dyanmic section in segment for phdr1 - // [400, 500) sement for phdr2 - Ehdr ehdr; - ehdr.e_phnum = 3; - ehdr.e_phoff = 0; - ehdr.e_phentsize = sizeof(Phdr); - - Phdr ent1; - Phdr ent2; - Phdr ent3; - SbMemorySet(&ent1, 0, sizeof(Phdr)); - SbMemorySet(&ent2, 0, sizeof(Phdr)); - SbMemorySet(&ent3, 0, sizeof(Phdr)); - - ent1.p_type = PT_LOAD; - ent1.p_vaddr = 0; - ent1.p_memsz = 2 * PAGE_SIZE; - ent1.p_offset = 200; - ent1.p_filesz = 100; - ent1.p_flags = kSbMemoryMapProtectRead; - - ent2.p_type = PT_LOAD; - ent2.p_vaddr = 2 * PAGE_SIZE; - ent2.p_memsz = 3 * PAGE_SIZE; - ent2.p_offset = 400; - ent2.p_filesz = 100; - ent1.p_flags = kSbMemoryMapProtectRead | kSbMemoryMapProtectExec; - - ent3.p_type = PT_DYNAMIC; - ent3.p_vaddr = 250; - ent3.p_memsz = 3 * sizeof(Dyn); - ent3.p_offset = 250; - ent3.p_filesz = 5 * sizeof(Dyn); - ent3.p_flags = 0x42; - - Phdr program_table_data[3]; - program_table_data[0] = ent1; - program_table_data[1] = ent2; - program_table_data[2] = ent3; - - Dyn dynamic_table_data[3]; - dynamic_table_data[0].d_tag = DT_DEBUG; - dynamic_table_data[1].d_tag = DT_DEBUG; - dynamic_table_data[2].d_tag = DT_DEBUG; - - char program_table_page[PAGE_SIZE]; - SbMemorySet(program_table_page, 0, sizeof(program_table_page)); - SbMemoryCopy(program_table_page, program_table_data, - sizeof(program_table_data)); - - char segment_file_data1[2 * PAGE_SIZE]; - char segment_file_data2[3 * PAGE_SIZE]; - - SbMemoryCopy(segment_file_data1 + 250, dynamic_table_data, - sizeof(dynamic_table_data)); - - std::vector<DummyFile::FileChunk> file_chunks; - file_chunks.push_back( - DummyFile::FileChunk(0, program_table_page, sizeof(program_table_page))); - file_chunks.push_back( - DummyFile::FileChunk(0, segment_file_data1, sizeof(segment_file_data1))); - file_chunks.push_back( - DummyFile::FileChunk(0, segment_file_data2, sizeof(segment_file_data2))); - - DummyFile file(file_chunks); - - EXPECT_TRUE(program_table_->LoadProgramHeader(&ehdr, &file)); - - EXPECT_EQ(program_table_->GetBaseMemoryAddress(), 0); - - EXPECT_TRUE(program_table_->ReserveLoadMemory()); - - EXPECT_NE(program_table_->GetBaseMemoryAddress(), 0); - - EXPECT_TRUE(program_table_->LoadSegments(&file)); - - Dyn* dynamic = NULL; - size_t dynamic_count = 0; - Word dynamic_flags = 0; - - program_table_->GetDynamicSection(&dynamic, &dynamic_count, &dynamic_flags); - Dyn* expected_dyn = reinterpret_cast<Dyn*>( - program_table_->GetBaseMemoryAddress() + ent3.p_vaddr); - EXPECT_TRUE(dynamic != NULL); - EXPECT_EQ(dynamic[0].d_tag, DT_DEBUG); - EXPECT_EQ(dynamic[1].d_tag, DT_DEBUG); - EXPECT_EQ(dynamic[2].d_tag, DT_DEBUG); - EXPECT_EQ(dynamic_count, 3); - EXPECT_EQ(dynamic_flags, 0x42); -} - -} // namespace -} // namespace elf_loader -} // namespace starboard -#endif // SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/relocations.cc b/src/starboard/elf_loader/relocations.cc deleted file mode 100644 index dae9157..0000000 --- a/src/starboard/elf_loader/relocations.cc +++ /dev/null
@@ -1,531 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/relocations.h" - -#include "starboard/common/log.h" - -namespace starboard { -namespace elf_loader { - -Relocations::Relocations(Addr base_memory_address, - DynamicSection* dynamic_section, - ExportedSymbols* exported_symbols) - : base_memory_address_(base_memory_address), - dynamic_section_(dynamic_section), - plt_relocations_(0), - plt_relocations_size_(0), - plt_got_(NULL), - relocations_(0), - relocations_size_(0), - android_relocations_(NULL), - android_relocations_size_(0), - has_text_relocations_(false), - has_symbolic_(false), - exported_symbols_(exported_symbols) {} - -bool Relocations::HasTextRelocations() { - return has_text_relocations_; -} - -bool Relocations::InitRelocations() { - SB_LOG(INFO) << "InitRelocations: dynamic_count=" - << dynamic_section_->GetDynamicTableSize(); - const Dyn* dynamic = dynamic_section_->GetDynamicTable(); - for (int i = 0; i < dynamic_section_->GetDynamicTableSize(); i++) { - Addr dyn_value = dynamic[i].d_un.d_val; - uintptr_t dyn_addr = base_memory_address_ + dynamic[i].d_un.d_ptr; - Addr tag = dynamic[i].d_tag; - SB_LOG(INFO) << "InitRelocations: tag=" << tag; - switch (tag) { -#if defined(USE_RELA) - case DT_REL: - case DT_RELSZ: - case DT_ANDROID_REL: - case DT_ANDROID_RELSZ: -#else - case DT_RELA: - case DT_RELASZ: - case DT_ANDROID_RELA: - case DT_ANDROID_RELASZ: -#endif - SB_LOG(ERROR) << "unsupported relocation type"; - return false; - case DT_PLTREL: - SB_LOG(INFO) << " DT_PLTREL value=" << dyn_value; -#if defined(USE_RELA) - if (dyn_value != DT_RELA) { - SB_LOG(ERROR) << "unsupported DT_PLTREL expected DT_RELA"; - return false; - } -#else - if (dyn_value != DT_REL) { - SB_LOG(ERROR) << "unsupported DT_PLTREL expected DT_REL"; - return false; - } -#endif - break; - case DT_JMPREL: - SB_LOG(INFO) << " DT_JMPREL addr=0x" << std::hex - << (dyn_addr - base_memory_address_); - plt_relocations_ = dyn_addr; - break; - case DT_PLTRELSZ: - plt_relocations_size_ = dyn_value; - SB_LOG(INFO) << " DT_PLTRELSZ size=" << dyn_value; - break; -#if defined(USE_RELA) - case DT_RELA: -#else - case DT_REL: -#endif - SB_LOG(INFO) << " " << ((tag == DT_RELA) ? "DT_RELA" : "DT_REL") - << " addr=" << std::hex - << (dyn_addr - base_memory_address_); - if (relocations_) { - SB_LOG(ERROR) - << "Unsupported DT_RELA/DT_REL combination in dynamic section"; - return false; - } - relocations_ = dyn_addr; - break; -#if defined(USE_RELA) - case DT_RELASZ: -#else - case DT_RELSZ: -#endif - SB_LOG(INFO) << " " << ((tag == DT_RELASZ) ? "DT_RELASZ" : "DT_RELSZ") - << " size=" << dyn_value; - relocations_size_ = dyn_value; - break; -#if defined(USE_RELA) - case DT_ANDROID_RELA: -#else - case DT_ANDROID_REL: -#endif - SB_LOG(INFO) << " " - << ((tag == DT_ANDROID_REL) ? "DT_ANDROID_REL" - : "DT_ANDROID_RELA") - << " addr=" << std::hex - << (dyn_addr - base_memory_address_); - if (android_relocations_) { - SB_LOG(ERROR) << "Multiple DT_ANDROID_* sections defined."; - return false; - } - android_relocations_ = reinterpret_cast<uint8_t*>(dyn_addr); - break; -#if defined(USE_RELA) - case DT_ANDROID_RELASZ: -#else - case DT_ANDROID_RELSZ: -#endif - SB_LOG(ERROR) << " DT_ANDROID_RELSZ NOT IMPELMENTED"; - android_relocations_size_ = dyn_value; - break; - case DT_RELR: - case DT_ANDROID_RELR: - SB_LOG(ERROR) << " DT_RELR NOT IMPELMENTED"; - break; - case DT_ANDROID_RELRSZ: - case DT_RELRSZ: - SB_LOG(ERROR) << " DT_RELRSZ NOT IMPELMENTED"; - break; - case DT_RELRENT: - case DT_ANDROID_RELRENT: - if (dyn_value != sizeof(Relr)) { - SB_LOG(ERROR) << "Invalid DT_RELRENT value=" << std::hex - << static_cast<int>(dyn_value) - << " expected=" << static_cast<int>(sizeof(Relr)); - return false; - } - break; - case DT_PLTGOT: - SB_LOG(INFO) << "DT_PLTGOT addr=0x" << std::hex - << (dyn_addr - base_memory_address_); - plt_got_ = reinterpret_cast<Addr*>(dyn_addr); - break; - case DT_TEXTREL: - SB_LOG(INFO) << " DT_TEXTREL"; - has_text_relocations_ = true; - break; - case DT_SYMBOLIC: - SB_LOG(INFO) << " DT_SYMBOLIC"; - has_symbolic_ = true; - break; - case DT_FLAGS: - if (dyn_value & DF_TEXTREL) - has_text_relocations_ = true; - if (dyn_value & DF_SYMBOLIC) - has_symbolic_ = true; - - SB_LOG(INFO) << " DT_FLAGS has_text_relocations=" - << has_text_relocations_ - << " has_symbolic=" << has_symbolic_; - - break; - default: - break; - } - } - - return true; -} - -bool Relocations::ApplyAllRelocations() { - SB_LOG(INFO) << "Applying regular relocations"; - if (!ApplyRelocations(reinterpret_cast<rel_t*>(relocations_), - relocations_size_ / sizeof(rel_t))) { - SB_LOG(ERROR) << "regular relocations failed"; - return false; - } - - SB_LOG(INFO) << "Applying PLT relocations"; - if (!ApplyRelocations(reinterpret_cast<rel_t*>(plt_relocations_), - plt_relocations_size_ / sizeof(rel_t))) { - SB_LOG(ERROR) << "PLT relocations failed"; - return false; - } - return true; -} - -bool Relocations::ApplyRelocations(const rel_t* rel, size_t rel_count) { - SB_LOG(INFO) << "rel=" << std::hex << rel << std::dec - << " rel_count=" << rel_count; - - if (!rel) - return true; - - for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { - SB_LOG(INFO) << " Relocation " << rel_n + 1 << " of " << rel_count; - - if (!ApplyRelocation(rel)) - return false; - } - - return true; -} - -bool Relocations::ApplyRelocation(const rel_t* rel) { - const Word rel_type = ELF_R_TYPE(rel->r_info); - const Word rel_symbol = ELF_R_SYM(rel->r_info); - - Addr sym_addr = 0; - Addr reloc = static_cast<Addr>(rel->r_offset + base_memory_address_); - SB_LOG(INFO) << " offset=0x" << std::hex << rel->r_offset - << " type=" << std::dec << rel_type << " reloc=0x" << std::hex - << reloc << " symbol=" << rel_symbol; - - if (rel_type == 0) - return true; - - if (rel_symbol != 0) { - if (!ResolveSymbol(rel_type, rel_symbol, reloc, &sym_addr)) { - SB_LOG(ERROR) << "Failed to resolve symbol: " << rel_symbol; - return false; - } - } - - return ApplyResolvedReloc(rel, sym_addr); -} - -#if defined(USE_RELA) -bool Relocations::ApplyResolvedReloc(const Rela* rela, Addr sym_addr) { - const Word rela_type = ELF_R_TYPE(rela->r_info); - const Sword addend = rela->r_addend; - const Addr reloc = static_cast<Addr>(rela->r_offset + base_memory_address_); - - SB_LOG(INFO) << " rela reloc=0x" << std::hex << reloc << " offset=0x" - << rela->r_offset << " type=" << std::dec << rela_type - << " addend=0x" << std::hex << addend; - Addr* target = reinterpret_cast<Addr*>(reloc); - switch (rela_type) { -#if SB_IS(ARCH_ARM) && SB_IS(64_BIT) - case R_AARCH64_JUMP_SLOT: - SB_LOG(INFO) << " R_AARCH64_JUMP_SLOT target=" << std::hex << target - << " addr=" << (sym_addr + addend); - *target = sym_addr + addend; - break; - - case R_AARCH64_GLOB_DAT: - SB_LOG(INFO) << " R_AARCH64_GLOB_DAT target=" << std::hex << target - << " addr=" << (sym_addr + addend); - *target = sym_addr + addend; - break; - - case R_AARCH64_ABS64: - SB_LOG(INFO) << " R_AARCH64_ABS64 target=" << std::hex << target << " " - << *target << " addr=" << sym_addr + addend; - *target += sym_addr + addend; - break; - - case R_AARCH64_RELATIVE: - SB_LOG(INFO) << " R_AARCH64_RELATIVE target=" << std::hex << target - << " " << *target - << " bias=" << base_memory_address_ + addend; - *target = base_memory_address_ + addend; - break; - - case R_AARCH64_COPY: - // NOTE: These relocations are forbidden in shared libraries. - SB_LOG(ERROR) << "Invalid R_AARCH64_COPY relocation in shared library"; - return false; -#endif - -#if SB_IS(ARCH_X86) && SB_IS(64_BIT) - case R_X86_64_JMP_SLOT: - SB_LOG(INFO) << " R_X86_64_JMP_SLOT target=" << std::hex << target - << " addr=" << (sym_addr + addend); - *target = sym_addr + addend; - break; - - case R_X86_64_GLOB_DAT: - SB_LOG(INFO) << " R_X86_64_GLOB_DAT target=" << std::hex << target - << " addr=" << (sym_addr + addend); - - *target = sym_addr + addend; - break; - - case R_X86_64_RELATIVE: - SB_LOG(INFO) << " R_X86_64_RELATIVE target=" << std::hex << target << " " - << *target << " bias=" << base_memory_address_ + addend; - *target = base_memory_address_ + addend; - break; - - case R_X86_64_64: - *target = sym_addr + addend; - break; - - case R_X86_64_PC32: - *target = sym_addr + (addend - reloc); - break; -#endif - - default: - SB_LOG(ERROR) << "Invalid relocation type: " << rela_type; - return false; - } - - return true; -} -#else -bool Relocations::ApplyResolvedReloc(const Rel* rel, Addr sym_addr) { - const Word rel_type = ELF_R_TYPE(rel->r_info); - const Addr reloc = static_cast<Addr>(rel->r_offset + base_memory_address_); - - SB_LOG(INFO) << " rel reloc=0x" << std::hex << reloc << " offset=0x" - << rel->r_offset << " type=" << std::dec << rel_type; - - Addr* target = reinterpret_cast<Addr*>(reloc); - switch (rel_type) { -#if SB_IS(ARCH_ARM) && SB_IS(32_BIT) - case R_ARM_JUMP_SLOT: - SB_LOG(INFO) << " R_ARM_JUMP_SLOT target=" << std::hex << target - << " addr=" << sym_addr; - *target = sym_addr; - break; - - case R_ARM_GLOB_DAT: - SB_LOG(INFO) << " R_ARM_GLOB_DAT target=" << std::hex << target - << " addr=" << sym_addr; - *target = sym_addr; - break; - - case R_ARM_ABS32: - SB_LOG(INFO) << " R_ARM_ABS32 target=" << std::hex << target << " " - << *target << " addr=" << sym_addr; - *target += sym_addr; - break; - - case R_ARM_REL32: - SB_LOG(INFO) << " R_ARM_REL32 target=" << std::hex << target << " " - << *target << " addr=" << sym_addr - << " offset=" << rel->r_offset; - *target += sym_addr - rel->r_offset; - break; - - case R_ARM_RELATIVE: - SB_LOG(INFO) << " RR_ARM_RELATIVE target=" << std::hex << target << " " - << *target << " bias=" << base_memory_address_; - *target += base_memory_address_; - break; - - case R_ARM_COPY: - // NOTE: These relocations are forbidden in shared libraries. - // The Android linker has special code to deal with this, which - // is not needed here. - SB_LOG(ERROR) << "Invalid R_ARM_COPY relocation in shared library"; - - return false; -#endif - -#if SB_IS(ARCH_X86) && SB_IS(32_BIT) - case R_386_JMP_SLOT: - SB_LOG(INFO) << " R_386_JMP_SLOT target=" << std::hex << target - << " addr=" << sym_addr; - - *target = sym_addr; - break; - - case R_386_GLOB_DAT: - SB_LOG(INFO) << " R_386_GLOB_DAT target=" << std::hex << target - << " addr=" << sym_addr; - *target = sym_addr; - - break; - - case R_386_RELATIVE: - SB_LOG(INFO) << " R_386_RELATIVE target=" << std::hex << target << " " - << *target << " bias=" << base_memory_address_; - - *target += base_memory_address_; - break; - - case R_386_32: - SB_LOG(INFO) << " R_386_32 target=" << std::hex << target << " " - << *target << " addr=" << sym_addr; - *target += sym_addr; - break; - - case R_386_PC32: - SB_LOG(INFO) << " R_386_PC32 target=" << std::hex << target << " " - << *target << " addr=" << sym_addr << " reloc=" << reloc; - *target += (sym_addr - reloc); - break; -#endif - - default: - SB_LOG(ERROR) << "Invalid relocation type: " << rel_type; - return false; - } - - return true; -} -#endif - -RelocationType Relocations::GetRelocationType(Word r_type) { - switch (r_type) { -#if SB_IS(ARCH_ARM) && SB_IS(32_BIT) - case R_ARM_JUMP_SLOT: - case R_ARM_GLOB_DAT: - case R_ARM_ABS32: - return RELOCATION_TYPE_ABSOLUTE; - - case R_ARM_REL32: - case R_ARM_RELATIVE: - return RELOCATION_TYPE_RELATIVE; - - case R_ARM_COPY: - return RELOCATION_TYPE_COPY; -#endif - -#if SB_IS(ARCH_ARM) && SB_IS(64_BIT) - case R_AARCH64_JUMP_SLOT: - case R_AARCH64_GLOB_DAT: - case R_AARCH64_ABS64: - return RELOCATION_TYPE_ABSOLUTE; - - case R_AARCH64_RELATIVE: - return RELOCATION_TYPE_RELATIVE; - - case R_AARCH64_COPY: - return RELOCATION_TYPE_COPY; -#endif - -#if SB_IS(ARCH_X86) && SB_IS(32_BIT) - case R_386_JMP_SLOT: - case R_386_GLOB_DAT: - case R_386_32: - return RELOCATION_TYPE_ABSOLUTE; - - case R_386_RELATIVE: - return RELOCATION_TYPE_RELATIVE; - - case R_386_PC32: - return RELOCATION_TYPE_PC_RELATIVE; -#endif - -#if SB_IS(ARCH_X86) && SB_IS(64_BIT) - case R_X86_64_JMP_SLOT: - case R_X86_64_GLOB_DAT: - case R_X86_64_64: - return RELOCATION_TYPE_ABSOLUTE; - - case R_X86_64_RELATIVE: - return RELOCATION_TYPE_RELATIVE; - - case R_X86_64_PC32: - return RELOCATION_TYPE_PC_RELATIVE; -#endif - default: - return RELOCATION_TYPE_UNKNOWN; - } -} - -bool Relocations::ResolveSymbol(Word rel_type, - Word rel_symbol, - Addr reloc, - Addr* sym_addr) { - const char* sym_name = dynamic_section_->LookupNameById(rel_symbol); - SB_LOG(INFO) << "Resolve: " << sym_name; - const void* address = NULL; - - const Sym* sym = dynamic_section_->LookupByName(sym_name); - if (sym) { - address = reinterpret_cast<void*>(base_memory_address_ + sym->st_value); - } else { - address = exported_symbols_->Lookup(sym_name); - } - - SB_LOG(INFO) << "Resolve: address=0x" << std::hex << address; - - if (address) { - // The symbol was found, so compute its address. - *sym_addr = reinterpret_cast<Addr>(address); - return true; - } - - // The symbol was not found. Normally this is an error except - // if this is a weak reference. - if (!dynamic_section_->IsWeakById(rel_symbol)) { - SB_LOG(ERROR) << "Could not find symbol: " << sym_name; - return false; - } - - // IHI0044C AAELF 4.5.1.1: - // Libraries are not searched to resolve weak references. - // It is not an error for a weak reference to remain - // unsatisfied. - // - // During linking, the value of an undefined weak reference is: - // - Zero if the relocation type is absolute - // - The address of the place if the relocation is pc-relative - // - The address of nominal base address if the relocation - // type is base-relative. - RelocationType r = GetRelocationType(rel_type); - if (r == RELOCATION_TYPE_ABSOLUTE || r == RELOCATION_TYPE_RELATIVE) { - *sym_addr = 0; - return true; - } - - if (r == RELOCATION_TYPE_PC_RELATIVE) { - *sym_addr = reloc; - return true; - } - - SB_LOG(ERROR) << "Invalid weak relocation type (" << r - << ") for unknown symbol '" << sym_name << "'"; - return false; -} -} // namespace elf_loader -} // namespace starboard
diff --git a/src/starboard/elf_loader/relocations.h b/src/starboard/elf_loader/relocations.h deleted file mode 100644 index b763c1b..0000000 --- a/src/starboard/elf_loader/relocations.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_ELF_LOADER_RELOCATIONS_H_ -#define STARBOARD_ELF_LOADER_RELOCATIONS_H_ - -#include "starboard/elf_loader/elf.h" - -#include "starboard/elf_loader/dynamic_section.h" -#include "starboard/elf_loader/program_table.h" - -namespace starboard { -namespace elf_loader { - -enum RelocationType { - RELOCATION_TYPE_UNKNOWN = 0, - RELOCATION_TYPE_ABSOLUTE = 1, - RELOCATION_TYPE_RELATIVE = 2, - RELOCATION_TYPE_PC_RELATIVE = 3, - RELOCATION_TYPE_COPY = 4, -}; - -// class representing the ELF relocations. -class Relocations { - public: - Relocations(Addr base_memory_adddress, - DynamicSection* dynamic_section, - ExportedSymbols* exported_symbols); - - // Initialize the relocation tables. - bool InitRelocations(); - - // Apply all the relocations. - bool ApplyAllRelocations(); - - // Apply a set of relocations. - bool ApplyRelocations(const rel_t* rel, size_t rel_count); - - // Apply an individual relocation. - bool ApplyRelocation(const rel_t* rel); - -// Apply a resolved symbol relocation. -#if defined(USE_RELA) - bool ApplyResolvedReloc(const Rela* rela, Addr sym_addr); -#else - bool ApplyResolvedReloc(const Rel* rel, Addr sym_addr); -#endif - - // Convert an ELF relocation type info a RelocationType value. - RelocationType GetRelocationType(Word r_type); - - // Resolve a symbol address. - bool ResolveSymbol(Word rel_type, - Word rel_symbol, - Addr reloc, - Addr* sym_addr); - - // Checks if there are any text relocations. - bool HasTextRelocations(); - - private: - Addr base_memory_address_; - DynamicSection* dynamic_section_; - Addr plt_relocations_; - size_t plt_relocations_size_; - Addr* plt_got_; - - Addr relocations_; - size_t relocations_size_; - - uint8_t* android_relocations_; - size_t android_relocations_size_; - - bool has_text_relocations_; - bool has_symbolic_; - - ExportedSymbols* exported_symbols_; - - SB_DISALLOW_COPY_AND_ASSIGN(Relocations); -}; - -} // namespace elf_loader -} // namespace starboard - -#endif // STARBOARD_ELF_LOADER_RELOCATIONS_H_
diff --git a/src/starboard/elf_loader/relocations_test.cc b/src/starboard/elf_loader/relocations_test.cc deleted file mode 100644 index fcae59c..0000000 --- a/src/starboard/elf_loader/relocations_test.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/elf_loader/relocations.h" - -#include "starboard/common/scoped_ptr.h" -#include "starboard/elf_loader/elf.h" -#include "starboard/elf_loader/file_impl.h" -#include "starboard/string.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY) -namespace starboard { -namespace elf_loader { - -namespace { - -// TODO: implement -class RelocationsTest : public ::testing::Test { - protected: - RelocationsTest() {} - ~RelocationsTest() {} - - scoped_ptr<Relocations> relocations_; -}; - -#if SB_IS(ARCH_X86) && SB_IS(64_BIT) -TEST_F(RelocationsTest, Initialize_X86_64) { - char buff[1024] = "AAAAAAAAAAAAAAAAAAA"; - Addr load_bias = reinterpret_cast<Addr>(&buff); - Dyn dynamic_table[10]; - Dyn entry1; - entry1.d_tag = DT_REL; - - dynamic_table[0] = entry1; - Dyn* dyn = dynamic_table; - size_t dyn_count = 1; - Word dyn_flags = 0; - - scoped_ptr<DynamicSection> dynamic_section( - new DynamicSection(load_bias, dyn, dyn_count, dyn_flags)); - dynamic_section->InitDynamicSection(); - dynamic_section->InitDynamicSymbols(); - - scoped_ptr<ExportedSymbols> exported_symbols(new ExportedSymbols()); - relocations_.reset(new Relocations(load_bias, dynamic_section.get(), - exported_symbols.get())); - Rela rela; - rela.r_offset = 2; - rela.r_info = R_X86_64_JMP_SLOT; - rela.r_addend = 5; - Addr sym_addr = 34; - - Addr target = rela.r_offset + load_bias; - SB_LOG(INFO) << "target= " << reinterpret_cast<char*>(target); - relocations_->ApplyResolvedReloc(&rela, sym_addr); - EXPECT_EQ(39, *reinterpret_cast<Elf64_Sxword*>(buff + 2)); - SB_LOG(INFO) << "buffer= " << *reinterpret_cast<Elf64_Sxword*>(buff + 2); -} -#endif - -} // namespace -} // namespace elf_loader -} // namespace starboard -#endif // SB_API_VERSION >= 12 && SB_HAS(MMAP) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/sandbox.cc b/src/starboard/elf_loader/sandbox.cc deleted file mode 100644 index 86e0476..0000000 --- a/src/starboard/elf_loader/sandbox.cc +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/common/log.h" -#include "starboard/event.h" - -#include "starboard/elf_loader/elf_loader.h" - -starboard::elf_loader::ElfLoader g_elfLoader; - -void (*g_sb_event_func)(const SbEvent*) = NULL; - -void SbEventHandle(const SbEvent* event) { - switch (event->type) { - case kSbEventTypeStart: { - SbEventStartData* data = static_cast<SbEventStartData*>(event->data); - if (!g_sb_event_func && data->argument_count == 2) { - if (!g_elfLoader.Load(data->argument_values[1])) { - SB_LOG(INFO) << "Failed to load library"; - return; - } - - SB_LOG(INFO) << "Successfully loaded library\n"; - void* p = g_elfLoader.LookupSymbol("SbEventHandle"); - if (p != NULL) { - SB_LOG(INFO) << "Symbol Lookup succeeded address=0x" << std::hex << p; - g_sb_event_func = (void (*)(const SbEvent*))p; - g_sb_event_func(event); - } else { - SB_LOG(INFO) << "Symbol Lookup failed\n"; - } - } - break; - } - default: { - if (g_sb_event_func) { - g_sb_event_func(event); - } - } - } -}
diff --git a/src/starboard/event.h b/src/starboard/event.h index f965b25..8fea369 100644 --- a/src/starboard/event.h +++ b/src/starboard/event.h
@@ -219,7 +219,8 @@ // SbEventWindowSizeChangedData. kSbEventTypeWindowSizeChanged, #endif // SB_API_VERSION >= 8 -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // The platform has shown the on screen keyboard. This event is triggered by // the system or by the application's OnScreenKeyboard show method. The event // has int data representing a ticket. The ticket is used by the application @@ -268,12 +269,13 @@ kSbEventTypeOnScreenKeyboardSuggestionsUpdated, #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) -#if SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) // One or more of the fields returned by SbAccessibilityGetCaptionSettings // has changed. kSbEventTypeAccessibilityCaptionSettingsChanged, -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) } SbEventType; // Structure representing a Starboard event and its data.
diff --git a/src/starboard/file.h b/src/starboard/file.h index 8fc57b5..11f7494 100644 --- a/src/starboard/file.h +++ b/src/starboard/file.h
@@ -160,6 +160,21 @@ // |file|: The absolute path of the file to be closed. SB_EXPORT bool SbFileClose(SbFile file); +#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + +// Replaces the content of the file at |path| with |data|. Returns whether the +// contents of the file were replaced. The replacement of the content is an +// atomic operation. The file will either have all of the data, or none. +// +// |path|: The path to the file whose contents should be replaced. +// |data|: The data to replace the file contents with. +// |data_size|: The amount of |data|, in bytes, to be written to the file. +SB_EXPORT bool SbFileAtomicReplace(const char* path, + const char* data, + int64_t data_size); + +#endif // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + // Changes the current read/write position in |file|. The return value // identifies the resultant current read/write position in the file (relative // to the start) or |-1| in case of an error. This function might not support @@ -276,7 +291,7 @@ int rv; do { rv = SbFileRead(file, data + bytes_read, size - bytes_read); - if (bytes_read <= 0) { + if (rv <= 0) { break; } bytes_read += rv; @@ -302,7 +317,7 @@ int rv; do { rv = SbFileWrite(file, data + bytes_written, size - bytes_written); - if (bytes_written <= 0) { + if (rv <= 0) { break; } bytes_written += rv;
diff --git a/src/starboard/gles.h b/src/starboard/gles.h index 6858437..2b74b0b 100644 --- a/src/starboard/gles.h +++ b/src/starboard/gles.h
@@ -37,6 +37,8 @@ #include "starboard/log.h" #include "starboard/types.h" +#if SB_API_VERSION >= 11 + #ifdef __cplusplus extern "C" { #endif @@ -1398,4 +1400,6 @@ } // extern "C" #endif +#endif // SB_API_VERSION >= 11 + #endif // STARBOARD_GLES_H_
diff --git a/src/starboard/input.h b/src/starboard/input.h index a8a8aec..3014ce6 100644 --- a/src/starboard/input.h +++ b/src/starboard/input.h
@@ -88,12 +88,14 @@ // Produces |Move|, |Press|, and |Unpress| events. kSbInputDeviceTypeTouchPad, -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // Keyboard input from an on screen keyboard. // // Produces |Input| events. kSbInputDeviceTypeOnScreenKeyboard, -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) } SbInputDeviceType; // The action that an input event represents. @@ -132,10 +134,12 @@ // Wheel movement. Provides relative movements of the |Mouse| wheel. kSbInputEventTypeWheel, -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // https://w3c.github.io/uievents/#event-type-input kSbInputEventTypeInput, -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) } SbInputEventType; // A 2-dimensional vector used to represent points and motion vectors. @@ -213,7 +217,8 @@ // towards the user (y). Use (NaN, NaN) for devices that do not report tilt. // This value is used for input events with device type mouse or touch screen. SbInputVector tilt; -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // The text to input for events of type |Input|. const char* input_text;
diff --git a/src/starboard/linux/shared/BUILD.gn b/src/starboard/linux/shared/BUILD.gn index 8fa8add..202313b 100644 --- a/src/starboard/linux/shared/BUILD.gn +++ b/src/starboard/linux/shared/BUILD.gn
@@ -359,6 +359,7 @@ "//starboard/shared/nouser/user_get_signed_in.cc", "//starboard/shared/nouser/user_internal.cc", "//starboard/shared/posix/directory_create.cc", + "//starboard/shared/posix/file_atomic_replace.cc", "//starboard/shared/posix/file_can_open.cc", "//starboard/shared/posix/file_close.cc", "//starboard/shared/posix/file_delete.cc", @@ -390,6 +391,7 @@ "//starboard/shared/posix/socket_internal.cc", "//starboard/shared/posix/socket_is_connected.cc", "//starboard/shared/posix/socket_is_connected_and_idle.cc", + "//starboard/shared/posix/socket_is_ipv6_supported.cc", "//starboard/shared/posix/socket_join_multicast_group.cc", "//starboard/shared/posix/socket_listen.cc", "//starboard/shared/posix/socket_receive_from.cc", @@ -418,6 +420,7 @@ "//starboard/shared/posix/time_get_monotonic_now.cc", "//starboard/shared/posix/time_get_monotonic_thread_now.cc", "//starboard/shared/posix/time_get_now.cc", + "//starboard/shared/posix/time_is_time_thread_now_supported.cc", "//starboard/shared/posix/time_zone_get_current.cc", "//starboard/shared/posix/time_zone_get_dst_name.cc", "//starboard/shared/posix/time_zone_get_name.cc", @@ -469,6 +472,8 @@ "//starboard/shared/starboard/directory_can_open.cc", "//starboard/shared/starboard/event_cancel.cc", "//starboard/shared/starboard/event_schedule.cc", + "//starboard/shared/starboard/file_atomic_replace_write_file.cc", + "//starboard/shared/starboard/file_atomic_replace_write_file.h", "//starboard/shared/starboard/file_mode_string_to_flags.cc", "//starboard/shared/starboard/file_storage/storage_close_record.cc", "//starboard/shared/starboard/file_storage/storage_delete_record.cc", @@ -502,7 +507,7 @@ "//starboard/shared/starboard/player/filter/audio_renderer_sink.h", "//starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc", "//starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h", - "//starboard/shared/starboard/player/filter/audio_resampler_impl.cc', + "//starboard/shared/starboard/player/filter/audio_resampler_impl.cc", "//starboard/shared/starboard/player/filter/audio_time_stretcher.cc", "//starboard/shared/starboard/player/filter/audio_time_stretcher.h", "//starboard/shared/starboard/player/filter/cpu_video_frame.cc", @@ -557,6 +562,7 @@ "//starboard/shared/starboard/system_request_unpause.cc", "//starboard/shared/starboard/system_supports_resume.cc", "//starboard/shared/starboard/window_set_default_options.cc", + "//starboard/shared/stub/accessibility_get_caption_settings.cc", "//starboard/shared/stub/accessibility_get_display_settings.cc", "//starboard/shared/stub/accessibility_get_text_to_speech_settings.cc", "//starboard/shared/stub/cryptography_create_transformer.cc",
diff --git a/src/starboard/linux/shared/cobalt/configuration.py b/src/starboard/linux/shared/cobalt/configuration.py index 51949c0..ce31306 100644 --- a/src/starboard/linux/shared/cobalt/configuration.py +++ b/src/starboard/linux/shared/cobalt/configuration.py
@@ -50,11 +50,20 @@ def GetWebPlatformTestFilters(self): filters = super(CobaltLinuxConfiguration, self).GetWebPlatformTestFilters() - filters += [ - 'xhr/WebPlatformTest.Run/XMLHttpRequest_send_timeout_events_htm', - 'streams/WebPlatformTest.Run/streams_readable_streams_templated_html', - 'cors/WebPlatformTest.Run/cors_preflight_failure_htm', - ] + filters.extend([ + # These tests are timing-sensitive, and are thus flaky on slower builds + test_filter.TestFilter( + 'web_platform_tests', + 'xhr/WebPlatformTest.Run/XMLHttpRequest_send_timeout_events_htm', + 'debug'), + test_filter.TestFilter( + 'web_platform_tests', + 'streams/WebPlatformTest.Run/streams_readable_streams_templated_html', + 'debug'), + test_filter.TestFilter( + 'web_platform_tests', + 'cors/WebPlatformTest.Run/cors_preflight_failure_htm', 'devel') + ]) return filters def GetTestEnvVariables(self):
diff --git a/src/starboard/linux/shared/command_line_defaults.cc b/src/starboard/linux/shared/command_line_defaults.cc new file mode 100644 index 0000000..78b0ca3 --- /dev/null +++ b/src/starboard/linux/shared/command_line_defaults.cc
@@ -0,0 +1,43 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/linux/shared/command_line_defaults.h" + +namespace starboard { +namespace linux_platform { // name conflict w/ compiler macro "linux" +namespace shared { + +namespace { +// See: cobalt/browser/switches.cc +const char kDevServersListenIpSwitch[] = "dev_servers_listen_ip"; +const char kDevServersListenIpSwitchDefault[] = "::1"; +} // namespace + +using starboard::shared::starboard::CommandLine; + +CommandLine GetCommandLine(int argc, char** argv) { + CommandLine command_line(argc, argv); + + // On Linux we default dev servers to only listen to localhost. + if (!command_line.HasSwitch(kDevServersListenIpSwitch)) { + command_line.AppendSwitch(kDevServersListenIpSwitch, + kDevServersListenIpSwitchDefault); + } + + return command_line; +} + +} // namespace shared +} // namespace linux_platform +} // namespace starboard
diff --git a/src/starboard/linux/shared/command_line_defaults.h b/src/starboard/linux/shared/command_line_defaults.h new file mode 100644 index 0000000..5fbd371 --- /dev/null +++ b/src/starboard/linux/shared/command_line_defaults.h
@@ -0,0 +1,29 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef STARBOARD_LINUX_SHARED_COMMAND_LINE_DEFAULTS_H_ +#define STARBOARD_LINUX_SHARED_COMMAND_LINE_DEFAULTS_H_ + +#include "starboard/shared/starboard/command_line.h" + +namespace starboard { +namespace linux_platform { // name conflict w/ compiler macro "linux" +namespace shared { + +starboard::shared::starboard::CommandLine GetCommandLine(int argc, char** argv); + +} // namespace shared +} // namespace linux_platform +} // namespace starboard + +#endif // STARBOARD_LINUX_SHARED_COMMAND_LINE_DEFAULTS_H_
diff --git a/src/starboard/linux/shared/compiler_flags.gypi b/src/starboard/linux/shared/compiler_flags.gypi index ed98d05..53b3229 100644 --- a/src/starboard/linux/shared/compiler_flags.gypi +++ b/src/starboard/linux/shared/compiler_flags.gypi
@@ -103,6 +103,20 @@ ], }], ], + 'defines_debug': [ + # Enable debug mode for the C++ standard library. + # https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/manual/debug_mode_using.html + # https://libcxx.llvm.org/docs/DesignDocs/DebugMode.html + '_GLIBCXX_DEBUG', + '_LIBCPP_DEBUG=1', + ], + 'defines_devel': [ + # Enable debug mode for the C++ standard library. + # https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/manual/debug_mode_using.html + # https://libcxx.llvm.org/docs/DesignDocs/DebugMode.html + '_GLIBCXX_DEBUG', + '_LIBCPP_DEBUG=0', + ], }, 'target_defaults': { @@ -147,6 +161,23 @@ '-Wno-undefined-var-template', ], }], + ['use_source_code_coverage==1', { + 'cflags': [ + # Enable Source Based Code Coverage instrumentation. + # See https://clang.llvm.org/docs/SourceBasedCodeCoverage.html + '-fprofile-instr-generate', + '-fcoverage-mapping', + ], + 'ldflags': [ + # Enable Source Based Code Coverage instrumentation. + # See https://clang.llvm.org/docs/SourceBasedCodeCoverage.html + '-fprofile-instr-generate', + '-fcoverage-mapping', + ], + 'defines': [ + 'USE_SOURCE_CODE_COVERAGE', + ], + }], ['use_asan==1', { 'cflags': [ '-fsanitize=address',
diff --git a/src/starboard/linux/shared/configuration_public.h b/src/starboard/linux/shared/configuration_public.h index 49ac525..b3aeff7 100644 --- a/src/starboard/linux/shared/configuration_public.h +++ b/src/starboard/linux/shared/configuration_public.h
@@ -23,10 +23,6 @@ #ifndef STARBOARD_LINUX_SHARED_CONFIGURATION_PUBLIC_H_ #define STARBOARD_LINUX_SHARED_CONFIGURATION_PUBLIC_H_ -#ifndef SB_API_VERSION -#define SB_API_VERSION SB_EXPERIMENTAL_API_VERSION -#endif - // --- System Header Configuration ------------------------------------------- // Any system headers listed here that are not provided by the platform will be @@ -191,12 +187,13 @@ // working properly. #define SB_HAS_BILINEAR_FILTERING_SUPPORT 1 +#if SB_API_VERSION < SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER_DEPRECATED_VERSION // Whether the current platform should frequently flip their display buffer. // If this is not required (e.g. SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is set // to 0), then optimizations where the display buffer is not flipped if the // scene hasn't changed are enabled. #define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER 0 - +#endif // --- I/O Configuration ----------------------------------------------------- // Whether the current platform has speech recognizer. @@ -273,7 +270,9 @@ // Whether this platform has and should use an MMAP function to map physical // memory to the virtual address space. +#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION #define SB_HAS_MMAP 1 +#endif // Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is // required for platforms that want to JIT.
diff --git a/src/starboard/linux/x64x11/enable_glx_via_angle.gypi b/src/starboard/linux/shared/enable_glx_via_angle.gypi similarity index 100% rename from src/starboard/linux/x64x11/enable_glx_via_angle.gypi rename to src/starboard/linux/shared/enable_glx_via_angle.gypi
diff --git a/src/starboard/linux/shared/gyp_configuration.gypi b/src/starboard/linux/shared/gyp_configuration.gypi index d1ac63b..b224935 100644 --- a/src/starboard/linux/shared/gyp_configuration.gypi +++ b/src/starboard/linux/shared/gyp_configuration.gypi
@@ -17,6 +17,10 @@ # { 'variables': { + # Override that omits the "data" subdirectory. + # TODO: Remove when omitted for all platforms in base_configuration.gypi. + 'sb_static_contents_output_data_dir': '<(PRODUCT_DIR)/content', + 'target_arch%': 'x64', 'target_os': 'linux', 'yasm_exists': 1,
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py index c77e593..574bc2a 100644 --- a/src/starboard/linux/shared/gyp_configuration.py +++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -27,8 +27,10 @@ def __init__(self, platform, asan_enabled_by_default=True, - goma_supports_compiler=True): + goma_supports_compiler=True, + sabi_json_path=None): self.goma_supports_compiler = goma_supports_compiler + self.sabi_json_path = sabi_json_path super(LinuxConfiguration, self).__init__(platform, asan_enabled_by_default) self.AppendApplicationConfigurationPath(os.path.dirname(__file__)) @@ -45,6 +47,8 @@ variables.update({ 'javascript_engine': 'v8', 'cobalt_enable_jit': 1, + 'include_path_platform_deploy_gypi': + 'starboard/linux/shared/platform_deploy.gypi', }) return variables @@ -89,6 +93,9 @@ filters.extend(test_filter.TestFilter(target, test) for test in tests) return filters - __FILTERED_TESTS = { + def GetPathToSabiJsonFile(self): + return self.sabi_json_path + + __FILTERED_TESTS = { # pylint: disable=invalid-name 'nplb': ['SbDrmTest.AnySupportedKeySystems',], }
diff --git a/src/starboard/linux/shared/launcher.py b/src/starboard/linux/shared/launcher.py index 8fe2616..662e68d 100644 --- a/src/starboard/linux/shared/launcher.py +++ b/src/starboard/linux/shared/launcher.py
@@ -14,6 +14,7 @@ # limitations under the License. """Linux implementation of Starboard launcher abstraction.""" +import errno import os import signal import socket @@ -34,8 +35,8 @@ Args: pid: process id of specified cobalt instance. """ - output = subprocess.check_output( - ["ps -o state= -p {}".format(pid)], shell=True) + output = subprocess.check_output(["ps -o state= -p {}".format(pid)], + shell=True) return output @@ -57,6 +58,21 @@ env.update(self.env_variables) self.full_env = env + # Ensure that if the binary has code coverage or profiling instrumentation, + # the output will be written to a file in the coverage_directory named as + # the target_name with '.profraw' postfixed. + if self.coverage_directory: + target_profraw = os.path.join(self.coverage_directory, + target_name + ".profraw") + env.update({"LLVM_PROFILE_FILE": target_profraw}) + + # Remove any stale profraw file that may already exist. + try: + os.remove(target_profraw) + except OSError as e: + if e.errno != errno.ENOENT: + raise + self.proc = None self.pid = None @@ -68,7 +84,8 @@ stdout=self.output_file, stderr=self.output_file, env=self.full_env, - close_fds=True) + close_fds=True, + cwd=self.out_directory) self.pid = self.proc.pid self.proc.wait() return self.proc.returncode @@ -111,10 +128,8 @@ """Wait for Cobalt to turn to target status within specified timeout limit. Args: - target_status: A character representing application status: - R-running; - T-stopped/suspended; - S-sleep/paused; + target_status: A character representing application status: R-running; + T-stopped/suspended; S-sleep/paused; timeout: Time limit in unit of seconds. """ elapsed_time = 0
diff --git a/src/starboard/linux/x64x11/libraries.gypi b/src/starboard/linux/shared/libraries.gypi similarity index 100% rename from src/starboard/linux/x64x11/libraries.gypi rename to src/starboard/linux/shared/libraries.gypi
diff --git a/src/starboard/linux/shared/media_is_audio_supported.cc b/src/starboard/linux/shared/media_is_audio_supported.cc index d0d9c7a..ecd147c 100644 --- a/src/starboard/linux/shared/media_is_audio_supported.cc +++ b/src/starboard/linux/shared/media_is_audio_supported.cc
@@ -17,8 +17,7 @@ #include "starboard/configuration.h" #include "starboard/media.h" -SB_EXPORT bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - int64_t bitrate) { +bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate) { if (audio_codec == kSbMediaAudioCodecAac) { return bitrate <= SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND; }
diff --git a/src/starboard/linux/shared/media_is_video_supported.cc b/src/starboard/linux/shared/media_is_video_supported.cc index dcb89b9..cd3cbe6 100644 --- a/src/starboard/linux/shared/media_is_video_supported.cc +++ b/src/starboard/linux/shared/media_is_video_supported.cc
@@ -15,6 +15,9 @@ #include "starboard/shared/starboard/media/media_support_internal.h" #include "starboard/configuration.h" +#if SB_API_VERSION >= 11 +#include "starboard/gles.h" +#endif // SB_API_VERSION >= 11 #include "starboard/media.h" #include "starboard/shared/libaom/aom_library_loader.h" #include "starboard/shared/libde265/de265_library_loader.h" @@ -26,24 +29,24 @@ using starboard::shared::starboard::media::IsSDRVideo; using starboard::shared::vpx::is_vpx_supported; -SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, +bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT) - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, #endif // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT) - int frame_width, - int frame_height, - int64_t bitrate, - int fps + int frame_width, + int frame_height, + int64_t bitrate, + int fps #if SB_API_VERSION >= 10 - , - bool decode_to_texture_required + , + bool decode_to_texture_required #endif // SB_API_VERSION >= 10 - ) { + ) { #if SB_API_VERSION < 11 const auto kSbMediaVideoCodecAv1 = kSbMediaVideoCodecVp10; #endif // SB_API_VERSION < 11 @@ -53,7 +56,7 @@ SB_UNREFERENCED_PARAMETER(level); if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) { - if (bit_depth != 10) { + if (bit_depth != 10 && bit_depth != 12) { return false; } if (video_codec != kSbMediaVideoCodecAv1 && @@ -61,18 +64,24 @@ return false; } } - #endif // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT) + #if SB_API_VERSION >= 10 -#if SB_HAS(BLITTER) if (decode_to_texture_required) { - return false; + bool has_gles_support = false; + +#if SB_API_VERSION >= 11 + has_gles_support = SbGetGlesInterface(); +#elif SB_HAS(GLES2) + has_gles_support = true; +#endif + + if (!has_gles_support) { + return false; + } + // Assume that all GLES2 Linux platforms can play decode-to-texture video + // just as well as normal video. } -#else - // Assume that all non-Blitter Linux platforms can play decode-to-texture - // video just as well as normal video. - SB_UNREFERENCED_PARAMETER(decode_to_texture_required); -#endif // SB_HAS(BLITTER) #endif // SB_API_VERSION >= 10 return ((video_codec == kSbMediaVideoCodecAv1 && is_aom_supported()) ||
diff --git a/src/starboard/linux/shared/platform_deploy.gypi b/src/starboard/linux/shared/platform_deploy.gypi new file mode 100644 index 0000000..0bbac50 --- /dev/null +++ b/src/starboard/linux/shared/platform_deploy.gypi
@@ -0,0 +1,37 @@ +# Copyright 2019 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. +{ + 'variables': { + 'executable_file': '<(PRODUCT_DIR)/<(executable_name)', + 'deploy_executable_file': '<(target_deploy_dir)/<(executable_name)', + }, + 'includes': [ '<(DEPTH)/starboard/build/collect_deploy_content.gypi' ], + 'actions': [ + { + 'action_name': 'deploy_executable', + 'message': 'Link deploy executable: <(deploy_executable_file)', + 'inputs': [ + '<(executable_file)', + '<(content_deploy_stamp_file)', + ], + 'outputs': [ '<(deploy_executable_file)' ], + 'action': [ + 'ln', + '-sf', + '$$(realpath --relative-to=<(target_deploy_dir) <(executable_file))', + '<(deploy_executable_file)', + ], + }, + ], +}
diff --git a/src/starboard/linux/shared/player_components_impl.cc b/src/starboard/linux/shared/player_components_impl.cc index 9154edc..53652ef 100644 --- a/src/starboard/linux/shared/player_components_impl.cc +++ b/src/starboard/linux/shared/player_components_impl.cc
@@ -16,6 +16,9 @@ #include "starboard/common/ref_counted.h" #include "starboard/common/scoped_ptr.h" +#if SB_API_VERSION >= 11 +#include "starboard/gles.h" +#endif // SB_API_VERSION >= 11 #include "starboard/media.h" #include "starboard/shared/ffmpeg/ffmpeg_audio_decoder.h" #include "starboard/shared/ffmpeg/ffmpeg_video_decoder.h" @@ -159,10 +162,19 @@ SbDrmSystem drm_system) { SB_UNREFERENCED_PARAMETER(codec); SB_UNREFERENCED_PARAMETER(drm_system); -#if SB_HAS(BLITTER) - return output_mode == kSbPlayerOutputModePunchOut; + + bool has_gles_support = false; + +#if SB_API_VERSION >= 11 + has_gles_support = SbGetGlesInterface(); +#elif SB_HAS(GLES2) + has_gles_support = true; #endif + if (!has_gles_support) { + return output_mode == kSbPlayerOutputModePunchOut; + } + #if defined(SB_FORCE_DECODE_TO_TEXTURE_ONLY) // Starboard lib targets may not draw directly to the window, so punch through // video is not made available.
diff --git a/src/starboard/linux/shared/starboard_platform.gypi b/src/starboard/linux/shared/starboard_platform.gypi index 1297986..d335946 100644 --- a/src/starboard/linux/shared/starboard_platform.gypi +++ b/src/starboard/linux/shared/starboard_platform.gypi
@@ -14,6 +14,7 @@ { 'includes': [ '<(DEPTH)/starboard/shared/starboard/player/filter/player_filter.gypi', + '<(DEPTH)/starboard/stub/blitter_stub_sources.gypi', ], 'variables': { 'variables': { @@ -23,9 +24,12 @@ # This has_cdm gets exported to gyp files that include this one. 'has_cdm%': '<(has_cdm)', 'starboard_platform_sources': [ + '<@(blitter_stub_sources)', '<@(filter_based_player_sources)', '<(DEPTH)/starboard/linux/shared/atomic_public.h', '<(DEPTH)/starboard/linux/shared/audio_sink_type_dispatcher.cc', + '<(DEPTH)/starboard/linux/shared/command_line_defaults.cc', + '<(DEPTH)/starboard/linux/shared/command_line_defaults.h', '<(DEPTH)/starboard/linux/shared/configuration_public.h', '<(DEPTH)/starboard/linux/shared/decode_target_get_info.cc', '<(DEPTH)/starboard/linux/shared/decode_target_internal.cc', @@ -122,6 +126,7 @@ '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc', '<(DEPTH)/starboard/shared/nouser/user_internal.cc', '<(DEPTH)/starboard/shared/posix/directory_create.cc', + '<(DEPTH)/starboard/shared/posix/file_atomic_replace.cc', '<(DEPTH)/starboard/shared/posix/file_can_open.cc', '<(DEPTH)/starboard/shared/posix/file_close.cc', '<(DEPTH)/starboard/shared/posix/file_delete.cc', @@ -153,6 +158,7 @@ '<(DEPTH)/starboard/shared/posix/socket_internal.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected_and_idle.cc', + '<(DEPTH)/starboard/shared/posix/socket_is_ipv6_supported.cc', '<(DEPTH)/starboard/shared/posix/socket_join_multicast_group.cc', '<(DEPTH)/starboard/shared/posix/socket_listen.cc', '<(DEPTH)/starboard/shared/posix/socket_receive_from.cc', @@ -181,6 +187,7 @@ '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_now.cc', + '<(DEPTH)/starboard/shared/posix/time_is_time_thread_now_supported.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_name.cc', '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc', @@ -223,6 +230,7 @@ '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc', '<(DEPTH)/starboard/shared/signal/suspend_signals.cc', '<(DEPTH)/starboard/shared/signal/suspend_signals.h', + '<(DEPTH)/starboard/shared/signal/system_request_suspend.cc', '<(DEPTH)/starboard/shared/starboard/application.cc', '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc', '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc', @@ -241,6 +249,8 @@ '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc', '<(DEPTH)/starboard/shared/starboard/event_cancel.cc', '<(DEPTH)/starboard/shared/starboard/event_schedule.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.h', '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc', @@ -312,10 +322,10 @@ '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc', '<(DEPTH)/starboard/shared/starboard/system_request_pause.cc', '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc', - '<(DEPTH)/starboard/shared/starboard/system_request_suspend.cc', '<(DEPTH)/starboard/shared/starboard/system_request_unpause.cc', '<(DEPTH)/starboard/shared/starboard/system_supports_resume.cc', '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc', + '<(DEPTH)/starboard/shared/stub/accessibility_get_caption_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_display_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc', '<(DEPTH)/starboard/shared/linux/cpu_features_get.cc', @@ -336,13 +346,32 @@ '<(DEPTH)/starboard/shared/stub/microphone_is_sample_rate_supported.cc', '<(DEPTH)/starboard/shared/stub/microphone_open.cc', '<(DEPTH)/starboard/shared/stub/microphone_read.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_cancel.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_create.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_destroy.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_start.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_stop.cc', + '<(DEPTH)/starboard/shared/stub/speech_synthesis_cancel.cc', + '<(DEPTH)/starboard/shared/stub/speech_synthesis_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/speech_synthesis_speak.cc', '<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc', '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc', '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc', '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', '<(DEPTH)/starboard/shared/stub/system_sign_with_certification_secret_key.cc', '<(DEPTH)/starboard/shared/stub/ui_nav_get_interface.cc', + '<(DEPTH)/starboard/shared/stub/window_blur_on_screen_keyboard.cc', + '<(DEPTH)/starboard/shared/stub/window_focus_on_screen_keyboard.cc', '<(DEPTH)/starboard/shared/stub/window_get_diagonal_size_in_inches.cc', + '<(DEPTH)/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc', + '<(DEPTH)/starboard/shared/stub/window_hide_on_screen_keyboard.cc', + '<(DEPTH)/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc', + '<(DEPTH)/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc', + '<(DEPTH)/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc', + '<(DEPTH)/starboard/shared/stub/window_show_on_screen_keyboard.cc', + '<(DEPTH)/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc', ], 'starboard_platform_dependencies': [ '<(DEPTH)/starboard/common/common.gyp:common',
diff --git a/src/starboard/linux/shared/system_get_path.cc b/src/starboard/linux/shared/system_get_path.cc index ac8f5fa..c536e32 100644 --- a/src/starboard/linux/shared/system_get_path.cc +++ b/src/starboard/linux/shared/system_get_path.cc
@@ -44,6 +44,22 @@ return SbDirectoryCreate(out_path); } +// Gets the path to the storage directory, using the user's home directory. +bool GetStorageDirectory(char* out_path, int path_size) { + char home_path[kMaxPathSize + 1]; + if (!SbUserGetProperty(SbUserGetCurrent(), kSbUserPropertyHomeDirectory, + home_path, kMaxPathSize)) { + return false; + } + int result = + SbStringFormatF(out_path, path_size, "%s/.cobalt_storage", home_path); + if (result < 0 || result >= path_size) { + out_path[0] = '\0'; + return false; + } + return SbDirectoryCreate(out_path); +} + // Places up to |path_size| - 1 characters of the path to the current // executable in |out_path|, ensuring it is NULL-terminated. Returns success // status. The result being greater than |path_size| - 1 characters is a @@ -134,7 +150,7 @@ if (!GetExecutableDirectory(path, kPathSize)) { return false; } - if (SbStringConcat(path, "/content/data", kPathSize) >= kPathSize) { + if (SbStringConcat(path, "/content", kPathSize) >= kPathSize) { return false; } break; @@ -179,6 +195,14 @@ case kSbSystemPathFontDirectory: return false; +#if SB_API_VERSION >= SB_STORAGE_PATH_VERSION + case kSbSystemPathStorageDirectory: + if (!GetStorageDirectory(path, kPathSize)) { + return false; + } + break; +#endif + default: SB_NOTIMPLEMENTED() << "SbSystemGetPath not implemented for " << path_id;
diff --git a/src/starboard/linux/x64directfb/README.md b/src/starboard/linux/x64directfb/README.md deleted file mode 100644 index b8fd196..0000000 --- a/src/starboard/linux/x64directfb/README.md +++ /dev/null
@@ -1,70 +0,0 @@ -# Starboard on DirectFB - -Starboard features a configuration for DirectFB, allowing applications targeting -Starboard to be run on devices that support DirectFB. - -Building Starboard to target DirectFB is setup as its own configuration which -must be specifically selected by gyp. The configuration files can be found -in starboard/linux/x64directfb, the same directory as this README file. The -configuration assumes that DirectFB is running on a Linux x64 platform. - -## Building an application for Starboard DirectFB x64 Linux - -First, ensure that the DirectFB libraries are installed and accessible. - - $ sudo apt-get install libdirectfb-dev libdirectfb-extra - -Next, run gyp for this DirectFB configuration: - - $ cobalt/build/gyp_cobalt linux-x64directfb - -And finally, run ninja to build the application: - - $ ninja -C out/linux-x64directfb_debug starboard_blitter_example - -## Running an application built for Starboard DirectFB x64 Linux - -If you are using a desktop Linux workstation to run the executable, you will -likely not have framebuffer support enabled in your Linux build. In order to -have DirectFB applications run under X11, you will need to modify your -DirectFB configuration file. - - $ vi ~/.directfbrc - > system=x11 - > quiet - -Adding the "quiet" flag is optional, it will suppress log output from DirectFB. - -You can now run applications built under this configuration. However, if you -run an application, you may encounter a message (if you don’t specify “quiet” -in your .directfbrc file) indicating that XShm is not being used. If you see -this, you will likely encounter a crash when DirectFB is shutdown (such as -during application shutdown). To avoid this, you can run all DirectFB apps -through Xephyr. - -First, install Xephyr: - - $ sudo apt-get install xserver-xephyr - -There is a script, starboard/linux/x64/directfb/xephyr_run.sh -which will automatically run an executable (and its parameters) within a -Xephyr window. For example, to run the nplb executable under Xephyr: - - $ starboard/linux/x64directfb/xephyr_run.sh out/linux-x64directfb_debug/nplb - -Note that the script will start an instance of Xephyr, run the application -within it, and then shutdown Xephyr when the application terminates. - -If you would like to manually start Xephyr and run applications within it (e.g. -to make debugging easier), you can do so by first starting Xephyr in the -background: - - $ Xephyr -screen 1920x1080 :1 2> /dev/null & - -And then launch the application and have it target the Xephyr display: - - $ DISPLAY=:1 out/linux-x64directfb_debug/starboard_blitter_example - -or - - $ DISPLAY=:1 out/linux-x64directfb_debug/nplb
diff --git a/src/starboard/linux/x64directfb/atomic_public.h b/src/starboard/linux/x64directfb/atomic_public.h deleted file mode 100644 index df6dc82..0000000 --- a/src/starboard/linux/x64directfb/atomic_public.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2016 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/linux/shared/atomic_public.h"
diff --git a/src/starboard/linux/x64directfb/configuration_public.h b/src/starboard/linux/x64directfb/configuration_public.h deleted file mode 100644 index 4d40794..0000000 --- a/src/starboard/linux/x64directfb/configuration_public.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2016 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. - -// The Starboard configuration for Desktop X86 Linux. Other devices will have -// specific Starboard implementations, even if they ultimately are running some -// version of Linux. - -// Other source files should never include this header directly, but should -// include the generic "starboard/configuration.h" instead. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_CONFIGURATION_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_CONFIGURATION_PUBLIC_H_ - -// Reuse the configuration from Linux_x64, but we'll also enable the Blitter -// API afterwards since we'll have DirectFB available. -#include "starboard/linux/x64x11/configuration_public.h" - -// Indicates whether or not the given platform supports rendering of NV12 -// textures. These textures typically originate from video decoders. -#undef SB_HAS_NV12_TEXTURE_SUPPORT -#define SB_HAS_NV12_TEXTURE_SUPPORT 0 - -// This configuration supports the blitter API (implemented via DirectFB). -#undef SB_HAS_BLITTER -#define SB_HAS_BLITTER 1 - -// Unfortunately, DirectFB does not support bilinear filtering. According to -// http://osdir.com/ml/graphics.directfb.user/2008-06/msg00028.html, "smooth -// scaling is not supported in conjunction with blending", and we need blending -// more. -#undef SB_HAS_BILINEAR_FILTERING_SUPPORT -#define SB_HAS_BILINEAR_FILTERING_SUPPORT 0 - -// DirectFB's only 32-bit RGBA color format is word-order ARGB. This translates -// to byte-order ARGB for big endian platforms and byte-order BGRA for -// little-endian platforms. -#undef SB_PREFERRED_RGBA_BYTE_ORDER -#if SB_IS(BIG_ENDIAN) -#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_ARGB -#else -#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_BGRA -#endif - -#endif // STARBOARD_LINUX_X64DIRECTFB_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.gypi b/src/starboard/linux/x64directfb/gyp_configuration.gypi deleted file mode 100644 index 4956cb4..0000000 --- a/src/starboard/linux/x64directfb/gyp_configuration.gypi +++ /dev/null
@@ -1,51 +0,0 @@ -# Copyright 2014 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. - -# Platform specific configuration for Linux on Starboard. Automatically -# included by gyp_cobalt in all .gyp files by Cobalt together with base.gypi. -# - -{ - 'variables': { - 'platform_libraries': [ - '-ldirectfb', - '-ldirect', - ], - - 'gl_type': 'none', - }, - - 'target_defaults': { - 'default_configuration': 'linux-x64directfb_debug', - 'configurations': { - 'linux-x64directfb_debug': { - 'inherit_from': ['debug_base'], - }, - 'linux-x64directfb_devel': { - 'inherit_from': ['devel_base'], - }, - 'linux-x64directfb_qa': { - 'inherit_from': ['qa_base'], - }, - 'linux-x64directfb_gold': { - 'inherit_from': ['gold_base'], - }, - }, # end of configurations - }, - - 'includes': [ - '../shared/compiler_flags.gypi', - '../shared/gyp_configuration.gypi', - ], -}
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.py b/src/starboard/linux/x64directfb/gyp_configuration.py deleted file mode 100644 index 7ed3457..0000000 --- a/src/starboard/linux/x64directfb/gyp_configuration.py +++ /dev/null
@@ -1,73 +0,0 @@ -# Copyright 2017 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Starboard Linux X64 DirectFB platform configuration.""" - -from starboard.linux.shared import gyp_configuration as shared_configuration -from starboard.tools.testing import test_filter - - -class CobaltLinuxX64DirectFbConfiguration( - shared_configuration.LinuxConfiguration): - - # Unfortunately, some memory leaks outside of our control, and difficult - # to pattern match with ASAN's suppression list, appear in DirectFB - # builds, and so ASAN must be disabled. - def __init__(self, - platform='linux-x64directfb', - asan_enabled_by_default=False, - goma_supported_by_compiler=True): - super(CobaltLinuxX64DirectFbConfiguration, - self).__init__(platform, asan_enabled_by_default, - goma_supported_by_compiler) - - def GetTestFilters(self): - filters = ( - super(CobaltLinuxX64DirectFbConfiguration, self).GetTestFilters()) - for target, tests in self.__FILTERED_TESTS.iteritems(): - filters.extend(test_filter.TestFilter(target, test) for test in tests) - return filters - - # All filtered tests are filtered because the DirectFB drivers on - # many Linux distributions are unstable and experience crashes when - # creating and working with SbWindow objects. - __FILTERED_TESTS = { - 'nplb': [ - 'SbBlitterCreateSwapChainFromWindowTest.RainyDayBadDevice', - 'SbBlitterCreateSwapChainFromWindowTest.RainyDayBadWindow', - 'SbBlitterCreateSwapChainFromWindowTest.RainyDayInvalidSwapChain', - 'SbBlitterCreateSwapChainFromWindowTest.SunnyDay', - 'SbBlitterCreateSwapChainFromWindowTest.SunnyDayMultipleTimes', - 'SbBlitterFlipSwapChainTest.SunnyDay', - 'SbBlitterGetRenderTargetFromSwapChainTest.SunnyDay', - 'SbBlitterGetRenderTargetFromSwapChainTest.SunnyDayCanDraw', - # FakeGraphicsContextProvider does not support DirectFB currently. - 'SbMediaSetAudioWriteDurationTests/SbMediaSetAudioWriteDurationTest.*', - 'SbPlayerTest.AudioOnly', - 'SbPlayerTest.Audioless', - 'SbPlayerTest.MultiPlayer', - 'SbPlayerTest.NullCallbacks', - 'SbPlayerTest.SunnyDay', - 'SbWindowCreateTest.SunnyDayDefault', - 'SbWindowCreateTest.SunnyDayDefaultSet', - 'SbWindowGetPlatformHandleTest.RainyDay', - 'SbWindowGetPlatformHandleTest.SunnyDay', - 'SbWindowGetSizeTest.RainyDayInvalid', - 'SbWindowGetSizeTest.SunnyDay', - ], - 'player_filter_tests': [test_filter.FILTER_ALL], - } - - -def CreatePlatformConfig(): - return CobaltLinuxX64DirectFbConfiguration()
diff --git a/src/starboard/linux/x64directfb/main.cc b/src/starboard/linux/x64directfb/main.cc deleted file mode 100644 index fa0bd94..0000000 --- a/src/starboard/linux/x64directfb/main.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2016 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 <time.h> - -#include "starboard/configuration.h" -#include "starboard/shared/directfb/application_directfb.h" -#include "starboard/shared/signal/crash_signals.h" -#include "starboard/shared/signal/suspend_signals.h" - -int main(int argc, char** argv) { - tzset(); - starboard::shared::signal::InstallCrashSignalHandlers(); - starboard::shared::signal::InstallSuspendSignalHandlers(); - starboard::ApplicationDirectFB application; - int result = application.Run(argc, argv); - starboard::shared::signal::UninstallSuspendSignalHandlers(); - starboard::shared::signal::UninstallCrashSignalHandlers(); - return result; -}
diff --git a/src/starboard/linux/x64directfb/sanitizer_options.cc b/src/starboard/linux/x64directfb/sanitizer_options.cc deleted file mode 100644 index 366f8ba..0000000 --- a/src/starboard/linux/x64directfb/sanitizer_options.cc +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2016 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. - -// Removes gallium leak warnings from x11 GL code, but defines it as a weak -// symbol, so other code can override it if they want to. - -#if defined(ADDRESS_SANITIZER) - -// Functions returning default options are declared weak in the tools' runtime -// libraries. To make the linker pick the strong replacements for those -// functions from this module, we explicitly force its inclusion by passing -// -Wl,-u_sanitizer_options_link_helper -extern "C" void _sanitizer_options_link_helper() { } - -#define SANITIZER_HOOK_ATTRIBUTE \ - extern "C" \ - __attribute__((no_sanitize_address)) \ - __attribute__((no_sanitize_memory)) \ - __attribute__((no_sanitize_thread)) \ - __attribute__((visibility("default"))) \ - __attribute__((weak)) \ - __attribute__((used)) - -// Newline separated list of issues to suppress, see -// http://clang.llvm.org/docs/AddressSanitizer.html#issue-suppression -// http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_suppressions.cc -SANITIZER_HOOK_ATTRIBUTE const char* __lsan_default_suppressions() { - return - // DirectFB leaks __strdup data at initialization time. - "leak:__strdup\n"; -} - -#if defined(ASAN_SYMBOLIZER_PATH) -extern "C" const char *__asan_default_options() { - return "external_symbolizer_path=" ASAN_SYMBOLIZER_PATH; -} -#endif - -#endif // defined(ADDRESS_SANITIZER)
diff --git a/src/starboard/linux/x64directfb/sbversion/10/atomic_public.h b/src/starboard/linux/x64directfb/sbversion/10/atomic_public.h deleted file mode 100644 index 2f5b518..0000000 --- a/src/starboard/linux/x64directfb/sbversion/10/atomic_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_ATOMIC_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_ATOMIC_PUBLIC_H_ - -#include "starboard/linux/x64directfb/atomic_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/sbversion/10/configuration_public.h b/src/starboard/linux/x64directfb/sbversion/10/configuration_public.h deleted file mode 100644 index 887eb66..0000000 --- a/src/starboard/linux/x64directfb/sbversion/10/configuration_public.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_CONFIGURATION_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_CONFIGURATION_PUBLIC_H_ - -#undef SB_API_VERSION -#define SB_API_VERSION 10 - -#include "starboard/linux/x64directfb/configuration_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/sbversion/10/gyp_configuration.gypi b/src/starboard/linux/x64directfb/sbversion/10/gyp_configuration.gypi deleted file mode 100644 index 33e612d..0000000 --- a/src/starboard/linux/x64directfb/sbversion/10/gyp_configuration.gypi +++ /dev/null
@@ -1,40 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'target_defaults': { - 'default_configuration': 'linux-x64directfb-sbversion-10_debug', - 'configurations': { - 'linux-x64directfb-sbversion-10_debug': { - 'inherit_from': ['debug_base'], - }, - 'linux-x64directfb-sbversion-10_devel': { - 'inherit_from': ['devel_base'], - }, - 'linux-x64directfb-sbversion-10_qa': { - 'inherit_from': ['qa_base'], - }, - 'linux-x64directfb-sbversion-10_gold': { - 'inherit_from': ['gold_base'], - }, - }, # end of configurations - }, - - 'includes': [ - '<(DEPTH)/starboard/linux/x64directfb/gyp_configuration.gypi', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/10/gyp_configuration.py b/src/starboard/linux/x64directfb/sbversion/10/gyp_configuration.py deleted file mode 100644 index 45ee34e..0000000 --- a/src/starboard/linux/x64directfb/sbversion/10/gyp_configuration.py +++ /dev/null
@@ -1,23 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - - -from starboard.linux.x64directfb import gyp_configuration as parent_configuration - - -def CreatePlatformConfig(): - return parent_configuration.CobaltLinuxX64DirectFbConfiguration('linux-x64directfb-sbversion-10')
diff --git a/src/starboard/linux/x64directfb/sbversion/10/starboard_platform.gyp b/src/starboard/linux/x64directfb/sbversion/10/starboard_platform.gyp deleted file mode 100644 index ec523b0..0000000 --- a/src/starboard/linux/x64directfb/sbversion/10/starboard_platform.gyp +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'includes': [ - # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea - # is that we just want this file to *be* the parent gyp file. - '<(DEPTH)/starboard/linux/x64directfb/starboard_platform.gyp', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/10/starboard_platform_tests.gyp b/src/starboard/linux/x64directfb/sbversion/10/starboard_platform_tests.gyp deleted file mode 100644 index b5175c6..0000000 --- a/src/starboard/linux/x64directfb/sbversion/10/starboard_platform_tests.gyp +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'includes': [ - # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea - # is that we just want this file to *be* the parent gyp file. - '<(DEPTH)/starboard/linux/x64directfb/starboard_platform_tests.gyp', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/10/thread_types_public.h b/src/starboard/linux/x64directfb/sbversion/10/thread_types_public.h deleted file mode 100644 index ffd1c28..0000000 --- a/src/starboard/linux/x64directfb/sbversion/10/thread_types_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_THREAD_TYPES_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_THREAD_TYPES_PUBLIC_H_ - -#include "starboard/linux/x64directfb/thread_types_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_10_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/sbversion/11/atomic_public.h b/src/starboard/linux/x64directfb/sbversion/11/atomic_public.h deleted file mode 100644 index 77c1c54..0000000 --- a/src/starboard/linux/x64directfb/sbversion/11/atomic_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_ATOMIC_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_ATOMIC_PUBLIC_H_ - -#include "starboard/linux/x64directfb/atomic_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/sbversion/11/configuration_public.h b/src/starboard/linux/x64directfb/sbversion/11/configuration_public.h deleted file mode 100644 index 206f764..0000000 --- a/src/starboard/linux/x64directfb/sbversion/11/configuration_public.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_CONFIGURATION_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_CONFIGURATION_PUBLIC_H_ - -#undef SB_API_VERSION -#define SB_API_VERSION 11 - -#include "starboard/linux/x64directfb/configuration_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/sbversion/11/gyp_configuration.gypi b/src/starboard/linux/x64directfb/sbversion/11/gyp_configuration.gypi deleted file mode 100644 index 0b311fd..0000000 --- a/src/starboard/linux/x64directfb/sbversion/11/gyp_configuration.gypi +++ /dev/null
@@ -1,40 +0,0 @@ -# Copyright 2019 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'target_defaults': { - 'default_configuration': 'linux-x64directfb-sbversion-11_debug', - 'configurations': { - 'linux-x64directfb-sbversion-11_debug': { - 'inherit_from': ['debug_base'], - }, - 'linux-x64directfb-sbversion-11_devel': { - 'inherit_from': ['devel_base'], - }, - 'linux-x64directfb-sbversion-11_qa': { - 'inherit_from': ['qa_base'], - }, - 'linux-x64directfb-sbversion-11_gold': { - 'inherit_from': ['gold_base'], - }, - }, # end of configurations - }, - - 'includes': [ - '<(DEPTH)/starboard/linux/x64directfb/gyp_configuration.gypi', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/11/gyp_configuration.py b/src/starboard/linux/x64directfb/sbversion/11/gyp_configuration.py deleted file mode 100644 index 8a5279a..0000000 --- a/src/starboard/linux/x64directfb/sbversion/11/gyp_configuration.py +++ /dev/null
@@ -1,23 +0,0 @@ -# Copyright 2019 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - - -from starboard.linux.x64directfb import gyp_configuration as parent_configuration - - -def CreatePlatformConfig(): - return parent_configuration.CobaltLinuxX64DirectFbConfiguration('linux-x64directfb-sbversion-11')
diff --git a/src/starboard/linux/x64directfb/sbversion/11/starboard_platform.gyp b/src/starboard/linux/x64directfb/sbversion/11/starboard_platform.gyp deleted file mode 100644 index b841547..0000000 --- a/src/starboard/linux/x64directfb/sbversion/11/starboard_platform.gyp +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2019 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'includes': [ - # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea - # is that we just want this file to *be* the parent gyp file. - '<(DEPTH)/starboard/linux/x64directfb/starboard_platform.gyp', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/11/starboard_platform_tests.gyp b/src/starboard/linux/x64directfb/sbversion/11/starboard_platform_tests.gyp deleted file mode 100644 index 5d82b6c..0000000 --- a/src/starboard/linux/x64directfb/sbversion/11/starboard_platform_tests.gyp +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2019 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'includes': [ - # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea - # is that we just want this file to *be* the parent gyp file. - '<(DEPTH)/starboard/linux/x64directfb/starboard_platform_tests.gyp', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/11/thread_types_public.h b/src/starboard/linux/x64directfb/sbversion/11/thread_types_public.h deleted file mode 100644 index 0938261..0000000 --- a/src/starboard/linux/x64directfb/sbversion/11/thread_types_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_THREAD_TYPES_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_THREAD_TYPES_PUBLIC_H_ - -#include "starboard/linux/x64directfb/thread_types_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_11_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/sbversion/6/atomic_public.h b/src/starboard/linux/x64directfb/sbversion/6/atomic_public.h deleted file mode 100644 index 99350dc..0000000 --- a/src/starboard/linux/x64directfb/sbversion/6/atomic_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_ATOMIC_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_ATOMIC_PUBLIC_H_ - -#include "starboard/linux/x64directfb/atomic_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/sbversion/6/configuration_public.h b/src/starboard/linux/x64directfb/sbversion/6/configuration_public.h deleted file mode 100644 index 5df43f6..0000000 --- a/src/starboard/linux/x64directfb/sbversion/6/configuration_public.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_CONFIGURATION_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_CONFIGURATION_PUBLIC_H_ - -#undef SB_API_VERSION -#define SB_API_VERSION 6 - -#include "starboard/linux/x64directfb/configuration_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/sbversion/6/gyp_configuration.gypi b/src/starboard/linux/x64directfb/sbversion/6/gyp_configuration.gypi deleted file mode 100644 index 7804843..0000000 --- a/src/starboard/linux/x64directfb/sbversion/6/gyp_configuration.gypi +++ /dev/null
@@ -1,40 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'target_defaults': { - 'default_configuration': 'linux-x64directfb-sbversion-6_debug', - 'configurations': { - 'linux-x64directfb-sbversion-6_debug': { - 'inherit_from': ['debug_base'], - }, - 'linux-x64directfb-sbversion-6_devel': { - 'inherit_from': ['devel_base'], - }, - 'linux-x64directfb-sbversion-6_qa': { - 'inherit_from': ['qa_base'], - }, - 'linux-x64directfb-sbversion-6_gold': { - 'inherit_from': ['gold_base'], - }, - }, # end of configurations - }, - - 'includes': [ - '<(DEPTH)/starboard/linux/x64directfb/gyp_configuration.gypi', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/6/gyp_configuration.py b/src/starboard/linux/x64directfb/sbversion/6/gyp_configuration.py deleted file mode 100644 index d5632e5..0000000 --- a/src/starboard/linux/x64directfb/sbversion/6/gyp_configuration.py +++ /dev/null
@@ -1,38 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by create_derived_build.py, -# though it may have been modified since its creation. - -from starboard.linux.x64directfb import gyp_configuration as parent_configuration - - -class LinuxX64DirectFbSbversion6Configuration( - parent_configuration.CobaltLinuxX64DirectFbConfiguration): - - def GetVariables(self, config_name): - variables = super(LinuxX64DirectFbSbversion6Configuration, - self).GetVariables(config_name) - # V8 requires new Starboard features so we must use SpiderMonkey in older - # versions of Starboard. - variables.update({ - 'javascript_engine': 'mozjs-45', - 'cobalt_enable_jit': 0, - }) - return variables - - -def CreatePlatformConfig(): - return LinuxX64DirectFbSbversion6Configuration( - 'linux-x64directfb-sbversion-6')
diff --git a/src/starboard/linux/x64directfb/sbversion/6/starboard_platform.gyp b/src/starboard/linux/x64directfb/sbversion/6/starboard_platform.gyp deleted file mode 100644 index 58fddef..0000000 --- a/src/starboard/linux/x64directfb/sbversion/6/starboard_platform.gyp +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'includes': [ - # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea - # is that we just want this file to *be* the parent gyp file. - '<(DEPTH)/starboard/linux/x64directfb/starboard_platform.gyp', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/6/starboard_platform_tests.gyp b/src/starboard/linux/x64directfb/sbversion/6/starboard_platform_tests.gyp deleted file mode 100644 index 4bbf4f3..0000000 --- a/src/starboard/linux/x64directfb/sbversion/6/starboard_platform_tests.gyp +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'includes': [ - # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea - # is that we just want this file to *be* the parent gyp file. - '<(DEPTH)/starboard/linux/x64directfb/starboard_platform_tests.gyp', - ], -}
diff --git a/src/starboard/linux/x64directfb/sbversion/6/thread_types_public.h b/src/starboard/linux/x64directfb/sbversion/6/thread_types_public.h deleted file mode 100644 index f6fe910..0000000 --- a/src/starboard/linux/x64directfb/sbversion/6/thread_types_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_THREAD_TYPES_PUBLIC_H_ -#define STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_THREAD_TYPES_PUBLIC_H_ - -#include "starboard/linux/x64directfb/thread_types_public.h" - -#endif // STARBOARD_LINUX_X64DIRECTFB_SBVERSION_6_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp deleted file mode 100644 index 096b55f..0000000 --- a/src/starboard/linux/x64directfb/starboard_platform.gyp +++ /dev/null
@@ -1,36 +0,0 @@ -# Copyright 2015 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. -{ - 'includes': [ - 'starboard_platform.gypi' - ], - 'targets': [ - { - 'target_name': 'starboard_platform', - 'type': 'static_library', - 'sources': ['<@(starboard_platform_sources)'], - 'include_dirs': [ - '/usr/include/directfb', - ], - 'defines': [ - # This must be defined when building Starboard, and must not when - # building Starboard client code. - 'STARBOARD_IMPLEMENTATION', - ], - 'dependencies': [ - '<@(starboard_platform_dependencies)', - ], - }, - ], -}
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gypi b/src/starboard/linux/x64directfb/starboard_platform.gypi deleted file mode 100644 index b598f37..0000000 --- a/src/starboard/linux/x64directfb/starboard_platform.gypi +++ /dev/null
@@ -1,69 +0,0 @@ -# Copyright 2016 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. -{ - 'includes': ['../shared/starboard_platform.gypi'], - - 'variables': { - 'starboard_platform_sources': [ - '<(DEPTH)/starboard/linux/x64directfb/main.cc', - '<(DEPTH)/starboard/linux/x64directfb/sanitizer_options.cc', - '<(DEPTH)/starboard/linux/x64directfb/system_get_property.cc', - '<(DEPTH)/starboard/shared/directfb/application_directfb.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_blit_rect_to_rect.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_create_context.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_create_default_device.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_create_pixel_data.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_create_render_target_surface.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_create_surface_from_pixel_data.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_create_swap_chain_from_window.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_destroy_context.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_destroy_device.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_destroy_pixel_data.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_destroy_surface.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_destroy_swap_chain.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_download_surface_pixels.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_fill_rect.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_flip_swap_chain.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_flush_context.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_get_max_contexts.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_get_pixel_data_pitch_in_bytes.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_get_pixel_data_pointer.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_get_render_target_from_surface.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_get_render_target_from_swap_chain.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_get_surface_info.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_internal.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_is_pixel_format_supported_by_download_surface_pixels.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_is_pixel_format_supported_by_pixel_data.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_is_surface_format_supported_by_render_target_surface.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_set_blending.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_set_color.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_set_modulate_blits_with_color.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_set_render_target.cc', - '<(DEPTH)/starboard/shared/directfb/blitter_set_scissor.cc', - '<(DEPTH)/starboard/shared/directfb/window_create.cc', - '<(DEPTH)/starboard/shared/directfb/window_destroy.cc', - '<(DEPTH)/starboard/shared/directfb/window_get_platform_handle.cc', - '<(DEPTH)/starboard/shared/directfb/window_get_size.cc', - '<(DEPTH)/starboard/shared/directfb/window_internal.cc', - '<(DEPTH)/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc', - '<(DEPTH)/starboard/shared/starboard/blitter_blit_rects_to_rects.cc', - '<(DEPTH)/starboard/shared/stub/system_egl.cc', - '<(DEPTH)/starboard/shared/stub/system_gles.cc', - ], - 'starboard_platform_sources!': [ - '<(DEPTH)/starboard/shared/egl/system_egl.cc', - '<(DEPTH)/starboard/shared/egl/system_gles2.cc', - ], - }, -}
diff --git a/src/starboard/linux/x64directfb/starboard_platform_tests.gyp b/src/starboard/linux/x64directfb/starboard_platform_tests.gyp deleted file mode 100644 index 0ea8622..0000000 --- a/src/starboard/linux/x64directfb/starboard_platform_tests.gyp +++ /dev/null
@@ -1,18 +0,0 @@ -# Copyright 2018 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. -{ - 'includes': [ - '<(DEPTH)/starboard/linux/shared/starboard_platform_tests.gypi', - ], -}
diff --git a/src/starboard/linux/x64directfb/system_get_property.cc b/src/starboard/linux/x64directfb/system_get_property.cc deleted file mode 100644 index ba9af40..0000000 --- a/src/starboard/linux/x64directfb/system_get_property.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2016 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/system.h" - -#include "starboard/common/log.h" -#include "starboard/common/string.h" - -namespace { - -const char* kFriendlyName = "Linux Desktop"; -const char* kPlatformName = "DirectFB; Linux x86_64"; - -bool CopyStringAndTestIfSuccess(char* out_value, - int value_length, - const char* from_value) { - if (SbStringGetLength(from_value) + 1 > value_length) - return false; - SbStringCopy(out_value, from_value, value_length); - return true; -} - -} // namespace - -bool SbSystemGetProperty(SbSystemPropertyId property_id, - char* out_value, - int value_length) { - if (!out_value || !value_length) { - return false; - } - - switch (property_id) { - case kSbSystemPropertyBrandName: - case kSbSystemPropertyChipsetModelNumber: - case kSbSystemPropertyFirmwareVersion: - case kSbSystemPropertyModelName: - case kSbSystemPropertyModelYear: -#if SB_API_VERSION >= 11 - case kSbSystemPropertyOriginalDesignManufacturerName: -#else - case kSbSystemPropertyNetworkOperatorName: -#endif - case kSbSystemPropertySpeechApiKey: - return false; - - case kSbSystemPropertyFriendlyName: - return CopyStringAndTestIfSuccess(out_value, value_length, kFriendlyName); - - case kSbSystemPropertyPlatformName: - return CopyStringAndTestIfSuccess(out_value, value_length, kPlatformName); - -#if SB_API_VERSION < 10 - case kSbSystemPropertyPlatformUuid: - SB_NOTIMPLEMENTED(); - return CopyStringAndTestIfSuccess(out_value, value_length, "N/A"); -#endif // SB_API_VERSION < 10 - - default: - SB_DLOG(WARNING) << __FUNCTION__ - << ": Unrecognized property: " << property_id; - break; - } - - return false; -}
diff --git a/src/starboard/linux/x64directfb/thread_types_public.h b/src/starboard/linux/x64directfb/thread_types_public.h deleted file mode 100644 index c486537..0000000 --- a/src/starboard/linux/x64directfb/thread_types_public.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2016 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/linux/shared/thread_types_public.h"
diff --git a/src/starboard/linux/x64directfb/xephyr_run.sh b/src/starboard/linux/x64directfb/xephyr_run.sh deleted file mode 100755 index 5eef2a5..0000000 --- a/src/starboard/linux/x64directfb/xephyr_run.sh +++ /dev/null
@@ -1,135 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2016 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script can be used as a convenience to launch an app under a new -# X server. Xephyr requires a base X server, so will be launched if there is a -# DISPLAY environment variable set. Xvfb does not, so it will be launched if -# there is no DISPLAY variable set, which is likely to come from a remote shell -# or background process. It will first launch the X server, and then launch the -# executable given on the command line such that it targets the newly-launched -# X server. It shuts down the X server after the main executable finishes. - -# Standard stuff to get the real script name. -script_file="$(readlink -f "${BASH_SOURCE[0]}")" -script_name="$(basename "${script_file}")" - -if [[ -n "$DISPLAY" ]]; then - # The binary to run to start the X Server. - xserver_bin=Xephyr - # The command-line args to set the screen dimensions. - declare -a xserver_screen=(-screen 1920x1080) - # The package to install for this X Server. - xserver_package=xserver-xephyr -else - xserver_bin=Xvfb - declare -a xserver_screen=(-screen 0 1920x1080x24) - xserver_package=xvfb -fi - -# Use display 42 as it is unlikely to be used by another process on this host. -# TODO: Scan displays for a free one. -xserver_display=":42" - -function log() { - echo "${script_name}: $@" -} - -function deleteTempTrap() { - # If something interrupted the script, it might have printed a partial line. - echo - deleteDirectory "${temp_dir}" -} - -function killServerTrap() { - echo - # Kill the Xephyr process. - kill "${xserver_pid}" &> /dev/null - # Waits for the kill to finish. - wait - log "${xserver_bin} (pid ${xserver_pid}) terminated." - deleteDirectory "${temp_dir}" -} - -function deleteDirectory() { - if [[ -z "$1" ]]; then - log "deleteDirectory with no argument" - exit 1 - fi - - # Only delete target if it is an existing directory. - if [[ -d "$1" ]]; then - rm -rf "$1" - fi -} - -function main() { - if [[ "$#" = "0" ]]; then - echo - echo "${script_name}: Launches a given executable file under a ${xserver_bin} X server." - echo - echo "Usage:" - echo " ${script_name} PATH_TO_EXECUTABLE_FILE [ARGS...] " - echo - exit 1 - fi - - if ! hash "${xserver_bin}" 2>/dev/null ; then - log "${xserver_bin} is not installed. Please run:" - log " sudo apt-get install ${xserver_package}" - exit 1 - fi - - # Create an auth file that will allow the current user to access the display. - temp_dir="$(mktemp -dt "${script_name}.XXXXXXXXXX")" - - # Delete the temporary directory on exit. - trap deleteTempTrap EXIT - - # In this case, we don't want to try to tunnel authority through to remote - # connections, we want to use this X server with the client. So we create - # our own auth and forcibly pass it through both sides of the client and - # server. Apologies for the X11 magic here. - xserver_auth="${temp_dir}/XAuthority" - touch "${xserver_auth}" - token="$(dd if=/dev/urandom count=1 2> /dev/null | md5sum | cut -f1 -d' ')" - xauth -qf "${xserver_auth}" add "${xserver_display}" . "${token}" - - xserver_log="${temp_dir}/${xserver_bin}.txt" - # Launch an X Server in the background at a new display. - "${xserver_bin}" "${xserver_display}" \ - -auth "${xserver_auth}" \ - "${xserver_screen[@]}" \ - &> "${xserver_log}" & - xserver_pid=$! - log "${xserver_bin} (pid ${xserver_pid}) running on ${xserver_display}." - - # Setup a trap to clean up Xephyr upon termination of this script - trap killServerTrap EXIT - - # Give Xephyr some time to setup. - sleep 0.5 - - # Launch the executable passed as a parameter on the new display. - DISPLAY="${xserver_display}" XAUTHORITY="${xserver_auth}" "$@" - result=$? - if [[ "${result}" != "0" ]]; then - log "$1 result: ${result}" - log "--- ${xserver_bin} log ---------------------------------------" - cat "${xserver_log}" - fi - return ${result} -} - -main "$@"
diff --git a/src/starboard/linux/x64x11/blittergles/configuration_public.h b/src/starboard/linux/x64x11/blittergles/configuration_public.h index 74c7872..4207604 100644 --- a/src/starboard/linux/x64x11/blittergles/configuration_public.h +++ b/src/starboard/linux/x64x11/blittergles/configuration_public.h
@@ -22,12 +22,8 @@ // API afterwards. #include "starboard/linux/x64x11/configuration_public.h" -// This configuration supports the blitter API (implemented via GLES). -#undef SB_HAS_BLITTER -#define SB_HAS_BLITTER 1 - -// Linux implementation of Blitter API does not support NV12 textures. -#undef SB_HAS_NV12_TEXTURE_SUPPORT -#define SB_HAS_NV12_TEXTURE_SUPPORT 0 +// Include the Blitter - GLES configuration that's common between all Blitter - +// GLES configurations. +#include "starboard/linux/x64x11/blittergles/shared/configuration_public.h" #endif // STARBOARD_LINUX_X64X11_BLITTERGLES_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/gyp_configuration.gypi b/src/starboard/linux/x64x11/blittergles/gyp_configuration.gypi index 68020b8..b582da2 100644 --- a/src/starboard/linux/x64x11/blittergles/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/blittergles/gyp_configuration.gypi
@@ -16,23 +16,6 @@ # though it may have been modified since its creation. { - 'variables': { - # Set 'gl_type' to 'none' because we want Cobalt to think GLES is not - # supported on this build, even though we do in fact use GL within this - # Starboard implementation of the Blitter API. - 'gl_type': 'none', - - 'cobalt_platform_dependencies!': [ - # Since we pretend gl_type is none, exclude this dependency and below, - # explicitly include the one we need. - '<(DEPTH)/starboard/egl_and_gles/egl_and_gles.gyp:egl_and_gles', - ], - - 'cobalt_platform_dependencies': [ - '<(DEPTH)/starboard/egl_and_gles/egl_and_gles_angle.gyp:egl_and_gles_implementation', - ], - }, - 'target_defaults': { 'default_configuration': 'linux-x64x11-blittergles_debug', 'configurations': { @@ -52,8 +35,7 @@ }, 'includes': [ - '../../shared/compiler_flags.gypi', - '../../shared/gyp_configuration.gypi', - '../libraries.gypi', + '<(DEPTH)/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/sabi/sabi.gypi', ], }
diff --git a/src/starboard/linux/x64x11/blittergles/gyp_configuration.py b/src/starboard/linux/x64x11/blittergles/gyp_configuration.py index 3d021a5..87d96c7 100644 --- a/src/starboard/linux/x64x11/blittergles/gyp_configuration.py +++ b/src/starboard/linux/x64x11/blittergles/gyp_configuration.py
@@ -21,4 +21,5 @@ def CreatePlatformConfig(): return parent_configuration.LinuxX64X11Configuration( - 'linux-x64x11-blittergles') + 'linux-x64x11-blittergles', + sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h b/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h index 53a5d3f..5b3ac1e 100644 --- a/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h +++ b/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h
@@ -18,6 +18,77 @@ #ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_10_CONFIGURATION_PUBLIC_H_ #define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_10_CONFIGURATION_PUBLIC_H_ -#include "starboard/linux/x64x11/blittergles/configuration_public.h" +#undef SB_API_VERSION +#define SB_API_VERSION 10 + +// --- Architecture Configuration -------------------------------------------- + +// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be +// automatically set based on this. +#define SB_IS_BIG_ENDIAN 0 + +// Whether the current platform is an ARM architecture. +#define SB_IS_ARCH_ARM 0 + +// Whether the current platform is a MIPS architecture. +#define SB_IS_ARCH_MIPS 0 + +// Whether the current platform is a PPC architecture. +#define SB_IS_ARCH_PPC 0 + +// Whether the current platform is an x86 architecture. +#define SB_IS_ARCH_X86 1 + +// Whether the current platform is a 32-bit architecture. +#define SB_IS_32_BIT 0 + +// Whether the current platform is a 64-bit architecture. +#define SB_IS_64_BIT 1 + +// Whether the current platform's pointers are 32-bit. +// Whether the current platform's longs are 32-bit. +#define SB_HAS_32_BIT_POINTERS 0 +#define SB_HAS_32_BIT_LONG 0 + +// Whether the current platform's pointers are 64-bit. +// Whether the current platform's longs are 64-bit. +#define SB_HAS_64_BIT_POINTERS 1 +#define SB_HAS_64_BIT_LONG 1 + +// Configuration parameters that allow the application to make some general +// compile-time decisions with respect to the the number of cores likely to be +// available on this platform. For a definitive measure, the application should +// still call SbSystemGetNumberOfProcessors at runtime. + +// Whether the current platform's thread scheduler will automatically balance +// threads between cores, as opposed to systems where threads will only ever run +// on the specifically pinned core. +#define SB_HAS_CROSS_CORE_SCHEDULER 1 + +// --- Graphics Configuration ------------------------------------------------ + +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 1 + +// --- Shared Configuration and Overrides ------------------------------------ + +// Include the Linux configuration that's common between all Desktop Linuxes. +#include "starboard/linux/shared/configuration_public.h" + +// Include the Blitter - GLES configuration that's common between all Blitter - +// GLES configurations. +#include "starboard/linux/x64x11/blittergles/shared/configuration_public.h" + +// Starboard API versions 11 and earlier must define this variable, and have +// microphone supported. +#define SB_HAS_MICROPHONE 1 + +// Whether the current platform has speech synthesis. +#undef SB_HAS_SPEECH_SYNTHESIS +#define SB_HAS_SPEECH_SYNTHESIS 0 + +// Whether the current platform implements the on screen keyboard interface. +#define SB_HAS_ON_SCREEN_KEYBOARD 0 #endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_10_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/10/gyp_configuration.gypi b/src/starboard/linux/x64x11/blittergles/sbversion/10/gyp_configuration.gypi index d9855d7..d86b34b 100644 --- a/src/starboard/linux/x64x11/blittergles/sbversion/10/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/blittergles/sbversion/10/gyp_configuration.gypi
@@ -35,6 +35,6 @@ }, 'includes': [ - '<(DEPTH)/starboard/linux/x64x11/blittergles/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi', ], }
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/10/gyp_configuration.py b/src/starboard/linux/x64x11/blittergles/sbversion/10/gyp_configuration.py index 046bf56..1a55271 100644 --- a/src/starboard/linux/x64x11/blittergles/sbversion/10/gyp_configuration.py +++ b/src/starboard/linux/x64x11/blittergles/sbversion/10/gyp_configuration.py
@@ -16,7 +16,6 @@ # though it may have been modified since its creation. """Starboard Linux X64X11 Blittergles Sbversion 10 platform configuration.""" - from starboard.linux.x64x11 import gyp_configuration as parent_configuration
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/11/configuration_public.h b/src/starboard/linux/x64x11/blittergles/sbversion/11/configuration_public.h index 55cf0ba..6aa1686 100644 --- a/src/starboard/linux/x64x11/blittergles/sbversion/11/configuration_public.h +++ b/src/starboard/linux/x64x11/blittergles/sbversion/11/configuration_public.h
@@ -18,6 +18,77 @@ #ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_11_CONFIGURATION_PUBLIC_H_ #define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_11_CONFIGURATION_PUBLIC_H_ -#include "starboard/linux/x64x11/blittergles/configuration_public.h" +#undef SB_API_VERSION +#define SB_API_VERSION 11 + +// --- Architecture Configuration -------------------------------------------- + +// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be +// automatically set based on this. +#define SB_IS_BIG_ENDIAN 0 + +// Whether the current platform is an ARM architecture. +#define SB_IS_ARCH_ARM 0 + +// Whether the current platform is a MIPS architecture. +#define SB_IS_ARCH_MIPS 0 + +// Whether the current platform is a PPC architecture. +#define SB_IS_ARCH_PPC 0 + +// Whether the current platform is an x86 architecture. +#define SB_IS_ARCH_X86 1 + +// Whether the current platform is a 32-bit architecture. +#define SB_IS_32_BIT 0 + +// Whether the current platform is a 64-bit architecture. +#define SB_IS_64_BIT 1 + +// Whether the current platform's pointers are 32-bit. +// Whether the current platform's longs are 32-bit. +#define SB_HAS_32_BIT_POINTERS 0 +#define SB_HAS_32_BIT_LONG 0 + +// Whether the current platform's pointers are 64-bit. +// Whether the current platform's longs are 64-bit. +#define SB_HAS_64_BIT_POINTERS 1 +#define SB_HAS_64_BIT_LONG 1 + +// Configuration parameters that allow the application to make some general +// compile-time decisions with respect to the the number of cores likely to be +// available on this platform. For a definitive measure, the application should +// still call SbSystemGetNumberOfProcessors at runtime. + +// Whether the current platform's thread scheduler will automatically balance +// threads between cores, as opposed to systems where threads will only ever run +// on the specifically pinned core. +#define SB_HAS_CROSS_CORE_SCHEDULER 1 + +// --- Graphics Configuration ------------------------------------------------ + +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 1 + +// --- Shared Configuration and Overrides ------------------------------------ + +// Include the Linux configuration that's common between all Desktop Linuxes. +#include "starboard/linux/shared/configuration_public.h" + +// Include the Blitter - GLES configuration that's common between all Blitter - +// GLES configurations. +#include "starboard/linux/x64x11/blittergles/shared/configuration_public.h" + +// Starboard API versions 11 and earlier must define this variable, and have +// microphone supported. +#define SB_HAS_MICROPHONE 1 + +// Whether the current platform has speech synthesis. +#undef SB_HAS_SPEECH_SYNTHESIS +#define SB_HAS_SPEECH_SYNTHESIS 0 + +// Whether the current platform implements the on screen keyboard interface. +#define SB_HAS_ON_SCREEN_KEYBOARD 0 #endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/11/gyp_configuration.gypi b/src/starboard/linux/x64x11/blittergles/sbversion/11/gyp_configuration.gypi index 573d659..a68e872 100644 --- a/src/starboard/linux/x64x11/blittergles/sbversion/11/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/blittergles/sbversion/11/gyp_configuration.gypi
@@ -35,6 +35,6 @@ }, 'includes': [ - '<(DEPTH)/starboard/linux/x64x11/blittergles/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi', ], }
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h b/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h index e73676b..beb7a18 100644 --- a/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h +++ b/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h
@@ -18,6 +18,74 @@ #ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_CONFIGURATION_PUBLIC_H_ #define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_CONFIGURATION_PUBLIC_H_ -#include "starboard/linux/x64x11/blittergles/configuration_public.h" +#undef SB_API_VERSION +#define SB_API_VERSION 6 + +// --- Architecture Configuration -------------------------------------------- + +// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be +// automatically set based on this. +#define SB_IS_BIG_ENDIAN 0 + +// Whether the current platform is an ARM architecture. +#define SB_IS_ARCH_ARM 0 + +// Whether the current platform is a MIPS architecture. +#define SB_IS_ARCH_MIPS 0 + +// Whether the current platform is a PPC architecture. +#define SB_IS_ARCH_PPC 0 + +// Whether the current platform is an x86 architecture. +#define SB_IS_ARCH_X86 1 + +// Whether the current platform is a 32-bit architecture. +#define SB_IS_32_BIT 0 + +// Whether the current platform is a 64-bit architecture. +#define SB_IS_64_BIT 1 + +// Whether the current platform's pointers are 32-bit. +// Whether the current platform's longs are 32-bit. +#define SB_HAS_32_BIT_POINTERS 0 +#define SB_HAS_32_BIT_LONG 0 + +// Whether the current platform's pointers are 64-bit. +// Whether the current platform's longs are 64-bit. +#define SB_HAS_64_BIT_POINTERS 1 +#define SB_HAS_64_BIT_LONG 1 + +// Configuration parameters that allow the application to make some general +// compile-time decisions with respect to the the number of cores likely to be +// available on this platform. For a definitive measure, the application should +// still call SbSystemGetNumberOfProcessors at runtime. + +// Whether the current platform's thread scheduler will automatically balance +// threads between cores, as opposed to systems where threads will only ever run +// on the specifically pinned core. +#define SB_HAS_CROSS_CORE_SCHEDULER 1 + +// --- Graphics Configuration ------------------------------------------------ + +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 1 + +// --- Shared Configuration and Overrides ------------------------------------ + +// Include the Linux configuration that's common between all Desktop Linuxes. +#include "starboard/linux/shared/configuration_public.h" + +// Include the Blitter - GLES configuration that's common between all Blitter - +// GLES configurations. +#include "starboard/linux/x64x11/blittergles/shared/configuration_public.h" + +// Starboard API versions 11 and earlier must define this variable, and have +// microphone supported. +#define SB_HAS_MICROPHONE 1 + +// Whether the current platform has speech synthesis. +#undef SB_HAS_SPEECH_SYNTHESIS +#define SB_HAS_SPEECH_SYNTHESIS 0 #endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi b/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi index 44aba2b..3b6dac2 100644 --- a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi
@@ -35,6 +35,6 @@ }, 'includes': [ - '<(DEPTH)/starboard/linux/x64x11/blittergles/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi', ], }
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py b/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py index 6930874..228c1ba 100644 --- a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py +++ b/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py
@@ -20,7 +20,7 @@ class LinuxX64X11BlitterglesSbversion6Configuration( - parent_configuration.LinuxX64X11Configuration('linux-x64x11-blittergles')): + parent_configuration.LinuxX64X11Configuration): def GetVariables(self, config_name): variables = super(LinuxX64X11BlitterglesSbversion6Configuration, @@ -35,5 +35,5 @@ def CreatePlatformConfig(): - return parent_configuration.LinuxX64X11Configuration( + return LinuxX64X11BlitterglesSbversion6Configuration( 'linux-x64x11-blittergles-sbversion-6')
diff --git a/src/starboard/linux/x64x11/blittergles/shared/configuration_public.h b/src/starboard/linux/x64x11/blittergles/shared/configuration_public.h new file mode 100644 index 0000000..7a312fd --- /dev/null +++ b/src/starboard/linux/x64x11/blittergles/shared/configuration_public.h
@@ -0,0 +1,29 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file was initially generated by starboard/tools/create_derived_build.py, +// though it may have been modified since its creation. + +#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SHARED_CONFIGURATION_PUBLIC_H_ +#define STARBOARD_LINUX_X64X11_BLITTERGLES_SHARED_CONFIGURATION_PUBLIC_H_ + +// This configuration supports the blitter API (implemented via GLES). +#undef SB_HAS_BLITTER +#define SB_HAS_BLITTER 1 + +// Linux implementation of Blitter API does not support NV12 textures. +#undef SB_HAS_NV12_TEXTURE_SUPPORT +#define SB_HAS_NV12_TEXTURE_SUPPORT 0 + +#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SHARED_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi b/src/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi new file mode 100644 index 0000000..2e844a1 --- /dev/null +++ b/src/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi
@@ -0,0 +1,42 @@ +# Copyright 2019 The Cobalt Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file was initially generated by starboard/tools/create_derived_build.py, +# though it may have been modified since its creation. + +{ + 'variables': { + # Set 'gl_type' to 'none' because we want Cobalt to think GLES is not + # supported on this build, even though we do in fact use GL within this + # Starboard implementation of the Blitter API. + 'gl_type': 'none', + + 'cobalt_platform_dependencies!': [ + # Since we pretend gl_type is none, exclude this dependency and below, + # explicitly include the one we need. + '<(DEPTH)/starboard/egl_and_gles/egl_and_gles.gyp:egl_and_gles', + '<(DEPTH)/starboard/stub/blitter_stub_sources.gypi:blitter_stub_sources', + ], + + 'cobalt_platform_dependencies': [ + '<(DEPTH)/starboard/egl_and_gles/egl_and_gles_angle.gyp:egl_and_gles_implementation', + ], + }, + + 'includes': [ + '<(DEPTH)/starboard/linux/shared/compiler_flags.gypi', + '<(DEPTH)/starboard/linux/shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/shared/libraries.gypi', + ], +}
diff --git a/src/starboard/linux/x64x11/blittergles/starboard_platform.gyp b/src/starboard/linux/x64x11/blittergles/starboard_platform.gyp index 9ce7256..644ab06 100644 --- a/src/starboard/linux/x64x11/blittergles/starboard_platform.gyp +++ b/src/starboard/linux/x64x11/blittergles/starboard_platform.gyp
@@ -65,6 +65,7 @@ '<(DEPTH)/starboard/shared/blittergles/blitter_get_surface_info.cc', '<(DEPTH)/starboard/shared/blittergles/blitter_internal.cc', '<(DEPTH)/starboard/shared/blittergles/blitter_internal.h', + '<(DEPTH)/starboard/shared/blittergles/blitter_is_blitter_supported.cc', '<(DEPTH)/starboard/shared/blittergles/blitter_is_pixel_format_supported_by_download_surface_pixels.cc', '<(DEPTH)/starboard/shared/blittergles/blitter_is_pixel_format_supported_by_pixel_data.cc', '<(DEPTH)/starboard/shared/blittergles/blitter_is_surface_format_supported_by_render_target_surface.cc', @@ -81,6 +82,11 @@ '<(DEPTH)/starboard/shared/blittergles/shader_program.h', '<(DEPTH)/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc', '<(DEPTH)/starboard/shared/starboard/blitter_blit_rects_to_rects.cc', + '<(DEPTH)/starboard/shared/stub/system_gles.cc', + ], + 'sources!': [ + '<@(blitter_stub_sources)', + '<(DEPTH)/starboard/shared/gles/system_gles2.cc', ], 'defines': [ # This must be defined when building Starboard, and must not when
diff --git a/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi b/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi index ed8a8d4..0515825 100644 --- a/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi +++ b/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi
@@ -37,9 +37,14 @@ ], 'compiler_flags_gold': [ '-fno-rtti', - '-O2', '-gline-tables-only', ], + 'compiler_flags_gold_size': [ + '-Os', + ], + 'compiler_flags_gold_speed': [ + '-O2', + ], 'conditions': [ ['clang==1', { 'common_clang_flags': [
diff --git a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py index 159d094..1c3847b 100644 --- a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py +++ b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
@@ -24,9 +24,15 @@ class LinuxX64X11Clang36Configuration(shared_configuration.LinuxConfiguration): """Starboard Linux X64 X11 Clang 3.6 platform configuration.""" - def __init__(self, platform, asan_enabled_by_default=False): + def __init__(self, + platform, + asan_enabled_by_default=False, + sabi_json_path=None): super(LinuxX64X11Clang36Configuration, self).__init__( - platform, asan_enabled_by_default, goma_supports_compiler=False) + platform, + asan_enabled_by_default, + goma_supports_compiler=False, + sabi_json_path=sabi_json_path) self.toolchain_top_dir = os.path.join(build.GetToolchainsDir(), 'x86_64-linux-gnu-clang-3.6') @@ -63,7 +69,9 @@ def CreatePlatformConfig(): try: - return LinuxX64X11Clang36Configuration('linux-x64x11-clang-3-6') + return LinuxX64X11Clang36Configuration( + 'linux-x64x11-clang-3-6', + sabi_json_path='starboard/sabi/x64/sysv/sabi.json') except RuntimeError as e: logging.critical(e) return None
diff --git a/src/starboard/linux/x64x11/clang/gyp_configuration.gypi b/src/starboard/linux/x64x11/clang/gyp_configuration.gypi index fd15c93..cfe1a2e 100644 --- a/src/starboard/linux/x64x11/clang/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/clang/gyp_configuration.gypi
@@ -14,7 +14,8 @@ { 'includes': [ - '../libraries.gypi', - '../../shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/shared/libraries.gypi', + '<(DEPTH)/starboard/sabi/sabi.gypi', ], }
diff --git a/src/starboard/linux/x64x11/configuration_public.h b/src/starboard/linux/x64x11/configuration_public.h index 487d19e..38bcc2e 100644 --- a/src/starboard/linux/x64x11/configuration_public.h +++ b/src/starboard/linux/x64x11/configuration_public.h
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// The Starboard configuration for Desktop X86 Linux. Other devices will have +// The Starboard configuration for Desktop x64 Linux. Other devices will have // specific Starboard implementations, even if they ultimately are running some // version of Linux. @@ -22,58 +22,14 @@ #ifndef STARBOARD_LINUX_X64X11_CONFIGURATION_PUBLIC_H_ #define STARBOARD_LINUX_X64X11_CONFIGURATION_PUBLIC_H_ +#if SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION +#error \ + "This platform's sabi.json file is expected to track the experimental " \ +"Starboard API version." +#endif // SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION + // --- Architecture Configuration -------------------------------------------- -// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be -// automatically set based on this. -#define SB_IS_BIG_ENDIAN 0 - -// Whether the current platform is an ARM architecture. -#define SB_IS_ARCH_ARM 0 - -// Whether the current platform is a MIPS architecture. -#define SB_IS_ARCH_MIPS 0 - -// Whether the current platform is a PPC architecture. -#define SB_IS_ARCH_PPC 0 - -// Whether the current platform is an x86 architecture. -#define SB_IS_ARCH_X86 1 - -// Whether the current platform is a 32-bit architecture. -#if defined(__i386__) -#define SB_IS_32_BIT 1 -#else -#define SB_IS_32_BIT 0 -#endif - -// Whether the current platform is a 64-bit architecture. -#if defined(__x86_64__) -#define SB_IS_64_BIT 1 -#else -#define SB_IS_64_BIT 0 -#endif - -// Whether the current platform's pointers are 32-bit. -// Whether the current platform's longs are 32-bit. -#if SB_IS(32_BIT) -#define SB_HAS_32_BIT_POINTERS 1 -#define SB_HAS_32_BIT_LONG 1 -#else -#define SB_HAS_32_BIT_POINTERS 0 -#define SB_HAS_32_BIT_LONG 0 -#endif - -// Whether the current platform's pointers are 64-bit. -// Whether the current platform's longs are 64-bit. -#if SB_IS(64_BIT) -#define SB_HAS_64_BIT_POINTERS 1 -#define SB_HAS_64_BIT_LONG 1 -#else -#define SB_HAS_64_BIT_POINTERS 0 -#define SB_HAS_64_BIT_LONG 0 -#endif - // Configuration parameters that allow the application to make some general // compile-time decisions with respect to the the number of cores likely to be // available on this platform. For a definitive measure, the application should
diff --git a/src/starboard/linux/x64x11/dlmalloc/gyp_configuration.py b/src/starboard/linux/x64x11/dlmalloc/gyp_configuration.py index 0edf71a..ea9e459 100644 --- a/src/starboard/linux/x64x11/dlmalloc/gyp_configuration.py +++ b/src/starboard/linux/x64x11/dlmalloc/gyp_configuration.py
@@ -30,4 +30,6 @@ def CreatePlatformConfig(): - return LinuxX64X11DlmallocConfiguration('linux-x64x11-dlmalloc') + return LinuxX64X11DlmallocConfiguration( + 'linux-x64x11-dlmalloc', + sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x64x11/egl/gyp_configuration.py b/src/starboard/linux/x64x11/egl/gyp_configuration.py index 521ef26..5fad9bc 100644 --- a/src/starboard/linux/x64x11/egl/gyp_configuration.py +++ b/src/starboard/linux/x64x11/egl/gyp_configuration.py
@@ -17,4 +17,5 @@ def CreatePlatformConfig(): - return linux_configuration.LinuxX64X11Configuration('linux-x64x11-egl') + return linux_configuration.LinuxX64X11Configuration( + 'linux-x64x11-egl', sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x64x11/evergreen/atomic_public.h b/src/starboard/linux/x64x11/evergreen/atomic_public.h deleted file mode 100644 index 2b3073c..0000000 --- a/src/starboard/linux/x64x11/evergreen/atomic_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64X11_EVERGREEN_ATOMIC_PUBLIC_H_ -#define STARBOARD_LINUX_X64X11_EVERGREEN_ATOMIC_PUBLIC_H_ - -#include "starboard/linux/x64x11/atomic_public.h" - -#endif // STARBOARD_LINUX_X64X11_EVERGREEN_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/evergreen/configuration_public.h b/src/starboard/linux/x64x11/evergreen/configuration_public.h deleted file mode 100644 index c535f5a..0000000 --- a/src/starboard/linux/x64x11/evergreen/configuration_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64X11_EVERGREEN_CONFIGURATION_PUBLIC_H_ -#define STARBOARD_LINUX_X64X11_EVERGREEN_CONFIGURATION_PUBLIC_H_ - -#include "starboard/linux/x64x11/configuration_public.h" - -#endif // STARBOARD_LINUX_X64X11_EVERGREEN_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/evergreen/gyp_configuration.gypi b/src/starboard/linux/x64x11/evergreen/gyp_configuration.gypi deleted file mode 100644 index 37d4666..0000000 --- a/src/starboard/linux/x64x11/evergreen/gyp_configuration.gypi +++ /dev/null
@@ -1,50 +0,0 @@ -# Copyright 2019 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ -'variables': { - 'sb_target_platform': 'linux-x64x11-evergreen', - 'sb_evergreen': 1, - }, - 'target_defaults': { - 'cflags_c': [ - '-fPIC', - ], - 'cflags_cc': [ - '-fPIC', - ], - 'default_configuration': 'linux-x64x11-evergreen_debug', - 'configurations': { - 'linux-x64x11-evergreen_debug': { - 'inherit_from': ['debug_base'], - }, - 'linux-x64x11-evergreen_devel': { - 'inherit_from': ['devel_base'], - }, - 'linux-x64x11-evergreen_qa': { - 'inherit_from': ['qa_base'], - }, - 'linux-x64x11-evergreen_gold': { - 'inherit_from': ['gold_base'], - }, - }, # end of configurations - }, - - 'includes': [ - '<(DEPTH)/starboard/linux/x64x11/gyp_configuration.gypi', - ], -}
diff --git a/src/starboard/linux/x64x11/evergreen/gyp_configuration.py b/src/starboard/linux/x64x11/evergreen/gyp_configuration.py deleted file mode 100644 index 820830a..0000000 --- a/src/starboard/linux/x64x11/evergreen/gyp_configuration.py +++ /dev/null
@@ -1,23 +0,0 @@ -# Copyright 2019 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - - -from starboard.linux.x64x11 import gyp_configuration as parent_configuration - - -def CreatePlatformConfig(): - return parent_configuration.LinuxX64X11Configuration('linux-x64x11-evergreen')
diff --git a/src/starboard/linux/x64x11/evergreen/starboard_platform.gyp b/src/starboard/linux/x64x11/evergreen/starboard_platform.gyp deleted file mode 100644 index d67c740..0000000 --- a/src/starboard/linux/x64x11/evergreen/starboard_platform.gyp +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2019 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'includes': [ - # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea - # is that we just want this file to *be* the parent gyp file. - '<(DEPTH)/starboard/linux/x64x11/starboard_platform.gyp', - ], -}
diff --git a/src/starboard/linux/x64x11/evergreen/starboard_platform_tests.gyp b/src/starboard/linux/x64x11/evergreen/starboard_platform_tests.gyp deleted file mode 100644 index 533c7b3..0000000 --- a/src/starboard/linux/x64x11/evergreen/starboard_platform_tests.gyp +++ /dev/null
@@ -1,24 +0,0 @@ -# Copyright 2019 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'includes': [ - # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea - # is that we just want this file to *be* the parent gyp file. - '<(DEPTH)/starboard/linux/x64x11/starboard_platform_tests.gyp', - ], -}
diff --git a/src/starboard/linux/x64x11/evergreen/thread_types_public.h b/src/starboard/linux/x64x11/evergreen/thread_types_public.h deleted file mode 100644 index 13ec782..0000000 --- a/src/starboard/linux/x64x11/evergreen/thread_types_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2019 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X64X11_EVERGREEN_THREAD_TYPES_PUBLIC_H_ -#define STARBOARD_LINUX_X64X11_EVERGREEN_THREAD_TYPES_PUBLIC_H_ - -#include "starboard/linux/x64x11/thread_types_public.h" - -#endif // STARBOARD_LINUX_X64X11_EVERGREEN_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/gcc/6.3/compiler_flags.gypi b/src/starboard/linux/x64x11/gcc/6.3/compiler_flags.gypi index cd8b46d..03217f5 100644 --- a/src/starboard/linux/x64x11/gcc/6.3/compiler_flags.gypi +++ b/src/starboard/linux/x64x11/gcc/6.3/compiler_flags.gypi
@@ -44,7 +44,10 @@ 'compiler_flags_cc_gold': [ '-fno-rtti', ], - 'compiler_flags_gold': [ + 'compiler_flags_gold_size': [ + '-Os', + ], + 'compiler_flags_gold_speed': [ '-O2', ], 'common_compiler_flags': [ @@ -95,6 +98,20 @@ ], }], ], + 'defines_debug': [ + # Enable debug mode for the C++ standard library. + # https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/manual/debug_mode_using.html + # https://libcxx.llvm.org/docs/DesignDocs/DebugMode.html + '_GLIBCXX_DEBUG', + '_LIBCPP_DEBUG=1', + ], + 'defines_devel': [ + # Enable debug mode for the C++ standard library. + # https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/manual/debug_mode_using.html + # https://libcxx.llvm.org/docs/DesignDocs/DebugMode.html + '_GLIBCXX_DEBUG', + '_LIBCPP_DEBUG=0', + ], }, 'target_defaults': {
diff --git a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py index 0066119..6d8bd71 100644 --- a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py +++ b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py
@@ -23,9 +23,15 @@ class LinuxX64X11Gcc63Configuration(shared_configuration.LinuxConfiguration): """Starboard Linux platform configuration.""" - def __init__(self, platform, asan_enabled_by_default=False): + def __init__(self, + platform, + asan_enabled_by_default=False, + sabi_json_path=None): super(LinuxX64X11Gcc63Configuration, self).__init__( - platform, asan_enabled_by_default, goma_supports_compiler=False) + platform, + asan_enabled_by_default, + goma_supports_compiler=False, + sabi_json_path=sabi_json_path) self.toolchain_dir = os.path.join(build.GetToolchainsDir(), 'x86_64-linux-gnu-gcc-6.3.0', 'gcc') @@ -60,4 +66,6 @@ def CreatePlatformConfig(): - return LinuxX64X11Gcc63Configuration('linux-x64x11-gcc-6-3') + return LinuxX64X11Gcc63Configuration( + 'linux-x64x11-gcc-6-3', + sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x64x11/gcc/gyp_configuration.gypi b/src/starboard/linux/x64x11/gcc/gyp_configuration.gypi index fd15c93..cfe1a2e 100644 --- a/src/starboard/linux/x64x11/gcc/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/gcc/gyp_configuration.gypi
@@ -14,7 +14,8 @@ { 'includes': [ - '../libraries.gypi', - '../../shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/shared/libraries.gypi', + '<(DEPTH)/starboard/sabi/sabi.gypi', ], }
diff --git a/src/starboard/linux/x64x11/gczeal/gyp_configuration.py b/src/starboard/linux/x64x11/gczeal/gyp_configuration.py index f30055b..fff7400 100644 --- a/src/starboard/linux/x64x11/gczeal/gyp_configuration.py +++ b/src/starboard/linux/x64x11/gczeal/gyp_configuration.py
@@ -17,4 +17,5 @@ def CreatePlatformConfig(): - return linux_configuration.LinuxX64X11Configuration('linux-x64x11-gczeal') + return linux_configuration.LinuxX64X11Configuration( + 'linux-x64x11-gczeal', sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x64x11/gyp_configuration.gypi b/src/starboard/linux/x64x11/gyp_configuration.gypi index 0620089..96e16b7 100644 --- a/src/starboard/linux/x64x11/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/gyp_configuration.gypi
@@ -13,10 +13,6 @@ # limitations under the License. { - 'variables': { - 'enable_map_to_mesh': 1, - }, - 'target_defaults': { 'default_configuration': 'linux-x64x11_debug', 'configurations': { @@ -36,9 +32,7 @@ }, 'includes': [ - 'enable_glx_via_angle.gypi', - 'libraries.gypi', - '../shared/compiler_flags.gypi', - '../shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/x64x11/shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/sabi/sabi.gypi', ], }
diff --git a/src/starboard/linux/x64x11/gyp_configuration.py b/src/starboard/linux/x64x11/gyp_configuration.py index 4da8f37..6b08b17 100644 --- a/src/starboard/linux/x64x11/gyp_configuration.py +++ b/src/starboard/linux/x64x11/gyp_configuration.py
@@ -31,9 +31,13 @@ def __init__(self, platform_name='linux-x64x11', asan_enabled_by_default=True, - goma_supports_compiler=True): + goma_supports_compiler=True, + sabi_json_path=None): super(LinuxX64X11Configuration, self).__init__( - platform_name, asan_enabled_by_default, goma_supports_compiler) + platform_name, + asan_enabled_by_default, + goma_supports_compiler, + sabi_json_path=sabi_json_path) def GetTargetToolchain(self): return self.GetHostToolchain() @@ -77,4 +81,5 @@ def CreatePlatformConfig(): - return LinuxX64X11Configuration() + return LinuxX64X11Configuration( + sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x64x11/main.cc b/src/starboard/linux/x64x11/main.cc index 954077b..01fa733 100644 --- a/src/starboard/linux/x64x11/main.cc +++ b/src/starboard/linux/x64x11/main.cc
@@ -15,6 +15,7 @@ #include <time.h> #include "starboard/configuration.h" +#include "starboard/linux/shared/command_line_defaults.h" #include "starboard/shared/signal/crash_signals.h" #include "starboard/shared/signal/suspend_signals.h" #include "starboard/shared/starboard/link_receiver.h" @@ -28,7 +29,8 @@ int result = 0; { starboard::shared::starboard::LinkReceiver receiver(&application); - result = application.Run(argc, argv); + result = application.Run( + starboard::linux_platform::shared::GetCommandLine(argc, argv)); } starboard::shared::signal::UninstallSuspendSignalHandlers(); starboard::shared::signal::UninstallCrashSignalHandlers();
diff --git a/src/starboard/linux/x64x11/mock/atomic_public.h b/src/starboard/linux/x64x11/mock/atomic_public.h deleted file mode 100644 index bd69833..0000000 --- a/src/starboard/linux/x64x11/mock/atomic_public.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2017 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_LINUX_X64X11_MOCK_ATOMIC_PUBLIC_H_ -#define STARBOARD_LINUX_X64X11_MOCK_ATOMIC_PUBLIC_H_ - -#include "starboard/linux/shared/atomic_public.h" - -#endif // STARBOARD_LINUX_X64X11_MOCK_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/mock/configuration_public.h b/src/starboard/linux/x64x11/mock/configuration_public.h deleted file mode 100644 index f3ecd25..0000000 --- a/src/starboard/linux/x64x11/mock/configuration_public.h +++ /dev/null
@@ -1,441 +0,0 @@ -// Copyright 2017 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// The Starboard configuration for a mock implementation designed to be -// built on Desktop Linux. - -#ifndef STARBOARD_LINUX_X64X11_MOCK_CONFIGURATION_PUBLIC_H_ -#define STARBOARD_LINUX_X64X11_MOCK_CONFIGURATION_PUBLIC_H_ - -// The API version implemented by this platform. This will generally be set to -// the current value of SB_MAXIMUM_API_VERSION at the time of implementation. -#define SB_API_VERSION SB_EXPERIMENTAL_API_VERSION - -// --- Architecture Configuration -------------------------------------------- - -// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be -// automatically set based on this. -#define SB_IS_BIG_ENDIAN 0 - -// Whether the current platform is an ARM architecture. -#define SB_IS_ARCH_ARM 0 - -// Whether the current platform is a MIPS architecture. -#define SB_IS_ARCH_MIPS 0 - -// Whether the current platform is a PPC architecture. -#define SB_IS_ARCH_PPC 0 - -// Whether the current platform is an x86 architecture. -#define SB_IS_ARCH_X86 1 - -// Assume a 64-bit architecture. -#define SB_IS_32_BIT 0 -#define SB_IS_64_BIT 1 - -// Whether the current platform's pointers are 32-bit. -// Whether the current platform's longs are 32-bit. -#if SB_IS(32_BIT) -#define SB_HAS_32_BIT_POINTERS 1 -#define SB_HAS_32_BIT_LONG 1 -#else -#define SB_HAS_32_BIT_POINTERS 0 -#define SB_HAS_32_BIT_LONG 0 -#endif - -// Whether the current platform's pointers are 64-bit. -// Whether the current platform's longs are 64-bit. -#if SB_IS(64_BIT) -#define SB_HAS_64_BIT_POINTERS 1 -#define SB_HAS_64_BIT_LONG 1 -#else -#define SB_HAS_64_BIT_POINTERS 0 -#define SB_HAS_64_BIT_LONG 0 -#endif - -// Configuration parameters that allow the application to make some general -// compile-time decisions with respect to the the number of cores likely to be -// available on this platform. For a definitive measure, the application should -// still call SbSystemGetNumberOfProcessors at runtime. - -// Whether the current platform's thread scheduler will automatically balance -// threads between cores, as opposed to systems where threads will only ever run -// on the specifically pinned core. -#define SB_HAS_CROSS_CORE_SCHEDULER 1 - -// Some platforms will not align variables on the stack with an alignment -// greater than 16 bytes. Platforms where this is the case should define the -// following quirk. -#undef SB_HAS_QUIRK_DOES_NOT_STACK_ALIGN_OVER_16_BYTES - -// --- System Header Configuration ------------------------------------------- - -// Any system headers listed here that are not provided by the platform will be -// emulated in starboard/types.h. - -// Whether the current platform provides the standard header stdarg.h. -#define SB_HAS_STDARG_H 1 - -// Whether the current platform provides the standard header stdbool.h. -#define SB_HAS_STDBOOL_H 1 - -// Whether the current platform provides the standard header stddef.h. -#define SB_HAS_STDDEF_H 1 - -// Whether the current platform provides the standard header stdint.h. -#define SB_HAS_STDINT_H 1 - -// Whether the current platform provides the standard header inttypes.h. -#define SB_HAS_INTTYPES_H 1 - -// Whether the current platform provides the standard header limits.h. -#define SB_HAS_LIMITS_H 1 - -// Whether the current platform provides the standard header float.h. -#define SB_HAS_FLOAT_H 1 - -// Whether the current platform provides ssize_t. -#define SB_HAS_SSIZE_T 1 - -// Type detection for wchar_t. -#if defined(__WCHAR_MAX__) && \ - (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) -#define SB_IS_WCHAR_T_UTF32 1 -#elif defined(__WCHAR_MAX__) && \ - (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff) -#define SB_IS_WCHAR_T_UTF16 1 -#endif - -// Chrome only defines these two if ARMEL or MIPSEL are defined. -#if defined(__ARMEL__) -// Chrome has an exclusion for iOS here, we should too when we support iOS. -#define SB_IS_WCHAR_T_UNSIGNED 1 -#elif defined(__MIPSEL__) -#define SB_IS_WCHAR_T_SIGNED 1 -#endif - -// --- Compiler Configuration ------------------------------------------------ - -// The platform's annotation for forcing a C function to be inlined. -#define SB_C_FORCE_INLINE __inline__ __attribute__((always_inline)) - -// The platform's annotation for marking a C function as suggested to be -// inlined. -#define SB_C_INLINE inline - -// The platform's annotation for marking a C function as forcibly not -// inlined. -#define SB_C_NOINLINE __attribute__((noinline)) - -// The platform's annotation for marking a symbol as exported outside of the -// current shared library. -#define SB_EXPORT_PLATFORM __attribute__((visibility("default"))) - -// The platform's annotation for marking a symbol as imported from outside of -// the current linking unit. -#define SB_IMPORT_PLATFORM - -// On some platforms the __GNUC__ is defined even though parts of the -// functionality are missing. Setting this to non-zero allows disabling missing -// functionality encountered. -#undef SB_HAS_QUIRK_COMPILER_SAYS_GNUC_BUT_ISNT - -// On some compilers, the frontend has a quirk such that #ifdef cannot -// correctly detect __has_feature is defined, and an example error you get is: -#undef SB_HAS_QUIRK_HASFEATURE_NOT_DEFINED_BUT_IT_IS - -// --- Extensions Configuration ---------------------------------------------- - -// Do not use <unordered_map> and <unordered_set> for the hash table types. -#define SB_HAS_STD_UNORDERED_HASH 0 - -// GCC/Clang doesn't define a long long hash function, except for Android and -// Game consoles. -#define SB_HAS_LONG_LONG_HASH 0 - -// GCC/Clang doesn't define a string hash function, except for Game Consoles. -#define SB_HAS_STRING_HASH 0 - -// Desktop Linux needs a using statement for the hash functions. -#define SB_HAS_HASH_USING 0 - -// Set this to 1 if hash functions for custom types can be defined as a -// hash_value() function. Otherwise, they need to be placed inside a -// partially-specified hash struct template with an operator(). -#define SB_HAS_HASH_VALUE 0 - -// Set this to 1 if use of hash_map or hash_set causes a deprecation warning -// (which then breaks the build). -#define SB_HAS_HASH_WARNING 1 - -// The location to include hash_map on this platform. -#define SB_HASH_MAP_INCLUDE <ext/hash_map> - -// C++'s hash_map and hash_set are often found in different namespaces depending -// on the compiler. -#define SB_HASH_NAMESPACE __gnu_cxx - -// The location to include hash_set on this platform. -#define SB_HASH_SET_INCLUDE <ext/hash_set> - -// Define this to how this platform copies varargs blocks. -#define SB_VA_COPY(dest, source) va_copy(dest, source) - -// --- Filesystem Configuration ---------------------------------------------- - -// The current platform's maximum length of the name of a single directory -// entry, not including the absolute path. -#define SB_FILE_MAX_NAME 64 - -// The current platform's maximum length of an absolute path. -#define SB_FILE_MAX_PATH 4096 - -// The current platform's maximum number of files that can be opened at the -// same time by one process. -#define SB_FILE_MAX_OPEN 64 - -// The current platform's file path component separator character. This is the -// character that appears after a directory in a file path. For example, the -// absolute canonical path of the file "/path/to/a/file.txt" uses '/' as a path -// component separator character. -#define SB_FILE_SEP_CHAR '/' - -// The current platform's alternate file path component separator character. -// This is like SB_FILE_SEP_CHAR, except if your platform supports an alternate -// character, then you can place that here. For example, on windows machines, -// the primary separator character is probably '\', but the alternate is '/'. -#define SB_FILE_ALT_SEP_CHAR '/' - -// The current platform's search path component separator character. When -// specifying an ordered list of absolute paths of directories to search for a -// given reason, this is the character that appears between entries. For -// example, the search path of "/etc/search/first:/etc/search/second" uses ':' -// as a search path component separator character. -#define SB_PATH_SEP_CHAR ':' - -// The string form of SB_FILE_SEP_CHAR. -#define SB_FILE_SEP_STRING "/" - -// The string form of SB_FILE_ALT_SEP_CHAR. -#define SB_FILE_ALT_SEP_STRING "/" - -// The string form of SB_PATH_SEP_CHAR. -#define SB_PATH_SEP_STRING ":" - -// On some platforms the file system stores access times at a coarser -// granularity than other times. When this quirk is defined, we assume the -// access time is of 1 day precision. -#undef SB_HAS_QUIRK_FILESYSTEM_COARSE_ACCESS_TIME - -// --- Graphics Configuration ------------------------------------------------ - -// Specifies whether this platform supports a performant accelerated blitter -// API. The basic requirement is a scaled, clipped, alpha-blended blit. -#define SB_HAS_BLITTER 0 - -// Specifies the preferred byte order of color channels in a pixel. Refer to -// starboard/configuration.h for the possible values. EGL/GLES platforms should -// generally prefer a byte order of RGBA, regardless of endianness. -#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_RGBA - -// Indicates whether or not the given platform supports bilinear filtering. -// This can be checked to enable/disable renderer tests that verify that this is -// working properly. -#define SB_HAS_BILINEAR_FILTERING_SUPPORT 1 - -// Indicates whether or not the given platform supports rendering of NV12 -// textures. These textures typically originate from video decoders. -#define SB_HAS_NV12_TEXTURE_SUPPORT 0 - -// Whether the current platform should frequently flip its display buffer. If -// this is not required (i.e. SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is set to -// 0), then optimizations are enabled so the display buffer is not flipped if -// the scene hasn't changed. -#define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER 0 - -#define SB_HAS_VIRTUAL_REALITY 0 - -// --- I/O Configuration ----------------------------------------------------- - -// Whether the current platform has speech recognizer. -#define SB_HAS_SPEECH_RECOGNIZER 1 - -// Whether the current platform has speech synthesis. -#define SB_HAS_SPEECH_SYNTHESIS 1 - -// --- Media Configuration --------------------------------------------------- - -// After a seek is triggerred, the default behavior is to append video frames -// from the last key frame before the seek time and append audio frames from the -// seek time because usually all audio frames are key frames. On platforms that -// cannot decode video frames without displaying them, this will cause the video -// being played without audio for several seconds after seeking. When the -// following macro is defined, the app will append audio frames start from the -// timestamp that is before the timestamp of the video key frame being appended. -#undef SB_HAS_QUIRK_SEEK_TO_KEYFRAME - -// dlmalloc will use the ffs intrinsic if available. Platforms on which this is -// not available should define the following quirk. -#undef SB_HAS_QUIRK_NO_FFS - -// The maximum audio bitrate the platform can decode. The following value -// equals to 5M bytes per seconds which is more than enough for compressed -// audio. -#define SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND (40 * 1024 * 1024) - -// The maximum video bitrate the platform can decode. The following value -// equals to 25M bytes per seconds which is more than enough for compressed -// video. -#define SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND (200 * 1024 * 1024) - -// Specifies whether this platform has webm/vp9 support. This should be set to -// non-zero on platforms with webm/vp9 support. -#define SB_HAS_MEDIA_WEBM_VP9_SUPPORT 0 - -// Specifies whether this platform updates audio frames asynchronously. In such -// case an extra parameter will be added to |SbAudioSinkConsumeFramesFunc| to -// indicate the absolute time that the consumed audio frames are reported. -// Check document for |SbAudioSinkConsumeFramesFunc| in audio_sink.h for more -// details. -#define SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING 0 - -// Specifies the stack size for threads created inside media stack. Set to 0 to -// use the default thread stack size. Set to non-zero to explicitly set the -// stack size for media stack threads. -#define SB_MEDIA_THREAD_STACK_SIZE 0U - -// --- Decoder-only Params --- - -// Specifies how media buffers must be aligned on this platform as some -// decoders may have special requirement on the alignment of buffers being -// decoded. -#define SB_MEDIA_BUFFER_ALIGNMENT 128U - -// Specifies how video frame buffers must be aligned on this platform. -#define SB_MEDIA_VIDEO_FRAME_ALIGNMENT 256U - -// The encoded video frames are compressed in different ways, so their decoding -// time can vary a lot. Occasionally a single frame can take longer time to -// decode than the average time per frame. The player has to cache some frames -// to account for such inconsistency. The number of frames being cached are -// controlled by SB_MEDIA_MAXIMUM_VIDEO_PREROLL_FRAMES and -// SB_MEDIA_MAXIMUM_VIDEO_FRAMES. -// -// Specify the number of video frames to be cached before the playback starts. -// Note that setting this value too large may increase the playback start delay. -#define SB_MEDIA_MAXIMUM_VIDEO_PREROLL_FRAMES 4 - -// Specify the number of video frames to be cached during playback. A large -// value leads to more stable fps but also causes the app to use more memory. -#define SB_MEDIA_MAXIMUM_VIDEO_FRAMES 12 - -// --- Memory Configuration -------------------------------------------------- - -// The memory page size, which controls the size of chunks on memory that -// allocators deal with, and the alignment of those chunks. This doesn't have to -// be the hardware-defined physical page size, but it should be a multiple of -// it. -#define SB_MEMORY_PAGE_SIZE 4096 - -// Whether this platform has and should use an MMAP function to map physical -// memory to the virtual address space. -#define SB_HAS_MMAP 0 - -// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is -// required for platforms that want to JIT. -#define SB_CAN_MAP_EXECUTABLE_MEMORY 0 - -// Whether this platform has and should use an growable heap (e.g. with sbrk()) -// to map physical memory to the virtual address space. -#define SB_HAS_VIRTUAL_REGIONS 0 - -// Specifies the alignment for IO Buffers, in bytes. Some low-level network APIs -// may require buffers to have a specific alignment, and this is the place to -// specify that. -#define SB_NETWORK_IO_BUFFER_ALIGNMENT 16 - -// Determines the alignment that allocations should have on this platform. -#define SB_MALLOC_ALIGNMENT ((size_t)16U) - -// Determines the threshhold of allocation size that should be done with mmap -// (if available), rather than allocated within the core heap. -#define SB_DEFAULT_MMAP_THRESHOLD ((size_t)(256 * 1024U)) - -// Defines the path where memory debugging logs should be written to. -#define SB_MEMORY_LOG_PATH "/tmp/starboard" - -// --- Network Configuration ------------------------------------------------- - -// Specifies whether this platform supports IPV6. -#define SB_HAS_IPV6 1 - -// Specifies whether this platform supports pipe. -#define SB_HAS_PIPE 1 - -// --- Thread Configuration -------------------------------------------------- - -// Whether the current platform supports thread priorities. -#define SB_HAS_THREAD_PRIORITY_SUPPORT 0 - -// Defines the maximum number of simultaneous threads for this platform. Some -// platforms require sharing thread handles with other kinds of system handles, -// like mutexes, so we want to keep this managable. -#define SB_MAX_THREADS 90 - -// The maximum number of thread local storage keys supported by this platform. -#define SB_MAX_THREAD_LOCAL_KEYS 512 - -// The maximum length of the name for a thread, including the NULL-terminator. -#define SB_MAX_THREAD_NAME_LENGTH 16 - -// --- Timing API ------------------------------------------------------------ - -// Whether this platform has an API to retrieve how long the current thread -// has spent in the executing state. -#define SB_HAS_TIME_THREAD_NOW 1 - -// --- Tuneable Parameters --------------------------------------------------- - -// Specifies the network receive buffer size in bytes, set via -// SbSocketSetReceiveBufferSize(). -// -// Setting this to 0 indicates that SbSocketSetReceiveBufferSize() should -// not be called. Use this for OSs (such as Linux) where receive buffer -// auto-tuning is better. -// -// On some platforms, this may affect max TCP window size which may -// dramatically affect throughput in the presence of latency. -// -// If your platform does not have a good TCP auto-tuning mechanism, -// a setting of (128 * 1024) here is recommended. -#define SB_NETWORK_RECEIVE_BUFFER_SIZE (0) - -// --- User Configuration ---------------------------------------------------- - -// The maximum number of users that can be signed in at the same time. -#define SB_USER_MAX_SIGNED_IN 1 - -// --- Platform Specific Audits ---------------------------------------------- - -#if !defined(__GNUC__) -#error "Mock builds need a GCC-like compiler (for the moment)." -#endif - -#if SB_API_VERSION >= 8 -// Whether the current platform implements the on screen keyboard interface. -#define SB_HAS_ON_SCREEN_KEYBOARD 0 - -#endif // SB_API_VERSION >= 8 - -#endif // STARBOARD_LINUX_X64X11_MOCK_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/mock/gyp_configuration.gypi b/src/starboard/linux/x64x11/mock/gyp_configuration.gypi deleted file mode 100644 index 2b233cf..0000000 --- a/src/starboard/linux/x64x11/mock/gyp_configuration.gypi +++ /dev/null
@@ -1,170 +0,0 @@ -# Copyright 2017 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -{ - 'variables': { - # Mock does not use a filter-based player. - 'sb_filter_based_player': 0, - - 'target_arch': 'x64', - 'target_os': 'linux', - - # Use a stub rasterizer and graphical setup. - 'rasterizer_type': 'stub', - - # No GL drivers available. - 'gl_type': 'none', - - 'platform_libraries': [ - '-lpthread', - ], - - # Define platform specific compiler and linker flags. - # Refer to base.gypi for a list of all available variables. - 'compiler_flags_host': [ - '-O2', - ], - 'compiler_flags': [ - # We'll pretend not to be Linux, but Starboard instead. - '-U__linux__', - ], - 'linker_flags': [ - ], - 'compiler_flags_debug': [ - '-frtti', - '-O0', - ], - 'compiler_flags_devel': [ - '-frtti', - '-O2', - ], - 'compiler_flags_qa': [ - '-fno-rtti', - '-O2', - '-gline-tables-only', - ], - 'compiler_flags_gold': [ - '-fno-rtti', - '-O2', - '-gline-tables-only', - ], - 'conditions': [ - ['clang==1', { - 'common_clang_flags': [ - '-Werror', - '-fcolor-diagnostics', - # Default visibility to hidden, to enable dead stripping. - '-fvisibility=hidden', - # Warn for implicit type conversions that may change a value. - '-Wconversion', - '-Wno-c++11-compat', - # This (rightfully) complains about 'override', which we use - # heavily. - '-Wno-c++11-extensions', - # Warns on switches on enums that cover all enum values but - # also contain a default: branch. Chrome is full of that. - '-Wno-covered-switch-default', - # protobuf uses hash_map. - '-Wno-deprecated', - '-fno-exceptions', - # Don't warn about the "struct foo f = {0};" initialization pattern. - '-Wno-missing-field-initializers', - # Do not warn for implicit sign conversions. - '-Wno-sign-conversion', - '-fno-strict-aliasing', # See http://crbug.com/32204 - # TODO(pkasting): In C++11 this is legal, so this should be - # removed when we change to that. (This is also why we don't - # bother fixing all these cases today.) - '-Wno-unnamed-type-template-args', - # Triggered by the COMPILE_ASSERT macro. - '-Wno-unused-local-typedef', - # Do not warn if a function or variable cannot be implicitly - # instantiated. - '-Wno-undefined-var-template', - # Do not warn about unused function params. - '-Wno-unused-parameter', - ], - }], - ['cobalt_fastbuild==0', { - 'compiler_flags_debug': [ - '-g', - ], - 'compiler_flags_devel': [ - '-g', - ], - 'compiler_flags_qa': [ - '-gline-tables-only', - ], - 'compiler_flags_gold': [ - '-gline-tables-only', - ], - }], - ], - }, - - 'target_defaults': { - 'defines': [ - '__STDC_FORMAT_MACROS', # so that we get PRI* - # Enable GNU extensions to get prototypes like ffsl. - #'_GNU_SOURCE=1', - ], - 'cflags_c': [ - # Limit to C99. This allows stub to be a canary build for any - # C11 features that are not supported on some platforms' compilers. - #'-std=c99', - ], - 'cflags_cc': [ - '-std=gnu++11', - ], - 'default_configuration': 'linux-x64x11-mock_debug', - 'configurations': { - 'linux-x64x11-mock_debug': { - 'inherit_from': ['debug_base'], - }, - 'linux-x64x11-mock_devel': { - 'inherit_from': ['devel_base'], - }, - 'linux-x64x11-mock_qa': { - 'inherit_from': ['qa_base'], - }, - 'linux-x64x11-mock_gold': { - 'inherit_from': ['gold_base'], - }, - }, # end of configurations - 'target_conditions': [ - ['sb_pedantic_warnings==1', { - 'cflags': [ - '-Wall', - '-Wextra', - '-Wunreachable-code', - '<@(common_clang_flags)', - ], - },{ - 'cflags': [ - '<@(common_clang_flags)', - # 'this' pointer cannot be NULL...pointer may be assumed - # to always convert to true. - '-Wno-undefined-bool-conversion', - # Skia doesn't use overrides. - '-Wno-inconsistent-missing-override', - # Do not warn for implicit type conversions that may change a value. - '-Wno-conversion', - # shifting a negative signed value is undefined - '-Wno-shift-negative-value', - # Width of bit-field exceeds width of its type- value will be truncated - '-Wno-bitfield-width', - ], - }], - ], - }, # end of target_defaults -}
diff --git a/src/starboard/linux/x64x11/mock/gyp_configuration.py b/src/starboard/linux/x64x11/mock/gyp_configuration.py deleted file mode 100644 index 2abddb0..0000000 --- a/src/starboard/linux/x64x11/mock/gyp_configuration.py +++ /dev/null
@@ -1,60 +0,0 @@ -# Copyright 2017 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Starboard mock platform configuration for gyp_cobalt.""" - -from starboard.build import clang -from starboard.build import platform_configuration -from starboard.tools import build -from starboard.tools.testing import test_filter - - -class LinuxX64X11MockConfiguration( - platform_configuration.PlatformConfiguration): - """Starboard mock platform configuration.""" - - def GetBuildFormat(self): - return 'ninja,qtcreator_ninja' - - def GetVariables(self, configuration): - variables = super(LinuxX64X11MockConfiguration, self).GetVariables( - configuration, use_clang=1) - variables.update({ - 'javascript_engine': 'mozjs-45', - 'cobalt_enable_jit': 0, - }) - return variables - - def GetGeneratorVariables(self, configuration): - del configuration - generator_variables = { - 'qtcreator_session_name_prefix': 'cobalt', - } - return generator_variables - - def GetEnvironmentVariables(self): - if not hasattr(self, 'host_compiler_environment'): - goma_supports_compiler = True - self.host_compiler_environment = build.GetHostCompilerEnvironment( - clang.GetClangSpecification(), goma_supports_compiler) - - env_variables = self.host_compiler_environment - env_variables.update({ - 'CC': self.host_compiler_environment['CC_host'], - 'CXX': self.host_compiler_environment['CXX_host'], - }) - return env_variables - - -def CreatePlatformConfig(): - return LinuxX64X11MockConfiguration('linux-x64x11-mock')
diff --git a/src/starboard/linux/x64x11/mock/main.cc b/src/starboard/linux/x64x11/mock/main.cc deleted file mode 100644 index 2067e95..0000000 --- a/src/starboard/linux/x64x11/mock/main.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2017 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/configuration.h" -#include "starboard/stub/application_stub.h" - -int main(int argc, char** argv) { - starboard::stub::ApplicationStub application; - return application.Run(argc, argv); -}
diff --git a/src/starboard/linux/x64x11/mock/starboard_platform.gyp b/src/starboard/linux/x64x11/mock/starboard_platform.gyp deleted file mode 100644 index 367c7b6..0000000 --- a/src/starboard/linux/x64x11/mock/starboard_platform.gyp +++ /dev/null
@@ -1,96 +0,0 @@ -# Copyright 2017 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -{ - 'includes': [ - '<(DEPTH)/starboard/stub/stub_sources.gypi' - ], - 'targets': [ - { - 'target_name': 'starboard_platform', - 'type': 'static_library', - 'sources': [ - # TODO: Convert all stubs to mocks. - '<@(stub_sources)', - # Minimal Starboard implementation that allows to run unit tests. - '<(DEPTH)/starboard/linux/shared/atomic_public.h', - '<(DEPTH)/starboard/shared/iso/memory_allocate_unchecked.cc', - '<(DEPTH)/starboard/shared/iso/memory_compare.cc', - '<(DEPTH)/starboard/shared/iso/memory_copy.cc', - '<(DEPTH)/starboard/shared/iso/memory_find_byte.cc', - '<(DEPTH)/starboard/shared/iso/memory_free.cc', - '<(DEPTH)/starboard/shared/iso/memory_move.cc', - '<(DEPTH)/starboard/shared/iso/memory_reallocate_unchecked.cc', - '<(DEPTH)/starboard/shared/iso/memory_set.cc', - '<(DEPTH)/starboard/shared/linux/memory_get_stack_bounds.cc', - '<(DEPTH)/starboard/shared/posix/log.cc', - '<(DEPTH)/starboard/shared/posix/log_flush.cc', - '<(DEPTH)/starboard/shared/posix/log_format.cc', - '<(DEPTH)/starboard/shared/posix/log_is_tty.cc', - '<(DEPTH)/starboard/shared/posix/log_raw.cc', - '<(DEPTH)/starboard/shared/posix/memory_allocate_aligned_unchecked.cc', - '<(DEPTH)/starboard/shared/posix/memory_free_aligned.cc', - '<(DEPTH)/starboard/shared/starboard/application.cc', - '<(DEPTH)/starboard/shared/starboard/command_line.cc', - '<(DEPTH)/starboard/shared/starboard/command_line.h', - '<(DEPTH)/starboard/shared/starboard/event_cancel.cc', - '<(DEPTH)/starboard/shared/starboard/event_schedule.cc', - '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc', - '<(DEPTH)/starboard/shared/starboard/log_message.cc', - '<(DEPTH)/starboard/shared/starboard/log_mutex.cc', - '<(DEPTH)/starboard/shared/starboard/log_mutex.h', - '<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc', - '<(DEPTH)/starboard/shared/starboard/log_raw_format.cc', - '<(DEPTH)/starboard/shared/starboard/media/codec_util.cc', - '<(DEPTH)/starboard/shared/starboard/media/codec_util.h', - '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_type.h', - '<(DEPTH)/starboard/shared/starboard/queue_application.cc', - '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc', - '<(DEPTH)/starboard/stub/application_stub.cc', - '<(DEPTH)/starboard/stub/application_stub.h', - 'atomic_public.h', - 'main.cc', - 'thread_types_public.h', - ], - # Exclude unused stub sources. - 'sources!' : [ - '<(DEPTH)/starboard/shared/stub/atomic_public.h', - '<(DEPTH)/starboard/shared/stub/log.cc', - '<(DEPTH)/starboard/shared/stub/log_flush.cc', - '<(DEPTH)/starboard/shared/stub/log_format.cc', - '<(DEPTH)/starboard/shared/stub/log_is_tty.cc', - '<(DEPTH)/starboard/shared/stub/log_raw.cc', - '<(DEPTH)/starboard/shared/stub/log_raw_dump_stack.cc', - '<(DEPTH)/starboard/shared/stub/log_raw_format.cc', - '<(DEPTH)/starboard/shared/stub/memory_allocate_aligned_unchecked.cc', - '<(DEPTH)/starboard/shared/stub/memory_allocate_unchecked.cc', - '<(DEPTH)/starboard/shared/stub/memory_compare.cc', - '<(DEPTH)/starboard/shared/stub/memory_copy.cc', - '<(DEPTH)/starboard/shared/stub/memory_find_byte.cc', - '<(DEPTH)/starboard/shared/stub/memory_free.cc', - '<(DEPTH)/starboard/shared/stub/memory_free_aligned.cc', - '<(DEPTH)/starboard/shared/stub/memory_get_stack_bounds.cc', - '<(DEPTH)/starboard/shared/stub/memory_move.cc', - '<(DEPTH)/starboard/shared/stub/memory_reallocate_unchecked.cc', - '<(DEPTH)/starboard/shared/stub/memory_set.cc', - '<(DEPTH)/starboard/shared/stub/system_request_stop.cc', - ], - 'defines': [ - # This must be defined when building Starboard, and must not when - # building Starboard client code. - 'STARBOARD_IMPLEMENTATION', - ], - }, - ], -}
diff --git a/src/starboard/linux/x64x11/mock/starboard_platform_tests.gyp b/src/starboard/linux/x64x11/mock/starboard_platform_tests.gyp deleted file mode 100644 index 0ea8622..0000000 --- a/src/starboard/linux/x64x11/mock/starboard_platform_tests.gyp +++ /dev/null
@@ -1,18 +0,0 @@ -# Copyright 2018 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. -{ - 'includes': [ - '<(DEPTH)/starboard/linux/shared/starboard_platform_tests.gypi', - ], -}
diff --git a/src/starboard/linux/x64x11/mock/thread_types_public.h b/src/starboard/linux/x64x11/mock/thread_types_public.h deleted file mode 100644 index 3a5b55e..0000000 --- a/src/starboard/linux/x64x11/mock/thread_types_public.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2017 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Includes threading primitive types and initializers. - -#ifndef STARBOARD_LINUX_X64X11_MOCK_THREAD_TYPES_PUBLIC_H_ -#define STARBOARD_LINUX_X64X11_MOCK_THREAD_TYPES_PUBLIC_H_ - -#include "starboard/shared/stub/thread_types_public.h" - -#endif // STARBOARD_LINUX_X64X11_MOCK_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/mozjs/gyp_configuration.py b/src/starboard/linux/x64x11/mozjs/gyp_configuration.py index f574ebd..ac34ad2 100644 --- a/src/starboard/linux/x64x11/mozjs/gyp_configuration.py +++ b/src/starboard/linux/x64x11/mozjs/gyp_configuration.py
@@ -31,4 +31,6 @@ def CreatePlatformConfig(): - return LinuxX64X11MozjsConfiguration('linux-x64x11-mozjs') + return LinuxX64X11MozjsConfiguration( + 'linux-x64x11-mozjs', + sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x64x11/sbversion/10/configuration_public.h b/src/starboard/linux/x64x11/sbversion/10/configuration_public.h index 229dd3d..61d198d 100644 --- a/src/starboard/linux/x64x11/sbversion/10/configuration_public.h +++ b/src/starboard/linux/x64x11/sbversion/10/configuration_public.h
@@ -21,6 +21,70 @@ #undef SB_API_VERSION #define SB_API_VERSION 10 -#include "starboard/linux/x64x11/configuration_public.h" +// --- Architecture Configuration -------------------------------------------- + +// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be +// automatically set based on this. +#define SB_IS_BIG_ENDIAN 0 + +// Whether the current platform is an ARM architecture. +#define SB_IS_ARCH_ARM 0 + +// Whether the current platform is a MIPS architecture. +#define SB_IS_ARCH_MIPS 0 + +// Whether the current platform is a PPC architecture. +#define SB_IS_ARCH_PPC 0 + +// Whether the current platform is an x86 architecture. +#define SB_IS_ARCH_X86 1 + +// Whether the current platform is a 32-bit architecture. +#define SB_IS_32_BIT 0 + +// Whether the current platform is a 64-bit architecture. +#define SB_IS_64_BIT 1 + +// Whether the current platform's pointers are 32-bit. +// Whether the current platform's longs are 32-bit. +#define SB_HAS_32_BIT_POINTERS 0 +#define SB_HAS_32_BIT_LONG 0 + +// Whether the current platform's pointers are 64-bit. +// Whether the current platform's longs are 64-bit. +#define SB_HAS_64_BIT_POINTERS 1 +#define SB_HAS_64_BIT_LONG 1 + +// Configuration parameters that allow the application to make some general +// compile-time decisions with respect to the the number of cores likely to be +// available on this platform. For a definitive measure, the application should +// still call SbSystemGetNumberOfProcessors at runtime. + +// Whether the current platform's thread scheduler will automatically balance +// threads between cores, as opposed to systems where threads will only ever run +// on the specifically pinned core. +#define SB_HAS_CROSS_CORE_SCHEDULER 1 + +// --- Graphics Configuration ------------------------------------------------ + +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 1 + +// --- Shared Configuration and Overrides ------------------------------------ + +// Include the Linux configuration that's common between all Desktop Linuxes. +#include "starboard/linux/shared/configuration_public.h" + +// Starboard API versions 11 and earlier must define this variable, and have +// microphone supported. +#define SB_HAS_MICROPHONE 1 + +// Whether the current platform has speech synthesis. +#undef SB_HAS_SPEECH_SYNTHESIS +#define SB_HAS_SPEECH_SYNTHESIS 0 + +// Whether the current platform implements the on screen keyboard interface. +#define SB_HAS_ON_SCREEN_KEYBOARD 0 #endif // STARBOARD_LINUX_X64X11_SBVERSION_10_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.gypi b/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.gypi index cedca3a..0175804 100644 --- a/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.gypi
@@ -35,6 +35,6 @@ }, 'includes': [ - '<(DEPTH)/starboard/linux/x64x11/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/x64x11/shared/gyp_configuration.gypi', ], }
diff --git a/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.py b/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.py index cf77bb8..5222f62 100644 --- a/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.py +++ b/src/starboard/linux/x64x11/sbversion/10/gyp_configuration.py
@@ -15,9 +15,9 @@ # This file was initially generated by starboard/tools/create_derived_build.py, # though it may have been modified since its creation. - from starboard.linux.x64x11 import gyp_configuration as parent_configuration def CreatePlatformConfig(): - return parent_configuration.LinuxX64X11Configuration('linux-x64x11-sbversion-10') + return parent_configuration.LinuxX64X11Configuration( + 'linux-x64x11-sbversion-10')
diff --git a/src/starboard/linux/x64x11/sbversion/10/starboard_platform.gyp b/src/starboard/linux/x64x11/sbversion/10/starboard_platform.gyp index 1478102..1c0f05b 100644 --- a/src/starboard/linux/x64x11/sbversion/10/starboard_platform.gyp +++ b/src/starboard/linux/x64x11/sbversion/10/starboard_platform.gyp
@@ -22,3 +22,4 @@ '<(DEPTH)/starboard/linux/x64x11/starboard_platform.gyp', ], } +
diff --git a/src/starboard/linux/x64x11/sbversion/11/configuration_public.h b/src/starboard/linux/x64x11/sbversion/11/configuration_public.h index c345470..3513fc5 100644 --- a/src/starboard/linux/x64x11/sbversion/11/configuration_public.h +++ b/src/starboard/linux/x64x11/sbversion/11/configuration_public.h
@@ -21,6 +21,70 @@ #undef SB_API_VERSION #define SB_API_VERSION 11 -#include "starboard/linux/x64x11/configuration_public.h" +// --- Architecture Configuration -------------------------------------------- + +// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be +// automatically set based on this. +#define SB_IS_BIG_ENDIAN 0 + +// Whether the current platform is an ARM architecture. +#define SB_IS_ARCH_ARM 0 + +// Whether the current platform is a MIPS architecture. +#define SB_IS_ARCH_MIPS 0 + +// Whether the current platform is a PPC architecture. +#define SB_IS_ARCH_PPC 0 + +// Whether the current platform is an x86 architecture. +#define SB_IS_ARCH_X86 1 + +// Whether the current platform is a 32-bit architecture. +#define SB_IS_32_BIT 0 + +// Whether the current platform is a 64-bit architecture. +#define SB_IS_64_BIT 1 + +// Whether the current platform's pointers are 32-bit. +// Whether the current platform's longs are 32-bit. +#define SB_HAS_32_BIT_POINTERS 0 +#define SB_HAS_32_BIT_LONG 0 + +// Whether the current platform's pointers are 64-bit. +// Whether the current platform's longs are 64-bit. +#define SB_HAS_64_BIT_POINTERS 1 +#define SB_HAS_64_BIT_LONG 1 + +// Configuration parameters that allow the application to make some general +// compile-time decisions with respect to the the number of cores likely to be +// available on this platform. For a definitive measure, the application should +// still call SbSystemGetNumberOfProcessors at runtime. + +// Whether the current platform's thread scheduler will automatically balance +// threads between cores, as opposed to systems where threads will only ever run +// on the specifically pinned core. +#define SB_HAS_CROSS_CORE_SCHEDULER 1 + +// --- Graphics Configuration ------------------------------------------------ + +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 1 + +// --- Shared Configuration and Overrides ------------------------------------ + +// Include the Linux configuration that's common between all Desktop Linuxes. +#include "starboard/linux/shared/configuration_public.h" + +// Starboard API versions 11 and earlier must define this variable, and have +// microphone supported. +#define SB_HAS_MICROPHONE 1 + +// Whether the current platform has speech synthesis. +#undef SB_HAS_SPEECH_SYNTHESIS +#define SB_HAS_SPEECH_SYNTHESIS 0 + +// Whether the current platform implements the on screen keyboard interface. +#define SB_HAS_ON_SCREEN_KEYBOARD 0 #endif // STARBOARD_LINUX_X64X11_SBVERSION_11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/11/gyp_configuration.gypi b/src/starboard/linux/x64x11/sbversion/11/gyp_configuration.gypi index dbecf92..37ee3f0 100644 --- a/src/starboard/linux/x64x11/sbversion/11/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/sbversion/11/gyp_configuration.gypi
@@ -35,6 +35,6 @@ }, 'includes': [ - '<(DEPTH)/starboard/linux/x64x11/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/x64x11/shared/gyp_configuration.gypi', ], }
diff --git a/src/starboard/linux/x64x11/sbversion/11/gyp_configuration.py b/src/starboard/linux/x64x11/sbversion/11/gyp_configuration.py index ed4f5d5..04f82ee 100644 --- a/src/starboard/linux/x64x11/sbversion/11/gyp_configuration.py +++ b/src/starboard/linux/x64x11/sbversion/11/gyp_configuration.py
@@ -15,9 +15,9 @@ # This file was initially generated by starboard/tools/create_derived_build.py, # though it may have been modified since its creation. - from starboard.linux.x64x11 import gyp_configuration as parent_configuration def CreatePlatformConfig(): - return parent_configuration.LinuxX64X11Configuration('linux-x64x11-sbversion-11') + return parent_configuration.LinuxX64X11Configuration( + 'linux-x64x11-sbversion-11')
diff --git a/src/starboard/linux/x64x11/sbversion/6/configuration_public.h b/src/starboard/linux/x64x11/sbversion/6/configuration_public.h index 2379ef8..ff0ff15 100644 --- a/src/starboard/linux/x64x11/sbversion/6/configuration_public.h +++ b/src/starboard/linux/x64x11/sbversion/6/configuration_public.h
@@ -21,6 +21,67 @@ #undef SB_API_VERSION #define SB_API_VERSION 6 -#include "starboard/linux/x64x11/configuration_public.h" +// --- Architecture Configuration -------------------------------------------- + +// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be +// automatically set based on this. +#define SB_IS_BIG_ENDIAN 0 + +// Whether the current platform is an ARM architecture. +#define SB_IS_ARCH_ARM 0 + +// Whether the current platform is a MIPS architecture. +#define SB_IS_ARCH_MIPS 0 + +// Whether the current platform is a PPC architecture. +#define SB_IS_ARCH_PPC 0 + +// Whether the current platform is an x86 architecture. +#define SB_IS_ARCH_X86 1 + +// Whether the current platform is a 32-bit architecture. +#define SB_IS_32_BIT 0 + +// Whether the current platform is a 64-bit architecture. +#define SB_IS_64_BIT 1 + +// Whether the current platform's pointers are 32-bit. +// Whether the current platform's longs are 32-bit. +#define SB_HAS_32_BIT_POINTERS 0 +#define SB_HAS_32_BIT_LONG 0 + +// Whether the current platform's pointers are 64-bit. +// Whether the current platform's longs are 64-bit. +#define SB_HAS_64_BIT_POINTERS 1 +#define SB_HAS_64_BIT_LONG 1 + +// Configuration parameters that allow the application to make some general +// compile-time decisions with respect to the the number of cores likely to be +// available on this platform. For a definitive measure, the application should +// still call SbSystemGetNumberOfProcessors at runtime. + +// Whether the current platform's thread scheduler will automatically balance +// threads between cores, as opposed to systems where threads will only ever run +// on the specifically pinned core. +#define SB_HAS_CROSS_CORE_SCHEDULER 1 + +// --- Graphics Configuration ------------------------------------------------ + +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 1 + +// --- Shared Configuration and Overrides ------------------------------------ + +// Include the Linux configuration that's common between all Desktop Linuxes. +#include "starboard/linux/shared/configuration_public.h" + +// Starboard API versions 11 and earlier must define this variable, and have +// microphone supported. +#define SB_HAS_MICROPHONE 1 + +// Whether the current platform has speech synthesis. +#undef SB_HAS_SPEECH_SYNTHESIS +#define SB_HAS_SPEECH_SYNTHESIS 0 #endif // STARBOARD_LINUX_X64X11_SBVERSION_6_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.gypi b/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.gypi index 6eda5ee..9a3ed06 100644 --- a/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.gypi +++ b/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.gypi
@@ -35,6 +35,6 @@ }, 'includes': [ - '<(DEPTH)/starboard/linux/x64x11/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/x64x11/shared/gyp_configuration.gypi', ], }
diff --git a/src/starboard/linux/x64x11/shared/gyp_configuration.gypi b/src/starboard/linux/x64x11/shared/gyp_configuration.gypi new file mode 100644 index 0000000..a9fbd7f --- /dev/null +++ b/src/starboard/linux/x64x11/shared/gyp_configuration.gypi
@@ -0,0 +1,26 @@ +# Copyright 2014 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. + +{ + 'variables': { + 'enable_map_to_mesh': 1, + }, + + 'includes': [ + '<(DEPTH)/starboard/linux/shared/compiler_flags.gypi', + '<(DEPTH)/starboard/linux/shared/enable_glx_via_angle.gypi', + '<(DEPTH)/starboard/linux/shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/linux/shared/libraries.gypi', + ], +}
diff --git a/src/starboard/linux/x64x11/skia/configuration_public.h b/src/starboard/linux/x64x11/skia/configuration_public.h index b78bebd..8879563 100644 --- a/src/starboard/linux/x64x11/skia/configuration_public.h +++ b/src/starboard/linux/x64x11/skia/configuration_public.h
@@ -20,7 +20,11 @@ // This is not a released configuration, so it should implement the // experimental API version to validate trunk's viability. -#define SB_API_VERSION SB_EXPERIMENTAL_API_VERSION +#if SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION +#error \ + "This platform's sabi.json file is expected to track the experimental " \ +"Starboard API version." +#endif // SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION // Include the X64X11 Linux configuration. #include "starboard/linux/x64x11/configuration_public.h"
diff --git a/src/starboard/linux/x64x11/skia/gyp_configuration.py b/src/starboard/linux/x64x11/skia/gyp_configuration.py index 557ec65..206dba1 100644 --- a/src/starboard/linux/x64x11/skia/gyp_configuration.py +++ b/src/starboard/linux/x64x11/skia/gyp_configuration.py
@@ -17,4 +17,5 @@ def CreatePlatformConfig(): - return linux_configuration.LinuxX64X11Configuration('linux-x64x11-skia') + return linux_configuration.LinuxX64X11Configuration( + 'linux-x64x11-skia', sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x86x11/atomic_public.h b/src/starboard/linux/x86x11/atomic_public.h deleted file mode 100644 index 1e7c7f5..0000000 --- a/src/starboard/linux/x86x11/atomic_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X86X11_ATOMIC_PUBLIC_H_ -#define STARBOARD_LINUX_X86X11_ATOMIC_PUBLIC_H_ - -#include "starboard/linux/shared/atomic_public.h" - -#endif // STARBOARD_LINUX_X86X11_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x86x11/compiler_flags.gypi b/src/starboard/linux/x86x11/compiler_flags.gypi deleted file mode 100644 index 7a61cea..0000000 --- a/src/starboard/linux/x86x11/compiler_flags.gypi +++ /dev/null
@@ -1,176 +0,0 @@ -# Copyright 2016 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. - -# Platform specific compiler flags for Linux on Starboard. Included from -# gyp_configuration.gypi. -# -{ - 'variables': { - 'compiler_flags_host': [ - '-O2', - ], - 'linker_flags': [ - ], - 'compiler_flags_debug': [ - '-frtti', - '-O0', - ], - 'compiler_flags_devel': [ - '-frtti', - '-O2', - ], - 'compiler_flags_qa': [ - '-fno-rtti', - '-O2', - '-gline-tables-only', - ], - 'compiler_flags_gold': [ - '-fno-rtti', - '-O2', - '-gline-tables-only', - ], - 'conditions': [ - ['clang==1', { - 'linker_flags': [ - '-target', 'i386-unknown-linux-gnu', - ], - 'common_clang_flags': [ - '-target', 'i386-unknown-linux-gnu', - '-Werror', - '-fcolor-diagnostics', - # Default visibility to hidden, to enable dead stripping. - '-fvisibility=hidden', - # Warn for implicit type conversions that may change a value. - '-Wconversion', - '-Wno-c++11-compat', - # This complains about 'override', which we use heavily. - '-Wno-c++11-extensions', - # Warns on switches on enums that cover all enum values but - # also contain a default: branch. Chrome is full of that. - '-Wno-covered-switch-default', - # protobuf uses hash_map. - '-Wno-deprecated', - '-fno-exceptions', - # Don't warn about the "struct foo f = {0};" initialization pattern. - '-Wno-missing-field-initializers', - # Do not warn for implicit sign conversions. - '-Wno-sign-conversion', - '-fno-strict-aliasing', # See http://crbug.com/32204 - '-Wno-unnamed-type-template-args', - # Triggered by the COMPILE_ASSERT macro. - '-Wno-unused-local-typedef', - # Do not warn if a function or variable cannot be implicitly - # instantiated. - '-Wno-undefined-var-template', - # Do not warn about an implicit exception spec mismatch. - '-Wno-implicit-exception-spec-mismatch', - # Do not warn about unused function params. - '-Wno-unused-parameter', - ], - }], - ['cobalt_fastbuild==0', { - 'compiler_flags_debug': [ - '-g', - ], - 'compiler_flags_devel': [ - '-g', - ], - 'compiler_flags_qa': [ - '-gline-tables-only', - ], - 'compiler_flags_gold': [ - '-gline-tables-only', - ], - }], - ], - }, - - 'target_defaults': { - 'defines': [ - # By default, <EGL/eglplatform.h> pulls in some X11 headers that have some - # nasty macros (|Status|, for example) that conflict with Chromium base. - 'MESA_EGL_NO_X11_HEADERS' - ], - 'cflags_c': [ - # Limit to C99. This allows Linux to be a canary build for any - # C11 features that are not supported on some platforms' compilers. - '-std=c99', - ], - 'cflags_cc': [ - '-std=gnu++11', - ], - 'ldflags': [ - '-Wl,-rpath=$ORIGIN/lib', - ], - 'target_conditions': [ - ['sb_pedantic_warnings==1', { - 'cflags': [ - '-Wall', - '-Wextra', - '-Wunreachable-code', - '<@(common_clang_flags)', - ], - },{ - 'cflags': [ - '<@(common_clang_flags)', - # 'this' pointer cannot be NULL...pointer may be assumed - # to always convert to true. - '-Wno-undefined-bool-conversion', - # Skia doesn't use overrides. - '-Wno-inconsistent-missing-override', - # Do not warn for implicit type conversions that may change a value. - '-Wno-conversion', - # shifting a negative signed value is undefined - '-Wno-shift-negative-value', - # Width of bit-field exceeds width of its type- value will be truncated - '-Wno-bitfield-width', - '-Wno-undefined-var-template', - ], - }], - ['use_asan==1', { - 'cflags': [ - '-fsanitize=address', - '-fno-omit-frame-pointer', - ], - 'ldflags': [ - '-fsanitize=address', - # Force linking of the helpers in sanitizer_options.cc - '-Wl,-u_sanitizer_options_link_helper', - ], - 'defines': [ - 'ADDRESS_SANITIZER', - ], - 'conditions': [ - ['asan_symbolizer_path!=""', { - 'defines': [ - 'ASAN_SYMBOLIZER_PATH="<@(asan_symbolizer_path)"', - ], - }], - ], - }], - ['use_tsan==1', { - 'cflags': [ - '-fsanitize=thread', - '-fno-omit-frame-pointer', - ], - 'ldflags': [ - '-fsanitize=thread', - ], - 'defines': [ - 'THREAD_SANITIZER', - ], - }], - ], - }, # end of target_defaults -}
diff --git a/src/starboard/linux/x86x11/configuration_public.h b/src/starboard/linux/x86x11/configuration_public.h deleted file mode 100644 index 18bddfc..0000000 --- a/src/starboard/linux/x86x11/configuration_public.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef STARBOARD_LINUX_X86X11_CONFIGURATION_PUBLIC_H_ -#define STARBOARD_LINUX_X86X11_CONFIGURATION_PUBLIC_H_ - -#include "starboard/linux/x64x11/configuration_public.h" - -#endif // STARBOARD_LINUX_X86X11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x86x11/gyp_configuration.gypi b/src/starboard/linux/x86x11/gyp_configuration.gypi deleted file mode 100644 index de33ec1..0000000 --- a/src/starboard/linux/x86x11/gyp_configuration.gypi +++ /dev/null
@@ -1,49 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - -{ - 'variables': { - 'sb_target_platform': 'linux-x86x11', - 'enable_map_to_mesh': 1, - 'target_arch': 'ia32', - }, - - 'target_defaults': { - 'default_configuration': 'linux-x86x11_debug', - 'configurations': { - 'linux-x86x11_debug': { - 'inherit_from': ['debug_base'], - }, - 'linux-x86x11_devel': { - 'inherit_from': ['devel_base'], - }, - 'linux-x86x11_qa': { - 'inherit_from': ['qa_base'], - }, - 'linux-x86x11_gold': { - 'inherit_from': ['gold_base'], - }, - }, # end of configurations - }, - - 'includes': [ - '<(DEPTH)/starboard/linux/x64x11/enable_glx_via_angle.gypi', - '<(DEPTH)/starboard/linux/x64x11/libraries.gypi', - 'compiler_flags.gypi', - '<(DEPTH)/starboard/linux/shared/gyp_configuration.gypi', - ], -}
diff --git a/src/starboard/linux/x86x11/gyp_configuration.py b/src/starboard/linux/x86x11/gyp_configuration.py deleted file mode 100644 index eb54f3f..0000000 --- a/src/starboard/linux/x86x11/gyp_configuration.py +++ /dev/null
@@ -1,35 +0,0 @@ -# Copyright 2018 The Cobalt Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file was initially generated by starboard/tools/create_derived_build.py, -# though it may have been modified since its creation. - - -from starboard.linux.shared import gyp_configuration as parent_configuration - -class LinuxX86Configuration(parent_configuration.LinuxConfiguration): - """Starboard Linux x86 Platform Configuration.""" - - def __init__(self): - self.host_compiler_environment = { - 'CC_host': '/usr/bin/clang', - 'CXX_host': '/usr/bin/clang++', - 'LD_host': '/usr/bin/clang++', - 'ARFLAGS_host': 'rcs', - 'ARTHINFLAGS_host': 'rcsT', - } - super(LinuxX86Configuration, self).__init__('linux-x86x11') - -def CreatePlatformConfig(): - return LinuxX86Configuration()
diff --git a/src/starboard/linux/x86x11/starboard_platform.gyp b/src/starboard/linux/x86x11/starboard_platform.gyp deleted file mode 100644 index 9baad0c..0000000 --- a/src/starboard/linux/x86x11/starboard_platform.gyp +++ /dev/null
@@ -1,22 +0,0 @@ -# Copyright 2015 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. - -# Note, that despite the file extension ".gyp", this file is included by several -# platform variants of linux-x64x11, like a ".gypi" file, since those platforms -# have no need to modify this code. -{ - 'includes': [ - '../x64x11/shared/starboard_platform_target.gypi' - ], -}
diff --git a/src/starboard/linux/x86x11/starboard_platform_tests.gyp b/src/starboard/linux/x86x11/starboard_platform_tests.gyp deleted file mode 100644 index 0ea8622..0000000 --- a/src/starboard/linux/x86x11/starboard_platform_tests.gyp +++ /dev/null
@@ -1,18 +0,0 @@ -# Copyright 2018 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. -{ - 'includes': [ - '<(DEPTH)/starboard/linux/shared/starboard_platform_tests.gypi', - ], -}
diff --git a/src/starboard/linux/x86x11/thread_types_public.h b/src/starboard/linux/x86x11/thread_types_public.h deleted file mode 100644 index f0af6f7..0000000 --- a/src/starboard/linux/x86x11/thread_types_public.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 The Cobalt Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file was initially generated by starboard/tools/create_derived_build.py, -// though it may have been modified since its creation. - -#ifndef STARBOARD_LINUX_X86X11_THREAD_TYPES_PUBLIC_H_ -#define STARBOARD_LINUX_X86X11_THREAD_TYPES_PUBLIC_H_ - -#include "starboard/linux/shared/thread_types_public.h" - -#endif // STARBOARD_LINUX_X86X11_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/memory.h b/src/starboard/memory.h index c9e7691..cd0ad95 100644 --- a/src/starboard/memory.h +++ b/src/starboard/memory.h
@@ -193,7 +193,7 @@ SB_DEPRECATED_EXTERNAL( SB_EXPORT void SbMemoryFreeAligned(void* memory)); -#if SB_HAS(MMAP) +#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) // Allocates |size_bytes| worth of physical memory pages and maps them into // an available virtual region. This function returns |SB_MEMORY_MAP_FAILED| // on failure. |NULL| is a valid return value. @@ -235,7 +235,7 @@ // memory that has been written to and might be executed in the future. SB_EXPORT void SbMemoryFlush(void* virtual_address, int64_t size_bytes); #endif -#endif // SB_HAS(MMAP) +#endif // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) // Gets the stack bounds for the current thread. //
diff --git a/src/starboard/microphone.h b/src/starboard/microphone.h index ae063d0..b2932fe 100644 --- a/src/starboard/microphone.h +++ b/src/starboard/microphone.h
@@ -43,7 +43,7 @@ #include "starboard/export.h" #include "starboard/types.h" -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) #if SB_API_VERSION >= 9 #define kSbMicrophoneLabelSize 256 @@ -205,6 +205,7 @@ } // extern "C" #endif -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) #endif // STARBOARD_MICROPHONE_H_
diff --git a/src/starboard/nplb/directory_can_open_test.cc b/src/starboard/nplb/directory_can_open_test.cc index 8a7c731..f97ef38 100644 --- a/src/starboard/nplb/directory_can_open_test.cc +++ b/src/starboard/nplb/directory_can_open_test.cc
@@ -41,6 +41,7 @@ TEST(SbDirectoryCanOpenTest, FailureRegularFile) { starboard::nplb::ScopedRandomFile file; + EXPECT_TRUE(SbFileExists(file.filename().c_str())); EXPECT_FALSE(SbDirectoryCanOpen(file.filename().c_str())); }
diff --git a/src/starboard/nplb/file_atomic_replace_test.cc b/src/starboard/nplb/file_atomic_replace_test.cc new file mode 100644 index 0000000..f0c9ba4 --- /dev/null +++ b/src/starboard/nplb/file_atomic_replace_test.cc
@@ -0,0 +1,101 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/file.h" +#include "starboard/nplb/file_helpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + +namespace starboard { +namespace nplb { +namespace { + +static const char kTestContents[] = + "The quick brown fox jumps over the lazy dog."; +static const int kTestContentsLength = sizeof(kTestContents); + +bool CompareFileContentsToString(const char* filename, + const char* str, + int size) { + char result[kTestContentsLength] = {'\0'}; + + SbFileError error; + SbFile file = + SbFileOpen(filename, kSbFileOpenOnly | kSbFileRead, nullptr, &error); + + EXPECT_EQ(kSbFileOk, error); + + // We always try to read kTestContentsLength since the data will at most be + // this long. There are test cases where the number of bytes read will be + // less. + EXPECT_EQ(size, SbFileReadAll(file, result, kTestContentsLength)); + EXPECT_TRUE(SbFileClose(file)); + + return SbStringCompare(str, result, kTestContentsLength) == 0; +} + +TEST(SbFileAtomicReplaceTest, ReplacesValidFile) { + ScopedRandomFile random_file(ScopedRandomFile::kDefaultLength, + ScopedRandomFile::kCreate); + const std::string& filename = random_file.filename(); + + EXPECT_TRUE(SbFileExists(filename.c_str())); + EXPECT_TRUE(SbFileAtomicReplace(filename.c_str(), kTestContents, + kTestContentsLength)); + EXPECT_TRUE(CompareFileContentsToString(filename.c_str(), kTestContents, + kTestContentsLength)); +} + +TEST(SbFileAtomicReplaceTest, ReplacesNonExistentFile) { + ScopedRandomFile random_file(ScopedRandomFile::kDontCreate); + const std::string& filename = random_file.filename(); + + EXPECT_FALSE(SbFileExists(filename.c_str())); + EXPECT_TRUE(SbFileAtomicReplace(filename.c_str(), kTestContents, + kTestContentsLength)); + EXPECT_TRUE(CompareFileContentsToString(filename.c_str(), kTestContents, + kTestContentsLength)); +} + +TEST(SbFileAtomicReplaceTest, ReplacesWithNoData) { + ScopedRandomFile random_file(ScopedRandomFile::kCreate); + const std::string& filename = random_file.filename(); + + EXPECT_TRUE(SbFileExists(filename.c_str())); + EXPECT_TRUE(SbFileAtomicReplace(filename.c_str(), nullptr, 0)); + EXPECT_TRUE(CompareFileContentsToString(filename.c_str(), "\0", 0)); +} + +TEST(SbFileAtomicReplaceTest, FailsWithNoDataButLength) { + ScopedRandomFile random_file(ScopedRandomFile::kCreate); + const std::string& filename = random_file.filename(); + + EXPECT_TRUE(SbFileExists(filename.c_str())); + EXPECT_FALSE(SbFileAtomicReplace(filename.c_str(), nullptr, 1)); +} + +TEST(SbFileAtomicReplaceTest, FailsWithInvalidLength) { + ScopedRandomFile random_file(ScopedRandomFile::kCreate); + const std::string& filename = random_file.filename(); + + EXPECT_TRUE(SbFileExists(filename.c_str())); + EXPECT_FALSE(SbFileAtomicReplace(filename.c_str(), kTestContents, -1)); +} + +} // namespace +} // namespace nplb +} // namespace starboard + +#endif // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
diff --git a/src/starboard/nplb/file_helpers.cc b/src/starboard/nplb/file_helpers.cc index 8e6f781..ff7753a 100644 --- a/src/starboard/nplb/file_helpers.cc +++ b/src/starboard/nplb/file_helpers.cc
@@ -89,7 +89,7 @@ data[i] = static_cast<char>(i & 0xFF); } - int bytes = SbFileWrite(file, data, length); + int bytes = SbFileWriteAll(file, data, length); EXPECT_EQ(bytes, length) << "Failed to write " << length << " bytes to " << filename;
diff --git a/src/starboard/nplb/file_read_write_all_test.cc b/src/starboard/nplb/file_read_write_all_test.cc new file mode 100644 index 0000000..9782fde --- /dev/null +++ b/src/starboard/nplb/file_read_write_all_test.cc
@@ -0,0 +1,65 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/file.h" +#include "starboard/nplb/file_helpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace nplb { +namespace { + +class SbReadWriteAllTestWithBuffer + : public ::testing::TestWithParam<int> { + public: + int GetBufferSize() { return GetParam(); } +}; + +TEST_P(SbReadWriteAllTestWithBuffer, ReadFile) { + ScopedRandomFile random_file(0, ScopedRandomFile::kDontCreate); + const std::string& filename = random_file.filename(); + + SbFile file = SbFileOpen( + filename.c_str(), kSbFileCreateAlways | kSbFileWrite, NULL, NULL); + + std::vector<char> file_contents; + file_contents.reserve(GetBufferSize()); + for (int i = 0; i < GetBufferSize(); ++i) { + file_contents.push_back(i % 255); + } + int bytes_written = + SbFileWriteAll(file, file_contents.data(), file_contents.size()); + EXPECT_EQ(GetBufferSize(), bytes_written); + + SbFileClose(file); + + file = SbFileOpen( + filename.c_str(), kSbFileOpenOnly | kSbFileRead, NULL, NULL); + std::vector<char> read_contents(GetBufferSize()); + int bytes_read = + SbFileReadAll(file, read_contents.data(), read_contents.size()); + EXPECT_EQ(GetBufferSize(), bytes_read); + EXPECT_EQ(file_contents, read_contents); + + SbFileClose(file); +} + +INSTANTIATE_TEST_CASE_P( + SbReadAllTestSbReadWriteAllTest, + SbReadWriteAllTestWithBuffer, + ::testing::Values(0, 1, 1024, 16 * 1024, 128 * 1024, 1024 * 1024)); + +} // namespace +} // namespace nplb +} // namespace starboard
diff --git a/src/starboard/nplb/file_truncate_test.cc b/src/starboard/nplb/file_truncate_test.cc index 300aa96..ae2b3de 100644 --- a/src/starboard/nplb/file_truncate_test.cc +++ b/src/starboard/nplb/file_truncate_test.cc
@@ -99,7 +99,7 @@ } char buffer[kEndSize] = {0}; - int bytes = SbFileRead(file, buffer, kEndSize); + int bytes = SbFileReadAll(file, buffer, kEndSize); EXPECT_EQ(kEndSize, bytes); ScopedRandomFile::ExpectPattern(0, buffer, kStartSize, __LINE__);
diff --git a/src/starboard/nplb/file_write_test.cc b/src/starboard/nplb/file_write_test.cc index 576c842..4aca8d7 100644 --- a/src/starboard/nplb/file_write_test.cc +++ b/src/starboard/nplb/file_write_test.cc
@@ -85,7 +85,8 @@ int remaining = kFileSize - total; int to_write = remaining < kBufferLength ? remaining : kBufferLength; - int bytes_written = TypeParam::Write(file, buffer, to_write); + int bytes_written = TypeParam::Write( + file, buffer + (total % kBufferLength), to_write); // Check that we didn't write more than the buffer size. EXPECT_GE(to_write, bytes_written);
diff --git a/src/starboard/nplb/flat_map_test.cc b/src/starboard/nplb/flat_map_test.cc index cac4d52..dde8625 100644 --- a/src/starboard/nplb/flat_map_test.cc +++ b/src/starboard/nplb/flat_map_test.cc
@@ -584,7 +584,7 @@ return delta_time; } -TEST(FlatMap, PerformanceTestFind) { +TEST(FlatMap, DISABLED_PerformanceTestFind) { std::vector<size_t> test_sizes; test_sizes.push_back(5); test_sizes.push_back(10);
diff --git a/src/starboard/nplb/media_set_audio_write_duration_test.cc b/src/starboard/nplb/media_set_audio_write_duration_test.cc index 2d3a964..8cdb565 100644 --- a/src/starboard/nplb/media_set_audio_write_duration_test.cc +++ b/src/starboard/nplb/media_set_audio_write_duration_test.cc
@@ -238,7 +238,7 @@ SbPlayerDestroy(player); } -TEST_P(SbMediaSetAudioWriteDurationTest, FLAKY_WriteContinuedLimitedInput) { +TEST_P(SbMediaSetAudioWriteDurationTest, WriteContinuedLimitedInput) { ASSERT_NE(dmp_reader_.audio_codec(), kSbMediaAudioCodecNone); ASSERT_GT(dmp_reader_.number_of_audio_buffers(), 0); @@ -273,8 +273,8 @@ } std::vector<const char*> GetSupportedTests() { - const char* kFilenames[] = {"beneath_the_canopy_140_aac.dmp", - "beneath_the_canopy_249_opus.dmp"}; + const char* kFilenames[] = {"beneath_the_canopy_aac_stereo.dmp", + "beneath_the_canopy_opus_stereo.dmp"}; static std::vector<const char*> test_params;
diff --git a/src/starboard/nplb/memory_map_test.cc b/src/starboard/nplb/memory_map_test.cc index 36808db..b255027 100644 --- a/src/starboard/nplb/memory_map_test.cc +++ b/src/starboard/nplb/memory_map_test.cc
@@ -21,7 +21,7 @@ namespace nplb { namespace { -#if SB_HAS(MMAP) +#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) const size_t kSize = SB_MEMORY_PAGE_SIZE * 8; const void* kFailed = SB_MEMORY_MAP_FAILED; @@ -293,7 +293,7 @@ } #endif // SB_API_VERSION >= 10 -#endif // SB_HAS(MMAP) +#endif // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) } // namespace } // namespace nplb
diff --git a/src/starboard/nplb/memory_reporter_test.cc b/src/starboard/nplb/memory_reporter_test.cc index 9fad889..5596514 100644 --- a/src/starboard/nplb/memory_reporter_test.cc +++ b/src/starboard/nplb/memory_reporter_test.cc
@@ -336,7 +336,7 @@ EXPECT_EQ_NO_TRACKING(mem_reporter()->number_allocs(), 0); } -#if SB_HAS(MMAP) +#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) // Tests the assumption that the SbMemoryMap and SbMemoryUnmap // will report memory allocations. TEST_F(MemoryReportingTest, CapturesMemMapUnmap) { @@ -356,7 +356,7 @@ EXPECT_EQ_NO_TRACKING(mem_chunk, mem_reporter()->last_mem_unmap()); EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_map_mem()); } -#endif // SB_HAS(MMAP) +#endif // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) // Tests the assumption that the operator new/delete will report // memory allocations.
diff --git a/src/starboard/nplb/microphone_close_test.cc b/src/starboard/nplb/microphone_close_test.cc index 6a8677d..e271bf2 100644 --- a/src/starboard/nplb/microphone_close_test.cc +++ b/src/starboard/nplb/microphone_close_test.cc
@@ -20,7 +20,7 @@ namespace nplb { namespace { -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) TEST(SbMicrophoneCloseTest, SunnyDayCloseAreCalledMultipleTimes) { SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; @@ -74,7 +74,8 @@ EXPECT_FALSE(success); } -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) } // namespace } // namespace nplb
diff --git a/src/starboard/nplb/microphone_create_test.cc b/src/starboard/nplb/microphone_create_test.cc index edb2e8a..94813cb 100644 --- a/src/starboard/nplb/microphone_create_test.cc +++ b/src/starboard/nplb/microphone_create_test.cc
@@ -21,7 +21,7 @@ namespace nplb { namespace { -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) TEST(SbMicrophoneCreateTest, SunnyDayOnlyOneMicrophone) { SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; @@ -183,7 +183,8 @@ } } -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) } // namespace } // namespace nplb
diff --git a/src/starboard/nplb/microphone_destroy_test.cc b/src/starboard/nplb/microphone_destroy_test.cc index 9b4ea45..bba3006 100644 --- a/src/starboard/nplb/microphone_destroy_test.cc +++ b/src/starboard/nplb/microphone_destroy_test.cc
@@ -19,13 +19,14 @@ namespace nplb { namespace { -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) TEST(SbMicrophoneDestroyTest, DestroyInvalidMicrophone) { SbMicrophoneDestroy(kSbMicrophoneInvalid); } -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) } // namespace } // namespace nplb
diff --git a/src/starboard/nplb/microphone_get_available_test.cc b/src/starboard/nplb/microphone_get_available_test.cc index 63c36f4..13eb081 100644 --- a/src/starboard/nplb/microphone_get_available_test.cc +++ b/src/starboard/nplb/microphone_get_available_test.cc
@@ -20,7 +20,7 @@ namespace nplb { namespace { -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) TEST(SbMicrophoneGetAvailableTest, SunnyDay) { SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; @@ -89,7 +89,8 @@ #endif // SB_API_VERSION >= 9 -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) } // namespace } // namespace nplb
diff --git a/src/starboard/nplb/microphone_helpers.h b/src/starboard/nplb/microphone_helpers.h index 08c23fa..eb683aa 100644 --- a/src/starboard/nplb/microphone_helpers.h +++ b/src/starboard/nplb/microphone_helpers.h
@@ -17,7 +17,7 @@ #include "starboard/microphone.h" -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) namespace starboard { namespace nplb { @@ -27,6 +27,7 @@ } // namespace nplb } // namespace starboard -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) #endif // STARBOARD_NPLB_MICROPHONE_HELPERS_H_
diff --git a/src/starboard/nplb/microphone_is_sample_rate_supported_test.cc b/src/starboard/nplb/microphone_is_sample_rate_supported_test.cc index cdf93e3..7fd6e8a 100644 --- a/src/starboard/nplb/microphone_is_sample_rate_supported_test.cc +++ b/src/starboard/nplb/microphone_is_sample_rate_supported_test.cc
@@ -20,7 +20,7 @@ namespace nplb { namespace { -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) TEST(SbMicrophoneIsSampleRateSupportedTest, SunnyDay) { SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; @@ -50,7 +50,8 @@ kNormallyUsedSampleRateInHz)); } -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) } // namespace } // namespace nplb
diff --git a/src/starboard/nplb/microphone_open_test.cc b/src/starboard/nplb/microphone_open_test.cc index 09efb34..27681b1 100644 --- a/src/starboard/nplb/microphone_open_test.cc +++ b/src/starboard/nplb/microphone_open_test.cc
@@ -20,7 +20,7 @@ namespace nplb { namespace { -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) TEST(SbMicrophoneOpenTest, SunnyDay) { SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; @@ -93,7 +93,8 @@ EXPECT_FALSE(success); } -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) } // namespace } // namespace nplb
diff --git a/src/starboard/nplb/microphone_read_test.cc b/src/starboard/nplb/microphone_read_test.cc index 7f9232e..af8b7d3 100644 --- a/src/starboard/nplb/microphone_read_test.cc +++ b/src/starboard/nplb/microphone_read_test.cc
@@ -21,7 +21,7 @@ namespace nplb { namespace { -#if SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE) TEST(SbMicrophoneReadTest, SunnyDay) { SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; @@ -236,7 +236,8 @@ EXPECT_LT(read_bytes, 0); } -#endif // SB_API_VERSION >= 12 || SB_HAS(MICROPHONE) +#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || + // SB_HAS(MICROPHONE) } // namespace } // namespace nplb
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp index e80cf3c..cd280b6 100644 --- a/src/starboard/nplb/nplb.gyp +++ b/src/starboard/nplb/nplb.gyp
@@ -124,6 +124,7 @@ 'drm_update_server_certificate_test.cc', 'egl_test.cc', 'extern_c_test.cc', + 'file_atomic_replace_test.cc', 'file_can_open_test.cc', 'file_close_test.cc', 'file_get_info_test.cc', @@ -132,6 +133,7 @@ 'file_mode_string_to_flags_test.cc', 'file_open_test.cc', 'file_read_test.cc', + 'file_read_write_all_test.cc', 'file_seek_test.cc', 'file_truncate_test.cc', 'file_write_test.cc', @@ -295,6 +297,7 @@ 'window_get_diagonal_size_in_inches_test.cc', 'window_get_platform_handle_test.cc', 'window_get_size_test.cc', + '<@(sabi_sources)', # Include private c headers, if present. '<!@(python "<(DEPTH)/starboard/tools/find_private_files.py" "<(DEPTH)" "nplb/include_all_private.c")', # Include private tests, if present. @@ -325,6 +328,7 @@ ], }], ], + 'includes': [ '<(DEPTH)/starboard/nplb/sabi/sabi.gypi' ], }, { 'target_name': 'nplb_deploy',
diff --git a/src/starboard/nplb/sabi/alignment_test.cc b/src/starboard/nplb/sabi/alignment_test.cc new file mode 100644 index 0000000..59060f9 --- /dev/null +++ b/src/starboard/nplb/sabi/alignment_test.cc
@@ -0,0 +1,51 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/configuration.h" + +#if SB_API_VERSION >= SB_SABI_FILE_VERSION + +namespace starboard { +namespace sabi { +namespace { + +SB_COMPILE_ASSERT(SB_ALIGNOF(char) == SB_ALIGNMENT_OF_CHAR, + SB_ALIGNMENT_OF_CHAR_is_inconsistent_with_SB_ALIGNOF_char); + +SB_COMPILE_ASSERT(SB_ALIGNOF(double) == SB_ALIGNMENT_OF_DOUBLE, + SB_ALIGNMENT_OF_DOUBLE_is_inconsistent_with_SB_ALIGNOF_double); + +SB_COMPILE_ASSERT(SB_ALIGNOF(float) == SB_ALIGNMENT_OF_FLOAT, + SB_ALIGNMENT_OF_FLOAT_is_inconsistent_with_SB_ALIGNOF_float); + +SB_COMPILE_ASSERT(SB_ALIGNOF(int) == SB_ALIGNMENT_OF_INT, + SB_ALIGNMENT_OF_INT_is_inconsistent_with_SB_ALIGNOF_int); + +SB_COMPILE_ASSERT(SB_ALIGNOF(int*) == SB_ALIGNMENT_OF_POINTER, + SB_ALIGNMENT_OF_POINTER_is_inconsistent_with_SB_ALIGNOF_pointer); + +SB_COMPILE_ASSERT(SB_ALIGNOF(long) == SB_ALIGNMENT_OF_LONG, // NOLINT(runtime/int) + SB_ALIGNMENT_OF_LONG_is_inconsistent_with_SB_ALIGNOF_long); + +SB_COMPILE_ASSERT(SB_ALIGNOF(long long) == SB_ALIGNMENT_OF_LLONG, // NOLINT(runtime/int) + SB_ALIGNMENT_OF_LLONG_is_inconsistent_with_SB_ALIGNOF_long_long); + +SB_COMPILE_ASSERT(SB_ALIGNOF(short) == SB_ALIGNMENT_OF_SHORT, // NOLINT(runtime/int) + SB_ALIGNMENT_OF_SHORT_is_inconsistent_with_SB_ALIGNOF_short); + +} // namespace +} // namespace sabi +} // namespace starboard + +#endif // SB_API_VERSION >= SB_SABI_FILE_VERSION
diff --git a/src/starboard/nplb/sabi/endianness_test.cc b/src/starboard/nplb/sabi/endianness_test.cc new file mode 100644 index 0000000..f1ce27e --- /dev/null +++ b/src/starboard/nplb/sabi/endianness_test.cc
@@ -0,0 +1,43 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/types.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if SB_API_VERSION >= SB_SABI_FILE_VERSION + +namespace starboard { +namespace sabi { +namespace { + +static constexpr int32_t kCobalt21 = 0xC0BA1721; + +#if SB_IS(BIG_ENDIAN) +static constexpr uint8_t kBytes[] = {0xC0, 0xBA, 0x17, 0x21}; +#else // !SB_IS(BIG_ENDIAN) +static constexpr uint8_t kBytes[] = {0x21, 0x17, 0xBA, 0xC0}; +#endif // SB_IS(BIG_ENDIAN) + +} // namespace + +TEST(SbSabiEndiannessTest, Endianness) { + for (int i = 0; i < 4; ++i) { + EXPECT_EQ(*(reinterpret_cast<const uint8_t*>(&kCobalt21) + i), kBytes[i]); + } +} + +} // namespace sabi +} // namespace starboard + +#endif // SB_API_VERSION >= SB_SABI_FILE_VERSION
diff --git a/src/starboard/nplb/sabi/sabi.gypi b/src/starboard/nplb/sabi/sabi.gypi new file mode 100644 index 0000000..3d76231 --- /dev/null +++ b/src/starboard/nplb/sabi/sabi.gypi
@@ -0,0 +1,25 @@ +# Copyright 2019 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. + +{ + 'variables': { + 'sabi_sources': [ + '<(DEPTH)/starboard/nplb/sabi/alignment_test.cc', + '<(DEPTH)/starboard/nplb/sabi/endianness_test.cc', + '<(DEPTH)/starboard/nplb/sabi/signedness_of_char_test.cc', + '<(DEPTH)/starboard/nplb/sabi/size_test.cc', + '<(DEPTH)/starboard/nplb/sabi/struct_alignment_test.cc', + ], + }, +}
diff --git a/src/starboard/nplb/sabi/signedness_of_char_test.cc b/src/starboard/nplb/sabi/signedness_of_char_test.cc new file mode 100644 index 0000000..b736e08 --- /dev/null +++ b/src/starboard/nplb/sabi/signedness_of_char_test.cc
@@ -0,0 +1,30 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/configuration.h" + +#if SB_API_VERSION >= SB_SABI_FILE_VERSION + +namespace starboard { +namespace sabi { +namespace { + +SB_COMPILE_ASSERT((static_cast<char>(-1) < 0) == SB_HAS_SIGNED_CHAR, // NOLINT(readability/casting) + SB_HAS_SIGNED_CHAR_is_inconsistent_with_sign_of_char); + +} // namespace +} // namespace sabi +} // namespace starboard + +#endif // SB_API_VERSION >= SB_SABI_FILE_VERSION
diff --git a/src/starboard/nplb/sabi/size_test.cc b/src/starboard/nplb/sabi/size_test.cc new file mode 100644 index 0000000..8d55ee9 --- /dev/null +++ b/src/starboard/nplb/sabi/size_test.cc
@@ -0,0 +1,51 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/configuration.h" + +#if SB_API_VERSION >= SB_SABI_FILE_VERSION + +namespace starboard { +namespace sabi { +namespace { + +SB_COMPILE_ASSERT(sizeof(char) == SB_SIZE_OF_CHAR, + SB_SIZE_OF_CHAR_is_inconsistent_with_sizeof_char); + +SB_COMPILE_ASSERT(sizeof(double) == SB_SIZE_OF_DOUBLE, + SB_SIZE_OF_DOUBLE_is_inconsistent_with_sizeof_double); + +SB_COMPILE_ASSERT(sizeof(float) == SB_SIZE_OF_FLOAT, + SB_SIZE_OF_FLOAT_is_inconsistent_with_sizeof_float); + +SB_COMPILE_ASSERT(sizeof(int) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_int); + +SB_COMPILE_ASSERT(sizeof(int*) == SB_SIZE_OF_POINTER, + SB_SIZE_OF_POINTER_is_inconsistent_with_sizeof_intptr_t); + +SB_COMPILE_ASSERT(sizeof(long) == SB_SIZE_OF_LONG, // NOLINT(runtime/int) + SB_SIZE_OF_LONG_is_inconsistent_with_sizeof_long); + +SB_COMPILE_ASSERT(sizeof(long long) == SB_SIZE_OF_LLONG, // NOLINT(runtime/int) + SB_SIZE_OF_LONG_is_inconsistent_with_sizeof_llong); + +SB_COMPILE_ASSERT(sizeof(short) == SB_SIZE_OF_SHORT, // NOLINT(runtime/int) + SB_SIZE_OF_SHORT_is_inconsistent_with_sizeof_short); + +} // namespace +} // namespace sabi +} // namespace starboard + +#endif // SB_API_VERSION >= SB_SABI_FILE_VERSION
diff --git a/src/starboard/nplb/sabi/struct_alignment_test.cc b/src/starboard/nplb/sabi/struct_alignment_test.cc new file mode 100644 index 0000000..92bb474 --- /dev/null +++ b/src/starboard/nplb/sabi/struct_alignment_test.cc
@@ -0,0 +1,169 @@ +// Copyright 2019 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 <cstddef> + +#include "starboard/configuration.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if SB_API_VERSION >= SB_SABI_FILE_VERSION + +// 8-byte integers make structs 4-byte aligned on ia32. +#if SB_IS(ARCH_IA32) || (SB_IS(ARCH_X86) && SB_IS(32_BIT)) +#define ALIGNMENT_8_BYTE_INT 4 +#else // !SB_IS(ARCH_IA32) && (!SB_IS(ARCH_X86) || !SB_IS(32_BIT)) +#define ALIGNMENT_8_BYTE_INT 8 +#endif // SB_IS(ARCH_IA32) || (SB_IS(ARCH_X86) && SB_IS(32_BIT)) + +namespace starboard { +namespace sabi { +namespace { + +static const int8_t kInt8 = 0x74; +static const int16_t kInt16 = 0x2DEF; +static const int32_t kInt32 = 0x35C7ADD2; +static const int64_t kInt64 = 0x16FE0870D4784352; + +// Checks the trailing padding of members of ascending data type sizes. +typedef struct Struct1 { + int8_t a; + int16_t b; + int32_t c; + int64_t d; +} Struct1; + +SB_COMPILE_ASSERT(SB_ALIGNOF(Struct1) == ALIGNMENT_8_BYTE_INT, + SB_ALIGNOF_Struct1_is_inconsistent_with_expectations); + +SB_COMPILE_ASSERT(offsetof(Struct1, a) == 0, + offsetof_Struct1_a_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct1, b) == 2, + offsetof_Struct1_b_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct1, c) == 4, + offsetof_Struct1_c_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct1, d) == 8, + offsetof_Struct1_d_is_inconsistent_with_expectations); + +// Checks the trailing padding of members of descending data type sizes. +typedef struct Struct2 { + int64_t a; + int32_t b; + int16_t c; + int8_t d; +} Struct2; + +SB_COMPILE_ASSERT(SB_ALIGNOF(Struct2) == ALIGNMENT_8_BYTE_INT, + ALIGNOF_Struct2_is_inconsistent_with_expectations); + +SB_COMPILE_ASSERT(offsetof(Struct2, a) == 0, + offsetof_Struct2_a_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct2, b) == 8, + offsetof_Struct2_b_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct2, c) == 12, + offsetof_Struct2_c_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct2, d) == 14, + offsetof_Struct2_d_is_inconsistent_with_expectations); + +// Checks the trailing padding of nested struct members. +typedef struct Struct3 { + int8_t a; + + struct { + int32_t b; + } c; + + int8_t d; +} Struct3; + +SB_COMPILE_ASSERT(SB_ALIGNOF(Struct3) == 4, + ALIGNOF_Struct3_is_inconsistent_with_expectations); + +SB_COMPILE_ASSERT(offsetof(Struct3, a) == 0, + offsetof_Struct3_a_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct3, c) == 4, + offsetof_Struct3_c_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct3, c.b) == 4, + offsetof_Struct3_c_b_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct3, d) == 8, + offsetof_Struct3_d_is_inconsistent_with_expectations); + +// Checks the trailing padding of nested union members. +typedef struct Struct4 { + int8_t a; + + union { + int32_t b; + } c; + + int8_t d; +} Struct4; + +SB_COMPILE_ASSERT(SB_ALIGNOF(Struct4) == 4, + ALIGNOF_Struct4_is_inconsistent_with_expectations); + +SB_COMPILE_ASSERT(offsetof(Struct4, a) == 0, + offsetof_Struct4_a_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct4, c) == 4, + offsetof_Struct4_c_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct4, c.b) == 4, + offsetof_Struct4_c_b_is_inconsistent_with_expectations); +SB_COMPILE_ASSERT(offsetof(Struct4, d) == 8, + offsetof_Struct4_d_is_inconsistent_with_expectations); + +} // namespace + +TEST(SbSabiStructAlignmentTest, AscendingDataTypeSizes) { + const Struct1 struct1 = {kInt8, kInt16, kInt32, kInt64}; + const int8_t* base = reinterpret_cast<const int8_t*>(&struct1); + + EXPECT_EQ(kInt8, *base); + EXPECT_EQ(kInt16, *reinterpret_cast<const int16_t*>(base + 2)); + EXPECT_EQ(kInt32, *reinterpret_cast<const int32_t*>(base + 4)); + EXPECT_EQ(kInt64, *reinterpret_cast<const int64_t*>(base + 8)); +} + +TEST(SbSabiStructAlignmentTest, DescendingDataTypeSizes) { + const Struct2 struct2 = {kInt64, kInt32, kInt16, kInt8}; + const int8_t* base = reinterpret_cast<const int8_t*>(&struct2); + + EXPECT_EQ(kInt64, *reinterpret_cast<const int64_t*>(base)); + EXPECT_EQ(kInt32, *reinterpret_cast<const int32_t*>(base + 8)); + EXPECT_EQ(kInt16, *reinterpret_cast<const int16_t*>(base + 12)); + EXPECT_EQ(kInt8, *(base + 14)); +} + +TEST(SbSabiStructAlignmentTest, NestedStruct) { + const Struct3 struct3 = {kInt8, {kInt32}, kInt8}; + const int8_t* base = reinterpret_cast<const int8_t*>(&struct3); + + EXPECT_EQ(kInt8, *base); + EXPECT_EQ(kInt32, *reinterpret_cast<const int32_t*>(base + 4)); + EXPECT_EQ(kInt8, *(base + 8)); +} + +TEST(SbSabiStructAlignmentTest, NestedUnion) { + const Struct4 struct4 = { kInt8, kInt32, kInt8 }; + const int8_t* base = reinterpret_cast<const int8_t*>(&struct4); + + EXPECT_EQ(kInt8, *base); + EXPECT_EQ(kInt32, *reinterpret_cast<const int32_t*>(base + 4)); + EXPECT_EQ(kInt8, *(base + 8)); +} + +} // namespace sabi +} // namespace starboard + +#undef ALIGNMENT_8_BYTE_INT + +#endif // SB_API_VERSION >= SB_SABI_FILE_VERSION
diff --git a/src/starboard/nplb/thread_yield_test.cc b/src/starboard/nplb/thread_yield_test.cc index c160dde..cd899d9 100644 --- a/src/starboard/nplb/thread_yield_test.cc +++ b/src/starboard/nplb/thread_yield_test.cc
@@ -27,10 +27,8 @@ return (trial % 2 ? (index % 2 != 0) : (index % 2 == 0)); } -// This number was experimentally determined on my desktop to be close to the -// minimum number of loops for the yielders to lose very consistently. The more -// loops, the more the yielders should fall behind. -const int kLoops = 1000; +// The more loops, the more the yielders should fall behind. +const int kLoops = 10000; void* YieldingEntryPoint(void* context) { for (int i = 0; i < kLoops; ++i) { @@ -76,7 +74,7 @@ SbThreadAffinity affinity = 0; // We want enough racers such that the threads must contend for cpu time, // and enough data for the averages to be consistently divergent. - const int64_t kRacers = 16; + const int64_t kRacers = 32; SbThread threads[kRacers]; SbTimeMonotonic end_times[kRacers] = {0}; for (int i = 0; i < kRacers; ++i) {
diff --git a/src/starboard/raspi/0/configuration_public.h b/src/starboard/raspi/0/configuration_public.h index fd38d59..d2c292b 100644 --- a/src/starboard/raspi/0/configuration_public.h +++ b/src/starboard/raspi/0/configuration_public.h
@@ -20,60 +20,6 @@ #ifndef STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_ #define STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_ -// --- Architecture Configuration -------------------------------------------- - -// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be -// automatically set based on this. -#define SB_IS_BIG_ENDIAN 0 - -// Whether the current platform is an ARM architecture. -#define SB_IS_ARCH_ARM 1 - -// Whether the current platform is a MIPS architecture. -#define SB_IS_ARCH_MIPS 0 - -// Whether the current platform is a PPC architecture. -#define SB_IS_ARCH_PPC 0 - -// Whether the current platform is an x86 architecture. -#define SB_IS_ARCH_X86 0 - -// Whether the current platform is a 32-bit architecture. -#define SB_IS_32_BIT 1 - -// Whether the current platform is a 64-bit architecture. -#define SB_IS_64_BIT 0 - -// Whether the current platform's pointers are 32-bit. -// Whether the current platform's longs are 32-bit. -#if SB_IS(32_BIT) -#define SB_HAS_32_BIT_POINTERS 1 -#define SB_HAS_32_BIT_LONG 1 -#else -#define SB_HAS_32_BIT_POINTERS 0 -#define SB_HAS_32_BIT_LONG 0 -#endif - -// Whether the current platform's pointers are 64-bit. -// Whether the current platform's longs are 64-bit. -#if SB_IS(64_BIT) -#define SB_HAS_64_BIT_POINTERS 1 -#define SB_HAS_64_BIT_LONG 1 -#else -#define SB_HAS_64_BIT_POINTERS 0 -#define SB_HAS_64_BIT_LONG 0 -#endif - -// Configuration parameters that allow the application to make some general -// compile-time decisions with respect to the the number of cores likely to be -// available on this platform. For a definitive measure, the application should -// still call SbSystemGetNumberOfProcessors at runtime. - -// Whether the current platform's thread scheduler will automatically balance -// threads between cores, as opposed to systems where threads will only ever run -// on the specifically pinned core. -#define SB_HAS_CROSS_CORE_SCHEDULER 1 - #include "starboard/raspi/shared/configuration_public.h" #endif // STARBOARD_RASPI_0_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/raspi/0/gyp_configuration.py b/src/starboard/raspi/0/gyp_configuration.py index 72f4437..1fdc988 100644 --- a/src/starboard/raspi/0/gyp_configuration.py +++ b/src/starboard/raspi/0/gyp_configuration.py
@@ -19,8 +19,9 @@ class Raspi0PlatformConfig(shared_configuration.RaspiPlatformConfig): - def __init__(self, platform): - super(Raspi0PlatformConfig, self).__init__(platform) + def __init__(self, platform, sabi_json_path=None): + super(Raspi0PlatformConfig, self).__init__( + platform, sabi_json_path=sabi_json_path) def GetVariables(self, config_name): variables = super(Raspi0PlatformConfig, self).GetVariables(config_name) @@ -41,13 +42,18 @@ # TODO: debug these failures. 'SbPlayerTest.MultiPlayer', # crashes ], - # Temporarily disable most of the tests until we can narrow it down to the - # minimum number of cases that are real test failures. 'player_filter_tests': [ - 'VideoDecoderTests/VideoDecoderTest.DecodeFullGOP/0' + # The implementation for the raspberry pi 0 is incomplete and not + # meant to be a reference implementation. As such we will not repair + # these failing tests for now. + 'VideoDecoderTests/VideoDecoderTest.DecodeFullGOP/0', + 'VideoDecoderTests/VideoDecoderTest.HoldFramesUntilFull/0', + 'VideoDecoderTests/VideoDecoderTest.MultipleInputs/0', + 'VideoDecoderTests/VideoDecoderTest.Preroll/0', ] } def CreatePlatformConfig(): - return Raspi0PlatformConfig('raspi-0') + return Raspi0PlatformConfig( + 'raspi-0', sabi_json_path='starboard/sabi/arm/hardfp/v6zk/sabi.json')
diff --git a/src/starboard/raspi/2/configuration_public.h b/src/starboard/raspi/2/configuration_public.h index d840214..e9faada 100644 --- a/src/starboard/raspi/2/configuration_public.h +++ b/src/starboard/raspi/2/configuration_public.h
@@ -20,60 +20,6 @@ #ifndef STARBOARD_RASPI_2_CONFIGURATION_PUBLIC_H_ #define STARBOARD_RASPI_2_CONFIGURATION_PUBLIC_H_ -// --- Architecture Configuration -------------------------------------------- - -// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be -// automatically set based on this. -#define SB_IS_BIG_ENDIAN 0 - -// Whether the current platform is an ARM architecture. -#define SB_IS_ARCH_ARM 1 - -// Whether the current platform is a MIPS architecture. -#define SB_IS_ARCH_MIPS 0 - -// Whether the current platform is a PPC architecture. -#define SB_IS_ARCH_PPC 0 - -// Whether the current platform is an x86 architecture. -#define SB_IS_ARCH_X86 0 - -// Whether the current platform is a 32-bit architecture. -#define SB_IS_32_BIT 1 - -// Whether the current platform is a 64-bit architecture. -#define SB_IS_64_BIT 0 - -// Whether the current platform's pointers are 32-bit. -// Whether the current platform's longs are 32-bit. -#if SB_IS(32_BIT) -#define SB_HAS_32_BIT_POINTERS 1 -#define SB_HAS_32_BIT_LONG 1 -#else -#define SB_HAS_32_BIT_POINTERS 0 -#define SB_HAS_32_BIT_LONG 0 -#endif - -// Whether the current platform's pointers are 64-bit. -// Whether the current platform's longs are 64-bit. -#if SB_IS(64_BIT) -#define SB_HAS_64_BIT_POINTERS 1 -#define SB_HAS_64_BIT_LONG 1 -#else -#define SB_HAS_64_BIT_POINTERS 0 -#define SB_HAS_64_BIT_LONG 0 -#endif - -// Configuration parameters that allow the application to make some general -// compile-time decisions with respect to the the number of cores likely to be -// available on this platform. For a definitive measure, the application should -// still call SbSystemGetNumberOfProcessors at runtime. - -// Whether the current platform's thread scheduler will automatically balance -// threads between cores, as opposed to systems where threads will only ever run -// on the specifically pinned core. -#define SB_HAS_CROSS_CORE_SCHEDULER 1 - #include "starboard/raspi/shared/configuration_public.h" #endif // STARBOARD_RASPI_2_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/raspi/2/gyp_configuration.py b/src/starboard/raspi/2/gyp_configuration.py index 2bd91cb..dd29994 100644 --- a/src/starboard/raspi/2/gyp_configuration.py +++ b/src/starboard/raspi/2/gyp_configuration.py
@@ -18,8 +18,9 @@ class Raspi2PlatformConfig(shared_configuration.RaspiPlatformConfig): - def __init__(self, platform): - super(Raspi2PlatformConfig, self).__init__(platform) + def __init__(self, platform, sabi_json_path=None): + super(Raspi2PlatformConfig, self).__init__( + platform, sabi_json_path=sabi_json_path) def GetVariables(self, config_name): variables = super(Raspi2PlatformConfig, self).GetVariables(config_name) @@ -31,4 +32,5 @@ def CreatePlatformConfig(): - return Raspi2PlatformConfig('raspi-2') + return Raspi2PlatformConfig( + 'raspi-2', sabi_json_path='starboard/sabi/arm/hardfp/sabi.json')
diff --git a/src/starboard/raspi/2/mozjs/gyp_configuration.gypi b/src/starboard/raspi/2/mozjs/gyp_configuration.gypi index 3cf9ab8..4cc3212 100644 --- a/src/starboard/raspi/2/mozjs/gyp_configuration.gypi +++ b/src/starboard/raspi/2/mozjs/gyp_configuration.gypi
@@ -34,5 +34,6 @@ 'includes': [ '../architecture.gypi', '../../shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/sabi/sabi.gypi', ], }
diff --git a/src/starboard/raspi/2/mozjs/gyp_configuration.py b/src/starboard/raspi/2/mozjs/gyp_configuration.py index 79ff824..decc64f 100644 --- a/src/starboard/raspi/2/mozjs/gyp_configuration.py +++ b/src/starboard/raspi/2/mozjs/gyp_configuration.py
@@ -22,8 +22,9 @@ class Raspi2MozjsPlatformConfig(Raspi2PlatformConfig): - def __init__(self, platform): - super(Raspi2MozjsPlatformConfig, self).__init__(platform) + def __init__(self, platform, sabi_json_path=None): + super(Raspi2MozjsPlatformConfig, self).__init__( + platform, sabi_json_path=sabi_json_path) def GetVariables(self, config_name): variables = super(Raspi2MozjsPlatformConfig, self).GetVariables(config_name) @@ -35,4 +36,5 @@ def CreatePlatformConfig(): - return Raspi2MozjsPlatformConfig('raspi-2-mozjs') + return Raspi2MozjsPlatformConfig( + 'raspi-2-mozjs', sabi_json_path='starboard/sabi/arm/hardfp/sabi.json')
diff --git a/src/starboard/raspi/2/skia/gyp_configuration.gypi b/src/starboard/raspi/2/skia/gyp_configuration.gypi index 973b87f..bb5762b 100644 --- a/src/starboard/raspi/2/skia/gyp_configuration.gypi +++ b/src/starboard/raspi/2/skia/gyp_configuration.gypi
@@ -39,5 +39,6 @@ 'includes': [ '../architecture.gypi', '../../shared/gyp_configuration.gypi', + '<(DEPTH)/starboard/sabi/sabi.gypi', ], }
diff --git a/src/starboard/raspi/2/skia/gyp_configuration.py b/src/starboard/raspi/2/skia/gyp_configuration.py index 8ccd3fe..4cb713a 100644 --- a/src/starboard/raspi/2/skia/gyp_configuration.py +++ b/src/starboard/raspi/2/skia/gyp_configuration.py
@@ -19,5 +19,7 @@ Raspi2PlatformConfig = importlib.import_module( 'starboard.raspi.2.gyp_configuration').Raspi2PlatformConfig + def CreatePlatformConfig(): - return Raspi2PlatformConfig('raspi-2-skia') + return Raspi2PlatformConfig( + 'raspi-2-skia', sabi_json_path='starboard/sabi/arm/hardfp/sabi.json')
diff --git a/src/starboard/raspi/shared/application_dispmanx.cc b/src/starboard/raspi/shared/application_dispmanx.cc index 8e6330b..5424fd1 100644 --- a/src/starboard/raspi/shared/application_dispmanx.cc +++ b/src/starboard/raspi/shared/application_dispmanx.cc
@@ -49,7 +49,7 @@ SB_DCHECK(IsDispmanxInitialized()); window_ = new SbWindowPrivate(*display_, options); - input_ = DevInput::Create(window_); + input_.reset(DevInput::Create(window_)); video_renderer_.reset(new DispmanxVideoRenderer(*display_, kVideoLayer)); @@ -63,10 +63,6 @@ SB_DCHECK(IsDispmanxInitialized()); - SB_DCHECK(input_); - delete input_; - input_ = NULL; - SB_DCHECK(window_ == window); delete window; window_ = kSbWindowInvalid; @@ -83,6 +79,25 @@ SbAudioSinkPrivate::TearDown(); } +void ApplicationDispmanx ::OnSuspend() { + // |window_| has not been initialized if Cobalt is in a preloaded state. + if (window_) { + video_renderer_->HideElement(); + + // Destroy the DevInput object so that other processes can access input + // devices while Cobalt is in a suspended state. + input_.reset(); + } +} + +void ApplicationDispmanx::OnResume() { + if (window_) { + input_.reset(DevInput::Create(window_)); + + video_renderer_->ShowElement(); + } +} + void ApplicationDispmanx::AcceptFrame(SbPlayer player, const scoped_refptr<VideoFrame>& frame, int z_index,
diff --git a/src/starboard/raspi/shared/application_dispmanx.h b/src/starboard/raspi/shared/application_dispmanx.h index f07f3c9..a23ff53 100644 --- a/src/starboard/raspi/shared/application_dispmanx.h +++ b/src/starboard/raspi/shared/application_dispmanx.h
@@ -15,6 +15,8 @@ #ifndef STARBOARD_RASPI_SHARED_APPLICATION_DISPMANX_H_ #define STARBOARD_RASPI_SHARED_APPLICATION_DISPMANX_H_ +#include <memory> + #include "starboard/common/scoped_ptr.h" #include "starboard/configuration.h" #include "starboard/raspi/shared/dispmanx_util.h" @@ -33,7 +35,7 @@ class ApplicationDispmanx : public ::starboard::shared::starboard::QueueApplication { public: - ApplicationDispmanx() : window_(kSbWindowInvalid), input_(NULL) {} + ApplicationDispmanx() : window_(kSbWindowInvalid) {} ~ApplicationDispmanx() override {} static ApplicationDispmanx* Get() { @@ -48,6 +50,8 @@ // --- Application overrides --- void Initialize() override; void Teardown() override; + void OnSuspend() override; + void OnResume() override; void AcceptFrame(SbPlayer player, const scoped_refptr<VideoFrame>& frame, int z_index, @@ -85,7 +89,7 @@ SbWindow window_; // The /dev/input input handler. Only set when there is an open window. - ::starboard::shared::dev_input::DevInput* input_; + std::unique_ptr<::starboard::shared::dev_input::DevInput> input_; }; } // namespace shared
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h index 53ac4c6..bbeb085 100644 --- a/src/starboard/raspi/shared/configuration_public.h +++ b/src/starboard/raspi/shared/configuration_public.h
@@ -17,8 +17,21 @@ #ifndef STARBOARD_RASPI_SHARED_CONFIGURATION_PUBLIC_H_ #define STARBOARD_RASPI_SHARED_CONFIGURATION_PUBLIC_H_ -// The API version implemented by this platform. -#define SB_API_VERSION SB_EXPERIMENTAL_API_VERSION +#if SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION +#error \ + "This platform's sabi.json file is expected to track the experimental " \ +"Starboard API version." +#endif // SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION + +// Configuration parameters that allow the application to make some general +// compile-time decisions with respect to the the number of cores likely to be +// available on this platform. For a definitive measure, the application should +// still call SbSystemGetNumberOfProcessors at runtime. + +// Whether the current platform's thread scheduler will automatically balance +// threads between cores, as opposed to systems where threads will only ever run +// on the specifically pinned core. +#define SB_HAS_CROSS_CORE_SCHEDULER 1 // --- System Header Configuration ------------------------------------------- @@ -185,12 +198,6 @@ // textures. These textures typically originate from video decoders. #define SB_HAS_NV12_TEXTURE_SUPPORT 1 -// Whether the current platform should frequently flip their display buffer. -// If this is not required (e.g. SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is set -// to 0), then optimizations where the display buffer is not flipped if the -// scene hasn't changed are enabled. -#define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER 0 - // --- I/O Configuration ----------------------------------------------------- // Whether the current platform implements the on screen keyboard interface. @@ -264,7 +271,9 @@ // Whether this platform has and should use an MMAP function to map physical // memory to the virtual address space. +#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION #define SB_HAS_MMAP 1 +#endif // Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is // required for platforms that want to JIT.
diff --git a/src/starboard/raspi/shared/dispmanx_util.cc b/src/starboard/raspi/shared/dispmanx_util.cc index 3f2fc30..906cfb0 100644 --- a/src/starboard/raspi/shared/dispmanx_util.cc +++ b/src/starboard/raspi/shared/dispmanx_util.cc
@@ -164,6 +164,20 @@ frame_ = video_frame; } +void DispmanxVideoRenderer::HideElement() { + DispmanxResource transparent_resource_; + element_->ChangeSource(transparent_resource_); + + // |frame| != |hidden_frame_| ensures that the call to Update() in + // ShowElement() actually updates the video renderer with the desired video + // frame. + hidden_frame_ = std::move(frame_); +} + +void DispmanxVideoRenderer::ShowElement() { + Update(hidden_frame_); +} + } // namespace shared } // namespace raspi } // namespace starboard
diff --git a/src/starboard/raspi/shared/dispmanx_util.h b/src/starboard/raspi/shared/dispmanx_util.h index 240a663..4556323 100644 --- a/src/starboard/raspi/shared/dispmanx_util.h +++ b/src/starboard/raspi/shared/dispmanx_util.h
@@ -170,9 +170,14 @@ void Update(const scoped_refptr<VideoFrame>& video_frame); + void HideElement(); + void ShowElement(); + private: scoped_ptr<DispmanxElement> element_; scoped_refptr<VideoFrame> frame_; + // Value of |frame_| when HideElement() gets called. + scoped_refptr<VideoFrame> hidden_frame_; // Used to fill the background with black if no video is playing so that the // console does not show through.
diff --git a/src/starboard/raspi/shared/gyp_configuration.gypi b/src/starboard/raspi/shared/gyp_configuration.gypi index f680796..54413a7 100644 --- a/src/starboard/raspi/shared/gyp_configuration.gypi +++ b/src/starboard/raspi/shared/gyp_configuration.gypi
@@ -14,6 +14,10 @@ { 'variables': { + # Override that omits the "data" subdirectory. + # TODO: Remove when omitted for all platforms in base_configuration.gypi. + 'sb_static_contents_output_data_dir': '<(PRODUCT_DIR)/content', + 'target_arch': 'arm', 'target_os': 'linux', @@ -184,4 +188,8 @@ }], ], }, # end of target_defaults + + 'includes': [ + '<(DEPTH)/starboard/sabi/sabi.gypi', + ], }
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py index f25f2a4..2205b26 100644 --- a/src/starboard/raspi/shared/gyp_configuration.py +++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -29,10 +29,11 @@ class RaspiPlatformConfig(platform_configuration.PlatformConfiguration): """Starboard Raspberry Pi platform configuration.""" - def __init__(self, platform): + def __init__(self, platform, sabi_json_path=None): super(RaspiPlatformConfig, self).__init__(platform) self.AppendApplicationConfigurationPath(os.path.dirname(__file__)) self.raspi_home = os.environ.get('RASPI_HOME', _UNDEFINED_RASPI_HOME) + self.sabi_json_path = sabi_json_path self.sysroot = os.path.realpath(os.path.join(self.raspi_home, 'sysroot')) def GetBuildFormat(self): @@ -47,6 +48,9 @@ variables.update({ 'clang': 0, 'sysroot': self.sysroot, + 'include_path_platform_deploy_gypi': + 'starboard/raspi/shared/platform_deploy.gypi', + 'STRIP': os.environ.get('STRIP') }) return variables @@ -62,6 +66,7 @@ env_variables.update({ 'CC': os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-gcc'), 'CXX': os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-g++'), + 'STRIP': os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-strip'), }) return env_variables @@ -91,24 +96,18 @@ filters.extend(test_filter.TestFilter(target, test) for test in tests) return filters - __FILTERED_TESTS = { + __FILTERED_TESTS = { # pylint: disable=invalid-name 'nplb': [ 'SbDrmTest.AnySupportedKeySystems', - # The RasPi test devices don't have access to an IPV6 network, so - # disable the related tests. - 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest' - '.SunnyDayDestination/1', - 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest' - '.SunnyDaySourceForDestination/1', - 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest' - '.SunnyDaySourceNotLoopback/1', ], 'player_filter_tests': [ - # TODO: debug these failures. + # The implementations for the raspberry pi (0 and 2) are incomplete + # and not meant to be a reference implementation. As such we will + # not repair these failing tests for now. 'VideoDecoderTests/VideoDecoderTest.EndOfStreamWithoutAnyInput/0', 'VideoDecoderTests/VideoDecoderTest.MultipleResets/0', - 'VideoDecoderTests/VideoDecoderTest' - '.MultipleValidInputsAfterInvalidKeyFrame/*', - 'VideoDecoderTests/VideoDecoderTest.MultipleInvalidInput/*', ], } + + def GetPathToSabiJsonFile(self): + return self.sabi_json_path
diff --git a/src/starboard/raspi/shared/launcher.py b/src/starboard/raspi/shared/launcher.py index 965521a..8533926 100644 --- a/src/starboard/raspi/shared/launcher.py +++ b/src/starboard/raspi/shared/launcher.py
@@ -44,7 +44,7 @@ class Launcher(abstract_launcher.AbstractLauncher): """Class for launching Cobalt/tools on Raspi.""" - _STARTUP_TIMEOUT_SECONDS = 1200 + _STARTUP_TIMEOUT_SECONDS = 1800 _RASPI_USERNAME = 'pi' _RASPI_PASSWORD = 'raspberry' @@ -91,20 +91,24 @@ def _InitPexpectCommands(self): """Initializes all of the pexpect commands needed for running the test.""" - test_path = self.GetTargetPath() + test_dir = os.path.join(self.out_directory, 'deploy', self.target_name) + test_file = self.target_name + + test_path = os.path.join(test_dir, test_file) if not os.path.isfile(test_path): raise ValueError('TargetPath ({}) must be a file.'.format(test_path)) - test_dir_path, test_file = os.path.split(test_path) - test_base_dir = os.path.basename(os.path.normpath(test_dir_path)) - raspi_user_hostname = Launcher._RASPI_USERNAME + '@' + self.device_id - raspi_test_path = os.path.join(test_base_dir, test_file) + + # Use the basename of the out directory as a common directory on the device + # so content can be reused for several targets w/o re-syncing for each one. + raspi_test_dir = os.path.basename(self.out_directory) + raspi_test_path = os.path.join(raspi_test_dir, test_file) # rsync command setup - options = '-avzLh --exclude obj/ --exclude obj.host/ --exclude gen/' - source = test_dir_path - destination = raspi_user_hostname + ':~/' + options = '-avzLh' + source = test_dir + '/' + destination = '{}:~/{}/'.format(raspi_user_hostname, raspi_test_dir) self.rsync_command = 'rsync ' + options + ' ' + source + ' ' + destination # ssh command setup @@ -138,6 +142,7 @@ command: The command to use when spawning the pexpect process. """ + logging.info('executing: %s', command) self.pexpect_process = pexpect.spawn( command, timeout=Launcher._PEXPECT_TIMEOUT) retry_count = 0
diff --git a/src/starboard/raspi/shared/media_is_video_supported.cc b/src/starboard/raspi/shared/media_is_video_supported.cc index 03c9b63..9f8ec09 100644 --- a/src/starboard/raspi/shared/media_is_video_supported.cc +++ b/src/starboard/raspi/shared/media_is_video_supported.cc
@@ -18,18 +18,18 @@ #include "starboard/media.h" #include "starboard/shared/starboard/media/media_util.h" -SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, - int frame_width, - int frame_height, - int64_t bitrate, - int fps, - bool decode_to_texture_required) { +bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required) { SB_UNREFERENCED_PARAMETER(profile); SB_UNREFERENCED_PARAMETER(level);
diff --git a/src/starboard/raspi/shared/platform_deploy.gypi b/src/starboard/raspi/shared/platform_deploy.gypi new file mode 100644 index 0000000..098a22c --- /dev/null +++ b/src/starboard/raspi/shared/platform_deploy.gypi
@@ -0,0 +1,36 @@ +# Copyright 2019 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. +{ + 'variables': { + 'executable_file': '<(PRODUCT_DIR)/<(executable_name)', + 'deploy_executable_file': '<(target_deploy_dir)/<(executable_name)', + }, + 'includes': [ '<(DEPTH)/starboard/build/collect_deploy_content.gypi' ], + 'actions': [ + { + 'action_name': 'deploy_executable', + 'message': 'Strip executable: <(deploy_executable_file)', + 'inputs': [ + '<(executable_file)', + '<(content_deploy_stamp_file)', + ], + 'outputs': [ '<(deploy_executable_file)' ], + 'action': [ + '<(STRIP)', + '-o', '<(deploy_executable_file)', + '<(executable_file)', + ], + }, + ], +}
diff --git a/src/starboard/raspi/shared/starboard_platform.gypi b/src/starboard/raspi/shared/starboard_platform.gypi index beadef6..17498ec 100644 --- a/src/starboard/raspi/shared/starboard_platform.gypi +++ b/src/starboard/raspi/shared/starboard_platform.gypi
@@ -14,6 +14,7 @@ { 'includes': [ '<(DEPTH)/starboard/shared/starboard/player/filter/player_filter.gypi', + '<(DEPTH)/starboard/stub/blitter_stub_sources.gypi', ], 'variables': { 'sb_pedantic_warnings': 1, @@ -38,6 +39,7 @@ 'target_name': 'starboard_platform', 'type': 'static_library', 'sources': [ + '<@(blitter_stub_sources)', '<@(filter_based_player_sources)', '<(DEPTH)/starboard/linux/shared/atomic_public.h', '<(DEPTH)/starboard/linux/shared/configuration_public.h', @@ -160,6 +162,7 @@ '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc', '<(DEPTH)/starboard/shared/nouser/user_internal.cc', '<(DEPTH)/starboard/shared/posix/directory_create.cc', + '<(DEPTH)/starboard/shared/posix/file_atomic_replace.cc', '<(DEPTH)/starboard/shared/posix/file_can_open.cc', '<(DEPTH)/starboard/shared/posix/file_close.cc', '<(DEPTH)/starboard/shared/posix/file_delete.cc', @@ -191,6 +194,7 @@ '<(DEPTH)/starboard/shared/posix/socket_internal.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected.cc', '<(DEPTH)/starboard/shared/posix/socket_is_connected_and_idle.cc', + '<(DEPTH)/starboard/shared/posix/socket_is_ipv6_supported.cc', '<(DEPTH)/starboard/shared/posix/socket_join_multicast_group.cc', '<(DEPTH)/starboard/shared/posix/socket_listen.cc', '<(DEPTH)/starboard/shared/posix/socket_receive_from.cc', @@ -219,6 +223,7 @@ '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc', '<(DEPTH)/starboard/shared/posix/time_get_now.cc', + '<(DEPTH)/starboard/shared/posix/time_is_time_thread_now_supported.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc', '<(DEPTH)/starboard/shared/posix/time_zone_get_name.cc', '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc', @@ -257,6 +262,7 @@ '<(DEPTH)/starboard/shared/signal/crash_signals.h', '<(DEPTH)/starboard/shared/signal/suspend_signals.cc', '<(DEPTH)/starboard/shared/signal/suspend_signals.h', + '<(DEPTH)/starboard/shared/signal/system_request_suspend.cc', '<(DEPTH)/starboard/shared/starboard/application.cc', '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc', '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc', @@ -275,6 +281,8 @@ '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc', '<(DEPTH)/starboard/shared/starboard/event_cancel.cc', '<(DEPTH)/starboard/shared/starboard/event_schedule.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.cc', + '<(DEPTH)/starboard/shared/starboard/file_atomic_replace_write_file.h', '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc', '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc', @@ -348,10 +356,10 @@ '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc', '<(DEPTH)/starboard/shared/starboard/system_request_pause.cc', '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc', - '<(DEPTH)/starboard/shared/starboard/system_request_suspend.cc', '<(DEPTH)/starboard/shared/starboard/system_request_unpause.cc', '<(DEPTH)/starboard/shared/starboard/system_supports_resume.cc', '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc', + '<(DEPTH)/starboard/shared/stub/accessibility_get_caption_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_display_settings.cc', '<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc', '<(DEPTH)/starboard/shared/stub/cryptography_create_transformer.cc', @@ -377,6 +385,15 @@ '<(DEPTH)/starboard/shared/stub/microphone_is_sample_rate_supported.cc', '<(DEPTH)/starboard/shared/stub/microphone_open.cc', '<(DEPTH)/starboard/shared/stub/microphone_read.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_cancel.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_create.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_destroy.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_start.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_stop.cc', + '<(DEPTH)/starboard/shared/stub/speech_synthesis_cancel.cc', + '<(DEPTH)/starboard/shared/stub/speech_synthesis_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/speech_synthesis_speak.cc', '<(DEPTH)/starboard/shared/stub/system_get_extensions.cc', '<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc', '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc', @@ -384,7 +401,17 @@ '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', '<(DEPTH)/starboard/shared/stub/system_sign_with_certification_secret_key.cc', '<(DEPTH)/starboard/shared/stub/ui_nav_get_interface.cc', + '<(DEPTH)/starboard/shared/stub/window_blur_on_screen_keyboard.cc', + '<(DEPTH)/starboard/shared/stub/window_focus_on_screen_keyboard.cc', '<(DEPTH)/starboard/shared/stub/window_get_diagonal_size_in_inches.cc', + '<(DEPTH)/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc', + '<(DEPTH)/starboard/shared/stub/window_hide_on_screen_keyboard.cc', + '<(DEPTH)/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc', + '<(DEPTH)/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc', + '<(DEPTH)/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc', + '<(DEPTH)/starboard/shared/stub/window_show_on_screen_keyboard.cc', + '<(DEPTH)/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc', ], 'defines': [ # This must be defined when building Starboard, and must not when
diff --git a/src/starboard/sabi/arm/hardfp/sabi.json b/src/starboard/sabi/arm/hardfp/sabi.json new file mode 100644 index 0000000..d65b551 --- /dev/null +++ b/src/starboard/sabi/arm/hardfp/sabi.json
@@ -0,0 +1,32 @@ +{ + "variables": { + "sb_api_version": 12, + "target_arch": "arm", + "target_arch_sub": "v7a", + "word_size": 32, + "endianness": "little", + "calling_convention": "eabi", + "floating_point_abi": "hard", + "floating_point_fpu": "vfpv3", + "signedness_of_char": "signed", + "signedness_of_enum": "signed", + "alignment_char": 1, + "alignment_double": 8, + "alignment_float": 4, + "alignment_int": 4, + "alignment_llong": 8, + "alignment_long": 4, + "alignment_pointer": 4, + "alignment_short": 2, + "size_of_char": 1, + "size_of_enum": 4, + "size_of_double": 8, + "size_of_float": 4, + "size_of_int": 4, + "size_of_llong": 8, + "size_of_long": 4, + "size_of_pointer": 4, + "size_of_short": 2 + } +} +
diff --git a/src/starboard/sabi/arm/hardfp/v6zk/sabi.json b/src/starboard/sabi/arm/hardfp/v6zk/sabi.json new file mode 100644 index 0000000..4502f3f --- /dev/null +++ b/src/starboard/sabi/arm/hardfp/v6zk/sabi.json
@@ -0,0 +1,32 @@ +{ + "variables": { + "sb_api_version": 12, + "target_arch": "arm", + "target_arch_sub": "v6zk", + "word_size": 32, + "endianness": "little", + "calling_convention": "eabi", + "floating_point_abi": "hard", + "floating_point_fpu": "vfpv2", + "signedness_of_char": "signed", + "signedness_of_enum": "signed", + "alignment_char": 1, + "alignment_double": 8, + "alignment_float": 4, + "alignment_int": 4, + "alignment_llong": 8, + "alignment_long": 4, + "alignment_pointer": 4, + "alignment_short": 2, + "size_of_char": 1, + "size_of_enum": 4, + "size_of_double": 8, + "size_of_float": 4, + "size_of_int": 4, + "size_of_llong": 8, + "size_of_long": 4, + "size_of_pointer": 4, + "size_of_short": 2 + } +} +
diff --git a/src/starboard/sabi/arm/softfp/sabi.json b/src/starboard/sabi/arm/softfp/sabi.json new file mode 100644 index 0000000..ce2b3de --- /dev/null +++ b/src/starboard/sabi/arm/softfp/sabi.json
@@ -0,0 +1,32 @@ +{ + "variables": { + "sb_api_version": 12, + "target_arch": "arm", + "target_arch_sub": "v7a", + "word_size": 32, + "endianness": "little", + "calling_convention": "eabi", + "floating_point_abi": "softfp", + "floating_point_fpu": "vfpv3", + "signedness_of_char": "signed", + "signedness_of_enum": "signed", + "alignment_char": 1, + "alignment_double": 8, + "alignment_float": 4, + "alignment_int": 4, + "alignment_llong": 8, + "alignment_long": 4, + "alignment_pointer": 4, + "alignment_short": 2, + "size_of_char": 1, + "size_of_enum": 4, + "size_of_double": 8, + "size_of_float": 4, + "size_of_int": 4, + "size_of_llong": 8, + "size_of_long": 4, + "size_of_pointer": 4, + "size_of_short": 2 + } +} +
diff --git a/src/starboard/sabi/arm64/sabi.json b/src/starboard/sabi/arm64/sabi.json new file mode 100644 index 0000000..09cb005 --- /dev/null +++ b/src/starboard/sabi/arm64/sabi.json
@@ -0,0 +1,32 @@ +{ + "variables": { + "sb_api_version": 12, + "target_arch": "arm64", + "target_arch_sub": "v8a", + "word_size": 64, + "endianness": "little", + "calling_convention": "aarch64", + "floating_point_abi": "", + "floating_point_fpu": "", + "signedness_of_char": "signed", + "signedness_of_enum": "signed", + "alignment_char": 1, + "alignment_double": 8, + "alignment_float": 4, + "alignment_int": 4, + "alignment_llong": 8, + "alignment_long": 8, + "alignment_pointer": 8, + "alignment_short": 2, + "size_of_char": 1, + "size_of_enum": 4, + "size_of_double": 8, + "size_of_float": 4, + "size_of_int": 4, + "size_of_llong": 8, + "size_of_long": 8, + "size_of_pointer": 8, + "size_of_short": 2 + } +} +
diff --git a/src/starboard/sabi/default/sabi.json b/src/starboard/sabi/default/sabi.json new file mode 100644 index 0000000..db0c403 --- /dev/null +++ b/src/starboard/sabi/default/sabi.json
@@ -0,0 +1,4 @@ +{ + "sabi_warning": "Including this file results in default values for the Starboard ABI." +} +
diff --git a/src/starboard/sabi/ia32/sabi.json b/src/starboard/sabi/ia32/sabi.json new file mode 100644 index 0000000..3638ec1 --- /dev/null +++ b/src/starboard/sabi/ia32/sabi.json
@@ -0,0 +1,32 @@ +{ + "variables": { + "sb_api_version": 12, + "target_arch": "ia32", + "target_arch_sub": "", + "word_size": 32, + "endianness": "little", + "calling_convention": "sysv", + "floating_point_abi": "", + "floating_point_fpu": "", + "signedness_of_char": "signed", + "signedness_of_enum": "signed", + "alignment_char": 1, + "alignment_double": 8, + "alignment_float": 4, + "alignment_int": 4, + "alignment_llong": 8, + "alignment_long": 4, + "alignment_pointer": 4, + "alignment_short": 2, + "size_of_char": 1, + "size_of_enum": 4, + "size_of_double": 8, + "size_of_float": 4, + "size_of_int": 4, + "size_of_llong": 8, + "size_of_long": 4, + "size_of_pointer": 4, + "size_of_short": 2 + } +} +
diff --git a/src/starboard/sabi/sabi.gypi b/src/starboard/sabi/sabi.gypi new file mode 100644 index 0000000..870adbb --- /dev/null +++ b/src/starboard/sabi/sabi.gypi
@@ -0,0 +1,147 @@ +# Copyright 2019 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. + +# Starboard Application Binary Interface +# +# This file is [mostly] platform-agnostic and translates the set of ABI +# variables, which should be overridden by each Evergreen platform, into build +# time defines. + +{ + 'variables': { + # Default ABI variables + 'sb_api_version%': 0, + 'target_arch%': '', + 'target_arch_sub%': '', + 'word_size%': 0, + 'endianness%': '', + 'calling_convention%': '', + 'floating_point_abi%': '', + 'floating_point_fpu%': '', + 'signedness_of_char%': '', + 'signedness_of_enum%': '', + 'alignment_char%': 0, + 'alignment_double%': 0, + 'alignment_float%': 0, + 'alignment_int%': 0, + 'alignment_llong%': 0, + 'alignment_long%': 0, + 'alignment_pointer%': 0, + 'alignment_short%': 0, + 'size_of_char%': 0, + 'size_of_enum%': 0, + 'size_of_double%': 0, + 'size_of_float%': 0, + 'size_of_int%': 0, + 'size_of_llong%': 0, + 'size_of_long%': 0, + 'size_of_pointer%': 0, + 'size_of_short%': 0, + + # arm and arm64 + 'conditions': [ + ['target_arch=="arm" or target_arch=="arm64"', { + 'arm_float_abi': '<(floating_point_abi)', + 'arm_fpu': '<(floating_point_fpu)', + + 'conditions': [ + ['target_arch_sub=="v6zk"', { + 'arm_version': 6, + 'armv7': 0, + }], + ['target_arch_sub=="v7a"', { + 'arm_version': 7, + 'armv7': 1, + }], + ['target_arch_sub=="v8a"', { + 'arm_version': 8, + 'armv7': 0, + }], + ], + }], + ], + }, + 'target_defaults': { + 'defines': [ + 'SB_API_VERSION=<(sb_api_version)', + + # Inlined Python used to capitalize the variable values. + 'SB_IS_ARCH_<!(python -c "print(\'<(target_arch)\'.upper())")=1', + 'SB_HAS_<!(python -c "print(\'<(calling_convention)\'.upper())")_CALLING=1', + 'SB_HAS_<!(python -c "print(\'<(floating_point_abi)\'.upper())")_FLOATS=1', + + 'SB_IS_<(word_size)_BIT=1', + 'SB_ALIGNMENT_OF_CHAR=<(alignment_char)', + 'SB_ALIGNMENT_OF_DOUBLE=<(alignment_double)', + 'SB_ALIGNMENT_OF_FLOAT=<(alignment_float)', + 'SB_ALIGNMENT_OF_INT=<(alignment_int)', + 'SB_ALIGNMENT_OF_LLONG=<(alignment_llong)', + 'SB_ALIGNMENT_OF_LONG=<(alignment_long)', + 'SB_ALIGNMENT_OF_POINTER=<(alignment_pointer)', + 'SB_ALIGNMENT_OF_SHORT=<(alignment_short)', + 'SB_SIZE_OF_CHAR=<(size_of_char)', + 'SB_SIZE_OF_ENUM=<(size_of_enum)', + 'SB_SIZE_OF_DOUBLE=<(size_of_double)', + 'SB_SIZE_OF_FLOAT=<(size_of_float)', + 'SB_SIZE_OF_INT=<(size_of_int)', + 'SB_SIZE_OF_LONG=<(size_of_long)', + 'SB_SIZE_OF_LLONG=<(size_of_llong)', + 'SB_SIZE_OF_POINTER=<(size_of_pointer)', + 'SB_SIZE_OF_SHORT=<(size_of_short)', + ], + 'conditions': [ + ['endianness=="little"', { + 'defines': ['SB_IS_BIG_ENDIAN=0'], + }, { + 'defines': ['SB_IS_BIG_ENDIAN=1'], + }], + ['signedness_of_char=="signed"', { + 'defines': ['SB_HAS_SIGNED_CHAR=1'], + }, { + 'defines': ['SB_HAS_SIGNED_CHAR=0'], + }], + ['signedness_of_enum=="signed"', { + 'defines': ['SB_HAS_SIGNED_ENUM=1'], + }, { + 'defines': ['SB_HAS_SIGNED_ENUM=0'], + }], + # TODO: Remove when all platforms have adopted the ABI manifest. + ['size_of_pointer==4', { + 'defines': ['SB_HAS_32_BIT_POINTERS=1'], + }, { + 'defines': ['SB_HAS_64_BIT_POINTERS=1'], + }], + # TODO: Remove when all platforms have adopted the ABI manifest. + ['size_of_long==4', { + 'defines': ['SB_HAS_32_BIT_LONG=1'], + }, { + 'defines': ['SB_HAS_64_BIT_LONG=1'], + }], + # TODO: Remove when all platforms have adopted the ABI manifest. + ['target_arch=="arm64"', { + 'defines': ['SB_IS_ARCH_ARM=1'], + }], + # TODO: Remove when all platforms have adopted the ABI manifest. + ['target_arch=="x64" or target_arch=="ia32"', { + 'defines': ['SB_IS_ARCH_X86=1'], + }], + ], + }, + 'includes': [ + # This JSON file also happens to be valid GYP configuration language so we + # include it here. Slightly hacky, highly effective. + '<(DEPTH)/<(sabi_json_path)', + ], +} +
diff --git a/src/starboard/sabi/x64/sysv/sabi.json b/src/starboard/sabi/x64/sysv/sabi.json new file mode 100644 index 0000000..9b197cd --- /dev/null +++ b/src/starboard/sabi/x64/sysv/sabi.json
@@ -0,0 +1,32 @@ +{ + "variables": { + "sb_api_version": 12, + "target_arch": "x64", + "target_arch_sub": "", + "word_size": 64, + "endianness": "little", + "calling_convention": "sysv", + "floating_point_abi": "", + "floating_point_fpu": "", + "signedness_of_char": "signed", + "signedness_of_enum": "signed", + "alignment_char": 1, + "alignment_double": 8, + "alignment_float": 4, + "alignment_int": 4, + "alignment_llong": 8, + "alignment_long": 8, + "alignment_pointer": 8, + "alignment_short": 2, + "size_of_char": 1, + "size_of_enum": 4, + "size_of_double": 8, + "size_of_float": 4, + "size_of_int": 4, + "size_of_llong": 8, + "size_of_long": 8, + "size_of_pointer": 8, + "size_of_short": 2 + } +} +
diff --git a/src/starboard/sabi/x64/windows/sabi.json b/src/starboard/sabi/x64/windows/sabi.json new file mode 100644 index 0000000..99b6acd --- /dev/null +++ b/src/starboard/sabi/x64/windows/sabi.json
@@ -0,0 +1,32 @@ +{ + "variables": { + "sb_api_version": 12, + "target_arch": "x64", + "target_arch_sub": "", + "word_size": 64, + "endianness": "little", + "calling_convention": "windows", + "floating_point_abi": "", + "floating_point_fpu": "", + "signedness_of_char": "signed", + "signedness_of_enum": "signed", + "alignment_char": 1, + "alignment_double": 8, + "alignment_float": 4, + "alignment_int": 4, + "alignment_llong": 8, + "alignment_long": 4, + "alignment_pointer": 8, + "alignment_short": 2, + "size_of_char": 1, + "size_of_double": 8, + "size_of_enum": 4, + "size_of_float": 4, + "size_of_int": 4, + "size_of_llong": 8, + "size_of_long": 4, + "size_of_pointer": 8, + "size_of_short": 2 + } +} +
diff --git a/src/starboard/shared/blittergles/blitter_create_default_device.cc b/src/starboard/shared/blittergles/blitter_create_default_device.cc index 8435118..41bb497 100644 --- a/src/starboard/shared/blittergles/blitter_create_default_device.cc +++ b/src/starboard/shared/blittergles/blitter_create_default_device.cc
@@ -15,6 +15,7 @@ #include "starboard/blitter.h" #include <EGL/egl.h> +#include <sanitizer/lsan_interface.h> #include <memory> @@ -96,13 +97,27 @@ SbBlitterDestroySurface(dummy_surface); } +#if defined ADDRESS_SANITIZER + +class ScopedLeakSanitizerDisabler { + public: + ScopedLeakSanitizerDisabler() { __lsan_disable(); } + ~ScopedLeakSanitizerDisabler() { __lsan_enable(); } +}; +#define ANNOTATE_SCOPED_MEMORY_LEAK \ + ScopedLeakSanitizerDisabler leak_sanitizer_disabler; static_cast<void>(0) + +#else + +#define ANNOTATE_SCOPED_MEMORY_LEAK ((void)0) + +#endif } // namespace SbBlitterDevice SbBlitterCreateDefaultDevice() { starboard::shared::blittergles::SbBlitterDeviceRegistry* device_registry = starboard::shared::blittergles::GetBlitterDeviceRegistry(); starboard::ScopedLock lock(device_registry->mutex); - if (device_registry->default_device) { SB_DLOG(ERROR) << ": Default device has already been created."; return kSbBlitterInvalidDevice; @@ -115,9 +130,14 @@ return kSbBlitterInvalidDevice; } - if (!eglInitialize(device->display, NULL, NULL)) { - SB_DLOG(ERROR) << ": Failed to initialize device."; - return kSbBlitterInvalidDevice; + { + // Despite eglTerminate() being used in SbBlitterDestroyDevice(), the + // current mesa egl drivers still leak memory. + ANNOTATE_SCOPED_MEMORY_LEAK; + if (!eglInitialize(device->display, NULL, NULL)) { + SB_DLOG(ERROR) << ": Failed to initialize device."; + return kSbBlitterInvalidDevice; + } } starboard::optional<EGLConfig> config = GetEGLConfig(device->display);
diff --git a/src/starboard/shared/blittergles/blitter_destroy_swap_chain.cc b/src/starboard/shared/blittergles/blitter_destroy_swap_chain.cc index 8eb0f30..3c3d6ec 100644 --- a/src/starboard/shared/blittergles/blitter_destroy_swap_chain.cc +++ b/src/starboard/shared/blittergles/blitter_destroy_swap_chain.cc
@@ -20,7 +20,7 @@ #include "starboard/common/recursive_mutex.h" #include "starboard/shared/blittergles/blitter_internal.h" -SB_EXPORT bool SbBlitterDestroySwapChain(SbBlitterSwapChain swap_chain) { +bool SbBlitterDestroySwapChain(SbBlitterSwapChain swap_chain) { if (!SbBlitterIsSwapChainValid(swap_chain)) { SB_DLOG(ERROR) << ": Invalid swap chain."; return false;
diff --git a/src/starboard/shared/blittergles/blitter_is_blitter_supported.cc b/src/starboard/shared/blittergles/blitter_is_blitter_supported.cc new file mode 100644 index 0000000..0a6e9e9 --- /dev/null +++ b/src/starboard/shared/blittergles/blitter_is_blitter_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterIsBlitterSupported() { + return true; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc b/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc index 94b4497..7d3079e 100644 --- a/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc +++ b/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc
@@ -18,7 +18,7 @@ #include "starboard/common/log.h" #include "starboard/shared/directfb/blitter_internal.h" -SB_EXPORT bool SbBlitterDestroySwapChain(SbBlitterSwapChain swap_chain) { +bool SbBlitterDestroySwapChain(SbBlitterSwapChain swap_chain) { if (!SbBlitterIsSwapChainValid(swap_chain)) { SB_DLOG(ERROR) << __FUNCTION__ << ": Invalid swap chain."; return false;
diff --git a/src/starboard/shared/directfb/blitter_is_blitter_supported.cc b/src/starboard/shared/directfb/blitter_is_blitter_supported.cc new file mode 100644 index 0000000..0a6e9e9 --- /dev/null +++ b/src/starboard/shared/directfb/blitter_is_blitter_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterIsBlitterSupported() { + return true; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/dlmalloc/page_internal.h b/src/starboard/shared/dlmalloc/page_internal.h index 100a1d2..b792207 100644 --- a/src/starboard/shared/dlmalloc/page_internal.h +++ b/src/starboard/shared/dlmalloc/page_internal.h
@@ -65,10 +65,10 @@ // Platforms that have OS support for the virtual region ("MORECORE") behavior // will enable SB_HAS_VIRTUAL_REGIONS in configuration_public.h. // -// Platforms that support SbMap() must enable SB_HAS_MMAP in their -// configuration_public.h file. dlmalloc is very flexible and if a platform -// can't implement virtual regions, it will use Map() for all allocations, -// merging adjacent allocations when it can. +// Platforms that support SbMap() must be at least starboard version 12 or +// enable SB_HAS_MMAP in their configuration_public.h file. dlmalloc is very +// flexible and if a platform can't implement virtual regions, it will use +// Map() for all allocations, merging adjacent allocations when it can. // // If a platform can't use Map(), it will just use MORECORE for everything. // Currently we believe a mixture of both provides best behavior, but more @@ -105,7 +105,7 @@ size_t SbPageGetVirtualRegionSize(); #endif -#if SB_HAS(MMAP) +#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) // Allocates |size_bytes| worth of physical memory pages and maps them into an // available virtual region. On some platforms, |name| appears in the debugger // and can be up to 32 bytes. Returns SB_MEMORY_MAP_FAILED on failure, as NULL @@ -135,7 +135,7 @@ // |virtual_address|, to |flags|, returning |true| on success. bool SbPageProtect(void* virtual_address, int64_t size_bytes, int flags); #endif -#endif // SB_HAS(MMAP) +#endif // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) // Returns the total amount, in bytes, of physical memory available. Should // always be a multiple of SB_MEMORY_PAGE_SIZE.
diff --git a/src/starboard/shared/egl/system_egl.cc b/src/starboard/shared/egl/system_egl.cc index 68248ec..4837c35 100644 --- a/src/starboard/shared/egl/system_egl.cc +++ b/src/starboard/shared/egl/system_egl.cc
@@ -17,6 +17,8 @@ #include "starboard/egl.h" +#if SB_API_VERSION >= 11 + #if !defined(EGL_VERSION_1_0) || !defined(EGL_VERSION_1_1) || \ !defined(EGL_VERSION_1_2) || !defined(EGL_VERSION_1_3) || \ !defined(EGL_VERSION_1_4) @@ -110,3 +112,5 @@ const SbEglInterface* SbGetEglInterface() { return &g_sb_egl_interface; } + +#endif // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc index 246fd2a..8fe9577 100644 --- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc +++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc
@@ -200,7 +200,7 @@ } scoped_refptr<AudioDecoderImpl<FFMPEG>::DecodedAudio> -AudioDecoderImpl<FFMPEG>::Read() { +AudioDecoderImpl<FFMPEG>::Read(int* samples_per_second) { SB_DCHECK(BelongsToCurrentThread()); SB_DCHECK(output_cb_); SB_DCHECK(!decoded_audios_.empty()); @@ -210,6 +210,7 @@ result = decoded_audios_.front(); decoded_audios_.pop(); } + *samples_per_second = audio_sample_info_.samples_per_second; return result; } @@ -260,10 +261,6 @@ return kSbMediaAudioFrameStorageTypeInterleaved; } -int AudioDecoderImpl<FFMPEG>::GetSamplesPerSecond() const { - return audio_sample_info_.samples_per_second; -} - void AudioDecoderImpl<FFMPEG>::InitializeCodec() { codec_context_ = ffmpeg_->avcodec_alloc_context3(NULL);
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.h b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.h index 476de60..e917ec8 100644 --- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.h +++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.h
@@ -55,13 +55,13 @@ void Decode(const scoped_refptr<InputBuffer>& input_buffer, const ConsumedCB& consumed_cb) override; void WriteEndOfStream() override; - scoped_refptr<DecodedAudio> Read() override; + scoped_refptr<DecodedAudio> Read(int* samples_per_second) override; void Reset() override; - SbMediaAudioSampleType GetSampleType() const override; - SbMediaAudioFrameStorageType GetStorageType() const override; - int GetSamplesPerSecond() const override; private: + SbMediaAudioSampleType GetSampleType() const; + SbMediaAudioFrameStorageType GetStorageType() const; + void InitializeCodec(); void TeardownCodec();
diff --git a/src/starboard/shared/gles/system_gles2.cc b/src/starboard/shared/gles/system_gles2.cc index a0ccae9..fe8d181 100644 --- a/src/starboard/shared/gles/system_gles2.cc +++ b/src/starboard/shared/gles/system_gles2.cc
@@ -17,6 +17,8 @@ #include "starboard/gles.h" +#if SB_API_VERSION >= 11 + namespace { const SbGlesInterface g_sb_gles_interface = { @@ -273,3 +275,5 @@ const SbGlesInterface* SbGetGlesInterface() { return &g_sb_gles_interface; } + +#endif // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/libaom/aom_video_decoder.cc b/src/starboard/shared/libaom/aom_video_decoder.cc index f75f816..f2caac4 100644 --- a/src/starboard/shared/libaom/aom_video_decoder.cc +++ b/src/starboard/shared/libaom/aom_video_decoder.cc
@@ -240,7 +240,8 @@ } } - if (aom_image->bit_depth != 8 && aom_image->bit_depth != 10) { + if (aom_image->bit_depth != 8 && aom_image->bit_depth != 10 && + aom_image->bit_depth != 12) { SB_DLOG(ERROR) << "Unsupported bit depth " << aom_image->bit_depth; ReportError( FormatString("Unsupported bit depth %d.", aom_image->bit_depth));
diff --git a/src/starboard/shared/libde265/de265_video_decoder.cc b/src/starboard/shared/libde265/de265_video_decoder.cc index 13db895..619f962 100644 --- a/src/starboard/shared/libde265/de265_video_decoder.cc +++ b/src/starboard/shared/libde265/de265_video_decoder.cc
@@ -249,7 +249,7 @@ int strides[kImagePlanes]; auto bit_depth = de265_get_bits_per_pixel(image, 0); - if (bit_depth != 8 && bit_depth != 10) { + if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) { SB_DLOG(ERROR) << "Unsupported bit depth " << bit_depth; ReportError(FormatString("Unsupported bit depth %d.", bit_depth)); return;
diff --git a/src/starboard/shared/libvpx/vpx_video_decoder.cc b/src/starboard/shared/libvpx/vpx_video_decoder.cc index 1a1029b..9cb5253 100644 --- a/src/starboard/shared/libvpx/vpx_video_decoder.cc +++ b/src/starboard/shared/libvpx/vpx_video_decoder.cc
@@ -238,7 +238,8 @@ } } - if (vpx_image->bit_depth != 8 && vpx_image->bit_depth != 10) { + if (vpx_image->bit_depth != 8 && vpx_image->bit_depth != 10 && + vpx_image->bit_depth != 12) { SB_DLOG(ERROR) << "Unsupported bit depth " << vpx_image->bit_depth; ReportError( FormatString("Unsupported bit depth %d.", vpx_image->bit_depth));
diff --git a/src/starboard/shared/opus/opus_audio_decoder.cc b/src/starboard/shared/opus/opus_audio_decoder.cc index a6bf83e..04dd0a6 100644 --- a/src/starboard/shared/opus/opus_audio_decoder.cc +++ b/src/starboard/shared/opus/opus_audio_decoder.cc
@@ -142,8 +142,8 @@ } scoped_refptr<DecodedAudio> decoded_audio = new DecodedAudio( - audio_sample_info_.number_of_channels, GetSampleType(), GetStorageType(), - input_buffer->timestamp(), + audio_sample_info_.number_of_channels, GetSampleType(), + kSbMediaAudioFrameStorageTypeInterleaved, input_buffer->timestamp(), audio_sample_info_.number_of_channels * decoded_frames * starboard::media::GetBytesPerSample(GetSampleType())); SbMemoryCopy(decoded_audio->buffer(), working_buffer_.data(), @@ -165,7 +165,8 @@ Schedule(output_cb_); } -scoped_refptr<OpusAudioDecoder::DecodedAudio> OpusAudioDecoder::Read() { +scoped_refptr<OpusAudioDecoder::DecodedAudio> OpusAudioDecoder::Read( + int* samples_per_second) { SB_DCHECK(BelongsToCurrentThread()); SB_DCHECK(output_cb_); SB_DCHECK(!decoded_audios_.empty()); @@ -175,6 +176,7 @@ result = decoded_audios_.front(); decoded_audios_.pop(); } + *samples_per_second = audio_sample_info_.samples_per_second; return result; } @@ -202,15 +204,6 @@ #endif // SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES) } -SbMediaAudioFrameStorageType OpusAudioDecoder::GetStorageType() const { - SB_DCHECK(BelongsToCurrentThread()); - return kSbMediaAudioFrameStorageTypeInterleaved; -} - -int OpusAudioDecoder::GetSamplesPerSecond() const { - return audio_sample_info_.samples_per_second; -} - } // namespace opus } // namespace shared } // namespace starboard
diff --git a/src/starboard/shared/opus/opus_audio_decoder.h b/src/starboard/shared/opus/opus_audio_decoder.h index 3c7184d..689c33d 100644 --- a/src/starboard/shared/opus/opus_audio_decoder.h +++ b/src/starboard/shared/opus/opus_audio_decoder.h
@@ -44,13 +44,12 @@ void Decode(const scoped_refptr<InputBuffer>& input_buffer, const ConsumedCB& consumed_cb) override; void WriteEndOfStream() override; - scoped_refptr<DecodedAudio> Read() override; + scoped_refptr<DecodedAudio> Read(int* samples_per_second) override; void Reset() override; - SbMediaAudioSampleType GetSampleType() const override; - SbMediaAudioFrameStorageType GetStorageType() const override; - int GetSamplesPerSecond() const override; private: + SbMediaAudioSampleType GetSampleType() const; + OutputCB output_cb_; ErrorCB error_cb_;
diff --git a/src/starboard/shared/posix/file_atomic_replace.cc b/src/starboard/shared/posix/file_atomic_replace.cc new file mode 100644 index 0000000..3ee0700 --- /dev/null +++ b/src/starboard/shared/posix/file_atomic_replace.cc
@@ -0,0 +1,57 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/file.h" + +#include <cstdio> + +#include "starboard/common/log.h" +#include "starboard/common/string.h" +#include "starboard/shared/starboard/file_atomic_replace_write_file.h" + +#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + +namespace { + +const char kTempFileSuffix[] = ".temp"; + +} // namespace + +bool SbFileAtomicReplace(const char* path, + const char* data, + int64_t data_size) { + if ((data_size < 0) || ((data_size > 0) && !data)) { + return false; + } + + const bool file_exists = SbFileExists(path); + char temp_path[SB_FILE_MAX_PATH]; + + SbStringCopy(temp_path, path, SB_FILE_MAX_PATH); + SbStringConcat(temp_path, kTempFileSuffix, SB_FILE_MAX_PATH); + + if (!::starboard::shared::starboard::SbFileAtomicReplaceWriteFile( + temp_path, data, data_size)) { + return false; + } + if (file_exists && !SbFileDelete(path)) { + return false; + } + if (rename(temp_path, path) != 0) { + return false; + } + return true; +} + +#endif // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
diff --git a/src/starboard/shared/posix/socket_is_ipv6_supported.cc b/src/starboard/shared/posix/socket_is_ipv6_supported.cc new file mode 100644 index 0000000..2d60d16 --- /dev/null +++ b/src/starboard/shared/posix/socket_is_ipv6_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/socket.h" + +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION + +bool SbSocketIsIpv6Supported() { + return SB_HAS_IPV6; +} + +#endif
diff --git a/src/starboard/shared/posix/storage_write_record.cc b/src/starboard/shared/posix/storage_write_record.cc index 6dfcb4d0..dfa8fa4 100644 --- a/src/starboard/shared/posix/storage_write_record.cc +++ b/src/starboard/shared/posix/storage_write_record.cc
@@ -69,16 +69,17 @@ SbFileFlush(temp_file); if (SbFileIsValid(record->file) && !SbFileClose(record->file)) { + SbFileClose(temp_file); + SbFileDelete(temp_file_path); return false; } record->file = kSbFileInvalid; - if (!SbFileDelete(original_file_path)) { - return false; - } - - if (rename(temp_file_path, original_file_path) != 0) { + if ((!SbFileDelete(original_file_path)) || + (rename(temp_file_path, original_file_path) != 0)) { + SbFileClose(temp_file); + SbFileDelete(temp_file_path); return false; }
diff --git a/src/starboard/shared/posix/time_is_time_thread_now_supported.cc b/src/starboard/shared/posix/time_is_time_thread_now_supported.cc new file mode 100644 index 0000000..dda22a9 --- /dev/null +++ b/src/starboard/shared/posix/time_is_time_thread_now_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/time.h" + +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION + +bool SbTimeIsTimeThreadNowSupported() { + return true; +} + +#endif
diff --git a/src/starboard/shared/pulse/pulse_audio_sink_type.cc b/src/starboard/shared/pulse/pulse_audio_sink_type.cc index 38e6a8c..3bfa883 100644 --- a/src/starboard/shared/pulse/pulse_audio_sink_type.cc +++ b/src/starboard/shared/pulse/pulse_audio_sink_type.cc
@@ -67,7 +67,7 @@ void SetVolume(double volume) override; bool Initialize(pa_context* context); - bool WriteFrameIfNecessary(); + bool WriteFrameIfNecessary(pa_context* context); private: PulseAudioSink(const PulseAudioSink&) = delete; @@ -100,7 +100,9 @@ size_t last_request_size_ = 0; int64_t total_frames_played_ = 0; int64_t total_frames_written_ = 0; - atomic_bool is_paused_; + atomic_double volume_{1.0}; + atomic_bool volume_updated_{true}; + atomic_bool is_paused_{false}; }; class PulseAudioSinkType : public SbAudioSinkPrivate::Type { @@ -169,8 +171,7 @@ consume_frame_func_(consume_frame_func), context_(context), bytes_per_frame_(static_cast<size_t>(channels) * - GetBytesPerSample(sample_type)), - is_paused_(false) { + GetBytesPerSample(sample_type)) { SB_DCHECK(update_source_status_func_); SB_DCHECK(consume_frame_func_); SB_DCHECK(frame_buffer_); @@ -194,7 +195,11 @@ } void PulseAudioSink::SetVolume(double volume) { - SB_NOTIMPLEMENTED(); + SB_DCHECK(volume >= 0.0); + SB_DCHECK(volume <= 1.0); + if (volume_.exchange(volume) != volume) { + volume_updated_.store(true); + } } bool PulseAudioSink::Initialize(pa_context* context) { @@ -222,13 +227,26 @@ return stream_ != NULL; } -bool PulseAudioSink::WriteFrameIfNecessary() { +bool PulseAudioSink::WriteFrameIfNecessary(pa_context* context) { SB_DCHECK(type_->BelongToAudioThread()); - // Wait until |stream_| is ready; if (pa_stream_get_state(stream_) != PA_STREAM_READY) { return false; } + // Update volume if necessary. + if (volume_updated_.exchange(false)) { + pa_cvolume cvol; + cvol.channels = channels_; + pa_cvolume_set( + &cvol, channels_, + (PA_VOLUME_NORM - PA_VOLUME_MUTED) * volume_.load() + PA_VOLUME_MUTED); + uint32_t sink_input_index = pa_stream_get_index(stream_); + SB_DCHECK(sink_input_index != PA_INVALID_INDEX); + pa_operation* op = pa_context_set_sink_input_volume( + context, sink_input_index, &cvol, NULL, NULL); + SB_DCHECK(op); + pa_operation_unref(op); + } bool pulse_paused = pa_stream_is_corked(stream_) == 1; // Calculate consumed frames. if (!pulse_paused) { @@ -406,7 +424,7 @@ return false; } // Create pulse context. - context_ = pa_context_new(pa_mainloop_get_api(mainloop_), "pulse_audio"); + context_ = pa_context_new(pa_mainloop_get_api(mainloop_), "cobalt_audio"); if (!context_) { SB_LOG(WARNING) << "Pulse audio error: cannot create context."; return false; @@ -453,7 +471,8 @@ pa_stream_request_cb_t stream_request_cb, void* userdata) { ScopedLock lock(mutex_); - pa_stream* stream = pa_stream_new(context_, "pulseaudio", sample_spec, NULL); + pa_stream* stream = + pa_stream_new(context_, "cobalt_stream", sample_spec, NULL); if (!stream) { SB_LOG(ERROR) << "Pulse audio error: cannot create stream."; return NULL; @@ -508,7 +527,7 @@ break; } for (PulseAudioSink* sink : sinks_) { - has_running_sink |= sink->WriteFrameIfNecessary(); + has_running_sink |= sink->WriteFrameIfNecessary(context_); } pa_mainloop_iterate(mainloop_, 0, NULL); }
diff --git a/src/starboard/shared/pulse/pulse_dynamic_load_dispatcher.cc b/src/starboard/shared/pulse/pulse_dynamic_load_dispatcher.cc index 0ed0800..2ac81f4 100644 --- a/src/starboard/shared/pulse/pulse_dynamic_load_dispatcher.cc +++ b/src/starboard/shared/pulse/pulse_dynamic_load_dispatcher.cc
@@ -33,8 +33,15 @@ pa_context_flags_t, const pa_spawn_api*) = NULL; void (*pa_context_disconnect)(pa_context*) = NULL; +pa_cvolume* (*pa_cvolume_set)(pa_cvolume*, unsigned, pa_volume_t) = NULL; +uint32_t (*pa_stream_get_index)(const pa_stream*) = NULL; pa_context_state_t (*pa_context_get_state)(pa_context*) = NULL; pa_context* (*pa_context_new)(pa_mainloop_api*, const char*) = NULL; +pa_operation* (*pa_context_set_sink_input_volume)(pa_context*, + uint32_t, + const pa_cvolume*, + pa_context_success_cb_t, + void*) = NULL; void (*pa_context_set_state_callback)(pa_context*, pa_context_notify_cb_t, void*) = NULL; @@ -107,8 +114,10 @@ INITSYMBOL(pa_context_disconnect); INITSYMBOL(pa_context_get_state); INITSYMBOL(pa_context_new); + INITSYMBOL(pa_context_set_sink_input_volume) INITSYMBOL(pa_context_set_state_callback); INITSYMBOL(pa_context_unref); + INITSYMBOL(pa_cvolume_set); INITSYMBOL(pa_frame_size); INITSYMBOL(pa_mainloop_free); INITSYMBOL(pa_mainloop_get_api); @@ -118,6 +127,7 @@ INITSYMBOL(pa_stream_connect_playback); INITSYMBOL(pa_stream_cork); INITSYMBOL(pa_stream_disconnect); + INITSYMBOL(pa_stream_get_index); INITSYMBOL(pa_stream_get_state); INITSYMBOL(pa_stream_get_time); INITSYMBOL(pa_stream_is_corked);
diff --git a/src/starboard/shared/pulse/pulse_dynamic_load_dispatcher.h b/src/starboard/shared/pulse/pulse_dynamic_load_dispatcher.h index 2de7410..1bbae81 100644 --- a/src/starboard/shared/pulse/pulse_dynamic_load_dispatcher.h +++ b/src/starboard/shared/pulse/pulse_dynamic_load_dispatcher.h
@@ -31,8 +31,16 @@ pa_context_flags_t, const pa_spawn_api*); extern void (*pa_context_disconnect)(pa_context*); +extern pa_cvolume* (*pa_cvolume_set)(pa_cvolume*, unsigned, pa_volume_t); +extern uint32_t (*pa_stream_get_index)(const pa_stream*); extern pa_context_state_t (*pa_context_get_state)(pa_context*); extern pa_context* (*pa_context_new)(pa_mainloop_api*, const char*); +extern pa_operation* (*pa_context_set_sink_input_volume)( + pa_context*, + uint32_t, + const pa_cvolume*, + pa_context_success_cb_t, + void*); extern void (*pa_context_set_state_callback)(pa_context*, pa_context_notify_cb_t, void*);
diff --git a/src/starboard/shared/signal/suspend_signals.cc b/src/starboard/shared/signal/suspend_signals.cc index b4d0579..0ad5584 100644 --- a/src/starboard/shared/signal/suspend_signals.cc +++ b/src/starboard/shared/signal/suspend_signals.cc
@@ -54,15 +54,10 @@ ::sigaction(signal_id, &action, NULL); } -void SuspendDone(void* /*context*/) { - // Stop all thread execution after fully transitioning into Suspended. - raise(SIGSTOP); -} - void Suspend(int signal_id) { SignalMask(kAllSignals, SIG_BLOCK); LogSignalCaught(signal_id); - starboard::Application::Get()->Suspend(NULL, &SuspendDone); + SbSystemRequestSuspend(); SignalMask(kAllSignals, SIG_UNBLOCK); }
diff --git a/src/starboard/shared/signal/system_request_suspend.cc b/src/starboard/shared/signal/system_request_suspend.cc new file mode 100644 index 0000000..a663bc9 --- /dev/null +++ b/src/starboard/shared/signal/system_request_suspend.cc
@@ -0,0 +1,27 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/system.h" + +#include "starboard/shared/signal/signal_internal.h" +#include "starboard/shared/starboard/application.h" + +void SuspendDone(void* /*context*/) { + // Stop all thread execution after fully transitioning into Suspended. + raise(SIGSTOP); +} + +void SbSystemRequestSuspend() { + starboard::shared::starboard::Application::Get()->Suspend(NULL, &SuspendDone); +}
diff --git a/src/starboard/shared/speechd/speech_synthesis_is_supported.cc b/src/starboard/shared/speechd/speech_synthesis_is_supported.cc new file mode 100644 index 0000000..1364fbc --- /dev/null +++ b/src/starboard/shared/speechd/speech_synthesis_is_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/speech_synthesis.h" + +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION + +bool SbSpeechSynthesisIsSupported() { + return true; +} + +#endif
diff --git a/src/starboard/shared/starboard/decode_target/decode_target_context_runner.h b/src/starboard/shared/starboard/decode_target/decode_target_context_runner.h index 012eb23..4d3bcee 100644 --- a/src/starboard/shared/starboard/decode_target/decode_target_context_runner.h +++ b/src/starboard/shared/starboard/decode_target/decode_target_context_runner.h
@@ -30,6 +30,10 @@ SbDecodeTargetGraphicsContextProvider* provider); void RunOnGlesContext(std::function<void()> function); + SbDecodeTargetGraphicsContextProvider* context_provider() const { + return provider_; + } + private: SbDecodeTargetGraphicsContextProvider* provider_; };
diff --git a/src/starboard/shared/starboard/file_atomic_replace_write_file.cc b/src/starboard/shared/starboard/file_atomic_replace_write_file.cc new file mode 100644 index 0000000..8d2dea9 --- /dev/null +++ b/src/starboard/shared/starboard/file_atomic_replace_write_file.cc
@@ -0,0 +1,71 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/shared/starboard/file_atomic_replace_write_file.h" + +#include <algorithm> + +#include "starboard/common/log.h" +#include "starboard/file.h" + +#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + +namespace starboard { +namespace shared { +namespace starboard { + +bool SbFileAtomicReplaceWriteFile(const char* path, + const char* data, + int64_t data_size) { + SbFileError error; + SbFile temp_file = SbFileOpen( + path, kSbFileCreateAlways | kSbFileWrite | kSbFileRead, NULL, &error); + + if (error != kSbFileOk) { + return false; + } + + SbFileTruncate(temp_file, 0); + + const char* source = data; + int64_t to_write = data_size; + + while (to_write > 0) { + const int to_write_max = + static_cast<int>(std::min(to_write, static_cast<int64_t>(kSbInt32Max))); + const int bytes_written = SbFileWrite(temp_file, source, to_write_max); + + if (bytes_written < 0) { + SbFileClose(temp_file); + SbFileDelete(path); + return false; + } + + source += bytes_written; + to_write -= bytes_written; + } + + SbFileFlush(temp_file); + + if (!SbFileClose(temp_file)) { + return false; + } + return true; +} + +} // namespace starboard +} // namespace shared +} // namespace starboard + +#endif // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
diff --git a/src/starboard/shared/starboard/file_atomic_replace_write_file.h b/src/starboard/shared/starboard/file_atomic_replace_write_file.h new file mode 100644 index 0000000..d89c750 --- /dev/null +++ b/src/starboard/shared/starboard/file_atomic_replace_write_file.h
@@ -0,0 +1,37 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_SHARED_STARBOARD_FILE_ATOMIC_REPLACE_WRITE_FILE_H_ +#define STARBOARD_SHARED_STARBOARD_FILE_ATOMIC_REPLACE_WRITE_FILE_H_ + +#include "starboard/configuration.h" +#include "starboard/types.h" + +#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + +namespace starboard { +namespace shared { +namespace starboard { + +bool SbFileAtomicReplaceWriteFile(const char* path, + const char* data, + int64_t data_size); + +} // namespace starboard +} // namespace shared +} // namespace starboard + +#endif // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + +#endif // STARBOARD_SHARED_STARBOARD_FILE_ATOMIC_REPLACE_WRITE_FILE_H_
diff --git a/src/starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc b/src/starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc index 0ee50f5..d9d2909 100644 --- a/src/starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc +++ b/src/starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc
@@ -28,7 +28,7 @@ // Use define forwarded from GYP variable. return COBALT_MEDIA_BUFFER_ALLOCATION_UNIT; #else // defined(COBALT_MEDIA_BUFFER_ALLOCATION_UNIT - return 1 * 1024 * 1024; + return 4 * 1024 * 1024; #endif // defined(COBALT_MEDIA_BUFFER_ALLOCATION_UNIT } #endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc b/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc index b0f1415..1410b43 100644 --- a/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc +++ b/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc
@@ -18,8 +18,8 @@ #if SB_API_VERSION >= 10 // These are the legacy default values of the GYP variables. -#define LEGACY_MAX_CAPACITY_1080P 36 * 1024 * 1024 -#define LEGACY_MAX_CAPACITY_4K 65 * 1024 * 1024 +#define LEGACY_MAX_CAPACITY_1080P 50 * 1024 * 1024 +#define LEGACY_MAX_CAPACITY_4K 140 * 1024 * 1024 int SbMediaGetMaxBufferCapacity(SbMediaVideoCodec codec, int resolution_width,
diff --git a/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc b/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc index 05e0b5a..bb8352e 100644 --- a/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc +++ b/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc
@@ -18,8 +18,8 @@ #if SB_API_VERSION >= 10 // These are the legacy default values of the GYP variables. -#define LEGACY_VIDEO_BUDGET_1080P 16 * 1024 * 1024 -#define LEGACY_VIDEO_BUDGET_4K 60 * 1024 * 1024 +#define LEGACY_VIDEO_BUDGET_1080P 30 * 1024 * 1024 +#define LEGACY_VIDEO_BUDGET_4K 100 * 1024 * 1024 int SbMediaGetVideoBufferBudget(SbMediaVideoCodec codec, int resolution_width,
diff --git a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc index e137651..8e55eb2 100644 --- a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc +++ b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc
@@ -17,8 +17,7 @@ #include "starboard/configuration.h" #include "starboard/media.h" -SB_EXPORT bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - int64_t bitrate) { +bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate) { if (audio_codec == kSbMediaAudioCodecAac) { return bitrate <= SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND; }
diff --git a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc index e8e2de7..eec13e0 100644 --- a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc +++ b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc
@@ -17,8 +17,7 @@ #include "starboard/configuration.h" #include "starboard/media.h" -SB_EXPORT bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - int64_t bitrate) { +bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate) { return audio_codec == kSbMediaAudioCodecAac && bitrate <= SB_MEDIA_MAX_AUDIO_BITRATE_IN_BITS_PER_SECOND; }
diff --git a/src/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc b/src/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc index 56f8407..487ebf6 100644 --- a/src/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc +++ b/src/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc
@@ -17,8 +17,7 @@ #include "starboard/media.h" #if !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT) -SB_EXPORT bool SbMediaIsTransferCharacteristicsSupported( - SbMediaTransferId transfer_id) { +bool SbMediaIsTransferCharacteristicsSupported(SbMediaTransferId transfer_id) { return transfer_id == kSbMediaTransferIdBt709 || transfer_id == kSbMediaTransferIdUnspecified; }
diff --git a/src/starboard/shared/starboard/media/media_util.cc b/src/starboard/shared/starboard/media/media_util.cc index 50a26ac..f66216f 100644 --- a/src/starboard/shared/starboard/media/media_util.cc +++ b/src/starboard/shared/starboard/media/media_util.cc
@@ -115,15 +115,19 @@ std::string eotf = mime_type.GetParamStringValue("eotf", ""); if (!eotf.empty()) { - SB_LOG_IF(WARNING, transfer_id != kSbMediaTransferIdUnspecified) - << "transfer_id " << transfer_id << " set by the codec string \"" - << codec << "\" will be overwritten by the eotf attribute " << eotf; - transfer_id = GetTransferIdFromString(eotf); + SbMediaTransferId transfer_id_from_eotf = GetTransferIdFromString(eotf); // If the eotf is not known, reject immediately - without checking with // the platform. - if (transfer_id == kSbMediaTransferIdUnknown) { + if (transfer_id_from_eotf == kSbMediaTransferIdUnknown) { return false; } + if (transfer_id != kSbMediaTransferIdUnspecified && + transfer_id != transfer_id_from_eotf) { + SB_LOG_IF(WARNING, transfer_id != kSbMediaTransferIdUnspecified) + << "transfer_id " << transfer_id << " set by the codec string \"" + << codec << "\" will be overwritten by the eotf attribute " << eotf; + } + transfer_id = transfer_id_from_eotf; #if !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT) if (!SbMediaIsTransferCharacteristicsSupported(transfer_id)) { return false; @@ -222,17 +226,20 @@ } if (primary_id != kSbMediaPrimaryIdBt709 && - primary_id != kSbMediaPrimaryIdUnspecified) { + primary_id != kSbMediaPrimaryIdUnspecified && + primary_id != kSbMediaPrimaryIdSmpte170M) { return false; } if (transfer_id != kSbMediaTransferIdBt709 && - transfer_id != kSbMediaTransferIdUnspecified) { + transfer_id != kSbMediaTransferIdUnspecified && + transfer_id != kSbMediaTransferIdSmpte170M) { return false; } if (matrix_id != kSbMediaMatrixIdBt709 && - matrix_id != kSbMediaMatrixIdUnspecified) { + matrix_id != kSbMediaMatrixIdUnspecified && + matrix_id != kSbMediaMatrixIdSmpte170M) { return false; } @@ -575,13 +582,28 @@ } std::ostream& operator<<(std::ostream& os, + const SbMediaMasteringMetadata& metadata) { + os << "r(" << metadata.primary_r_chromaticity_x << ", " + << metadata.primary_r_chromaticity_y << "), g(" + << metadata.primary_g_chromaticity_x << ", " + << metadata.primary_g_chromaticity_y << "), b(" + << metadata.primary_b_chromaticity_x << ", " + << metadata.primary_b_chromaticity_y << "), white(" + << metadata.white_point_chromaticity_x << ", " + << metadata.white_point_chromaticity_y << "), luminance(" + << metadata.luminance_min << " to " << metadata.luminance_max << ")"; + return os; +} + +std::ostream& operator<<(std::ostream& os, const SbMediaColorMetadata& metadata) { using starboard::shared::starboard::media::GetPrimaryIdName; using starboard::shared::starboard::media::GetTransferIdName; using starboard::shared::starboard::media::GetMatrixIdName; using starboard::shared::starboard::media::GetRangeIdName; os << metadata.bits_per_channel - << " bits, primary: " << GetPrimaryIdName(metadata.primaries) + << " bits, mastering metadata: " << metadata.mastering_metadata + << ", primary: " << GetPrimaryIdName(metadata.primaries) << ", transfer: " << GetTransferIdName(metadata.transfer) << ", matrix: " << GetMatrixIdName(metadata.matrix) << ", range: " << GetRangeIdName(metadata.range);
diff --git a/src/starboard/shared/starboard/media/media_util.h b/src/starboard/shared/starboard/media/media_util.h index 4ecd521..53f7fc7 100644 --- a/src/starboard/shared/starboard/media/media_util.h +++ b/src/starboard/shared/starboard/media/media_util.h
@@ -93,6 +93,8 @@ // For logging use only. std::ostream& operator<<(std::ostream& os, + const SbMediaMasteringMetadata& metadata); +std::ostream& operator<<(std::ostream& os, const SbMediaColorMetadata& metadata); std::ostream& operator<<(std::ostream& os, const SbMediaVideoSampleInfo& sample_info);
diff --git a/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc b/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc index 8b06d66..76973fd 100644 --- a/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc +++ b/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc
@@ -17,6 +17,7 @@ #include "starboard/audio_sink.h" #include "starboard/common/log.h" #include "starboard/common/reset_and_return.h" +#include "starboard/shared/starboard/player/decoded_audio_internal.h" namespace starboard { namespace shared { @@ -27,27 +28,6 @@ using common::ResetAndReturn; #if SB_API_VERSION >= 11 -SbMediaAudioSampleType GetDefaultSupportedAudioSampleType() { - if (SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32)) { - return kSbMediaAudioSampleTypeFloat32; - } - if (SbAudioSinkIsAudioSampleTypeSupported( - kSbMediaAudioSampleTypeInt16Deprecated)) { - return kSbMediaAudioSampleTypeInt16Deprecated; - } - SB_NOTREACHED(); - return kSbMediaAudioSampleTypeFloat32; -} - -SbMediaAudioFrameStorageType GetDefaultSupportedAudioFrameStorageType() { - if (SbAudioSinkIsAudioFrameStorageTypeSupported( - kSbMediaAudioFrameStorageTypeInterleaved)) { - return kSbMediaAudioFrameStorageTypeInterleaved; - } - SB_NOTREACHED(); - return kSbMediaAudioFrameStorageTypeInterleaved; -} - int GetDefaultSupportedAudioSamplesPerSecond() { const int kDefaultOutputSamplesPerSecond = 48000; return SbAudioSinkGetNearestSupportedSampleFrequency( @@ -62,6 +42,9 @@ if (current_info.samples_per_second != new_info.samples_per_second) { return true; } + if (current_info.number_of_channels != new_info.number_of_channels) { + return true; + } if (current_info.audio_specific_config_size != new_info.audio_specific_config_size) { return true; @@ -79,10 +62,10 @@ SbDrmSystem drm_system, const AudioDecoderCreator& audio_decoder_creator, const OutputFormatAdjustmentCallback& output_adjustment_callback) - : initilize_audio_sample_info_(audio_sample_info), - drm_system_(drm_system), + : drm_system_(drm_system), audio_decoder_creator_(audio_decoder_creator), - output_adjustment_callback_(output_adjustment_callback) { + output_adjustment_callback_(output_adjustment_callback), + output_number_of_channels_(audio_sample_info.number_of_channels) { SB_DCHECK(audio_sample_info.codec != kSbMediaAudioCodecNone); } @@ -147,27 +130,30 @@ if (audio_decoder_) { audio_decoder_->WriteEndOfStream(); } else { - // It's possible that WriteEndOfStream() is called without any - // other input. In that case, we need to give |output_sample_type_|, - // |output_storage_type_| and |output_samples_per_second_| default - // value. - if (!first_output_received_) { - first_output_received_ = true; - output_sample_type_ = GetDefaultSupportedAudioSampleType(); - output_storage_type_ = GetDefaultSupportedAudioFrameStorageType(); - output_samples_per_second_ = GetDefaultSupportedAudioSamplesPerSecond(); - } decoded_audios_.push(new DecodedAudio); Schedule(output_cb_); } } -scoped_refptr<DecodedAudio> AdaptiveAudioDecoder::Read() { +scoped_refptr<DecodedAudio> AdaptiveAudioDecoder::Read( + int* samples_per_second) { SB_DCHECK(BelongsToCurrentThread()); SB_DCHECK(!decoded_audios_.empty()); scoped_refptr<DecodedAudio> ret = decoded_audios_.front(); decoded_audios_.pop(); + + SB_DCHECK(ret->is_end_of_stream() || + ret->sample_type() == output_sample_type_); + SB_DCHECK(ret->is_end_of_stream() || + ret->storage_type() == output_storage_type_); + SB_DCHECK(ret->is_end_of_stream() || + ret->channels() == output_number_of_channels_); + + SB_DCHECK(first_output_received_ || ret->is_end_of_stream()); + *samples_per_second = first_output_received_ + ? output_samples_per_second_ + : GetDefaultSupportedAudioSamplesPerSecond(); return ret; } @@ -193,6 +179,8 @@ SB_DCHECK(!audio_decoder_); SB_DCHECK(output_cb_); SB_DCHECK(error_cb_); + SB_DCHECK(!resampler_); + SB_DCHECK(!channel_mixer_); input_audio_sample_info_ = audio_sample_info; output_format_checked_ = false; @@ -214,30 +202,37 @@ void AdaptiveAudioDecoder::TeardownAudioDecoder() { audio_decoder_.reset(); resampler_.reset(); + channel_mixer_.reset(); } void AdaptiveAudioDecoder::OnDecoderOutput() { SB_DCHECK(BelongsToCurrentThread()); SB_DCHECK(output_cb_); + int decoded_sample_rate; + scoped_refptr<DecodedAudio> decoded_audio = + audio_decoder_->Read(&decoded_sample_rate); if (!first_output_received_) { first_output_received_ = true; - output_sample_type_ = audio_decoder_->GetSampleType(); - output_storage_type_ = audio_decoder_->GetStorageType(); - output_samples_per_second_ = audio_decoder_->GetSamplesPerSecond(); + output_sample_type_ = decoded_audio->sample_type(); + output_storage_type_ = decoded_audio->storage_type(); + output_samples_per_second_ = decoded_sample_rate; if (output_adjustment_callback_) { output_adjustment_callback_(&output_sample_type_, &output_storage_type_, - &output_samples_per_second_); + &output_samples_per_second_, + &output_number_of_channels_); } } - scoped_refptr<DecodedAudio> decoded_audio = audio_decoder_->Read(); if (decoded_audio->is_end_of_stream()) { // Flush resampler. if (resampler_) { scoped_refptr<DecodedAudio> resampler_output = resampler_->WriteEndOfStream(); if (resampler_output && resampler_output->size() > 0) { + if (channel_mixer_) { + resampler_output = channel_mixer_->Mix(resampler_output); + } decoded_audios_.push(resampler_output); Schedule(output_cb_); } @@ -256,23 +251,35 @@ return; } + SB_DCHECK(input_audio_sample_info_.number_of_channels == + decoded_audio->channels()); if (!output_format_checked_) { SB_DCHECK(!resampler_); + SB_DCHECK(!channel_mixer_); output_format_checked_ = true; - if (audio_decoder_->GetSampleType() != output_sample_type_ || - audio_decoder_->GetStorageType() != output_storage_type_ || - audio_decoder_->GetSamplesPerSecond() != output_samples_per_second_) { + if (output_sample_type_ != decoded_audio->sample_type() || + output_storage_type_ != decoded_audio->storage_type() || + output_samples_per_second_ != decoded_sample_rate) { resampler_ = AudioResampler::Create( - audio_decoder_->GetSampleType(), audio_decoder_->GetStorageType(), - audio_decoder_->GetSamplesPerSecond(), output_sample_type_, - output_storage_type_, output_samples_per_second_, - initilize_audio_sample_info_.number_of_channels); + decoded_audio->sample_type(), decoded_audio->storage_type(), + decoded_sample_rate, output_sample_type_, output_storage_type_, + output_samples_per_second_, + input_audio_sample_info_.number_of_channels); + } + if (input_audio_sample_info_.number_of_channels != + output_number_of_channels_) { + channel_mixer_ = AudioChannelLayoutMixer::Create( + output_sample_type_, output_storage_type_, + output_number_of_channels_); } } if (resampler_) { decoded_audio = resampler_->Resample(decoded_audio); } if (decoded_audio && decoded_audio->size() > 0) { + if (channel_mixer_) { + decoded_audio = channel_mixer_->Mix(decoded_audio); + } decoded_audios_.push(decoded_audio); Schedule(output_cb_); }
diff --git a/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h b/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h index b884432..e37b02f 100644 --- a/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h +++ b/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h
@@ -22,6 +22,7 @@ #include "starboard/common/scoped_ptr.h" #include "starboard/media.h" #include "starboard/shared/internal_only.h" +#include "starboard/shared/starboard/player/filter/audio_channel_layout_mixer.h" #include "starboard/shared/starboard/player/filter/audio_decoder_internal.h" #include "starboard/shared/starboard/player/filter/audio_resampler.h" #include "starboard/shared/starboard/player/job_queue.h" @@ -42,7 +43,8 @@ typedef std::function<void(SbMediaAudioSampleType* output_sample_type, SbMediaAudioFrameStorageType* output_storage_type, - int* output_samples_per_second)> + int* output_samples_per_second, + int* output_number_of_channels)> OutputFormatAdjustmentCallback; AdaptiveAudioDecoder(const SbMediaAudioSampleInfo& audio_sample_info, @@ -56,22 +58,9 @@ void Decode(const scoped_refptr<InputBuffer>& input_buffer, const ConsumedCB& consumed_cb) override; void WriteEndOfStream() override; - scoped_refptr<DecodedAudio> Read() override; + scoped_refptr<DecodedAudio> Read(int* samples_per_second) override; void Reset() override; - SbMediaAudioSampleType GetSampleType() const override { - SB_DCHECK(first_output_received_); - return output_sample_type_; - } - SbMediaAudioFrameStorageType GetStorageType() const override { - SB_DCHECK(first_output_received_); - return output_storage_type_; - } - int GetSamplesPerSecond() const override { - SB_DCHECK(first_output_received_); - return output_samples_per_second_; - } - private: void ProcessOneInputBuffer(const scoped_refptr<InputBuffer>& input_buffer, const ConsumedCB& consumed_cb); @@ -80,13 +69,13 @@ void TeardownAudioDecoder(); void OnDecoderOutput(); - const SbMediaAudioSampleInfo initilize_audio_sample_info_; const SbDrmSystem drm_system_; const AudioDecoderCreator audio_decoder_creator_; const OutputFormatAdjustmentCallback output_adjustment_callback_; SbMediaAudioSampleType output_sample_type_; SbMediaAudioFrameStorageType output_storage_type_; int output_samples_per_second_; + int output_number_of_channels_; SbMediaAudioSampleInfo input_audio_sample_info_ = {}; OutputCB output_cb_ = nullptr; @@ -94,6 +83,7 @@ scoped_ptr<filter::AudioDecoder> audio_decoder_; scoped_ptr<filter::AudioResampler> resampler_; + scoped_ptr<filter::AudioChannelLayoutMixer> channel_mixer_; scoped_refptr<InputBuffer> pending_input_buffer_; ConsumedCB pending_consumed_cb_; std::queue<scoped_refptr<DecodedAudio>> decoded_audios_;
diff --git a/src/starboard/shared/starboard/player/filter/audio_channel_layout_mixer.h b/src/starboard/shared/starboard/player/filter/audio_channel_layout_mixer.h new file mode 100644 index 0000000..31da031 --- /dev/null +++ b/src/starboard/shared/starboard/player/filter/audio_channel_layout_mixer.h
@@ -0,0 +1,53 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_CHANNEL_LAYOUT_MIXER_H_ +#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_CHANNEL_LAYOUT_MIXER_H_ + +#include <vector> + +#include "starboard/common/ref_counted.h" +#include "starboard/common/scoped_ptr.h" +#include "starboard/media.h" +#include "starboard/shared/internal_only.h" +#include "starboard/shared/starboard/player/decoded_audio_internal.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace player { +namespace filter { + +class AudioChannelLayoutMixer { + public: + typedef ::starboard::shared::starboard::player::DecodedAudio DecodedAudio; + + virtual ~AudioChannelLayoutMixer() {} + + virtual scoped_refptr<DecodedAudio> Mix( + const scoped_refptr<DecodedAudio>& audio_data) = 0; + + static scoped_ptr<AudioChannelLayoutMixer> Create( + SbMediaAudioSampleType sample_type, + SbMediaAudioFrameStorageType storage_type, + int output_channels); +}; + +} // namespace filter +} // namespace player +} // namespace starboard +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_CHANNEL_LAYOUT_MIXER_H_
diff --git a/src/starboard/shared/starboard/player/filter/audio_channel_layout_mixer_impl.cc b/src/starboard/shared/starboard/player/filter/audio_channel_layout_mixer_impl.cc new file mode 100644 index 0000000..a052408 --- /dev/null +++ b/src/starboard/shared/starboard/player/filter/audio_channel_layout_mixer_impl.cc
@@ -0,0 +1,370 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/shared/starboard/player/filter/audio_channel_layout_mixer.h" + +#include <vector> + +#include "starboard/common/log.h" +#include "starboard/shared/starboard/media/media_util.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace player { +namespace filter { + +namespace { + +using media::GetBytesPerSample; + +// 1 -> 2 +const float kMonoToStereoMatrix[] = { + 1.0f, // output.L = input + 1.0f, // output.R = input +}; + +// 1 -> 4 +const float kMonoToQuadMatrix[] = { + 1.0f, // output.L = input + 1.0f, // output.R = input + 0.0f, // output.SL = 0 + 0.0f, // output.SR = 0 +}; + +// 1 -> 5.1 +const float kMonoToFivePointOneMatrix[] = { + 0.0f, // output.L = 0 + 0.0f, // output.R = 0 + 1.0f, // output.C = input + 0.0f, // output.LFE = 0 + 0.0f, // output.SL = 0 + 0.0f, // output.SR = 0 +}; + +// 2 -> 4 +const float kStereoToQuadMatrix[] = { + 1.0f, 0.0f, // output.L = input.L + 0.0f, 1.0f, // output.R = input.R + 0.0f, 0.0f, // output.SL = 0 + 0.0f, 0.0f, // output.SR = 0 +}; + +// 2 -> 5.1 +const float kStereoToFivePointOneMatrix[] = { + 1.0f, 0.0f, // output.L = input.L + 0.0f, 1.0f, // output.R = input.R + 0.0f, 0.0f, // output.C = 0 + 0.0f, 0.0f, // output.LFE = 0 + 0.0f, 0.0f, // output.SL = 0 + 0.0f, 0.0f, // output.SR = 0 +}; + +// 4 -> 5.1 +const float kQuadToFivePointOneMatrix[] = { + 1.0f, 0.0f, 0.0f, 0.0f, // output.L = input.L + 0.0f, 1.0f, 0.0f, 0.0f, // output.R = input.R + 0.0f, 0.0f, 0.0f, 0.0f, // output.C = 0 + 0.0f, 0.0f, 0.0f, 0.0f, // output.LFE = 0 + 0.0f, 0.0f, 1.0f, 0.0f, // output.SL = input.SL + 0.0f, 0.0f, 0.0f, 1.0f, // output.SR = input.SR +}; + +// 2 -> 1 +const float kStereoToMonoMatrix[] = { + 0.5f, 0.5f, // output = 0.5 * (input.L + input.R) +}; + +// 4 -> 1 +const float kQuadToMonoMatrix[] = { + // output = 0.25 * (input.L + input.R + input.SL + input.SR) + 0.25f, 0.25f, 0.25f, 0.25f, +}; + +// 5.1 -> 1 +const float kFivePointOneToMonoMatrix[] = { + // output = sqrt(0.5) * (input.L + input.R) + input.C + 0.5 * (input.SL + + // input.SR) + 0.7071f, 0.7071f, 1.0f, 0.0f, 0.5f, 0.5f, +}; + +// 4 -> 2 +const float kQuadToStereoMatrix[] = { + 0.5f, 0.0f, 0.5f, 0.0f, // output.L = 0.5 * (input.L + input.SL) + 0.0f, 0.5f, 0.0f, 0.5f, // output.R = 0.5 * (input.R + input.SR) +}; + +// 5.1 -> 2 +const float kFivePointOneToStereoMatrix[] = { + // output.L = L + sqrt(0.5) * (input.C + input.SL) + 1.0f, 0.0f, 0.7071f, 0.0f, 0.7071f, 0.0f, + // output.R = R + sqrt(0.5) * (input.C + input.SR) + 0.0f, 1.0f, 0.7071f, 0.0f, 0.0f, 0.7071f, +}; + +// 5.1 -> 4 +const float kFivePointOneToQuadMatrix[] = { + // output.L = L + sqrt(0.5) * input.C + 1.0f, 0.0f, 0.7071f, 0.0f, 0.0f, 0.0f, + // output.R = R + sqrt(0.5) * input.C + 0.0f, 1.0f, 0.7071f, 0.0f, 0.0f, 0.0f, + // output.SL = input.SL + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, + // output.SR = input.SR + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, +}; + +// Get the samples of frames at |frame_index|. If |input| is already +// interleaved, the return pointer points to the buffer contained inside +// |input|. If |input| is planar, it will copy all samples into |aux_buffer| and +// return |aux_buffer| instead. Note that |aux_buffer| should be large enough +// to hold samples from all channels of the frame. +template <typename SampleType> +const SampleType* GetInterleavedSamplesOfFrame( + const scoped_refptr<DecodedAudio>& input, + int frame_index, + SampleType* aux_buffer) { + const SampleType* input_buffer = + reinterpret_cast<const SampleType*>(input->buffer()); + if (input->storage_type() == kSbMediaAudioFrameStorageTypeInterleaved) { + return input_buffer + frame_index * input->channels(); + } + SB_DCHECK(input->storage_type() == kSbMediaAudioFrameStorageTypePlanar); + for (size_t channel_index = 0; channel_index < input->channels(); + channel_index++) { + aux_buffer[channel_index] = + input_buffer[channel_index * input->frames() + frame_index]; + } + return aux_buffer; +} + +template <typename SampleType> +void StoreInterleavedSamplesOfFrame(const SampleType* samples, + scoped_refptr<DecodedAudio>* destination, + int frame_index) { + SampleType* dest_buffer = + reinterpret_cast<SampleType*>((*destination)->buffer()); + for (size_t channel_index = 0; channel_index < (*destination)->channels(); + channel_index++) { + if ((*destination)->storage_type() == + kSbMediaAudioFrameStorageTypeInterleaved) { + dest_buffer[frame_index * (*destination)->channels() + channel_index] = + samples[channel_index]; + } else { + SB_DCHECK((*destination)->storage_type() == + kSbMediaAudioFrameStorageTypePlanar); + dest_buffer[channel_index * (*destination)->frames() + frame_index] = + samples[channel_index]; + } + } +} + +template <typename SampleType> +SampleType ClipSample(float sample); + +template <> +float ClipSample<float>(float sample) { + return sample; +} + +template <> +int16_t ClipSample<int16_t>(float sample) { + if (sample > kSbInt16Max) { + return kSbInt16Max; + } + if (sample < kSbInt16Min) { + return kSbInt16Min; + } + return sample; +} + +// Apply a matrix of [number_of_output_samples, number_of_input_samples] to +// |input_samples| and store the result in |output_samples|. +template <typename SampleType> +void MixFrameWithMatrix(const SampleType* input_frame, + int number_of_input_channels, + const float* matrix, + SampleType* output_frame, + int number_of_output_channels) { + for (size_t output_index = 0; output_index < number_of_output_channels; + output_index++) { + float output_sample = 0; + for (size_t input_index = 0; input_index < number_of_input_channels; + input_index++) { + output_sample += + input_frame[input_index] * + matrix[output_index * number_of_input_channels + input_index]; + } + output_frame[output_index] = ClipSample<SampleType>(output_sample); + } +} + +class AudioChannelLayoutMixerImpl : public AudioChannelLayoutMixer { + public: + AudioChannelLayoutMixerImpl(SbMediaAudioSampleType sample_type, + SbMediaAudioFrameStorageType storage_type, + int output_channels); + + scoped_refptr<DecodedAudio> Mix( + const scoped_refptr<DecodedAudio>& input) override; + + private: + template <typename SampleType> + scoped_refptr<DecodedAudio> Mix(const scoped_refptr<DecodedAudio>& input, + const float* matrix); + + scoped_refptr<DecodedAudio> MixMonoToStereoOptimized( + const scoped_refptr<DecodedAudio>& input); + + SbMediaAudioSampleType sample_type_; + SbMediaAudioFrameStorageType storage_type_; + int output_channels_; +}; + +AudioChannelLayoutMixerImpl::AudioChannelLayoutMixerImpl( + SbMediaAudioSampleType sample_type, + SbMediaAudioFrameStorageType storage_type, + int output_channels) + : sample_type_(sample_type), + storage_type_(storage_type), + output_channels_(output_channels) {} + +scoped_refptr<DecodedAudio> AudioChannelLayoutMixerImpl::Mix( + const scoped_refptr<DecodedAudio>& input) { + SB_DCHECK(input->sample_type() == sample_type_); + SB_DCHECK(input->storage_type() == storage_type_); + + if (input->channels() == output_channels_) { + return input; + } + + if (input->channels() == 1 && output_channels_ == 2) { + return MixMonoToStereoOptimized(input); + } + + const float* matrix = nullptr; + if (input->channels() == 1) { + if (output_channels_ == 2) { + matrix = kMonoToStereoMatrix; + } else if (output_channels_ == 4) { + matrix = kMonoToQuadMatrix; + } else if (output_channels_ == 6) { + matrix = kMonoToFivePointOneMatrix; + } + } else if (input->channels() == 2) { + if (output_channels_ == 1) { + matrix = kStereoToMonoMatrix; + } else if (output_channels_ == 4) { + matrix = kStereoToQuadMatrix; + } else if (output_channels_ == 6) { + matrix = kStereoToFivePointOneMatrix; + } + } else if (input->channels() == 4) { + if (output_channels_ == 1) { + matrix = kQuadToMonoMatrix; + } else if (output_channels_ == 2) { + matrix = kQuadToStereoMatrix; + } else if (output_channels_ == 6) { + matrix = kQuadToFivePointOneMatrix; + } + } else if (input->channels() == 6) { + if (output_channels_ == 1) { + matrix = kFivePointOneToMonoMatrix; + } else if (output_channels_ == 2) { + matrix = kFivePointOneToStereoMatrix; + } else if (output_channels_ == 4) { + matrix = kFivePointOneToQuadMatrix; + } + } + + if (!matrix) { + SB_NOTREACHED() << "Mixing " << input->channels() << " channels to " + << output_channels_ << " channels is not supported."; + return scoped_refptr<DecodedAudio>(); + } + + if (sample_type_ == kSbMediaAudioSampleTypeInt16Deprecated) { + return Mix<int16_t>(input, matrix); + } + SB_DCHECK(sample_type_ == kSbMediaAudioSampleTypeFloat32); + return Mix<float>(input, matrix); +} + +template <typename SampleType> +scoped_refptr<DecodedAudio> AudioChannelLayoutMixerImpl::Mix( + const scoped_refptr<DecodedAudio>& input, + const float* matrix) { + size_t frames = input->frames(); + scoped_refptr<DecodedAudio> output(new DecodedAudio( + output_channels_, sample_type_, storage_type_, input->timestamp(), + frames * output_channels_ * GetBytesPerSample(sample_type_))); + SampleType aux_buffer[8]; + SampleType output_buffer[8]; + for (int frame_index = 0; frame_index < frames; frame_index++) { + const SampleType* interleavedSamplesOfFrame = + GetInterleavedSamplesOfFrame(input, frame_index, aux_buffer); + MixFrameWithMatrix(interleavedSamplesOfFrame, input->channels(), matrix, + output_buffer, output_channels_); + StoreInterleavedSamplesOfFrame(output_buffer, &output, frame_index); + } + return output; +} + +scoped_refptr<DecodedAudio> +AudioChannelLayoutMixerImpl::MixMonoToStereoOptimized( + const scoped_refptr<DecodedAudio>& input) { + SB_DCHECK(output_channels_ == 2); + SB_DCHECK(input->channels() == 1); + + scoped_refptr<DecodedAudio> output( + new DecodedAudio(output_channels_, sample_type_, storage_type_, + input->timestamp(), input->size() * 2)); + if (storage_type_ == kSbMediaAudioFrameStorageTypeInterleaved) { + size_t frames_left = input->frames(); + size_t bytes_per_sample = GetBytesPerSample(sample_type_); + const uint8_t* src_buffer_ptr = input->buffer(); + uint8_t* dest_buffer_ptr = output->buffer(); + while (frames_left > 0) { + SbMemoryCopy(dest_buffer_ptr, src_buffer_ptr, bytes_per_sample); + dest_buffer_ptr += bytes_per_sample; + SbMemoryCopy(dest_buffer_ptr, src_buffer_ptr, bytes_per_sample); + dest_buffer_ptr += bytes_per_sample; + src_buffer_ptr += bytes_per_sample; + frames_left--; + } + } else { + SB_DCHECK(storage_type_ == kSbMediaAudioFrameStorageTypePlanar); + SbMemoryCopy(output->buffer(), input->buffer(), input->size()); + SbMemoryCopy(output->buffer() + input->size(), input->buffer(), + input->size()); + } + return output; +} + +} // namespace + +// static +scoped_ptr<AudioChannelLayoutMixer> AudioChannelLayoutMixer::Create( + SbMediaAudioSampleType sample_type, + SbMediaAudioFrameStorageType storage_type, + int output_channels) { + return scoped_ptr<AudioChannelLayoutMixer>(new AudioChannelLayoutMixerImpl( + sample_type, storage_type, output_channels)); +} + +} // namespace filter +} // namespace player +} // namespace starboard +} // namespace shared +} // namespace starboard
diff --git a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h index e1c85cf..6d4fca9 100644 --- a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h +++ b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
@@ -73,25 +73,12 @@ // combine multiple decoded audio access units into one. The implementation // has to ensure that the particular resampler can handle such combined access // units as input. - virtual scoped_refptr<DecodedAudio> Read() = 0; + virtual scoped_refptr<DecodedAudio> Read(int* samples_per_second) = 0; // Clear any cached buffer of the codec and reset the state of the codec. This // function will be called during seek to ensure that the left over data from // from previous buffers are cleared. virtual void Reset() = 0; - - // Return the sample type of the decoded pcm data. - virtual SbMediaAudioSampleType GetSampleType() const = 0; - - // Return the storage type of the decoded pcm data. - virtual SbMediaAudioFrameStorageType GetStorageType() const = 0; - - // Return the sample rate of the incoming audio. This should be used by the - // audio renderer as the sample rate of the underlying audio stream can be - // different than the sample rate stored in the meta data. - // This function can only be called after |output_cb| passed to Initialize() - // is called for the first time. - virtual int GetSamplesPerSecond() const = 0; }; } // namespace filter
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc index 8d4695e..8ebbfad 100644 --- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc +++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc
@@ -493,30 +493,29 @@ } } -void AudioRenderer::OnFirstOutput() { +void AudioRenderer::OnFirstOutput( + const SbMediaAudioSampleType decoded_sample_type, + const SbMediaAudioFrameStorageType decoded_storage_type, + const int decoded_sample_rate) { SB_DCHECK(BelongsToCurrentThread()); SB_DCHECK(!decoder_sample_rate_); - decoder_sample_rate_ = decoder_->GetSamplesPerSecond(); + decoder_sample_rate_ = decoded_sample_rate; int destination_sample_rate = audio_renderer_sink_->GetNearestSupportedSampleFrequency( *decoder_sample_rate_); - time_stretcher_.Initialize(sink_sample_type_, channels_, + time_stretcher_.Initialize(kSbMediaAudioSampleTypeFloat32, channels_, destination_sample_rate); // Start play after have enough buffered frames to play 0.2s. buffered_frames_to_start_ = destination_sample_rate * 0.2; - SbMediaAudioSampleType source_sample_type = decoder_->GetSampleType(); - SbMediaAudioFrameStorageType source_storage_type = decoder_->GetStorageType(); - - if (*decoder_sample_rate_ != destination_sample_rate || - source_sample_type != sink_sample_type_ || - source_storage_type != kSbMediaAudioFrameStorageTypeInterleaved) { + if (decoded_sample_rate != destination_sample_rate || + decoded_sample_type != sink_sample_type_ || + decoded_storage_type != kSbMediaAudioFrameStorageTypeInterleaved) { resampler_ = AudioResampler::Create( - decoder_->GetSampleType(), decoder_->GetStorageType(), - *decoder_sample_rate_, sink_sample_type_, - kSbMediaAudioFrameStorageTypeInterleaved, destination_sample_rate, - channels_); + decoded_sample_type, decoded_storage_type, decoded_sample_rate, + sink_sample_type_, kSbMediaAudioFrameStorageTypeInterleaved, + destination_sample_rate, channels_); SB_DCHECK(resampler_); } else { resampler_.reset(new IdentityAudioResampler); @@ -566,10 +565,6 @@ process_audio_data_job_token_.ResetToInvalid(); } - if (!audio_renderer_sink_->HasStarted()) { - OnFirstOutput(); - } - ProcessAudioData(); } @@ -578,16 +573,16 @@ process_audio_data_job_token_.ResetToInvalid(); - SB_DCHECK(resampler_); - // Loop until no audio is appended, i.e. AppendAudioToFrameBuffer() returns // false. bool is_frame_buffer_full = false; - while (AppendAudioToFrameBuffer(&is_frame_buffer_full)) { + if (audio_renderer_sink_->HasStarted()) { + while (AppendAudioToFrameBuffer(&is_frame_buffer_full)) { + } } while (pending_decoder_outputs_ > 0) { - if (time_stretcher_.IsQueueFull()) { + if (audio_renderer_sink_->HasStarted() && time_stretcher_.IsQueueFull()) { // There is no room to do any further processing, schedule the function // again for a later time. The delay time is 1/4 of the buffer size. const SbTimeMonotonic delay = @@ -597,10 +592,17 @@ } scoped_refptr<DecodedAudio> resampled_audio; - scoped_refptr<DecodedAudio> decoded_audio = decoder_->Read(); + int decoded_audio_sample_rate; + scoped_refptr<DecodedAudio> decoded_audio = + decoder_->Read(&decoded_audio_sample_rate); + SB_DCHECK(decoded_audio); + if (!audio_renderer_sink_->HasStarted()) { + OnFirstOutput(decoded_audio->sample_type(), decoded_audio->storage_type(), + decoded_audio_sample_rate); + } + SB_DCHECK(resampler_); --pending_decoder_outputs_; - SB_DCHECK(decoded_audio); if (!decoded_audio) { continue; } @@ -627,6 +629,10 @@ } if (resampled_audio && resampled_audio->size() > 0) { + // |time_stretcher_| only support kSbMediaAudioSampleTypeFloat32 and + // kSbMediaAudioFrameStorageTypeInterleaved. + resampled_audio->SwitchFormatTo(kSbMediaAudioSampleTypeFloat32, + kSbMediaAudioFrameStorageTypeInterleaved); time_stretcher_.EnqueueBuffer(resampled_audio); } @@ -696,7 +702,8 @@ audio_frame_tracker_.AddFrames(decoded_audio->frames(), playback_rate_); } - // TODO: Support kSbMediaAudioFrameStorageTypePlanar. + // |time_stretcher_| only support kSbMediaAudioSampleTypeFloat32 and + // kSbMediaAudioFrameStorageTypeInterleaved. decoded_audio->SwitchFormatTo(sink_sample_type_, kSbMediaAudioFrameStorageTypeInterleaved); const uint8_t* source_buffer = decoded_audio->buffer();
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h index 43be250..af4fd90 100644 --- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h +++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
@@ -144,7 +144,9 @@ void UpdateVariablesOnSinkThread_Locked(SbTime system_time_on_consume_frames); - void OnFirstOutput(); + void OnFirstOutput(const SbMediaAudioSampleType decoded_sample_type, + const SbMediaAudioFrameStorageType decoded_storage_type, + const int decoded_sample_rate); bool IsEndOfStreamPlayed_Locked() const; void OnDecoderConsumed();
diff --git a/src/starboard/shared/starboard/player/filter/audio_time_stretcher.cc b/src/starboard/shared/starboard/player/filter/audio_time_stretcher.cc index a75fca3..845d35e 100644 --- a/src/starboard/shared/starboard/player/filter/audio_time_stretcher.cc +++ b/src/starboard/shared/starboard/player/filter/audio_time_stretcher.cc
@@ -104,6 +104,8 @@ void AudioTimeStretcher::Initialize(SbMediaAudioSampleType sample_type, int channels, int samples_per_second) { + SB_DCHECK(samples_per_second > 0); + sample_type_ = sample_type; channels_ = channels; bytes_per_frame_ = media::GetBytesPerSample(sample_type_) * channels_;
diff --git a/src/starboard/shared/starboard/player/filter/cpu_video_frame.cc b/src/starboard/shared/starboard/player/filter/cpu_video_frame.cc index 1d79355..3aecfd4 100644 --- a/src/starboard/shared/starboard/player/filter/cpu_video_frame.cc +++ b/src/starboard/shared/starboard/player/filter/cpu_video_frame.cc
@@ -77,10 +77,21 @@ return s_clamp_table[component + 512]; } -void Copy10bitsPlane(uint8_t* destination, const uint8_t* source, int pixels) { +void CopyPlane(int bit_depth, + uint8_t* destination, + const uint8_t* source, + int pixels) { + if (bit_depth == 8) { + SbMemoryCopy(destination, source, pixels); + return; + } + SB_DCHECK(bit_depth == 10 || bit_depth == 12); + + const int conversion_factor = 1 << (bit_depth - 8); + const uint16_t* source_in_uint16 = reinterpret_cast<const uint16_t*>(source); while (pixels > 0) { - *destination = static_cast<uint8_t>(*source_in_uint16 / 4); + *destination = static_cast<uint8_t>(*source_in_uint16 / conversion_factor); ++source_in_uint16; ++destination; --pixels; @@ -174,7 +185,7 @@ const uint8_t* y, const uint8_t* u, const uint8_t* v) { - SB_DCHECK(bit_depth == 8 || bit_depth == 10); + SB_DCHECK(bit_depth == 8 || bit_depth == 10 || bit_depth == 12); scoped_refptr<CpuVideoFrame> frame(new CpuVideoFrame(timestamp)); frame->format_ = kYV12; @@ -182,7 +193,7 @@ frame->height_ = height; auto destination_pitch_in_bytes = source_pitch_in_bytes; - if (bit_depth == 10) { + if (bit_depth == 10 || bit_depth == 12) { // Reduce destination pitch to half as it will be converted into 8 bits. destination_pitch_in_bytes /= 2; } @@ -200,21 +211,13 @@ frame->pixel_buffer_.reset( new uint8_t[y_plane_size_in_bytes + uv_plane_size_in_bytes * 2]); - if (bit_depth == 8) { - SbMemoryCopy(frame->pixel_buffer_.get(), y, y_plane_size_in_bytes); - SbMemoryCopy(frame->pixel_buffer_.get() + y_plane_size_in_bytes, u, - uv_plane_size_in_bytes); - SbMemoryCopy(frame->pixel_buffer_.get() + y_plane_size_in_bytes + - uv_plane_size_in_bytes, - v, uv_plane_size_in_bytes); - } else { - Copy10bitsPlane(frame->pixel_buffer_.get(), y, y_plane_size_in_bytes); - Copy10bitsPlane(frame->pixel_buffer_.get() + y_plane_size_in_bytes, u, - uv_plane_size_in_bytes); - Copy10bitsPlane(frame->pixel_buffer_.get() + y_plane_size_in_bytes + - uv_plane_size_in_bytes, - v, uv_plane_size_in_bytes); - } + CopyPlane(bit_depth, frame->pixel_buffer_.get(), y, y_plane_size_in_bytes); + CopyPlane(bit_depth, frame->pixel_buffer_.get() + y_plane_size_in_bytes, u, + uv_plane_size_in_bytes); + CopyPlane(bit_depth, + frame->pixel_buffer_.get() + y_plane_size_in_bytes + + uv_plane_size_in_bytes, + v, uv_plane_size_in_bytes); frame->planes_.push_back(Plane(width, height, destination_pitch_in_bytes, frame->pixel_buffer_.get()));
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc index 6f5593e..ea3a192 100644 --- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc +++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -493,9 +493,14 @@ } SbDecodeTarget FilterBasedPlayerWorkerHandler::GetCurrentDecodeTarget() { - ::starboard::ScopedLock lock(video_renderer_existence_mutex_); - return video_renderer_ ? video_renderer_->GetCurrentDecodeTarget() - : kSbDecodeTargetInvalid; + SbDecodeTarget decode_target = kSbDecodeTargetInvalid; + if (video_renderer_existence_mutex_.AcquireTry()) { + if (video_renderer_) { + decode_target = video_renderer_->GetCurrentDecodeTarget(); + } + video_renderer_existence_mutex_.Release(); + } + return decode_target; } MediaTimeProvider* FilterBasedPlayerWorkerHandler::GetMediaTimeProvider()
diff --git a/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h b/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h index 0f5af0f..c8b120c 100644 --- a/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h +++ b/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
@@ -37,30 +37,14 @@ public: MockAudioDecoder(SbMediaAudioSampleType sample_type, SbMediaAudioFrameStorageType storage_type, - int sample_per_second) - : sample_type_(sample_type), - storage_type_(storage_type), - samples_per_second_(sample_per_second) {} + int samples_per_second) {} MOCK_METHOD2(Initialize, void(const OutputCB&, const ErrorCB&)); MOCK_METHOD2(Decode, void(const scoped_refptr<InputBuffer>&, const ConsumedCB&)); MOCK_METHOD0(WriteEndOfStream, void()); - MOCK_METHOD0(Read, scoped_refptr<DecodedAudio>()); + MOCK_METHOD1(Read, scoped_refptr<DecodedAudio>(int*)); MOCK_METHOD0(Reset, void()); - - SbMediaAudioSampleType GetSampleType() const override { - return sample_type_; - } - SbMediaAudioFrameStorageType GetStorageType() const override { - return storage_type_; - } - int GetSamplesPerSecond() const override { return samples_per_second_; } - - private: - SbMediaAudioSampleType sample_type_; - SbMediaAudioFrameStorageType storage_type_; - int samples_per_second_; }; } // namespace testing
diff --git a/src/starboard/shared/starboard/player/filter/player_filter.gypi b/src/starboard/shared/starboard/player/filter/player_filter.gypi index 9515f24..1a32ffb 100644 --- a/src/starboard/shared/starboard/player/filter/player_filter.gypi +++ b/src/starboard/shared/starboard/player/filter/player_filter.gypi
@@ -16,6 +16,8 @@ 'filter_based_player_sources': [ '<(DEPTH)/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h', + '<(DEPTH)/starboard/shared/starboard/player/filter/audio_channel_layout_mixer.h', + '<(DEPTH)/starboard/shared/starboard/player/filter/audio_channel_layout_mixer_impl.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_frame_tracker.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_frame_tracker.h',
diff --git a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc index b5888c1..13ffdc3 100644 --- a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc +++ b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.cc
@@ -65,8 +65,8 @@ SbTime diff = input_buffer->timestamp() - last_input_buffer_->timestamp(); SB_DCHECK(diff >= 0); size_t sample_size = - GetSampleType() == kSbMediaAudioSampleTypeInt16Deprecated ? 2 : 4; - size_t size = diff * GetSamplesPerSecond() * sample_size * + sample_type_ == kSbMediaAudioSampleTypeInt16Deprecated ? 2 : 4; + size_t size = diff * audio_sample_info_.samples_per_second * sample_size * audio_sample_info_.number_of_channels / kSbTimeSecond; size -= size % (sample_size * audio_sample_info_.number_of_channels); if (audio_codec_ == kSbMediaAudioCodecAac) { @@ -75,9 +75,10 @@ size = sample_size * audio_sample_info_.number_of_channels * 1024; } - decoded_audios_.push(new DecodedAudio( - audio_sample_info_.number_of_channels, GetSampleType(), - GetStorageType(), last_input_buffer_->timestamp(), size)); + decoded_audios_.push( + new DecodedAudio(audio_sample_info_.number_of_channels, sample_type_, + kSbMediaAudioFrameStorageTypeInterleaved, + last_input_buffer_->timestamp(), size)); if (fill_type == kSilence) { SbMemorySet(decoded_audios_.back()->buffer(), 0, size); @@ -106,7 +107,7 @@ // 4 times the encoded size. size_t fake_size = 4 * last_input_buffer_->size(); size_t sample_size = - GetSampleType() == kSbMediaAudioSampleTypeInt16Deprecated ? 2 : 4; + sample_type_ == kSbMediaAudioSampleTypeInt16Deprecated ? 2 : 4; fake_size -= fake_size % (sample_size * audio_sample_info_.number_of_channels); if (audio_codec_ == kSbMediaAudioCodecAac) { @@ -114,9 +115,10 @@ // number of frames matches up. fake_size = sample_size * audio_sample_info_.number_of_channels * 1024; } - decoded_audios_.push(new DecodedAudio( - audio_sample_info_.number_of_channels, GetSampleType(), - GetStorageType(), last_input_buffer_->timestamp(), fake_size)); + decoded_audios_.push( + new DecodedAudio(audio_sample_info_.number_of_channels, sample_type_, + kSbMediaAudioFrameStorageTypeInterleaved, + last_input_buffer_->timestamp(), fake_size)); Schedule(output_cb_); } decoded_audios_.push(new DecodedAudio()); @@ -124,12 +126,13 @@ Schedule(output_cb_); } -scoped_refptr<DecodedAudio> StubAudioDecoder::Read() { +scoped_refptr<DecodedAudio> StubAudioDecoder::Read(int* samples_per_second) { scoped_refptr<DecodedAudio> result; if (!decoded_audios_.empty()) { result = decoded_audios_.front(); decoded_audios_.pop(); } + *samples_per_second = audio_sample_info_.samples_per_second; return result; } @@ -142,15 +145,6 @@ CancelPendingJobs(); } -SbMediaAudioSampleType StubAudioDecoder::GetSampleType() const { - return sample_type_; -} -SbMediaAudioFrameStorageType StubAudioDecoder::GetStorageType() const { - return kSbMediaAudioFrameStorageTypeInterleaved; -} -int StubAudioDecoder::GetSamplesPerSecond() const { - return audio_sample_info_.samples_per_second; -} } // namespace filter } // namespace player
diff --git a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.h b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.h index d42ecd0..0fe3aa1 100644 --- a/src/starboard/shared/starboard/player/filter/stub_audio_decoder.h +++ b/src/starboard/shared/starboard/player/filter/stub_audio_decoder.h
@@ -40,16 +40,10 @@ void WriteEndOfStream() override; - scoped_refptr<DecodedAudio> Read() override; + scoped_refptr<DecodedAudio> Read(int* samples_per_second) override; void Reset() override; - SbMediaAudioSampleType GetSampleType() const override; - - SbMediaAudioFrameStorageType GetStorageType() const override; - - int GetSamplesPerSecond() const override; - private: OutputCB output_cb_; SbMediaAudioSampleType sample_type_;
diff --git a/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc index c68e925..c5af2e8 100644 --- a/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc +++ b/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc
@@ -252,10 +252,6 @@ break; } case kOutput: { - if (!first_output_received_) { - output_sample_rate_ = audio_decoder_->GetSamplesPerSecond(); - first_output_received_ = true; - } ReadFromDecoder(); break; } @@ -268,8 +264,16 @@ } void ReadFromDecoder() { - scoped_refptr<DecodedAudio> decoded_audio = audio_decoder_->Read(); + int samples_per_second; + scoped_refptr<DecodedAudio> decoded_audio = + audio_decoder_->Read(&samples_per_second); ASSERT_TRUE(decoded_audio); + if (first_output_received_) { + ASSERT_EQ(output_sample_rate_, samples_per_second); + } else { + output_sample_rate_ = samples_per_second; + first_output_received_ = true; + } if (decoded_audio->is_end_of_stream()) { last_decoded_audio_ = decoded_audio; @@ -366,16 +370,19 @@ } vector<vector<const char*>> GetSupportedTests() { - // beneath_the_canopy_140_aac.dmp + // beneath_the_canopy_aac_stereo.dmp // codec: kSbMediaAudioCodecAac // sampling rate: 44.1k // frames per AU: 1024 - // beneath_the_canopy_249_opus.dmp + // beneath_the_canopy_opus_stereo.dmp // codec: kSbMediaAudioCodecOpus // sampling rate: 48.0k // frames per AU: 960 - const char* kFilenames[] = {"beneath_the_canopy_140_aac.dmp", - "beneath_the_canopy_249_opus.dmp"}; + const char* kFilenames[] = { + "beneath_the_canopy_aac_stereo.dmp", "beneath_the_canopy_aac_5_1.dmp", + "beneath_the_canopy_aac_mono.dmp", "beneath_the_canopy_opus_5_1.dmp", + "beneath_the_canopy_opus_stereo.dmp", "beneath_the_canopy_opus_mono.dmp", + }; static vector<vector<const char*>> test_params;
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_channel_layout_mixer_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_channel_layout_mixer_test.cc new file mode 100644 index 0000000..2ca3a1c --- /dev/null +++ b/src/starboard/shared/starboard/player/filter/testing/audio_channel_layout_mixer_test.cc
@@ -0,0 +1,347 @@ +// Copyright 2019 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 <cmath> +#include <functional> +#include <numeric> + +#include "starboard/common/ref_counted.h" +#include "starboard/common/scoped_ptr.h" +#include "starboard/shared/starboard/player/decoded_audio_internal.h" +#include "starboard/shared/starboard/player/filter/audio_channel_layout_mixer.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if SB_HAS(PLAYER_FILTER_TESTS) + +namespace starboard { +namespace shared { +namespace starboard { +namespace player { +namespace filter { +namespace testing { +namespace { + +using ::testing::Combine; +using ::testing::Values; + +class AudioChannelLayoutMixerTest + : public ::testing::TestWithParam< + std::tuple<SbMediaAudioSampleType, SbMediaAudioFrameStorageType>> { + protected: + AudioChannelLayoutMixerTest() + : sample_type_(std::get<0>(GetParam())), + storage_type_(std::get<1>(GetParam())) { + SB_DCHECK(sample_type_ == kSbMediaAudioSampleTypeInt16Deprecated || + sample_type_ == kSbMediaAudioSampleTypeFloat32); + SB_DCHECK(storage_type_ == kSbMediaAudioFrameStorageTypeInterleaved || + storage_type_ == kSbMediaAudioFrameStorageTypePlanar); + } + + scoped_refptr<DecodedAudio> GetTestDecodedAudio(int num_of_channels) { + // Interleaved test audio data, stored in float. + const float kMonoInputAudioData[] = { + -1.0f, -0.5f, 0.0f, 0.5f, 1.0f, + }; + + const float kStereoInputAudioData[] = { + -1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 1.0f, 1.0f, + }; + + const float kQuadInputAudioData[] = { + -1.0f, 1.0f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, + }; + + const float kFivePointOneInputAudioData[] = { + -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -0.5f, 0.5f, 0.5f, -0.5f, + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + }; + + const size_t kInputFrames = SB_ARRAY_SIZE(kMonoInputAudioData); + + const float* data_buffer; + if (num_of_channels == 1) { + data_buffer = kMonoInputAudioData; + } else if (num_of_channels == 2) { + data_buffer = kStereoInputAudioData; + } else if (num_of_channels == 4) { + data_buffer = kQuadInputAudioData; + } else if (num_of_channels == 6) { + data_buffer = kFivePointOneInputAudioData; + } else { + SB_NOTREACHED() << "Invalid number of channels."; + } + + scoped_refptr<DecodedAudio> decoded_audio(new DecodedAudio( + num_of_channels, sample_type_, storage_type_, 0, + kInputFrames * num_of_channels * + (sample_type_ == kSbMediaAudioSampleTypeFloat32 ? 4 : 2))); + + if (sample_type_ == kSbMediaAudioSampleTypeFloat32) { + float* dest_buffer = reinterpret_cast<float*>(decoded_audio->buffer()); + for (size_t i = 0; i < num_of_channels * kInputFrames; i++) { + int src_index = i; + if (storage_type_ == kSbMediaAudioFrameStorageTypePlanar) { + src_index = i % kInputFrames * num_of_channels + i / kInputFrames; + } + dest_buffer[i] = data_buffer[src_index]; + } + } else { + int16_t* dest_buffer = + reinterpret_cast<int16_t*>(decoded_audio->buffer()); + for (size_t i = 0; i < num_of_channels * kInputFrames; i++) { + int src_index = i; + if (storage_type_ == kSbMediaAudioFrameStorageTypePlanar) { + src_index = i % kInputFrames * num_of_channels + i / kInputFrames; + } + dest_buffer[i] = data_buffer[src_index] * kSbInt16Max; + } + } + return decoded_audio; + } + + void AssertExpectedAndOutputMatch(const scoped_refptr<DecodedAudio>& input, + const scoped_refptr<DecodedAudio>& output, + int output_num_of_channels, + const float* expected_output) { + ASSERT_EQ(output_num_of_channels, output->channels()); + ASSERT_EQ(input->sample_type(), output->sample_type()); + ASSERT_EQ(input->storage_type(), output->storage_type()); + ASSERT_EQ(input->timestamp(), output->timestamp()); + ASSERT_EQ(input->size() * output->channels(), + output->size() * input->channels()); + + if (sample_type_ == kSbMediaAudioSampleTypeFloat32) { + float* output_buffer = reinterpret_cast<float*>(output->buffer()); + for (size_t i = 0; i < output->frames() * output_num_of_channels; i++) { + int src_index = i; + if (storage_type_ == kSbMediaAudioFrameStorageTypePlanar) { + src_index = i % output->frames() * output_num_of_channels + + i / output->frames(); + } + if (expected_output[src_index] >= 1.0f) { + ASSERT_GE(output_buffer[i], 0.999f); + } else if (expected_output[src_index] <= -0.999f) { + ASSERT_LE(output_buffer[i], -1.0f); + } else { + ASSERT_LE(fabs(expected_output[src_index] - output_buffer[i]), + 0.001f); + } + } + } else { + int16_t* output_buffer = reinterpret_cast<int16_t*>(output->buffer()); + for (size_t i = 0; i < output->frames() * output_num_of_channels; i++) { + int src_index = i; + if (storage_type_ == kSbMediaAudioFrameStorageTypePlanar) { + src_index = i % output->frames() * output_num_of_channels + + i / output->frames(); + } + ASSERT_LE(fabs(expected_output[src_index] - + static_cast<float>(output_buffer[i]) / + static_cast<float>(kSbInt16Max)), + 0.001f); + } + } + } + + SbMediaAudioSampleType sample_type_; + SbMediaAudioFrameStorageType storage_type_; +}; + +TEST_P(AudioChannelLayoutMixerTest, MixToMono) { + scoped_ptr<AudioChannelLayoutMixer> mixer = + AudioChannelLayoutMixer::Create(sample_type_, storage_type_, 1); + ASSERT_TRUE(mixer); + + const float kExpectedMonoToMonoOutput[] = { + -1.0f, -0.5f, 0.0f, 0.5f, 1.0f, + }; + scoped_refptr<DecodedAudio> mono_input = GetTestDecodedAudio(1); + scoped_refptr<DecodedAudio> mono_output = mixer->Mix(mono_input); + AssertExpectedAndOutputMatch(mono_input, mono_output, 1, + kExpectedMonoToMonoOutput); + + const float kExpectedStereoToMonoOutput[] = { + -0.25f, 0.0f, 0.0f, 0.5f, 1.0f, + }; + scoped_refptr<DecodedAudio> stereo_input = GetTestDecodedAudio(2); + scoped_refptr<DecodedAudio> stereo_output = mixer->Mix(stereo_input); + AssertExpectedAndOutputMatch(stereo_input, stereo_output, 1, + kExpectedStereoToMonoOutput); + + const float kExpectedQuadToMonoOutput[] = { + 0.0f, -0.25f, 0.0f, 0.5f, 1.0f, + }; + scoped_refptr<DecodedAudio> quad_input = GetTestDecodedAudio(4); + scoped_refptr<DecodedAudio> quad_output = mixer->Mix(quad_input); + AssertExpectedAndOutputMatch(quad_input, quad_output, 1, + kExpectedQuadToMonoOutput); + + const float kExpectedFivePointOneToMonoOutput[] = { + 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> five_point_one_input = GetTestDecodedAudio(6); + scoped_refptr<DecodedAudio> five_point_one_output = + mixer->Mix(five_point_one_input); + AssertExpectedAndOutputMatch(five_point_one_input, five_point_one_output, 1, + kExpectedFivePointOneToMonoOutput); +} + +TEST_P(AudioChannelLayoutMixerTest, MixToStereo) { + scoped_ptr<AudioChannelLayoutMixer> mixer = + AudioChannelLayoutMixer::Create(sample_type_, storage_type_, 2); + ASSERT_TRUE(mixer); + + const float kExpectedMonoToStereoOutput[] = { + -1.0f, -1.0f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> mono_input = GetTestDecodedAudio(1); + scoped_refptr<DecodedAudio> mono_output = mixer->Mix(mono_input); + AssertExpectedAndOutputMatch(mono_input, mono_output, 2, + kExpectedMonoToStereoOutput); + + const float kExpectedStereoToStereoOutput[] = { + -1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> stereo_input = GetTestDecodedAudio(2); + scoped_refptr<DecodedAudio> stereo_output = mixer->Mix(stereo_input); + AssertExpectedAndOutputMatch(stereo_input, stereo_output, 2, + kExpectedStereoToStereoOutput); + + const float kExpectedQuadToStereoOutput[] = { + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> quad_input = GetTestDecodedAudio(4); + scoped_refptr<DecodedAudio> quad_output = mixer->Mix(quad_input); + AssertExpectedAndOutputMatch(quad_input, quad_output, 2, + kExpectedQuadToStereoOutput); + + const float kExpectedFivePointOneToStereoOutput[] = { + -1.0f, 1.0f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> five_point_one_input = GetTestDecodedAudio(6); + scoped_refptr<DecodedAudio> five_point_one_output = + mixer->Mix(five_point_one_input); + AssertExpectedAndOutputMatch(five_point_one_input, five_point_one_output, 2, + kExpectedFivePointOneToStereoOutput); +} + +TEST_P(AudioChannelLayoutMixerTest, MixToQuad) { + scoped_ptr<AudioChannelLayoutMixer> mixer = + AudioChannelLayoutMixer::Create(sample_type_, storage_type_, 4); + ASSERT_TRUE(mixer); + + const float kExpectedMonoToQuadOutput[] = { + -1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, + }; + scoped_refptr<DecodedAudio> mono_input = GetTestDecodedAudio(1); + scoped_refptr<DecodedAudio> mono_output = mixer->Mix(mono_input); + AssertExpectedAndOutputMatch(mono_input, mono_output, 4, + kExpectedMonoToQuadOutput); + + const float kExpectedStereoToQuadOutput[] = { + -1.0f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, + }; + scoped_refptr<DecodedAudio> stereo_input = GetTestDecodedAudio(2); + scoped_refptr<DecodedAudio> stereo_output = mixer->Mix(stereo_input); + AssertExpectedAndOutputMatch(stereo_input, stereo_output, 4, + kExpectedStereoToQuadOutput); + + const float kExpectedQuadToQuadOutput[] = { + -1.0f, 1.0f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> quad_input = GetTestDecodedAudio(4); + scoped_refptr<DecodedAudio> quad_output = mixer->Mix(quad_input); + AssertExpectedAndOutputMatch(quad_input, quad_output, 4, + kExpectedQuadToQuadOutput); + + const float kExpectedFivePointOneToQuadOutput[] = { + -0.2929f, 1.0f, -1.0f, -1.0f, -0.1464f, 0.8535f, -0.5f, + -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.8535f, 0.8535f, + 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> five_point_one_input = GetTestDecodedAudio(6); + scoped_refptr<DecodedAudio> five_point_one_output = + mixer->Mix(five_point_one_input); + AssertExpectedAndOutputMatch(five_point_one_input, five_point_one_output, 4, + kExpectedFivePointOneToQuadOutput); +} + +TEST_P(AudioChannelLayoutMixerTest, MixToFivePointOne) { + scoped_ptr<AudioChannelLayoutMixer> mixer = + AudioChannelLayoutMixer::Create(sample_type_, storage_type_, 6); + ASSERT_TRUE(mixer); + + const float kExpectedMonoToFivePointOneOutput[] = { + 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, + }; + scoped_refptr<DecodedAudio> mono_input = GetTestDecodedAudio(1); + scoped_refptr<DecodedAudio> mono_output = mixer->Mix(mono_input); + AssertExpectedAndOutputMatch(mono_input, mono_output, 6, + kExpectedMonoToFivePointOneOutput); + + const float kExpectedStereoToFivePointOneOutput[] = { + -1.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + }; + scoped_refptr<DecodedAudio> stereo_input = GetTestDecodedAudio(2); + scoped_refptr<DecodedAudio> stereo_output = mixer->Mix(stereo_input); + AssertExpectedAndOutputMatch(stereo_input, stereo_output, 6, + kExpectedStereoToFivePointOneOutput); + + const float kExpectedQuadToFivePointOneOutput[] = { + -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, + 0.0f, 0.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> quad_input = GetTestDecodedAudio(4); + scoped_refptr<DecodedAudio> quad_output = mixer->Mix(quad_input); + AssertExpectedAndOutputMatch(quad_input, quad_output, 6, + kExpectedQuadToFivePointOneOutput); + + const float kExpectedFivePointOneToFivePointOneOutput[] = { + -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -0.5f, 0.5f, 0.5f, -0.5f, + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + }; + scoped_refptr<DecodedAudio> five_point_one_input = GetTestDecodedAudio(6); + scoped_refptr<DecodedAudio> five_point_one_output = + mixer->Mix(five_point_one_input); + AssertExpectedAndOutputMatch(five_point_one_input, five_point_one_output, 6, + kExpectedFivePointOneToFivePointOneOutput); +} + +INSTANTIATE_TEST_CASE_P(AudioChannelLayoutMixerTests, + AudioChannelLayoutMixerTest, + Combine(Values(kSbMediaAudioSampleTypeInt16Deprecated, + kSbMediaAudioSampleTypeFloat32), + Values(kSbMediaAudioFrameStorageTypeInterleaved, + kSbMediaAudioFrameStorageTypePlanar))); + +} // namespace +} // namespace testing +} // namespace filter +} // namespace player +} // namespace starboard +} // namespace shared +} // namespace starboard + +#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc index 4f348d8..179dac1 100644 --- a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc +++ b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
@@ -25,6 +25,7 @@ #include "starboard/memory.h" #include "starboard/shared/starboard/media/media_support_internal.h" #include "starboard/shared/starboard/media/media_util.h" +#include "starboard/shared/starboard/player/decoded_audio_internal.h" #include "starboard/shared/starboard/player/filter/player_components.h" #include "starboard/shared/starboard/player/filter/stub_player_components_impl.h" #include "starboard/shared/starboard/player/video_dmp_reader.h" @@ -92,9 +93,27 @@ ASSERT_NE(dmp_reader_.audio_codec(), kSbMediaAudioCodecNone); ASSERT_GT(dmp_reader_.number_of_audio_buffers(), 0); + CreateComponents(dmp_reader_.audio_codec(), dmp_reader_.audio_sample_info(), + &audio_decoder_, &audio_renderer_sink_); + ASSERT_TRUE(audio_decoder_); + ASSERT_TRUE(audio_renderer_sink_); + } + + protected: + enum Event { kConsumed, kOutput, kError }; + + void CreateComponents(SbMediaAudioCodec codec, + const SbMediaAudioSampleInfo& audio_sample_info, + scoped_ptr<AudioDecoder>* audio_decoder, + scoped_ptr<AudioRendererSink>* audio_renderer_sink) { + ASSERT_TRUE(audio_decoder); + ASSERT_TRUE(audio_renderer_sink); + + audio_renderer_sink->reset(); + audio_decoder->reset(); + PlayerComponents::AudioParameters audio_parameters = { - dmp_reader_.audio_codec(), dmp_reader_.audio_sample_info(), - kSbDrmSystemInvalid}; + codec, audio_sample_info, kSbDrmSystemInvalid}; scoped_ptr<PlayerComponents> components; if (using_stub_decoder_) { @@ -103,26 +122,25 @@ } else { components = PlayerComponents::Create(); } - components->CreateAudioComponents(audio_parameters, &audio_decoder_, - &audio_renderer_sink_); - ASSERT_TRUE(audio_decoder_); - - audio_decoder_->Initialize(std::bind(&AudioDecoderTest::OnOutput, this), - std::bind(&AudioDecoderTest::OnError, this)); + components->CreateAudioComponents(audio_parameters, audio_decoder, + audio_renderer_sink); + if (*audio_decoder) { + (*audio_decoder) + ->Initialize(std::bind(&AudioDecoderTest::OnOutput, this), + std::bind(&AudioDecoderTest::OnError, this)); + } } void OnOutput() { ScopedLock scoped_lock(event_queue_mutex_); event_queue_.push_back(kOutput); } + void OnError() { ScopedLock scoped_lock(event_queue_mutex_); event_queue_.push_back(kError); } - protected: - enum Event { kConsumed, kOutput, kError }; - void OnConsumed() { ScopedLock scoped_lock(event_queue_mutex_); event_queue_.push_back(kConsumed); @@ -172,13 +190,25 @@ void ReadFromDecoder(scoped_refptr<DecodedAudio>* decoded_audio) { ASSERT_TRUE(decoded_audio); - scoped_refptr<DecodedAudio> local_decoded_audio = audio_decoder_->Read(); + int decoded_sample_rate; + scoped_refptr<DecodedAudio> local_decoded_audio = + audio_decoder_->Read(&decoded_sample_rate); ASSERT_TRUE(local_decoded_audio); + if (!first_output_received_) { + first_output_received_ = true; + decoded_audio_sample_type_ = local_decoded_audio->sample_type(); + decoded_audio_storage_type_ = local_decoded_audio->storage_type(); + decoded_audio_samples_per_second_ = decoded_sample_rate; + } if (local_decoded_audio->is_end_of_stream()) { *decoded_audio = local_decoded_audio; return; } + ASSERT_EQ(decoded_audio_sample_type_, local_decoded_audio->sample_type()); + ASSERT_EQ(decoded_audio_storage_type_, local_decoded_audio->storage_type()); + ASSERT_EQ(decoded_audio_samples_per_second_, decoded_sample_rate); + // TODO: Adaptive audio decoder outputs may don't have timestamp info. // Currently, we skip timestamp check if the outputs don't have timestamp // info. Enable it after we fix timestamp issues. @@ -193,7 +223,7 @@ void WriteMultipleInputs(size_t start_index, size_t number_of_inputs_to_write, - bool* error_occurred = NULL) { + bool* error_occurred = nullptr) { ASSERT_LE(start_index + number_of_inputs_to_write, dmp_reader_.number_of_audio_buffers()); @@ -259,7 +289,7 @@ } } - void DrainOutputs(bool* error_occurred = NULL) { + void DrainOutputs(bool* error_occurred = nullptr) { if (error_occurred) { *error_occurred = false; } @@ -291,9 +321,11 @@ void ResetDecoder() { audio_decoder_->Reset(); can_accept_more_input_ = true; - last_input_buffer_ = NULL; - last_decoded_audio_ = NULL; + last_input_buffer_ = nullptr; + last_decoded_audio_ = nullptr; eos_written_ = false; + decoded_audio_samples_per_second_ = 0; + first_output_received_ = false; } void WaitForDecodedAudio() { @@ -315,14 +347,14 @@ auto player_sample_info = dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeAudio, index); #if SB_API_VERSION >= 11 - auto input_buffer = - new InputBuffer(DeallocateSampleFunc, NULL, NULL, player_sample_info); + auto input_buffer = new InputBuffer(DeallocateSampleFunc, nullptr, nullptr, + player_sample_info); #else // SB_API_VERSION >= 11 SbMediaAudioSampleInfo audio_sample_info = dmp_reader_.GetAudioSampleInfo(index); auto input_buffer = - new InputBuffer(kSbMediaTypeAudio, DeallocateSampleFunc, NULL, NULL, - player_sample_info, &audio_sample_info); + new InputBuffer(kSbMediaTypeAudio, DeallocateSampleFunc, nullptr, + nullptr, player_sample_info, &audio_sample_info); #endif // SB_API_VERSION >= 11 auto iter = invalid_inputs_.find(index); if (iter != invalid_inputs_.end()) { @@ -345,19 +377,17 @@ } void AssertInvalidOutputFormat() { - SbMediaAudioSampleType output_sample_type = audio_decoder_->GetSampleType(); - ASSERT_TRUE(output_sample_type == kSbMediaAudioSampleTypeFloat32 || - output_sample_type == kSbMediaAudioSampleTypeInt16Deprecated); + ASSERT_TRUE(decoded_audio_sample_type_ == kSbMediaAudioSampleTypeFloat32 || + decoded_audio_sample_type_ == + kSbMediaAudioSampleTypeInt16Deprecated); - SbMediaAudioFrameStorageType output_storage_type = - audio_decoder_->GetStorageType(); - ASSERT_TRUE(output_storage_type == + ASSERT_TRUE(decoded_audio_storage_type_ == kSbMediaAudioFrameStorageTypeInterleaved || - output_storage_type == kSbMediaAudioFrameStorageTypePlanar); + decoded_audio_storage_type_ == + kSbMediaAudioFrameStorageTypePlanar); - int output_samples_per_second = audio_decoder_->GetSamplesPerSecond(); - ASSERT_TRUE(output_samples_per_second > 0 && - output_samples_per_second <= 480000); + ASSERT_TRUE(decoded_audio_samples_per_second_ > 0 && + decoded_audio_samples_per_second_ <= 480000); } void AssertExpectedAndOutputFramesMatch(int expected_output_frames) { @@ -393,26 +423,29 @@ std::map<size_t, uint8_t> invalid_inputs_; int num_of_output_frames_ = 0; + + SbMediaAudioSampleType decoded_audio_sample_type_ = + kSbMediaAudioSampleTypeInt16Deprecated; + SbMediaAudioFrameStorageType decoded_audio_storage_type_ = + kSbMediaAudioFrameStorageTypeInterleaved; + int decoded_audio_samples_per_second_ = 0; + + bool first_output_received_ = false; }; -TEST_P(AudioDecoderTest, ThreeMoreDecoders) { - const int kDecodersToCreate = 3; +TEST_P(AudioDecoderTest, MultiDecoders) { + const int kDecodersToCreate = 100; + const int kMinimumNumberOfExtraDecodersRequired = 3; - PlayerComponents::AudioParameters audio_parameters = { - dmp_reader_.audio_codec(), dmp_reader_.audio_sample_info(), - kSbDrmSystemInvalid}; - - scoped_ptr<PlayerComponents> components = PlayerComponents::Create(); scoped_ptr<AudioDecoder> audio_decoders[kDecodersToCreate]; scoped_ptr<AudioRendererSink> audio_renderer_sinks[kDecodersToCreate]; for (int i = 0; i < kDecodersToCreate; ++i) { - components->CreateAudioComponents(audio_parameters, &audio_decoders[i], - &audio_renderer_sinks[i]); - ASSERT_TRUE(audio_decoders[i]); - - audio_decoders[i]->Initialize(std::bind(&AudioDecoderTest::OnOutput, this), - std::bind(&AudioDecoderTest::OnError, this)); + CreateComponents(dmp_reader_.audio_codec(), dmp_reader_.audio_sample_info(), + &audio_decoders[i], &audio_renderer_sinks[i]); + if (!audio_decoders[i]) { + ASSERT_GE(i, kMinimumNumberOfExtraDecodersRequired); + } } } @@ -441,13 +474,87 @@ int input_sample_rate = last_input_buffer_->audio_sample_info().samples_per_second; - int output_sample_rate = audio_decoder_->GetSamplesPerSecond(); - ASSERT_NE(0, output_sample_rate); + ASSERT_NE(0, decoded_audio_samples_per_second_); int expected_output_frames = - kAacFrameSize * output_sample_rate / input_sample_rate; + kAacFrameSize * decoded_audio_samples_per_second_ / input_sample_rate; AssertExpectedAndOutputFramesMatch(expected_output_frames); } +TEST_P(AudioDecoderTest, InvalidCodec) { + auto invalid_codec = dmp_reader_.audio_codec() == kSbMediaAudioCodecAac + ? kSbMediaAudioCodecOpus + : kSbMediaAudioCodecAac; + auto audio_sample_info = dmp_reader_.audio_sample_info(); + +#if SB_API_VERSION >= 11 + audio_sample_info.codec = invalid_codec; +#endif // SB_API_VERSION >= 11 + + CreateComponents(invalid_codec, audio_sample_info, &audio_decoder_, + &audio_renderer_sink_); + if (!audio_decoder_) { + return; + } + + WriteSingleInput(0); + WriteEndOfStream(); + + bool error_occurred = true; + ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); +} + +TEST_P(AudioDecoderTest, InvalidConfig) { + auto original_audio_sample_info = dmp_reader_.audio_sample_info(); + + for (uint16_t i = 0; + i < original_audio_sample_info.audio_specific_config_size; ++i) { + std::vector<uint8_t> config( + original_audio_sample_info.audio_specific_config_size); + SbMemoryCopy(config.data(), + original_audio_sample_info.audio_specific_config, + original_audio_sample_info.audio_specific_config_size); + auto audio_sample_info = original_audio_sample_info; + config[i] = ~config[i]; + audio_sample_info.audio_specific_config = config.data(); + + CreateComponents(dmp_reader_.audio_codec(), audio_sample_info, + &audio_decoder_, &audio_renderer_sink_); + if (!audio_decoder_) { + return; + } + WriteSingleInput(0); + WriteEndOfStream(); + + bool error_occurred = true; + ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); + + ResetDecoder(); + } + + for (uint16_t i = 0; + i < original_audio_sample_info.audio_specific_config_size; ++i) { + std::vector<uint8_t> config(i); + SbMemoryCopy(config.data(), + original_audio_sample_info.audio_specific_config, i); + auto audio_sample_info = original_audio_sample_info; + audio_sample_info.audio_specific_config = config.data(); + audio_sample_info.audio_specific_config_size = i; + + CreateComponents(dmp_reader_.audio_codec(), audio_sample_info, + &audio_decoder_, &audio_renderer_sink_); + if (!audio_decoder_) { + return; + } + WriteSingleInput(0); + WriteEndOfStream(); + + bool error_occurred = true; + ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); + + ResetDecoder(); + } +} + TEST_P(AudioDecoderTest, SingleInvalidInput) { UseInvalidDataForInput(0, 0xab); @@ -582,8 +689,10 @@ #endif // SB_API_VERSION >= 11 std::vector<const char*> GetSupportedTests() { - const char* kFilenames[] = {"beneath_the_canopy_140_aac.dmp", - "beneath_the_canopy_249_opus.dmp", "heaac.dmp"}; + const char* kFilenames[] = { + "beneath_the_canopy_aac_5_1.dmp", "beneath_the_canopy_aac_stereo.dmp", + "beneath_the_canopy_opus_5_1.dmp", "beneath_the_canopy_opus_stereo.dmp", + "heaac.dmp"}; static std::vector<const char*> test_params;
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc index 9d9458b..78331f7 100644 --- a/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc +++ b/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
@@ -44,12 +44,13 @@ using ::testing::InvokeWithoutArgs; using ::testing::Return; using ::testing::SaveArg; +using ::testing::SetArgPointee; // TODO: Write tests to cover callbacks. class AudioRendererTest : public ::testing::Test { protected: static const int kDefaultNumberOfChannels = 2; - static const int kDefaultSamplesPerSecond = 100000; + static const int kDefaultSamplesPerSecond; static const SbMediaAudioSampleType kDefaultAudioSampleType = kSbMediaAudioSampleTypeFloat32; static const SbMediaAudioFrameStorageType kDefaultAudioFrameStorageType = @@ -71,6 +72,10 @@ audio_decoder_ = new MockAudioDecoder(sample_type_, storage_type_, kDefaultSamplesPerSecond); + ON_CALL(*audio_decoder_, Read(_)) + .WillByDefault( + DoAll(SetArgPointee<0>(kDefaultSamplesPerSecond), + Return(scoped_refptr<DecodedAudio>(new DecodedAudio())))); ON_CALL(*audio_renderer_sink_, Start(_, _, _, _, _, _, _)) .WillByDefault(DoAll(InvokeWithoutArgs([this]() { audio_renderer_sink_->SetHasStarted(true); @@ -177,7 +182,9 @@ void SendDecoderOutput(const scoped_refptr<DecodedAudio>& decoded_audio) { ASSERT_TRUE(output_cb_); - EXPECT_CALL(*audio_decoder_, Read()).WillOnce(Return(decoded_audio)); + EXPECT_CALL(*audio_decoder_, Read(_)) + .WillOnce(DoAll(SetArgPointee<0>(kDefaultSamplesPerSecond), + Return(decoded_audio))); output_cb_(); job_queue_.RunUntilIdle(); } @@ -263,6 +270,9 @@ } }; +// static +const int AudioRendererTest::kDefaultSamplesPerSecond = 100000; + TEST_F(AudioRendererTest, StateAfterConstructed) { EXPECT_FALSE(audio_renderer_->IsEndOfStreamWritten()); EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
diff --git a/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp b/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp index 8c29ef1..60f08fc 100644 --- a/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp +++ b/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp
@@ -20,6 +20,7 @@ 'sources': [ '<(DEPTH)/starboard/common/test_main.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc', + '<(DEPTH)/starboard/shared/starboard/player/filter/testing/audio_channel_layout_mixer_test.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc',
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc index c02bbcf..93c50f6 100644 --- a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc +++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
@@ -130,10 +130,7 @@ output_mode, dmp_reader_.video_codec(), kSbDrmSystemInvalid)); PlayerComponents::VideoParameters video_parameters = { - &player_, - dmp_reader_.video_codec(), - kSbDrmSystemInvalid, - output_mode, + &player_, dmp_reader_.video_codec(), kSbDrmSystemInvalid, output_mode, fake_graphics_context_provider_.decoder_target_provider()}; scoped_ptr<PlayerComponents> components; @@ -156,6 +153,11 @@ video_decoder_->Initialize( std::bind(&VideoDecoderTest::OnDecoderStatusUpdate, this, _1, _2), std::bind(&VideoDecoderTest::OnError, this)); + if (HasPendingEvents()) { + bool error_occurred = false; + ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); + ASSERT_FALSE(error_occurred); + } } void Render(VideoRendererSink::DrawFrameCB draw_frame_cb) { @@ -562,9 +564,7 @@ for (int i = 0; i < kDecodersToCreate; ++i) { PlayerComponents::VideoParameters video_parameters = { - &players[i], - dmp_reader_.video_codec(), - kSbDrmSystemInvalid, + &players[i], dmp_reader_.video_codec(), kSbDrmSystemInvalid, output_mode, fake_graphics_context_provider_.decoder_target_provider()}; @@ -588,6 +588,11 @@ } #endif // SB_HAS(GLES2) } + if (HasPendingEvents()) { + bool error_occurred = false; + ASSERT_NO_FATAL_FAILURE(DrainOutputs(&error_occurred)); + ASSERT_FALSE(error_occurred); + } } } }
diff --git a/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc b/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc index 7d981e8..d87e5b1 100644 --- a/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc +++ b/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc
@@ -155,8 +155,10 @@ if (data->argument_count < 2) { SB_LOG(INFO) << "Usage: audio_dmp_player <dmp file name>"; - SB_LOG(INFO) << "e.g. audio_dmp_player beneath_the_canopy_140_aac.dmp"; - SB_LOG(INFO) << " audio_dmp_player beneath_the_canopy_249_opus.dmp"; + SB_LOG(INFO) + << "e.g. audio_dmp_player beneath_the_canopy_aac_stereo.dmp"; + SB_LOG(INFO) + << " audio_dmp_player beneath_the_canopy_opus_stereo.dmp"; SbSystemRequestStop(0); return; }
diff --git a/src/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc b/src/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc index 0c4634a..0215bc6 100644 --- a/src/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc +++ b/src/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc
@@ -26,7 +26,9 @@ const GetRefreshRateFn& get_refresh_rate_fn) : get_refresh_rate_fn_(get_refresh_rate_fn) { if (get_refresh_rate_fn_) { - SB_LOG(INFO) << "VideoRenderAlgorithmImpl will render with cadence control"; + SB_LOG(INFO) << "VideoRenderAlgorithmImpl will render with cadence control " + << "with display refresh rate set at " + << get_refresh_rate_fn_(); } } @@ -154,6 +156,12 @@ return; } + auto refresh_rate = get_refresh_rate_fn_(); + SB_DCHECK(refresh_rate >= 1); + if (refresh_rate < 1) { + refresh_rate = 60; + } + bool is_audio_playing; bool is_audio_eos_played; bool is_underflow; @@ -165,28 +173,38 @@ frame_rate_estimate_.Update(*frames); auto frame_rate = frame_rate_estimate_.frame_rate(); SB_DCHECK(frame_rate != VideoFrameRateEstimator::kInvalidFrameRate); - cadence_pattern_generator_.UpdateRefreshRateAndMaybeReset( - get_refresh_rate_fn_()); + cadence_pattern_generator_.UpdateRefreshRateAndMaybeReset(refresh_rate); cadence_pattern_generator_.UpdateFrameRate(frame_rate); SB_DCHECK(cadence_pattern_generator_.has_cadence()); - if (current_frame_rendered_times_ >= - cadence_pattern_generator_.GetNumberOfTimesCurrentFrameDisplays()) { - frames->pop_front(); - cadence_pattern_generator_.AdvanceToNextFrame(); - break; - } - auto second_iter = frames->begin(); ++second_iter; - if ((*second_iter)->is_end_of_stream() || - (*second_iter)->timestamp() > media_time) { + if ((*second_iter)->is_end_of_stream()) { break; } auto frame_duration = - static_cast<SbTime>(kSbTimeSecond / get_refresh_rate_fn_()); + static_cast<SbTime>(kSbTimeSecond / refresh_rate); + + if (current_frame_rendered_times_ >= + cadence_pattern_generator_.GetNumberOfTimesCurrentFrameDisplays()) { + if (current_frame_rendered_times_ == 0) { + ++dropped_frames_; + } + frames->pop_front(); + cadence_pattern_generator_.AdvanceToNextFrame(); + current_frame_rendered_times_ = 0; + if (cadence_pattern_generator_.GetNumberOfTimesCurrentFrameDisplays() + == 0) { + continue; + } + if (frames->front()->timestamp() <= media_time - frame_duration) { + continue; + } + break; + } + if ((*second_iter)->timestamp() > media_time - frame_duration) { break; } @@ -215,7 +233,8 @@ << " call are " << media_time - media_time_of_last_render_call_ << "/" << now - system_time_of_last_render_call_ << " microseconds, the" << " video is at " << frame_rate_estimate_.frame_rate() << " fps," - << " media time is " << media_time; + << " media time is " << media_time << ", backlog " << frames->size() + << " frames."; #endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK } frames->pop_front();
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc index 396d832..0eae09d 100644 --- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc +++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
@@ -318,8 +318,19 @@ { ScopedLock scoped_lock_decoder_frames(decoder_frames_mutex_); sink_frames_mutex_.Acquire(); - sink_frames_.insert(sink_frames_.end(), decoder_frames_.begin(), - decoder_frames_.end()); + for (auto decoder_frame : decoder_frames_) { + if (sink_frames_.empty()) { + sink_frames_.push_back(decoder_frame); + continue; + } + if (sink_frames_.back()->is_end_of_stream()) { + continue; + } + if (decoder_frame->is_end_of_stream() || + decoder_frame->timestamp() > sink_frames_.back()->timestamp()) { + sink_frames_.push_back(decoder_frame); + } + } decoder_frames_.clear(); } size_t number_of_sink_frames = sink_frames_.size();
diff --git a/src/starboard/shared/starboard/player/player_worker.cc b/src/starboard/shared/starboard/player/player_worker.cc index 970c7b4..3300f48 100644 --- a/src/starboard/shared/starboard/player/player_worker.cc +++ b/src/starboard/shared/starboard/player/player_worker.cc
@@ -17,6 +17,7 @@ #include <string> #include "starboard/common/condition_variable.h" +#include "starboard/common/instance_counter.h" #include "starboard/common/mutex.h" #include "starboard/common/reset_and_return.h" #include "starboard/memory.h" @@ -45,6 +46,8 @@ // backlogs. const SbTimeMonotonic kWritePendingSampleDelay = 8 * kSbTimeMillisecond; +DECLARE_INSTANCE_COUNTER(PlayerWorker); + struct ThreadParam { explicit ThreadParam(PlayerWorker* player_worker) : condition_variable(mutex), player_worker(player_worker) {} @@ -84,6 +87,8 @@ } PlayerWorker::~PlayerWorker() { + ON_INSTANCE_RELEASED(PlayerWorker); + if (SbThreadIsValid(thread_)) { job_queue_->Schedule(std::bind(&PlayerWorker::DoStop, this)); SbThreadJoin(thread_, NULL); @@ -123,6 +128,8 @@ SB_DCHECK(handler_ != NULL); SB_DCHECK(update_media_info_cb_); + ON_INSTANCE_CREATED(PlayerWorker); + ThreadParam thread_param(this); thread_ = SbThreadCreate(kPlayerStackSize, kSbThreadPriorityHigh, kSbThreadNoAffinity, true, "player_worker",
diff --git a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_aac_5_1.dmp.sha1 b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_aac_5_1.dmp.sha1 new file mode 100644 index 0000000..8ae1579 --- /dev/null +++ b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_aac_5_1.dmp.sha1
@@ -0,0 +1 @@ +6d8fd13961e519725481fd122f60514adc16f0da \ No newline at end of file
diff --git a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_aac_mono.dmp.sha1 b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_aac_mono.dmp.sha1 new file mode 100644 index 0000000..969f852 --- /dev/null +++ b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_aac_mono.dmp.sha1
@@ -0,0 +1 @@ +ded4cfaba4dde8fff9e5de209b9593dafe70e912 \ No newline at end of file
diff --git a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_140_aac.dmp.sha1 b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_aac_stereo.dmp.sha1 similarity index 100% rename from src/starboard/shared/starboard/player/testdata/beneath_the_canopy_140_aac.dmp.sha1 rename to src/starboard/shared/starboard/player/testdata/beneath_the_canopy_aac_stereo.dmp.sha1
diff --git a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_opus_5_1.dmp.sha1 b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_opus_5_1.dmp.sha1 new file mode 100644 index 0000000..a42109c --- /dev/null +++ b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_opus_5_1.dmp.sha1
@@ -0,0 +1 @@ +53e543fed416debd4b34e394766ba7fb65d483de \ No newline at end of file
diff --git a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_opus_mono.dmp.sha1 b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_opus_mono.dmp.sha1 new file mode 100644 index 0000000..8fa07b5 --- /dev/null +++ b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_opus_mono.dmp.sha1
@@ -0,0 +1 @@ +a821fbd0211ddf4f91375d1eb3f8b3b1ec06b8e3 \ No newline at end of file
diff --git a/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_249_opus.dmp.sha1 b/src/starboard/shared/starboard/player/testdata/beneath_the_canopy_opus_stereo.dmp.sha1 similarity index 100% rename from src/starboard/shared/starboard/player/testdata/beneath_the_canopy_249_opus.dmp.sha1 rename to src/starboard/shared/starboard/player/testdata/beneath_the_canopy_opus_stereo.dmp.sha1
diff --git a/src/starboard/shared/starboard/player/video_dmp_reader.cc b/src/starboard/shared/starboard/player/video_dmp_reader.cc index 250a0f7..6f2de79 100644 --- a/src/starboard/shared/starboard/player/video_dmp_reader.cc +++ b/src/starboard/shared/starboard/player/video_dmp_reader.cc
@@ -14,6 +14,7 @@ #include "starboard/shared/starboard/player/video_dmp_reader.h" +#include <algorithm> #include <functional> #if SB_HAS(PLAYER_FILTER_TESTS) @@ -95,22 +96,13 @@ using std::placeholders::_2; VideoDmpReader::VideoDmpReader(const char* filename) - : reverse_byte_order_(false), - read_cb_(std::bind(&VideoDmpReader::ReadFromCache, this, _1, _2)) { + : reverse_byte_order_(false) { ScopedFile file(filename, kSbFileOpenOnly | kSbFileRead); SB_CHECK(file.IsValid()) << "Failed to open " << filename; int64_t file_size = file.GetSize(); SB_CHECK(file_size >= 0); - - file_cache_.resize(file_size); - int bytes_read = file.Read(file_cache_.data(), file_size); - SB_CHECK(bytes_read == file_size); - + read_cb_ = std::bind(&VideoDmpReader::ReadFromFile, this, &file, _1, _2); Parse(); - - // To free memory used by |file_cache_|. - decltype(file_cache_) empty; - file_cache_.swap(empty); } VideoDmpReader::~VideoDmpReader() {} @@ -164,8 +156,10 @@ } for (;;) { uint32_t type; - int bytes_read = ReadFromCache(&type, sizeof(type)); - if (bytes_read <= 0) { + int bytes_read = read_cb_(&type, sizeof(type)); + if (bytes_read != sizeof(type)) { + // Read an invalid number of bytes (corrupt file), or we read zero bytes + // (end of file). break; } if (reverse_byte_order_) { @@ -261,12 +255,10 @@ std::move(data), video_sample_info); } -int VideoDmpReader::ReadFromCache(void* buffer, int bytes_to_read) { - bytes_to_read = std::min( - bytes_to_read, static_cast<int>(file_cache_.size()) - file_cache_offset_); - SbMemoryCopy(buffer, file_cache_.data() + file_cache_offset_, bytes_to_read); - file_cache_offset_ += bytes_to_read; - return bytes_to_read; +int VideoDmpReader::ReadFromFile(ScopedFile* file, + void* buffer, + int bytes_to_read) { + return file->ReadAll(static_cast<char*>(buffer), bytes_to_read); } } // namespace video_dmp
diff --git a/src/starboard/shared/starboard/player/video_dmp_reader.h b/src/starboard/shared/starboard/player/video_dmp_reader.h index e870946..063eb68 100644 --- a/src/starboard/shared/starboard/player/video_dmp_reader.h +++ b/src/starboard/shared/starboard/player/video_dmp_reader.h
@@ -119,7 +119,7 @@ void Parse(); AudioAccessUnit ReadAudioAccessUnit(); VideoAccessUnit ReadVideoAccessUnit(); - int ReadFromCache(void* buffer, int bytes_to_read); + int ReadFromFile(ScopedFile* file, void* buffer, int bytes_to_read); ReadCB read_cb_; @@ -135,9 +135,6 @@ std::vector<AudioAccessUnit> audio_access_units_; std::vector<VideoAccessUnit> video_access_units_; - - int file_cache_offset_ = 0; - std::vector<char> file_cache_; }; } // namespace video_dmp
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_cancel.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_cancel.cc index 0949e03..7ac0882 100644 --- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_cancel.cc +++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_cancel.cc
@@ -14,7 +14,8 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 #include "starboard/common/log.h" #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h" @@ -25,4 +26,6 @@ } } -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc index 22456f3..3127fa4 100644 --- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc +++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_create.cc
@@ -14,7 +14,8 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h" @@ -23,4 +24,6 @@ return SbSpeechRecognizerPrivate::CreateSpeechRecognizer(handler); } -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc index acd0585..1a46ae5 100644 --- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc +++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_destroy.cc
@@ -14,7 +14,8 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h" @@ -24,4 +25,6 @@ } } -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h index 63f24c8..9f5779a 100644 --- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h +++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h
@@ -18,7 +18,8 @@ #include "starboard/shared/internal_only.h" #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 struct SbSpeechRecognizerPrivate { virtual ~SbSpeechRecognizerPrivate() {} virtual bool Start(const SbSpeechConfiguration* configuration) = 0; @@ -28,6 +29,8 @@ const SbSpeechRecognizerHandler* handler); static void DestroySpeechRecognizer(SbSpeechRecognizer speech_recognizer); }; -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5 #endif // STARBOARD_SHARED_STARBOARD_SPEECH_RECOGNIZER_SPEECH_RECOGNIZER_INTERNAL_H_
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_is_supported.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_is_supported.cc new file mode 100644 index 0000000..102a7c0 --- /dev/null +++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_is_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/speech_recognizer.h" + +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION + +bool SbSpeechRecognizerIsSupported() { + return true; +} + +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc index 54c1547..01253a1 100644 --- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc +++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_start.cc
@@ -14,7 +14,8 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h" @@ -25,4 +26,6 @@ : false; } -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc index 6655330..f50e53a 100644 --- a/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc +++ b/src/starboard/shared/starboard/speech_recognizer/speech_recognizer_stop.cc
@@ -14,7 +14,8 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 #include "starboard/common/log.h" #include "starboard/shared/starboard/speech_recognizer/speech_recognizer_internal.h" @@ -25,4 +26,6 @@ } } -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/accessibility_get_caption_settings.cc b/src/starboard/shared/stub/accessibility_get_caption_settings.cc index 609a610..2f042d7 100644 --- a/src/starboard/shared/stub/accessibility_get_caption_settings.cc +++ b/src/starboard/shared/stub/accessibility_get_caption_settings.cc
@@ -17,61 +17,9 @@ #include "starboard/accessibility.h" #include "starboard/memory.h" -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) bool SbAccessibilityGetCaptionSettings( - SbAccessibilityCaptionSettings* caption_settings) { - if (!caption_settings || - !SbMemoryIsZero(caption_settings, - sizeof(SbAccessibilityCaptionSettings))) { - return false; - } - - caption_settings->background_color = kSbAccessibilityCaptionColorWhite; - - caption_settings->background_color_state = - kSbAccessibilityCaptionStateUnsupported; - - caption_settings->background_opacity = - kSbAccessibilityCaptionOpacityPercentage100; - - caption_settings->background_opacity_state = - kSbAccessibilityCaptionStateUnsupported; - - caption_settings->character_edge_style = - kSbAccessibilityCaptionCharacterEdgeStyleNone; - - caption_settings->character_edge_style_state = - kSbAccessibilityCaptionStateUnsupported; - - caption_settings->font_color = kSbAccessibilityCaptionColorWhite; - - caption_settings->font_color_state = kSbAccessibilityCaptionStateUnsupported; - - caption_settings->font_size = kSbAccessibilityCaptionFontSizePercentage100; - - caption_settings->font_size_state = kSbAccessibilityCaptionStateUnsupported; - - caption_settings->font_opacity = kSbAccessibilityCaptionOpacityPercentage100; - - caption_settings->font_opacity_state = - kSbAccessibilityCaptionStateUnsupported; - - caption_settings->window_color = kSbAccessibilityCaptionColorWhite; - - caption_settings->window_color_state = - kSbAccessibilityCaptionStateUnsupported; - - caption_settings->window_opacity = - kSbAccessibilityCaptionOpacityPercentage100; - - caption_settings->window_opacity_state = - kSbAccessibilityCaptionStateUnsupported; - - caption_settings->is_enabled = false; - - caption_settings->supports_is_enabled = false; - caption_settings->supports_set_enabled = false; - - return true; + SbAccessibilityCaptionSettings* caption_settings) { + return false; } -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
diff --git a/src/starboard/shared/stub/accessibility_set_captions_enabled.cc b/src/starboard/shared/stub/accessibility_set_captions_enabled.cc index 29b1969..29e910c 100644 --- a/src/starboard/shared/stub/accessibility_set_captions_enabled.cc +++ b/src/starboard/shared/stub/accessibility_set_captions_enabled.cc
@@ -15,9 +15,9 @@ #include "starboard/accessibility.h" #include "starboard/configuration.h" -#if SB_HAS(CAPTIONS) +#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS) bool SbAccessibilitySetCaptionsEnabled(bool enabled) { SB_UNREFERENCED_PARAMETER(enabled); return false; } -#endif // SB_HAS(CAPTIONS) +#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
diff --git a/src/starboard/shared/stub/blitter_blit_rect_to_rect.cc b/src/starboard/shared/stub/blitter_blit_rect_to_rect.cc new file mode 100644 index 0000000..ec5dc26 --- /dev/null +++ b/src/starboard/shared/stub/blitter_blit_rect_to_rect.cc
@@ -0,0 +1,26 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterBlitRectToRect(SbBlitterContext context, + SbBlitterSurface source_surface, + SbBlitterRect src_rect, + SbBlitterRect dst_rect) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_blit_rect_to_rect_tiled.cc b/src/starboard/shared/stub/blitter_blit_rect_to_rect_tiled.cc new file mode 100644 index 0000000..7823d2e --- /dev/null +++ b/src/starboard/shared/stub/blitter_blit_rect_to_rect_tiled.cc
@@ -0,0 +1,26 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterBlitRectToRectTiled(SbBlitterContext context, + SbBlitterSurface source_surface, + SbBlitterRect src_rect, + SbBlitterRect dst_rect) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_blit_rects_to_rects.cc b/src/starboard/shared/stub/blitter_blit_rects_to_rects.cc new file mode 100644 index 0000000..0d6f19f --- /dev/null +++ b/src/starboard/shared/stub/blitter_blit_rects_to_rects.cc
@@ -0,0 +1,27 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterBlitRectsToRects(SbBlitterContext context, + SbBlitterSurface source_surface, + const SbBlitterRect* src_rects, + const SbBlitterRect* dst_rects, + int num_rects) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_create_context.cc b/src/starboard/shared/stub/blitter_create_context.cc new file mode 100644 index 0000000..206d574 --- /dev/null +++ b/src/starboard/shared/stub/blitter_create_context.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +SbBlitterContext SbBlitterCreateContext(SbBlitterDevice device) { + return kSbBlitterInvalidContext; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_create_default_device.cc b/src/starboard/shared/stub/blitter_create_default_device.cc new file mode 100644 index 0000000..0b77ab6 --- /dev/null +++ b/src/starboard/shared/stub/blitter_create_default_device.cc
@@ -0,0 +1,26 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#include "base/logging.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +SbBlitterDevice SbBlitterCreateDefaultDevice() { + SB_LOG(ERROR) << "SbBlitter API not supported on this platform."; + return kSbBlitterInvalidDevice; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_create_pixel_data.cc b/src/starboard/shared/stub/blitter_create_pixel_data.cc new file mode 100644 index 0000000..3f63bb8 --- /dev/null +++ b/src/starboard/shared/stub/blitter_create_pixel_data.cc
@@ -0,0 +1,27 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +SbBlitterPixelData SbBlitterCreatePixelData( + SbBlitterDevice device, + int width, + int height, + SbBlitterPixelDataFormat pixel_format) { + return kSbBlitterInvalidPixelData; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_create_render_target_surface.cc b/src/starboard/shared/stub/blitter_create_render_target_surface.cc new file mode 100644 index 0000000..6d31b3b --- /dev/null +++ b/src/starboard/shared/stub/blitter_create_render_target_surface.cc
@@ -0,0 +1,27 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +SbBlitterSurface SbBlitterCreateRenderTargetSurface( + SbBlitterDevice device, + int width, + int height, + SbBlitterSurfaceFormat surface_format) { + return kSbBlitterInvalidSurface; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_create_surface_from_pixel_data.cc b/src/starboard/shared/stub/blitter_create_surface_from_pixel_data.cc new file mode 100644 index 0000000..94810c2 --- /dev/null +++ b/src/starboard/shared/stub/blitter_create_surface_from_pixel_data.cc
@@ -0,0 +1,25 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +SbBlitterSurface SbBlitterCreateSurfaceFromPixelData( + SbBlitterDevice device, + SbBlitterPixelData pixel_data) { + return kSbBlitterInvalidSurface; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_create_swap_chain_from_window.cc b/src/starboard/shared/stub/blitter_create_swap_chain_from_window.cc new file mode 100644 index 0000000..05c4301 --- /dev/null +++ b/src/starboard/shared/stub/blitter_create_swap_chain_from_window.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +SbBlitterSwapChain SbBlitterCreateSwapChainFromWindow(SbBlitterDevice device, + SbWindow window) { + return kSbBlitterInvalidSwapChain; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_destroy_context.cc b/src/starboard/shared/stub/blitter_destroy_context.cc new file mode 100644 index 0000000..d48e1ea --- /dev/null +++ b/src/starboard/shared/stub/blitter_destroy_context.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterDestroyContext(SbBlitterContext context) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_destroy_device.cc b/src/starboard/shared/stub/blitter_destroy_device.cc new file mode 100644 index 0000000..599dc99 --- /dev/null +++ b/src/starboard/shared/stub/blitter_destroy_device.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterDestroyDevice(SbBlitterDevice device) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_destroy_pixel_data.cc b/src/starboard/shared/stub/blitter_destroy_pixel_data.cc new file mode 100644 index 0000000..c966170 --- /dev/null +++ b/src/starboard/shared/stub/blitter_destroy_pixel_data.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterDestroyPixelData(SbBlitterPixelData pixel_data) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_destroy_surface.cc b/src/starboard/shared/stub/blitter_destroy_surface.cc new file mode 100644 index 0000000..47756c4 --- /dev/null +++ b/src/starboard/shared/stub/blitter_destroy_surface.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterDestroySurface(SbBlitterSurface surface) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_destroy_swap_chain.cc b/src/starboard/shared/stub/blitter_destroy_swap_chain.cc new file mode 100644 index 0000000..49a8562 --- /dev/null +++ b/src/starboard/shared/stub/blitter_destroy_swap_chain.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterDestroySwapChain(SbBlitterSwapChain swap_chain) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_download_surface_pixels.cc b/src/starboard/shared/stub/blitter_download_surface_pixels.cc new file mode 100644 index 0000000..11c0fc3 --- /dev/null +++ b/src/starboard/shared/stub/blitter_download_surface_pixels.cc
@@ -0,0 +1,26 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterDownloadSurfacePixels(SbBlitterSurface surface, + SbBlitterPixelDataFormat pixel_format, + int pitch_in_bytes, + void* out_pixel_data) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_fill_rect.cc b/src/starboard/shared/stub/blitter_fill_rect.cc new file mode 100644 index 0000000..bc84d3a --- /dev/null +++ b/src/starboard/shared/stub/blitter_fill_rect.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterFillRect(SbBlitterContext context, SbBlitterRect rect) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_flip_swap_chain.cc b/src/starboard/shared/stub/blitter_flip_swap_chain.cc new file mode 100644 index 0000000..da0f88b --- /dev/null +++ b/src/starboard/shared/stub/blitter_flip_swap_chain.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterFlipSwapChain(SbBlitterSwapChain swap_chain) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_flush_context.cc b/src/starboard/shared/stub/blitter_flush_context.cc new file mode 100644 index 0000000..ca0b932 --- /dev/null +++ b/src/starboard/shared/stub/blitter_flush_context.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterFlushContext(SbBlitterContext context) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_get_max_contexts.cc b/src/starboard/shared/stub/blitter_get_max_contexts.cc new file mode 100644 index 0000000..c04255a --- /dev/null +++ b/src/starboard/shared/stub/blitter_get_max_contexts.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +int SbBlitterGetMaxContexts(SbBlitterDevice device) { + return -1; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_get_pixel_data_pitch_in_bytes.cc b/src/starboard/shared/stub/blitter_get_pixel_data_pitch_in_bytes.cc new file mode 100644 index 0000000..1ab06ea --- /dev/null +++ b/src/starboard/shared/stub/blitter_get_pixel_data_pitch_in_bytes.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +int SbBlitterGetPixelDataPitchInBytes(SbBlitterPixelData pixel_data) { + return -1; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_get_pixel_data_pointer.cc b/src/starboard/shared/stub/blitter_get_pixel_data_pointer.cc new file mode 100644 index 0000000..96b27f0 --- /dev/null +++ b/src/starboard/shared/stub/blitter_get_pixel_data_pointer.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +void* SbBlitterGetPixelDataPointer(SbBlitterPixelData pixel_data) { + return NULL; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_get_render_target_from_surface.cc b/src/starboard/shared/stub/blitter_get_render_target_from_surface.cc new file mode 100644 index 0000000..219de3b --- /dev/null +++ b/src/starboard/shared/stub/blitter_get_render_target_from_surface.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +SbBlitterRenderTarget SbBlitterGetRenderTargetFromSurface( + SbBlitterSurface surface) { + return kSbBlitterInvalidRenderTarget; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_get_render_target_from_swap_chain.cc b/src/starboard/shared/stub/blitter_get_render_target_from_swap_chain.cc new file mode 100644 index 0000000..2563e43 --- /dev/null +++ b/src/starboard/shared/stub/blitter_get_render_target_from_swap_chain.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +SbBlitterRenderTarget SbBlitterGetRenderTargetFromSwapChain( + SbBlitterSwapChain swap_chain) { + return kSbBlitterInvalidRenderTarget; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_get_surface_info.cc b/src/starboard/shared/stub/blitter_get_surface_info.cc new file mode 100644 index 0000000..142a806 --- /dev/null +++ b/src/starboard/shared/stub/blitter_get_surface_info.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterGetSurfaceInfo(SbBlitterSurface surface, + SbBlitterSurfaceInfo* surface_info) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_is_blitter_supported.cc b/src/starboard/shared/stub/blitter_is_blitter_supported.cc new file mode 100644 index 0000000..614132f --- /dev/null +++ b/src/starboard/shared/stub/blitter_is_blitter_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterIsBlitterSupported() { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_is_pixel_format_supported_by_download_surface_pixels.cc b/src/starboard/shared/stub/blitter_is_pixel_format_supported_by_download_surface_pixels.cc new file mode 100644 index 0000000..9427086 --- /dev/null +++ b/src/starboard/shared/stub/blitter_is_pixel_format_supported_by_download_surface_pixels.cc
@@ -0,0 +1,25 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterIsPixelFormatSupportedByDownloadSurfacePixels( + SbBlitterSurface surface, + SbBlitterPixelDataFormat pixel_format) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_is_pixel_format_supported_by_pixel_data.cc b/src/starboard/shared/stub/blitter_is_pixel_format_supported_by_pixel_data.cc new file mode 100644 index 0000000..641233e --- /dev/null +++ b/src/starboard/shared/stub/blitter_is_pixel_format_supported_by_pixel_data.cc
@@ -0,0 +1,25 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterIsPixelFormatSupportedByPixelData( + SbBlitterDevice device, + SbBlitterPixelDataFormat pixel_format) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_is_surface_format_supported_by_render_target_surface.cc b/src/starboard/shared/stub/blitter_is_surface_format_supported_by_render_target_surface.cc new file mode 100644 index 0000000..7968f7e --- /dev/null +++ b/src/starboard/shared/stub/blitter_is_surface_format_supported_by_render_target_surface.cc
@@ -0,0 +1,25 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterIsSurfaceFormatSupportedByRenderTargetSurface( + SbBlitterDevice device, + SbBlitterSurfaceFormat surface_format) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_set_blending.cc b/src/starboard/shared/stub/blitter_set_blending.cc new file mode 100644 index 0000000..3668919 --- /dev/null +++ b/src/starboard/shared/stub/blitter_set_blending.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterSetBlending(SbBlitterContext context, bool blending) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_set_color.cc b/src/starboard/shared/stub/blitter_set_color.cc new file mode 100644 index 0000000..904e70b --- /dev/null +++ b/src/starboard/shared/stub/blitter_set_color.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterSetColor(SbBlitterContext context, SbBlitterColor color) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_set_modulate_blits_with_color.cc b/src/starboard/shared/stub/blitter_set_modulate_blits_with_color.cc new file mode 100644 index 0000000..751011a --- /dev/null +++ b/src/starboard/shared/stub/blitter_set_modulate_blits_with_color.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterSetModulateBlitsWithColor(SbBlitterContext context, + bool modulate_blits_with_color) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_set_render_target.cc b/src/starboard/shared/stub/blitter_set_render_target.cc new file mode 100644 index 0000000..371237e --- /dev/null +++ b/src/starboard/shared/stub/blitter_set_render_target.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterSetRenderTarget(SbBlitterContext context, + SbBlitterRenderTarget render_target) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/blitter_set_scissor.cc b/src/starboard/shared/stub/blitter_set_scissor.cc new file mode 100644 index 0000000..76ecac3 --- /dev/null +++ b/src/starboard/shared/stub/blitter_set_scissor.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/blitter.h" + +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION + +bool SbBlitterSetScissor(SbBlitterContext context, SbBlitterRect rect) { + return false; +} + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/file_atomic_replace.cc b/src/starboard/shared/stub/file_atomic_replace.cc new file mode 100644 index 0000000..636b1e8 --- /dev/null +++ b/src/starboard/shared/stub/file_atomic_replace.cc
@@ -0,0 +1,25 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/file.h" + +#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION + +bool SbFileAtomicReplace(const char* /* path */, + const char* /* data */, + int64_t /* data_size */) { + return false; +} + +#endif // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
diff --git a/src/starboard/shared/stub/media_is_audio_supported.cc b/src/starboard/shared/stub/media_is_audio_supported.cc index 916221a..c8a199b 100644 --- a/src/starboard/shared/stub/media_is_audio_supported.cc +++ b/src/starboard/shared/stub/media_is_audio_supported.cc
@@ -16,7 +16,7 @@ #include "starboard/media.h" -SB_EXPORT bool SbMediaIsAudioSupported(SbMediaAudioCodec /*audio_codec*/, - int64_t /*bitrate*/) { +bool SbMediaIsAudioSupported(SbMediaAudioCodec /*audio_codec*/, + int64_t /*bitrate*/) { return false; }
diff --git a/src/starboard/shared/stub/media_is_supported.cc b/src/starboard/shared/stub/media_is_supported.cc index 76a6033..884ffda 100644 --- a/src/starboard/shared/stub/media_is_supported.cc +++ b/src/starboard/shared/stub/media_is_supported.cc
@@ -14,8 +14,8 @@ #include "starboard/media.h" -SB_EXPORT bool SbMediaIsSupported(SbMediaVideoCodec /*video_codec*/, - SbMediaAudioCodec /*audio_codec*/, - const char* /*key_system*/) { +bool SbMediaIsSupported(SbMediaVideoCodec /*video_codec*/, + SbMediaAudioCodec /*audio_codec*/, + const char* /*key_system*/) { return false; }
diff --git a/src/starboard/shared/stub/media_is_transfer_characteristics_supported.cc b/src/starboard/shared/stub/media_is_transfer_characteristics_supported.cc index 189e5dd..e62b8e0 100644 --- a/src/starboard/shared/stub/media_is_transfer_characteristics_supported.cc +++ b/src/starboard/shared/stub/media_is_transfer_characteristics_supported.cc
@@ -17,7 +17,7 @@ #include "starboard/media.h" #if !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT) -SB_EXPORT bool SbMediaIsTransferCharacteristicsSupported( +bool SbMediaIsTransferCharacteristicsSupported( SbMediaTransferId /*transfer_id*/) { return false; }
diff --git a/src/starboard/shared/stub/media_is_video_supported.cc b/src/starboard/shared/stub/media_is_video_supported.cc index 481ad6f..4ceead5 100644 --- a/src/starboard/shared/stub/media_is_video_supported.cc +++ b/src/starboard/shared/stub/media_is_video_supported.cc
@@ -16,23 +16,23 @@ #include "starboard/media.h" -SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec /*video_codec*/, +bool SbMediaIsVideoSupported(SbMediaVideoCodec /*video_codec*/, #if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT) - int /*profile*/, - int /*level*/, - int /*bit_depth*/, - SbMediaPrimaryId /*primary_id*/, - SbMediaTransferId /*transfer_id*/, - SbMediaMatrixId /*matrix_id*/, + int /*profile*/, + int /*level*/, + int /*bit_depth*/, + SbMediaPrimaryId /*primary_id*/, + SbMediaTransferId /*transfer_id*/, + SbMediaMatrixId /*matrix_id*/, #endif // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT) - int /*frame_width*/, - int /*frame_height*/, - int64_t /*bitrate*/, - int /*fps*/ + int /*frame_width*/, + int /*frame_height*/, + int64_t /*bitrate*/, + int /*fps*/ #if SB_API_VERSION >= 10 - , - bool /*decode_to_texture_required*/ -#endif // SB_API_VERSION >= 10 - ) { + , + bool /*decode_to_texture_required*/ +#endif // SB_API_VERSION >= 10 + ) { return false; }
diff --git a/src/starboard/shared/stub/socket_is_ipv6_supported.cc b/src/starboard/shared/stub/socket_is_ipv6_supported.cc new file mode 100644 index 0000000..c79a7b3 --- /dev/null +++ b/src/starboard/shared/stub/socket_is_ipv6_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/socket.h" + +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION + +bool SbSocketIsIpv6Supported() { + return false; +} + +#endif
diff --git a/src/starboard/shared/stub/speech_recognizer_cancel.cc b/src/starboard/shared/stub/speech_recognizer_cancel.cc index a781b9e..e85ee0a 100644 --- a/src/starboard/shared/stub/speech_recognizer_cancel.cc +++ b/src/starboard/shared/stub/speech_recognizer_cancel.cc
@@ -14,8 +14,11 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 void SbSpeechRecognizerCancel(SbSpeechRecognizer /*recognizer*/) {} -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_recognizer_create.cc b/src/starboard/shared/stub/speech_recognizer_create.cc index d72731b..3064a22 100644 --- a/src/starboard/shared/stub/speech_recognizer_create.cc +++ b/src/starboard/shared/stub/speech_recognizer_create.cc
@@ -14,11 +14,14 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 SbSpeechRecognizer SbSpeechRecognizerCreate( const SbSpeechRecognizerHandler* /*handler*/) { return kSbSpeechRecognizerInvalid; } -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_recognizer_destroy.cc b/src/starboard/shared/stub/speech_recognizer_destroy.cc index 0552201..8f4d056 100644 --- a/src/starboard/shared/stub/speech_recognizer_destroy.cc +++ b/src/starboard/shared/stub/speech_recognizer_destroy.cc
@@ -14,8 +14,11 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 void SbSpeechRecognizerDestroy(SbSpeechRecognizer /*recognizer*/) {} -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_recognizer_is_supported.cc b/src/starboard/shared/stub/speech_recognizer_is_supported.cc new file mode 100644 index 0000000..84d7a49 --- /dev/null +++ b/src/starboard/shared/stub/speech_recognizer_is_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/speech_recognizer.h" + +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION + +bool SbSpeechRecognizerIsSupported() { + return false; +} + +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
diff --git a/src/starboard/shared/stub/speech_recognizer_start.cc b/src/starboard/shared/stub/speech_recognizer_start.cc index c73abf1..b80ebea 100644 --- a/src/starboard/shared/stub/speech_recognizer_start.cc +++ b/src/starboard/shared/stub/speech_recognizer_start.cc
@@ -14,11 +14,14 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 bool SbSpeechRecognizerStart(SbSpeechRecognizer /*recognizer*/, const SbSpeechConfiguration* /*configuration*/) { return false; } -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_recognizer_stop.cc b/src/starboard/shared/stub/speech_recognizer_stop.cc index 4831bba..ad9f63a 100644 --- a/src/starboard/shared/stub/speech_recognizer_stop.cc +++ b/src/starboard/shared/stub/speech_recognizer_stop.cc
@@ -14,8 +14,11 @@ #include "starboard/speech_recognizer.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 void SbSpeechRecognizerStop(SbSpeechRecognizer /*recognizer*/) {} -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5
diff --git a/src/starboard/shared/stub/speech_synthesis_cancel.cc b/src/starboard/shared/stub/speech_synthesis_cancel.cc index 65aaa62..c9b9712 100644 --- a/src/starboard/shared/stub/speech_synthesis_cancel.cc +++ b/src/starboard/shared/stub/speech_synthesis_cancel.cc
@@ -14,9 +14,9 @@ #include "starboard/speech_synthesis.h" -#if !SB_HAS(SPEECH_SYNTHESIS) -#error If speech synthesis not enabled on this platform, please exclude it\ - from the build -#endif +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \ + SB_HAS(SPEECH_SYNTHESIS) void SbSpeechSynthesisCancel() {} + +#endif
diff --git a/src/starboard/shared/stub/speech_synthesis_is_supported.cc b/src/starboard/shared/stub/speech_synthesis_is_supported.cc new file mode 100644 index 0000000..d82c1b7 --- /dev/null +++ b/src/starboard/shared/stub/speech_synthesis_is_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/speech_synthesis.h" + +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION + +bool SbSpeechSynthesisIsSupported() { + return false; +} + +#endif
diff --git a/src/starboard/shared/stub/speech_synthesis_speak.cc b/src/starboard/shared/stub/speech_synthesis_speak.cc index 744b1ce..d11cf31 100644 --- a/src/starboard/shared/stub/speech_synthesis_speak.cc +++ b/src/starboard/shared/stub/speech_synthesis_speak.cc
@@ -14,9 +14,9 @@ #include "starboard/speech_synthesis.h" -#if !SB_HAS(SPEECH_SYNTHESIS) -#error If speech synthesis not enabled on this platform, please exclude it\ - from the build -#endif +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \ + SB_HAS(SPEECH_SYNTHESIS) void SbSpeechSynthesisSpeak(const char* text) {} + +#endif
diff --git a/src/starboard/shared/stub/system_egl.cc b/src/starboard/shared/stub/system_egl.cc index d43eaf2..272e840 100644 --- a/src/starboard/shared/stub/system_egl.cc +++ b/src/starboard/shared/stub/system_egl.cc
@@ -14,6 +14,10 @@ #include "starboard/egl.h" +#if SB_API_VERSION >= 11 + const SbEglInterface* SbGetEglInterface() { return nullptr; } + +#endif // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/stub/system_gles.cc b/src/starboard/shared/stub/system_gles.cc index 09100e0..5160614 100644 --- a/src/starboard/shared/stub/system_gles.cc +++ b/src/starboard/shared/stub/system_gles.cc
@@ -14,6 +14,10 @@ #include "starboard/gles.h" +#if SB_API_VERSION >= 11 + const SbGlesInterface* SbGetGlesInterface() { return nullptr; } + +#endif
diff --git a/src/starboard/shared/stub/time_is_time_thread_now_supported.cc b/src/starboard/shared/stub/time_is_time_thread_now_supported.cc new file mode 100644 index 0000000..de464dc --- /dev/null +++ b/src/starboard/shared/stub/time_is_time_thread_now_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/time.h" + +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION + +bool SbTimeIsTimeThreadNowSupported() { + return false; +} + +#endif
diff --git a/src/starboard/shared/stub/window_blur_on_screen_keyboard.cc b/src/starboard/shared/stub/window_blur_on_screen_keyboard.cc new file mode 100644 index 0000000..f4dbd36 --- /dev/null +++ b/src/starboard/shared/stub/window_blur_on_screen_keyboard.cc
@@ -0,0 +1,21 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +void SbWindowBlurOnScreenKeyboard(SbWindow /* window */, int /* ticket */) {} + +#endif
diff --git a/src/starboard/shared/stub/window_focus_on_screen_keyboard.cc b/src/starboard/shared/stub/window_focus_on_screen_keyboard.cc new file mode 100644 index 0000000..76b9387 --- /dev/null +++ b/src/starboard/shared/stub/window_focus_on_screen_keyboard.cc
@@ -0,0 +1,21 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +void SbWindowFocusOnScreenKeyboard(SbWindow /* window */, int /* ticket */) {} + +#endif
diff --git a/src/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc b/src/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc new file mode 100644 index 0000000..8072dbd --- /dev/null +++ b/src/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc
@@ -0,0 +1,25 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +bool SbWindowGetOnScreenKeyboardBoundingRect( + SbWindow /* window */, + SbWindowRect* /* bounding_rect */) { + return false; +} + +#endif
diff --git a/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc b/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc new file mode 100644 index 0000000..2632582 --- /dev/null +++ b/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc
@@ -0,0 +1,21 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +void SbWindowHideOnScreenKeyboard(SbWindow /* window */, int /* ticket */) {} + +#endif
diff --git a/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc b/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc new file mode 100644 index 0000000..efc823b --- /dev/null +++ b/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +bool SbWindowIsOnScreenKeyboardShown(SbWindow /* window */) { + return false; +} + +#endif
diff --git a/src/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc b/src/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc new file mode 100644 index 0000000..b9eb7e8 --- /dev/null +++ b/src/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc
@@ -0,0 +1,23 @@ +// Copyright 2018 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +bool SbWindowOnScreenKeyboardIsSupported() { + return false; +} + +#endif
diff --git a/src/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc b/src/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc index 2efa262..94c75b1 100644 --- a/src/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc +++ b/src/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc
@@ -14,10 +14,12 @@ #include "starboard/window.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) #if SB_API_VERSION >= 11 bool SbWindowOnScreenKeyboardSuggestionsSupported(SbWindow window) { return false; } #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc b/src/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc new file mode 100644 index 0000000..ef192f6 --- /dev/null +++ b/src/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc
@@ -0,0 +1,22 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +void SbWindowSetOnScreenKeyboardKeepFocus(SbWindow /* window */, + bool /* keep_focus */) {} + +#endif
diff --git a/src/starboard/shared/stub/window_show_on_screen_keyboard.cc b/src/starboard/shared/stub/window_show_on_screen_keyboard.cc new file mode 100644 index 0000000..aa17235 --- /dev/null +++ b/src/starboard/shared/stub/window_show_on_screen_keyboard.cc
@@ -0,0 +1,23 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/window.h" + +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION + +void SbWindowShowOnScreenKeyboard(SbWindow /* window */, + const char* /* input_text */, + int /* ticket */) {} + +#endif
diff --git a/src/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc b/src/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc index e5f5436..665ba4e 100644 --- a/src/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc +++ b/src/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc
@@ -14,11 +14,13 @@ #include "starboard/window.h" -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) #if SB_API_VERSION >= 11 void SbWindowUpdateOnScreenKeyboardSuggestions(SbWindow window, const char* suggestions[], int num_suggestions, int ticket) {} #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/shared/widevine/drm_system_widevine.cc b/src/starboard/shared/widevine/drm_system_widevine.cc index e884249..e5c08ea 100644 --- a/src/starboard/shared/widevine/drm_system_widevine.cc +++ b/src/starboard/shared/widevine/drm_system_widevine.cc
@@ -18,6 +18,7 @@ #include <vector> #include "starboard/character.h" +#include "starboard/common/instance_counter.h" #include "starboard/common/log.h" #include "starboard/common/mutex.h" #include "starboard/common/string.h" @@ -46,6 +47,8 @@ // get HDCP authentication complete. We set a timeout of 6 seconds for retries. const SbTimeMonotonic kUnblockKeyRetryTimeout = kSbTimeSecond * 6; +DECLARE_INSTANCE_COUNTER(DrmSystemWidevine); + class WidevineClock : public wv3cdm::IClock { public: int64_t now() override { @@ -225,6 +228,8 @@ SB_DCHECK(!company_name.empty()); SB_DCHECK(!model_name.empty()); + ON_INSTANCE_CREATED(DrmSystemWidevine); + #if !defined(COBALT_BUILD_TYPE_GOLD) using shared::starboard::Application; @@ -250,6 +255,8 @@ } DrmSystemWidevine::~DrmSystemWidevine() { + ON_INSTANCE_RELEASED(DrmSystemWidevine); + GetRegistry()->Unregister(this); }
diff --git a/src/starboard/shared/widevine/media_is_supported.cc b/src/starboard/shared/widevine/media_is_supported.cc index f201c68..55292ab 100644 --- a/src/starboard/shared/widevine/media_is_supported.cc +++ b/src/starboard/shared/widevine/media_is_supported.cc
@@ -15,9 +15,9 @@ #include "starboard/media.h" #include "starboard/shared/widevine/drm_system_widevine.h" -SB_EXPORT bool SbMediaIsSupported(SbMediaVideoCodec video_codec, - SbMediaAudioCodec audio_codec, - const char* key_system) { +bool SbMediaIsSupported(SbMediaVideoCodec video_codec, + SbMediaAudioCodec audio_codec, + const char* key_system) { using starboard::shared::widevine::DrmSystemWidevine; SB_UNREFERENCED_PARAMETER(video_codec);
diff --git a/src/starboard/shared/widevine/widevine3.gyp b/src/starboard/shared/widevine/widevine3.gyp index 3575419..fe8b7cf 100644 --- a/src/starboard/shared/widevine/widevine3.gyp +++ b/src/starboard/shared/widevine/widevine3.gyp
@@ -34,6 +34,7 @@ 'platform_oem_sources': [ '<(DEPTH)/starboard/keyboxes/<(sb_widevine_platform)/<(sb_widevine_platform).h', '<(DEPTH)/starboard/keyboxes/<(sb_widevine_platform)/<(sb_widevine_platform)_client.c', + '<(DEPTH)/starboard/shared/widevine/widevine_keybox_hash.cc', '<(DEPTH)/starboard/shared/widevine/wv_keybox.cc', ], },
diff --git a/src/starboard/shared/widevine/widevine_keybox_hash.cc b/src/starboard/shared/widevine/widevine_keybox_hash.cc new file mode 100644 index 0000000..281b4b8 --- /dev/null +++ b/src/starboard/shared/widevine/widevine_keybox_hash.cc
@@ -0,0 +1,48 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/shared/widevine/widevine_keybox_hash.h" + +#include <sstream> + +#include "starboard/common/murmurhash2.h" +#include "third_party/ce_cdm/oemcrypto/mock/src/wv_keybox.h" + +namespace wvoec_mock { +namespace { +#if defined(COBALT_WIDEVINE_KEYBOX_INCLUDE) +#include COBALT_WIDEVINE_KEYBOX_INCLUDE +#else // COBALT_WIDEVINE_KEYBOX_INCLUDE +#error "COBALT_WIDEVINE_KEYBOX_INCLUDE is not defined." +#endif // COBALT_WIDEVINE_KEYBOX_INCLUDE +} // namespace +} // namespace wvoec_mock + +namespace starboard { +namespace shared { +namespace widevine { + +std::string GetWidevineKeyboxHash() { + // Note: not a cryptographic hash. + uint32_t value = + MurmurHash2_32(reinterpret_cast<const void*>(&wvoec_mock::kKeybox), + sizeof(wvoec_mock::WidevineKeybox)); + std::stringstream ss; + ss << value; + return ss.str(); +} + +} // namespace widevine +} // namespace shared +} // namespace starboard
diff --git a/src/starboard/shared/widevine/widevine_keybox_hash.h b/src/starboard/shared/widevine/widevine_keybox_hash.h new file mode 100644 index 0000000..e9af759 --- /dev/null +++ b/src/starboard/shared/widevine/widevine_keybox_hash.h
@@ -0,0 +1,34 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_SHARED_WIDEVINE_WIDEVINE_KEYBOX_HASH_H_ +#define STARBOARD_SHARED_WIDEVINE_WIDEVINE_KEYBOX_HASH_H_ + +#include <string> + +#include "starboard/types.h" + +namespace starboard { +namespace shared { +namespace widevine { + +// Computes the checksum of the Widevine Keybox. +// NOTE: this is not a cryptographic hash, but serves our purposes here. +std::string GetWidevineKeyboxHash(); + +} // namespace widevine +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_WIDEVINE_WIDEVINE_KEYBOX_HASH_H_
diff --git a/src/starboard/shared/widevine/widevine_storage.cc b/src/starboard/shared/widevine/widevine_storage.cc index 9d0d6e6..91819e7 100644 --- a/src/starboard/shared/widevine/widevine_storage.cc +++ b/src/starboard/shared/widevine/widevine_storage.cc
@@ -16,12 +16,17 @@ #include "starboard/common/log.h" #include "starboard/file.h" +#include "starboard/shared/widevine/widevine_keybox_hash.h" #include "starboard/types.h" namespace starboard { namespace shared { namespace widevine { +// Reserved key name for referring to the Widevine Keybox checksum value. +const char WidevineStorage::kCobaltWidevineKeyboxChecksumKey[] = + "cobalt_widevine_keybox_checksum"; + namespace { void ReadFile(const std::string& path_name, std::vector<uint8_t>* content) { @@ -121,48 +126,49 @@ } SB_LOG(INFO) << "Loaded " << cache_.size() << " records from " << path_name_; + + // Not a cryptographic hash but is sufficient for this problem space. + std::string keybox_checksum = GetWidevineKeyboxHash(); + if (existsInternal(kCobaltWidevineKeyboxChecksumKey)) { + std::string cached_checksum; + readInternal(kCobaltWidevineKeyboxChecksumKey, &cached_checksum); + if (keybox_checksum == cached_checksum) { + return; + } + SB_LOG(INFO) << "Cobalt widevine keybox checksums do not match. Clearing " + "to force re-provisioning."; + cache_.clear(); + // Save the new keybox checksum to be used after provisioning completes. + writeInternal(kCobaltWidevineKeyboxChecksumKey, keybox_checksum); + return; + } + SB_LOG(INFO) << "Widevine checksum is not stored on disk. Writing the " + "computed checksum to disk."; + writeInternal(kCobaltWidevineKeyboxChecksumKey, keybox_checksum); } bool WidevineStorage::read(const std::string& name, std::string* data) { - SB_DCHECK(data); - ScopedLock scoped_lock(lock_); - auto iter = cache_.find(name); - if (iter == cache_.end()) { - return false; - } - *data = iter->second; - return true; + SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey); + return readInternal(name, data); } bool WidevineStorage::write(const std::string& name, const std::string& data) { - ScopedLock scoped_lock(lock_); - cache_[name] = data; - - std::vector<uint8_t> content; - for (auto iter : cache_) { - WriteString(iter.first, &content); - WriteString(iter.second, &content); - } - - return WriteFile(path_name_, content); + SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey); + return writeInternal(name, data); } bool WidevineStorage::exists(const std::string& name) { - ScopedLock scoped_lock(lock_); - return cache_.find(name) != cache_.end(); + SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey); + return existsInternal(name); } bool WidevineStorage::remove(const std::string& name) { - ScopedLock scoped_lock(lock_); - auto iter = cache_.find(name); - if (iter == cache_.end()) { - return false; - } - cache_.erase(iter); - return true; + SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey); + return removeInternal(name); } int32_t WidevineStorage::size(const std::string& name) { + SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey); ScopedLock scoped_lock(lock_); auto iter = cache_.find(name); return iter == cache_.end() ? -1 : static_cast<int32_t>(iter->second.size()); @@ -173,11 +179,54 @@ ScopedLock scoped_lock(lock_); records->clear(); for (auto item : cache_) { + if (item.first == kCobaltWidevineKeyboxChecksumKey) { + continue; + } records->push_back(item.first); } return !records->empty(); } +bool WidevineStorage::readInternal(const std::string& name, + std::string* data) const { + SB_DCHECK(data); + ScopedLock scoped_lock(lock_); + auto iter = cache_.find(name); + if (iter == cache_.end()) { + return false; + } + *data = iter->second; + return true; +} + +bool WidevineStorage::writeInternal(const std::string& name, + const std::string& data) { + ScopedLock scoped_lock(lock_); + cache_[name] = data; + + std::vector<uint8_t> content; + for (auto iter : cache_) { + WriteString(iter.first, &content); + WriteString(iter.second, &content); + } + return WriteFile(path_name_, content); +} + +bool WidevineStorage::existsInternal(const std::string& name) const { + ScopedLock scoped_lock(lock_); + return cache_.find(name) != cache_.end(); +} + +bool WidevineStorage::removeInternal(const std::string& name) { + ScopedLock scoped_lock(lock_); + auto iter = cache_.find(name); + if (iter == cache_.end()) { + return false; + } + cache_.erase(iter); + return true; +} + } // namespace widevine } // namespace shared } // namespace starboard
diff --git a/src/starboard/shared/widevine/widevine_storage.h b/src/starboard/shared/widevine/widevine_storage.h index 218b118..5ee9ba8 100644 --- a/src/starboard/shared/widevine/widevine_storage.h +++ b/src/starboard/shared/widevine/widevine_storage.h
@@ -30,8 +30,13 @@ // Widevine to store persistent data like device provisioning. class WidevineStorage : public ::widevine::Cdm::IStorage { public: + // This key is restricted to internal use only. + static const char kCobaltWidevineKeyboxChecksumKey[]; + explicit WidevineStorage(const std::string& path_name); + // For these accessor methods the |name| field cannot be + // |kCobaltWidevineKeyboxChecksumKey|. bool read(const std::string& name, std::string* data) override; bool write(const std::string& name, const std::string& data) override; bool exists(const std::string& name) override; @@ -44,6 +49,11 @@ bool list(std::vector<std::string>* records) override; private: + bool readInternal(const std::string& name, std::string* data) const; + bool writeInternal(const std::string& name, const std::string& data); + bool existsInternal(const std::string& name) const; + bool removeInternal(const std::string& name); + Mutex lock_; std::string path_name_; std::map<std::string, std::string> cache_;
diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc index 514aedf..42376d4 100644 --- a/src/starboard/shared/x11/application_x11.cc +++ b/src/starboard/shared/x11/application_x11.cc
@@ -843,7 +843,9 @@ int z_index, int x, int y, int width, int height) { ScopedLock lock(frame_mutex_); - // The bounds should only take effect once the UI frame is submitted. + bool player_exists = + next_video_bounds_.find(player) != next_video_bounds_.end(); + FrameInfo& frame_info = next_video_bounds_[player]; frame_info.player = player; frame_info.z_index = z_index; @@ -851,6 +853,22 @@ frame_info.y = y; frame_info.width = width; frame_info.height = height; + + if (player_exists) { + return; + } + + // The bounds should only take effect once the UI frame is submitted. But we + // apply the bounds immediately if it is the first time the bounds for this + // player are set. + auto position = current_video_bounds_.begin(); + while (position != current_video_bounds_.end()) { + if (frame_info.z_index < position->z_index) { + break; + } + ++position; + } + current_video_bounds_.insert(position, frame_info); } void ApplicationX11::Initialize() {
diff --git a/src/starboard/socket.h b/src/starboard/socket.h index 9db8dfc..663c43b 100644 --- a/src/starboard/socket.h +++ b/src/starboard/socket.h
@@ -135,6 +135,11 @@ return socket != kSbSocketInvalid; } +#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION +// Returns whether IPV6 is supported on the current platform. +SB_EXPORT bool SbSocketIsIpv6Supported(); +#endif + // Creates a new non-blocking socket for protocol |protocol| using address // family |address_type|. //
diff --git a/src/starboard/speech_recognizer.h b/src/starboard/speech_recognizer.h index 67eca0b..4524a84 100644 --- a/src/starboard/speech_recognizer.h +++ b/src/starboard/speech_recognizer.h
@@ -35,7 +35,8 @@ #include "starboard/export.h" #include "starboard/types.h" -#if SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \ + SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 #ifdef __cplusplus extern "C" { @@ -145,6 +146,11 @@ void* context; }; +#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION +// Returns whether the platform supports SbSpeechRecognizer. +SB_EXPORT bool SbSpeechRecognizerIsSupported(); +#endif + // Creates a speech recognizer with a speech recognizer handler. // // If the system has a speech recognition service available, this function @@ -194,6 +200,8 @@ } // extern "C" #endif -#endif // SB_HAS(SPEECH_RECOGNIZER) && SB_API_VERSION >= 5 +#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || + // SB_HAS(SPEECH_RECOGNIZER) + // && SB_API_VERSION >= 5 #endif // STARBOARD_SPEECH_RECOGNIZER_H_
diff --git a/src/starboard/speech_synthesis.h b/src/starboard/speech_synthesis.h index 583f1c4..771be95 100644 --- a/src/starboard/speech_synthesis.h +++ b/src/starboard/speech_synthesis.h
@@ -29,12 +29,18 @@ #include "starboard/export.h" #include "starboard/types.h" -#if SB_HAS(SPEECH_SYNTHESIS) +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \ + SB_HAS(SPEECH_SYNTHESIS) #ifdef __cplusplus extern "C" { #endif +#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION +// Returns whether the platform supports speech synthesis +SB_EXPORT bool SbSpeechSynthesisIsSupported(); +#endif + // Enqueues |text|, a UTF-8 string, to be spoken. // Returns immediately. // @@ -54,6 +60,7 @@ } // extern "C" #endif -#endif // SB_HAS(SPEECH_SYNTHESIS) +#endif // SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || + // SB_HAS(SPEECH_SYNTHESIS) #endif // STARBOARD_SPEECH_SYNTHESIS_H_
diff --git a/src/starboard/starboard_all.gyp b/src/starboard/starboard_all.gyp index a5b3291..76bb448 100644 --- a/src/starboard/starboard_all.gyp +++ b/src/starboard/starboard_all.gyp
@@ -66,6 +66,7 @@ '<(DEPTH)/starboard/nplb/blitter_pixel_tests/blitter_pixel_tests.gyp:*', '<(DEPTH)/starboard/nplb/nplb.gyp:*', '<(DEPTH)/starboard/starboard.gyp:*', + '<(DEPTH)/starboard/tools/tools.gyp:*', ], 'conditions': [ ['gl_type != "none"', {
diff --git a/src/starboard/storage.h b/src/starboard/storage.h index 41712e8..393ac88 100644 --- a/src/starboard/storage.h +++ b/src/starboard/storage.h
@@ -109,9 +109,7 @@ // // |record|: The record to be written to. // |data|: The data to write to the record. -// |data_size|: The amount of |data|, in bytes, to write to the record. Thus, -// if |data_size| is smaller than the total size of |data|, only part of -// |data| is written to the record. +// |data_size|: The amount of |data|, in bytes, to write to the record. SB_EXPORT bool SbStorageWriteRecord(SbStorageRecord record, const char* data, int64_t data_size);
diff --git a/src/starboard/stub/BUILD.gn b/src/starboard/stub/BUILD.gn index cfeb1ba..45470df 100644 --- a/src/starboard/stub/BUILD.gn +++ b/src/starboard/stub/BUILD.gn
@@ -172,6 +172,7 @@ "//starboard/shared/starboard/player/filter/stub_video_decoder.cc", "//starboard/shared/starboard/player/filter/stub_video_decoder.h", "//starboard/shared/starboard/queue_application.cc", + "//starboard/shared/stub/accessibility_get_caption_settings.cc", "//starboard/shared/stub/accessibility_get_display_settings.cc", "//starboard/shared/stub/accessibility_get_text_to_speech_settings.cc", "//starboard/shared/stub/atomic_public.h", @@ -220,6 +221,7 @@ "//starboard/shared/stub/drm_system_internal.h", "//starboard/shared/stub/drm_update_server_certificate.cc", "//starboard/shared/stub/drm_update_session.cc", + "//starboard/shared/stub/file_atomic_replace.cc", "//starboard/shared/stub/file_can_open.cc", "//starboard/shared/stub/file_close.cc", "//starboard/shared/stub/file_delete.cc", @@ -320,9 +322,11 @@ "//starboard/shared/stub/speech_recognizer_cancel.cc", "//starboard/shared/stub/speech_recognizer_create.cc", "//starboard/shared/stub/speech_recognizer_destroy.cc", + "//starboard/shared/stub/speech_recognizer_is_supported.cc", "//starboard/shared/stub/speech_recognizer_start.cc", "//starboard/shared/stub/speech_recognizer_stop.cc", "//starboard/shared/stub/speech_synthesis_cancel.cc", + "//starboard/shared/stub/speech_synthesis_is_supported.cc", "//starboard/shared/stub/speech_synthesis_speak.cc", "//starboard/shared/stub/storage_close_record.cc", "//starboard/shared/stub/storage_delete_record.cc", @@ -399,6 +403,7 @@ "//starboard/shared/stub/time_get_monotonic_now.cc", "//starboard/shared/stub/time_get_monotonic_thread_now.cc", "//starboard/shared/stub/time_get_now.cc", + "//starboard/shared/posix/time_is_time_thread_now_supported.cc", "//starboard/shared/stub/time_zone_get_current.cc", "//starboard/shared/stub/time_zone_get_dst_name.cc", "//starboard/shared/stub/time_zone_get_name.cc",
diff --git a/src/starboard/stub/blitter_stub_sources.gypi b/src/starboard/stub/blitter_stub_sources.gypi new file mode 100644 index 0000000..095eaba --- /dev/null +++ b/src/starboard/stub/blitter_stub_sources.gypi
@@ -0,0 +1,52 @@ +# Copyright 2019 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. +{ + 'variables': { + 'blitter_stub_sources': [ + '<(DEPTH)/starboard/shared/stub/blitter_blit_rects_to_rects.cc', + '<(DEPTH)/starboard/shared/stub/blitter_blit_rect_to_rect.cc', + '<(DEPTH)/starboard/shared/stub/blitter_blit_rect_to_rect_tiled.cc', + '<(DEPTH)/starboard/shared/stub/blitter_create_context.cc', + '<(DEPTH)/starboard/shared/stub/blitter_create_default_device.cc', + '<(DEPTH)/starboard/shared/stub/blitter_create_pixel_data.cc', + '<(DEPTH)/starboard/shared/stub/blitter_create_render_target_surface.cc', + '<(DEPTH)/starboard/shared/stub/blitter_create_surface_from_pixel_data.cc', + '<(DEPTH)/starboard/shared/stub/blitter_create_swap_chain_from_window.cc', + '<(DEPTH)/starboard/shared/stub/blitter_destroy_context.cc', + '<(DEPTH)/starboard/shared/stub/blitter_destroy_device.cc', + '<(DEPTH)/starboard/shared/stub/blitter_destroy_pixel_data.cc', + '<(DEPTH)/starboard/shared/stub/blitter_destroy_surface.cc', + '<(DEPTH)/starboard/shared/stub/blitter_destroy_swap_chain.cc', + '<(DEPTH)/starboard/shared/stub/blitter_download_surface_pixels.cc', + '<(DEPTH)/starboard/shared/stub/blitter_fill_rect.cc', + '<(DEPTH)/starboard/shared/stub/blitter_flip_swap_chain.cc', + '<(DEPTH)/starboard/shared/stub/blitter_flush_context.cc', + '<(DEPTH)/starboard/shared/stub/blitter_get_max_contexts.cc', + '<(DEPTH)/starboard/shared/stub/blitter_get_pixel_data_pitch_in_bytes.cc', + '<(DEPTH)/starboard/shared/stub/blitter_get_pixel_data_pointer.cc', + '<(DEPTH)/starboard/shared/stub/blitter_get_render_target_from_surface.cc', + '<(DEPTH)/starboard/shared/stub/blitter_get_render_target_from_swap_chain.cc', + '<(DEPTH)/starboard/shared/stub/blitter_get_surface_info.cc', + '<(DEPTH)/starboard/shared/stub/blitter_is_blitter_supported.cc', + '<(DEPTH)/starboard/shared/stub/blitter_is_pixel_format_supported_by_download_surface_pixels.cc', + '<(DEPTH)/starboard/shared/stub/blitter_is_pixel_format_supported_by_pixel_data.cc', + '<(DEPTH)/starboard/shared/stub/blitter_is_surface_format_supported_by_render_target_surface.cc', + '<(DEPTH)/starboard/shared/stub/blitter_set_blending.cc', + '<(DEPTH)/starboard/shared/stub/blitter_set_color.cc', + '<(DEPTH)/starboard/shared/stub/blitter_set_modulate_blits_with_color.cc', + '<(DEPTH)/starboard/shared/stub/blitter_set_render_target.cc', + '<(DEPTH)/starboard/shared/stub/blitter_set_scissor.cc', + ] + } +} \ No newline at end of file
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h index 2483b93..265be2a 100644 --- a/src/starboard/stub/configuration_public.h +++ b/src/starboard/stub/configuration_public.h
@@ -22,52 +22,14 @@ #ifndef STARBOARD_STUB_CONFIGURATION_PUBLIC_H_ #define STARBOARD_STUB_CONFIGURATION_PUBLIC_H_ -// The API version implemented by this platform. This will generally be set to -// the current value of SB_MAXIMUM_API_VERSION at the time of implementation. -#define SB_API_VERSION SB_EXPERIMENTAL_API_VERSION +#if SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION +#error \ + "This platform's sabi.json file is expected to track the experimental " \ +"Starboard API version." +#endif // SB_API_VERSION != SB_EXPERIMENTAL_API_VERSION // --- Architecture Configuration -------------------------------------------- -// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be -// automatically set based on this. -#define SB_IS_BIG_ENDIAN 0 - -// Whether the current platform is an ARM architecture. -#define SB_IS_ARCH_ARM 0 - -// Whether the current platform is a MIPS architecture. -#define SB_IS_ARCH_MIPS 0 - -// Whether the current platform is a PPC architecture. -#define SB_IS_ARCH_PPC 0 - -// Whether the current platform is an x86 architecture. -#define SB_IS_ARCH_X86 1 - -// Assume a 64-bit architecture. -#define SB_IS_32_BIT 0 -#define SB_IS_64_BIT 1 - -// Whether the current platform's pointers are 32-bit. -// Whether the current platform's longs are 32-bit. -#if SB_IS(32_BIT) -#define SB_HAS_32_BIT_POINTERS 1 -#define SB_HAS_32_BIT_LONG 1 -#else -#define SB_HAS_32_BIT_POINTERS 0 -#define SB_HAS_32_BIT_LONG 0 -#endif - -// Whether the current platform's pointers are 64-bit. -// Whether the current platform's longs are 64-bit. -#if SB_IS(64_BIT) -#define SB_HAS_64_BIT_POINTERS 1 -#define SB_HAS_64_BIT_LONG 1 -#else -#define SB_HAS_64_BIT_POINTERS 0 -#define SB_HAS_64_BIT_LONG 0 -#endif - // Configuration parameters that allow the application to make some general // compile-time decisions with respect to the the number of cores likely to be // available on this platform. For a definitive measure, the application should @@ -295,12 +257,6 @@ // textures. These textures typically originate from video decoders. #define SB_HAS_NV12_TEXTURE_SUPPORT 0 -// Whether the current platform should frequently flip its display buffer. If -// this is not required (i.e. SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER is set to -// 0), then optimizations are enabled so the display buffer is not flipped if -// the scene hasn't changed. -#define SB_MUST_FREQUENTLY_FLIP_DISPLAY_BUFFER 0 - #define SB_HAS_VIRTUAL_REALITY 1 // --- I/O Configuration ----------------------------------------------------- @@ -394,7 +350,9 @@ // Whether this platform has and should use an MMAP function to map physical // memory to the virtual address space. +#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION #define SB_HAS_MMAP 1 +#endif // Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is // required for platforms that want to JIT.
diff --git a/src/starboard/stub/gyp_configuration.gypi b/src/starboard/stub/gyp_configuration.gypi index e0af518..1692859 100644 --- a/src/starboard/stub/gyp_configuration.gypi +++ b/src/starboard/stub/gyp_configuration.gypi
@@ -163,4 +163,8 @@ }], ], }, # end of target_defaults + + 'includes': [ + '<(DEPTH)/starboard/sabi/sabi.gypi', + ], }
diff --git a/src/starboard/stub/gyp_configuration.py b/src/starboard/stub/gyp_configuration.py index e548bdd..38b5493 100644 --- a/src/starboard/stub/gyp_configuration.py +++ b/src/starboard/stub/gyp_configuration.py
@@ -19,6 +19,8 @@ from starboard.build import clang from starboard.tools import build +_SABI_JSON_PATH = 'starboard/sabi/x64/sysv/sabi.json' + def CreatePlatformConfig(): try: @@ -63,3 +65,6 @@ A list of initialized TestFilter objects. """ return [] + + def GetPathToSabiJsonFile(self): + return _SABI_JSON_PATH
diff --git a/src/starboard/stub/stub_sources.gypi b/src/starboard/stub/stub_sources.gypi index 8a9cffb..10cacff 100644 --- a/src/starboard/stub/stub_sources.gypi +++ b/src/starboard/stub/stub_sources.gypi
@@ -12,8 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. { + 'includes': [ + 'blitter_stub_sources.gypi', + ], 'variables': { 'stub_sources': [ + '<@(blitter_stub_sources)', '<(DEPTH)/starboard/shared/starboard/application.cc', '<(DEPTH)/starboard/shared/starboard/command_line.cc', '<(DEPTH)/starboard/shared/starboard/command_line.h', @@ -77,8 +81,7 @@ '<(DEPTH)/starboard/shared/stub/drm_system_internal.h', '<(DEPTH)/starboard/shared/stub/drm_update_server_certificate.cc', '<(DEPTH)/starboard/shared/stub/drm_update_session.cc', - '<(DEPTH)/starboard/shared/stub/image_decode.cc', - '<(DEPTH)/starboard/shared/stub/image_is_decode_supported.cc', + '<(DEPTH)/starboard/shared/stub/file_atomic_replace.cc', '<(DEPTH)/starboard/shared/stub/file_can_open.cc', '<(DEPTH)/starboard/shared/stub/file_close.cc', '<(DEPTH)/starboard/shared/stub/file_delete.cc', @@ -91,6 +94,8 @@ '<(DEPTH)/starboard/shared/stub/file_seek.cc', '<(DEPTH)/starboard/shared/stub/file_truncate.cc', '<(DEPTH)/starboard/shared/stub/file_write.cc', + '<(DEPTH)/starboard/shared/stub/image_decode.cc', + '<(DEPTH)/starboard/shared/stub/image_is_decode_supported.cc', '<(DEPTH)/starboard/shared/stub/log.cc', '<(DEPTH)/starboard/shared/stub/log_flush.cc', '<(DEPTH)/starboard/shared/stub/log_format.cc', @@ -175,6 +180,7 @@ '<(DEPTH)/starboard/shared/stub/socket_get_local_address.cc', '<(DEPTH)/starboard/shared/stub/socket_is_connected.cc', '<(DEPTH)/starboard/shared/stub/socket_is_connected_and_idle.cc', + '<(DEPTH)/starboard/shared/stub/socket_is_ipv6_supported.cc', '<(DEPTH)/starboard/shared/stub/socket_join_multicast_group.cc', '<(DEPTH)/starboard/shared/stub/socket_listen.cc', '<(DEPTH)/starboard/shared/stub/socket_receive_from.cc', @@ -197,9 +203,11 @@ '<(DEPTH)/starboard/shared/stub/speech_recognizer_cancel.cc', '<(DEPTH)/starboard/shared/stub/speech_recognizer_create.cc', '<(DEPTH)/starboard/shared/stub/speech_recognizer_destroy.cc', + '<(DEPTH)/starboard/shared/stub/speech_recognizer_is_supported.cc', '<(DEPTH)/starboard/shared/stub/speech_recognizer_start.cc', '<(DEPTH)/starboard/shared/stub/speech_recognizer_stop.cc', '<(DEPTH)/starboard/shared/stub/speech_synthesis_cancel.cc', + '<(DEPTH)/starboard/shared/stub/speech_synthesis_is_supported.cc', '<(DEPTH)/starboard/shared/stub/speech_synthesis_speak.cc', '<(DEPTH)/starboard/shared/stub/storage_close_record.cc', '<(DEPTH)/starboard/shared/stub/storage_delete_record.cc', @@ -286,19 +294,28 @@ '<(DEPTH)/starboard/shared/stub/time_get_monotonic_now.cc', '<(DEPTH)/starboard/shared/stub/time_get_monotonic_thread_now.cc', '<(DEPTH)/starboard/shared/stub/time_get_now.cc', + '<(DEPTH)/starboard/shared/stub/time_is_time_thread_now_supported.cc', '<(DEPTH)/starboard/shared/stub/time_zone_get_current.cc', '<(DEPTH)/starboard/shared/stub/time_zone_get_name.cc', '<(DEPTH)/starboard/shared/stub/ui_nav_get_interface.cc', '<(DEPTH)/starboard/shared/stub/user_get_current.cc', '<(DEPTH)/starboard/shared/stub/user_get_property.cc', '<(DEPTH)/starboard/shared/stub/user_get_signed_in.cc', + '<(DEPTH)/starboard/shared/stub/window_blur_on_screen_keyboard.cc', '<(DEPTH)/starboard/shared/stub/window_create.cc', '<(DEPTH)/starboard/shared/stub/window_destroy.cc', + '<(DEPTH)/starboard/shared/stub/window_focus_on_screen_keyboard.cc', '<(DEPTH)/starboard/shared/stub/window_get_diagonal_size_in_inches.cc', + '<(DEPTH)/starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc', '<(DEPTH)/starboard/shared/stub/window_get_platform_handle.cc', '<(DEPTH)/starboard/shared/stub/window_get_size.cc', + '<(DEPTH)/starboard/shared/stub/window_hide_on_screen_keyboard.cc', + '<(DEPTH)/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc', + '<(DEPTH)/starboard/shared/stub/window_on_screen_keyboard_is_supported.cc', '<(DEPTH)/starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc', '<(DEPTH)/starboard/shared/stub/window_set_default_options.cc', + '<(DEPTH)/starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc', + '<(DEPTH)/starboard/shared/stub/window_show_on_screen_keyboard.cc', '<(DEPTH)/starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc', ], },
diff --git a/src/starboard/system.h b/src/starboard/system.h index 1f41f54..beea1bd 100644 --- a/src/starboard/system.h +++ b/src/starboard/system.h
@@ -69,6 +69,13 @@ // Full path to the executable file. kSbSystemPathExecutableFile, + +#if SB_API_VERSION >= SB_STORAGE_PATH_VERSION + // Path to a directory for permanent file storage. Both read and write + // access is required. This is where an app may store its persistent settings. + // The location should be user agnostic if possible. + kSbSystemPathStorageDirectory, +#endif } SbSystemPathId; // System properties that can be queried for. Many of these are used in @@ -630,10 +637,11 @@ // (or greater), since 32-bytes will be written into it. // Returns false in the case of an error, or if it is not implemented. In this // case the contents of |digest| will be undefined. -bool SbSystemSignWithCertificationSecretKey(const uint8_t* message, - size_t message_size_in_bytes, - uint8_t* digest, - size_t digest_size_in_bytes); +SB_EXPORT bool SbSystemSignWithCertificationSecretKey( + const uint8_t* message, + size_t message_size_in_bytes, + uint8_t* digest, + size_t digest_size_in_bytes); #endif #ifdef __cplusplus
diff --git a/src/starboard/testing/fake_graphics_context_provider.cc b/src/starboard/testing/fake_graphics_context_provider.cc index 0e31aa1..50ce274 100644 --- a/src/starboard/testing/fake_graphics_context_provider.cc +++ b/src/starboard/testing/fake_graphics_context_provider.cc
@@ -33,23 +33,40 @@ #include "starboard/configuration.h" #include "starboard/memory.h" +#if SB_API_VERSION >= 11 #define EGL_CALL_PREFIX SbGetEglInterface()-> -#define GL_CALL_PREFIX SbGetGlInterface()-> -#define EGL_CALL(x) \ - do { \ - EGL_CALL_PREFIX x; \ - SB_DCHECK(EGL_CALL_PREFIX eglGetError() == SB_EGL_SUCCESS); \ - } while (false) +#define EGLConfig SbEglConfig +#define EGLint SbEglInt32 +#define EGLNativeWindowType SbEglNativeWindowType -#define GL_CALL(x) \ - do { \ - GL_CALL_PREFIX x; \ - SB_DCHECK(GL_CALL_PREFIX glGetError() == SB_GL_NO_ERROR); \ +#define EGL_ALPHA_SIZE SB_EGL_ALPHA_SIZE +#define EGL_BLUE_SIZE SB_EGL_BLUE_SIZE +#define EGL_CONTEXT_CLIENT_VERSION SB_EGL_CONTEXT_CLIENT_VERSION +#define EGL_DEFAULT_DISPLAY SB_EGL_DEFAULT_DISPLAY +#define EGL_GREEN_SIZE SB_EGL_GREEN_SIZE +#define EGL_NONE SB_EGL_NONE +#define EGL_NO_CONTEXT SB_EGL_NO_CONTEXT +#define EGL_NO_DISPLAY SB_EGL_NO_DISPLAY +#define EGL_NO_SURFACE SB_EGL_NO_SURFACE +#define EGL_OPENGL_ES2_BIT SB_EGL_OPENGL_ES2_BIT +#define EGL_PBUFFER_BIT SB_EGL_PBUFFER_BIT +#define EGL_RED_SIZE SB_EGL_RED_SIZE +#define EGL_RENDERABLE_TYPE SB_EGL_RENDERABLE_TYPE +#define EGL_SUCCESS SB_EGL_SUCCESS +#define EGL_SURFACE_TYPE SB_EGL_SURFACE_TYPE +#define EGL_WINDOW_BIT SB_EGL_WINDOW_BIT +#else // SB_API_VERSION < 11 +#define EGL_CALL_PREFIX +#endif // SB_API_VERSION >= 11 + +#define EGL_CALL(x) \ + do { \ + EGL_CALL_PREFIX x; \ + SB_DCHECK(EGL_CALL_PREFIX eglGetError() == EGL_SUCCESS); \ } while (false) #define EGL_CALL_SIMPLE(x) (EGL_CALL_PREFIX x) -#define GL_CALL_SIMPLE(x) (GL_CALL_PREFIX x) namespace starboard { namespace testing { @@ -57,19 +74,19 @@ namespace { #if SB_HAS(GLES2) -SbEglInt32 const kAttributeList[] = {SB_EGL_RED_SIZE, - 8, - SB_EGL_GREEN_SIZE, - 8, - SB_EGL_BLUE_SIZE, - 8, - SB_EGL_ALPHA_SIZE, - 8, - SB_EGL_SURFACE_TYPE, - SB_EGL_WINDOW_BIT | SB_EGL_PBUFFER_BIT, - SB_EGL_RENDERABLE_TYPE, - SB_EGL_OPENGL_ES2_BIT, - SB_EGL_NONE}; +EGLint const kAttributeList[] = {EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 8, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT | EGL_PBUFFER_BIT, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_NONE}; #endif // SB_HAS(GLES2) } // namespace @@ -77,9 +94,9 @@ FakeGraphicsContextProvider::FakeGraphicsContextProvider() : #if SB_HAS(GLES2) - display_(SB_EGL_NO_DISPLAY), - surface_(SB_EGL_NO_SURFACE), - context_(SB_EGL_NO_CONTEXT), + display_(EGL_NO_DISPLAY), + surface_(EGL_NO_SURFACE), + context_(EGL_NO_CONTEXT), #endif // SB_HAS(GLES2) window_(kSbWindowInvalid) { InitializeWindow(); @@ -170,9 +187,9 @@ #if SB_HAS(GLES2) void FakeGraphicsContextProvider::InitializeEGL() { - display_ = EGL_CALL_SIMPLE(eglGetDisplay(SB_EGL_DEFAULT_DISPLAY)); - SB_DCHECK(SB_EGL_SUCCESS == EGL_CALL_SIMPLE(eglGetError())); - SB_CHECK(SB_EGL_NO_DISPLAY != display_); + display_ = EGL_CALL_SIMPLE(eglGetDisplay(EGL_DEFAULT_DISPLAY)); + SB_DCHECK(EGL_SUCCESS == EGL_CALL_SIMPLE(eglGetError())); + SB_CHECK(EGL_NO_DISPLAY != display_); #if HAS_LEAK_SANITIZER __lsan_disable(); @@ -181,7 +198,7 @@ #if HAS_LEAK_SANITIZER __lsan_enable(); #endif // HAS_LEAK_SANITIZER - SB_DCHECK(SB_EGL_SUCCESS == EGL_CALL_SIMPLE(eglGetError())); + SB_DCHECK(EGL_SUCCESS == EGL_CALL_SIMPLE(eglGetError())); // Some EGL drivers can return a first config that doesn't allow // eglCreateWindowSurface(), with no differences in EGLConfig attribute values @@ -189,19 +206,19 @@ // eglCreateWindowSurface() until we find a config that succeeds. // First, query how many configs match the given attribute list. - SbEglInt32 num_configs = 0; + EGLint num_configs = 0; EGL_CALL(eglChooseConfig(display_, kAttributeList, NULL, 0, &num_configs)); SB_CHECK(0 != num_configs); // Allocate space to receive the matching configs and retrieve them. - SbEglConfig* configs = reinterpret_cast<SbEglConfig*>( - SbMemoryAllocate(num_configs * sizeof(SbEglConfig))); + EGLConfig* configs = reinterpret_cast<EGLConfig*>( + SbMemoryAllocate(num_configs * sizeof(EGLConfig))); EGL_CALL(eglChooseConfig(display_, kAttributeList, configs, num_configs, &num_configs)); - SbEglNativeWindowType native_window = - (SbEglNativeWindowType)SbWindowGetPlatformHandle(window_); - SbEglConfig config = SbEglConfig(); + EGLNativeWindowType native_window = + (EGLNativeWindowType)SbWindowGetPlatformHandle(window_); + EGLConfig config = EGLConfig(); // Find the first config that successfully allow a window surface to be // created. @@ -209,30 +226,30 @@ config = configs[config_number]; surface_ = EGL_CALL_SIMPLE( eglCreateWindowSurface(display_, config, native_window, NULL)); - if (SB_EGL_SUCCESS == EGL_CALL_SIMPLE(eglGetError())) + if (EGL_SUCCESS == EGL_CALL_SIMPLE(eglGetError())) break; } - SB_DCHECK(surface_ != SB_EGL_NO_SURFACE); + SB_DCHECK(surface_ != EGL_NO_SURFACE); SbMemoryDeallocate(configs); // Create the GLES2 or GLEX3 Context. - SbEglInt32 context_attrib_list[] = { - SB_EGL_CONTEXT_CLIENT_VERSION, 3, SB_EGL_NONE, + EGLint context_attrib_list[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE, }; #if defined(GLES3_SUPPORTED) // Attempt to create an OpenGL ES 3.0 context. context_ = EGL_CALL_SIMPLE(eglCreateContext( - display_, config, SB_EGL_NO_CONTEXT, context_attrib_list)); + display_, config, EGL_NO_CONTEXT, context_attrib_list)); #endif - if (context_ == SB_EGL_NO_CONTEXT) { + if (context_ == EGL_NO_CONTEXT) { // Create an OpenGL ES 2.0 context. context_attrib_list[1] = 2; context_ = EGL_CALL_SIMPLE(eglCreateContext( - display_, config, SB_EGL_NO_CONTEXT, context_attrib_list)); + display_, config, EGL_NO_CONTEXT, context_attrib_list)); } - SB_CHECK(SB_EGL_SUCCESS == EGL_CALL_SIMPLE(eglGetError())); - SB_CHECK(context_ != SB_EGL_NO_CONTEXT); + SB_CHECK(EGL_SUCCESS == EGL_CALL_SIMPLE(eglGetError())); + SB_CHECK(context_ != EGL_NO_CONTEXT); MakeContextCurrent(); @@ -271,22 +288,22 @@ } void FakeGraphicsContextProvider::MakeContextCurrent() { - SB_CHECK(SB_EGL_NO_DISPLAY != display_); + SB_CHECK(EGL_NO_DISPLAY != display_); EGL_CALL_SIMPLE(eglMakeCurrent(display_, surface_, surface_, context_)); - SbEglInt32 error = EGL_CALL_SIMPLE(eglGetError()); - SB_CHECK(SB_EGL_SUCCESS == error) << " eglGetError " << error; + EGLint error = EGL_CALL_SIMPLE(eglGetError()); + SB_CHECK(EGL_SUCCESS == error) << " eglGetError " << error; } void FakeGraphicsContextProvider::MakeNoContextCurrent() { - EGL_CALL(eglMakeCurrent(display_, SB_EGL_NO_SURFACE, SB_EGL_NO_SURFACE, - SB_EGL_NO_CONTEXT)); + EGL_CALL(eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT)); } void FakeGraphicsContextProvider::DestroyContext() { MakeNoContextCurrent(); EGL_CALL_SIMPLE(eglDestroyContext(display_, context_)); - SbEglInt32 error = EGL_CALL_SIMPLE(eglGetError()); - SB_CHECK(SB_EGL_SUCCESS == error) << " eglGetError " << error; + EGLint error = EGL_CALL_SIMPLE(eglGetError()); + SB_CHECK(EGL_SUCCESS == error) << " eglGetError " << error; } // static
diff --git a/src/starboard/testing/fake_graphics_context_provider.h b/src/starboard/testing/fake_graphics_context_provider.h index fcde71d..cf243d1 100644 --- a/src/starboard/testing/fake_graphics_context_provider.h +++ b/src/starboard/testing/fake_graphics_context_provider.h
@@ -20,11 +20,20 @@ #include "starboard/common/queue.h" #include "starboard/configuration.h" #include "starboard/decode_target.h" -#include "starboard/egl.h" -#include "starboard/gles.h" #include "starboard/thread.h" #include "starboard/window.h" +#if SB_API_VERSION >= 11 +#include "starboard/egl.h" +#include "starboard/gles.h" +#else // SB_API_VERSION < 11 +// SB_HAS() is available after starboard/configuration.h is included. +#if SB_HAS(GLES2) +#include <EGL/egl.h> +#include <GLES2/gl2.h> +#endif // SB_HAS(GLES2) +#endif // SB_API_VERSION >= 11 + namespace starboard { namespace testing { @@ -74,9 +83,15 @@ SbDecodeTargetGlesContextRunnerTarget target_function, void* target_function_context); +#if SB_API_VERSION >= 11 SbEglDisplay display_; SbEglSurface surface_; SbEglContext context_; +#else // SB_API_VERSION < 11 + EGLDisplay display_; + EGLSurface surface_; + EGLContext context_; +#endif // SB_API_VERSION >= 11 Queue<std::function<void()>> functor_queue_; SbThread decode_target_context_thread_; #endif // SB_HAS(GLES2)
diff --git a/src/starboard/time.h b/src/starboard/time.h index cfedb06..088f682 100644 --- a/src/starboard/time.h +++ b/src/starboard/time.h
@@ -91,14 +91,23 @@ // Gets a monotonically increasing time representing right now. SB_EXPORT SbTimeMonotonic SbTimeGetMonotonicNow(); -#if SB_HAS(TIME_THREAD_NOW) +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \ + SB_HAS(TIME_THREAD_NOW) + +#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION +// Returns whether the current platform supports time thread now +SB_EXPORT bool SbTimeIsTimeThreadNowSupported(); +#endif + // Gets a monotonically increasing time representing how long the current // thread has been in the executing state (i.e. not pre-empted nor waiting // on an event). This is not necessarily total time and is intended to allow // measuring thread execution time between two timestamps. If this is not // available then SbTimeGetMonotonicNow() should be used. SB_EXPORT SbTimeMonotonic SbTimeGetMonotonicThreadNow(); -#endif + +#endif // SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || + // SB_HAS(TIME_THREAD_NOW) #ifdef __cplusplus } // extern "C"
diff --git a/src/starboard/tools/abstract_launcher.py b/src/starboard/tools/abstract_launcher.py index 30fbeb4..90dc288 100644 --- a/src/starboard/tools/abstract_launcher.py +++ b/src/starboard/tools/abstract_launcher.py
@@ -48,7 +48,8 @@ target_params=None, output_file=None, out_directory=None, - env_variables=None): + env_variables=None, + **kwargs): """Creates the proper launcher based upon command line args. Args: @@ -61,7 +62,8 @@ None, sys.stdout is used. out_directory: Directory containing the executable target. If None is provided, the path to the directory is dynamically generated. - env_variables: Environment variables for the executable + env_variables: Environment variables for the executable. + **kwargs: Additional parameters to be passed to the launcher. Returns: An instance of the concrete launcher class for the desired platform. @@ -84,7 +86,8 @@ target_params=target_params, output_file=output_file, out_directory=out_directory, - env_variables=env_variables) + env_variables=env_variables, + **kwargs) class AbstractLauncher(object): @@ -105,6 +108,7 @@ if not out_directory: out_directory = paths.BuildOutputDirectory(platform_name, config) self.out_directory = out_directory + self.coverage_directory = kwargs.get("coverage_directory", out_directory) output_file = kwargs.get("output_file", None) if not output_file: @@ -127,7 +131,9 @@ @abc.abstractmethod def Run(self): - """Runs the launcher's executable. Must be implemented in subclasses. + """Runs the launcher's executable. + + Must be implemented in subclasses. Returns: The return code from the launcher's executable.
diff --git a/src/starboard/tools/app_launcher_packager.py b/src/starboard/tools/app_launcher_packager.py index 4991c6a..9090373 100644 --- a/src/starboard/tools/app_launcher_packager.py +++ b/src/starboard/tools/app_launcher_packager.py
@@ -1,5 +1,3 @@ -#!/usr/bin/python -# # Copyright 2017 The Cobalt Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,56 +19,22 @@ that the app launcher can be run independent of the Cobalt source tree. """ - -################################################################################ -# API # -################################################################################ - - -def CopyAppLauncherTools(repo_root, dest_root, - additional_glob_patterns=None, - include_black_box_tests=True): - """Copies app launcher related files to the destination root. - repo_root: The 'src' path that will be used for packaging. - dest_root: The directory where the src files will be stored. - additional_glob_patterns: Some platforms may need to include certain - dependencies beyond the default include file patterns. The results here will - be merged in with _INCLUDE_FILE_PATTERNS. - include_black_box_tests: If True then the resources for the black box tests - are included.""" - _CopyAppLauncherTools(repo_root, dest_root, - additional_glob_patterns, - include_black_box_tests=include_black_box_tests) - - -def MakeZipArchive(src, output_zip): - """Convenience function to zip up all files in the src directory (produced - as dest_root argument in CopyAppLauncherTools()) which will create a zip - file with the relative root being the src directory.""" - _MakeZipArchive(src, output_zip) - - -################################################################################ -# IMPL # -################################################################################ - - import argparse import fnmatch import logging import os import shutil import sys +import tempfile import _env # pylint: disable=unused-import from paths import REPOSITORY_ROOT from paths import THIRD_PARTY_ROOT sys.path.append(THIRD_PARTY_ROOT) -from cobalt.build import cobalt_archive_extract -import starboard.build.port_symlink as port_symlink -import starboard.tools.platform +# pylint: disable=g-import-not-at-top,g-bad-import-order import jinja2 - +from starboard.tools import port_symlink +import starboard.tools.platform # Default python directories to app launcher resources. _INCLUDE_FILE_PATTERNS = [ @@ -81,11 +45,10 @@ ('lbshell', '*.py'), ('starboard', '*.py'), # jinja2 required by this app_launcher_packager.py script. - ('third_party/jinja2', '*.py'), - ('third_party/markupsafe', '*.py'), # Required by third_party/jinja2 + ('third_party/jinja2', '*.py'), + ('third_party/markupsafe', '*.py'), # Required by third_party/jinja2 ] - _INCLUDE_BLACK_BOX_TESTS_PATTERNS = [ # Black box and web platform tests have non-py assets, so everything # is picked up. @@ -116,18 +79,24 @@ Args: source_root: Absolute path to the root of the files to be copied. d: Directory to be checked. + + Returns: + true if d in in source_root/out. """ out_dir = os.path.join(source_root, 'out') return out_dir in d -def _FindFilesRecursive(src_root, glob_pattern): +def _FindFilesRecursive( # pylint: disable=missing-docstring + src_root, glob_pattern): src_root = os.path.normpath(src_root) logging.info('Searching in %s for %s type files.', src_root, glob_pattern) file_list = [] for root, dirs, files in os.walk(src_root, topdown=True): # Prunes when using os.walk with topdown=True - [dirs.remove(d) for d in list(dirs) if d in _EXCLUDE_DIRECTORY_PATTERNS] + for d in list(dirs): + if d in _EXCLUDE_DIRECTORY_PATTERNS: + dirs.remove(d) # Eliminate any locally built files under the out directory. if _IsOutDir(src_root, root): continue @@ -160,7 +129,9 @@ for p in starboard.tools.platform.GetAll(): platform_path = os.path.relpath( starboard.tools.platform.Get(p).path, repo_root) - platforms_map[p] = platform_path + # Store posix paths even on Windows so MH Linux hosts can use them. + # The template has code to re-normalize them when used on Windows hosts. + platforms_map[p] = platform_path.replace('\\', '/') template = jinja2.Template( open(os.path.join(current_dir, 'platform.py.template')).read()) with open(os.path.join(dest_dir, 'platform.py'), 'w+') as f: @@ -168,20 +139,46 @@ logging.info('Finished baking in platform info files.') -def _CopyAppLauncherTools(repo_root, dest_root, additional_glob_patterns, - include_black_box_tests): - # Step 1: Make sure dest_root is an absolute path. +def CopyAppLauncherTools(repo_root, + dest_root, + additional_glob_patterns=None, + include_black_box_tests=True): + """Copies app launcher related files to the destination root. + + Args: + repo_root: The 'src' path that will be used for packaging. + dest_root: The directory where the src files will be stored. + additional_glob_patterns: Some platforms may need to include certain + dependencies beyond the default include file patterns. The results here + will be merged in with _INCLUDE_FILE_PATTERNS. + include_black_box_tests: If True then the resources for the black box tests + are included. + """ + dest_root = _PrepareDestination(dest_root) + copy_list = _GetSourceFilesList(repo_root, additional_glob_patterns, + include_black_box_tests) + _CopyFiles(repo_root, dest_root, copy_list) + + +def _PrepareDestination(dest_root): # pylint: disable=missing-docstring + # Make sure dest_root is an absolute path. logging.info('Copying App Launcher tools to = %s', dest_root) dest_root = os.path.normpath(dest_root) if not os.path.isabs(dest_root): dest_root = os.path.join(os.getcwd(), dest_root) - if port_symlink.IsWindows(): - dest_root = cobalt_archive_extract.ToWinUncPath(dest_root) + dest_root = port_symlink.ToLongPath(dest_root) logging.info('Absolute destination path = %s', dest_root) - # Step 2: Remove previous output directory if it exists + # Remove previous output directory if it exists if os.path.isdir(dest_root): shutil.rmtree(dest_root) - # Step 3: Find all glob files from specified search directories. + return dest_root + + +def _GetSourceFilesList( # pylint: disable=missing-docstring + repo_root, + additional_glob_patterns=None, + include_black_box_tests=True): + # Find all glob files from specified search directories. include_glob_patterns = _INCLUDE_FILE_PATTERNS if additional_glob_patterns: include_glob_patterns += additional_glob_patterns @@ -199,8 +196,13 @@ # Order by file path string and remove any duplicate paths. copy_list = list(set(copy_list)) copy_list.sort() + return copy_list + + +def _CopyFiles( # pylint: disable=missing-docstring + repo_root, dest_root, copy_list): + # Copy the src files to the destination directory. folders_logged = set() - # Step 4: Copy the src files to the destination directory. for src in copy_list: tail_path = os.path.relpath(src, repo_root) dst = os.path.join(dest_root, tail_path) @@ -208,15 +210,24 @@ if not os.path.isdir(d): os.makedirs(d) src_folder = os.path.dirname(src) - if not src_folder in folders_logged: + if src_folder not in folders_logged: folders_logged.add(src_folder) logging.info(src_folder + ' -> ' + os.path.dirname(dst)) shutil.copy2(src, dst) - # Step 5: Re-write the platform infos file in the new repo copy. + # Re-write the platform infos file in the new repo copy. _WritePlatformsInfo(repo_root, dest_root) -def _MakeZipArchive(src, output_zip): +def MakeZipArchive(src, output_zip): + """Convenience function to zip up all files in the src directory. + + Intended for use with the dest_root output from CopyAppLauncherTools() to + create a zip file with the relative root being the src directory. + + Args: + src: Path to the directory of files to zip up. + output_zip: Path to the zip file to create. + """ if os.path.isfile(output_zip): os.unlink(output_zip) logging.info('Creating a zip file of the app launcher package') @@ -228,14 +239,49 @@ def main(command_args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser() - parser.add_argument( + dest_group = parser.add_mutually_exclusive_group(required=True) + dest_group.add_argument( '-d', '--destination_root', - required=True, help='The path to the root of the destination folder into which the ' - 'application resources are packaged.') + 'application resources are packaged.') + dest_group.add_argument( + '-z', + '--zip_file', + help='The path to a zip file into which the application resources are ' + 'packaged.') + dest_group.add_argument( + '-l', + '--list', + action='store_true', + help='List to stdout the application resources relative to the current ' + 'directory.') + parser.add_argument( + '-v', '--verbose', action='store_true', help='Verbose logging output.') args = parser.parse_args(command_args) - CopyAppLauncherTools(REPOSITORY_ROOT, args.destination_root) + + if not args.verbose: + logging.disable(logging.INFO) + + if args.destination_root: + CopyAppLauncherTools(REPOSITORY_ROOT, args.destination_root) + elif args.zip_file: + try: + temp_dir = tempfile.mkdtemp(prefix='cobalt_app_launcher_') + CopyAppLauncherTools(REPOSITORY_ROOT, temp_dir) + MakeZipArchive(temp_dir, args.zip_file) + finally: + shutil.rmtree(temp_dir) + elif args.list: + for src_file in _GetSourceFilesList(REPOSITORY_ROOT): + # Skip paths with '$' since they won't get through the Ninja generator. + if '$' in src_file: + continue + # Relative to CWD where gyp ran this; same as '<(DEPTH)' in gyp file. + src_file = os.path.relpath(src_file) + # Forward slashes for gyp, even on Windows. + src_file = src_file.replace('\\', '/') + print src_file return 0
diff --git a/src/starboard/tools/build.py b/src/starboard/tools/build.py index 5c83b79..d28d8d4 100644 --- a/src/starboard/tools/build.py +++ b/src/starboard/tools/build.py
@@ -21,12 +21,12 @@ import os import subprocess import sys -import starboard.tools.goma import _env # pylint: disable=unused-import from starboard.tools import config from starboard.tools import paths from starboard.tools import platform +import starboard.tools.goma _STARBOARD_TOOLCHAINS_DIR_KEY = 'STARBOARD_TOOLCHAINS_DIR' _STARBOARD_TOOLCHAINS_DIR_NAME = 'starboard-toolchains' @@ -97,9 +97,10 @@ raw_configuration = os.environ[_BUILD_CONFIGURATION_KEY] build_configuration = raw_configuration.lower() if '_' not in build_configuration: - logging.warning("Expected a '_' in '%s' and did not find one. " - "'%s' must be of the form <platform>_<config>.", - _BUILD_CONFIGURATION_KEY, _BUILD_CONFIGURATION_KEY) + logging.warning( + "Expected a '_' in '%s' and did not find one. " + "'%s' must be of the form <platform>_<config>.", + _BUILD_CONFIGURATION_KEY, _BUILD_CONFIGURATION_KEY) return default_config_name, default_platform_name platform_name, config_name = build_configuration.split('_', 1) @@ -118,9 +119,8 @@ def GetGyp(): """Gets the GYP module, loading it, if necessary.""" if 'gyp' not in sys.modules: - sys.path.insert(0, - os.path.join(paths.REPOSITORY_ROOT, 'tools', 'gyp', - 'pylib')) + sys.path.insert( + 0, os.path.join(paths.REPOSITORY_ROOT, 'tools', 'gyp', 'pylib')) importlib.import_module('gyp') return sys.modules['gyp'] @@ -161,13 +161,8 @@ 'x86_64-linux-gnu-clang-chromium-' + clang_spec.revision) -def _GetClangInstallPath(clang_spec): - return os.path.join( - _GetClangBasePath(clang_spec), 'llvm-build', 'Release+Asserts') - - def _GetClangBinPath(clang_spec): - return os.path.join(_GetClangInstallPath(clang_spec), 'bin') + return os.path.join(_GetClangBasePath(clang_spec), 'bin') def EnsureClangAvailable(clang_spec): @@ -180,7 +175,7 @@ base_dir = _GetClangBasePath(clang_spec) update_proc = subprocess.Popen([ update_script, '--force-clang-revision', clang_spec.revision, - '--clang-version', clang_spec.version, '--force-base-dir', base_dir + '--verify-version', clang_spec.version, '--clang-dir', base_dir ]) rc = update_proc.wait() if rc != 0: @@ -192,7 +187,7 @@ if not os.path.exists(clang_bin): raise RuntimeError('Clang not found.') - return _GetClangInstallPath(clang_spec) + return _GetClangBasePath(clang_spec) def GetHostCompilerEnvironment(clang_spec, goma_supports_compiler):
diff --git a/src/starboard/tools/command_line.py b/src/starboard/tools/command_line.py index c7d2f2e..bf4db77 100644 --- a/src/starboard/tools/command_line.py +++ b/src/starboard/tools/command_line.py
@@ -32,20 +32,18 @@ arg_parser = CreatePlatformConfigParser( description='Runs application/tool executables.') arg_parser.add_argument( - '-d', - '--device_id', - help='Devkit or IP address for the target device.') + '-d', '--device_id', help='Devkit or IP address for the target device.') arg_parser.add_argument( '--target_params', help='Command line arguments to pass to the executable.' - ' Because different executables could have differing command' - ' line syntax, list all arguments exactly as you would to the' - ' executable between a set of double quotation marks.') + ' Because different executables could have differing command' + ' line syntax, list all arguments exactly as you would to the' + ' executable between a set of double quotation marks.') arg_parser.add_argument( '-o', '--out_directory', help='Directory containing tool binaries or their components.' - ' Automatically derived if absent.') + ' Automatically derived if absent.') return arg_parser @@ -53,8 +51,8 @@ """An arg parser suitable for building. Args: - description: Description passed onto argument parser, if none then a - default is assigned. + description: Description passed onto argument parser, if none then a default + is assigned. **kwargs: are constructor arguments for the argparser. Returns: @@ -70,7 +68,8 @@ choices=starboard.tools.platform.GetAll(), default=default_platform, required=not default_platform, - help="Device platform, eg 'linux-x64x11'.") + help="Device platform, eg 'linux-x64x11'. Requires that you have " + 'already run gyp_cobalt for the desired platform.') arg_parser.add_argument( '-c', '--config', @@ -78,4 +77,18 @@ default=default_config, required=not default_config, help="Build config (eg, 'qa' or 'devel')") + arg_parser.add_argument( + '-P', + '--loader_platform', + help='Specifies the platform to build the loader with. This flag is only ' + 'relevant for Evergreen builds, and should be the platform you intend to ' + "run your tests on (eg 'linux-x64x11', or 'raspi-2'). Requires that " + '--loader_config be given, and that you have already run gyp_cobalt for ' + 'the desired loader platform.') + arg_parser.add_argument( + '-C', + '--loader_config', + help="Specifies the config to build the loader with (eg 'qa' or 'devel'). This flag is only " + 'relevant for Evergreen builds, and requires that --loader_platform be ' + 'given.') return arg_parser
diff --git a/src/starboard/tools/platform.py.template b/src/starboard/tools/platform.py.template index 7a211bc..17d55b5 100644 --- a/src/starboard/tools/platform.py.template +++ b/src/starboard/tools/platform.py.template
@@ -21,6 +21,7 @@ # The name->platform path mapping. _PATH_MAP = {{platforms_map}} +_PATH_MAP = {k:os.path.normpath(v) for k,v in _PATH_MAP.iteritems()} # Cache of the name->PlatformInfo mapping.
diff --git a/src/starboard/tools/port_symlink.py b/src/starboard/tools/port_symlink.py new file mode 100644 index 0000000..afd1202 --- /dev/null +++ b/src/starboard/tools/port_symlink.py
@@ -0,0 +1,170 @@ +#!/usr/bin/env python +# +# Copyright 2019 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. + + +"""A portable interface for symlinking.""" + + +import argparse +import logging +import os +import shutil +import sys + +import _env # pylint: disable=relative-import,unused-import + +from starboard.tools import util + + +def IsWindows(): + return sys.platform in ['win32', 'cygwin'] + + +def ToLongPath(path): + """Converts to a path that supports long filenames.""" + if IsWindows(): + # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink + return win_symlink.ToDevicePath(path) + else: + return path + +def IsSymLink(path): + """Platform neutral version os os.path.islink()""" + if IsWindows(): + # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink + return win_symlink.IsReparsePoint(path) + else: + return os.path.islink(path) + + +def MakeSymLink(from_folder, link_folder): + """Makes a symlink. + + Args: + from_folder: Path to the actual folder + link_folder: Path to the link + + Returns: + None + """ + if IsWindows(): + # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink + win_symlink.CreateReparsePoint(from_folder, link_folder) + else: + util.MakeDirs(os.path.dirname(link_folder)) + os.symlink(from_folder, link_folder) + + +def ReadSymLink(link_path): + """Returns the path (abs. or rel.) to the folder referred to by link_path.""" + if IsWindows(): + # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink + path = win_symlink.ReadReparsePoint(link_path) + else: + try: + path = os.readlink(link_path) + except OSError: + path = None + return path + + +def DelSymLink(link_path): + if IsWindows(): + # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink + win_symlink.UnlinkReparsePoint(link_path) + else: + os.unlink(link_path) + + +def Rmtree(path): + """See Rmtree() for documentation of this function.""" + if not os.path.exists(path): + return + if IsWindows(): + # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink + win_symlink.RmtreeShallow(path) + else: + if os.path.islink(path): + os.unlink(path) + else: + shutil.rmtree(path) + + +def OsWalk(root_dir, topdown=True, onerror=None, followlinks=False): + if IsWindows(): + # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink + return win_symlink.OsWalk(root_dir, topdown, onerror, followlinks) + else: + return os.walk(root_dir, topdown, onerror, followlinks) + + +def _CreateArgumentParser(): + """Creates an argument parser for port_symlink.""" + + class MyParser(argparse.ArgumentParser): + + def error(self, message): + sys.stderr.write('error: %s\n' % message) + self.print_help() + sys.exit(2) + help_msg = ( + 'Example 1:\n' + ' python port_link.py --link "actual_folder_path" "link_path"\n\n' + 'Example 2:\n' + ' python port_link.py --link "../actual_folder_path" "link_path"\n\n') + # Enables new lines in the description and epilog. + formatter_class = argparse.RawDescriptionHelpFormatter + parser = MyParser(epilog=help_msg, formatter_class=formatter_class) + parser.add_argument( + '-f', + '--force', + action='store_true', + help='Force the symbolic link to be created, removing existing files and ' + 'directories if needed.') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('--link', + help='Issues an scp command to upload src to remote_dst', + metavar='"path"', + nargs=2) + return parser + + +def main(): + util.SetupDefaultLoggingConfig() + parser = _CreateArgumentParser() + args = parser.parse_args() + + folder_path, link_path = args.link + if '.' in folder_path: + d1 = os.path.abspath(folder_path) + else: + d1 = os.path.abspath(os.path.join(link_path, folder_path)) + if not os.path.isdir(d1): + logging.warning('%s is not a directory.', d1) + if args.force: + Rmtree(link_path) + MakeSymLink(from_folder=folder_path, link_folder=link_path) + + +if __name__ == '__main__': + main()
diff --git a/src/starboard/tools/port_symlink_test.py b/src/starboard/tools/port_symlink_test.py new file mode 100644 index 0000000..9985bb6 --- /dev/null +++ b/src/starboard/tools/port_symlink_test.py
@@ -0,0 +1,189 @@ +#!/usr/bin/env python +# +# Copyright 2019 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 os +import shutil +import tempfile +import unittest + +import _env # pylint: disable=relative-import,unused-import + +from starboard.tools import port_symlink +from starboard.tools import util + + +# Replace this function signature for other implementations of symlink +# functions. +def MakeSymLink(*args, **kwargs): + return port_symlink.MakeSymLink(*args, **kwargs) + + +def IsSymLink(*args, **kwargs): + return port_symlink.IsSymLink(*args, **kwargs) + + +def ReadSymLink(*args, **kwargs): + return port_symlink.ReadSymLink(*args, **kwargs) + + +def Rmtree(*args, **kwargs): + return port_symlink.Rmtree(*args, **kwargs) + + +def OsWalk(*args, **kwargs): + return port_symlink.OsWalk(*args, **kwargs) + + +class PortSymlinkTest(unittest.TestCase): + + def setUp(self): + super(PortSymlinkTest, self).setUp() + self.tmp_dir = os.path.join(tempfile.gettempdir(), 'port_symlink') + if os.path.exists(self.tmp_dir): + Rmtree(self.tmp_dir) + self.from_dir = os.path.join(self.tmp_dir, 'from_dir') + self.test_txt = os.path.join(self.from_dir, 'test.txt') + self.inner_dir = os.path.join(self.from_dir, 'inner_dir') + self.link_dir = os.path.join(self.tmp_dir, 'link') + _MakeDirs(self.tmp_dir) + _MakeDirs(self.from_dir) + _MakeDirs(self.inner_dir) + MakeSymLink(self.from_dir, self.link_dir) + with open(self.test_txt, 'w') as fd: + fd.write('hello world') + + def tearDown(self): + Rmtree(self.tmp_dir) + super(PortSymlinkTest, self).tearDown() + + def testSanity(self): + self.assertTrue(os.path.isdir(self.tmp_dir)) + self.assertTrue(os.path.isdir(self.from_dir)) + self.assertTrue(os.path.isdir(self.inner_dir)) + + def testReadSymlinkNormalDirectory(self): + self.assertIsNone(ReadSymLink(self.from_dir)) + + def testReadSymlinkNormalFile(self): + self.assertIsNone(ReadSymLink(self.test_txt)) + + def testSymlinkDir(self): + self.assertTrue(os.path.exists(self.link_dir)) + self.assertTrue(IsSymLink(self.link_dir)) + from_dir_2 = ReadSymLink(self.link_dir) + self.assertTrue(_IsSamePath(from_dir_2, self.from_dir)) + + def testRelativeSymlinkDir(self): + rel_link_dir = os.path.join(self.tmp_dir, 'foo', 'rel_link') + rel_dir_path = os.path.relpath(self.from_dir, rel_link_dir) + MakeSymLink(rel_dir_path, rel_link_dir) + self.assertTrue(IsSymLink(rel_link_dir)) + link_value = ReadSymLink(rel_link_dir) + self.assertIn('..', link_value, + msg='Expected ".." in relative path %s' % link_value) + + def testDelSymlink(self): + link_dir2 = os.path.join(self.tmp_dir, 'link2') + MakeSymLink(self.from_dir, link_dir2) + self.assertTrue(IsSymLink(link_dir2)) + port_symlink.DelSymLink(link_dir2) + self.assertFalse(os.path.exists(link_dir2)) + + def testRmtreeRemovesLink(self): + Rmtree(self.link_dir) + self.assertFalse(os.path.exists(self.link_dir)) + self.assertTrue(os.path.exists(self.from_dir)) + + def testRmtreeDoesNotFollowSymlinks(self): + """Tests that Rmtree(...) will delete the symlink and not the target.""" + external_temp_dir = tempfile.mkdtemp() + try: + external_temp_file = os.path.join(external_temp_dir, 'test.txt') + with open(external_temp_file, 'w') as fd: + fd.write('HI') + link_dir = os.path.join(self.tmp_dir, 'foo', 'link_dir') + MakeSymLink(external_temp_file, link_dir) + Rmtree(self.tmp_dir) + # The target file should still exist + self.assertTrue(os.path.isfile(external_temp_file)) + finally: + shutil.rmtree(external_temp_file, ignore_errors=True) + + def testOsWalk(self): + paths_nofollow_links = _GetAllPaths(self.tmp_dir, followlinks=False) + paths_follow_links = _GetAllPaths(self.tmp_dir, followlinks=True) + print '\nOsWalk Follow links:' + for path in paths_follow_links: + print ' ' + path + ' (' + _PathTypeToString(path) + ')' + print '\nOsWalk No-Follow links:' + for path in paths_nofollow_links: + print ' ' + path + ' (' + _PathTypeToString(path) + ')' + print '' + self.assertIn(self.link_dir, paths_nofollow_links) + self.assertIn(self.link_dir, paths_follow_links) + self.assertIn(os.path.join(self.link_dir, 'test.txt'), + paths_follow_links) + self.assertNotIn(os.path.join(self.link_dir, 'test.txt'), + paths_nofollow_links) + + +def _MakeDirs(path): + if not os.path.isdir(path): + os.makedirs(path) + + +def _PathTypeToString(path): + if IsSymLink(path): + return 'link' + if os.path.isdir(path): + return 'dir' + return 'file' + + +def _GetAllPaths(start_dir, followlinks): + paths = [] + for root, dirs, files in OsWalk(start_dir, followlinks=followlinks): + for name in files: + path = os.path.join(root, name) + paths.append(path) + for name in dirs: + path = os.path.join(root, name) + paths.append(path) + return paths + + +def _IsSamePath(p1, p2): + if not p1: + p1 = None + if not p2: + p2 = None + if p1 == p2: + return True + if (not p1) or (not p2): + return False + p1 = os.path.abspath(os.path.normpath(p1)) + p2 = os.path.abspath(os.path.normpath(p2)) + if p1 == p2: + return True + try: + return os.stat(p1) == os.stat(p2) + except Exception: # pylint: disable=broad-except + return False + + +if __name__ == '__main__': + util.SetupDefaultLoggingConfig() + unittest.main(verbosity=2)
diff --git a/src/starboard/tools/testing/build_tests.py b/src/starboard/tools/testing/build_tests.py index b02470e..c9f7082 100644 --- a/src/starboard/tools/testing/build_tests.py +++ b/src/starboard/tools/testing/build_tests.py
@@ -1,7 +1,25 @@ +# Copyright 2018 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. +"""Common code for building various types of targets, typically tests.""" + import logging import os import subprocess +APP_LAUNCHER_TARGET = 'app_launcher_zip' + + def BuildTargets(targets, out_directory, dry_run=False, extra_build_flags=[]): """Builds all specified targets. @@ -16,6 +34,7 @@ if dry_run: args_list.append("-n") + args_list.append(APP_LAUNCHER_TARGET) args_list.extend(["{}_deploy".format(test_name) for test_name in targets]) args_list.extend(extra_build_flags)
diff --git a/src/starboard/tools/testing/test_runner.py b/src/starboard/tools/testing/test_runner.py index 5896355..ba8f2b6 100755 --- a/src/starboard/tools/testing/test_runner.py +++ b/src/starboard/tools/testing/test_runner.py
@@ -42,6 +42,13 @@ _TESTS_FAILED_REGEX = re.compile(r"^\[ FAILED \] (.*) tests?, listed below:") _SINGLE_TEST_FAILED_REGEX = re.compile(r"^\[ FAILED \] (.*)") +_LOADER_TARGET = "elf_loader_sandbox" + + +def _EnsureBuildDirectoryExists(path): + if not os.path.exists(path): + raise ValueError("'{}' does not exist.".format(path)) + def _FilterTests(target_list, filters, config_name): """Returns a Mapping of test targets -> filtered tests.""" @@ -74,7 +81,9 @@ """Ensures a platform or app config is self-consistent.""" targets = config.GetTestTargets() filters = config.GetTestFilters() - filter_targets = [f.target_name for f in filters] + filter_targets = [ + f.target_name for f in filters if f != test_filter.DISABLE_TESTING + ] # Filters must be defined in the same config as the targets they're filtering, # platform filters in platform config, and app filters in app config. @@ -196,6 +205,8 @@ def __init__(self, platform, config, + loader_platform, + loader_config, device_id, specified_targets, target_params, @@ -207,10 +218,24 @@ log_xml_results=False): self.platform = platform self.config = config + self.loader_platform = loader_platform + self.loader_config = loader_config self.device_id = device_id self.target_params = target_params self.out_directory = out_directory + if not self.out_directory: + self.out_directory = paths.BuildOutputDirectory(self.platform, + self.config) + self.coverage_directory = os.path.join(self.out_directory, "coverage") + if self.loader_platform: + self.loader_out_directory = paths.BuildOutputDirectory( + self.loader_platform, self.loader_config) + else: + self.loader_out_directory = None + self._platform_config = build.GetPlatformConfig(platform) + if self.loader_platform: + self._loader_platform_config = build.GetPlatformConfig(loader_platform) self._app_config = self._platform_config.GetApplicationConfiguration( application_name) self.dry_run = dry_run @@ -218,7 +243,13 @@ self.log_xml_results = log_xml_results self.threads = [] + _EnsureBuildDirectoryExists(self.out_directory) _VerifyConfig(self._platform_config) + + if self.loader_platform: + _EnsureBuildDirectoryExists(self.loader_out_directory) + _VerifyConfig(self._loader_platform_config) + _VerifyConfig(self._app_config) # If a particular test binary has been provided, configure only that one. @@ -229,6 +260,30 @@ self.test_env_vars = self._GetAllTestEnvVariables() + def _Exec(self, cmd_list, output_file=None): + """Execute a command in a subprocess.""" + try: + msg = "Executing:\n " + " ".join(cmd_list) + logging.info(msg) + if output_file: + with open(output_file, "wb") as out: + p = subprocess.Popen( + cmd_list, + stdout=out, + universal_newlines=True, + cwd=self.out_directory) + else: + p = subprocess.Popen( + cmd_list, + stderr=subprocess.STDOUT, + universal_newlines=True, + cwd=self.out_directory) + p.wait() + return p.returncode + except KeyboardInterrupt: + p.kill() + return 1 + def _GetSpecifiedTestTargets(self, specified_targets): """Sets up specified test targets for a given platform and configuration. @@ -259,7 +314,7 @@ """Collects all test targets for a given platform and configuration. Args: - platform_only: If True then only the platform tests are fetched. + platform_tests_only: If True then only the platform tests are fetched. Returns: A mapping from names of test binaries to lists of filters for @@ -347,6 +402,8 @@ test_params.append("--gtest_output=xml:%s" % (xml_output_path)) test_params.extend(self.target_params) + if self.dry_run: + test_params.extend(["--gtest_list_tests"]) launcher = abstract_launcher.LauncherFactory( self.platform, @@ -356,7 +413,11 @@ target_params=test_params, output_file=write_pipe, out_directory=self.out_directory, - env_variables=env) + coverage_directory=self.coverage_directory, + env_variables=env, + loader_platform=self.loader_platform, + loader_config=self.loader_config, + loader_out_directory=self.loader_out_directory) test_reader = TestLineReader(read_pipe) test_launcher = TestLauncher(launcher) @@ -373,30 +434,22 @@ sys.stdout.write("Starting {}{}{}".format( test_name if test_name else target_name, dump_params, dump_env)) - if self.dry_run: - # Output a newline before running the test target / case. - sys.stdout.write("\n") + # Output a newline before running the test target / case. + sys.stdout.write("\n") - if test_params: - sys.stdout.write(" {}\n".format(test_params)) - write_pipe.close() - read_pipe.close() + if test_params: + sys.stdout.write(" {}\n".format(test_params)) + test_reader.Start() + test_launcher.Start() - else: - # Output a newline before running the test target / case. - sys.stdout.write("\n") + # Wait for the launcher to exit then close the write pipe, which will + # cause the reader to exit. + test_launcher.Join() + write_pipe.close() - test_reader.Start() - test_launcher.Start() - - # Wait for the launcher to exit then close the write pipe, which will - # cause the reader to exit. - test_launcher.Join() - write_pipe.close() - - # Only after closing the write pipe, wait for the reader to exit. - test_reader.Join() - read_pipe.close() + # Only after closing the write pipe, wait for the reader to exit. + test_reader.Join() + read_pipe.close() output = test_reader.GetLines() @@ -551,6 +604,12 @@ error = True test_status = "FAILED" failed_test_groups.append(target_name) + # Be specific about the cause of failure if it was caused due to crash + # upon exit. Normal Gtest failures have return_code = 1; test crashes + # yield different return codes (e.g. segfault has return_code = 11). + if (return_code != 1 and actual_failed_count == 0 and + flaky_failed_count == 0): + test_status = "FAILED (CRASHED)" logging.info("%s: %s.", target_name, test_status) if return_code != 0 and run_count == 0 and filtered_count == 0: @@ -614,7 +673,7 @@ return result - def BuildAllTests(self, ninja_flags): + def BuildAllTargets(self, ninja_flags): """Runs build step for all specified unit test binaries. Args: @@ -626,18 +685,18 @@ result = True try: - if self.out_directory: - out_directory = self.out_directory - else: - out_directory = paths.BuildOutputDirectory(self.platform, self.config) - if ninja_flags: extra_flags = [ninja_flags] else: extra_flags = [] - build_tests.BuildTargets(self.test_targets, out_directory, self.dry_run, - extra_flags) + # The loader is not built with the same platform configuration as our + # tests so we need to build it separately. + if self.loader_platform: + build_tests.BuildTargets([_LOADER_TARGET], self.loader_out_directory, + self.dry_run, extra_flags) + build_tests.BuildTargets(self.test_targets, self.out_directory, + self.dry_run, extra_flags) except subprocess.CalledProcessError as e: result = False @@ -659,6 +718,47 @@ return self._ProcessAllTestResults(results) + def GenerateCoverageReport(self): + """Generate the source code coverage report.""" + available_profraw_files = [] + available_targets = [] + for target in sorted(self.test_targets.keys()): + profraw_file = os.path.join(self.coverage_directory, target + ".profraw") + if os.path.isfile(profraw_file): + available_profraw_files.append(profraw_file) + available_targets.append(target) + + # If there are no profraw files, then there is no work to do. + if not available_profraw_files: + return + + report_name = "report" + profdata_name = os.path.join(self.coverage_directory, + report_name + ".profdata") + merge_cmd_list = [ + "llvm-profdata", "merge", "-sparse=true", "-o", profdata_name + ] + merge_cmd_list += available_profraw_files + + self._Exec(merge_cmd_list) + show_cmd_list = [ + "llvm-cov", "show", "-instr-profile=" + profdata_name, "-format=html", + "-output-dir=" + os.path.join(self.coverage_directory, "html"), + available_targets[0] + ] + show_cmd_list += ["-object=" + target for target in available_targets[1:]] + self._Exec(show_cmd_list) + + report_cmd_list = [ + "llvm-cov", "report", "-instr-profile=" + profdata_name, + available_targets[0] + ] + report_cmd_list += ["-object=" + target for target in available_targets[1:]] + self._Exec( + report_cmd_list, + output_file=os.path.join(self.coverage_directory, report_name + ".txt")) + return + def main(): SetupDefaultLoggingConfig() @@ -713,13 +813,20 @@ " complete. --xml_output_dir will be ignored.") args = arg_parser.parse_args() + if (args.loader_platform and not args.loader_config or + args.loader_config and not args.loader_platform): + arg_parser.error( + "You must specify both --loader_platform and --loader_config.") + return 1 + # Extra arguments for the test target target_params = [] if args.target_params: target_params = args.target_params.split(" ") - runner = TestRunner(args.platform, args.config, args.device_id, - args.target_name, target_params, args.out_directory, + runner = TestRunner(args.platform, args.config, args.loader_platform, + args.loader_config, args.device_id, args.target_name, + target_params, args.out_directory, args.platform_tests_only, args.application_name, args.dry_run, args.xml_output_dir, args.log_xml_results) @@ -743,7 +850,7 @@ sys.stderr.write("=== Dry run ===\n") if args.build: - build_success = runner.BuildAllTests(args.ninja_flags) + build_success = runner.BuildAllTargets(args.ninja_flags) # If the build fails, don't try to run the tests. if not build_success: return 1 @@ -751,6 +858,8 @@ if args.run: run_success = runner.RunAllTests() + runner.GenerateCoverageReport() + # If either step has failed, count the whole test run as failed. if not build_success or not run_success: return 1
diff --git a/src/starboard/tools/tools.gyp b/src/starboard/tools/tools.gyp new file mode 100644 index 0000000..a80103f --- /dev/null +++ b/src/starboard/tools/tools.gyp
@@ -0,0 +1,47 @@ +# Copyright 2019 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. + +# The Starboard "all" target, which includes all interesting targets for the +# Starboard project. + +{ + 'targets': [ + { + 'target_name': 'app_launcher_zip', + 'type': 'none', + 'variables': { + 'app_launcher_packager_path': 'app_launcher_packager.py', + 'app_launcher_zip_file': '<(PRODUCT_DIR)/app_launcher.zip', + }, + 'actions': [ + { + 'action_name': 'package_app_launcher', + 'message': 'Zipping <(app_launcher_zip_file)', + 'inputs': [ + '<!@(["python", "<(app_launcher_packager_path)", "-l"])', + ], + 'outputs': [ + '<(app_launcher_zip_file)', + ], + 'action': [ + 'python', + '<(app_launcher_packager_path)', + '-z', + '<(app_launcher_zip_file)', + ], + }, + ], + }, + ] +}
diff --git a/src/starboard/tools/win_symlink.py b/src/starboard/tools/win_symlink.py new file mode 100644 index 0000000..8426b21 --- /dev/null +++ b/src/starboard/tools/win_symlink.py
@@ -0,0 +1,288 @@ +#!/usr/bin/python +# Copyright 2018 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. + +"""Provides functions for symlinking on Windows. + +Reparse points: Are os-level symlinks for folders which can be created without +admin access. Symlinks for folders are supported using this mechanism. Note +that reparse points require special care for traversal, because reparse points +are often skipped or treated as files by the various python path manipulation +functions in os and shutil modules. rmtree() as a replacement for +shutil.rmtree() is provided. + +""" + +import logging +import os +import re +import shutil +import stat +import subprocess +import time + + +_RETRY_TIMES = 10 + + +def ToDevicePath(dos_path, encoding=None): + r"""Convert to a device path to avoid MAX_PATH limits on Windows. + + https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation + + Args: + dos_path: Path to a file that's not already a device path. + encoding: Optional character encoding of dos_path, if it's not unicode. + + Returns: + Absolute device path starting with "\\?\". + """ + if not isinstance(dos_path, unicode) and encoding is not None: + dos_path = dos_path.decode(encoding) + path = os.path.abspath(dos_path) + if path.startswith(u'\\\\'): + return u'\\\\?\\UNC\\' + path[2:] + return u'\\\\?\\' + path + + +def _RemoveEmptyDirectory(path): + """Removes a directory with retry amounts.""" + for i in range(0, _RETRY_TIMES): + try: + os.chmod(path, stat.S_IWRITE) + os.rmdir(path) + return + except Exception: # pylint: disable=broad-except + if i == _RETRY_TIMES-1: + raise + else: + time.sleep(.1) + + +def _RmtreeOsWalk(root_dir): + """Walks the directory structure to delete directories and files.""" + del_dirs = [] # Defer deletion of directories. + if IsReparsePoint(root_dir): + UnlinkReparsePoint(root_dir) + return + for root, dirs, files in OsWalk(root_dir, followlinks=False): + for name in files: + path = os.path.join(root, name) + os.remove(path) + for name in dirs: + path = os.path.join(root, name) + if IsReparsePoint(path): + UnlinkReparsePoint(path) + else: + del_dirs.append(path) + # At this point, all files should be deleted and all symlinks should be + # unlinked. + for d in del_dirs + [root_dir]: + try: + if os.path.isdir(d): + shutil.rmtree(d) + except Exception as err: # pylint: disable=broad-except + logging.exception('Error while deleting: %s', err) + + +def _RmtreeShellCmd(root_dir): + subprocess.call(['cmd', '/c', 'rmdir', '/S', '/Q', root_dir]) + + +def RmtreeShallow(root_dir): + """Emulates shutil.rmtree on linux. + + Will delete symlinks but doesn't follow them. Note that shutil.rmtree on + windows will follow the symlink and delete the files in the original + directory! + + Args: + root_dir: The start path to delete files. + """ + try: + # This can fail if there are very long file names. + _RmtreeOsWalk(root_dir) + except OSError: + # This fallback will handle very long file. Note that it is VERY slow + # in comparison to the _RmtreeOsWalk() version. + _RmtreeShellCmd(root_dir) + if os.path.isdir(root_dir): + logging.error('Directory %s still exists.', root_dir) + + +def ReadReparsePointShell(path): + """Implements reading a reparse point via a shell command.""" + cmd_parts = ['cmd', '/C', 'dir', os.path.dirname(path)] + try: + out = subprocess.check_output(cmd_parts) + except subprocess.CalledProcessError: + # Expected if the link doesn't exist. + return None + try: + pattern = re.compile('.*<SYMLINKD>[ ]+%s \\[(.*)]' % os.path.basename(path)) + for l in out.splitlines(): + m = pattern.match(l) + if m: + return m.group(1) + except Exception as err: # pylint: disable=broad-except + logging.exception(err) + return None + + +def ReadReparsePoint(path): + """Mimics os.readlink for usage.""" + try: + # pylint: disable=g-import-not-at-top + import win_symlink_fast + return win_symlink_fast.FastReadReparseLink(path) + except Exception as err: # pylint: disable=broad-except + logging.exception(' error: %s, falling back to command line version.', err) + return ReadReparsePointShell(path) + + +def IsReparsePoint(path): + """Mimics os.islink for usage.""" + try: + # pylint: disable=g-import-not-at-top + import win_symlink_fast + return win_symlink_fast.FastIsReparseLink(path) + except Exception as err: # pylint: disable=broad-except + logging.exception(' error: %s, falling back to command line version.', err) + return None is not ReadReparsePointShell(path) + + +def CreateReparsePoint(from_folder, link_folder): + """Mimics os.symlink for usage. + + Args: + from_folder: Path of target directory. + link_folder: Path to create link. + + Returns: + None. + + Raises: + OSError: if link cannot be created + """ + if os.path.isdir(link_folder): + _RemoveEmptyDirectory(link_folder) + else: + UnlinkReparsePoint(link_folder) # Deletes if it exists. + try: + # pylint: disable=g-import-not-at-top + import win_symlink_fast + win_symlink_fast.FastCreateReparseLink(from_folder, link_folder) + return + except OSError: + pass + except Exception as err: # pylint: disable=broad-except + logging.exception('unexpected error: %s, from=%s, link=%s, falling back to ' + 'command line version.', err, from_folder, link_folder) + par_dir = os.path.dirname(link_folder) + if not os.path.isdir(par_dir): + os.makedirs(par_dir) + try: + subprocess.check_output( + ['cmd', '/c', 'mklink', '/d', link_folder, from_folder], + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + # Fallback to junction points, which require less privileges to create. + subprocess.check_output( + ['cmd', '/c', 'mklink', '/j', link_folder, from_folder]) + if not IsReparsePoint(link_folder): + raise OSError('Could not create sym link %s to %s' % + (link_folder, from_folder)) + + +def UnlinkReparsePoint(link_dir): + """Mimics os.unlink for usage. The sym link_dir is removed.""" + if not IsReparsePoint(link_dir): + return + cmd_parts = ['fsutil', 'reparsepoint', 'delete', link_dir] + subprocess.check_output(cmd_parts) + # The folder will now be unlinked, but will still exist. + if os.path.isdir(link_dir): + try: + _RemoveEmptyDirectory(link_dir) + except Exception as err: # pylint: disable=broad-except + logging.exception('could not remove %s because of %s', link_dir, err) + if IsReparsePoint(link_dir): + raise IOError('Link still exists: %s' % ReadReparsePoint(link_dir)) + if os.path.isdir(link_dir): + logging.info('WARNING - Link as folder still exists: %s', link_dir) + + +def _IsSamePath(p1, p2): + """Returns true if p1 and p2 represent the same path.""" + if not p1: + p1 = None + if not p2: + p2 = None + if p1 == p2: + return True + if (not p1) or (not p2): + return False + p1 = os.path.abspath(os.path.normpath(p1)) + p2 = os.path.abspath(os.path.normpath(p2)) + if p1 == p2: + return True + try: + return os.stat(p1) == os.stat(p2) + except Exception: # pylint: disable=broad-except + return False + + +def OsWalk(top, topdown=True, onerror=None, followlinks=False): + """Emulates os.walk() on linux. + + Args: + top: see os.walk(...) + topdown: see os.walk(...) + onerror: see os.walk(...) + followlinks: see os.walk(...) + + Yields: + see os.walk(...) + + Correctly handles windows reparse points as symlinks. + All symlink directories are returned in the directory list and the caller must + call IsReparsePoint() on the path to determine whether the directory is + real or a symlink. + """ + # Need an absolute path to use listdir and isdir with long paths. + top_abs_path = top + if not os.path.isabs(top_abs_path): + top_abs_path = os.path.join(os.getcwd(), top_abs_path) + top_abs_path = ToDevicePath(top) + try: + names = os.listdir(top_abs_path) + except OSError as err: + if onerror is not None: + onerror(err) + return + dirs, nondirs = [], [] + for name in names: + if os.path.isdir(os.path.join(top_abs_path, name)): + dirs.append(name) + else: + nondirs.append(name) + if topdown: + yield top, dirs, nondirs + for name in dirs: + new_path = os.path.join(top, name) + if followlinks or not IsReparsePoint(new_path): + for x in OsWalk(new_path, topdown, onerror, followlinks): + yield x + if not topdown: + yield top, dirs, nondirs
diff --git a/src/starboard/tools/win_symlink_fast.py b/src/starboard/tools/win_symlink_fast.py new file mode 100644 index 0000000..987a69b --- /dev/null +++ b/src/starboard/tools/win_symlink_fast.py
@@ -0,0 +1,243 @@ +#!/usr/bin/python +# Copyright 2019 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. + + +"""Provides functions for symlinking on Windows.""" + + +import ctypes +from ctypes import wintypes +import os + + +DWORD = wintypes.DWORD +LPCWSTR = wintypes.LPCWSTR +HANDLE = wintypes.HANDLE +LPVOID = wintypes.LPVOID +BOOL = wintypes.BOOL +USHORT = wintypes.USHORT +ULONG = wintypes.ULONG +WCHAR = wintypes.WCHAR + + +kernel32 = wintypes.WinDLL('kernel32') +LPDWORD = ctypes.POINTER(DWORD) +UCHAR = ctypes.c_ubyte + + +GetFileAttributesW = kernel32.GetFileAttributesW +GetFileAttributesW.restype = DWORD +GetFileAttributesW.argtypes = (LPCWSTR,) # lpFileName In + + +INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF +FILE_ATTRIBUTE_REPARSE_POINT = 0x00400 + + +CreateFileW = kernel32.CreateFileW +CreateFileW.restype = HANDLE +CreateFileW.argtypes = (LPCWSTR, # lpFileName In + DWORD, # dwDesiredAccess In + DWORD, # dwShareMode In + LPVOID, # lpSecurityAttributes In_opt + DWORD, # dwCreationDisposition In + DWORD, # dwFlagsAndAttributes In + HANDLE) # hTemplateFile In_opt + + +CloseHandle = kernel32.CloseHandle +CloseHandle.restype = BOOL +CloseHandle.argtypes = (HANDLE,) # hObject In + + +INVALID_HANDLE_VALUE = HANDLE(-1).value +OPEN_EXISTING = 3 +FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 +FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 + + +DeviceIoControl = kernel32.DeviceIoControl +DeviceIoControl.restype = BOOL +DeviceIoControl.argtypes = (HANDLE, # hDevice In + DWORD, # dwIoControlCode In + LPVOID, # lpInBuffer In_opt + DWORD, # nInBufferSize In + LPVOID, # lpOutBuffer Out_opt + DWORD, # nOutBufferSize In + LPDWORD, # lpBytesReturned Out_opt + LPVOID) # lpOverlapped Inout_opt + + +FSCTL_GET_REPARSE_POINT = 0x000900A8 +IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 +IO_REPARSE_TAG_SYMLINK = 0xA000000C +MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 0x4000 +SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1 +# Developer Mode must be enabled in order to use the following flag. +SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2 +SYMLINK_FLAG_RELATIVE = 0x1 + + +class GenericReparseBuffer(ctypes.Structure): + """Win32 api data structure.""" + _fields_ = (('DataBuffer', UCHAR * 1),) + + +class SymbolicLinkReparseBuffer(ctypes.Structure): + """Win32 api data structure.""" + + _fields_ = (('SubstituteNameOffset', USHORT), + ('SubstituteNameLength', USHORT), + ('PrintNameOffset', USHORT), + ('PrintNameLength', USHORT), + ('Flags', ULONG), + ('PathBuffer', WCHAR * 1)) + + @property + def print_name(self): + arrayt = WCHAR * (self.PrintNameLength // 2) + offset = type(self).PathBuffer.offset + self.PrintNameOffset + return arrayt.from_address(ctypes.addressof(self) + offset).value + + @property + def substitute_name(self): + arrayt = WCHAR * (self.SubstituteNameLength // 2) + offset = type(self).PathBuffer.offset + self.SubstituteNameOffset + return arrayt.from_address(ctypes.addressof(self) + offset).value + + @property + def is_relative_path(self): + return bool(self.Flags & SYMLINK_FLAG_RELATIVE) + + +class MountPointReparseBuffer(ctypes.Structure): + """Win32 api data structure.""" + _fields_ = (('SubstituteNameOffset', USHORT), + ('SubstituteNameLength', USHORT), + ('PrintNameOffset', USHORT), + ('PrintNameLength', USHORT), + ('PathBuffer', WCHAR * 1)) + + @property + def print_name(self): + arrayt = WCHAR * (self.PrintNameLength // 2) + offset = type(self).PathBuffer.offset + self.PrintNameOffset + return arrayt.from_address(ctypes.addressof(self) + offset).value + + @property + def substitute_name(self): + arrayt = WCHAR * (self.SubstituteNameLength // 2) + offset = type(self).PathBuffer.offset + self.SubstituteNameOffset + return arrayt.from_address(ctypes.addressof(self) + offset).value + + +class ReparseDataBuffer(ctypes.Structure): + """Win32 api data structure.""" + + class ReparseBuffer(ctypes.Union): + """Win32 api data structure.""" + _fields_ = (('SymbolicLinkReparseBuffer', SymbolicLinkReparseBuffer), + ('MountPointReparseBuffer', MountPointReparseBuffer), + ('GenericReparseBuffer', GenericReparseBuffer)) + _fields_ = (('ReparseTag', ULONG), + ('ReparseDataLength', USHORT), + ('Reserved', USHORT), + ('ReparseBuffer', ReparseBuffer)) + _anonymous_ = ('ReparseBuffer',) + + +def _ToUnicode(s): + return s.decode('utf-8') + + +_kdll = None + + +def _GetKernel32Dll(): + global _kdll + if _kdll: + return _kdll + _kdll = ctypes.windll.LoadLibrary('kernel32.dll') + return _kdll + + +def FastCreateReparseLink(from_folder, link_folder): + """Creates a reparse link. + + Args: + from_folder: The folder that the link will point to. + link_folder: The path of the link to be created. + + Returns: + None + + Raises: + OSError: if link cannot be created + """ + from_folder = _ToUnicode(from_folder) + link_folder = _ToUnicode(link_folder) + par_dir = os.path.dirname(link_folder) + if not os.path.isdir(par_dir): + os.makedirs(par_dir) + kdll = _GetKernel32Dll() + # Only supported from Windows 10 Insiders build 14972 + flags = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE | \ + SYMBOLIC_LINK_FLAG_DIRECTORY + ok = kdll.CreateSymbolicLinkW(link_folder, from_folder, flags) + if not ok or not FastIsReparseLink(link_folder): + raise OSError('Could not create sym link ' + link_folder + ' to ' + + from_folder) + + +def FastIsReparseLink(path): + path = _ToUnicode(path) + result = GetFileAttributesW(path) + if result == INVALID_FILE_ATTRIBUTES: + return False + return bool(result & FILE_ATTRIBUTE_REPARSE_POINT) + + +def FastReadReparseLink(path): + """See api docstring, above.""" + path = _ToUnicode(path) + reparse_point_handle = CreateFileW(path, + 0, + 0, + None, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | + FILE_FLAG_BACKUP_SEMANTICS, + None) + if reparse_point_handle == INVALID_HANDLE_VALUE: + return None + # Remove false positive below. + # pylint: disable=deprecated-method + target_buffer = ctypes.c_buffer(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) + n_bytes_returned = DWORD() + io_result = DeviceIoControl(reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + None, 0, + target_buffer, len(target_buffer), + ctypes.byref(n_bytes_returned), + None) + CloseHandle(reparse_point_handle) + if not io_result: + return None + rdb = ReparseDataBuffer.from_buffer(target_buffer) + if rdb.ReparseTag == IO_REPARSE_TAG_SYMLINK: + return rdb.SymbolicLinkReparseBuffer.print_name + elif rdb.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT: + return rdb.MountPointReparseBuffer.print_name + return None
diff --git a/src/starboard/tools/win_symlink_fast_test.py b/src/starboard/tools/win_symlink_fast_test.py new file mode 100644 index 0000000..473a2f8 --- /dev/null +++ b/src/starboard/tools/win_symlink_fast_test.py
@@ -0,0 +1,59 @@ +#!/usr/bin/python +# Copyright 2019 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 the win_symlink_fast functionality.""" + +import sys +import unittest + + +import _env # pylint: disable=relative-import,unused-import + + +if __name__ == '__main__' and sys.platform == 'win32': + from starboard.tools import port_symlink_test # pylint: disable=g-import-not-at-top + from starboard.tools import util # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink_fast # pylint: disable=g-import-not-at-top + + # Override the port_symlink_test symlink functions to point to our win_symlink + # and win_symlink_fast versions. + def MakeSymLink(*args, **kwargs): + return win_symlink_fast.FastCreateReparseLink(*args, **kwargs) + + def IsSymLink(*args, **kwargs): + return win_symlink_fast.FastIsReparseLink(*args, **kwargs) + + def ReadSymLink(*args, **kwargs): + return win_symlink_fast.FastReadReparseLink(*args, **kwargs) + + def Rmtree(*args, **kwargs): + return win_symlink.RmtreeShallow(*args, **kwargs) + + def OsWalk(*args, **kwargs): + return win_symlink.OsWalk(*args, **kwargs) + + port_symlink_test.MakeSymLink = MakeSymLink + port_symlink_test.IsSymLink = IsSymLink + port_symlink_test.ReadSymLink = ReadSymLink + port_symlink_test.Rmtree = Rmtree + port_symlink_test.OsWalk = OsWalk + + # Makes a unit test available to the unittest.main (through magic). + class WinSymlinkTest(port_symlink_test.PortSymlinkTest): + pass + + util.SetupDefaultLoggingConfig() + unittest.main(verbosity=2)
diff --git a/src/starboard/tools/win_symlink_test.py b/src/starboard/tools/win_symlink_test.py new file mode 100644 index 0000000..851ae76 --- /dev/null +++ b/src/starboard/tools/win_symlink_test.py
@@ -0,0 +1,91 @@ +#!/usr/bin/python +# Copyright 2018 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 win_symlink.""" + +import os +import shutil +import sys +import tempfile +import unittest + + +import _env # pylint: disable=relative-import,unused-import + + +if __name__ == '__main__' and sys.platform == 'win32': + from starboard.tools import port_symlink_test # pylint: disable=g-import-not-at-top + from starboard.tools import util # pylint: disable=g-import-not-at-top + from starboard.tools import win_symlink # pylint: disable=g-import-not-at-top + + # Override the port_symlink_test symlink functions to point to our win_symlink + # versions. + def MakeSymLink(*args, **kwargs): + return win_symlink.CreateReparsePoint(*args, **kwargs) + + def IsSymLink(*args, **kwargs): + return win_symlink.IsReparsePoint(*args, **kwargs) + + def ReadSymLink(*args, **kwargs): + return win_symlink.ReadReparsePoint(*args, **kwargs) + + def Rmtree(*args, **kwargs): + return win_symlink.RmtreeShallow(*args, **kwargs) + + def OsWalk(*args, **kwargs): + return win_symlink.OsWalk(*args, **kwargs) + + port_symlink_test.MakeSymLink = MakeSymLink + port_symlink_test.IsSymLink = IsSymLink + port_symlink_test.ReadSymLink = ReadSymLink + port_symlink_test.Rmtree = Rmtree + port_symlink_test.OsWalk = OsWalk + + # Makes a unit test available to the unittest.main (through magic). + class WinSymlinkTest(port_symlink_test.PortSymlinkTest): + + def testRmtreeOsWalkDoesNotFollowSymlinks(self): + """_RmtreeOsWalk(...) will delete the symlink and not the target.""" + external_temp_dir = tempfile.mkdtemp() + try: + external_temp_file = os.path.join(external_temp_dir, 'test.txt') + with open(external_temp_file, 'w') as fd: + fd.write('HI') + link_dir = os.path.join(self.tmp_dir, 'foo', 'link_dir') + MakeSymLink(external_temp_file, link_dir) + win_symlink._RmtreeOsWalk(self.tmp_dir) + # The target file should still exist + self.assertTrue(os.path.isfile(external_temp_file)) + finally: + shutil.rmtree(external_temp_dir, ignore_errors=True) + + def testRmtreeCmdShellDoesNotFollowSymlinks(self): + """_RmtreeShellCmd(...) will delete the symlink and not the target.""" + external_temp_dir = tempfile.mkdtemp() + try: + external_temp_file = os.path.join(external_temp_dir, 'test.txt') + with open(external_temp_file, 'w') as fd: + fd.write('HI') + link_dir = os.path.join(self.tmp_dir, 'foo', 'link_dir') + MakeSymLink(external_temp_file, link_dir) + win_symlink._RmtreeShellCmd(self.tmp_dir) + # The target file should still exist + self.assertTrue(os.path.isfile(external_temp_file)) + finally: + shutil.rmtree(external_temp_dir, ignore_errors=True) + + + util.SetupDefaultLoggingConfig() + unittest.main(verbosity=2)
diff --git a/src/starboard/window.h b/src/starboard/window.h index 5ccc4d9..df29899 100644 --- a/src/starboard/window.h +++ b/src/starboard/window.h
@@ -139,7 +139,8 @@ // |window|: The SbWindow to retrieve the platform handle for. SB_EXPORT void* SbWindowGetPlatformHandle(SbWindow window); -#if SB_HAS(ON_SCREEN_KEYBOARD) +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \ + SB_HAS(ON_SCREEN_KEYBOARD) // System-triggered OnScreenKeyboard events have ticket value // kSbEventOnScreenKeyboardInvalidTicket. @@ -154,6 +155,11 @@ float height; } SbWindowRect; +#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION +// Return whether the current platform supports an on screen keyboard +SB_EXPORT bool SbWindowOnScreenKeyboardIsSupported(); +#endif + // Determine if the on screen keyboard is shown. SB_EXPORT bool SbWindowIsOnScreenKeyboardShown(SbWindow window); @@ -224,7 +230,8 @@ SB_EXPORT bool SbWindowOnScreenKeyboardSuggestionsSupported(SbWindow window); #endif // SB_API_VERSION >= 11 -#endif // SB_HAS(ON_SCREEN_KEYBOARD) +#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || + // SB_HAS(ON_SCREEN_KEYBOARD) #ifdef __cplusplus } // extern "C"
diff --git a/src/testing/gtest.gyp b/src/testing/gtest.gyp index 71dd4c9..86ec54b 100644 --- a/src/testing/gtest.gyp +++ b/src/testing/gtest.gyp
@@ -179,7 +179,7 @@ '_POSIX_PATH_MAX=255', ], }], - ['target_arch=="ps4"', { + ['sb_target_platform=="ps4"', { 'gtest_defines!' : [ 'GTEST_USE_OWN_TR1_TUPLE=1', ],
diff --git a/src/third_party/angle/src/libANGLE/params.h b/src/third_party/angle/src/libANGLE/params.h index 32a5795..11467ec 100644 --- a/src/third_party/angle/src/libANGLE/params.h +++ b/src/third_party/angle/src/libANGLE/params.h
@@ -36,13 +36,20 @@ constexpr bool hasDynamicType(const ParamTypeInfo &typeInfo) const { - return mSelfClass == typeInfo.mSelfClass || + return areEqual(mSelfClass, typeInfo.mSelfClass) || (mParentTypeInfo && mParentTypeInfo->hasDynamicType(typeInfo)); } constexpr bool isValid() const { return mSelfClass != nullptr; } private: + // This function performs a compile-time comparison of string literals. + // This function cannot be made more beautiful [without C++ 14]. + constexpr bool areEqual(const char* lhs, const char* rhs) const + { + return (*lhs == *rhs) && ((*lhs == 0) || (areEqual(lhs + 1, rhs + 1))); + } + const char *mSelfClass; const ParamTypeInfo *mParentTypeInfo; };
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 0948858..d9b0b27 100644 --- a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -1307,6 +1307,9 @@ case DXGI_FORMAT_R16G16B16A16_FLOAT: case DXGI_FORMAT_R32G32B32A32_FLOAT: case DXGI_FORMAT_NV12: +#if defined(STARBOARD) + case DXGI_FORMAT_R10G10B10A2_UNORM: +#endif // defined(STARBOARD) case DXGI_FORMAT_R8_UNORM: case DXGI_FORMAT_R16_UNORM: break;
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp index bf43fe0..a8f4627 100644 --- a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -569,6 +569,16 @@ device, mRenderer->getDxgiFactory(), getSwapChainNativeFormat(), backbufferWidth, backbufferHeight, getD3DSamples(), &mSwapChain); +#if defined(STARBOARD) + // When an application is run in as a service, which is Session 0, a very specific error is + // returned. To allow unit tests to continue, silently continue using an offscreen texture. + bool failed_in_session_0 = FAILED(result) && result == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE; + if (failed_in_session_0) + { + mNeedsOffscreenTexture = true; + } + else +#endif if (FAILED(result)) { ERR() << "Could not create additional swap chains or offscreen surfaces, " @@ -585,6 +595,27 @@ } } +#if defined(STARBOARD) + if (mSwapChain) + { + if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2) + { + mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain); + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + + gl::Error err = mRenderer->allocateResourceNoDesc(mBackBufferTexture, &mBackBufferRTView); + ASSERT(!err.isError()); + mBackBufferRTView.setDebugName("Back buffer render target"); + + result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view"); + } +#else if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2) { mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain); @@ -601,6 +632,7 @@ result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view"); +#endif } mFirstSwap = true;
diff --git a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h index 59fa41a..85bd35d 100644 --- a/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h +++ b/src/third_party/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
@@ -89,7 +89,11 @@ d3d11::RenderTargetView mBackBufferRTView; ID3D11ShaderResourceView *mBackBufferSRView; +#if defined(STARBOARD) + bool mNeedsOffscreenTexture; +#else const bool mNeedsOffscreenTexture; +#endif ID3D11Texture2D *mOffscreenTexture; d3d11::RenderTargetView mOffscreenRTView; ID3D11ShaderResourceView *mOffscreenSRView;
diff --git a/src/third_party/dlmalloc/dlmalloc_config.h b/src/third_party/dlmalloc/dlmalloc_config.h index 4ba17f7..8b8543f 100644 --- a/src/third_party/dlmalloc/dlmalloc_config.h +++ b/src/third_party/dlmalloc/dlmalloc_config.h
@@ -98,7 +98,7 @@ // Adapt Starboard configuration to old LBShell-style configuration. #if defined(STARBOARD) -#if SB_HAS(MMAP) +#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) #define LB_HAS_MMAP #endif #if SB_HAS(VIRTUAL_REGIONS) @@ -128,7 +128,7 @@ #if defined(STARBOARD) -#if SB_HAS(MMAP) +#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) #define DEFAULT_MMAP_THRESHOLD SB_DEFAULT_MMAP_THRESHOLD #endif
diff --git a/src/third_party/googletest/src/googletest/include/gtest/gtest_prod.h b/src/third_party/googletest/src/googletest/include/gtest/gtest_prod.h new file mode 100644 index 0000000..060dc6e --- /dev/null +++ b/src/third_party/googletest/src/googletest/include/gtest/gtest_prod.h
@@ -0,0 +1,11 @@ +// This header is to redirect Chromium gtest_prod consumer code to where +// Cobalt puts it. It is only used by V8 so far. + +#ifndef THIRD_PARTY_GOOGLETEST_SRC_GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define THIRD_PARTY_GOOGLETEST_SRC_GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ + +// #include "testing/gtest/include/gtest/gtest_prod.h" + +#define FRIEND_TEST(test_case_name, test_name) + +#endif // THIRD_PARTY_GOOGLETEST_SRC_GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ \ No newline at end of file
diff --git a/src/third_party/icu/source/common/umapfile.c b/src/third_party/icu/source/common/umapfile.c index 96c198c..b40dd6c 100644 --- a/src/third_party/icu/source/common/umapfile.c +++ b/src/third_party/icu/source/common/umapfile.c
@@ -318,7 +318,7 @@ } /* read the file */ - if (fileLength != SbFileRead(file, p, fileLength)) { + if (fileLength != SbFileReadAll(file, p, fileLength)) { uprv_free(p); SbFileClose(file); return FALSE;
diff --git a/src/third_party/libvpx/vp9/common/vp9_loopfilter.c b/src/third_party/libvpx/vp9/common/vp9_loopfilter.c index 183dec4..0d48194 100644 --- a/src/third_party/libvpx/vp9/common/vp9_loopfilter.c +++ b/src/third_party/libvpx/vp9/common/vp9_loopfilter.c
@@ -1213,7 +1213,7 @@ } // Disable filtering on the leftmost column - border_mask = ~(mi_col == 0); + border_mask = ~(mi_col == 0 ? 1 : 0); #if CONFIG_VP9_HIGHBITDEPTH if (cm->use_highbitdepth) { highbd_filter_selectively_vert(CONVERT_TO_SHORTPTR(dst->buf),
diff --git a/src/third_party/llvm-project/compiler-rt/compiler-rt.gyp b/src/third_party/llvm-project/compiler-rt/compiler-rt.gyp index b7b2215..77a9527 100644 --- a/src/third_party/llvm-project/compiler-rt/compiler-rt.gyp +++ b/src/third_party/llvm-project/compiler-rt/compiler-rt.gyp
@@ -89,6 +89,14 @@ 'lib/builtins/trunctfsf2.c', ], }], + ['sb_evergreen == 1 and target_arch == "ia32"', { + 'sources': [ + 'lib/builtins/i386/divdi3.S', + 'lib/builtins/i386/moddi3.S', + 'lib/builtins/i386/udivdi3.S', + 'lib/builtins/i386/umoddi3.S', + ], + }], ] } ]
diff --git a/src/third_party/mozjs-45/js/src/jit/ExecutableAllocatorStarboard.cpp b/src/third_party/mozjs-45/js/src/jit/ExecutableAllocatorStarboard.cpp index 31975ea..3979201 100644 --- a/src/third_party/mozjs-45/js/src/jit/ExecutableAllocatorStarboard.cpp +++ b/src/third_party/mozjs-45/js/src/jit/ExecutableAllocatorStarboard.cpp
@@ -50,7 +50,7 @@ #if !SB_CAN(MAP_EXECUTABLE_MEMORY) SB_NOTREACHED(); return nullptr; -#elif !SB_HAS(MMAP) +#elif !(SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) SB_NOTIMPLEMENTED(); return nullptr; #else @@ -63,12 +63,12 @@ js::jit::DeallocateExecutableMemory(void* addr, size_t bytes, size_t pageSize) { MOZ_ASSERT(bytes % pageSize == 0); -#if SB_HAS(MMAP) +#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) mozilla::DebugOnly<bool> result = SbMemoryUnmap(addr, bytes); MOZ_ASSERT(result); -#else // SB_HAS(MMAP) +#else // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) SB_NOTIMPLEMENTED(); -#endif // SB_HAS(MMAP) +#endif // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) } ExecutablePool::Allocation
diff --git a/src/third_party/mozjs-45/js/src/jit/x86-shared/Encoding-x86-shared.h b/src/third_party/mozjs-45/js/src/jit/x86-shared/Encoding-x86-shared.h index 2457f85..99d8859 100644 --- a/src/third_party/mozjs-45/js/src/jit/x86-shared/Encoding-x86-shared.h +++ b/src/third_party/mozjs-45/js/src/jit/x86-shared/Encoding-x86-shared.h
@@ -244,6 +244,16 @@ case OP2_MOVSD_WsdVsd: // also OP2_MOVPS_WpsVps case OP2_MOVAPS_WsdVsd: case OP2_MOVDQ_WdqVdq: + return true; + default: + break; + } + return false; +} + +inline bool IsXMMReversedOperands(ThreeByteOpcodeID opcode) +{ + switch (opcode) { case OP3_PEXTRD_EdVdqIb: return true; default:
diff --git a/src/third_party/mozjs-45/js/src/vm/SharedArrayObject.cpp b/src/third_party/mozjs-45/js/src/vm/SharedArrayObject.cpp index 09acd00..602d576 100644 --- a/src/third_party/mozjs-45/js/src/vm/SharedArrayObject.cpp +++ b/src/third_party/mozjs-45/js/src/vm/SharedArrayObject.cpp
@@ -36,14 +36,16 @@ static inline void* MapMemory(size_t length, bool commit) { -#if defined(STARBOARD) && !SB_HAS(MMAP) +#if defined(STARBOARD) && \ + !(SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) SB_NOTIMPLEMENTED(); return NULL; -#elif defined(STARBOARD) && SB_HAS(MMAP) - if (!commit) { - SB_NOTREACHED(); - } - return SbMemoryMap(length, kSbMemoryMapProtectReadWrite, NULL); +#elif defined(STARBOARD) && \ + (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) + if (!commit) { + SB_NOTREACHED(); + } + return SbMemoryMap(length, kSbMemoryMapProtectReadWrite, NULL); #elif defined(XP_WIN) int prot = (commit ? MEM_COMMIT : MEM_RESERVE); int flags = (commit ? PAGE_READWRITE : PAGE_NOACCESS); @@ -60,10 +62,12 @@ static inline void UnmapMemory(void* addr, size_t len) { -#if defined(STARBOARD) && !SB_HAS(MMAP) +#if defined(STARBOARD) && \ + !(SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) SB_NOTIMPLEMENTED(); -#elif defined(STARBOARD) && SB_HAS(MMAP) - SbMemoryUnmap(addr, len); +#elif defined(STARBOARD) && \ + (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) + SbMemoryUnmap(addr, len); #elif defined(XP_WIN) VirtualFree(addr, 0, MEM_RELEASE); #else
diff --git a/src/third_party/mozjs-45/mfbt/TaggedAnonymousMemory.h b/src/third_party/mozjs-45/mfbt/TaggedAnonymousMemory.h index 140c64a..389f30c 100644 --- a/src/third_party/mozjs-45/mfbt/TaggedAnonymousMemory.h +++ b/src/third_party/mozjs-45/mfbt/TaggedAnonymousMemory.h
@@ -48,12 +48,12 @@ { // Starboard has no concept of passing an address into mmap. SB_DCHECK(aAddr == nullptr); -#if SB_HAS(MMAP) +#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) return SbMemoryMap(aLength, aProt, aTag); -#else // SB_HAS(MMAP) +#else // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) SB_NOTIMPLEMENTED(); return nullptr; -#endif // SB_HAS(MMAP) +#endif // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP) } static inline int
diff --git a/src/third_party/mozjs-45/mozjs-45.gyp b/src/third_party/mozjs-45/mozjs-45.gyp index 13d5e4e..d90092d 100644 --- a/src/third_party/mozjs-45/mozjs-45.gyp +++ b/src/third_party/mozjs-45/mozjs-45.gyp
@@ -110,15 +110,6 @@ ], }], - # TODO: Remove once ps4 configuration todos are addressed. - ['target_arch == "ps4" or sb_target_platform == "ps4"', { - 'common_defines': [ - 'JS_CPU_X64=1', - 'JS_CODEGEN_X64=1', - 'JS_PUNBOX64=1', - ], - }], - ['cobalt_config != "gold"', { 'common_defines': [ 'JS_TRACE_LOGGING=1', @@ -227,8 +218,7 @@ 'js/src/jit/x86/Trampoline-x86.cpp', ], }], - # TODO: Remove "* == ps4" once ps4 configuration todos are addressed. - ['target_arch == "x64" or target_arch == "ps4" or sb_target_platform == "ps4"', { + ['target_arch == "x64"', { 'sources': [ 'js/src/jit/x64/Assembler-x64.cpp', 'js/src/jit/x64/Bailouts-x64.cpp',
diff --git a/src/third_party/musl/musl.gyp b/src/third_party/musl/musl.gyp index 8c826fb..30c47d7 100644 --- a/src/third_party/musl/musl.gyp +++ b/src/third_party/musl/musl.gyp
@@ -525,6 +525,17 @@ 'src/string/wmemmove.c', 'src/string/wmemset.c', ] + }, + { + 'target_name': 'musl_unittests', + 'type': '<(gtest_target_type)', + 'sources': [ + 'test/type_size_test.cc', + ], + 'dependencies': [ + 'c', + '<(DEPTH)/starboard/starboard_headers_only.gyp:starboard_headers_only', + ], } ] }
diff --git a/src/third_party/musl/test/type_size_test.cc b/src/third_party/musl/test/type_size_test.cc new file mode 100644 index 0000000..e32cc70 --- /dev/null +++ b/src/third_party/musl/test/type_size_test.cc
@@ -0,0 +1,206 @@ +// Copyright 2019 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/configuration.h" + +#if SB_IS(EVERGREEN) + +#include <inttypes.h> +#include <limits.h> +#include <math.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <sys/types.h> +#include <wchar.h> + +SB_COMPILE_ASSERT(sizeof(int8_t) == SB_SIZE_OF_CHAR, + SB_SIZE_OF_CHAR_is_inconsistent_with_sizeof_int8_t); + +SB_COMPILE_ASSERT(sizeof(uint8_t) == SB_SIZE_OF_CHAR, + SB_SIZE_OF_CHAR_is_inconsistent_with_sizeof_uint8_t); + +SB_COMPILE_ASSERT(sizeof(clockid_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_clockid_t); + +SB_COMPILE_ASSERT(sizeof(gid_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_gid_t); + +SB_COMPILE_ASSERT(sizeof(id_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_id_t); + +SB_COMPILE_ASSERT(sizeof(int32_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_int32_t); + +SB_COMPILE_ASSERT(sizeof(key_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_key_t); + +SB_COMPILE_ASSERT(sizeof(mode_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_mode_t); + +SB_COMPILE_ASSERT(sizeof(pid_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_pid_t); + +SB_COMPILE_ASSERT(sizeof(uid_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_uid_t); + +SB_COMPILE_ASSERT(sizeof(uint32_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_uint32_t); + +SB_COMPILE_ASSERT(sizeof(useconds_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_useconds_t); + +SB_COMPILE_ASSERT(sizeof(wint_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_wint_t); + +#if SB_IS(ARCH_ARM) && SB_IS(64_BIT) +SB_COMPILE_ASSERT(sizeof(blksize_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_blksize_t); +#else // !SB_IS(ARCH_ARM) || !SB_IS(64_BIT) +SB_COMPILE_ASSERT(sizeof(blksize_t) == SB_SIZE_OF_LONG, + SB_SIZE_OF_LONG_is_inconsistent_with_sizeof_blksize_t); +#endif // SB_IS(ARCH_ARM) && SB_IS(64_BIT) + +SB_COMPILE_ASSERT(sizeof(clock_t) == SB_SIZE_OF_LONG, + SB_SIZE_OF_LONG_is_inconsistent_with_sizeof_clock_t); + +SB_COMPILE_ASSERT(sizeof(suseconds_t) == SB_SIZE_OF_LONG, + SB_SIZE_OF_LONG_is_inconsistent_with_sizeof_suseconds_t); + +SB_COMPILE_ASSERT(sizeof(time_t) == SB_SIZE_OF_LONG, + SB_SIZE_OF_LONG_is_inconsistent_with_sizeof_time_t); + +SB_COMPILE_ASSERT(sizeof(wctype_t) == SB_SIZE_OF_LONG, + SB_SIZE_OF_LONG_is_inconsistent_with_sizeof_wctype_t); + +SB_COMPILE_ASSERT(sizeof(timer_t) == SB_SIZE_OF_POINTER, + SB_SIZE_OF_POINTER_is_inconsistent_with_sizeof_timer_t); + +SB_COMPILE_ASSERT(sizeof(int16_t) == SB_SIZE_OF_SHORT, + SB_SIZE_OF_SHORT_is_inconsistent_with_sizeof_int16_t); + +SB_COMPILE_ASSERT(sizeof(uint16_t) == SB_SIZE_OF_SHORT, + SB_SIZE_OF_SHORT_is_inconsistent_with_sizeof_uint16_t); + +// WARNING: do not change unless you know what you are doing. The following +// define, SB_TYPE_SIZE_EXPECTED, is used to simplify the size checking across +// different architectures. + +#if SB_IS(32_BIT) +#define SB_EXPECTED_TYPE_SIZE SB_SIZE_OF_INT +#elif SB_IS(64_BIT) +#define SB_EXPECTED_TYPE_SIZE SB_SIZE_OF_LONG +#endif // SB_IS(64_BIT) + +SB_COMPILE_ASSERT(sizeof(intptr_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_intptr_t); + +#if SB_IS(ARCH_ARM) && SB_IS(64_BIT) +SB_COMPILE_ASSERT(sizeof(nlink_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_nlink_t); +#else // !SB_IS(ARCH_ARM) || !SB_IS(64_BIT) +SB_COMPILE_ASSERT(sizeof(nlink_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_nlink_t); +#endif // SB_IS(ARCH_ARM) && SB_IS(64_BIT) + +SB_COMPILE_ASSERT(sizeof(ptrdiff_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_ptrdiff_t); + +SB_COMPILE_ASSERT(sizeof(register_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_register_t); + +SB_COMPILE_ASSERT(sizeof(size_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_size_t); + +SB_COMPILE_ASSERT(sizeof(ssize_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_ssize_t); + +SB_COMPILE_ASSERT(sizeof(uintptr_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_uintptr_t); + +#undef SB_EXPECTED_TYPE_SIZE + +#if SB_IS(32_BIT) +#define SB_EXPECTED_TYPE_SIZE SB_SIZE_OF_LLONG +#elif SB_IS(64_BIT) +#define SB_EXPECTED_TYPE_SIZE SB_SIZE_OF_LONG +#endif // SB_IS(64_BIT) + +SB_COMPILE_ASSERT(sizeof(blkcnt_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_blkcnt_t); + +SB_COMPILE_ASSERT(sizeof(dev_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_dev_t); + +SB_COMPILE_ASSERT(sizeof(fsblkcnt_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_fsblkcnt_t); + +SB_COMPILE_ASSERT(sizeof(fsfilcnt_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_fsfilcnt_t); + +SB_COMPILE_ASSERT(sizeof(ino_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_ino_t); + +SB_COMPILE_ASSERT(sizeof(int64_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_int64_t); + +SB_COMPILE_ASSERT(sizeof(intmax_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_intmax_t); + +SB_COMPILE_ASSERT(sizeof(off_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_off_t); + +SB_COMPILE_ASSERT(sizeof(u_int64_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_u_int64_t); + +SB_COMPILE_ASSERT(sizeof(uint64_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_uint64_t); + +SB_COMPILE_ASSERT(sizeof(uintmax_t) == SB_EXPECTED_TYPE_SIZE, + SB_EXPECTED_TYPE_SIZE_is_inconsistent_with_sizeof_uintmax_t); + +#undef SB_EXPECTED_TYPE_SIZE + +#if SB_IS(ARCH_I386) +#if defined(__WCHAR_TYPE__) +#else // !defined(__WCHAR_TYPE__) +SB_COMPILE_ASSERT(sizeof(wchar_t) == SB_SIZE_OF_LONG, + SB_SIZE_OF_LONG_is_inconsistent_with_sizeof_wchar_t); +#endif // defined(__WCHAR_TYPE__) +// TODO: Decide if we should, and how, verify that __WCHAR_TYPE__ is the +// expected size. +#else // !SB_IS(ARCH_I386) +SB_COMPILE_ASSERT(sizeof(wchar_t) == SB_SIZE_OF_INT, + SB_SIZE_OF_INT_is_inconsistent_with_sizeof_wchar_t); +#endif // SB_IS(ARCH_I386) + +#if (SB_IS(ARCH_I386) && SB_IS(32_BIT) && \ + defined(__FLT_EVAL_METHOD__) && (__FLT_EVAL_METHOD__ != 0)) || \ + (SB_IS(ARCH_X86) && SB_IS(64_BIT) && \ + defined(__FLT_EVAL_METHOD__) && (__FLT_EVAL_METHOD__ == 2)) +SB_COMPILE_ASSERT(sizeof(float_t) == SB_SIZE_OF_LONG_DOUBLE, + SB_SIZE_OF_LONG_DOUBLE_is_inconsistent_with_sizeof_float_t); + +SB_COMPILE_ASSERT(sizeof(double_t) == SB_SIZE_OF_LONG_DOUBLE, + SB_SIZE_OF_LONG_DOUBLE_is_inconsistent_with_sizeof_double_t); +#else +SB_COMPILE_ASSERT(sizeof(float_t) == SB_SIZE_OF_FLOAT, + SB_SIZE_OF_FLOAT_is_inconsistent_with_sizeof_float_t); + +SB_COMPILE_ASSERT(sizeof(double_t) == SB_SIZE_OF_DOUBLE, + SB_SIZE_OF_DOUBLE_is_inconsistent_with_sizeof_double_t); +#endif + +#endif // SB_IS(EVERGREEN)
diff --git a/src/third_party/protobuf/protobuf.gyp b/src/third_party/protobuf/protobuf.gyp index bd1886c..48db80e 100644 --- a/src/third_party/protobuf/protobuf.gyp +++ b/src/third_party/protobuf/protobuf.gyp
@@ -4,6 +4,30 @@ { 'conditions': [ + ['clang==1', { + 'target_defaults': { + 'cflags': [ + # protobuf-3 contains a few functions that are unused. + '-Wno-unused-function', + # protobuf-3 mixes generated enum types. + '-Wno-enum-compare-switch', + # Used by older version of clang. + '-Wno-enum-compare', + # Older version of clang don't have -Wno-enum-compare-switch + '-Wno-unknown-warning-option', + ], + 'cflags_host': [ + # protobuf-3 contains a few functions that are unused. + '-Wno-unused-function', + # protobuf-3 mixes generated enum types. + '-Wno-enum-compare-switch', + # Used by older version of clang. + '-Wno-enum-compare', + # Older version of clang don't have -Wno-enum-compare-switch + '-Wno-unknown-warning-option', + ] + }, + }], ['use_system_protobuf==0', { 'conditions': [ ['OS=="win"', { @@ -42,12 +66,6 @@ 'includes': [ 'protobuf_lite.gypi', ], - 'variables': { - 'clang_warning_flags': [ - # protobuf-3 contains a few functions that are unused. - '-Wno-unused-function', - ], - }, # Required for component builds. See http://crbug.com/172800. 'defines': [ 'LIBPROTOBUF_EXPORTS', @@ -59,11 +77,24 @@ ], }, 'all_dependent_settings': { + 'include_dirs': [ + # Get protobuf headers from the chromium tree. + '<(DEPTH)/third_party/protobuf/src', + ], 'defines': [ - # This macro must be defined to suppress the use - # of dynamic_cast<>, which requires RTTI. + # This macro must be defined to suppress the use of + # dynamic_cast<>, which requires RTTI. 'GOOGLE_PROTOBUF_NO_RTTI', - ] + + # The generated code needs to be compiled with the same flags as the + # protobuf library. Otherwise we get static initializers which are not + # thread safe. + 'GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER', + + # pthread is used on the host platform, but the target platform + # actually uses SbThread. + 'HAVE_PTHREAD', + ], }, }, # This is the full, heavy protobuf lib that's needed for c++ .protos @@ -78,12 +109,6 @@ 'includes': [ 'protobuf_lite.gypi', ], - 'variables': { - 'clang_warning_flags': [ - # protobuf-3 contains a few functions that are unused. - '-Wno-unused-function', - ], - }, 'sources': [ 'src/google/protobuf/any.cc', 'src/google/protobuf/any.h', @@ -402,12 +427,6 @@ "src/google/protobuf/compiler/zip_writer.cc", "src/google/protobuf/compiler/zip_writer.h", ], - 'variables': { - 'clang_warning_flags': [ - # protobuf-3 contains a few functions that are unused. - '-Wno-unused-function', - ], - }, 'dependencies': [ 'protobuf_full_do_not_use', ],
diff --git a/src/third_party/skia/src/gpu/gl/GrGLUtil.cpp b/src/third_party/skia/src/gpu/gl/GrGLUtil.cpp index 0e05f79..aadefbe 100644 --- a/src/third_party/skia/src/gpu/gl/GrGLUtil.cpp +++ b/src/third_party/skia/src/gpu/gl/GrGLUtil.cpp
@@ -8,6 +8,21 @@ #include "GrGLUtil.h" #include "SkMatrix.h" +/////////////////////////////////////////////////////////////////////////////// + +#if GR_GL_LOG_CALLS +bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START); +#endif + +#if GR_GL_CHECK_ERROR +bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START); +#endif + +/////////////////////////////////////////////////////////////////////////////// + +#include "starboard/configuration.h" +#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + #if defined(STARBOARD) #include "starboard/common/string.h" #include "starboard/configuration.h" @@ -16,7 +31,7 @@ #include <stdio.h> #endif -#if defined(STARBOARD) && (SB_API_VERSION >= SB_EGL_AND_GL_INTERFACE_VERSION) +#if defined(STARBOARD) && (SB_API_VERSION >= 11) #include "starboard/egl.h" #define EGLint SbEglInt32 #define EGLBoolean SbEglBoolean @@ -24,10 +39,10 @@ #define EGL_OPENGL_ES_API SB_EGL_OPENGL_ES_API #define EGL_CONTEXT_CLIENT_VERSION SB_EGL_CONTEXT_CLIENT_VERSION #define EGL_CALL_PREFIX ::SkiaGetEglInterface(). -#else // !defined(STARBOARD) || (SB_API_VERSION < SB_EGL_AND_GL_INTERFACE_VERSION) +#else // !defined(STARBOARD) || (SB_API_VERSION < 11) #include <EGL/egl.h> #define EGL_CALL_PREFIX -#endif // defined(STARBOARD) && (SB_API_VERSION >= SB_EGL_AND_GL_INTERFACE_VERSION) +#endif // defined(STARBOARD) && (SB_API_VERSION >= 11) #define EGL_CALL_SIMPLE(x) (EGL_CALL_PREFIX x) @@ -54,13 +69,13 @@ return "Unknown"; } -#if defined(STARBOARD) && (SB_API_VERSION >= SB_EGL_AND_GL_INTERFACE_VERSION) +#if defined(STARBOARD) && (SB_API_VERSION >= 11) const SbEglInterface& SkiaGetEglInterface() { static const SbEglInterface* egl_interface = SbGetEglInterface(); return *egl_interface; } -#endif // defined(STARBOARD) && (SB_API_VERSION >= SB_EGL_AND_GL_INTERFACE_VERSION) +#endif // defined(STARBOARD) && (SB_API_VERSION >= 11) } void GrGLCheckErr(const GrGLInterface* gl, @@ -79,18 +94,6 @@ } } -/////////////////////////////////////////////////////////////////////////////// - -#if GR_GL_LOG_CALLS - bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START); -#endif - -#if GR_GL_CHECK_ERROR - bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START); -#endif - -/////////////////////////////////////////////////////////////////////////////// - GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) { if (nullptr == versionString) { SkDebugf("nullptr GL version string."); @@ -469,3 +472,30 @@ return gTable[(int)test]; } + +#else // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2) + +void GrGLCheckErr(const GrGLInterface* gl, const char* location, const char* call) {} + +void GrGLClearErr(const GrGLInterface* gl) {} + +GrGLenum GrToGLStencilFunc(GrStencilTest test) { return NULL; } + +GrGLVersion GrGLGetVersionFromString(const char* versionString) { return NULL; } + +GrGLVendor GrGLGetVendor(const GrGLInterface* gl) { return kOther_GrGLVendor; } + +GrGLRenderer GrGLGetRendererFromString(const char* rendererString) { return kOther_GrGLRenderer; } + +void GrGLGetDriverInfo(GrGLStandard standard, + GrGLVendor vendor, + const char* rendererString, + const char* versionString, + GrGLDriver* outDriver, + GrGLDriverVersion* outVersion) {} + +GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) { return NULL; } + +GrGLVersion GrGLGetVersion(const GrGLInterface* gl) { return NULL; } + +#endif // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
diff --git a/src/third_party/zlib/contrib/minizip/ioapi.c b/src/third_party/zlib/contrib/minizip/ioapi.c index 49958f6..9e8b184 100644 --- a/src/third_party/zlib/contrib/minizip/ioapi.c +++ b/src/third_party/zlib/contrib/minizip/ioapi.c
@@ -70,7 +70,7 @@ p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; } - +#if (!defined(STARBOARD)) static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); @@ -233,3 +233,5 @@ pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->opaque = NULL; } + +#endif //!defined(STARBOARD)
diff --git a/src/third_party/zlib/contrib/minizip/ioapi.h b/src/third_party/zlib/contrib/minizip/ioapi.h index c5de341..4d2590c 100644 --- a/src/third_party/zlib/contrib/minizip/ioapi.h +++ b/src/third_party/zlib/contrib/minizip/ioapi.h
@@ -167,8 +167,10 @@ voidpf opaque; } zlib_filefunc64_def; +#if (!defined(STARBOARD)) void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +#endif //!defined(STARBOARD) /* now internal definition, only for zip.c and unzip.h */ typedef struct zlib_filefunc64_32_def_s
diff --git a/src/third_party/zlib/contrib/minizip/iostarboard.c b/src/third_party/zlib/contrib/minizip/iostarboard.c new file mode 100644 index 0000000..a3e42b3 --- /dev/null +++ b/src/third_party/zlib/contrib/minizip/iostarboard.c
@@ -0,0 +1,219 @@ +// Copyright 2019 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. + +// Starboard IO base function header for compress/uncompress .zip + +#include "zlib.h" +#include "iostarboard.h" +#include "starboard/file.h" + +static voidpf ZCALLBACK starboard_open_file_func OF((voidpf opaque, const char* filename, int mode)); +static voidpf ZCALLBACK starboard_open64_file_func OF((voidpf opaque, const void* filename, int mode)); +static uLong ZCALLBACK starboard_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK starboard_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +static ZPOS64_T ZCALLBACK starboard_tell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK starboard_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK starboard_close_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK starboard_error_file_func OF((voidpf opaque, voidpf stream)); + +static voidpf ZCALLBACK starboard_open_file_func (voidpf opaque, const char* filename, int mode) { + SbFile file = NULL; + int flags = 0; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) { + flags = kSbFileRead | kSbFileOpenOnly; + } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING){ + flags = kSbFileRead | kSbFileWrite | kSbFileOpenOnly; + } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) { + flags = kSbFileRead | kSbFileWrite | kSbFileCreateAlways | kSbFileOpenTruncated; + } + + if ((filename!=NULL) && (flags != 0)) { + file = SbFileOpen(filename, flags, NULL, NULL); + } + return file; +} + +static voidpf ZCALLBACK starboard_open64_file_func (voidpf opaque, const void* filename, int mode) { + SbFile file = NULL; + int flags = 0; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) { + flags = kSbFileRead | kSbFileOpenOnly; + } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING){ + flags = kSbFileRead | kSbFileWrite | kSbFileOpenOnly; + } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) { + flags = kSbFileRead | kSbFileWrite | kSbFileCreateAlways | kSbFileOpenTruncated; + } + + if ((filename!=NULL) && (flags != 0)) { + file = SbFileOpen((const char*)filename, flags, NULL, NULL); + } + return file; +} + +static uLong ZCALLBACK starboard_read_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) { + uLong ret = 0; + SbFile file = NULL; + if (stream != NULL) { + file = (SbFile)stream; + } + if (file != NULL) { + int bytes_read = SbFileRead(file, (char*)buf, (int)size); + ret = (uLong)(bytes_read == -1 ? 0 : bytes_read); + } + return ret; +} + +static uLong ZCALLBACK starboard_write_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) { + uLong ret = 0; + SbFile file = NULL; + if (stream != NULL) { + file = (SbFile)stream; + } + if (file != NULL) { + int bytes_written = SbFileWrite(file, (const char*)buf, (int)size); + ret = (uLong)(bytes_written == -1 ? 0 : bytes_written); + } + return ret; +} + +static long ZCALLBACK starboard_tell_file_func (voidpf opaque, voidpf stream) { + long ret = -1; + SbFile file = NULL; + if (stream != NULL) { + file = (SbFile)stream; + } + if (file != NULL) { + ret = SbFileSeek(file, kSbFileFromCurrent, 0); + } + return ret; +} + +static ZPOS64_T ZCALLBACK starboard_tell64_file_func (voidpf opaque, voidpf stream) { + ZPOS64_T ret = -1; + SbFile file = NULL; + if (stream != NULL) { + file = (SbFile)stream; + } + if (file != NULL) { + ret = (ZPOS64_T)SbFileSeek(file, kSbFileFromCurrent, 0); + } + return ret; +} + +static long ZCALLBACK starboard_seek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) { + long ret = -1; + SbFile file = NULL; + SbFileWhence file_whence = 0; + if (stream != NULL) { + file = (SbFile)stream; + } + switch (origin) { + case ZLIB_FILEFUNC_SEEK_CUR : + file_whence = kSbFileFromCurrent; + break; + case ZLIB_FILEFUNC_SEEK_END : + file_whence = kSbFileFromEnd; + break; + case ZLIB_FILEFUNC_SEEK_SET : + file_whence = kSbFileFromBegin; + break; + default: + return -1; + } + + if (file != NULL) { + if (SbFileSeek(file, file_whence, (int64_t)offset) != -1) { + ret = 0; + } + } + return ret; +} + +static long ZCALLBACK starboard_seek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { + long ret = -1; + SbFile file = NULL; + SbFileWhence file_whence = 0; + if (stream != NULL) { + file = (SbFile)stream; + } + switch (origin) { + case ZLIB_FILEFUNC_SEEK_CUR : + file_whence = kSbFileFromCurrent; + break; + case ZLIB_FILEFUNC_SEEK_END : + file_whence = kSbFileFromEnd; + break; + case ZLIB_FILEFUNC_SEEK_SET : + file_whence = kSbFileFromBegin; + break; + default: + return -1; + } + + if (file != NULL) { + if (SbFileSeek(file, file_whence, (int64_t)offset) != -1) { + ret = 0; + } + } + return ret; +} + +static int ZCALLBACK starboard_close_file_func (voidpf opaque, voidpf stream) { + int ret = -1; + SbFile file = NULL; + if (stream != NULL) { + file = (SbFile)stream; + } + if (file != NULL && SbFileClose(file)) { + ret = 0; + } + return ret; +} + +static int ZCALLBACK starboard_error_file_func (voidpf opaque, voidpf stream) { + // This function is NOOP because Starboard doesn't have a counterpart of ferror. Starboard sets + // the file error code in SbFileOpen, but zlib uses this function to get the file error code + // only after reading a file (SbFileRead), which doesn't set the error code anyways. + int ret = -1; + SbFile file = NULL; + if (stream != NULL) { + file = (SbFile)stream; + } + if (file != NULL) { + ret = 0; + } + return ret; +} + +void fill_starboard_filefunc (zlib_filefunc_def* pzlib_filefunc_def) { + pzlib_filefunc_def->zopen_file = starboard_open_file_func; + pzlib_filefunc_def->zread_file = starboard_read_file_func; + pzlib_filefunc_def->zwrite_file = starboard_write_file_func; + pzlib_filefunc_def->ztell_file = starboard_tell_file_func; + pzlib_filefunc_def->zseek_file = starboard_seek_file_func; + pzlib_filefunc_def->zclose_file = starboard_close_file_func; + pzlib_filefunc_def->zerror_file = starboard_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_starboard_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) { + pzlib_filefunc_def->zopen64_file = starboard_open64_file_func; + pzlib_filefunc_def->zread_file = starboard_read_file_func; + pzlib_filefunc_def->zwrite_file = starboard_write_file_func; + pzlib_filefunc_def->ztell64_file = starboard_tell64_file_func; + pzlib_filefunc_def->zseek64_file = starboard_seek64_file_func; + pzlib_filefunc_def->zclose_file = starboard_close_file_func; + pzlib_filefunc_def->zerror_file = starboard_error_file_func; + pzlib_filefunc_def->opaque = NULL; +}
diff --git a/src/third_party/zlib/contrib/minizip/iostarboard.h b/src/third_party/zlib/contrib/minizip/iostarboard.h new file mode 100644 index 0000000..f6bae39 --- /dev/null +++ b/src/third_party/zlib/contrib/minizip/iostarboard.h
@@ -0,0 +1,34 @@ +// Copyright 2019 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. + +// Starboard IO base function header for compress/uncompress .zip + +#ifndef _ZLIBIOSTARBOARD_H_ +#define _ZLIBIOSTARBOARD_H_ + +#include "ioapi.h" +#include "third_party/zlib/zlib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void fill_starboard_filefunc OF((zlib_filefunc_def * pzlib_filefunc_def)); +void fill_starboard_filefunc64 OF((zlib_filefunc64_def * pzlib_filefunc_def)); + +#ifdef __cplusplus +} +#endif + +#endif // _ZLIBIOSTARBOARD_H_
diff --git a/src/third_party/zlib/contrib/minizip/unzip.c b/src/third_party/zlib/contrib/minizip/unzip.c index 4289207..65e0c10 100644 --- a/src/third_party/zlib/contrib/minizip/unzip.c +++ b/src/third_party/zlib/contrib/minizip/unzip.c
@@ -122,6 +122,9 @@ #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) +#if defined(STARBOARD) +#include "third_party/zlib/contrib/minizip/iostarboard.h" +#endif const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; @@ -610,7 +613,11 @@ us.z_filefunc.zseek32_file = NULL; us.z_filefunc.ztell32_file = NULL; if (pzlib_filefunc64_32_def==NULL) +#if defined(STARBOARD) + fill_starboard_filefunc64(&us.z_filefunc.zfile_func64); +#else fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); +#endif else us.z_filefunc = *pzlib_filefunc64_32_def; us.is64bitOpenFunction = is64bitOpenFunction;
diff --git a/src/third_party/zlib/contrib/minizip/zip.c b/src/third_party/zlib/contrib/minizip/zip.c index 04c6b25..b269588 100644 --- a/src/third_party/zlib/contrib/minizip/zip.c +++ b/src/third_party/zlib/contrib/minizip/zip.c
@@ -25,7 +25,12 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#if defined(STARBOARD) +#include "starboard/client_porting/poem/eztime_poem.h" +#include "third_party/zlib/contrib/minizip/iostarboard.h" +#else #include <time.h> +#endif #if defined(USE_SYSTEM_ZLIB) #include <zlib.h> #else @@ -859,7 +864,11 @@ ziinit.z_filefunc.zseek32_file = NULL; ziinit.z_filefunc.ztell32_file = NULL; if (pzlib_filefunc64_32_def==NULL) +#if defined(STARBOARD) + fill_starboard_filefunc64(&ziinit.z_filefunc.zfile_func64); +#else fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); +#endif else ziinit.z_filefunc = *pzlib_filefunc64_32_def;
diff --git a/src/third_party/zlib/zlib.gyp b/src/third_party/zlib/zlib.gyp index 1136faa..d8bdf96 100644 --- a/src/third_party/zlib/zlib.gyp +++ b/src/third_party/zlib/zlib.gyp
@@ -93,6 +93,8 @@ 'sources': [ 'contrib/minizip/ioapi.c', 'contrib/minizip/ioapi.h', + 'contrib/minizip/iostarboard.c', + 'contrib/minizip/iostarboard.h', 'contrib/minizip/iowin32.c', 'contrib/minizip/iowin32.h', 'contrib/minizip/unzip.c', @@ -118,14 +120,6 @@ ['OS=="android"', { 'toolsets': ['target', 'host'], }], - ['OS=="starboard" or OS=="lb_shell"', { - # NOTE: This library is not used in Cobalt, so completely - # disabling it to prove it. If re-enabled, will have to be ported - # to Starboard. Alternatively, we could delete it from the repo. - 'sources/': [ - ['exclude', '.*'], - ], - }], ], }, { 'direct_dependent_settings': { @@ -162,6 +156,9 @@ ], }], ], + 'dependencies': [ + 'zlib', + ], } ], }
diff --git a/src/third_party/zlib2/BUILD.gn b/src/third_party/zlib2/BUILD.gn new file mode 100644 index 0000000..0f59c0a --- /dev/null +++ b/src/third_party/zlib2/BUILD.gn
@@ -0,0 +1,378 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/compiler/compiler.gni") + +if (current_cpu == "arm" || current_cpu == "arm64") { + import("//build/config/arm.gni") +} + +config("zlib_config") { + include_dirs = [ "." ] +} + +config("zlib_internal_config") { + defines = [ "ZLIB_IMPLEMENTATION" ] +} + +use_arm_neon_optimizations = false +if (current_cpu == "arm" || current_cpu == "arm64") { + if (arm_use_neon) { + use_arm_neon_optimizations = true + } +} + +use_x86_x64_optimizations = + (current_cpu == "x86" || current_cpu == "x64") && !is_ios + +config("zlib_adler32_simd_config") { + if (use_x86_x64_optimizations) { + defines = [ "ADLER32_SIMD_SSSE3" ] + } + + if (use_arm_neon_optimizations) { + defines = [ "ADLER32_SIMD_NEON" ] + } +} + +source_set("zlib_adler32_simd") { + visibility = [ ":*" ] + + if (use_x86_x64_optimizations) { + sources = [ + "adler32_simd.c", + "adler32_simd.h", + ] + + if (!is_win || is_clang) { + cflags = [ "-mssse3" ] + } + } + + if (use_arm_neon_optimizations) { + sources = [ + "adler32_simd.c", + "adler32_simd.h", + ] + if (!is_debug) { + # Use optimize_speed (-O3) to output the _smallest_ code. + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_speed" ] + } + } + + configs += [ ":zlib_internal_config" ] + + public_configs = [ ":zlib_adler32_simd_config" ] +} + +if (use_arm_neon_optimizations) { + config("zlib_arm_crc32_config") { + # Disabled for iPhone, as described in DDI0487C_a_armv8_arm: + # "All implementations of the ARMv8.1 architecture are required to + # implement the CRC32* instructions. These are optional in ARMv8.0." + if (!is_ios) { + defines = [ "CRC32_ARMV8_CRC32" ] + if (is_android) { + defines += [ "ARMV8_OS_ANDROID" ] + } else if (is_linux || is_chromeos) { + defines += [ "ARMV8_OS_LINUX" ] + } else if (is_fuchsia) { + defines += [ "ARMV8_OS_FUCHSIA" ] + } else if (is_win) { + defines += [ "ARMV8_OS_WINDOWS" ] + } else { + assert(false, "Unsupported ARM OS") + } + } + } + + source_set("zlib_arm_crc32") { + visibility = [ ":*" ] + + if (!is_ios) { + include_dirs = [ "." ] + + if (is_android) { + import("//build/config/android/config.gni") + if (defined(android_ndk_root) && android_ndk_root != "") { + deps = [ + "//third_party/android_ndk:cpu_features", + ] + } else { + assert(false, "CPU detection requires the Android NDK") + } + } else if (!is_win && !is_clang) { + assert(!use_thin_lto, + "ThinLTO fails mixing different module-level targets") + cflags_c = [ "-march=armv8-a+crc" ] + } + + sources = [ + "arm_features.c", + "arm_features.h", + "crc32_simd.c", + "crc32_simd.h", + ] + + if (!is_debug) { + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_speed" ] + } + } + + configs += [ ":zlib_internal_config" ] + + public_configs = [ ":zlib_arm_crc32_config" ] + } +} + +config("zlib_inflate_chunk_simd_config") { + if (use_x86_x64_optimizations) { + defines = [ "INFLATE_CHUNK_SIMD_SSE2" ] + + if (current_cpu == "x64") { + defines += [ "INFLATE_CHUNK_READ_64LE" ] + } + } + + if (use_arm_neon_optimizations) { + defines = [ "INFLATE_CHUNK_SIMD_NEON" ] + if (current_cpu == "arm64") { + defines += [ "INFLATE_CHUNK_READ_64LE" ] + } + } +} + +source_set("zlib_inflate_chunk_simd") { + visibility = [ ":*" ] + + if (use_x86_x64_optimizations || use_arm_neon_optimizations) { + include_dirs = [ "." ] + + sources = [ + "contrib/optimizations/chunkcopy.h", + "contrib/optimizations/inffast_chunk.c", + "contrib/optimizations/inffast_chunk.h", + "contrib/optimizations/inflate.c", + ] + + if (use_arm_neon_optimizations && !is_debug) { + # Here we trade better performance on newer/bigger ARMv8 cores + # for less perf on ARMv7, per crbug.com/772870#c40 + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_speed" ] + } + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":zlib_internal_config", + "//build/config/compiler:no_chromium_code", + ] + + public_configs = [ ":zlib_inflate_chunk_simd_config" ] +} + +config("zlib_crc32_simd_config") { + if (use_x86_x64_optimizations) { + defines = [ "CRC32_SIMD_SSE42_PCLMUL" ] + } +} + +source_set("zlib_crc32_simd") { + visibility = [ ":*" ] + + if (use_x86_x64_optimizations) { + sources = [ + "crc32_simd.c", + "crc32_simd.h", + ] + + if (!is_win || is_clang) { + cflags = [ + "-msse4.2", + "-mpclmul", + ] + } + } + + configs += [ ":zlib_internal_config" ] + + public_configs = [ ":zlib_crc32_simd_config" ] +} + +source_set("zlib_x86_simd") { + visibility = [ ":*" ] + + if (use_x86_x64_optimizations) { + sources = [ + "crc_folding.c", + "fill_window_sse.c", + ] + + if (!is_win || is_clang) { + cflags = [ + "-msse4.2", + "-mpclmul", + ] + } + } else { + sources = [ + "simd_stub.c", + ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":zlib_internal_config", + "//build/config/compiler:no_chromium_code", + ] +} + +config("zlib_warnings") { + if (is_clang && use_x86_x64_optimizations) { + cflags = [ "-Wno-incompatible-pointer-types" ] + } +} + +component("zlib") { + if (!is_win) { + # Don't stomp on "libzlib" on other platforms. + output_name = "chrome_zlib" + } + + sources = [ + "adler32.c", + "chromeconf.h", + "compress.c", + "crc32.c", + "crc32.h", + "deflate.c", + "deflate.h", + "gzclose.c", + "gzguts.h", + "gzlib.c", + "gzread.c", + "gzwrite.c", + "infback.c", + "inffast.c", + "inffast.h", + "inffixed.h", + "inflate.h", + "inftrees.c", + "inftrees.h", + "trees.c", + "trees.h", + "uncompr.c", + "x86.h", + "zconf.h", + "zlib.h", + "zutil.c", + "zutil.h", + ] + + defines = [] + deps = [] + + if (use_x86_x64_optimizations || use_arm_neon_optimizations) { + deps += [ + ":zlib_adler32_simd", + ":zlib_inflate_chunk_simd", + ] + + if (use_x86_x64_optimizations) { + sources += [ "x86.c" ] + deps += [ ":zlib_crc32_simd" ] + } else if (use_arm_neon_optimizations) { + sources += [ "contrib/optimizations/slide_hash_neon.h" ] + deps += [ ":zlib_arm_crc32" ] + } + } else { + sources += [ "inflate.c" ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + ":zlib_internal_config", + "//build/config/compiler:no_chromium_code", + + # Must be after no_chromium_code for warning flags to be ordered correctly. + ":zlib_warnings", + ] + + public_configs = [ ":zlib_config" ] + + deps += [ ":zlib_x86_simd" ] + allow_circular_includes_from = deps +} + +config("minizip_warnings") { + visibility = [ ":*" ] + + if (is_clang) { + # zlib uses `if ((a == b))` for some reason. + cflags = [ "-Wno-parentheses-equality" ] + } +} + +static_library("minizip") { + sources = [ + "contrib/minizip/ioapi.c", + "contrib/minizip/ioapi.h", + "contrib/minizip/iowin32.c", + "contrib/minizip/iowin32.h", + "contrib/minizip/unzip.c", + "contrib/minizip/unzip.h", + "contrib/minizip/zip.c", + "contrib/minizip/zip.h", + ] + + if (!is_win) { + sources -= [ + "contrib/minizip/iowin32.c", + "contrib/minizip/iowin32.h", + ] + } + + if (is_mac || is_ios || is_android || is_nacl) { + # Mac, Android and the BSDs don't have fopen64, ftello64, or fseeko64. We + # use fopen, ftell, and fseek instead on these systems. + defines = [ "USE_FILE32API" ] + } + + deps = [ + ":zlib", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + "//build/config/compiler:no_chromium_code", + + # Must be after no_chromium_code for warning flags to be ordered correctly. + ":minizip_warnings", + ] + + public_configs = [ ":zlib_config" ] +} + +executable("zlib_bench") { + include_dirs = [ "." ] + + sources = [ + "contrib/bench/zlib_bench.cc", + ] + + if (!is_debug) { + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_speed" ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + deps = [ + ":zlib", + ] +}
diff --git a/src/third_party/zlib2/LICENSE b/src/third_party/zlib2/LICENSE new file mode 100644 index 0000000..9f05686 --- /dev/null +++ b/src/third_party/zlib2/LICENSE
@@ -0,0 +1,19 @@ +version 1.2.11, January 15th, 2017 + +Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution.
diff --git a/src/third_party/zlib2/README.chromium b/src/third_party/zlib2/README.chromium new file mode 100644 index 0000000..3d90f79 --- /dev/null +++ b/src/third_party/zlib2/README.chromium
@@ -0,0 +1,28 @@ +Name: zlib +Short Name: zlib +URL: http://zlib.net/ +Version: 1.2.11 +Security Critical: yes +License: Custom license +License File: LICENSE +License Android Compatible: yes + +Description: +"A massively spiffy yet delicately unobtrusive compression library." + +zlib is a free, general-purpose, legally unencumbered lossless data-compression +library. zlib implements the "deflate" compression algorithm described by RFC +1951, which combines the LZ77 (Lempel-Ziv) algorithm with Huffman coding. zlib +also implements the zlib (RFC 1950) and gzip (RFC 1952) wrapper formats. + +Local Modifications: + - Only source code from the zlib distribution used to build the zlib and + minizip libraries are present. Many other files have been omitted. Only *.c + and *.h files from the upstream root directory and contrib/minizip were + imported. + - The contents of the google directory are original Chromium-specific + additions. + - Added chromeconf.h + - Plus the changes in 'patches' folder. + - Code in contrib/ other than contrib/minizip was added to match zlib's + contributor layout.
diff --git a/src/third_party/zlib2/adler32.c b/src/third_party/zlib2/adler32.c new file mode 100644 index 0000000..a42f35f --- /dev/null +++ b/src/third_party/zlib2/adler32.c
@@ -0,0 +1,216 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + +#define BASE 65521U /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + +#if defined(ADLER32_SIMD_SSSE3) +#include "adler32_simd.h" +#include "x86.h" +#elif defined(ADLER32_SIMD_NEON) +#include "adler32_simd.h" +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32_z(adler, buf, len) + uLong adler; + const Bytef *buf; + z_size_t len; +{ + unsigned long sum2; + unsigned n; + +#if defined(ADLER32_SIMD_SSSE3) + if (x86_cpu_enable_ssse3 && buf && len >= 64) + return adler32_simd_(adler, buf, len); +#elif defined(ADLER32_SIMD_NEON) + if (buf && len >= 64) + return adler32_simd_(adler, buf, len); +#endif + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + +#if defined(ADLER32_SIMD_SSSE3) + /* + * Use SSSE3 to compute the adler32. Since this routine can be + * freely used, check CPU features here. zlib convention is to + * call adler32(0, NULL, 0), before making calls to adler32(). + * So this is a good early (and infrequent) place to cache CPU + * features for those later, more interesting adler32() calls. + */ + if (buf == Z_NULL) { + if (!len) /* Assume user is calling adler32(0, NULL, 0); */ + x86_check_features(); + return 1L; + } +#else + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; +#endif + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +}
diff --git a/src/third_party/zlib2/adler32_simd.c b/src/third_party/zlib2/adler32_simd.c new file mode 100644 index 0000000..1354915 --- /dev/null +++ b/src/third_party/zlib2/adler32_simd.c
@@ -0,0 +1,366 @@ +/* adler32_simd.c + * + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + * + * Per http://en.wikipedia.org/wiki/Adler-32 the adler32 A value (aka s1) is + * the sum of N input data bytes D1 ... DN, + * + * A = A0 + D1 + D2 + ... + DN + * + * where A0 is the initial value. + * + * SSE2 _mm_sad_epu8() can be used for byte sums (see http://bit.ly/2wpUOeD, + * for example) and accumulating the byte sums can use SSE shuffle-adds (see + * the "Integer" section of http://bit.ly/2erPT8t for details). Arm NEON has + * similar instructions. + * + * The adler32 B value (aka s2) sums the A values from each step: + * + * B0 + (A0 + D1) + (A0 + D1 + D2) + ... + (A0 + D1 + D2 + ... + DN) or + * + * B0 + N.A0 + N.D1 + (N-1).D2 + (N-2).D3 + ... + (N-(N-1)).DN + * + * B0 being the initial value. For 32 bytes (ideal for garden-variety SIMD): + * + * B = B0 + 32.A0 + [D1 D2 D3 ... D32] x [32 31 30 ... 1]. + * + * Adjacent blocks of 32 input bytes can be iterated with the expressions to + * compute the adler32 s1 s2 of M >> 32 input bytes [1]. + * + * As M grows, the s1 s2 sums grow. If left unchecked, they would eventually + * overflow the precision of their integer representation (bad). However, s1 + * and s2 also need to be computed modulo the adler BASE value (reduced). If + * at most NMAX bytes are processed before a reduce, s1 s2 _cannot_ overflow + * a uint32_t type (the NMAX constraint) [2]. + * + * [1] the iterative equations for s2 contain constant factors; these can be + * hoisted from the n-blocks do loop of the SIMD code. + * + * [2] zlib adler32_z() uses this fact to implement NMAX-block-based updates + * of the adler s1 s2 of uint32_t type (see adler32.c). + */ + +#include "adler32_simd.h" + +/* Definitions from adler32.c: largest prime smaller than 65536 */ +#define BASE 65521U +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ +#define NMAX 5552 + +#if defined(ADLER32_SIMD_SSSE3) + +#include <tmmintrin.h> + +uint32_t ZLIB_INTERNAL adler32_simd_( /* SSSE3 */ + uint32_t adler, + const unsigned char *buf, + z_size_t len) +{ + /* + * Split Adler-32 into component sums. + */ + uint32_t s1 = adler & 0xffff; + uint32_t s2 = adler >> 16; + + /* + * Process the data in blocks. + */ + const unsigned BLOCK_SIZE = 1 << 5; + + z_size_t blocks = len / BLOCK_SIZE; + len -= blocks * BLOCK_SIZE; + + while (blocks) + { + unsigned n = NMAX / BLOCK_SIZE; /* The NMAX constraint. */ + if (n > blocks) + n = (unsigned) blocks; + blocks -= n; + + const __m128i tap1 = + _mm_setr_epi8(32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17); + const __m128i tap2 = + _mm_setr_epi8(16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i zero = + _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + const __m128i ones = + _mm_set_epi16( 1, 1, 1, 1, 1, 1, 1, 1); + + /* + * Process n blocks of data. At most NMAX data bytes can be + * processed before s2 must be reduced modulo BASE. + */ + __m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n); + __m128i v_s2 = _mm_set_epi32(0, 0, 0, s2); + __m128i v_s1 = _mm_set_epi32(0, 0, 0, 0); + + do { + /* + * Load 32 input bytes. + */ + const __m128i bytes1 = _mm_loadu_si128((__m128i*)(buf)); + const __m128i bytes2 = _mm_loadu_si128((__m128i*)(buf + 16)); + + /* + * Add previous block byte sum to v_ps. + */ + v_ps = _mm_add_epi32(v_ps, v_s1); + + /* + * Horizontally add the bytes for s1, multiply-adds the + * bytes by [ 32, 31, 30, ... ] for s2. + */ + v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero)); + const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1); + v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones)); + + v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero)); + const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2); + v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones)); + + buf += BLOCK_SIZE; + + } while (--n); + + v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5)); + + /* + * Sum epi32 ints v_s1(s2) and accumulate in s1(s2). + */ + +#define S23O1 _MM_SHUFFLE(2,3,0,1) /* A B C D -> B A D C */ +#define S1O32 _MM_SHUFFLE(1,0,3,2) /* A B C D -> C D A B */ + + v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S23O1)); + v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S1O32)); + + s1 += _mm_cvtsi128_si32(v_s1); + + v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S23O1)); + v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S1O32)); + + s2 = _mm_cvtsi128_si32(v_s2); + +#undef S23O1 +#undef S1O32 + + /* + * Reduce. + */ + s1 %= BASE; + s2 %= BASE; + } + + /* + * Handle leftover data. + */ + if (len) { + if (len >= 16) { + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + len -= 16; + } + + while (len--) { + s2 += (s1 += *buf++); + } + + if (s1 >= BASE) + s1 -= BASE; + s2 %= BASE; + } + + /* + * Return the recombined sums. + */ + return s1 | (s2 << 16); +} + +#elif defined(ADLER32_SIMD_NEON) + +#include <arm_neon.h> + +uint32_t ZLIB_INTERNAL adler32_simd_( /* NEON */ + uint32_t adler, + const unsigned char *buf, + z_size_t len) +{ + /* + * Split Adler-32 into component sums. + */ + uint32_t s1 = adler & 0xffff; + uint32_t s2 = adler >> 16; + + /* + * Serially compute s1 & s2, until the data is 16-byte aligned. + */ + if ((uintptr_t)buf & 15) { + while ((uintptr_t)buf & 15) { + s2 += (s1 += *buf++); + --len; + } + + if (s1 >= BASE) + s1 -= BASE; + s2 %= BASE; + } + + /* + * Process the data in blocks. + */ + const unsigned BLOCK_SIZE = 1 << 5; + + z_size_t blocks = len / BLOCK_SIZE; + len -= blocks * BLOCK_SIZE; + + while (blocks) + { + unsigned n = NMAX / BLOCK_SIZE; /* The NMAX constraint. */ + if (n > blocks) + n = (unsigned) blocks; + blocks -= n; + + /* + * Process n blocks of data. At most NMAX data bytes can be + * processed before s2 must be reduced modulo BASE. + */ + uint32x4_t v_s2 = (uint32x4_t) { 0, 0, 0, s1 * n }; + uint32x4_t v_s1 = (uint32x4_t) { 0, 0, 0, 0 }; + + uint16x8_t v_column_sum_1 = vdupq_n_u16(0); + uint16x8_t v_column_sum_2 = vdupq_n_u16(0); + uint16x8_t v_column_sum_3 = vdupq_n_u16(0); + uint16x8_t v_column_sum_4 = vdupq_n_u16(0); + + do { + /* + * Load 32 input bytes. + */ + const uint8x16_t bytes1 = vld1q_u8((uint8_t*)(buf)); + const uint8x16_t bytes2 = vld1q_u8((uint8_t*)(buf + 16)); + + /* + * Add previous block byte sum to v_s2. + */ + v_s2 = vaddq_u32(v_s2, v_s1); + + /* + * Horizontally add the bytes for s1. + */ + v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2)); + + /* + * Vertically add the bytes for s2. + */ + v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8 (bytes1)); + v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1)); + v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8 (bytes2)); + v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2)); + + buf += BLOCK_SIZE; + + } while (--n); + + v_s2 = vshlq_n_u32(v_s2, 5); + + /* + * Multiply-add bytes by [ 32, 31, 30, ... ] for s2. + */ + v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_1), + (uint16x4_t) { 32, 31, 30, 29 }); + v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_1), + (uint16x4_t) { 28, 27, 26, 25 }); + v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_2), + (uint16x4_t) { 24, 23, 22, 21 }); + v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_2), + (uint16x4_t) { 20, 19, 18, 17 }); + v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_3), + (uint16x4_t) { 16, 15, 14, 13 }); + v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_3), + (uint16x4_t) { 12, 11, 10, 9 }); + v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_4), + (uint16x4_t) { 8, 7, 6, 5 }); + v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_4), + (uint16x4_t) { 4, 3, 2, 1 }); + + /* + * Sum epi32 ints v_s1(s2) and accumulate in s1(s2). + */ + uint32x2_t sum1 = vpadd_u32(vget_low_u32(v_s1), vget_high_u32(v_s1)); + uint32x2_t sum2 = vpadd_u32(vget_low_u32(v_s2), vget_high_u32(v_s2)); + uint32x2_t s1s2 = vpadd_u32(sum1, sum2); + + s1 += vget_lane_u32(s1s2, 0); + s2 += vget_lane_u32(s1s2, 1); + + /* + * Reduce. + */ + s1 %= BASE; + s2 %= BASE; + } + + /* + * Handle leftover data. + */ + if (len) { + if (len >= 16) { + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + s2 += (s1 += *buf++); + + len -= 16; + } + + while (len--) { + s2 += (s1 += *buf++); + } + + if (s1 >= BASE) + s1 -= BASE; + s2 %= BASE; + } + + /* + * Return the recombined sums. + */ + return s1 | (s2 << 16); +} + +#endif /* ADLER32_SIMD_SSSE3 */
diff --git a/src/third_party/zlib2/adler32_simd.h b/src/third_party/zlib2/adler32_simd.h new file mode 100644 index 0000000..52bb14d --- /dev/null +++ b/src/third_party/zlib2/adler32_simd.h
@@ -0,0 +1,16 @@ +/* adler32_simd.h + * + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include <stdint.h> + +#include "zconf.h" +#include "zutil.h" + +uint32_t ZLIB_INTERNAL adler32_simd_( + uint32_t adler, + const unsigned char *buf, + z_size_t len);
diff --git a/src/third_party/zlib2/arm_features.c b/src/third_party/zlib2/arm_features.c new file mode 100644 index 0000000..f5641c3 --- /dev/null +++ b/src/third_party/zlib2/arm_features.c
@@ -0,0 +1,90 @@ +/* arm_features.c -- ARM processor features detection. + * + * Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include "arm_features.h" +#include "zutil.h" +#include <stdint.h> + +int ZLIB_INTERNAL arm_cpu_enable_crc32 = 0; +int ZLIB_INTERNAL arm_cpu_enable_pmull = 0; + +#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA) +#include <pthread.h> +#endif + +#if defined(ARMV8_OS_ANDROID) +#include <cpu-features.h> +#elif defined(ARMV8_OS_LINUX) +#include <asm/hwcap.h> +#include <sys/auxv.h> +#elif defined(ARMV8_OS_FUCHSIA) +#include <zircon/features.h> +#include <zircon/syscalls.h> +#include <zircon/types.h> +#elif defined(ARMV8_OS_WINDOWS) +#include <windows.h> +#else +#error arm_features.c ARM feature detection in not defined for your platform +#endif + +static void _arm_check_features(void); + +#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA) +static pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT; +void ZLIB_INTERNAL arm_check_features(void) +{ + pthread_once(&cpu_check_inited_once, _arm_check_features); +} +#elif defined(ARMV8_OS_WINDOWS) +static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT; +static BOOL CALLBACK _arm_check_features_forwarder(PINIT_ONCE once, PVOID param, PVOID* context) +{ + _arm_check_features(); + return TRUE; +} +void ZLIB_INTERNAL arm_check_features(void) +{ + InitOnceExecuteOnce(&cpu_check_inited_once, _arm_check_features_forwarder, + NULL, NULL); +} +#endif + +/* + * See http://bit.ly/2CcoEsr for run-time detection of ARM features and also + * crbug.com/931275 for android_getCpuFeatures() use in the Android sandbox. + */ +static void _arm_check_features(void) +{ +#if defined(ARMV8_OS_ANDROID) && defined(__aarch64__) + uint64_t features = android_getCpuFeatures(); + arm_cpu_enable_crc32 = !!(features & ANDROID_CPU_ARM64_FEATURE_CRC32); + arm_cpu_enable_pmull = !!(features & ANDROID_CPU_ARM64_FEATURE_PMULL); +#elif defined(ARMV8_OS_ANDROID) /* aarch32 */ + uint64_t features = android_getCpuFeatures(); + arm_cpu_enable_crc32 = !!(features & ANDROID_CPU_ARM_FEATURE_CRC32); + arm_cpu_enable_pmull = !!(features & ANDROID_CPU_ARM_FEATURE_PMULL); +#elif defined(ARMV8_OS_LINUX) && defined(__aarch64__) + unsigned long features = getauxval(AT_HWCAP); + arm_cpu_enable_crc32 = !!(features & HWCAP_CRC32); + arm_cpu_enable_pmull = !!(features & HWCAP_PMULL); +#elif defined(ARMV8_OS_LINUX) && (defined(__ARM_NEON) || defined(__ARM_NEON__)) + /* Query HWCAP2 for ARMV8-A SoCs running in aarch32 mode */ + unsigned long features = getauxval(AT_HWCAP2); + arm_cpu_enable_crc32 = !!(features & HWCAP2_CRC32); + arm_cpu_enable_pmull = !!(features & HWCAP2_PMULL); +#elif defined(ARMV8_OS_FUCHSIA) + uint32_t features; + zx_status_t rc = zx_system_get_features(ZX_FEATURE_KIND_CPU, &features); + if (rc != ZX_OK || (features & ZX_ARM64_FEATURE_ISA_ASIMD) == 0) + return; /* Report nothing if ASIMD(NEON) is missing */ + arm_cpu_enable_crc32 = !!(features & ZX_ARM64_FEATURE_ISA_CRC32); + arm_cpu_enable_pmull = !!(features & ZX_ARM64_FEATURE_ISA_PMULL); +#elif defined(ARMV8_OS_WINDOWS) + arm_cpu_enable_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); + arm_cpu_enable_pmull = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE); +#endif +}
diff --git a/src/third_party/zlib2/arm_features.h b/src/third_party/zlib2/arm_features.h new file mode 100644 index 0000000..09fec25 --- /dev/null +++ b/src/third_party/zlib2/arm_features.h
@@ -0,0 +1,13 @@ +/* arm_features.h -- ARM processor features detection. + * + * Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include "zlib.h" + +extern int arm_cpu_enable_crc32; +extern int arm_cpu_enable_pmull; + +void arm_check_features(void);
diff --git a/src/third_party/zlib2/chromeconf.h b/src/third_party/zlib2/chromeconf.h new file mode 100644 index 0000000..666093d --- /dev/null +++ b/src/third_party/zlib2/chromeconf.h
@@ -0,0 +1,195 @@ +/* Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#ifndef THIRD_PARTY_ZLIB_CHROMECONF_H_ +#define THIRD_PARTY_ZLIB_CHROMECONF_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) +#if defined(ZLIB_IMPLEMENTATION) +#define ZEXTERN __declspec(dllexport) +#else +#define ZEXTERN __declspec(dllimport) +#endif +#elif defined(ZLIB_IMPLEMENTATION) +#define ZEXTERN __attribute__((visibility("default"))) +#endif +#endif + +/* Rename all zlib names with a Cr_z_ prefix. This is based on the Z_PREFIX + * option from zconf.h, but with a custom prefix. Where zconf.h would rename + * both a macro and its underscore-suffixed internal implementation (such as + * deflateInit2 and deflateInit2_), only the implementation is renamed here. + * The Byte type is also omitted. + * + * To generate this list, run + * sed -rn -e 's/^# *define +([^ ]+) +(z_[^ ]+)$/#define \1 Cr_\2/p' zconf.h + * (use -E instead of -r on macOS). + * + * gzread is also addressed by modifications in gzread.c and zlib.h. */ + +#define Z_CR_PREFIX_SET + +#define _dist_code Cr_z__dist_code +#define _length_code Cr_z__length_code +#define _tr_align Cr_z__tr_align +#define _tr_flush_bits Cr_z__tr_flush_bits +#define _tr_flush_block Cr_z__tr_flush_block +#define _tr_init Cr_z__tr_init +#define _tr_stored_block Cr_z__tr_stored_block +#define _tr_tally Cr_z__tr_tally +#define adler32 Cr_z_adler32 +#define adler32_combine Cr_z_adler32_combine +#define adler32_combine64 Cr_z_adler32_combine64 +#define adler32_z Cr_z_adler32_z +#define compress Cr_z_compress +#define compress2 Cr_z_compress2 +#define compressBound Cr_z_compressBound +#define crc32 Cr_z_crc32 +#define crc32_combine Cr_z_crc32_combine +#define crc32_combine64 Cr_z_crc32_combine64 +#define crc32_z Cr_z_crc32_z +#define deflate Cr_z_deflate +#define deflateBound Cr_z_deflateBound +#define deflateCopy Cr_z_deflateCopy +#define deflateEnd Cr_z_deflateEnd +#define deflateGetDictionary Cr_z_deflateGetDictionary +/* #undef deflateInit */ +/* #undef deflateInit2 */ +#define deflateInit2_ Cr_z_deflateInit2_ +#define deflateInit_ Cr_z_deflateInit_ +#define deflateParams Cr_z_deflateParams +#define deflatePending Cr_z_deflatePending +#define deflatePrime Cr_z_deflatePrime +#define deflateReset Cr_z_deflateReset +#define deflateResetKeep Cr_z_deflateResetKeep +#define deflateSetDictionary Cr_z_deflateSetDictionary +#define deflateSetHeader Cr_z_deflateSetHeader +#define deflateTune Cr_z_deflateTune +#define deflate_copyright Cr_z_deflate_copyright +#define get_crc_table Cr_z_get_crc_table +#define gz_error Cr_z_gz_error +#define gz_intmax Cr_z_gz_intmax +#define gz_strwinerror Cr_z_gz_strwinerror +#define gzbuffer Cr_z_gzbuffer +#define gzclearerr Cr_z_gzclearerr +#define gzclose Cr_z_gzclose +#define gzclose_r Cr_z_gzclose_r +#define gzclose_w Cr_z_gzclose_w +#define gzdirect Cr_z_gzdirect +#define gzdopen Cr_z_gzdopen +#define gzeof Cr_z_gzeof +#define gzerror Cr_z_gzerror +#define gzflush Cr_z_gzflush +#define gzfread Cr_z_gzfread +#define gzfwrite Cr_z_gzfwrite +#define gzgetc Cr_z_gzgetc +#define gzgetc_ Cr_z_gzgetc_ +#define gzgets Cr_z_gzgets +#define gzoffset Cr_z_gzoffset +#define gzoffset64 Cr_z_gzoffset64 +#define gzopen Cr_z_gzopen +#define gzopen64 Cr_z_gzopen64 +#define gzopen_w Cr_z_gzopen_w +#define gzprintf Cr_z_gzprintf +#define gzputc Cr_z_gzputc +#define gzputs Cr_z_gzputs +#define gzread Cr_z_gzread +#define gzrewind Cr_z_gzrewind +#define gzseek Cr_z_gzseek +#define gzseek64 Cr_z_gzseek64 +#define gzsetparams Cr_z_gzsetparams +#define gztell Cr_z_gztell +#define gztell64 Cr_z_gztell64 +#define gzungetc Cr_z_gzungetc +#define gzvprintf Cr_z_gzvprintf +#define gzwrite Cr_z_gzwrite +#define inflate Cr_z_inflate +#define inflateBack Cr_z_inflateBack +#define inflateBackEnd Cr_z_inflateBackEnd +/* #undef inflateBackInit */ +#define inflateBackInit_ Cr_z_inflateBackInit_ +#define inflateCodesUsed Cr_z_inflateCodesUsed +#define inflateCopy Cr_z_inflateCopy +#define inflateEnd Cr_z_inflateEnd +#define inflateGetDictionary Cr_z_inflateGetDictionary +#define inflateGetHeader Cr_z_inflateGetHeader +/* #undef inflateInit */ +/* #undef inflateInit2 */ +#define inflateInit2_ Cr_z_inflateInit2_ +#define inflateInit_ Cr_z_inflateInit_ +#define inflateMark Cr_z_inflateMark +#define inflatePrime Cr_z_inflatePrime +#define inflateReset Cr_z_inflateReset +#define inflateReset2 Cr_z_inflateReset2 +#define inflateResetKeep Cr_z_inflateResetKeep +#define inflateSetDictionary Cr_z_inflateSetDictionary +#define inflateSync Cr_z_inflateSync +#define inflateSyncPoint Cr_z_inflateSyncPoint +#define inflateUndermine Cr_z_inflateUndermine +#define inflateValidate Cr_z_inflateValidate +#define inflate_copyright Cr_z_inflate_copyright +#define inflate_fast Cr_z_inflate_fast +#define inflate_table Cr_z_inflate_table +#define uncompress Cr_z_uncompress +#define uncompress2 Cr_z_uncompress2 +#define zError Cr_z_zError +#define zcalloc Cr_z_zcalloc +#define zcfree Cr_z_zcfree +#define zlibCompileFlags Cr_z_zlibCompileFlags +#define zlibVersion Cr_z_zlibVersion +/* #undef Byte */ +#define Bytef Cr_z_Bytef +#define alloc_func Cr_z_alloc_func +#define charf Cr_z_charf +#define free_func Cr_z_free_func +#define gzFile Cr_z_gzFile +#define gz_header Cr_z_gz_header +#define gz_headerp Cr_z_gz_headerp +#define in_func Cr_z_in_func +#define intf Cr_z_intf +#define out_func Cr_z_out_func +#define uInt Cr_z_uInt +#define uIntf Cr_z_uIntf +#define uLong Cr_z_uLong +#define uLongf Cr_z_uLongf +#define voidp Cr_z_voidp +#define voidpc Cr_z_voidpc +#define voidpf Cr_z_voidpf +#define gz_header_s Cr_z_gz_header_s +/* #undef internal_state */ +/* #undef z_off64_t */ + +/* An exported symbol that isn't handled by Z_PREFIX in zconf.h */ +#define z_errmsg Cr_z_z_errmsg + +/* Symbols added in simd.patch */ +#define copy_with_crc Cr_z_copy_with_crc +#define crc_finalize Cr_z_crc_finalize +#define crc_fold_512to32 Cr_z_crc_fold_512to32 +#define crc_fold_copy Cr_z_crc_fold_copy +#define crc_fold_init Cr_z_crc_fold_init +#define crc_reset Cr_z_crc_reset +#define fill_window_sse Cr_z_fill_window_sse +#define deflate_read_buf Cr_z_deflate_read_buf +#define x86_check_features Cr_z_x86_check_features +#define x86_cpu_enable_simd Cr_z_x86_cpu_enable_simd + +/* Symbols added by adler_simd.c */ +#define adler32_simd_ Cr_z_adler32_simd_ +#define x86_cpu_enable_ssse3 Cr_z_x86_cpu_enable_ssse3 + +/* Symbols added by contrib/optimizations/inffast_chunk */ +#define inflate_fast_chunk_ Cr_z_inflate_fast_chunk_ + +/* Symbols added by crc32_simd.c */ +#define crc32_sse42_simd_ Cr_z_crc32_sse42_simd_ + +/* Symbols added by armv8_crc32 */ +#define arm_cpu_enable_crc32 Cr_z_arm_cpu_enable_crc32 +#define arm_cpu_enable_pmull Cr_z_arm_cpu_enable_pmull +#define arm_check_features Cr_z_arm_check_features +#define armv8_crc32_little Cr_z_armv8_crc32_little + +#endif /* THIRD_PARTY_ZLIB_CHROMECONF_H_ */
diff --git a/src/third_party/zlib2/compress.c b/src/third_party/zlib2/compress.c new file mode 100644 index 0000000..6e85173 --- /dev/null +++ b/src/third_party/zlib2/compress.c
@@ -0,0 +1,96 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + const uInt max = (uInt)-1; + uLong left; + + left = *destLen; + *destLen = 0; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + stream.next_out = dest; + stream.avail_out = 0; + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; + sourceLen -= stream.avail_in; + } + err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); + } while (err == Z_OK); + + *destLen = stream.total_out; + deflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + sourceLen = sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; + /* FIXME(cavalcantii): usage of CRC32 Castagnoli as a hash function + * for the hash table of symbols used for compression has a side effect + * where for compression level [4, 5] it will increase the output buffer size + * by 0.1% (i.e. less than 1%) for a high entropy input (i.e. random data). + * To avoid a scenario where client code would fail, for safety we increase + * the expected output size by 0.8% (i.e. 8x more than the worst scenario). + * See: http://crbug.com/990489 + */ + sourceLen += sourceLen >> 7; // Equivalent to 1.0078125 + return sourceLen; +}
diff --git a/src/third_party/zlib2/contrib/bench/zlib_bench.cc b/src/third_party/zlib2/contrib/bench/zlib_bench.cc new file mode 100644 index 0000000..5dcdef0 --- /dev/null +++ b/src/third_party/zlib2/contrib/bench/zlib_bench.cc
@@ -0,0 +1,316 @@ +/* + * Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + * + * A benchmark test harness for measuring decoding performance of gzip or zlib + * (deflate) encoded compressed data. Given a file containing any data, encode + * (compress) it into gzip or zlib format and then decode (uncompress). Output + * the median and maximum encoding and decoding rates in MB/s. + * + * Raw deflate (no gzip or zlib stream wrapper) mode is also supported. Select + * it with the [raw] argument. Use the [gzip] [zlib] arguments to select those + * stream wrappers. + * + * Note this code can be compiled outside of the Chromium build system against + * the system zlib (-lz) with g++ or clang++ as follows: + * + * g++|clang++ -O3 -Wall -std=c++11 -lstdc++ -lz zlib_bench.cc + */ + +#include <algorithm> +#include <chrono> +#include <fstream> +#include <memory> +#include <string> +#include <vector> + +#include <memory.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include "zlib.h" + +void error_exit(const char* error, int code) { + fprintf(stderr, "%s (%d)\n", error, code); + exit(code); +} + +inline char* string_data(std::string* s) { + return s->empty() ? 0 : &*s->begin(); +} + +struct Data { + Data(size_t s) { data.reset(new (std::nothrow) char[size = s]); } + std::unique_ptr<char[]> data; + size_t size; +}; + +Data read_file_data_or_exit(const char* name) { + std::ifstream file(name, std::ios::in | std::ios::binary); + if (!file) { + perror(name); + exit(1); + } + + file.seekg(0, std::ios::end); + Data data(file.tellg()); + file.seekg(0, std::ios::beg); + + if (file && data.data) + file.read(data.data.get(), data.size); + + if (!file || !data.data || !data.size) { + perror((std::string("failed: reading ") + name).c_str()); + exit(1); + } + + return data; +} + +size_t zlib_estimate_compressed_size(size_t input_size) { + return compressBound(input_size); +} + +enum zlib_wrapper { + kWrapperNONE, + kWrapperZLIB, + kWrapperGZIP, + kWrapperZRAW, +}; + +inline int zlib_stream_wrapper_type(zlib_wrapper type) { + if (type == kWrapperZLIB) // zlib DEFLATE stream wrapper + return MAX_WBITS; + if (type == kWrapperGZIP) // gzip DEFLATE stream wrapper + return MAX_WBITS + 16; + if (type == kWrapperZRAW) // no wrapper, use raw DEFLATE + return -MAX_WBITS; + error_exit("bad wrapper type", int(type)); + return 0; +} + +const char* zlib_wrapper_name(zlib_wrapper type) { + if (type == kWrapperZLIB) + return "ZLIB"; + if (type == kWrapperGZIP) + return "GZIP"; + if (type == kWrapperZRAW) + return "RAW"; + error_exit("bad wrapper type", int(type)); + return 0; +} + +static int zlib_compression_level; + +void zlib_compress( + const zlib_wrapper type, + const char* input, + const size_t input_size, + std::string* output, + bool resize_output = false) +{ + if (resize_output) + output->resize(zlib_estimate_compressed_size(input_size)); + size_t output_size = output->size(); + + z_stream stream; + memset(&stream, 0, sizeof(stream)); + + int result = deflateInit2(&stream, zlib_compression_level, Z_DEFLATED, + zlib_stream_wrapper_type(type), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); + if (result != Z_OK) + error_exit("deflateInit2 failed", result); + + stream.next_out = (Bytef*)string_data(output); + stream.avail_out = (uInt)output_size; + stream.next_in = (z_const Bytef*)input; + stream.avail_in = (uInt)input_size; + + result = deflate(&stream, Z_FINISH); + if (result == Z_STREAM_END) + output_size = stream.total_out; + result |= deflateEnd(&stream); + if (result != Z_STREAM_END) + error_exit("compress failed", result); + + if (resize_output) + output->resize(output_size); +} + +void zlib_uncompress( + const zlib_wrapper type, + const std::string& input, + const size_t output_size, + std::string* output) +{ + z_stream stream; + memset(&stream, 0, sizeof(stream)); + + int result = inflateInit2(&stream, zlib_stream_wrapper_type(type)); + if (result != Z_OK) + error_exit("inflateInit2 failed", result); + + stream.next_out = (Bytef*)string_data(output); + stream.avail_out = (uInt)output->size(); + stream.next_in = (z_const Bytef*)input.data(); + stream.avail_in = (uInt)input.size(); + + result = inflate(&stream, Z_FINISH); + if (stream.total_out != output_size) + result = Z_DATA_ERROR; + result |= inflateEnd(&stream); + if (result == Z_STREAM_END) + return; + + std::string error("uncompress failed: "); + if (stream.msg) + error.append(stream.msg); + error_exit(error.c_str(), result); +} + +void verify_equal(const char* input, size_t size, std::string* output) { + const char* data = string_data(output); + if (output->size() == size && !memcmp(data, input, size)) + return; + fprintf(stderr, "uncompressed data does not match the input data\n"); + exit(3); +} + +void zlib_file(const char* name, const zlib_wrapper type) { + /* + * Read the file data. + */ + const auto file = read_file_data_or_exit(name); + const int length = static_cast<int>(file.size); + const char* data = file.data.get(); + printf("%-40s :\n", name); + + /* + * Chop the data into blocks. + */ + const int block_size = 1 << 20; + const int blocks = (length + block_size - 1) / block_size; + + std::vector<const char*> input(blocks); + std::vector<size_t> input_length(blocks); + std::vector<std::string> compressed(blocks); + std::vector<std::string> output(blocks); + + for (int b = 0; b < blocks; ++b) { + int input_start = b * block_size; + int input_limit = std::min<int>((b + 1) * block_size, length); + input[b] = data + input_start; + input_length[b] = input_limit - input_start; + } + + /* + * Run the zlib compress/uncompress loop a few times with |repeats| to + * process about 10MB of data if the length is small relative to 10MB. + * If length is large relative to 10MB, process the data once. + */ + const int mega_byte = 1024 * 1024; + const int repeats = (10 * mega_byte + length) / (length + 1); + const int runs = 5; + double ctime[runs]; + double utime[runs]; + + for (int run = 0; run < runs; ++run) { + const auto now = [] { return std::chrono::steady_clock::now(); }; + + // Pre-grow the output buffer so we don't measure string resize time. + for (int b = 0; b < blocks; ++b) + compressed[b].resize(zlib_estimate_compressed_size(block_size)); + + auto start = now(); + for (int b = 0; b < blocks; ++b) + for (int r = 0; r < repeats; ++r) + zlib_compress(type, input[b], input_length[b], &compressed[b]); + ctime[run] = std::chrono::duration<double>(now() - start).count(); + + // Compress again, resizing compressed, so we don't leave junk at the + // end of the compressed string that could confuse zlib_uncompress(). + for (int b = 0; b < blocks; ++b) + zlib_compress(type, input[b], input_length[b], &compressed[b], true); + + for (int b = 0; b < blocks; ++b) + output[b].resize(input_length[b]); + + start = now(); + for (int r = 0; r < repeats; ++r) + for (int b = 0; b < blocks; ++b) + zlib_uncompress(type, compressed[b], input_length[b], &output[b]); + utime[run] = std::chrono::duration<double>(now() - start).count(); + + for (int b = 0; b < blocks; ++b) + verify_equal(input[b], input_length[b], &output[b]); + } + + /* + * Output the median/maximum compress/uncompress rates in MB/s. + */ + size_t output_length = 0; + for (size_t i = 0; i < compressed.size(); ++i) + output_length += compressed[i].size(); + + std::sort(ctime, ctime + runs); + std::sort(utime, utime + runs); + + double deflate_rate_med = length * repeats / mega_byte / ctime[runs / 2]; + double inflate_rate_med = length * repeats / mega_byte / utime[runs / 2]; + double deflate_rate_max = length * repeats / mega_byte / ctime[0]; + double inflate_rate_max = length * repeats / mega_byte / utime[0]; + + // type, block size, compression ratio, etc + printf("%s: [b %dM] bytes %6d -> %6u %4.1f%%", + zlib_wrapper_name(type), block_size / (1 << 20), length, + static_cast<unsigned>(output_length), output_length * 100.0 / length); + + // compress / uncompress median (max) rates + printf(" comp %5.1f (%5.1f) MB/s uncomp %5.1f (%5.1f) MB/s\n", + deflate_rate_med, deflate_rate_max, inflate_rate_med, inflate_rate_max); +} + +static int argn = 1; + +char* get_option(int argc, char* argv[], const char* option) { + if (argn < argc) + return !strcmp(argv[argn], option) ? argv[argn++] : 0; + return 0; +} + +bool get_compression(int argc, char* argv[], int* value) { + if (argn < argc) + *value = atoi(argv[argn++]); + return *value >= 1 && *value <= 9; +} + +void usage_exit(const char* program) { + printf("usage: %s gzip|zlib|raw [--compression 1:9] files...\n", program); + exit(1); +} + +int main(int argc, char* argv[]) { + zlib_wrapper type; + if (get_option(argc, argv, "zlib")) + type = kWrapperZLIB; + else if (get_option(argc, argv, "gzip")) + type = kWrapperGZIP; + else if (get_option(argc, argv, "raw")) + type = kWrapperZRAW; + else + usage_exit(argv[0]); + + if (!get_option(argc, argv, "--compression")) + zlib_compression_level = Z_DEFAULT_COMPRESSION; + else if (!get_compression(argc, argv, &zlib_compression_level)) + usage_exit(argv[0]); + + if (argn >= argc) + usage_exit(argv[0]); + while (argn < argc) + zlib_file(argv[argn++], type); + + return 0; +}
diff --git a/src/third_party/zlib2/contrib/minizip/ChangeLogUnzip b/src/third_party/zlib2/contrib/minizip/ChangeLogUnzip new file mode 100644 index 0000000..e62af14 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/ChangeLogUnzip
@@ -0,0 +1,67 @@ +Change in 1.01e (12 feb 05) +- Fix in zipOpen2 for globalcomment (Rolf Kalbermatter) +- Fix possible memory leak in unzip.c (Zoran Stevanovic) + +Change in 1.01b (20 may 04) +- Integrate patch from Debian package (submited by Mark Brown) +- Add tools mztools from Xavier Roche + +Change in 1.01 (8 may 04) +- fix buffer overrun risk in unzip.c (Xavier Roche) +- fix a minor buffer insecurity in minizip.c (Mike Whittaker) + +Change in 1.00: (10 sept 03) +- rename to 1.00 +- cosmetic code change + +Change in 0.22: (19 May 03) +- crypting support (unless you define NOCRYPT) +- append file in existing zipfile + +Change in 0.21: (10 Mar 03) +- bug fixes + +Change in 0.17: (27 Jan 02) +- bug fixes + +Change in 0.16: (19 Jan 02) +- Support of ioapi for virtualize zip file access + +Change in 0.15: (19 Mar 98) +- fix memory leak in minizip.c + +Change in 0.14: (10 Mar 98) +- fix bugs in minizip.c sample for zipping big file +- fix problem in month in date handling +- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for + comment handling + +Change in 0.13: (6 Mar 98) +- fix bugs in zip.c +- add real minizip sample + +Change in 0.12: (4 Mar 98) +- add zip.c and zip.h for creates .zip file +- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly) +- fix miniunz.c for file without specific record for directory + +Change in 0.11: (3 Mar 98) +- fix bug in unzGetCurrentFileInfo for get extra field and comment +- enhance miniunz sample, remove the bad unztst.c sample + +Change in 0.10: (2 Mar 98) +- fix bug in unzReadCurrentFile +- rename unzip* to unz* function and structure +- remove Windows-like hungary notation variable name +- modify some structure in unzip.h +- add somes comment in source +- remove unzipGetcCurrentFile function +- replace ZUNZEXPORT by ZEXPORT +- add unzGetLocalExtrafield for get the local extrafield info +- add a new sample, miniunz.c + +Change in 0.4: (25 Feb 98) +- suppress the type unzipFileInZip. + Only on file in the zipfile can be open at the same time +- fix somes typo in code +- added tm_unz structure in unzip_file_info (date/time in readable format)
diff --git a/src/third_party/zlib2/contrib/minizip/Makefile b/src/third_party/zlib2/contrib/minizip/Makefile new file mode 100644 index 0000000..84eaad2 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/Makefile
@@ -0,0 +1,25 @@ +CC=cc +CFLAGS=-O -I../.. + +UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a +ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a + +.c.o: + $(CC) -c $(CFLAGS) $*.c + +all: miniunz minizip + +miniunz: $(UNZ_OBJS) + $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) + +minizip: $(ZIP_OBJS) + $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) + +test: miniunz minizip + ./minizip test readme.txt + ./miniunz -l test.zip + mv readme.txt readme.old + ./miniunz test.zip + +clean: + /bin/rm -f *.o *~ minizip miniunz
diff --git a/src/third_party/zlib2/contrib/minizip/crypt.h b/src/third_party/zlib2/contrib/minizip/crypt.h new file mode 100644 index 0000000..1e9e820 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/crypt.h
@@ -0,0 +1,131 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(const char* passwd, /* password string */ + unsigned char* buf, /* where to write header */ + int bufSize, + unsigned long* pkeys, + const z_crc_t* pcrc_32_tab, + unsigned long crcForCrypting) +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize<RAND_HEAD_LEN) + return 0; + + /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the + * output of rand() to get less predictability, since rand() is + * often poorly implemented. + */ + if (++calls == 1) + { + srand((unsigned)(time(NULL) ^ ZCR_SEED2)); + } + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + c = (rand() >> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif
diff --git a/src/third_party/zlib2/contrib/minizip/ioapi.c b/src/third_party/zlib2/contrib/minizip/ioapi.c new file mode 100644 index 0000000..543910b --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/ioapi.c
@@ -0,0 +1,247 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) + #define _CRT_SECURE_NO_WARNINGS +#endif + +#if defined(__APPLE__) || defined(__Fuchsia__) || defined(IOAPI_NO_64) +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + +#include "ioapi.h" + +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) +{ + if (pfilefunc->zfile_func64.zopen64_file != NULL) + return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); + else + { + return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); + } +} + +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); + else + { + uLong offsetTruncated = (uLong)offset; + if (offsetTruncated != offset) + return -1; + else + return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); + } +} + +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); + else + { + uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + if ((tell_uLong) == MAXU32) + return (ZPOS64_T)-1; + else + return tell_uLong; + } +} + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) +{ + p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; + p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; + p_filefunc64_32->zfile_func64.ztell64_file = NULL; + p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; + p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; + p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; +} + + + +static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); +static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); +static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); + +static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = FOPEN_FUNC((const char*)filename, mode_fopen); + return file; +} + + +static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + + +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret; + ret = FTELLO_FUNC((FILE *)stream); + return ret; +} + +static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + if (fseek((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + return ret; +} + +static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + + if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + + return ret; +} + + +static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = fopen64_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell64_file = ftell64_file_func; + pzlib_filefunc_def->zseek64_file = fseek64_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +}
diff --git a/src/third_party/zlib2/contrib/minizip/ioapi.h b/src/third_party/zlib2/contrib/minizip/ioapi.h new file mode 100644 index 0000000..4feb758 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/ioapi.h
@@ -0,0 +1,208 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + + Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) + Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. + More if/def section may be needed to support other platforms + Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. + (but you should use iowin32.c for windows instead) + +*/ + +#ifndef _ZLIBIOAPI64_H +#define _ZLIBIOAPI64_H + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) && (!defined(__LB_WIIU__)) + + // Linux needs this to support file operation on files larger then 4+GB + // But might need better if/def to select just the platforms that needs them. + + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif + +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "third_party/zlib/zlib.h" + +#if defined(USE_FILE32API) +#define fopen64 fopen +#define ftello64 ftell +#define fseeko64 fseek +#else +#ifdef __FreeBSD__ +#define fopen64 fopen +#define ftello64 ftello +#define fseeko64 fseeko +#endif +#ifdef _MSC_VER + #define fopen64 fopen + #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) + #define ftello64 _ftelli64 + #define fseeko64 _fseeki64 + #else // old MSC + #define ftello64 ftell + #define fseeko64 fseek + #endif +#endif +#endif + +/* +#ifndef ZPOS64_T + #ifdef _WIN32 + #define ZPOS64_T fpos_t + #else + #include <stdint.h> + #define ZPOS64_T uint64_t + #endif +#endif +*/ + +#ifdef HAVE_MINIZIP64_CONF_H +#include "mz64conf.h" +#endif + +/* a type choosen by DEFINE */ +#ifdef HAVE_64BIT_INT_CUSTOM +typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; +#else +#ifdef HAS_STDINT_H +#include "stdint.h" +typedef uint64_t ZPOS64_T; +#else + +/* Maximum unsigned 32-bit value used as placeholder for zip64 */ +#define MAXU32 0xffffffff + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef unsigned __int64 ZPOS64_T; +#else +typedef unsigned long long int ZPOS64_T; +#endif +#endif +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) + #define ZCALLBACK CALLBACK + #else + #define ZCALLBACK + #endif +#endif + + + + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); + + +/* here is the "old" 32 bits structure structure */ +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); + +typedef struct zlib_filefunc64_def_s +{ + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc64_def; + +void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +/* now internal definition, only for zip.c and unzip.h */ +typedef struct zlib_filefunc64_32_def_s +{ + zlib_filefunc64_def zfile_func64; + open_file_func zopen32_file; + tell_file_func ztell32_file; + seek_file_func zseek32_file; +} zlib_filefunc64_32_def; + + +#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) +//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) +#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) + +voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); +long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); +ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); + +#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) +#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) +#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/src/third_party/zlib2/contrib/minizip/iowin32.c b/src/third_party/zlib2/contrib/minizip/iowin32.c new file mode 100644 index 0000000..246ceb9 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/iowin32.c
@@ -0,0 +1,469 @@ +/* iowin32.c -- IO base function header for compress/uncompress .zip + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#include <stdlib.h> + +#include "zlib.h" +#include "ioapi.h" +#include "iowin32.h" + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE (0xFFFFFFFF) +#endif + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x601 +#endif + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 +// see Include/shared/winapifamily.h in the Windows Kit +#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) +#if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) +#define IOWIN32_USING_WINRT_API 1 +#endif +#endif +#endif + +voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); +uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); +long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); +int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); + +typedef struct +{ + HANDLE hf; + int error; +} WIN32FILE_IOWIN; + + +static void win32_translate_open_mode(int mode, + DWORD* lpdwDesiredAccess, + DWORD* lpdwCreationDisposition, + DWORD* lpdwShareMode, + DWORD* lpdwFlagsAndAttributes) +{ + *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + { + *lpdwDesiredAccess = GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + *lpdwShareMode = FILE_SHARE_READ; + } + else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + } + else if (mode & ZLIB_FILEFUNC_MODE_CREATE) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = CREATE_ALWAYS; + } +} + +static voidpf win32_build_iowin(HANDLE hFile) +{ + voidpf ret=NULL; + + if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) + { + WIN32FILE_IOWIN w32fiow; + w32fiow.hf = hFile; + w32fiow.error = 0; + ret = malloc(sizeof(WIN32FILE_IOWIN)); + + if (ret==NULL) + CloseHandle(hFile); + else + *((WIN32FILE_IOWIN*)ret) = w32fiow; + } + return ret; +} + +voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#endif +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#endif +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile != NULL) + { + if (!ReadFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + } + + return ret; +} + + +uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile != NULL) + { + if (!WriteFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + } + + return ret; +} + +static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) +{ +#ifdef IOWIN32_USING_WINRT_API + return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); +#else + LONG lHigh = pos.HighPart; + DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod); + BOOL fOk = TRUE; + if (dwNewPos == 0xFFFFFFFF) + if (GetLastError() != NO_ERROR) + fOk = FALSE; + if ((newPos != NULL) && (fOk)) + { + newPos->LowPart = dwNewPos; + newPos->HighPart = lHigh; + } + return fOk; +#endif +} + +long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) +{ + long ret=-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + + if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=(long)pos.LowPart; + } + return ret; +} + +ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret= (ZPOS64_T)-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + + if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = (ZPOS64_T)-1; + } + else + ret=pos.QuadPart; + } + return ret; +} + + +long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + + long ret=-1; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + long ret=-1; + + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) +{ + int ret=-1; + + if (stream!=NULL) + { + HANDLE hFile; + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + CloseHandle(hFile); + ret=0; + } + free(stream); + } + return ret; +} + +int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) +{ + int ret=-1; + if (stream!=NULL) + { + ret = ((WIN32FILE_IOWIN*)stream) -> error; + } + return ret; +} + +void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = win32_open_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell_file = win32_tell_file_func; + pzlib_filefunc_def->zseek_file = win32_seek_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + + +void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + + +void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +}
diff --git a/src/third_party/zlib2/contrib/minizip/iowin32.h b/src/third_party/zlib2/contrib/minizip/iowin32.h new file mode 100644 index 0000000..0ca0969 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/iowin32.h
@@ -0,0 +1,28 @@ +/* iowin32.h -- IO base function header for compress/uncompress .zip + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#include <windows.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); + +#ifdef __cplusplus +} +#endif
diff --git a/src/third_party/zlib2/contrib/minizip/miniunz.c b/src/third_party/zlib2/contrib/minizip/miniunz.c new file mode 100644 index 0000000..3d65401 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/miniunz.c
@@ -0,0 +1,660 @@ +/* + miniunz.c + Version 1.1, February 14h, 2010 + sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) +*/ + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif +#endif + +#ifdef __APPLE__ +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <fcntl.h> + +#ifdef _WIN32 +# include <direct.h> +# include <io.h> +#else +# include <unistd.h> +# include <utime.h> +#endif + + +#include "unzip.h" + +#define CASESENSITIVITY (0) +#define WRITEBUFFERSIZE (8192) +#define MAXFILENAME (256) + +#ifdef _WIN32 +#define USEWIN32IOAPI +#include "iowin32.h" +#endif +/* + mini unzip, demo of unzip package + + usage : + Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] + + list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT + if it exists +*/ + + +/* change_file_date : change the date/time of a file + filename : the filename of the file where date/time must be modified + dosdate : the new date at the MSDos format (4 bytes) + tmu_date : the SAME new date at the tm_unz format */ +void change_file_date(filename,dosdate,tmu_date) + const char *filename; + uLong dosdate; + tm_unz tmu_date; +{ +#ifdef _WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; + + hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, + 0,NULL,OPEN_EXISTING,0,NULL); + GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); + DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); + CloseHandle(hFile); +#else +#ifdef unix || __APPLE__ + struct utimbuf ut; + struct tm newdate; + newdate.tm_sec = tmu_date.tm_sec; + newdate.tm_min=tmu_date.tm_min; + newdate.tm_hour=tmu_date.tm_hour; + newdate.tm_mday=tmu_date.tm_mday; + newdate.tm_mon=tmu_date.tm_mon; + if (tmu_date.tm_year > 1900) + newdate.tm_year=tmu_date.tm_year - 1900; + else + newdate.tm_year=tmu_date.tm_year ; + newdate.tm_isdst=-1; + + ut.actime=ut.modtime=mktime(&newdate); + utime(filename,&ut); +#endif +#endif +} + + +/* mymkdir and change_file_date are not 100 % portable + As I don't know well Unix, I wait feedback for the unix portion */ + +int mymkdir(dirname) + const char* dirname; +{ + int ret=0; +#ifdef _WIN32 + ret = _mkdir(dirname); +#elif unix + ret = mkdir (dirname,0775); +#elif __APPLE__ + ret = mkdir (dirname,0775); +#endif + return ret; +} + +int makedir (newdir) + char *newdir; +{ + char *buffer ; + char *p; + int len = (int)strlen(newdir); + + if (len <= 0) + return 0; + + buffer = (char*)malloc(len+1); + if (buffer==NULL) + { + printf("Error allocating memory\n"); + return UNZ_INTERNALERROR; + } + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mymkdir(buffer) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mymkdir(buffer) == -1) && (errno == ENOENT)) + { + printf("couldn't create directory %s\n",buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +void do_banner() +{ + printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); + printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); +} + +void do_help() +{ + printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ + " -e Extract without pathname (junk paths)\n" \ + " -x Extract with pathname\n" \ + " -v list files\n" \ + " -l list files\n" \ + " -d directory to extract into\n" \ + " -o overwrite files without prompting\n" \ + " -p extract crypted file using password\n\n"); +} + +void Display64BitsSize(ZPOS64_T n, int size_char) +{ + /* to avoid compatibility problem , we do here the conversion */ + char number[21]; + int offset=19; + int pos_string = 19; + number[20]=0; + for (;;) { + number[offset]=(char)((n%10)+'0'); + if (number[offset] != '0') + pos_string=offset; + n/=10; + if (offset==0) + break; + offset--; + } + { + int size_display_string = 19-pos_string; + while (size_char > size_display_string) + { + size_char--; + printf(" "); + } + } + + printf("%s",&number[pos_string]); +} + +int do_list(uf) + unzFile uf; +{ + uLong i; + unz_global_info64 gi; + int err; + + err = unzGetGlobalInfo64(uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); + printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); + for (i=0;i<gi.number_entry;i++) + { + char filename_inzip[256]; + unz_file_info64 file_info; + uLong ratio=0; + const char *string_method; + char charCrypt=' '; + err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); + break; + } + if (file_info.uncompressed_size>0) + ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); + + /* display a '*' if the file is crypted */ + if ((file_info.flag & 1) != 0) + charCrypt='*'; + + if (file_info.compression_method==0) + string_method="Stored"; + else + if (file_info.compression_method==Z_DEFLATED) + { + uInt iLevel=(uInt)((file_info.flag & 0x6)/2); + if (iLevel==0) + string_method="Defl:N"; + else if (iLevel==1) + string_method="Defl:X"; + else if ((iLevel==2) || (iLevel==3)) + string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ + } + else + if (file_info.compression_method==Z_BZIP2ED) + { + string_method="BZip2 "; + } + else + string_method="Unkn. "; + + Display64BitsSize(file_info.uncompressed_size,7); + printf(" %6s%c",string_method,charCrypt); + Display64BitsSize(file_info.compressed_size,7); + printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", + ratio, + (uLong)file_info.tmu_date.tm_mon + 1, + (uLong)file_info.tmu_date.tm_mday, + (uLong)file_info.tmu_date.tm_year % 100, + (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, + (uLong)file_info.crc,filename_inzip); + if ((i+1)<gi.number_entry) + { + err = unzGoToNextFile(uf); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzGoToNextFile\n",err); + break; + } + } + } + + return 0; +} + + +int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password) + unzFile uf; + const int* popt_extract_without_path; + int* popt_overwrite; + const char* password; +{ + char filename_inzip[256]; + char* filename_withoutpath; + char* p; + int err=UNZ_OK; + FILE *fout=NULL; + void* buf; + uInt size_buf; + + unz_file_info64 file_info; + uLong ratio=0; + err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); + + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); + return err; + } + + size_buf = WRITEBUFFERSIZE; + buf = (void*)malloc(size_buf); + if (buf==NULL) + { + printf("Error allocating memory\n"); + return UNZ_INTERNALERROR; + } + + p = filename_withoutpath = filename_inzip; + while ((*p) != '\0') + { + if (((*p)=='/') || ((*p)=='\\')) + filename_withoutpath = p+1; + p++; + } + + if ((*filename_withoutpath)=='\0') + { + if ((*popt_extract_without_path)==0) + { + printf("creating directory: %s\n",filename_inzip); + mymkdir(filename_inzip); + } + } + else + { + const char* write_filename; + int skip=0; + + if ((*popt_extract_without_path)==0) + write_filename = filename_inzip; + else + write_filename = filename_withoutpath; + + err = unzOpenCurrentFilePassword(uf,password); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err); + } + + if (((*popt_overwrite)==0) && (err==UNZ_OK)) + { + char rep=0; + FILE* ftestexist; + ftestexist = FOPEN_FUNC(write_filename,"rb"); + if (ftestexist!=NULL) + { + fclose(ftestexist); + do + { + char answer[128]; + int ret; + + printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename); + ret = scanf("%1s",answer); + if (ret != 1) + { + exit(EXIT_FAILURE); + } + rep = answer[0] ; + if ((rep>='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + } + + if (rep == 'N') + skip = 1; + + if (rep == 'A') + *popt_overwrite=1; + } + + if ((skip==0) && (err==UNZ_OK)) + { + fout=FOPEN_FUNC(write_filename,"wb"); + /* some zipfile don't contain directory alone before file */ + if ((fout==NULL) && ((*popt_extract_without_path)==0) && + (filename_withoutpath!=(char*)filename_inzip)) + { + char c=*(filename_withoutpath-1); + *(filename_withoutpath-1)='\0'; + makedir(write_filename); + *(filename_withoutpath-1)=c; + fout=FOPEN_FUNC(write_filename,"wb"); + } + + if (fout==NULL) + { + printf("error opening %s\n",write_filename); + } + } + + if (fout!=NULL) + { + printf(" extracting: %s\n",write_filename); + + do + { + err = unzReadCurrentFile(uf,buf,size_buf); + if (err<0) + { + printf("error %d with zipfile in unzReadCurrentFile\n",err); + break; + } + if (err>0) + if (fwrite(buf,err,1,fout)!=1) + { + printf("error in writing extracted file\n"); + err=UNZ_ERRNO; + break; + } + } + while (err>0); + if (fout) + fclose(fout); + + if (err==0) + change_file_date(write_filename,file_info.dosDate, + file_info.tmu_date); + } + + if (err==UNZ_OK) + { + err = unzCloseCurrentFile (uf); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzCloseCurrentFile\n",err); + } + } + else + unzCloseCurrentFile(uf); /* don't lose the error */ + } + + free(buf); + return err; +} + + +int do_extract(uf,opt_extract_without_path,opt_overwrite,password) + unzFile uf; + int opt_extract_without_path; + int opt_overwrite; + const char* password; +{ + uLong i; + unz_global_info64 gi; + int err; + FILE* fout=NULL; + + err = unzGetGlobalInfo64(uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + + for (i=0;i<gi.number_entry;i++) + { + if (do_extract_currentfile(uf,&opt_extract_without_path, + &opt_overwrite, + password) != UNZ_OK) + break; + + if ((i+1)<gi.number_entry) + { + err = unzGoToNextFile(uf); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzGoToNextFile\n",err); + break; + } + } + } + + return 0; +} + +int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password) + unzFile uf; + const char* filename; + int opt_extract_without_path; + int opt_overwrite; + const char* password; +{ + int err = UNZ_OK; + if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK) + { + printf("file %s not found in the zipfile\n",filename); + return 2; + } + + if (do_extract_currentfile(uf,&opt_extract_without_path, + &opt_overwrite, + password) == UNZ_OK) + return 0; + else + return 1; +} + + +int main(argc,argv) + int argc; + char *argv[]; +{ + const char *zipfilename=NULL; + const char *filename_to_extract=NULL; + const char *password=NULL; + char filename_try[MAXFILENAME+16] = ""; + int i; + int ret_value=0; + int opt_do_list=0; + int opt_do_extract=1; + int opt_do_extract_withoutpath=0; + int opt_overwrite=0; + int opt_extractdir=0; + const char *dirname=NULL; + unzFile uf=NULL; + + do_banner(); + if (argc==1) + { + do_help(); + return 0; + } + else + { + for (i=1;i<argc;i++) + { + if ((*argv[i])=='-') + { + const char *p=argv[i]+1; + + while ((*p)!='\0') + { + char c=*(p++);; + if ((c=='l') || (c=='L')) + opt_do_list = 1; + if ((c=='v') || (c=='V')) + opt_do_list = 1; + if ((c=='x') || (c=='X')) + opt_do_extract = 1; + if ((c=='e') || (c=='E')) + opt_do_extract = opt_do_extract_withoutpath = 1; + if ((c=='o') || (c=='O')) + opt_overwrite=1; + if ((c=='d') || (c=='D')) + { + opt_extractdir=1; + dirname=argv[i+1]; + } + + if (((c=='p') || (c=='P')) && (i+1<argc)) + { + password=argv[i+1]; + i++; + } + } + } + else + { + if (zipfilename == NULL) + zipfilename = argv[i]; + else if ((filename_to_extract==NULL) && (!opt_extractdir)) + filename_to_extract = argv[i] ; + } + } + } + + if (zipfilename!=NULL) + { + +# ifdef USEWIN32IOAPI + zlib_filefunc64_def ffunc; +# endif + + strncpy(filename_try, zipfilename,MAXFILENAME-1); + /* strncpy doesnt append the trailing NULL, of the string is too long. */ + filename_try[ MAXFILENAME ] = '\0'; + +# ifdef USEWIN32IOAPI + fill_win32_filefunc64A(&ffunc); + uf = unzOpen2_64(zipfilename,&ffunc); +# else + uf = unzOpen64(zipfilename); +# endif + if (uf==NULL) + { + strcat(filename_try,".zip"); +# ifdef USEWIN32IOAPI + uf = unzOpen2_64(filename_try,&ffunc); +# else + uf = unzOpen64(filename_try); +# endif + } + } + + if (uf==NULL) + { + printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename); + return 1; + } + printf("%s opened\n",filename_try); + + if (opt_do_list==1) + ret_value = do_list(uf); + else if (opt_do_extract==1) + { +#ifdef _WIN32 + if (opt_extractdir && _chdir(dirname)) +#else + if (opt_extractdir && chdir(dirname)) +#endif + { + printf("Error changing into %s, aborting\n", dirname); + exit(-1); + } + + if (filename_to_extract == NULL) + ret_value = do_extract(uf, opt_do_extract_withoutpath, opt_overwrite, password); + else + ret_value = do_extract_onefile(uf, filename_to_extract, opt_do_extract_withoutpath, opt_overwrite, password); + } + + unzClose(uf); + + return ret_value; +}
diff --git a/src/third_party/zlib2/contrib/minizip/minizip.c b/src/third_party/zlib2/contrib/minizip/minizip.c new file mode 100644 index 0000000..4288962 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/minizip.c
@@ -0,0 +1,520 @@ +/* + minizip.c + Version 1.1, February 14h, 2010 + sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) +*/ + + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif +#endif + +#ifdef __APPLE__ +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <fcntl.h> + +#ifdef _WIN32 +# include <direct.h> +# include <io.h> +#else +# include <unistd.h> +# include <utime.h> +# include <sys/types.h> +# include <sys/stat.h> +#endif + +#include "zip.h" + +#ifdef _WIN32 + #define USEWIN32IOAPI + #include "iowin32.h" +#endif + + + +#define WRITEBUFFERSIZE (16384) +#define MAXFILENAME (256) + +#ifdef _WIN32 +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret = 0; + { + FILETIME ftLocal; + HANDLE hFind; + WIN32_FIND_DATAA ff32; + + hFind = FindFirstFileA(f,&ff32); + if (hFind != INVALID_HANDLE_VALUE) + { + FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); + FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); + FindClose(hFind); + ret = 1; + } + } + return ret; +} +#else +#ifdef unix || __APPLE__ +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret=0; + struct stat s; /* results of stat() */ + struct tm* filedate; + time_t tm_t=0; + + if (strcmp(f,"-")!=0) + { + char name[MAXFILENAME+1]; + int len = strlen(f); + if (len > MAXFILENAME) + len = MAXFILENAME; + + strncpy(name, f,MAXFILENAME-1); + /* strncpy doesnt append the trailing NULL, of the string is too long. */ + name[ MAXFILENAME ] = '\0'; + + if (name[len - 1] == '/') + name[len - 1] = '\0'; + /* not all systems allow stat'ing a file with / appended */ + if (stat(name,&s)==0) + { + tm_t = s.st_mtime; + ret = 1; + } + } + filedate = localtime(&tm_t); + + tmzip->tm_sec = filedate->tm_sec; + tmzip->tm_min = filedate->tm_min; + tmzip->tm_hour = filedate->tm_hour; + tmzip->tm_mday = filedate->tm_mday; + tmzip->tm_mon = filedate->tm_mon ; + tmzip->tm_year = filedate->tm_year; + + return ret; +} +#else +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + return 0; +} +#endif +#endif + + + + +int check_exist_file(filename) + const char* filename; +{ + FILE* ftestexist; + int ret = 1; + ftestexist = FOPEN_FUNC(filename,"rb"); + if (ftestexist==NULL) + ret = 0; + else + fclose(ftestexist); + return ret; +} + +void do_banner() +{ + printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); + printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); +} + +void do_help() +{ + printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ + " -o Overwrite existing file.zip\n" \ + " -a Append to existing file.zip\n" \ + " -0 Store only\n" \ + " -1 Compress faster\n" \ + " -9 Compress better\n\n" \ + " -j exclude path. store only the file name.\n\n"); +} + +/* calculate the CRC32 of a file, + because to encrypt a file, we need known the CRC32 of the file before */ +int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) +{ + unsigned long calculate_crc=0; + int err=ZIP_OK; + FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); + + unsigned long size_read = 0; + unsigned long total_read = 0; + if (fin==NULL) + { + err = ZIP_ERRNO; + } + + if (err == ZIP_OK) + do + { + err = ZIP_OK; + size_read = (int)fread(buf,1,size_buf,fin); + if (size_read < size_buf) + if (feof(fin)==0) + { + printf("error in reading %s\n",filenameinzip); + err = ZIP_ERRNO; + } + + if (size_read>0) + calculate_crc = crc32(calculate_crc,buf,size_read); + total_read += size_read; + + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + *result_crc=calculate_crc; + printf("file %s crc %lx\n", filenameinzip, calculate_crc); + return err; +} + +int isLargeFile(const char* filename) +{ + int largeFile = 0; + ZPOS64_T pos = 0; + FILE* pFile = FOPEN_FUNC(filename, "rb"); + + if(pFile != NULL) + { + int n = FSEEKO_FUNC(pFile, 0, SEEK_END); + pos = FTELLO_FUNC(pFile); + + printf("File : %s is %lld bytes\n", filename, pos); + + if(pos >= 0xffffffff) + largeFile = 1; + + fclose(pFile); + } + + return largeFile; +} + +int main(argc,argv) + int argc; + char *argv[]; +{ + int i; + int opt_overwrite=0; + int opt_compress_level=Z_DEFAULT_COMPRESSION; + int opt_exclude_path=0; + int zipfilenamearg = 0; + char filename_try[MAXFILENAME+16]; + int zipok; + int err=0; + int size_buf=0; + void* buf=NULL; + const char* password=NULL; + + + do_banner(); + if (argc==1) + { + do_help(); + return 0; + } + else + { + for (i=1;i<argc;i++) + { + if ((*argv[i])=='-') + { + const char *p=argv[i]+1; + + while ((*p)!='\0') + { + char c=*(p++);; + if ((c=='o') || (c=='O')) + opt_overwrite = 1; + if ((c=='a') || (c=='A')) + opt_overwrite = 2; + if ((c>='0') && (c<='9')) + opt_compress_level = c-'0'; + if ((c=='j') || (c=='J')) + opt_exclude_path = 1; + + if (((c=='p') || (c=='P')) && (i+1<argc)) + { + password=argv[i+1]; + i++; + } + } + } + else + { + if (zipfilenamearg == 0) + { + zipfilenamearg = i ; + } + } + } + } + + size_buf = WRITEBUFFERSIZE; + buf = (void*)malloc(size_buf); + if (buf==NULL) + { + printf("Error allocating memory\n"); + return ZIP_INTERNALERROR; + } + + if (zipfilenamearg==0) + { + zipok=0; + } + else + { + int i,len; + int dot_found=0; + + zipok = 1 ; + strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1); + /* strncpy doesnt append the trailing NULL, of the string is too long. */ + filename_try[ MAXFILENAME ] = '\0'; + + len=(int)strlen(filename_try); + for (i=0;i<len;i++) + if (filename_try[i]=='.') + dot_found=1; + + if (dot_found==0) + strcat(filename_try,".zip"); + + if (opt_overwrite==2) + { + /* if the file don't exist, we not append file */ + if (check_exist_file(filename_try)==0) + opt_overwrite=1; + } + else + if (opt_overwrite==0) + if (check_exist_file(filename_try)!=0) + { + char rep=0; + do + { + char answer[128]; + int ret; + printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try); + ret = scanf("%1s",answer); + if (ret != 1) + { + exit(EXIT_FAILURE); + } + rep = answer[0] ; + if ((rep>='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + if (rep=='N') + zipok = 0; + if (rep=='A') + opt_overwrite = 2; + } + } + + if (zipok==1) + { + zipFile zf; + int errclose; +# ifdef USEWIN32IOAPI + zlib_filefunc64_def ffunc; + fill_win32_filefunc64A(&ffunc); + zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); +# else + zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0); +# endif + + if (zf == NULL) + { + printf("error opening %s\n",filename_try); + err= ZIP_ERRNO; + } + else + printf("creating %s\n",filename_try); + + for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++) + { + if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) && + ((argv[i][1]=='o') || (argv[i][1]=='O') || + (argv[i][1]=='a') || (argv[i][1]=='A') || + (argv[i][1]=='p') || (argv[i][1]=='P') || + ((argv[i][1]>='0') || (argv[i][1]<='9'))) && + (strlen(argv[i]) == 2))) + { + FILE * fin; + int size_read; + const char* filenameinzip = argv[i]; + const char *savefilenameinzip; + zip_fileinfo zi; + unsigned long crcFile=0; + int zip64 = 0; + + zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = + zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; + zi.dosDate = 0; + zi.internal_fa = 0; + zi.external_fa = 0; + filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); + +/* + err = zipOpenNewFileInZip(zf,filenameinzip,&zi, + NULL,0,NULL,0,NULL / * comment * /, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level); +*/ + if ((password != NULL) && (err==ZIP_OK)) + err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); + + zip64 = isLargeFile(filenameinzip); + + /* The path name saved, should not include a leading slash. */ + /*if it did, windows/xp and dynazip couldn't read the zip file. */ + savefilenameinzip = filenameinzip; + while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) + { + savefilenameinzip++; + } + + /*should the zip file contain any path at all?*/ + if( opt_exclude_path ) + { + const char *tmpptr; + const char *lastslash = 0; + for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++) + { + if( *tmpptr == '\\' || *tmpptr == '/') + { + lastslash = tmpptr; + } + } + if( lastslash != NULL ) + { + savefilenameinzip = lastslash+1; // base filename follows last slash. + } + } + + /**/ + err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi, + NULL,0,NULL,0,NULL /* comment*/, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level,0, + /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + password,crcFile, zip64); + + if (err != ZIP_OK) + printf("error in opening %s in zipfile\n",filenameinzip); + else + { + fin = FOPEN_FUNC(filenameinzip,"rb"); + if (fin==NULL) + { + err=ZIP_ERRNO; + printf("error in opening %s for reading\n",filenameinzip); + } + } + + if (err == ZIP_OK) + do + { + err = ZIP_OK; + size_read = (int)fread(buf,1,size_buf,fin); + if (size_read < size_buf) + if (feof(fin)==0) + { + printf("error in reading %s\n",filenameinzip); + err = ZIP_ERRNO; + } + + if (size_read>0) + { + err = zipWriteInFileInZip (zf,buf,size_read); + if (err<0) + { + printf("error in writing %s in the zipfile\n", + filenameinzip); + } + + } + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + if (err<0) + err=ZIP_ERRNO; + else + { + err = zipCloseFileInZip(zf); + if (err!=ZIP_OK) + printf("error in closing %s in the zipfile\n", + filenameinzip); + } + } + } + errclose = zipClose(zf,NULL); + if (errclose != ZIP_OK) + printf("error in closing %s\n",filename_try); + } + else + { + do_help(); + } + + free(buf); + return 0; +}
diff --git a/src/third_party/zlib2/contrib/minizip/mztools.c b/src/third_party/zlib2/contrib/minizip/mztools.c new file mode 100644 index 0000000..8bf9cca --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/mztools.c
@@ -0,0 +1,291 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "third_party/zlib/zlib.h" +#include "unzip.h" + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) + +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) +const char* file; +const char* fileOut; +const char* fileOutTmp; +uLong* nRecovered; +uLong* bytesRecovered; +{ + int err = Z_OK; + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + int entries = 0; + uLong totalBytes = 0; + char header[30]; + char filename[1024]; + char extra[1024]; + int offset = 0; + int offsetCD = 0; + while ( fread(header, 1, 30, fpZip) == 30 ) { + int currentOffset = offset; + + /* File entry */ + if (READ_32(header) == 0x04034b50) { + unsigned int version = READ_16(header + 4); + unsigned int gpflag = READ_16(header + 6); + unsigned int method = READ_16(header + 8); + unsigned int filetime = READ_16(header + 10); + unsigned int filedate = READ_16(header + 12); + unsigned int crc = READ_32(header + 14); /* crc */ + unsigned int cpsize = READ_32(header + 18); /* compressed size */ + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ + unsigned int fnsize = READ_16(header + 26); /* file name length */ + unsigned int extsize = READ_16(header + 28); /* extra field length */ + filename[0] = extra[0] = '\0'; + + /* Header */ + if (fwrite(header, 1, 30, fpOut) == 30) { + offset += 30; + } else { + err = Z_ERRNO; + break; + } + + /* Filename */ + if (fnsize > 0) { + if (fnsize < sizeof(filename)) { + if (fread(filename, 1, fnsize, fpZip) == fnsize) { + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { + offset += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (extsize < sizeof(extra)) { + if (fread(extra, 1, extsize, fpZip) == extsize) { + if (fwrite(extra, 1, extsize, fpOut) == extsize) { + offset += extsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } + + /* Data */ + { + int dataSize = cpsize; + if (dataSize == 0) { + dataSize = uncpsize; + } + if (dataSize > 0) { + char* data = malloc(dataSize); + if (data != NULL) { + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { + offset += dataSize; + totalBytes += dataSize; + } else { + err = Z_ERRNO; + } + } else { + err = Z_ERRNO; + } + free(data); + if (err != Z_OK) { + break; + } + } else { + err = Z_MEM_ERROR; + break; + } + } + } + + /* Central directory entry */ + { + char header[46]; + char* comment = ""; + int comsize = (int) strlen(comment); + WRITE_32(header, 0x02014b50); + WRITE_16(header + 4, version); + WRITE_16(header + 6, version); + WRITE_16(header + 8, gpflag); + WRITE_16(header + 10, method); + WRITE_16(header + 12, filetime); + WRITE_16(header + 14, filedate); + WRITE_32(header + 16, crc); + WRITE_32(header + 20, cpsize); + WRITE_32(header + 24, uncpsize); + WRITE_16(header + 28, fnsize); + WRITE_16(header + 30, extsize); + WRITE_16(header + 32, comsize); + WRITE_16(header + 34, 0); /* disk # */ + WRITE_16(header + 36, 0); /* int attrb */ + WRITE_32(header + 38, 0); /* ext attrb */ + WRITE_32(header + 42, currentOffset); + /* Header */ + if (fwrite(header, 1, 46, fpOutCD) == 46) { + offsetCD += 46; + + /* Filename */ + if (fnsize > 0) { + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { + offsetCD += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { + offsetCD += extsize; + } else { + err = Z_ERRNO; + break; + } + } + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { + offsetCD += comsize; + } else { + err = Z_ERRNO; + break; + } + } + + + } else { + err = Z_ERRNO; + break; + } + } + + /* Success */ + entries++; + + } else { + break; + } + } + + /* Final central directory */ + { + int entriesZip = entries; + char header[22]; + char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; + int comsize = (int) strlen(comment); + if (entriesZip > 0xffff) { + entriesZip = 0xffff; + } + WRITE_32(header, 0x06054b50); + WRITE_16(header + 4, 0); /* disk # */ + WRITE_16(header + 6, 0); /* disk # */ + WRITE_16(header + 8, entriesZip); /* hack */ + WRITE_16(header + 10, entriesZip); /* hack */ + WRITE_32(header + 12, offsetCD); /* size of CD */ + WRITE_32(header + 16, offset); /* offset to CD */ + WRITE_16(header + 20, comsize); /* comment */ + + /* Header */ + if (fwrite(header, 1, 22, fpOutCD) == 22) { + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { + err = Z_ERRNO; + } + } + + } else { + err = Z_ERRNO; + } + } + + /* Final merge (file + central directory) */ + fclose(fpOutCD); + if (err == Z_OK) { + fpOutCD = fopen(fileOutTmp, "rb"); + if (fpOutCD != NULL) { + int nRead; + char buffer[8192]; + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { + err = Z_ERRNO; + break; + } + } + fclose(fpOutCD); + } + } + + /* Close */ + fclose(fpZip); + fclose(fpOut); + + /* Wipe temporary file */ + (void)remove(fileOutTmp); + + /* Number of recovered entries */ + if (err == Z_OK) { + if (nRecovered != NULL) { + *nRecovered = entries; + } + if (bytesRecovered != NULL) { + *bytesRecovered = totalBytes; + } + } + } else { + err = Z_STREAM_ERROR; + } + return err; +}
diff --git a/src/third_party/zlib2/contrib/minizip/mztools.h b/src/third_party/zlib2/contrib/minizip/mztools.h new file mode 100644 index 0000000..f295ffe --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/mztools.h
@@ -0,0 +1,37 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +#ifndef _zip_tools_H +#define _zip_tools_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "third_party/zlib/zlib.h" +#endif + +#include "unzip.h" + +/* Repair a ZIP file (missing central directory) + file: file to recover + fileOut: output file after recovery + fileOutTmp: temporary file name used for recovery +*/ +extern int ZEXPORT unzRepair(const char* file, + const char* fileOut, + const char* fileOutTmp, + uLong* nRecovered, + uLong* bytesRecovered); + + +#ifdef __cplusplus +} +#endif + + +#endif
diff --git a/src/third_party/zlib2/contrib/minizip/unzip.c b/src/third_party/zlib2/contrib/minizip/unzip.c new file mode 100644 index 0000000..e8b2bc5c --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/unzip.c
@@ -0,0 +1,2117 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + + ------------------------------------------------------------------------------------ + Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of + compatibility with older software. The following is from the original crypt.c. + Code woven in by Terry Thorsen 1/2003. + + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html + + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + ------------------------------------------------------------------------------------ + + Changes in unzip.c + + 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos + 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* + 2007-2008 - Even Rouault - Remove old C style function prototypes + 2007-2008 - Even Rouault - Add unzip support for ZIP64 + + Copyright (C) 2007-2008 Even Rouault + + + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G + should only read the compressed/uncompressed size from the Zip64 format if + the size from normal header was 0xFFFFFFFF + Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Patch created by Daniel Borca + + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + + Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson + +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "third_party/zlib/zlib.h" +#include "unzip.h" + +#ifdef STDC +# include <stddef.h> +# include <string.h> +# include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info64_internal_s +{ + ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ +} unz_file_info64_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ + ZPOS64_T total_out_64; + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ + ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip64_read_info_s; + + +/* unz64_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + int is64bitOpenFunction; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info64 gi; /* public global information */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T num_file; /* number of the current file in the zipfile*/ + ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ + ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ + ZPOS64_T central_pos; /* position of the beginning of the central dir*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info64 cur_file_info; /* public info about the current file in zip*/ + unz_file_info64_internal cur_file_info_internal; /* private info about it*/ + file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; + + int isZip64; + +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const z_crc_t* pcrc_32_tab; +# endif +} unz64_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been successfully opened for reading. +*/ + + +local int unz64local_getByte OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unz64local_getShort OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX)); + + +local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) +{ + ZPOS64_T x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<24; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<32; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<40; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<48; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<56; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1<c2) + return -1; + if (c1>c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity) + +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize; + ZPOS64_T uReadPos ; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + + +/* + Locate the Central directory 64 of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream)); + +local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize; + ZPOS64_T uReadPos; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) + return 0; + + /* total number of disks */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + if (uL != 0x06064b50) + return 0; + + return relativeOffset; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +local unzFile unzOpenInternal (const void *path, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def, + int is64bitOpenFunction) +{ + unz64_s us; + unz64_s *s; + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + us.z_filefunc.zseek32_file = NULL; + us.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); + else + us.z_filefunc = *pzlib_filefunc64_32_def; + us.is64bitOpenFunction = is64bitOpenFunction; + + + + us.filestream = ZOPEN64(us.z_filefunc, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); + if (central_pos) + { + uLong uS; + ZPOS64_T uL64; + + us.isZip64 = 1; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* size of zip64 end of central directory record */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version made by */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version needed to extract */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + us.gi.size_comment = 0; + } + else + { + central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + us.isZip64 = 0; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.gi.number_entry = uL; + + /* total number of entries in the central dir */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + number_entry_CD = uL; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.size_central_dir = uL; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.offset_central_dir = uL; + + /* zipfile comment length */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + } + + if ((central_pos<us.offset_central_dir+us.size_central_dir) && + (err==UNZ_OK)) + err=UNZ_BADZIPFILE; + + if (err!=UNZ_OK) + { + ZCLOSE64(us.z_filefunc, us.filestream); + return NULL; + } + + us.byte_before_the_zipfile = central_pos - + (us.offset_central_dir+us.size_central_dir); + us.central_pos = central_pos; + us.pfile_in_zip_read = NULL; + us.encrypted = 0; + + + s=(unz64_s*)ALLOC(sizeof(unz64_s)); + if( s != NULL) + { + *s=us; + unzGoToFirstFile((unzFile)s); + } + return (unzFile)s; +} + + +extern unzFile ZEXPORT unzOpen2 (const char *path, + zlib_filefunc_def* pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); + return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0); + } + else + return unzOpenInternal(path, NULL, 0); +} + +extern unzFile ZEXPORT unzOpen2_64 (const void *path, + zlib_filefunc64_def* pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1); + } + else + return unzOpenInternal(path, NULL, 1); +} + +extern unzFile ZEXPORT unzOpen (const char *path) +{ + return unzOpenInternal(path, NULL, 0); +} + +extern unzFile ZEXPORT unzOpen64 (const void *path) +{ + return unzOpenInternal(path, NULL, 1); +} + +/* + Close a ZipFile opened with unzOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzCloseCurrentFile before call unzClose. + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzClose (unzFile file) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + if (s->pfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE64(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + /* to do : check if number_entry is not truncated */ + pglobal_info32->number_entry = (uLong)s->gi.number_entry; + pglobal_info32->size_comment = s->gi.size_comment; + return UNZ_OK; +} +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) +{ + ZPOS64_T uDate; + uDate = (ZPOS64_T)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unz64local_GetCurrentFileInfoInternal (unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz64_s* s; + unz_file_info64 file_info; + unz_file_info64_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + uLong uL; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.compressed_size = uL; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.uncompressed_size = uL; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + // relative offset of local header + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info_internal.offset_curfile = uL; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename<fileNameBufferSize) + { + *(szFileName+file_info.size_filename)='\0'; + uSizeRead = file_info.size_filename; + } + else + uSizeRead = fileNameBufferSize; + + if ((file_info.size_filename>0) && (fileNameBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + // Read extrafield + if ((err==UNZ_OK) && (extraField!=NULL)) + { + ZPOS64_T uSizeRead ; + if (file_info.size_file_extra<extraFieldBufferSize) + uSizeRead = file_info.size_file_extra; + else + uSizeRead = extraFieldBufferSize; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + + lSeek += file_info.size_file_extra - (uLong)uSizeRead; + } + else + lSeek += file_info.size_file_extra; + + + if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) + { + uLong acc = 0; + + // since lSeek now points to after the extra field we need to move back + lSeek -= file_info.size_file_extra; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + while(acc < file_info.size_file_extra) + { + uLong headerId; + uLong dataSize; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) + err=UNZ_ERRNO; + + /* ZIP64 extra fields */ + if (headerId == 0x0001) + { + uLong uL; + + if(file_info.uncompressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.compressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info_internal.offset_curfile == MAXU32) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.disk_num_start == MAXU32) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + } + + } + else + { + if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) + err=UNZ_ERRNO; + } + + acc += 2 + 2 + dataSize; + } + } + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_comment<commentBufferSize) + { + *(szComment+file_info.size_file_comment)='\0'; + uSizeRead = file_info.size_file_comment; + } + else + uSizeRead = commentBufferSize; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + int err; + unz_file_info64 file_info64; + err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); + if ((err==UNZ_OK) && (pfile_info != NULL)) + { + pfile_info->version = file_info64.version; + pfile_info->version_needed = file_info64.version_needed; + pfile_info->flag = file_info64.flag; + pfile_info->compression_method = file_info64.compression_method; + pfile_info->dosDate = file_info64.dosDate; + pfile_info->crc = file_info64.crc; + + pfile_info->size_filename = file_info64.size_filename; + pfile_info->size_file_extra = file_info64.size_file_extra; + pfile_info->size_file_comment = file_info64.size_file_comment; + + pfile_info->disk_num_start = file_info64.disk_num_start; + pfile_info->internal_fa = file_info64.internal_fa; + pfile_info->external_fa = file_info64.external_fa; + + pfile_info->tmu_date = file_info64.tmu_date, + + + pfile_info->compressed_size = (uLong)file_info64.compressed_size; + pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; + + } + return err; +} +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (unzFile file) +{ + int err=UNZ_OK; + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (unzFile file) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) +{ + unz64_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info64 cur_file_infoSaved; + unz_file_info64_internal cur_file_info_internalSaved; + ZPOS64_T num_fileSaved; + ZPOS64_T pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo64(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; // offset in file + ZPOS64_T num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) +{ + unz64_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + int err = unzGetFilePos64(file,&file_pos64); + if (err==UNZ_OK) + { + file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uLong)file_pos64.num_of_file; + } + return err; +} + +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) +{ + unz64_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + if (file_pos == NULL) + return UNZ_PARAMERROR; + + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + return unzGoToFilePos64(file,&file_pos64); +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, + int* level, int raw, const char* password) +{ + int err=UNZ_OK; + uInt iSizeVar; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->total_out_64=0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) + { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw=1; +#endif + } + else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = 0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + s->encrypted = 0; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->pfile_in_zip_read->rest_read_compressed-=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + s=(unz64_s*)file; + if (file==NULL) + return 0; //UNZ_PARAMERROR; + pfile_in_zip_read_info=s->pfile_in_zip_read; + if (pfile_in_zip_read_info==NULL) + return 0; //UNZ_PARAMERROR; + return pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile; +} + +/** Addition for GDAL : END */ + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressed<uReadThis) + uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;i<uReadThis;i++) + pfile_in_zip_read_info->read_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;i<uDoCopy;i++) + *(pfile_in_zip_read_info->stream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + + pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; + bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; + + err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err==BZ_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=BZ_OK) + break; +#endif + } // end Z_BZIP2ED + else + { + ZPOS64_T uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + ZPOS64_T uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + +extern ZPOS64_T ZEXPORT unztell64 (unzFile file) +{ + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return (ZPOS64_T)-1; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return (ZPOS64_T)-1; + + return pfile_in_zip_read_info->total_out_64; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* +Read extra field from the current file (opened by unzOpenCurrentFile) +This is the local-header version of the extra field (sometimes, there is +more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + uInt read_now; + ZPOS64_T size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (unzFile file) +{ + int err=UNZ_OK; + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) + inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif + + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) +{ + unz64_s* s; + uLong uReadThis ; + if (file==NULL) + return (int)UNZ_PARAMERROR; + s=(unz64_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) +{ + unz64_s* s; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern uLong ZEXPORT unzGetOffset (unzFile file) +{ + ZPOS64_T offset64; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + offset64 = unzGetOffset64(file); + return (uLong)offset64; +} + +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) +{ + return unzSetOffset64(file,pos); +}
diff --git a/src/third_party/zlib2/contrib/minizip/unzip.h b/src/third_party/zlib2/contrib/minizip/unzip.h new file mode 100644 index 0000000..3c01435 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/unzip.h
@@ -0,0 +1,437 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------------- + + Changes + + See header of unzip64.c + +*/ + +#ifndef _unz64_H +#define _unz64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "third_party/zlib/zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info64_s +{ + ZPOS64_T number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info64; + +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info64_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 8 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info64; + +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. + the "64" function take a const void* pointer, because the path is just the + value passed to the open64_file_func callback. + Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path + is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* + does not describe the reality +*/ + + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, + zlib_filefunc64_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unz64Open, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzCloseCurrentFile before call unzClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); + +extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, + unz_global_info64 *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +typedef struct unz64_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ + ZPOS64_T num_of_file; /* # of file */ +} unz64_file_pos; + +extern int ZEXPORT unzGetFilePos64( + unzFile file, + unz64_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos64( + unzFile file, + const unz64_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); + +/** Addition for GDAL : END */ + + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); + +extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz64_H */
diff --git a/src/third_party/zlib2/contrib/minizip/zip.c b/src/third_party/zlib2/contrib/minizip/zip.c new file mode 100644 index 0000000..65c0c72 --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/zip.c
@@ -0,0 +1,2007 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + Oct-2009 - Mathias Svensson - Remove old C style function prototypes + Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives + Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. + Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data + It is used when recreting zip archive with RAW when deleting items from a zip. + ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. + Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "third_party/zlib/zlib.h" +#include "zip.h" + +#ifdef STDC +# include <stddef.h> +# include <string.h> +# include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (64*1024) //(16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + + +// NOT sure that this work on ALL platform +#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) +#define ZIP64ENDHEADERMAGIC (0x6064b50) +#define ZIP64ENDLOCHEADERMAGIC (0x7064b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignment */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + ZPOS64_T pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralExtra; + uLong size_centralheader; /* size of the central header for cur file */ + uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; + int zip64; /* Add ZIP64 extened information in the extra field */ + ZPOS64_T pos_zip64extrainfo; + ZPOS64_T totalCompressedData; + ZPOS64_T totalUncompressedData; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const z_crc_t* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile64_info; + +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile64_info ci; /* info on the file curretly writing */ + + ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ + ZPOS64_T add_position_when_writing_offset; + ZPOS64_T number_entry; + +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif + +} zip64_internal; + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(linkedlist_datablock_internal* ldi) +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(linkedlist_data* ll) +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(linkedlist_data* ll) +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;i<copy_this;i++) + *(to_copy+i)=*(from_copy+i); + + ldi->filled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) +*/ + +local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); +local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) +{ + unsigned char buf[8]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) +{ + uLong year = (uLong)ptm->tm_year; + if (year>=1980) + year-=1980; + else if (year>=80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); + +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); + + +local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) +{ + ZPOS64_T x; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<24; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<32; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<40; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<48; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<56; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize; + ZPOS64_T uReadPos ; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* +Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before +the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize; + ZPOS64_T uReadPos; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + { + // Signature "0x07064b50" Zip64 end of central directory locater + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + } + + if (uPosFound!=0) + break; + } + + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) + return 0; + + /* total number of disks */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto Zip64 end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' + return 0; + + return relativeOffset; +} + +int LoadCentralDirectoryRecord(zip64_internal* pziinit) +{ + int err=ZIP_OK; + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory */ + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry; + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong VersionMadeBy; + uLong VersionNeeded; + uLong size_comment; + + int hasZIP64Record = 0; + + // check first if we find a ZIP64 record + central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); + if(central_pos > 0) + { + hasZIP64Record = 1; + } + else if(central_pos == 0) + { + central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); + } + +/* disable to allow appending to empty ZIP archive + if (central_pos==0) + err=ZIP_ERRNO; +*/ + + if(hasZIP64Record) + { + ZPOS64_T sizeEndOfCentralDirectory; + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* size of zip64 end of central directory record */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version made by */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version needed to extract */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + // TODO.. + // read the comment from the standard central header. + size_comment = 0; + } + else + { + // Read End of central Directory info + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + number_entry = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry = uL; + + /* total number of entries in the central dir */ + number_entry_CD = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry_CD = uL; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + size_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + size_central_dir = uL; + + /* offset of start of central directory with respect to the starting disk number */ + offset_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + offset_central_dir = uL; + + + /* zipfile global comment length */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + } + + if ((central_pos<offset_central_dir+size_central_dir) && + (err==ZIP_OK)) + err=ZIP_BADZIPFILE; + + if (err!=ZIP_OK) + { + ZCLOSE64(pziinit->z_filefunc, pziinit->filestream); + return ZIP_ERRNO; + } + + if (size_comment>0) + { + pziinit->globalcomment = (char*)ALLOC(size_comment+1); + if (pziinit->globalcomment) + { + size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); + pziinit->globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); + pziinit->add_position_when_writing_offset = byte_before_the_zipfile; + + { + ZPOS64_T size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + ZPOS64_T read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + + if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); + + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + pziinit->begin_pos = byte_before_the_zipfile; + pziinit->number_entry = number_entry_CD; + + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + return err; +} + + +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + + +/************************************************************/ +extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) +{ + zip64_internal ziinit; + zip64_internal* zi; + int err=ZIP_OK; + + ziinit.z_filefunc.zseek32_file = NULL; + ziinit.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); + else + ziinit.z_filefunc = *pzlib_filefunc64_32_def; + + ziinit.filestream = ZOPEN64(ziinit.z_filefunc, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + + if (append == APPEND_STATUS_CREATEAFTER) + ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); + + ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writing_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + + zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); + if (zi==NULL) + { + ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + // Read and Cache Central Directory Records + err = LoadCentralDirectoryRecord(&ziinit); + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + + + +extern zipFile ZEXPORT zipOpen (const char* pathname, int append) +{ + return zipOpen3((const void*)pathname,append,NULL,NULL); +} + +extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) +{ + return zipOpen3(pathname,append,NULL,NULL); +} + +int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) +{ + /* write the local header */ + int err; + uInt size_filename = (uInt)strlen(filename); + uInt size_extrafield = size_extrafield_local; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); + + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + } + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if(zi->ci.zip64) + { + size_extrafield += 20; + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); + + if ((err==ZIP_OK) && (size_filename > 0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + } + + if ((err==ZIP_OK) && (size_extrafield_local > 0)) + { + if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) + err = ZIP_ERRNO; + } + + + if ((err==ZIP_OK) && (zi->ci.zip64)) + { + // write the Zip64 extended info + short HeaderID = 1; + short DataSize = 16; + ZPOS64_T CompressedSize = 0; + ZPOS64_T UncompressedSize = 0; + + // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) + zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); + } + + return err; +} + +/* + NOTE. + When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped + before calling this function it can be done with zipRemoveExtraInfoBlock + + It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize + unnecessary allocations. + */ +extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) +{ + zip64_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + (crcForCrypting); + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + +#ifdef HAVE_BZIP2 + if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) + return ZIP_PARAMERROR; +#else + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; +#endif + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else + zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); + } + + zi->ci.flag = flagBase; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if (level==2) + zi->ci.flag |= 4; + if (level==1) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); + + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; + zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data + + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); + + zi->ci.size_centralExtra = size_extrafield_global; + zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + if(zi->ci.pos_local_header >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); + + for (i=0;i<size_filename;i++) + *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;i<size_extrafield_global;i++) + *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;i<size_comment;i++) + *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(comment+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + zi->ci.zip64 = zip64; + zi->ci.totalCompressedData = 0; + zi->ci.totalUncompressedData = 0; + zi->ci.pos_zip64extrainfo = 0; + + err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); + +#ifdef HAVE_BZIP2 + zi->ci.bstream.avail_in = (uInt)0; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + zi->ci.bstream.total_in_hi32 = 0; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_out_hi32 = 0; + zi->ci.bstream.total_out_lo32 = 0; +#endif + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + zi->ci.stream.data_type = Z_BINARY; + +#ifdef HAVE_BZIP2 + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) +#else + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) +#endif + { + if(zi->ci.method == Z_DEFLATED) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + if (windowBits>0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); + + if (err==Z_OK) + zi->ci.stream_initialised = Z_DEFLATED; + } + else if(zi->ci.method == Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + // Init BZip stuff here + zi->ci.bstream.bzalloc = 0; + zi->ci.bstream.bzfree = 0; + zi->ci.bstream.opaque = (voidpf)0; + + err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); + if(err == BZ_OK) + zi->ci.stream_initialised = Z_BZIP2ED; +#endif + } + + } + +# ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err==Z_OK) && (password != NULL)) + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + zi->ci.encrypt = 1; + zi->ci.pcrc_32_tab = get_crc_table(); + /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + + sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) + err = ZIP_ERRNO; + } +# endif + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, versionMadeBy, flagBase, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); +} + +local int zip64FlushWriteBuffer(zip64_internal* zi) +{ + int err=ZIP_OK; + + if (zi->ci.encrypt != 0) + { +#ifndef NOCRYPT + uInt i; + int t; + for (i=0;i<zi->ci.pos_in_buffered_data;i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); +#endif + } + + if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) + err = ZIP_ERRNO; + + zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; + +#ifdef HAVE_BZIP2 + if(zi->ci.method == Z_BZIP2ED) + { + zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_in_hi32 = 0; + } + else +#endif + { + zi->ci.totalUncompressedData += zi->ci.stream.total_in; + zi->ci.stream.total_in = 0; + } + + + zi->ci.pos_in_buffered_data = 0; + + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) +{ + zip64_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); + +#ifdef HAVE_BZIP2 + if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) + { + zi->ci.bstream.next_in = (void*)buf; + zi->ci.bstream.avail_in = len; + err = BZ_RUN_OK; + + while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) + { + if (zi->ci.bstream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + } + + + if(err != BZ_RUN_OK) + break; + + if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; +// uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; + err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; + } + } + + if(err == BZ_RUN_OK) + err = ZIP_OK; + } + else +#endif + { + zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.avail_in = len; + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + + if(err != ZIP_OK) + break; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + if(uTotalOutBefore > zi->ci.stream.total_out) + { + int bBreak = 0; + bBreak++; + } + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + + for (i = 0; i < copy_this; i++) + *(((char*)zi->ci.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + }// while(...) + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) +{ + return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); +} + +extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) +{ + zip64_internal* zi; + ZPOS64_T compressed_size; + uLong invalidValue = 0xffffffff; + short datasize = 0; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + } + else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { +#ifdef HAVE_BZIP2 + err = BZ_FINISH_OK; + while (err==BZ_FINISH_OK) + { + uLong uTotalOutBefore; + if (zi->ci.bstream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.bstream.total_out_lo32; + err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); + if(err == BZ_STREAM_END) + err = Z_STREAM_END; + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); + } + + if(err == BZ_FINISH_OK) + err = ZIP_OK; +#endif + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + { + if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) + err = ZIP_ERRNO; + } + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + int tmp_err = deflateEnd(&zi->ci.stream); + if (err == ZIP_OK) + err = tmp_err; + zi->ci.stream_initialised = 0; + } +#ifdef HAVE_BZIP2 + else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { + int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); + if (err==ZIP_OK) + err = tmperr; + zi->ci.stream_initialised = 0; + } +#endif + + if (!zi->ci.raw) + { + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = zi->ci.totalUncompressedData; + } + compressed_size = zi->ci.totalCompressedData; + +# ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +# endif + + // update Current Item crc and sizes, + if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) + { + /*version Made by*/ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); + /*version needed*/ + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); + + } + + zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + + + if(compressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ + else + zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ + + /// set internal file attributes field + if (zi->ci.stream.data_type == Z_ASCII) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + + if(uncompressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ + else + zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ + + // Add ZIP64 extra info field for uncompressed size + if(uncompressed_size >= 0xffffffff) + datasize += 8; + + // Add ZIP64 extra info field for compressed size + if(compressed_size >= 0xffffffff) + datasize += 8; + + // Add ZIP64 extra info field for relative offset to local file header of current file + if(zi->ci.pos_local_header >= 0xffffffff) + datasize += 8; + + if(datasize > 0) + { + char* p = NULL; + + if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) + { + // we can not write more data to the buffer that we have room for. + return ZIP_BADZIPFILE; + } + + p = zi->ci.central_header + zi->ci.size_centralheader; + + // Add Extra Information Header for 'ZIP64 information' + zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID + p += 2; + zip64local_putValue_inmemory(p, datasize, 2); // DataSize + p += 2; + + if(uncompressed_size >= 0xffffffff) + { + zip64local_putValue_inmemory(p, uncompressed_size, 8); + p += 8; + } + + if(compressed_size >= 0xffffffff) + { + zip64local_putValue_inmemory(p, compressed_size, 8); + p += 8; + } + + if(zi->ci.pos_local_header >= 0xffffffff) + { + zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); + p += 8; + } + + // Update how much extra free space we got in the memory buffer + // and increase the centralheader size so the new ZIP64 fields are included + // ( 4 below is the size of HeaderID and DataSize field ) + zi->ci.size_centralExtraFree -= datasize + 4; + zi->ci.size_centralheader += datasize + 4; + + // Update the extra info size field + zi->ci.size_centralExtra += datasize + 4; + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); + } + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); + + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + // Update the LocalFileHeader with the new values. + + ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + + if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + + if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff ) + { + if(zi->ci.pos_zip64extrainfo > 0) + { + // Update the size in the ZIP64 extended field. + if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); + } + else + err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal + } + else + { + if (err==ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); + } + + if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip (zipFile file) +{ + return zipCloseFileInZipRaw (file,0,0); +} + +int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) +{ + int err = ZIP_OK; + ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); + + /*num disks*/ + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + /*relative offset*/ + if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); + + /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); + + return err; +} + +int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ + int err = ZIP_OK; + + uLong Zip64DataSize = 44; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? + + if (err==ZIP_OK) /* version made by */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + + if (err==ZIP_OK) /* version needed */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + + if (err==ZIP_OK) /* number of this disk */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + + if (err==ZIP_OK) /* size of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ + { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); + } + return err; +} +int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ + int err = ZIP_OK; + + /*signature*/ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + { + { + if(zi->number_entry >= 0xFFFF) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + } + } + + if (err==ZIP_OK) /* total number of entries in the central dir */ + { + if(zi->number_entry >= 0xFFFF) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + } + + if (err==ZIP_OK) /* size of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ + { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + if(pos >= 0xffffffff) + { + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); + } + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4); + } + + return err; +} + +int Write_GlobalComment(zip64_internal* zi, const char* global_comment) +{ + int err = ZIP_OK; + uInt size_global_comment = 0; + + if(global_comment != NULL) + size_global_comment = (uInt)strlen(global_comment); + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + + if (err == ZIP_OK && size_global_comment > 0) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + } + return err; +} + +extern int ZEXPORT zipClose (zipFile file, const char* global_comment) +{ + zip64_internal* zi; + int err = 0; + uLong size_centraldir = 0; + ZPOS64_T centraldir_pos_inzip; + ZPOS64_T pos; + + if (file == NULL) + return ZIP_PARAMERROR; + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment==NULL) + global_comment = zi->globalcomment; +#endif + + centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) + err = ZIP_ERRNO; + } + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_linkedlist(&(zi->central_dir)); + + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) + { + ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); + Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + + Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); + } + + if (err==ZIP_OK) + err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + + if(err == ZIP_OK) + err = Write_GlobalComment(zi, global_comment); + + if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} + +extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) +{ + char* p = pData; + int size = 0; + char* pNewHeader; + char* pTmp; + short header; + short dataSize; + + int retVal = ZIP_OK; + + if(pData == NULL || *dataLen < 4) + return ZIP_PARAMERROR; + + pNewHeader = (char*)ALLOC(*dataLen); + pTmp = pNewHeader; + + while(p < (pData + *dataLen)) + { + header = *(short*)p; + dataSize = *(((short*)p)+1); + + if( header == sHeader ) // Header found. + { + p += dataSize + 4; // skip it. do not copy to temp buffer + } + else + { + // Extra Info block should not be removed, So copy it to the temp buffer. + memcpy(pTmp, p, dataSize + 4); + p += dataSize + 4; + size += dataSize + 4; + } + + } + + if(size < *dataLen) + { + // clean old extra info block. + memset(pData,0, *dataLen); + + // copy the new extra info block over the old + if(size > 0) + memcpy(pData, pNewHeader, size); + + // set the new extra info size + *dataLen = size; + + retVal = ZIP_OK; + } + else + retVal = ZIP_ERRNO; + + TRYFREE(pNewHeader); + + return retVal; +}
diff --git a/src/third_party/zlib2/contrib/minizip/zip.h b/src/third_party/zlib2/contrib/minizip/zip.h new file mode 100644 index 0000000..8c06c0a --- /dev/null +++ b/src/third_party/zlib2/contrib/minizip/zip.h
@@ -0,0 +1,362 @@ +/* zip.h -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------- + + Changes + + See header of zip.h + +*/ + +#ifndef _zip12_H +#define _zip12_H + +#ifdef __cplusplus +extern "C" { +#endif + +//#define HAVE_BZIP2 + +#ifndef _ZLIB_H +#include "third_party/zlib/zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc64_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); + +extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int zip64)); + +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) + zip64 is set to 1 if a zip64 extended information block should be added to the local file header. + this MUST be '1' if the uncompressed size is >= 0xffffffff. + +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + + +extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int zip64)); +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting)); + +extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + int zip64 + )); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCrypting : crc of file to compress (needed for crypting) + */ + +extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase + )); + + +extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase, + int zip64 + )); +/* + Same than zipOpenNewFileInZip4, except + versionMadeBy : value for Version made by field + flag : value for flag field (compression level info will be added) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); + +extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, + ZPOS64_T uncompressed_size, + uLong crc32)); + +/* + Close the current file in the zipfile, for file opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + + +extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); +/* + zipRemoveExtraInfoBlock - Added by Mathias Svensson + + Remove extra information block from a extra information data for the local file header or central directory header + + It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode. + + 0x0001 is the signature header for the ZIP64 extra information blocks + + usage. + Remove ZIP64 Extra information from a central director extra field data + zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001); + + Remove ZIP64 Extra information from a Local File Header extra field data + zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip64_H */
diff --git a/src/third_party/zlib2/contrib/optimizations/chunkcopy.h b/src/third_party/zlib2/contrib/optimizations/chunkcopy.h new file mode 100644 index 0000000..38ba0ed --- /dev/null +++ b/src/third_party/zlib2/contrib/optimizations/chunkcopy.h
@@ -0,0 +1,444 @@ +/* chunkcopy.h -- fast chunk copy and set operations + * Copyright (C) 2017 ARM, Inc. + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#ifndef CHUNKCOPY_H +#define CHUNKCOPY_H + +#include <stdint.h> +#include "zutil.h" + +#define Z_STATIC_ASSERT(name, assert) typedef char name[(assert) ? 1 : -1] + +#if __STDC_VERSION__ >= 199901L +#define Z_RESTRICT restrict +#else +#define Z_RESTRICT +#endif + +#if defined(__clang__) || defined(__GNUC__) || defined(__llvm__) +#define Z_BUILTIN_MEMCPY __builtin_memcpy +#else +#define Z_BUILTIN_MEMCPY zmemcpy +#endif + +#if defined(INFLATE_CHUNK_SIMD_NEON) +#include <arm_neon.h> +typedef uint8x16_t z_vec128i_t; +#elif defined(INFLATE_CHUNK_SIMD_SSE2) +#include <emmintrin.h> +typedef __m128i z_vec128i_t; +#else +#error chunkcopy.h inflate chunk SIMD is not defined for your build target +#endif + +/* + * chunk copy type: the z_vec128i_t type size should be exactly 128-bits + * and equal to CHUNKCOPY_CHUNK_SIZE. + */ +#define CHUNKCOPY_CHUNK_SIZE sizeof(z_vec128i_t) + +Z_STATIC_ASSERT(vector_128_bits_wide, + CHUNKCOPY_CHUNK_SIZE == sizeof(int8_t) * 16); + +/* + * Ask the compiler to perform a wide, unaligned load with a machine + * instruction appropriate for the z_vec128i_t type. + */ +static inline z_vec128i_t loadchunk( + const unsigned char FAR* s) { + z_vec128i_t v; + Z_BUILTIN_MEMCPY(&v, s, sizeof(v)); + return v; +} + +/* + * Ask the compiler to perform a wide, unaligned store with a machine + * instruction appropriate for the z_vec128i_t type. + */ +static inline void storechunk( + unsigned char FAR* d, + const z_vec128i_t v) { + Z_BUILTIN_MEMCPY(d, &v, sizeof(v)); +} + +/* + * Perform a memcpy-like operation, assuming that length is non-zero and that + * it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if + * the length is shorter than this. + * + * It also guarantees that it will properly unroll the data if the distance + * between `out` and `from` is at least CHUNKCOPY_CHUNK_SIZE, which we rely on + * in chunkcopy_relaxed(). + * + * Aside from better memory bus utilisation, this means that short copies + * (CHUNKCOPY_CHUNK_SIZE bytes or fewer) will fall straight through the loop + * without iteration, which will hopefully make the branch prediction more + * reliable. + */ +static inline unsigned char FAR* chunkcopy_core( + unsigned char FAR* out, + const unsigned char FAR* from, + unsigned len) { + const int bump = (--len % CHUNKCOPY_CHUNK_SIZE) + 1; + storechunk(out, loadchunk(from)); + out += bump; + from += bump; + len /= CHUNKCOPY_CHUNK_SIZE; + while (len-- > 0) { + storechunk(out, loadchunk(from)); + out += CHUNKCOPY_CHUNK_SIZE; + from += CHUNKCOPY_CHUNK_SIZE; + } + return out; +} + +/* + * Like chunkcopy_core(), but avoid writing beyond of legal output. + * + * Accepts an additional pointer to the end of safe output. A generic safe + * copy would use (out + len), but it's normally the case that the end of the + * output buffer is beyond the end of the current copy, and this can still be + * exploited. + */ +static inline unsigned char FAR* chunkcopy_core_safe( + unsigned char FAR* out, + const unsigned char FAR* from, + unsigned len, + unsigned char FAR* limit) { + Assert(out + len <= limit, "chunk copy exceeds safety limit"); + if ((limit - out) < (ptrdiff_t)CHUNKCOPY_CHUNK_SIZE) { + const unsigned char FAR* Z_RESTRICT rfrom = from; + if (len & 8) { + Z_BUILTIN_MEMCPY(out, rfrom, 8); + out += 8; + rfrom += 8; + } + if (len & 4) { + Z_BUILTIN_MEMCPY(out, rfrom, 4); + out += 4; + rfrom += 4; + } + if (len & 2) { + Z_BUILTIN_MEMCPY(out, rfrom, 2); + out += 2; + rfrom += 2; + } + if (len & 1) { + *out++ = *rfrom++; + } + return out; + } + return chunkcopy_core(out, from, len); +} + +/* + * Perform short copies until distance can be rewritten as being at least + * CHUNKCOPY_CHUNK_SIZE. + * + * Assumes it's OK to overwrite at least the first 2*CHUNKCOPY_CHUNK_SIZE + * bytes of output even if the copy is shorter than this. This assumption + * holds within zlib inflate_fast(), which starts every iteration with at + * least 258 bytes of output space available (258 being the maximum length + * output from a single token; see inffast.c). + */ +static inline unsigned char FAR* chunkunroll_relaxed( + unsigned char FAR* out, + unsigned FAR* dist, + unsigned FAR* len) { + const unsigned char FAR* from = out - *dist; + while (*dist < *len && *dist < CHUNKCOPY_CHUNK_SIZE) { + storechunk(out, loadchunk(from)); + out += *dist; + *len -= *dist; + *dist += *dist; + } + return out; +} + +#if defined(INFLATE_CHUNK_SIMD_NEON) +/* + * v_load64_dup(): load *src as an unaligned 64-bit int and duplicate it in + * every 64-bit component of the 128-bit result (64-bit int splat). + */ +static inline z_vec128i_t v_load64_dup(const void* src) { + return vcombine_u8(vld1_u8(src), vld1_u8(src)); +} + +/* + * v_load32_dup(): load *src as an unaligned 32-bit int and duplicate it in + * every 32-bit component of the 128-bit result (32-bit int splat). + */ +static inline z_vec128i_t v_load32_dup(const void* src) { + int32_t i32; + Z_BUILTIN_MEMCPY(&i32, src, sizeof(i32)); + return vreinterpretq_u8_s32(vdupq_n_s32(i32)); +} + +/* + * v_load16_dup(): load *src as an unaligned 16-bit int and duplicate it in + * every 16-bit component of the 128-bit result (16-bit int splat). + */ +static inline z_vec128i_t v_load16_dup(const void* src) { + int16_t i16; + Z_BUILTIN_MEMCPY(&i16, src, sizeof(i16)); + return vreinterpretq_u8_s16(vdupq_n_s16(i16)); +} + +/* + * v_load8_dup(): load the 8-bit int *src and duplicate it in every 8-bit + * component of the 128-bit result (8-bit int splat). + */ +static inline z_vec128i_t v_load8_dup(const void* src) { + return vld1q_dup_u8((const uint8_t*)src); +} + +/* + * v_store_128(): store the 128-bit vec in a memory destination (that might + * not be 16-byte aligned) void* out. + */ +static inline void v_store_128(void* out, const z_vec128i_t vec) { + vst1q_u8(out, vec); +} + +#elif defined(INFLATE_CHUNK_SIMD_SSE2) +/* + * v_load64_dup(): load *src as an unaligned 64-bit int and duplicate it in + * every 64-bit component of the 128-bit result (64-bit int splat). + */ +static inline z_vec128i_t v_load64_dup(const void* src) { + int64_t i64; + Z_BUILTIN_MEMCPY(&i64, src, sizeof(i64)); + return _mm_set1_epi64x(i64); +} + +/* + * v_load32_dup(): load *src as an unaligned 32-bit int and duplicate it in + * every 32-bit component of the 128-bit result (32-bit int splat). + */ +static inline z_vec128i_t v_load32_dup(const void* src) { + int32_t i32; + Z_BUILTIN_MEMCPY(&i32, src, sizeof(i32)); + return _mm_set1_epi32(i32); +} + +/* + * v_load16_dup(): load *src as an unaligned 16-bit int and duplicate it in + * every 16-bit component of the 128-bit result (16-bit int splat). + */ +static inline z_vec128i_t v_load16_dup(const void* src) { + int16_t i16; + Z_BUILTIN_MEMCPY(&i16, src, sizeof(i16)); + return _mm_set1_epi16(i16); +} + +/* + * v_load8_dup(): load the 8-bit int *src and duplicate it in every 8-bit + * component of the 128-bit result (8-bit int splat). + */ +static inline z_vec128i_t v_load8_dup(const void* src) { + return _mm_set1_epi8(*(const char*)src); +} + +/* + * v_store_128(): store the 128-bit vec in a memory destination (that might + * not be 16-byte aligned) void* out. + */ +static inline void v_store_128(void* out, const z_vec128i_t vec) { + _mm_storeu_si128((__m128i*)out, vec); +} +#endif + +/* + * Perform an overlapping copy which behaves as a memset() operation, but + * supporting periods other than one, and assume that length is non-zero and + * that it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE*3 bytes of output + * even if the length is shorter than this. + */ +static inline unsigned char FAR* chunkset_core( + unsigned char FAR* out, + unsigned period, + unsigned len) { + z_vec128i_t v; + const int bump = ((len - 1) % sizeof(v)) + 1; + + switch (period) { + case 1: + v = v_load8_dup(out - 1); + v_store_128(out, v); + out += bump; + len -= bump; + while (len > 0) { + v_store_128(out, v); + out += sizeof(v); + len -= sizeof(v); + } + return out; + case 2: + v = v_load16_dup(out - 2); + v_store_128(out, v); + out += bump; + len -= bump; + if (len > 0) { + v = v_load16_dup(out - 2); + do { + v_store_128(out, v); + out += sizeof(v); + len -= sizeof(v); + } while (len > 0); + } + return out; + case 4: + v = v_load32_dup(out - 4); + v_store_128(out, v); + out += bump; + len -= bump; + if (len > 0) { + v = v_load32_dup(out - 4); + do { + v_store_128(out, v); + out += sizeof(v); + len -= sizeof(v); + } while (len > 0); + } + return out; + case 8: + v = v_load64_dup(out - 8); + v_store_128(out, v); + out += bump; + len -= bump; + if (len > 0) { + v = v_load64_dup(out - 8); + do { + v_store_128(out, v); + out += sizeof(v); + len -= sizeof(v); + } while (len > 0); + } + return out; + } + out = chunkunroll_relaxed(out, &period, &len); + return chunkcopy_core(out, out - period, len); +} + +/* + * Perform a memcpy-like operation, but assume that length is non-zero and that + * it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if + * the length is shorter than this. + * + * Unlike chunkcopy_core() above, no guarantee is made regarding the behaviour + * of overlapping buffers, regardless of the distance between the pointers. + * This is reflected in the `restrict`-qualified pointers, allowing the + * compiler to re-order loads and stores. + */ +static inline unsigned char FAR* chunkcopy_relaxed( + unsigned char FAR* Z_RESTRICT out, + const unsigned char FAR* Z_RESTRICT from, + unsigned len) { + return chunkcopy_core(out, from, len); +} + +/* + * Like chunkcopy_relaxed(), but avoid writing beyond of legal output. + * + * Unlike chunkcopy_core_safe() above, no guarantee is made regarding the + * behaviour of overlapping buffers, regardless of the distance between the + * pointers. This is reflected in the `restrict`-qualified pointers, allowing + * the compiler to re-order loads and stores. + * + * Accepts an additional pointer to the end of safe output. A generic safe + * copy would use (out + len), but it's normally the case that the end of the + * output buffer is beyond the end of the current copy, and this can still be + * exploited. + */ +static inline unsigned char FAR* chunkcopy_safe( + unsigned char FAR* out, + const unsigned char FAR* Z_RESTRICT from, + unsigned len, + unsigned char FAR* limit) { + Assert(out + len <= limit, "chunk copy exceeds safety limit"); + return chunkcopy_core_safe(out, from, len, limit); +} + +/* + * Perform chunky copy within the same buffer, where the source and destination + * may potentially overlap. + * + * Assumes that len > 0 on entry, and that it's safe to write at least + * CHUNKCOPY_CHUNK_SIZE*3 bytes to the output. + */ +static inline unsigned char FAR* chunkcopy_lapped_relaxed( + unsigned char FAR* out, + unsigned dist, + unsigned len) { + if (dist < len && dist < CHUNKCOPY_CHUNK_SIZE) { + return chunkset_core(out, dist, len); + } + return chunkcopy_core(out, out - dist, len); +} + +/* + * Behave like chunkcopy_lapped_relaxed(), but avoid writing beyond of legal + * output. + * + * Accepts an additional pointer to the end of safe output. A generic safe + * copy would use (out + len), but it's normally the case that the end of the + * output buffer is beyond the end of the current copy, and this can still be + * exploited. + */ +static inline unsigned char FAR* chunkcopy_lapped_safe( + unsigned char FAR* out, + unsigned dist, + unsigned len, + unsigned char FAR* limit) { + Assert(out + len <= limit, "chunk copy exceeds safety limit"); + if ((limit - out) < (ptrdiff_t)(3 * CHUNKCOPY_CHUNK_SIZE)) { + /* TODO(cavalcantii): try harder to optimise this */ + while (len-- > 0) { + *out = *(out - dist); + out++; + } + return out; + } + return chunkcopy_lapped_relaxed(out, dist, len); +} + +/* + * The chunk-copy code above deals with writing the decoded DEFLATE data to + * the output with SIMD methods to increase decode speed. Reading the input + * to the DEFLATE decoder with a wide, SIMD method can also increase decode + * speed. This option is supported on little endian machines, and reads the + * input data in 64-bit (8 byte) chunks. + */ + +#ifdef INFLATE_CHUNK_READ_64LE +/* + * Buffer the input in a uint64_t (8 bytes) in the wide input reading case. + */ +typedef uint64_t inflate_holder_t; + +/* + * Ask the compiler to perform a wide, unaligned load of a uint64_t using a + * machine instruction appropriate for the uint64_t type. + */ +static inline inflate_holder_t read64le(const unsigned char FAR *in) { + inflate_holder_t input; + Z_BUILTIN_MEMCPY(&input, in, sizeof(input)); + return input; +} +#else +/* + * Otherwise, buffer the input bits using zlib's default input buffer type. + */ +typedef unsigned long inflate_holder_t; + +#endif /* INFLATE_CHUNK_READ_64LE */ + +#undef Z_STATIC_ASSERT +#undef Z_RESTRICT +#undef Z_BUILTIN_MEMCPY + +#endif /* CHUNKCOPY_H */
diff --git a/src/third_party/zlib2/contrib/optimizations/inffast_chunk.c b/src/third_party/zlib2/contrib/optimizations/inffast_chunk.c new file mode 100644 index 0000000..4099edf --- /dev/null +++ b/src/third_party/zlib2/contrib/optimizations/inffast_chunk.c
@@ -0,0 +1,359 @@ +/* inffast_chunk.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "contrib/optimizations/inffast_chunk.h" +#include "contrib/optimizations/chunkcopy.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate() execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= INFLATE_FAST_MIN_INPUT (6 or 8 bytes) + strm->avail_out >= INFLATE_FAST_MIN_OUTPUT (258 bytes) + start >= strm->avail_out + state->bits < 8 + (state->hold >> state->bits) == 0 + strm->next_out[0..strm->avail_out] does not overlap with + strm->next_in[0..strm->avail_in] + strm->state->window is allocated with an additional + CHUNKCOPY_CHUNK_SIZE-1 bytes of padding beyond strm->state->wsize + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + INFLATE_FAST_MIN_INPUT: 6 or 8 bytes + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The wide input data reading option reads 64 input bits at a time. Thus, + if strm->avail_in >= 8, then there is enough input to avoid checking for + available input while decoding. Reading consumes the input with: + + hold |= read64le(in) << bits; + in += 6; + bits += 48; + + reporting 6 bytes of new input because |bits| is 0..15 (2 bytes rounded + up, worst case) and 6 bytes is enough to decode as noted above. At exit, + hold &= (1U << bits) - 1 drops excess input to keep the invariant: + + (state->hold >> state->bits) == 0 + + INFLATE_FAST_MIN_OUTPUT: 258 bytes + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + available output space while decoding. + */ +void ZLIB_INTERNAL inflate_fast_chunk_(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned char FAR *limit; /* safety limit for chunky copies */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + inflate_holder_t hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - (INFLATE_FAST_MIN_INPUT - 1)); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - (INFLATE_FAST_MIN_OUTPUT - 1)); + limit = out + strm->avail_out; +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = (state->wnext == 0 && whave >= wsize) ? wsize : state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { +#ifdef INFLATE_CHUNK_READ_64LE + hold |= read64le(in) << bits; + in += 6; + bits += 48; +#else + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; +#endif + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + *out++ = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { +#ifdef INFLATE_CHUNK_READ_64LE + hold |= read64le(in) << bits; + in += 6; + bits += 48; +#else + hold += (unsigned long)(*in++) << bits; + bits += 8; +#endif + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { +#ifdef INFLATE_CHUNK_READ_64LE + hold |= read64le(in) << bits; + in += 6; + bits += 48; +#else + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; +#endif + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { +#ifdef INFLATE_CHUNK_READ_64LE + hold |= read64le(in) << bits; + in += 6; + bits += 48; +#else + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } +#endif + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext >= op) { /* contiguous in window */ + from += wnext - op; + } + else { /* wrap around window */ + op -= wnext; + from += wsize - op; + if (op < len) { /* some from end of window */ + len -= op; + out = chunkcopy_safe(out, from, op, limit); + from = window; /* more from start of window */ + op = wnext; + /* This (rare) case can create a situation where + the first chunkcopy below must be checked. + */ + } + } + if (op < len) { /* still need some from output */ + out = chunkcopy_safe(out, from, op, limit); + len -= op; + /* When dist is small the amount of data that can be + copied from the window is also small, and progress + towards the dangerous end of the output buffer is + also small. This means that for trivial memsets and + for chunkunroll_relaxed() a safety check is + unnecessary. However, these conditions may not be + entered at all, and in that case it's possible that + the main copy is near the end. + */ + out = chunkunroll_relaxed(out, &dist, &len); + out = chunkcopy_safe(out, out - dist, len, limit); + } else { + /* from points to window, so there is no risk of + overlapping pointers requiring memset-like behaviour + */ + out = chunkcopy_safe(out, from, len, limit); + } + } + else { + /* Whole reference is in range of current output. No + range checks are necessary because we start with room + for at least 258 bytes of output, so unroll and roundoff + operations can write beyond `out+len` so long as they + stay within 258 bytes of `out`. + */ + out = chunkcopy_lapped_relaxed(out, dist, len); + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? + (INFLATE_FAST_MIN_INPUT - 1) + (last - in) : + (INFLATE_FAST_MIN_INPUT - 1) - (in - last)); + strm->avail_out = (unsigned)(out < end ? + (INFLATE_FAST_MIN_OUTPUT - 1) + (end - out) : + (INFLATE_FAST_MIN_OUTPUT - 1) - (out - end)); + state->hold = hold; + state->bits = bits; + + Assert((state->hold >> state->bits) == 0, "invalid input data state"); + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */
diff --git a/src/third_party/zlib2/contrib/optimizations/inffast_chunk.h b/src/third_party/zlib2/contrib/optimizations/inffast_chunk.h new file mode 100644 index 0000000..39c771b --- /dev/null +++ b/src/third_party/zlib2/contrib/optimizations/inffast_chunk.h
@@ -0,0 +1,26 @@ +/* inffast_chunk.h -- header to use inffast_chunk.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * Copyright (C) 2017 ARM, Inc. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#include "inffast.h" + +/* INFLATE_FAST_MIN_INPUT: the minimum number of input bytes needed so that + we can safely call inflate_fast() with only one up-front bounds check. One + length/distance code pair (15 bits for the length code, 5 bits for length + extra, 15 bits for the distance code, 13 bits for distance extra) requires + reading up to 48 input bits (6 bytes). The wide input data reading option + requires a little endian machine, and reads 64 input bits (8 bytes). +*/ +#ifdef INFLATE_CHUNK_READ_64LE +#undef INFLATE_FAST_MIN_INPUT +#define INFLATE_FAST_MIN_INPUT 8 +#endif + +void ZLIB_INTERNAL inflate_fast_chunk_ OF((z_streamp strm, unsigned start));
diff --git a/src/third_party/zlib2/contrib/optimizations/inflate.c b/src/third_party/zlib2/contrib/optimizations/inflate.c new file mode 100644 index 0000000..81d558b --- /dev/null +++ b/src/third_party/zlib2/contrib/optimizations/inflate.c
@@ -0,0 +1,1583 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "contrib/optimizations/inffast_chunk.h" +#include "contrib/optimizations/chunkcopy.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); + +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + state->check = 1L; /* 1L is the result of adler32() zero length data */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include <stdio.h> + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, end, copy) +z_streamp strm; +const Bytef *end; +unsigned copy; +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + unsigned wsize = 1U << state->wbits; + state->window = (unsigned char FAR *) + ZALLOC(strm, wsize + CHUNKCOPY_CHUNK_SIZE, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; +#ifdef INFLATE_CLEAR_UNUSED_UNDEFINED + /* Copies from the overflow portion of this buffer are undefined and + may cause analysis tools to raise a warning if we don't initialize + it. However, this undefined data overwrites other undefined data + and is subsequently either overwritten or left deliberately + undefined at the end of decode; so there's really no point. + */ + zmemzero(state->window + wsize, CHUNKCOPY_CHUNK_SIZE); +#endif + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= INFLATE_FAST_MIN_INPUT && + left >= INFLATE_FAST_MIN_OUTPUT) { + RESTORE(); + inflate_fast_chunk_(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + put = chunkcopy_safe(put, from, copy, put + left); + } + else { /* copy from output */ + copy = state->length; + if (copy > left) copy = left; + put = chunkcopy_lapped_safe(put, state->offset, copy, put + left); + } + left -= copy; + state->length -= copy; + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + /* We write a defined value in the unused space to help mark + * where the stream has ended. We don't use zeros as that can + * mislead clients relying on undefined behavior (i.e. assuming + * that the data is over when the buffer has a zero/null value). + */ + if (left >= CHUNKCOPY_CHUNK_SIZE) + memset(put, 0x55, CHUNKCOPY_CHUNK_SIZE); + else + memset(put, 0x55, left); + + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +const unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +}
diff --git a/src/third_party/zlib2/contrib/optimizations/slide_hash_neon.h b/src/third_party/zlib2/contrib/optimizations/slide_hash_neon.h new file mode 100644 index 0000000..26995d7 --- /dev/null +++ b/src/third_party/zlib2/contrib/optimizations/slide_hash_neon.h
@@ -0,0 +1,65 @@ +/* Copyright 2018 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ +#ifndef __SLIDE_HASH__NEON__ +#define __SLIDE_HASH__NEON__ + +#include "deflate.h" +#include <arm_neon.h> + +inline static void ZLIB_INTERNAL neon_slide_hash_update(Posf *hash, + const uInt hash_size, + const ush w_size) +{ + /* NEON 'Q' registers allow to store 128 bits, so we can load 8x16-bits + * values. For further details, check: + * ARM DHT 0002A, section 1.3.2 NEON Registers. + */ + const size_t chunk = sizeof(uint16x8_t) / sizeof(uint16_t); + /* Unrolling the operation yielded a compression performance boost in both + * ARMv7 (from 11.7% to 13.4%) and ARMv8 (from 3.7% to 7.5%) for HTML4 + * content. For full benchmarking data, check: http://crbug.com/863257. + */ + const size_t stride = 2*chunk; + const uint16x8_t v = vdupq_n_u16(w_size); + + for (Posf *end = hash + hash_size; hash != end; hash += stride) { + uint16x8_t m_low = vld1q_u16(hash); + uint16x8_t m_high = vld1q_u16(hash + chunk); + + /* The first 'q' in vqsubq_u16 makes these subtracts saturate to zero, + * replacing the ternary operator expression in the original code: + * (m >= wsize ? m - wsize : NIL). + */ + m_low = vqsubq_u16(m_low, v); + m_high = vqsubq_u16(m_high, v); + + vst1q_u16(hash, m_low); + vst1q_u16(hash + chunk, m_high); + } +} + + +inline static void ZLIB_INTERNAL neon_slide_hash(Posf *head, Posf *prev, + const unsigned short w_size, + const uInt hash_size) +{ + /* + * SIMD implementation for hash table rebase assumes: + * 1. hash chain offset (Pos) is 2 bytes. + * 2. hash table size is multiple of 32 bytes. + * #1 should be true as Pos is defined as "ush" + * #2 should be true as hash_bits are greater than 7 + */ + const size_t size = hash_size * sizeof(head[0]); + Assert(sizeof(Pos) == 2, "Wrong Pos size."); + Assert((size % sizeof(uint16x8_t) * 2) == 0, "Hash table size error."); + + neon_slide_hash_update(head, hash_size, w_size); +#ifndef FASTEST + neon_slide_hash_update(prev, w_size, w_size); +#endif +} + +#endif
diff --git a/src/third_party/zlib2/contrib/tests/fuzzers/BUILD.gn b/src/third_party/zlib2/contrib/tests/fuzzers/BUILD.gn new file mode 100644 index 0000000..c46b664 --- /dev/null +++ b/src/third_party/zlib2/contrib/tests/fuzzers/BUILD.gn
@@ -0,0 +1,45 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//testing/libfuzzer/fuzzer_test.gni") + +# root BUILD depends on this target. Needed for package discovery +group("fuzzers") { +} + +fuzzer_test("zlib_uncompress_fuzzer") { + sources = [ + "uncompress_fuzzer.cc", + ] + deps = [ + "../../../:zlib", + ] +} + +fuzzer_test("zlib_inflate_fuzzer") { + sources = [ + "inflate_fuzzer.cc", + ] + deps = [ + "../../../:zlib", + ] +} + +fuzzer_test("zlib_deflate_set_dictionary_fuzzer") { + sources = [ + "deflate_set_dictionary_fuzzer.cc", + ] + deps = [ + "../../../:zlib", + ] +} + +fuzzer_test("zlib_deflate_fuzzer") { + sources = [ + "deflate_fuzzer.cc", + ] + deps = [ + "../../../:zlib", + ] +}
diff --git a/src/third_party/zlib2/contrib/tests/fuzzers/deflate_fuzzer.cc b/src/third_party/zlib2/contrib/tests/fuzzers/deflate_fuzzer.cc new file mode 100644 index 0000000..6098ff1 --- /dev/null +++ b/src/third_party/zlib2/contrib/tests/fuzzers/deflate_fuzzer.cc
@@ -0,0 +1,47 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <cassert> +#include <vector> + +#include "third_party/zlib/zlib.h" + +static Bytef buffer[256 * 1024] = {0}; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // zlib's deflate requires non-zero input sizes + if (!size) + return 0; + + // We need to strip the 'const' for zlib. + std::vector<unsigned char> input_buffer{data, data+size}; + + uLongf buffer_length = static_cast<uLongf>(sizeof(buffer)); + + z_stream stream; + stream.next_in = input_buffer.data(); + stream.avail_in = size; + stream.total_in = size; + stream.next_out = buffer; + stream.avail_out = buffer_length; + stream.total_out = buffer_length; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + + if (Z_OK != deflateInit(&stream, Z_DEFAULT_COMPRESSION)) { + deflateEnd(&stream); + assert(false); + } + + auto deflate_result = deflate(&stream, Z_NO_FLUSH); + deflateEnd(&stream); + if (Z_OK != deflate_result) + assert(false); + + return 0; +}
diff --git a/src/third_party/zlib2/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc b/src/third_party/zlib2/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc new file mode 100644 index 0000000..febbfcb --- /dev/null +++ b/src/third_party/zlib2/contrib/tests/fuzzers/deflate_set_dictionary_fuzzer.cc
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> +#include <cassert> +#include <vector> + +#include "third_party/zlib/zlib.h" + +static Bytef buffer[256 * 1024] = {0}; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // We need to strip the 'const' for zlib. + std::vector<unsigned char> input_buffer{data, data + size}; + + uLongf buffer_length = static_cast<uLongf>(sizeof(buffer)); + + z_stream stream; + stream.next_in = input_buffer.data(); + stream.avail_in = size; + stream.total_in = size; + stream.next_out = buffer; + stream.avail_out = buffer_length; + stream.total_out = buffer_length; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + + if (Z_OK != deflateInit(&stream, Z_DEFAULT_COMPRESSION)) { + deflateEnd(&stream); + assert(false); + } + + auto deflate_set_dictionary_result = + deflateSetDictionary(&stream, data, size); + deflateEnd(&stream); + if (Z_OK != deflate_set_dictionary_result) + assert(false); + + return 0; +}
diff --git a/src/third_party/zlib2/contrib/tests/fuzzers/inflate_fuzzer.cc b/src/third_party/zlib2/contrib/tests/fuzzers/inflate_fuzzer.cc new file mode 100644 index 0000000..44f9c72 --- /dev/null +++ b/src/third_party/zlib2/contrib/tests/fuzzers/inflate_fuzzer.cc
@@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <cassert> +#include <vector> + +#include "third_party/zlib/zlib.h" + +static Bytef buffer[256 * 1024] = {0}; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // We need to strip the 'const' for zlib + std::vector<unsigned char> input_buffer{data, data+size}; + + uLongf buffer_length = static_cast<uLongf>(sizeof(buffer)); + + z_stream stream; + stream.next_in = input_buffer.data(); + stream.avail_in = size; + stream.total_in = size; + stream.next_out = buffer; + stream.avail_out = buffer_length; + stream.total_out = buffer_length; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + + if (Z_OK != inflateInit(&stream)) { + inflateEnd(&stream); + assert(false); + } + + inflate(&stream, Z_NO_FLUSH); + inflateEnd(&stream); + + return 0; +}
diff --git a/src/third_party/zlib2/contrib/tests/fuzzers/uncompress_fuzzer.cc b/src/third_party/zlib2/contrib/tests/fuzzers/uncompress_fuzzer.cc new file mode 100644 index 0000000..bca5244 --- /dev/null +++ b/src/third_party/zlib2/contrib/tests/fuzzers/uncompress_fuzzer.cc
@@ -0,0 +1,21 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#include "third_party/zlib/zlib.h" + +static Bytef buffer[256 * 1024] = {0}; + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + uLongf buffer_length = static_cast<uLongf>(sizeof(buffer)); + if (Z_OK != + uncompress(buffer, &buffer_length, data, static_cast<uLong>(size))) { + return 0; + } + return 0; +}
diff --git a/src/third_party/zlib2/crc32.c b/src/third_party/zlib2/crc32.c new file mode 100644 index 0000000..e95b908 --- /dev/null +++ b/src/third_party/zlib2/crc32.c
@@ -0,0 +1,524 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. + */ + +#ifdef MAKECRCH +# include <stdio.h> +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "deflate.h" +#include "x86.h" +#include "zutil.h" /* for STDC and FAR definitions */ + +#if defined(CRC32_SIMD_SSE42_PCLMUL) +#include "crc32_simd.h" +#elif defined(CRC32_ARMV8_CRC32) +#include "arm_features.h" +#include "crc32_simd.h" +#endif + +/* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif +#ifdef BYFOUR + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, z_size_t)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, z_size_t)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local z_crc_t FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const z_crc_t FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + z_crc_t c; + int n, k; + z_crc_t poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (z_crc_t)1 << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (z_crc_t)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = ZSWAP32(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = ZSWAP32(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const z_crc_t FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const z_crc_t FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const z_crc_t FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const z_crc_t FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32_z(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + /* + * zlib convention is to call crc32(0, NULL, 0); before making + * calls to crc32(). So this is a good, early (and infrequent) + * place to cache CPU features if needed for those later, more + * interesting crc32() calls. + */ +#if defined(CRC32_SIMD_SSE42_PCLMUL) + /* + * Use x86 sse4.2+pclmul SIMD to compute the crc32. Since this + * routine can be freely used, check CPU features here. + */ + if (buf == Z_NULL) { + if (!len) /* Assume user is calling crc32(0, NULL, 0); */ + x86_check_features(); + return 0UL; + } + + if (x86_cpu_enable_simd && len >= Z_CRC32_SSE42_MINIMUM_LENGTH) { + /* crc32 16-byte chunks */ + z_size_t chunk_size = len & ~Z_CRC32_SSE42_CHUNKSIZE_MASK; + crc = ~crc32_sse42_simd_(buf, chunk_size, ~(uint32_t)crc); + /* check remaining data */ + len -= chunk_size; + if (!len) + return crc; + /* Fall into the default crc32 for the remaining data. */ + buf += chunk_size; + } +#else + if (buf == Z_NULL) { + return 0UL; + } +#endif /* CRC32_SIMD_SSE42_PCLMUL */ + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + z_crc_t endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ +#if defined(CRC32_ARMV8_CRC32) + /* We got to verify ARM CPU features, so exploit the common usage pattern + * of calling this function with Z_NULL for an initial valid crc value. + * This allows to cache the result of the feature check and avoid extraneous + * function calls. + * TODO: try to move this to crc32_z if we don't loose performance on ARM. + */ + if (buf == Z_NULL) { + if (!len) /* Assume user is calling crc32(0, NULL, 0); */ + arm_check_features(); + return 0UL; + } + + if (arm_cpu_enable_crc32) + return armv8_crc32_little(crc, buf, len); +#endif + return crc32_z(crc, buf, len); +} + +#ifdef BYFOUR + +/* + This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit + integer pointer type. This violates the strict aliasing rule, where a + compiler can assume, for optimization purposes, that two pointers to + fundamentally different types won't ever point to the same memory. This can + manifest as a problem only if one of the pointers is written to. This code + only reads from those pointers. So long as this code remains isolated in + this compilation unit, there won't be a problem. For this reason, this code + should not be copied and pasted into a compilation unit in which other code + writes to the buffer that is passed to these routines. + */ + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = (z_crc_t)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *buf4++; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = ZSWAP32((z_crc_t)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(ZSWAP32(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +ZLIB_INTERNAL void crc_reset(deflate_state *const s) +{ + if (x86_cpu_enable_simd) { + crc_fold_init(s); + return; + } + s->strm->adler = crc32(0L, Z_NULL, 0); +} + +ZLIB_INTERNAL void crc_finalize(deflate_state *const s) +{ + if (x86_cpu_enable_simd) + s->strm->adler = crc_fold_512to32(s); +} + +ZLIB_INTERNAL void copy_with_crc(z_streamp strm, Bytef *dst, long size) +{ + if (x86_cpu_enable_simd) { + crc_fold_copy(strm->state, dst, strm->next_in, size); + return; + } + zmemcpy(dst, strm->next_in, size); + strm->adler = crc32(strm->adler, dst, size); +}
diff --git a/src/third_party/zlib2/crc32.h b/src/third_party/zlib2/crc32.h new file mode 100644 index 0000000..9e0c778 --- /dev/null +++ b/src/third_party/zlib2/crc32.h
@@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const z_crc_t FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +};
diff --git a/src/third_party/zlib2/crc32_simd.c b/src/third_party/zlib2/crc32_simd.c new file mode 100644 index 0000000..988f00b --- /dev/null +++ b/src/third_party/zlib2/crc32_simd.c
@@ -0,0 +1,270 @@ +/* crc32_simd.c + * + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include "crc32_simd.h" + +#if defined(CRC32_SIMD_SSE42_PCLMUL) + +/* + * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer + * length must be at least 64, and a multiple of 16. Based on: + * + * "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction" + * V. Gopal, E. Ozturk, et al., 2009, http://intel.ly/2ySEwL0 + */ + +#include <emmintrin.h> +#include <smmintrin.h> +#include <wmmintrin.h> + +uint32_t ZLIB_INTERNAL crc32_sse42_simd_( /* SSE4.2+PCLMUL */ + const unsigned char *buf, + z_size_t len, + uint32_t crc) +{ + /* + * Definitions of the bit-reflected domain constants k1,k2,k3, etc and + * the CRC32+Barrett polynomials given at the end of the paper. + */ + static const uint64_t zalign(16) k1k2[] = { 0x0154442bd4, 0x01c6e41596 }; + static const uint64_t zalign(16) k3k4[] = { 0x01751997d0, 0x00ccaa009e }; + static const uint64_t zalign(16) k5k0[] = { 0x0163cd6124, 0x0000000000 }; + static const uint64_t zalign(16) poly[] = { 0x01db710641, 0x01f7011641 }; + + __m128i x0, x1, x2, x3, x4, x5, x6, x7, x8, y5, y6, y7, y8; + + /* + * There's at least one block of 64. + */ + x1 = _mm_loadu_si128((__m128i *)(buf + 0x00)); + x2 = _mm_loadu_si128((__m128i *)(buf + 0x10)); + x3 = _mm_loadu_si128((__m128i *)(buf + 0x20)); + x4 = _mm_loadu_si128((__m128i *)(buf + 0x30)); + + x1 = _mm_xor_si128(x1, _mm_cvtsi32_si128(crc)); + + x0 = _mm_load_si128((__m128i *)k1k2); + + buf += 64; + len -= 64; + + /* + * Parallel fold blocks of 64, if any. + */ + while (len >= 64) + { + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x6 = _mm_clmulepi64_si128(x2, x0, 0x00); + x7 = _mm_clmulepi64_si128(x3, x0, 0x00); + x8 = _mm_clmulepi64_si128(x4, x0, 0x00); + + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x2 = _mm_clmulepi64_si128(x2, x0, 0x11); + x3 = _mm_clmulepi64_si128(x3, x0, 0x11); + x4 = _mm_clmulepi64_si128(x4, x0, 0x11); + + y5 = _mm_loadu_si128((__m128i *)(buf + 0x00)); + y6 = _mm_loadu_si128((__m128i *)(buf + 0x10)); + y7 = _mm_loadu_si128((__m128i *)(buf + 0x20)); + y8 = _mm_loadu_si128((__m128i *)(buf + 0x30)); + + x1 = _mm_xor_si128(x1, x5); + x2 = _mm_xor_si128(x2, x6); + x3 = _mm_xor_si128(x3, x7); + x4 = _mm_xor_si128(x4, x8); + + x1 = _mm_xor_si128(x1, y5); + x2 = _mm_xor_si128(x2, y6); + x3 = _mm_xor_si128(x3, y7); + x4 = _mm_xor_si128(x4, y8); + + buf += 64; + len -= 64; + } + + /* + * Fold into 128-bits. + */ + x0 = _mm_load_si128((__m128i *)k3k4); + + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x1 = _mm_xor_si128(x1, x2); + x1 = _mm_xor_si128(x1, x5); + + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x1 = _mm_xor_si128(x1, x3); + x1 = _mm_xor_si128(x1, x5); + + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x1 = _mm_xor_si128(x1, x4); + x1 = _mm_xor_si128(x1, x5); + + /* + * Single fold blocks of 16, if any. + */ + while (len >= 16) + { + x2 = _mm_loadu_si128((__m128i *)buf); + + x5 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_clmulepi64_si128(x1, x0, 0x11); + x1 = _mm_xor_si128(x1, x2); + x1 = _mm_xor_si128(x1, x5); + + buf += 16; + len -= 16; + } + + /* + * Fold 128-bits to 64-bits. + */ + x2 = _mm_clmulepi64_si128(x1, x0, 0x10); + x3 = _mm_setr_epi32(~0, 0, ~0, 0); + x1 = _mm_srli_si128(x1, 8); + x1 = _mm_xor_si128(x1, x2); + + x0 = _mm_loadl_epi64((__m128i*)k5k0); + + x2 = _mm_srli_si128(x1, 4); + x1 = _mm_and_si128(x1, x3); + x1 = _mm_clmulepi64_si128(x1, x0, 0x00); + x1 = _mm_xor_si128(x1, x2); + + /* + * Barret reduce to 32-bits. + */ + x0 = _mm_load_si128((__m128i*)poly); + + x2 = _mm_and_si128(x1, x3); + x2 = _mm_clmulepi64_si128(x2, x0, 0x10); + x2 = _mm_and_si128(x2, x3); + x2 = _mm_clmulepi64_si128(x2, x0, 0x00); + x1 = _mm_xor_si128(x1, x2); + + /* + * Return the crc32. + */ + return _mm_extract_epi32(x1, 1); +} + +#elif defined(CRC32_ARMV8_CRC32) + +/* CRC32 checksums using ARMv8-a crypto instructions. + * + * TODO: implement a version using the PMULL instruction. + */ + +#if defined(__clang__) +/* CRC32 intrinsics are #ifdef'ed out of arm_acle.h unless we build with an + * armv8 target, which is incompatible with ThinLTO optimizations on Android. + * (Namely, mixing and matching different module-level targets makes ThinLTO + * warn, and Android defaults to armv7-a. This restriction does not apply to + * function-level `target`s, however.) + * + * Since we only need four crc intrinsics, and since clang's implementation of + * those are just wrappers around compiler builtins, it's simplest to #define + * those builtins directly. If this #define list grows too much (or we depend on + * an intrinsic that isn't a trivial wrapper), we may have to find a better way + * to go about this. + * + * NOTE: clang currently complains that "'+soft-float-abi' is not a recognized + * feature for this target (ignoring feature)." This appears to be a harmless + * bug in clang. + */ +#define __crc32b __builtin_arm_crc32b +#define __crc32d __builtin_arm_crc32d +#define __crc32w __builtin_arm_crc32w +#define __crc32cw __builtin_arm_crc32cw + +#if defined(__aarch64__) +#define TARGET_ARMV8_WITH_CRC __attribute__((target("crc"))) +#else // !defined(__aarch64__) +#define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc"))) +#endif // defined(__aarch64__) + +#elif defined(__GNUC__) +/* For GCC, we are setting CRC extensions at module level, so ThinLTO is not + * allowed. We can just include arm_acle.h. + */ +#include <arm_acle.h> +#define TARGET_ARMV8_WITH_CRC +#else // !defined(__GNUC__) && !defined(_aarch64__) +#error ARM CRC32 SIMD extensions only supported for Clang and GCC +#endif + +TARGET_ARMV8_WITH_CRC +uint32_t ZLIB_INTERNAL armv8_crc32_little(unsigned long crc, + const unsigned char *buf, + z_size_t len) +{ + uint32_t c = (uint32_t) ~crc; + + while (len && ((uintptr_t)buf & 7)) { + c = __crc32b(c, *buf++); + --len; + } + + const uint64_t *buf8 = (const uint64_t *)buf; + + while (len >= 64) { + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + c = __crc32d(c, *buf8++); + len -= 64; + } + + while (len >= 8) { + c = __crc32d(c, *buf8++); + len -= 8; + } + + buf = (const unsigned char *)buf8; + + while (len--) { + c = __crc32b(c, *buf++); + } + + return ~c; +} + +TARGET_ARMV8_WITH_CRC +Pos ZLIB_INTERNAL insert_string_arm(deflate_state *const s, const Pos str) +{ + Pos ret; + unsigned *ip, val, h = 0; + + ip = (unsigned *)&s->window[str]; + val = *ip; + + if (s->level >= 6) + val &= 0xFFFFFF; + + /* We use CRC32C (Castagnoli) to ensure that the compressed output + * will match between Intel x ARM. + * Unlike the case of data integrity checks for GZIP format where the + * polynomial used is defined (https://tools.ietf.org/html/rfc1952#page-11), + * here it is just a hash function for the hash table used while + * performing compression. + */ + h = __crc32cw(h, val); + + ret = s->head[h & s->hash_mask]; + s->head[h & s->hash_mask] = str; + s->prev[str & s->w_mask] = ret; + return ret; +} + +#endif
diff --git a/src/third_party/zlib2/crc32_simd.h b/src/third_party/zlib2/crc32_simd.h new file mode 100644 index 0000000..08f1756 --- /dev/null +++ b/src/third_party/zlib2/crc32_simd.h
@@ -0,0 +1,41 @@ +/* crc32_simd.h + * + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ + +#include <stdint.h> + +#include "zconf.h" +#include "zutil.h" +#include "deflate.h" + +/* + * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer + * length must be at least 64, and a multiple of 16. + */ +uint32_t ZLIB_INTERNAL crc32_sse42_simd_( + const unsigned char *buf, + z_size_t len, + uint32_t crc); + +/* + * crc32_sse42_simd_ buffer size constraints: see the use in zlib/crc32.c + * for computing the crc32 of an arbitrary length buffer. + */ +#define Z_CRC32_SSE42_MINIMUM_LENGTH 64 +#define Z_CRC32_SSE42_CHUNKSIZE_MASK 15 + +/* + * CRC32 checksums using ARMv8-a crypto instructions. + */ +uint32_t ZLIB_INTERNAL armv8_crc32_little(unsigned long crc, + const unsigned char* buf, + z_size_t len); + +/* + * Insert hash string. + */ +Pos ZLIB_INTERNAL insert_string_arm(deflate_state *const s, const Pos str); +
diff --git a/src/third_party/zlib2/crc_folding.c b/src/third_party/zlib2/crc_folding.c new file mode 100644 index 0000000..48d7774 --- /dev/null +++ b/src/third_party/zlib2/crc_folding.c
@@ -0,0 +1,493 @@ +/* + * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ + * instruction. + * + * A white paper describing this algorithm can be found at: + * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Authors: + * Wajdi Feghali <wajdi.k.feghali@intel.com> + * Jim Guilford <james.guilford@intel.com> + * Vinodh Gopal <vinodh.gopal@intel.com> + * Erdinc Ozturk <erdinc.ozturk@intel.com> + * Jim Kukunas <james.t.kukunas@linux.intel.com> + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "deflate.h" + +#include <inttypes.h> +#include <emmintrin.h> +#include <immintrin.h> +#include <wmmintrin.h> + +#define CRC_LOAD(s) \ + do { \ + __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0);\ + __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1);\ + __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2);\ + __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3);\ + __m128i xmm_crc_part = _mm_loadu_si128((__m128i *)s->crc0 + 4); + +#define CRC_SAVE(s) \ + _mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0);\ + _mm_storeu_si128((__m128i *)s->crc0 + 1, xmm_crc1);\ + _mm_storeu_si128((__m128i *)s->crc0 + 2, xmm_crc2);\ + _mm_storeu_si128((__m128i *)s->crc0 + 3, xmm_crc3);\ + _mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part);\ + } while (0); + +ZLIB_INTERNAL void crc_fold_init(deflate_state *const s) +{ + CRC_LOAD(s) + + xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); + xmm_crc1 = _mm_setzero_si128(); + xmm_crc2 = _mm_setzero_si128(); + xmm_crc3 = _mm_setzero_si128(); + + CRC_SAVE(s) + + s->strm->adler = 0; +} + +local void fold_1(deflate_state *const s, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3) +{ + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + + __m128i x_tmp3; + __m128 ps_crc0, ps_crc3, ps_res; + + x_tmp3 = *xmm_crc3; + + *xmm_crc3 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_res = _mm_xor_ps(ps_crc0, ps_crc3); + + *xmm_crc0 = *xmm_crc1; + *xmm_crc1 = *xmm_crc2; + *xmm_crc2 = x_tmp3; + *xmm_crc3 = _mm_castps_si128(ps_res); +} + +local void fold_2(deflate_state *const s, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3) +{ + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + + __m128i x_tmp3, x_tmp2; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20; + + x_tmp3 = *xmm_crc3; + x_tmp2 = *xmm_crc2; + + *xmm_crc3 = *xmm_crc1; + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_res31= _mm_xor_ps(ps_crc3, ps_crc1); + + *xmm_crc2 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_res20= _mm_xor_ps(ps_crc0, ps_crc2); + + *xmm_crc0 = x_tmp2; + *xmm_crc1 = x_tmp3; + *xmm_crc2 = _mm_castps_si128(ps_res20); + *xmm_crc3 = _mm_castps_si128(ps_res31); +} + +local void fold_3(deflate_state *const s, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3) +{ + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + + __m128i x_tmp3; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10; + + x_tmp3 = *xmm_crc3; + + *xmm_crc3 = *xmm_crc2; + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3); + + *xmm_crc2 = *xmm_crc1; + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_res21= _mm_xor_ps(ps_crc1, ps_crc2); + + *xmm_crc1 = *xmm_crc0; + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_res10= _mm_xor_ps(ps_crc0, ps_crc1); + + *xmm_crc0 = x_tmp3; + *xmm_crc1 = _mm_castps_si128(ps_res10); + *xmm_crc2 = _mm_castps_si128(ps_res21); + *xmm_crc3 = _mm_castps_si128(ps_res32); +} + +local void fold_4(deflate_state *const s, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3) +{ + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + + __m128i x_tmp0, x_tmp1, x_tmp2, x_tmp3; + __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3; + __m128 ps_t0, ps_t1, ps_t2, ps_t3; + __m128 ps_res0, ps_res1, ps_res2, ps_res3; + + x_tmp0 = *xmm_crc0; + x_tmp1 = *xmm_crc1; + x_tmp2 = *xmm_crc2; + x_tmp3 = *xmm_crc3; + + *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); + x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10); + ps_crc0 = _mm_castsi128_ps(*xmm_crc0); + ps_t0 = _mm_castsi128_ps(x_tmp0); + ps_res0 = _mm_xor_ps(ps_crc0, ps_t0); + + *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); + x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10); + ps_crc1 = _mm_castsi128_ps(*xmm_crc1); + ps_t1 = _mm_castsi128_ps(x_tmp1); + ps_res1 = _mm_xor_ps(ps_crc1, ps_t1); + + *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); + x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10); + ps_crc2 = _mm_castsi128_ps(*xmm_crc2); + ps_t2 = _mm_castsi128_ps(x_tmp2); + ps_res2 = _mm_xor_ps(ps_crc2, ps_t2); + + *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01); + x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10); + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + ps_t3 = _mm_castsi128_ps(x_tmp3); + ps_res3 = _mm_xor_ps(ps_crc3, ps_t3); + + *xmm_crc0 = _mm_castps_si128(ps_res0); + *xmm_crc1 = _mm_castps_si128(ps_res1); + *xmm_crc2 = _mm_castps_si128(ps_res2); + *xmm_crc3 = _mm_castps_si128(ps_res3); +} + +local const unsigned zalign(32) pshufb_shf_table[60] = { + 0x84838281,0x88878685,0x8c8b8a89,0x008f8e8d, /* shl 15 (16 - 1)/shr1 */ + 0x85848382,0x89888786,0x8d8c8b8a,0x01008f8e, /* shl 14 (16 - 3)/shr2 */ + 0x86858483,0x8a898887,0x8e8d8c8b,0x0201008f, /* shl 13 (16 - 4)/shr3 */ + 0x87868584,0x8b8a8988,0x8f8e8d8c,0x03020100, /* shl 12 (16 - 4)/shr4 */ + 0x88878685,0x8c8b8a89,0x008f8e8d,0x04030201, /* shl 11 (16 - 5)/shr5 */ + 0x89888786,0x8d8c8b8a,0x01008f8e,0x05040302, /* shl 10 (16 - 6)/shr6 */ + 0x8a898887,0x8e8d8c8b,0x0201008f,0x06050403, /* shl 9 (16 - 7)/shr7 */ + 0x8b8a8988,0x8f8e8d8c,0x03020100,0x07060504, /* shl 8 (16 - 8)/shr8 */ + 0x8c8b8a89,0x008f8e8d,0x04030201,0x08070605, /* shl 7 (16 - 9)/shr9 */ + 0x8d8c8b8a,0x01008f8e,0x05040302,0x09080706, /* shl 6 (16 -10)/shr10*/ + 0x8e8d8c8b,0x0201008f,0x06050403,0x0a090807, /* shl 5 (16 -11)/shr11*/ + 0x8f8e8d8c,0x03020100,0x07060504,0x0b0a0908, /* shl 4 (16 -12)/shr12*/ + 0x008f8e8d,0x04030201,0x08070605,0x0c0b0a09, /* shl 3 (16 -13)/shr13*/ + 0x01008f8e,0x05040302,0x09080706,0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/ + 0x0201008f,0x06050403,0x0a090807,0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ +}; + +local void partial_fold(deflate_state *const s, const size_t len, + __m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, + __m128i *xmm_crc_part) +{ + + const __m128i xmm_fold4 = _mm_set_epi32( + 0x00000001, 0x54442bd4, + 0x00000001, 0xc6e41596); + const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080); + + __m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3; + __m128i xmm_a0_0, xmm_a0_1; + __m128 ps_crc3, psa0_0, psa0_1, ps_res; + + xmm_shl = _mm_load_si128((__m128i *)pshufb_shf_table + (len - 1)); + xmm_shr = xmm_shl; + xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3); + + xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl); + + *xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr); + xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl); + *xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1); + + *xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr); + xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl); + *xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2); + + *xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr); + xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl); + *xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3); + + *xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr); + *xmm_crc_part = _mm_shuffle_epi8(*xmm_crc_part, xmm_shl); + *xmm_crc3 = _mm_or_si128(*xmm_crc3, *xmm_crc_part); + + xmm_a0_1 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x10); + xmm_a0_0 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x01); + + ps_crc3 = _mm_castsi128_ps(*xmm_crc3); + psa0_0 = _mm_castsi128_ps(xmm_a0_0); + psa0_1 = _mm_castsi128_ps(xmm_a0_1); + + ps_res = _mm_xor_ps(ps_crc3, psa0_0); + ps_res = _mm_xor_ps(ps_res, psa0_1); + + *xmm_crc3 = _mm_castps_si128(ps_res); +} + +ZLIB_INTERNAL void crc_fold_copy(deflate_state *const s, + unsigned char *dst, const unsigned char *src, long len) +{ + unsigned long algn_diff; + __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; + + CRC_LOAD(s) + + if (len < 16) { + if (len == 0) + return; + goto partial; + } + + algn_diff = 0 - (uintptr_t)src & 0xF; + if (algn_diff) { + xmm_crc_part = _mm_loadu_si128((__m128i *)src); + _mm_storeu_si128((__m128i *)dst, xmm_crc_part); + + dst += algn_diff; + src += algn_diff; + len -= algn_diff; + + partial_fold(s, algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, + &xmm_crc_part); + } + + while ((len -= 64) >= 0) { + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + xmm_t3 = _mm_load_si128((__m128i *)src + 3); + + fold_4(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); + _mm_storeu_si128((__m128i *)dst + 3, xmm_t3); + + xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); + + src += 64; + dst += 64; + } + + /* + * len = num bytes left - 64 + */ + if (len + 16 >= 0) { + len += 16; + + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + + fold_3(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); + + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); + + if (len == 0) + goto done; + + dst += 48; + src += 48; + } else if (len + 32 >= 0) { + len += 32; + + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + + fold_2(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); + + if (len == 0) + goto done; + + dst += 32; + src += 32; + } else if (len + 48 >= 0) { + len += 48; + + xmm_t0 = _mm_load_si128((__m128i *)src); + + fold_1(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + _mm_storeu_si128((__m128i *)dst, xmm_t0); + + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + + if (len == 0) + goto done; + + dst += 16; + src += 16; + } else { + len += 64; + if (len == 0) + goto done; + } + +partial: + +#if defined(_MSC_VER) + /* VS does not permit the use of _mm_set_epi64x in 32-bit builds */ + { + int32_t parts[4] = {0, 0, 0, 0}; + memcpy(&parts, src, len); + xmm_crc_part = _mm_set_epi32(parts[3], parts[2], parts[1], parts[0]); + } +#else + { + int64_t parts[2] = {0, 0}; + memcpy(&parts, src, len); + xmm_crc_part = _mm_set_epi64x(parts[1], parts[0]); + } +#endif + + _mm_storeu_si128((__m128i *)dst, xmm_crc_part); + partial_fold(s, len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, + &xmm_crc_part); +done: + CRC_SAVE(s) +} + +local const unsigned zalign(16) crc_k[] = { + 0xccaa009e, 0x00000000, /* rk1 */ + 0x751997d0, 0x00000001, /* rk2 */ + 0xccaa009e, 0x00000000, /* rk5 */ + 0x63cd6124, 0x00000001, /* rk6 */ + 0xf7011640, 0x00000001, /* rk7 */ + 0xdb710640, 0x00000001 /* rk8 */ +}; + +local const unsigned zalign(16) crc_mask[4] = { + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 +}; + +local const unsigned zalign(16) crc_mask2[4] = { + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) +{ + const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); + const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); + + unsigned crc; + __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; + + CRC_LOAD(s) + + /* + * k1 + */ + crc_fold = _mm_load_si128((__m128i *)crc_k); + + x_tmp0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x10); + xmm_crc0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x01); + xmm_crc1 = _mm_xor_si128(xmm_crc1, x_tmp0); + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_crc0); + + x_tmp1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x10); + xmm_crc1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x01); + xmm_crc2 = _mm_xor_si128(xmm_crc2, x_tmp1); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_crc1); + + x_tmp2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x10); + xmm_crc2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x01); + xmm_crc3 = _mm_xor_si128(xmm_crc3, x_tmp2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + + /* + * k5 + */ + crc_fold = _mm_load_si128((__m128i *)crc_k + 1); + + xmm_crc0 = xmm_crc3; + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); + xmm_crc0 = _mm_srli_si128(xmm_crc0, 8); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); + + xmm_crc0 = xmm_crc3; + xmm_crc3 = _mm_slli_si128(xmm_crc3, 4); + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); + xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask2); + + /* + * k7 + */ + xmm_crc1 = xmm_crc3; + xmm_crc2 = xmm_crc3; + crc_fold = _mm_load_si128((__m128i *)crc_k + 2); + + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask); + + xmm_crc2 = xmm_crc3; + xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1); + + crc = _mm_extract_epi32(xmm_crc3, 2); + return ~crc; + CRC_SAVE(s) +}
diff --git a/src/third_party/zlib2/deflate.c b/src/third_party/zlib2/deflate.c new file mode 100644 index 0000000..c950d6f --- /dev/null +++ b/src/third_party/zlib2/deflate.c
@@ -0,0 +1,2304 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://tools.ietf.org/html/rfc1951 + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ +#include <assert.h> +#include "deflate.h" +#include "x86.h" + +#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) +#include "contrib/optimizations/slide_hash_neon.h" +#endif +/* We need crypto extension crc32 to implement optimized hash in + * insert_string. + */ +#if defined(CRC32_ARMV8_CRC32) +#include "arm_features.h" +#include "crc32_simd.h" +#endif + +const char deflate_copyright[] = + " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local int deflateStateCheck OF((z_streamp strm)); +local void slide_hash OF((deflate_state *s)); +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +unsigned ZLIB_INTERNAL deflate_read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV +# pragma message("Assembler code may have bugs -- use at your own risk") + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef ZLIB_DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* From crc32.c */ +extern void ZLIB_INTERNAL crc_reset(deflate_state *const s); +extern void ZLIB_INTERNAL crc_finalize(deflate_state *const s); +extern void ZLIB_INTERNAL copy_with_crc(z_streamp strm, Bytef *dst, long size); + +#ifdef _MSC_VER +#define INLINE __inline +#else +#define INLINE inline +#endif + +/* Inline optimisation */ +local INLINE Pos insert_string_sse(deflate_state *const s, const Pos str); + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). + */ +local INLINE Pos insert_string_c(deflate_state *const s, const Pos str) +{ + Pos ret; + + UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]); +#ifdef FASTEST + ret = s->head[s->ins_h]; +#else + ret = s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = str; + + return ret; +} + +local INLINE Pos insert_string(deflate_state *const s, const Pos str) +{ +/* String dictionary insertion: faster symbol hashing has a positive impact + * on data compression speeds (around 20% on Intel and 36% on ARM Cortex big + * cores). + * A misfeature is that the generated compressed output will differ from + * vanilla zlib (even though it is still valid 'DEFLATE-d' content). + * + * We offer here a way to disable the optimization if there is the expectation + * that compressed content should match when compared to vanilla zlib. + */ +#if !defined(CHROMIUM_ZLIB_NO_CASTAGNOLI) +#if defined(CRC32_ARMV8_CRC32) + if (arm_cpu_enable_crc32) + return insert_string_arm(s, str); +#endif + if (x86_cpu_enable_simd) + return insert_string_sse(s, str); +#endif + return insert_string_c(s, str); +} + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +local void slide_hash(s) + deflate_state *s; +{ +#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) + /* NEON based hash table rebase. */ + return neon_slide_hash(s->head, s->prev, s->w_size, s->hash_size); +#endif + unsigned n, m; + Posf *p; + uInt wsize = s->w_size; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + } while (--n); + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif +} + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + unsigned window_padding = 8; + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + x86_check_features(); + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = (uInt)windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + if (x86_cpu_enable_simd) { + s->hash_bits = 15; + } else { + s->hash_bits = memLevel + 7; + } + + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, + s->w_size + window_padding, + 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + /* We overlay pending_buf and sym_buf. This works since the average size + * for length/distance pairs over any compressed block is assured to be 31 + * bits or less. + * + * Analysis: The longest fixed codes are a length code of 8 bits plus 5 + * extra bits, for lengths 131 to 257. The longest fixed distance codes are + * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest + * possible fixed-codes length/distance pair is then 31 bits total. + * + * sym_buf starts one-fourth of the way into pending_buf. So there are + * three bytes in sym_buf for every four bytes in pending_buf. Each symbol + * in sym_buf is three bytes -- two for the distance and one for the + * literal/length. As each symbol is consumed, the pointer to the next + * sym_buf value to read moves forward three bytes. From that symbol, up to + * 31 bits are written to pending_buf. The closest the written pending_buf + * bits gets to the next sym_buf symbol to read is just before the last + * code is written. At that time, 31*(n-2) bits have been written, just + * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at + * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 + * symbols are written.) The closest the writing gets to what is unread is + * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and + * can range from 128 to 32768. + * + * Therefore, at a minimum, there are 142 bits of space between what is + * written and what is read in the overlain buffers, so the symbols cannot + * be overwritten by the compressed data. That space is actually 139 bits, + * due to the three-bit fixed-code block header. + * + * That covers the case where either Z_FIXED is specified, forcing fixed + * codes, or when the use of fixed codes is chosen, because that choice + * results in a smaller compressed block than dynamic codes. That latter + * condition then assures that the above analysis also covers all dynamic + * blocks. A dynamic-code block will only be chosen to be emitted if it has + * fewer bits than a fixed-code block would for the same set of symbols. + * Therefore its average symbol length is assured to be less than 31. So + * the compressed data for a dynamic block also cannot overwrite the + * symbols from which it is being constructed. + */ + s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4); + s->pending_buf_size = (ulg)s->lit_bufsize * 4; + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->sym_buf = s->pending_buf + s->lit_bufsize; + s->sym_end = (s->lit_bufsize - 1) * 3; + /* We avoid equality with lit_bufsize*3 because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +local int deflateStateCheck (strm) + z_streamp strm; +{ + deflate_state *s; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && +#ifdef GZIP + s->status != GZIP_STATE && +#endif + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt str, n; + int wrap; + unsigned avail; + z_const unsigned char *next; + + if (deflateStateCheck(strm) || dictionary == Z_NULL) + return Z_STREAM_ERROR; + s = strm->state; + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) + return Z_STREAM_ERROR; + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) + strm->adler = adler32(strm->adler, dictionary, dictLength); + s->wrap = 0; /* avoid computing Adler-32 in deflate_read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; + } + + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (z_const Bytef *)dictionary; + fill_window(s); + while (s->lookahead >= MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { + insert_string(s, str); + str++; + } while (--n); + s->strstart = str; + s->lookahead = MIN_MATCH-1; + fill_window(s); + } + s->strstart += s->lookahead; + s->block_start = (long)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + strm->next_in = next; + strm->avail_in = avail; + s->wrap = wrap; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) + z_streamp strm; + Bytef *dictionary; + uInt *dictLength; +{ + deflate_state *s; + uInt len; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != Z_NULL && len) + zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != Z_NULL) + *dictLength = len; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateResetKeep (strm) + z_streamp strm; +{ + deflate_state *s; + + if (deflateStateCheck(strm)) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + int ret; + + ret = deflateResetKeep(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePending (strm, pending, bits) + unsigned *pending; + int *bits; + z_streamp strm; +{ + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + if (pending != Z_NULL) + *pending = strm->state->pending; + if (bits != Z_NULL) + *bits = strm->state->bi_valid; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + deflate_state *s; + int put; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; + if (s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) <