Import Cobalt 4.11565
diff --git a/src/cobalt/audio/audio_node_input.cc b/src/cobalt/audio/audio_node_input.cc index 2f42724..9be0c32 100644 --- a/src/cobalt/audio/audio_node_input.cc +++ b/src/cobalt/audio/audio_node_input.cc
@@ -232,7 +232,12 @@ // TODO: Consider computing computedNumberOfChannels and do up-mix or // down-mix base on computedNumberOfChannels. The current implementation // is based on the fact that the channelCountMode is max. - DCHECK_EQ(owner_node_->channel_count_mode(), AudioNode::kMax); + if (owner_node_->channel_count_mode() != AudioNode::kMax) { + DLOG(ERROR) << "Unsupported channel count mode: " + << owner_node_->channel_count_mode(); + return; + } + // Pull audio buffer from connected audio input. When an input is connected // from one or more AudioNode outputs. Fan-in is supported. for (std::set<AudioNodeOutput*>::iterator iter = outputs_.begin();
diff --git a/src/cobalt/base/base.gyp b/src/cobalt/base/base.gyp index a2822ab..19652ec 100644 --- a/src/cobalt/base/base.gyp +++ b/src/cobalt/base/base.gyp
@@ -45,6 +45,7 @@ 'log_message_handler.h', 'math.cc', 'math.h', + 'message_queue.h', 'poller.h', 'polymorphic_downcast.h', 'polymorphic_equatable.h',
diff --git a/src/cobalt/base/message_queue.h b/src/cobalt/base/message_queue.h new file mode 100644 index 0000000..3c7ad78 --- /dev/null +++ b/src/cobalt/base/message_queue.h
@@ -0,0 +1,63 @@ +/* + * Copyright 2016 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_BASE_MESSAGE_QUEUE_H_ +#define COBALT_BASE_MESSAGE_QUEUE_H_ + +#include <queue> +#include "base/callback.h" +#include "base/logging.h" +#include "base/synchronization/lock.h" + +namespace base { + +// A thread safe in-order message queue. In some situations this can be +// preferred versus PostTask()ing directly to a MessageLoop since the data +// stored within the queued Closures can be destroyed on demand, and also the +// queue messages can be processed at a time of the user's choosing. +class MessageQueue { + public: + ~MessageQueue() { + // Leave no message behind! + ProcessAll(); + } + + // Add a message to the end of the queue. + void AddMessage(const base::Closure& message) { + base::AutoLock lock(mutex_); + DCHECK(!message.is_null()); + queue_.push(message); + } + + // Execute all messages in the MessageQueue until the queue is empty and then + // return. + void ProcessAll() { + base::AutoLock lock(mutex_); + + while (!queue_.empty()) { + queue_.front().Run(); + queue_.pop(); + } + } + + private: + base::Lock mutex_; + std::queue<base::Closure> queue_; +}; + +} // namespace base + +#endif // COBALT_BASE_MESSAGE_QUEUE_H_
diff --git a/src/cobalt/bindings/testing/bindings_test_base.h b/src/cobalt/bindings/testing/bindings_test_base.h index 25e9ea2..f634699 100644 --- a/src/cobalt/bindings/testing/bindings_test_base.h +++ b/src/cobalt/bindings/testing/bindings_test_base.h
@@ -25,6 +25,7 @@ #include "cobalt/script/global_environment.h" #include "cobalt/script/javascript_engine.h" #include "cobalt/script/source_code.h" +#include "cobalt/script/wrappable.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -71,6 +72,17 @@ return global_environment_->EvaluateScript(source, out_result); } + bool EvaluateScript(const std::string& script, + const scoped_refptr<script::Wrappable>& owning_object, + base::optional<script::OpaqueHandleHolder::Reference>* + out_opaque_handle = NULL) { + scoped_refptr<script::SourceCode> source = + script::SourceCode::CreateSourceCode( + script, base::SourceLocation("[object BindingsTestBase]", 1, 1)); + return global_environment_->EvaluateScript(source, owning_object, + out_opaque_handle); + } + void CollectGarbage() { engine_->CollectGarbage(); } protected:
diff --git a/src/cobalt/bindings/testing/evaluate_script_test.cc b/src/cobalt/bindings/testing/evaluate_script_test.cc new file mode 100644 index 0000000..61d74fa --- /dev/null +++ b/src/cobalt/bindings/testing/evaluate_script_test.cc
@@ -0,0 +1,87 @@ +/* + * Copyright 2016 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/bindings/testing/arbitrary_interface.h" +#include "cobalt/bindings/testing/bindings_test_base.h" +#include "cobalt/bindings/testing/object_type_bindings_interface.h" +#include "cobalt/bindings/testing/script_object_owner.h" + +using cobalt::script::OpaqueHandleHolder; +using ::testing::_; +using ::testing::Invoke; +using ::testing::Return; +using ::testing::StrictMock; + +namespace cobalt { +namespace bindings { +namespace testing { + +namespace { +class EvaluateScriptTest + : public InterfaceBindingsTest<ObjectTypeBindingsInterface> {}; +} // namespace + +TEST_F(EvaluateScriptTest, TwoArguments) { + std::string result; + + std::string script = + "function fib(n) {\n" + " if (n <= 0) {\n" + " return 0;\n" + " } else if (n == 1) {\n" + " return 1;\n" + " } else {\n" + " return fib(n - 1) + fib(n - 2);\n" + " }\n" + "}\n" + "fib(8)"; + EXPECT_TRUE(EvaluateScript(script, &result)); + EXPECT_STREQ("21", result.c_str()); +} + +TEST_F(EvaluateScriptTest, ThreeArguments) { + std::string script = + "function fib(n) {\n" + " if (n <= 0) {\n" + " return 0;\n" + " } else if (n == 1) {\n" + " return 1;\n" + " } else {\n" + " return fib(n - 1) + fib(n - 2);\n" + " }\n" + "}\n" + "fib(8)"; + + // Call with null out handle. + scoped_refptr<StrictMock<ArbitraryInterface> > arbitrary_interface_mock( + new StrictMock<ArbitraryInterface>()); + EXPECT_TRUE(EvaluateScript(script, arbitrary_interface_mock, NULL)); + + // Call with non-null, but unset optional handle. + base::optional<OpaqueHandleHolder::Reference> opaque_handle; + EXPECT_TRUE(EvaluateScript(script, arbitrary_interface_mock, &opaque_handle)); + ASSERT_FALSE(opaque_handle->referenced_object().IsNull()); + + EXPECT_CALL(test_mock(), object_property()) + .WillOnce(Return(&opaque_handle->referenced_object())); + std::string result; + EXPECT_TRUE(EvaluateScript("test.objectProperty == 21;", &result)); + EXPECT_STREQ("true", result.c_str()); +} + +} // namespace testing +} // namespace bindings +} // namespace cobalt
diff --git a/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp b/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp deleted file mode 100644 index 1f9a3fc..0000000 --- a/src/cobalt/bindings/testing/global_constructors_idls_idl_files_list.tmp +++ /dev/null
@@ -1,45 +0,0 @@ -AnonymousIndexedGetterInterface.idl -AnonymousNamedGetterInterface.idl -AnonymousNamedIndexedGetterInterface.idl -ArbitraryInterface.idl -BaseInterface.idl -BooleanTypeTestInterface.idl -CallbackFunctionInterface.idl -CallbackInterfaceInterface.idl -ConditionalInterface.idl -ConstantsInterface.idl -ConstructorInterface.idl -ConstructorWithArgumentsInterface.idl -DerivedGetterSetterInterface.idl -DerivedInterface.idl -DisabledInterface.idl -DOMStringTestInterface.idl -EnumerationInterface.idl -ExceptionObjectInterface.idl -ExceptionsInterface.idl -ExtendedIDLAttributesInterface.idl -GarbageCollectionTestInterface.idl -GetOpaqueRootInterface.idl -GlobalInterfaceParent.idl -IndexedGetterInterface.idl -InterfaceWithUnsupportedProperties.idl -NamedConstructorInterface.idl -NamedGetterInterface.idl -NamedIndexedGetterInterface.idl -NestedPutForwardsInterface.idl -NoConstructorInterface.idl -NoInterfaceObjectInterface.idl -NullableTypesTestInterface.idl -NumericTypesTestInterface.idl -ObjectTypeBindingsInterface.idl -OperationsTestInterface.idl -PutForwardsInterface.idl -SingleOperationInterface.idl -StringifierAnonymousOperationInterface.idl -StringifierAttributeInterface.idl -StringifierOperationInterface.idl -StaticPropertiesInterface.idl -TargetInterface.idl -UnionTypesInterface.idl -Window.idl -UnsupportedInterface.idl
diff --git a/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp b/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp deleted file mode 100644 index c1c7594..0000000 --- a/src/cobalt/bindings/testing/global_objects_idl_files_list.tmp +++ /dev/null
@@ -1,44 +0,0 @@ -AnonymousIndexedGetterInterface.idl -AnonymousNamedGetterInterface.idl -AnonymousNamedIndexedGetterInterface.idl -ArbitraryInterface.idl -BaseInterface.idl -BooleanTypeTestInterface.idl -CallbackFunctionInterface.idl -CallbackInterfaceInterface.idl -ConditionalInterface.idl -ConstantsInterface.idl -ConstructorInterface.idl -ConstructorWithArgumentsInterface.idl -DerivedGetterSetterInterface.idl -DerivedInterface.idl -DisabledInterface.idl -DOMStringTestInterface.idl -EnumerationInterface.idl -ExceptionObjectInterface.idl -ExceptionsInterface.idl -ExtendedIDLAttributesInterface.idl -GarbageCollectionTestInterface.idl -GetOpaqueRootInterface.idl -GlobalInterfaceParent.idl -IndexedGetterInterface.idl -InterfaceWithUnsupportedProperties.idl -NamedConstructorInterface.idl -NamedGetterInterface.idl -NamedIndexedGetterInterface.idl -NestedPutForwardsInterface.idl -NoConstructorInterface.idl -NoInterfaceObjectInterface.idl -NullableTypesTestInterface.idl -NumericTypesTestInterface.idl -ObjectTypeBindingsInterface.idl -OperationsTestInterface.idl -PutForwardsInterface.idl -SingleOperationInterface.idl -StringifierAnonymousOperationInterface.idl -StringifierAttributeInterface.idl -StringifierOperationInterface.idl -StaticPropertiesInterface.idl -TargetInterface.idl -UnionTypesInterface.idl -Window.idl
diff --git a/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp deleted file mode 100644 index ff5e547..0000000 --- a/src/cobalt/bindings/testing/interfaces_info_individual_static_idl_files_list.tmp +++ /dev/null
@@ -1,48 +0,0 @@ -AnonymousIndexedGetterInterface.idl -AnonymousNamedGetterInterface.idl -AnonymousNamedIndexedGetterInterface.idl -ArbitraryInterface.idl -BaseInterface.idl -BooleanTypeTestInterface.idl -CallbackFunctionInterface.idl -CallbackInterfaceInterface.idl -ConditionalInterface.idl -ConstantsInterface.idl -ConstructorInterface.idl -ConstructorWithArgumentsInterface.idl -DerivedGetterSetterInterface.idl -DerivedInterface.idl -DisabledInterface.idl -DOMStringTestInterface.idl -EnumerationInterface.idl -ExceptionObjectInterface.idl -ExceptionsInterface.idl -ExtendedIDLAttributesInterface.idl -GarbageCollectionTestInterface.idl -GetOpaqueRootInterface.idl -GlobalInterfaceParent.idl -IndexedGetterInterface.idl -InterfaceWithUnsupportedProperties.idl -NamedConstructorInterface.idl -NamedGetterInterface.idl -NamedIndexedGetterInterface.idl -NestedPutForwardsInterface.idl -NoConstructorInterface.idl -NoInterfaceObjectInterface.idl -NullableTypesTestInterface.idl -NumericTypesTestInterface.idl -ObjectTypeBindingsInterface.idl -OperationsTestInterface.idl -PutForwardsInterface.idl -SingleOperationInterface.idl -StringifierAnonymousOperationInterface.idl -StringifierAttributeInterface.idl -StringifierOperationInterface.idl -StaticPropertiesInterface.idl -TargetInterface.idl -UnionTypesInterface.idl -Window.idl -ImplementedInterface.idl -PartialInterface.idl -InterfaceWithUnsupportedProperties_partial.idl -UnsupportedInterface.idl
diff --git a/src/cobalt/bindings/testing/testing.gyp b/src/cobalt/bindings/testing/testing.gyp index 0286dcd..e9f6492 100644 --- a/src/cobalt/bindings/testing/testing.gyp +++ b/src/cobalt/bindings/testing/testing.gyp
@@ -129,6 +129,7 @@ 'dependent_interface_test.cc', 'dom_string_bindings_test.cc', 'enumeration_bindings_test.cc', + 'evaluate_script_test.cc', 'exceptions_bindings_test.cc', 'extended_attributes_test.cc', 'garbage_collection_test.cc',
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc index 27c9f1a..7559d56 100644 --- a/src/cobalt/browser/application.cc +++ b/src/cobalt/browser/application.cc
@@ -104,7 +104,6 @@ #endif // ENABLE_WEBDRIVER GURL GetInitialURL() { -#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) // Allow the user to override the default URL via a command line parameter. CommandLine* command_line = CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(switches::kInitialURL)) { @@ -115,7 +114,6 @@ DLOG(INFO) << "URL from parameter is not valid, using default URL."; } } -#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES return GURL(kDefaultURL); }
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc index 692ee5d..73de733 100644 --- a/src/cobalt/browser/browser_module.cc +++ b/src/cobalt/browser/browser_module.cc
@@ -139,6 +139,9 @@ options.network_module_options), render_tree_combiner_(renderer_module_.pipeline(), renderer_module_.render_target()->GetSize()), +#if defined(ENABLE_SCREENSHOT) + screen_shot_writer_(new ScreenShotWriter(renderer_module_.pipeline())), +#endif // defined(ENABLE_SCREENSHOT) web_module_loaded_(true /* manually_reset */, false /* initially_signalled */), web_module_recreated_callback_(options.web_module_recreated_callback), @@ -158,9 +161,6 @@ kScreenshotCommandShortHelp, kScreenshotCommandLongHelp)), #endif // defined(ENABLE_SCREENSHOT) #endif // defined(ENABLE_DEBUG_CONSOLE) -#if defined(ENABLE_SCREENSHOT) - screen_shot_writer_(new ScreenShotWriter(renderer_module_.pipeline())), -#endif // defined(ENABLE_SCREENSHOT) ALLOW_THIS_IN_INITIALIZER_LIST( h5vcc_url_handler_(this, system_window, account_manager)), web_module_options_(options.web_module_options), @@ -190,7 +190,7 @@ #if defined(ENABLE_DEBUG_CONSOLE) debug_console_.reset(new DebugConsole( - base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced, + base::Bind(&BrowserModule::QueueOnDebugConsoleRenderTreeProduced, base::Unretained(this)), media_module_.get(), &network_module_, renderer_module_.render_target()->GetSize(), @@ -239,18 +239,19 @@ } // Destroy old WebModule first, so we don't get a memory high-watermark after - // the second WebModule's construtor runs, but before scoped_ptr::reset() is + // the second WebModule's constructor runs, but before scoped_ptr::reset() is // run. web_module_.reset(NULL); // Show a splash screen while we're waiting for the web page to load. const math::Size& viewport_size = renderer_module_.render_target()->GetSize(); DestroySplashScreen(); - splash_screen_.reset(new SplashScreen( - base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this)), - &network_module_, viewport_size, - renderer_module_.pipeline()->GetResourceProvider(), - kLayoutMaxRefreshFrequencyInHz)); + splash_screen_.reset( + new SplashScreen(base::Bind(&BrowserModule::QueueOnRenderTreeProduced, + base::Unretained(this)), + &network_module_, viewport_size, + renderer_module_.pipeline()->GetResourceProvider(), + kLayoutMaxRefreshFrequencyInHz)); // Create new WebModule. #if !defined(COBALT_FORCE_CSP) @@ -270,9 +271,10 @@ options.image_cache_capacity_multiplier_when_playing_video = COBALT_IMAGE_CACHE_CAPACITY_MULTIPLIER_WHEN_PLAYING_VIDEO; web_module_.reset(new WebModule( - url, - base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this)), + url, base::Bind(&BrowserModule::QueueOnRenderTreeProduced, + base::Unretained(this)), base::Bind(&BrowserModule::OnError, base::Unretained(this)), + base::Bind(&BrowserModule::OnWindowClose, base::Unretained(this)), media_module_.get(), &network_module_, viewport_size, renderer_module_.pipeline()->GetResourceProvider(), kLayoutMaxRefreshFrequencyInHz, options)); @@ -282,6 +284,14 @@ } void BrowserModule::OnLoad() { + // Repost to our own message loop if necessary. This also prevents + // asynchonrous access to this object by |web_module_| during destruction. + if (MessageLoop::current() != self_message_loop_) { + self_message_loop_->PostTask( + FROM_HERE, base::Bind(&BrowserModule::OnLoad, weak_this_)); + return; + } + DestroySplashScreen(); web_module_loaded_.Signal(); } @@ -303,16 +313,28 @@ } #endif +void BrowserModule::ProcessRenderTreeSubmissionQueue() { + TRACE_EVENT0("cobalt::browser", + "BrowserModule::ProcessRenderTreeSubmissionQueue()"); + DCHECK_EQ(MessageLoop::current(), self_message_loop_); + render_tree_submission_queue_.ProcessAll(); +} + +void BrowserModule::QueueOnRenderTreeProduced( + const browser::WebModule::LayoutResults& layout_results) { + TRACE_EVENT0("cobalt::browser", "BrowserModule::QueueOnRenderTreeProduced()"); + render_tree_submission_queue_.AddMessage( + base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this), + layout_results)); + self_message_loop_->PostTask( + FROM_HERE, + base::Bind(&BrowserModule::ProcessRenderTreeSubmissionQueue, weak_this_)); +} + void BrowserModule::OnRenderTreeProduced( const browser::WebModule::LayoutResults& layout_results) { TRACE_EVENT0("cobalt::browser", "BrowserModule::OnRenderTreeProduced()"); - if (MessageLoop::current() != self_message_loop_) { - self_message_loop_->PostTask( - FROM_HERE, - base::Bind(&BrowserModule::OnRenderTreeProduced, weak_this_, - layout_results)); - return; - } + DCHECK_EQ(MessageLoop::current(), self_message_loop_); renderer::Submission renderer_submission(layout_results.render_tree, layout_results.layout_time); @@ -328,6 +350,20 @@ #endif } +void BrowserModule::OnWindowClose() { +#if defined(ENABLE_DEBUG_CONSOLE) + if (input_device_manager_fuzzer_) { + return; + } +#endif + +#if defined(OS_STARBOARD) + SbSystemRequestStop(0); +#else + LOG(WARNING) << "window.close is not supported on this platform."; +#endif +} + #if defined(ENABLE_DEBUG_CONSOLE) void BrowserModule::OnFuzzerToggle(const std::string& message) { if (MessageLoop::current() != self_message_loop_) { @@ -372,17 +408,23 @@ } } +void BrowserModule::QueueOnDebugConsoleRenderTreeProduced( + const browser::WebModule::LayoutResults& layout_results) { + TRACE_EVENT0("cobalt::browser", + "BrowserModule::QueueOnDebugConsoleRenderTreeProduced()"); + render_tree_submission_queue_.AddMessage( + base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced, + base::Unretained(this), layout_results)); + self_message_loop_->PostTask( + FROM_HERE, + base::Bind(&BrowserModule::ProcessRenderTreeSubmissionQueue, weak_this_)); +} + void BrowserModule::OnDebugConsoleRenderTreeProduced( const browser::WebModule::LayoutResults& layout_results) { TRACE_EVENT0("cobalt::browser", "BrowserModule::OnDebugConsoleRenderTreeProduced()"); - if (MessageLoop::current() != self_message_loop_) { - self_message_loop_->PostTask( - FROM_HERE, - base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced, weak_this_, - layout_results)); - return; - } + DCHECK_EQ(MessageLoop::current(), self_message_loop_); render_tree_combiner_.UpdateDebugConsoleRenderTree(renderer::Submission( layout_results.render_tree, layout_results.layout_time));
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h index df6da73..d589084 100644 --- a/src/cobalt/browser/browser_module.h +++ b/src/cobalt/browser/browser_module.h
@@ -17,13 +17,14 @@ #ifndef COBALT_BROWSER_BROWSER_MODULE_H_ #define COBALT_BROWSER_BROWSER_MODULE_H_ -#include <list> #include <string> +#include <vector> #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "cobalt/account/account_manager.h" +#include "cobalt/base/message_queue.h" #include "cobalt/browser/h5vcc_url_handler.h" #include "cobalt/browser/render_tree_combiner.h" #include "cobalt/browser/screen_shot_writer.h" @@ -70,7 +71,7 @@ // Type for a collection of URL handler callbacks that can potentially handle // a URL before using it to initialize a new WebModule. - typedef std::list<URLHandler::URLHandlerCallback> URLHandlerCollection; + typedef std::vector<URLHandler::URLHandlerCallback> URLHandlerCollection; BrowserModule(const GURL& url, system_window::SystemWindow* system_window, account::AccountManager* account_manager, @@ -126,6 +127,8 @@ // Glue function to deal with the production of the main render tree, // and will manage handing it off to the renderer. + void QueueOnRenderTreeProduced( + const browser::WebModule::LayoutResults& layout_results); void OnRenderTreeProduced( const browser::WebModule::LayoutResults& layout_results); @@ -163,6 +166,9 @@ // Destroys the splash screen, if currently displayed. void DestroySplashScreen(); + // Called when web module has received window.close. + void OnWindowClose(); + #if defined(ENABLE_DEBUG_CONSOLE) // Toggles the input fuzzer on/off. Ignores the parameter. void OnFuzzerToggle(const std::string&); @@ -173,6 +179,8 @@ // Glue function to deal with the production of the debug console render tree, // and will manage handing it off to the renderer. + void QueueOnDebugConsoleRenderTreeProduced( + const browser::WebModule::LayoutResults& layout_results); void OnDebugConsoleRenderTreeProduced( const browser::WebModule::LayoutResults& layout_results); #endif // defined(ENABLE_DEBUG_CONSOLE) @@ -192,6 +200,9 @@ void OnRendererSubmissionRasterized(); #endif // OS_STARBOARD + // Process all messages queued into the |render_tree_submission_queue_|. + void ProcessRenderTreeSubmissionQueue(); + // TODO: // WeakPtr usage here can be avoided if BrowserModule has a thread to // own where it can ensure that its tasks are all resolved when it is @@ -244,6 +255,18 @@ // Manages the two render trees, combines and renders them. RenderTreeCombiner render_tree_combiner_; +#if defined(ENABLE_SCREENSHOT) + // Helper object to create screen shots of the last layout tree. + scoped_ptr<ScreenShotWriter> screen_shot_writer_; +#endif // defined(ENABLE_SCREENSHOT) + + // Keeps track of all messages containing render tree submissions that will + // ultimately reference the |render_tree_combiner_| and the + // |renderer_module_|. It is important that this is destroyed before the + // above mentioned references are. It must however outlive all WebModules + // that may be producing render trees. + base::MessageQueue render_tree_submission_queue_; + // Sets up everything to do with web page management, from loading and // parsing the web page and all referenced files to laying it out. The // web module will ultimately produce a render tree that can be passed @@ -283,11 +306,6 @@ #endif // defined(ENABLE_SCREENSHOT) #endif // defined(ENABLE_DEBUG_CONSOLE) -#if defined(ENABLE_SCREENSHOT) - // Helper object to create screen shots of the last layout tree. - scoped_ptr<ScreenShotWriter> screen_shot_writer_; -#endif // defined(ENABLE_SCREENSHOT) - // Handler object for h5vcc URLs. H5vccURLHandler h5vcc_url_handler_;
diff --git a/src/cobalt/browser/debug_console.cc b/src/cobalt/browser/debug_console.cc index a293be3..b02557d 100644 --- a/src/cobalt/browser/debug_console.cc +++ b/src/cobalt/browser/debug_console.cc
@@ -181,9 +181,10 @@ get_debug_server_callback); web_module_.reset(new WebModule( GURL(kInitialDebugConsoleUrl), render_tree_produced_callback, - base::Bind(&DebugConsole::OnError, base::Unretained(this)), media_module, - network_module, window_dimensions, resource_provider, layout_refresh_rate, - web_module_options)); + base::Bind(&DebugConsole::OnError, base::Unretained(this)), + base::Closure(), /* window_close_callback */ + media_module, network_module, window_dimensions, resource_provider, + layout_refresh_rate, web_module_options)); } DebugConsole::~DebugConsole() {}
diff --git a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp deleted file mode 100644 index 7c539ab..0000000 --- a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp +++ /dev/null
@@ -1,144 +0,0 @@ -../audio/AudioBuffer.idl -../audio/AudioBufferSourceNode.idl -../audio/AudioContext.idl -../audio/AudioDestinationNode.idl -../audio/AudioNode.idl -../cssom/CSSConditionRule.idl -../cssom/CSSGroupingRule.idl -../cssom/CSSFontFaceRule.idl -../cssom/CSSMediaRule.idl -../cssom/CSSKeyframeRule.idl -../cssom/CSSKeyframesRule.idl -../cssom/CSSRule.idl -../cssom/CSSRuleList.idl -../cssom/CSSStyleDeclaration.idl -../cssom/CSSStyleRule.idl -../cssom/CSSStyleSheet.idl -../cssom/MediaList.idl -../cssom/StyleSheet.idl -../cssom/StyleSheetList.idl -../debug/DebugHub.idl -../debug/Debugger.idl -../debug/DebuggerEventTarget.idl -../debug/DebugScriptRunner.idl -../dom/AnimationEvent.idl -../dom/ArrayBuffer.idl -../dom/ArrayBufferView.idl -../dom/Attr.idl -../dom/Blob.idl -../dom/CDATASection.idl -../dom/CharacterData.idl -../dom/Comment.idl -../dom/Console.idl -../dom/Crypto.idl -../dom/DataView.idl -../dom/Document.idl -../dom/DocumentTimeline.idl -../dom/DocumentType.idl -../dom/DOMException.idl -../dom/DOMImplementation.idl -../dom/DOMParser.idl -../dom/DOMRect.idl -../dom/DOMRectList.idl -../dom/DOMRectReadOnly.idl -../dom/DOMStringMap.idl -../dom/DOMTokenList.idl -../dom/Element.idl -../dom/Event.idl -../dom/EventListener.idl -../dom/EventTarget.idl -../dom/Float32Array.idl -../dom/Float64Array.idl -../dom/FocusEvent.idl -../dom/History.idl -../dom/HTMLAnchorElement.idl -../dom/HTMLBodyElement.idl -../dom/HTMLBRElement.idl -../dom/HTMLCollection.idl -../dom/HTMLDivElement.idl -../dom/HTMLElement.idl -../dom/HTMLHeadElement.idl -../dom/HTMLHeadingElement.idl -../dom/HTMLHtmlElement.idl -../dom/HTMLImageElement.idl -../dom/HTMLLinkElement.idl -../dom/HTMLMediaElement.idl -../dom/HTMLMetaElement.idl -../dom/HTMLParagraphElement.idl -../dom/HTMLScriptElement.idl -../dom/HTMLSpanElement.idl -../dom/HTMLStyleElement.idl -../dom/HTMLTitleElement.idl -../dom/HTMLUnknownElement.idl -../dom/HTMLVideoElement.idl -../dom/KeyboardEvent.idl -../dom/Location.idl -../dom/MediaError.idl -../dom/MediaKeyCompleteEvent.idl -../dom/MediaKeyError.idl -../dom/MediaKeyErrorEvent.idl -../dom/MediaKeyMessageEvent.idl -../dom/MediaKeyNeededEvent.idl -../dom/MediaQueryList.idl -../dom/MediaSource.idl -../dom/MimeTypeArray.idl -../dom/NamedNodeMap.idl -../dom/Navigator.idl -../dom/Node.idl -../dom/NodeList.idl -../dom/Performance.idl -../dom/PerformanceTiming.idl -../dom/PluginArray.idl -../dom/ProgressEvent.idl -../dom/Screen.idl -../dom/SecurityPolicyViolationEvent.idl -../dom/SourceBuffer.idl -../dom/SourceBufferList.idl -../dom/Storage.idl -../dom/StorageEvent.idl -../dom/TestRunner.idl -../dom/Text.idl -../dom/TimeRanges.idl -../dom/TransitionEvent.idl -../dom/UIEvent.idl -../dom/Uint16Array.idl -../dom/Uint32Array.idl -../dom/Uint8Array.idl -../dom/URL.idl -../dom/VideoPlaybackQuality.idl -../dom/Window.idl -../dom/XMLDocument.idl -../dom/XMLSerializer.idl -../h5vcc/dial/DialHttpRequest.idl -../h5vcc/dial/DialHttpResponse.idl -../h5vcc/dial/DialServer.idl -../h5vcc/H5vcc.idl -../h5vcc/H5vccAccountInfo.idl -../h5vcc/H5vccAccountManager.idl -../h5vcc/H5vccAudioConfig.idl -../h5vcc/H5vccAudioConfigArray.idl -../h5vcc/H5vccCVal.idl -../h5vcc/H5vccCValKeyList.idl -../h5vcc/H5vccDeepLinkEventTarget.idl -../h5vcc/H5vccRuntime.idl -../h5vcc/H5vccRuntimeEventTarget.idl -../h5vcc/H5vccSettings.idl -../h5vcc/H5vccStorage.idl -../h5vcc/H5vccSystem.idl -../speech/SpeechRecognition.idl -../speech/SpeechRecognitionAlternative.idl -../speech/SpeechRecognitionError.idl -../speech/SpeechRecognitionEvent.idl -../speech/SpeechRecognitionResult.idl -../speech/SpeechRecognitionResultList.idl -../web_animations/Animatable.idl -../web_animations/Animation.idl -../web_animations/AnimationEffectReadOnly.idl -../web_animations/AnimationEffectTimingReadOnly.idl -../web_animations/AnimationTimeline.idl -../web_animations/Keyframe.idl -../web_animations/KeyframeEffectReadOnly.idl -../webdriver/ScriptExecutor.idl -../xhr/XMLHttpRequest.idl -../xhr/XMLHttpRequestEventTarget.idl -../xhr/XMLHttpRequestUpload.idl
diff --git a/src/cobalt/browser/global_objects_idl_files_list.tmp b/src/cobalt/browser/global_objects_idl_files_list.tmp deleted file mode 100644 index 7c539ab..0000000 --- a/src/cobalt/browser/global_objects_idl_files_list.tmp +++ /dev/null
@@ -1,144 +0,0 @@ -../audio/AudioBuffer.idl -../audio/AudioBufferSourceNode.idl -../audio/AudioContext.idl -../audio/AudioDestinationNode.idl -../audio/AudioNode.idl -../cssom/CSSConditionRule.idl -../cssom/CSSGroupingRule.idl -../cssom/CSSFontFaceRule.idl -../cssom/CSSMediaRule.idl -../cssom/CSSKeyframeRule.idl -../cssom/CSSKeyframesRule.idl -../cssom/CSSRule.idl -../cssom/CSSRuleList.idl -../cssom/CSSStyleDeclaration.idl -../cssom/CSSStyleRule.idl -../cssom/CSSStyleSheet.idl -../cssom/MediaList.idl -../cssom/StyleSheet.idl -../cssom/StyleSheetList.idl -../debug/DebugHub.idl -../debug/Debugger.idl -../debug/DebuggerEventTarget.idl -../debug/DebugScriptRunner.idl -../dom/AnimationEvent.idl -../dom/ArrayBuffer.idl -../dom/ArrayBufferView.idl -../dom/Attr.idl -../dom/Blob.idl -../dom/CDATASection.idl -../dom/CharacterData.idl -../dom/Comment.idl -../dom/Console.idl -../dom/Crypto.idl -../dom/DataView.idl -../dom/Document.idl -../dom/DocumentTimeline.idl -../dom/DocumentType.idl -../dom/DOMException.idl -../dom/DOMImplementation.idl -../dom/DOMParser.idl -../dom/DOMRect.idl -../dom/DOMRectList.idl -../dom/DOMRectReadOnly.idl -../dom/DOMStringMap.idl -../dom/DOMTokenList.idl -../dom/Element.idl -../dom/Event.idl -../dom/EventListener.idl -../dom/EventTarget.idl -../dom/Float32Array.idl -../dom/Float64Array.idl -../dom/FocusEvent.idl -../dom/History.idl -../dom/HTMLAnchorElement.idl -../dom/HTMLBodyElement.idl -../dom/HTMLBRElement.idl -../dom/HTMLCollection.idl -../dom/HTMLDivElement.idl -../dom/HTMLElement.idl -../dom/HTMLHeadElement.idl -../dom/HTMLHeadingElement.idl -../dom/HTMLHtmlElement.idl -../dom/HTMLImageElement.idl -../dom/HTMLLinkElement.idl -../dom/HTMLMediaElement.idl -../dom/HTMLMetaElement.idl -../dom/HTMLParagraphElement.idl -../dom/HTMLScriptElement.idl -../dom/HTMLSpanElement.idl -../dom/HTMLStyleElement.idl -../dom/HTMLTitleElement.idl -../dom/HTMLUnknownElement.idl -../dom/HTMLVideoElement.idl -../dom/KeyboardEvent.idl -../dom/Location.idl -../dom/MediaError.idl -../dom/MediaKeyCompleteEvent.idl -../dom/MediaKeyError.idl -../dom/MediaKeyErrorEvent.idl -../dom/MediaKeyMessageEvent.idl -../dom/MediaKeyNeededEvent.idl -../dom/MediaQueryList.idl -../dom/MediaSource.idl -../dom/MimeTypeArray.idl -../dom/NamedNodeMap.idl -../dom/Navigator.idl -../dom/Node.idl -../dom/NodeList.idl -../dom/Performance.idl -../dom/PerformanceTiming.idl -../dom/PluginArray.idl -../dom/ProgressEvent.idl -../dom/Screen.idl -../dom/SecurityPolicyViolationEvent.idl -../dom/SourceBuffer.idl -../dom/SourceBufferList.idl -../dom/Storage.idl -../dom/StorageEvent.idl -../dom/TestRunner.idl -../dom/Text.idl -../dom/TimeRanges.idl -../dom/TransitionEvent.idl -../dom/UIEvent.idl -../dom/Uint16Array.idl -../dom/Uint32Array.idl -../dom/Uint8Array.idl -../dom/URL.idl -../dom/VideoPlaybackQuality.idl -../dom/Window.idl -../dom/XMLDocument.idl -../dom/XMLSerializer.idl -../h5vcc/dial/DialHttpRequest.idl -../h5vcc/dial/DialHttpResponse.idl -../h5vcc/dial/DialServer.idl -../h5vcc/H5vcc.idl -../h5vcc/H5vccAccountInfo.idl -../h5vcc/H5vccAccountManager.idl -../h5vcc/H5vccAudioConfig.idl -../h5vcc/H5vccAudioConfigArray.idl -../h5vcc/H5vccCVal.idl -../h5vcc/H5vccCValKeyList.idl -../h5vcc/H5vccDeepLinkEventTarget.idl -../h5vcc/H5vccRuntime.idl -../h5vcc/H5vccRuntimeEventTarget.idl -../h5vcc/H5vccSettings.idl -../h5vcc/H5vccStorage.idl -../h5vcc/H5vccSystem.idl -../speech/SpeechRecognition.idl -../speech/SpeechRecognitionAlternative.idl -../speech/SpeechRecognitionError.idl -../speech/SpeechRecognitionEvent.idl -../speech/SpeechRecognitionResult.idl -../speech/SpeechRecognitionResultList.idl -../web_animations/Animatable.idl -../web_animations/Animation.idl -../web_animations/AnimationEffectReadOnly.idl -../web_animations/AnimationEffectTimingReadOnly.idl -../web_animations/AnimationTimeline.idl -../web_animations/Keyframe.idl -../web_animations/KeyframeEffectReadOnly.idl -../webdriver/ScriptExecutor.idl -../xhr/XMLHttpRequest.idl -../xhr/XMLHttpRequestEventTarget.idl -../xhr/XMLHttpRequestUpload.idl
diff --git a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp deleted file mode 100644 index 216f4b4..0000000 --- a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp +++ /dev/null
@@ -1,171 +0,0 @@ -../audio/AudioBuffer.idl -../audio/AudioBufferSourceNode.idl -../audio/AudioContext.idl -../audio/AudioDestinationNode.idl -../audio/AudioNode.idl -../cssom/CSSConditionRule.idl -../cssom/CSSGroupingRule.idl -../cssom/CSSFontFaceRule.idl -../cssom/CSSMediaRule.idl -../cssom/CSSKeyframeRule.idl -../cssom/CSSKeyframesRule.idl -../cssom/CSSRule.idl -../cssom/CSSRuleList.idl -../cssom/CSSStyleDeclaration.idl -../cssom/CSSStyleRule.idl -../cssom/CSSStyleSheet.idl -../cssom/MediaList.idl -../cssom/StyleSheet.idl -../cssom/StyleSheetList.idl -../debug/DebugHub.idl -../debug/Debugger.idl -../debug/DebuggerEventTarget.idl -../debug/DebugScriptRunner.idl -../dom/AnimationEvent.idl -../dom/ArrayBuffer.idl -../dom/ArrayBufferView.idl -../dom/Attr.idl -../dom/Blob.idl -../dom/CDATASection.idl -../dom/CharacterData.idl -../dom/Comment.idl -../dom/Console.idl -../dom/Crypto.idl -../dom/DataView.idl -../dom/Document.idl -../dom/DocumentTimeline.idl -../dom/DocumentType.idl -../dom/DOMException.idl -../dom/DOMImplementation.idl -../dom/DOMParser.idl -../dom/DOMRect.idl -../dom/DOMRectList.idl -../dom/DOMRectReadOnly.idl -../dom/DOMStringMap.idl -../dom/DOMTokenList.idl -../dom/Element.idl -../dom/Event.idl -../dom/EventListener.idl -../dom/EventTarget.idl -../dom/Float32Array.idl -../dom/Float64Array.idl -../dom/FocusEvent.idl -../dom/History.idl -../dom/HTMLAnchorElement.idl -../dom/HTMLBodyElement.idl -../dom/HTMLBRElement.idl -../dom/HTMLCollection.idl -../dom/HTMLDivElement.idl -../dom/HTMLElement.idl -../dom/HTMLHeadElement.idl -../dom/HTMLHeadingElement.idl -../dom/HTMLHtmlElement.idl -../dom/HTMLImageElement.idl -../dom/HTMLLinkElement.idl -../dom/HTMLMediaElement.idl -../dom/HTMLMetaElement.idl -../dom/HTMLParagraphElement.idl -../dom/HTMLScriptElement.idl -../dom/HTMLSpanElement.idl -../dom/HTMLStyleElement.idl -../dom/HTMLTitleElement.idl -../dom/HTMLUnknownElement.idl -../dom/HTMLVideoElement.idl -../dom/KeyboardEvent.idl -../dom/Location.idl -../dom/MediaError.idl -../dom/MediaKeyCompleteEvent.idl -../dom/MediaKeyError.idl -../dom/MediaKeyErrorEvent.idl -../dom/MediaKeyMessageEvent.idl -../dom/MediaKeyNeededEvent.idl -../dom/MediaQueryList.idl -../dom/MediaSource.idl -../dom/MimeTypeArray.idl -../dom/NamedNodeMap.idl -../dom/Navigator.idl -../dom/Node.idl -../dom/NodeList.idl -../dom/Performance.idl -../dom/PerformanceTiming.idl -../dom/PluginArray.idl -../dom/ProgressEvent.idl -../dom/Screen.idl -../dom/SecurityPolicyViolationEvent.idl -../dom/SourceBuffer.idl -../dom/SourceBufferList.idl -../dom/Storage.idl -../dom/StorageEvent.idl -../dom/TestRunner.idl -../dom/Text.idl -../dom/TimeRanges.idl -../dom/TransitionEvent.idl -../dom/UIEvent.idl -../dom/Uint16Array.idl -../dom/Uint32Array.idl -../dom/Uint8Array.idl -../dom/URL.idl -../dom/VideoPlaybackQuality.idl -../dom/Window.idl -../dom/XMLDocument.idl -../dom/XMLSerializer.idl -../h5vcc/dial/DialHttpRequest.idl -../h5vcc/dial/DialHttpResponse.idl -../h5vcc/dial/DialServer.idl -../h5vcc/H5vcc.idl -../h5vcc/H5vccAccountInfo.idl -../h5vcc/H5vccAccountManager.idl -../h5vcc/H5vccAudioConfig.idl -../h5vcc/H5vccAudioConfigArray.idl -../h5vcc/H5vccCVal.idl -../h5vcc/H5vccCValKeyList.idl -../h5vcc/H5vccDeepLinkEventTarget.idl -../h5vcc/H5vccRuntime.idl -../h5vcc/H5vccRuntimeEventTarget.idl -../h5vcc/H5vccSettings.idl -../h5vcc/H5vccStorage.idl -../h5vcc/H5vccSystem.idl -../speech/SpeechRecognition.idl -../speech/SpeechRecognitionAlternative.idl -../speech/SpeechRecognitionError.idl -../speech/SpeechRecognitionEvent.idl -../speech/SpeechRecognitionResult.idl -../speech/SpeechRecognitionResultList.idl -../web_animations/Animatable.idl -../web_animations/Animation.idl -../web_animations/AnimationEffectReadOnly.idl -../web_animations/AnimationEffectTimingReadOnly.idl -../web_animations/AnimationTimeline.idl -../web_animations/Keyframe.idl -../web_animations/KeyframeEffectReadOnly.idl -../webdriver/ScriptExecutor.idl -../xhr/XMLHttpRequest.idl -../xhr/XMLHttpRequestEventTarget.idl -../xhr/XMLHttpRequestUpload.idl -../cssom/LinkStyle.idl -../dom/Document_CSSOM.idl -../dom/Document_HTML5.idl -../dom/Document_WebAnimationsAPI.idl -../dom/Element_CSSOMView.idl -../dom/Element_DOMParsingAndSerialization.idl -../dom/ElementCSSInlineStyle.idl -../dom/GlobalCrypto.idl -../dom/GlobalEventHandlers.idl -../dom/HTMLElement_CSSOMView.idl -../dom/NavigatorID.idl -../dom/NavigatorLanguage.idl -../dom/NavigatorPlugins.idl -../dom/NavigatorStorageUtils.idl -../dom/NonDocumentTypeChildNode.idl -../dom/NonElementParentNode.idl -../dom/ParentNode.idl -../dom/Performance_HighResolutionTime.idl -../dom/URLUtils.idl -../dom/Window_AnimationTiming.idl -../dom/Window_CSSOM.idl -../dom/Window_CSSOMView.idl -../dom/Window_Performance.idl -../dom/WindowEventHandlers.idl -../dom/WindowLocalStorage.idl -../dom/WindowSessionStorage.idl -../dom/WindowTimers.idl
diff --git a/src/cobalt/browser/splash_screen.cc b/src/cobalt/browser/splash_screen.cc index 85e55bd..804b92d 100644 --- a/src/cobalt/browser/splash_screen.cc +++ b/src/cobalt/browser/splash_screen.cc
@@ -37,6 +37,7 @@ web_module_.reset(new WebModule( options.url, render_tree_produced_callback, base::Bind(&SplashScreen::OnError, base::Unretained(this)), + base::Closure(), /* window_close_callback */ &stub_media_module_, network_module, window_dimensions, resource_provider, layout_refresh_rate, web_module_options)); }
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc index b6a41c1..a402253 100644 --- a/src/cobalt/browser/switches.cc +++ b/src/cobalt/browser/switches.cc
@@ -48,10 +48,6 @@ // Setting this switch causes all certificate errors to be ignored. const char kIgnoreCertificateErrors[] = "ignore_certificate_errors"; -// Setting this switch defines the startup URL that Cobalt will use. If no -// value is set, a default URL will be used. -const char kInitialURL[] = "url"; - // If this flag is set, input will be continuously generated randomly instead of // taken from an external input device (like a controller). const char kInputFuzzer[] = "input_fuzzer"; @@ -105,6 +101,10 @@ // ideally) these images are cached within GPU memory. const char kImageCacheSizeInBytes[] = "image_cache_size_in_bytes"; +// Setting this switch defines the startup URL that Cobalt will use. If no +// value is set, a default URL will be used. +const char kInitialURL[] = "url"; + // Determines the capacity of the remote typefaces cache which manages all // typefaces downloaded from a web page. const char kRemoteTypefaceCacheSizeInBytes[] =
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h index 3531931..7d463d0 100644 --- a/src/cobalt/browser/switches.h +++ b/src/cobalt/browser/switches.h
@@ -30,7 +30,6 @@ extern const char kEnableWebDriver[]; extern const char kExtraWebFileDir[]; extern const char kIgnoreCertificateErrors[]; -extern const char kInitialURL[]; extern const char kInputFuzzer[]; extern const char kNullAudioStreamer[]; extern const char kNullSavegame[]; @@ -46,6 +45,7 @@ #endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES extern const char kImageCacheSizeInBytes[]; +extern const char kInitialURL[]; extern const char kRemoteTypefaceCacheSizeInBytes[]; extern const char kScratchSurfaceCacheSizeInBytes[]; extern const char kSkiaCacheSizeInBytes[];
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc index b80a9bd..7932196 100644 --- a/src/cobalt/browser/web_module.cc +++ b/src/cobalt/browser/web_module.cc
@@ -23,7 +23,6 @@ #include "base/message_loop_proxy.h" #include "base/optional.h" #include "base/stringprintf.h" -#include "cobalt/base/address_sanitizer.h" #include "cobalt/base/tokens.h" #include "cobalt/browser/switches.h" #include "cobalt/browser/web_module_stat_tracker.h" @@ -321,7 +320,7 @@ data.network_module->cookie_jar(), data.network_module->GetPostSender(), data.options.location_policy, data.options.csp_enforcement_mode, base::Bind(&WebModule::Impl::OnCspPolicyChanged, base::Unretained(this)), - data.options.csp_insecure_allowed_token); + data.window_close_callback, data.options.csp_insecure_allowed_token); DCHECK(window_); window_weak_ = base::AsWeakPtr(window_.get()); @@ -556,28 +555,22 @@ WebModule::WebModule( const GURL& initial_url, const OnRenderTreeProducedCallback& render_tree_produced_callback, - const OnErrorCallback& error_callback, media::MediaModule* media_module, - network::NetworkModule* network_module, const math::Size& window_dimensions, + const OnErrorCallback& error_callback, + const base::Closure& window_close_callback, + media::MediaModule* media_module, network::NetworkModule* network_module, + const math::Size& window_dimensions, render_tree::ResourceProvider* resource_provider, float layout_refresh_rate, const Options& options) : thread_(options.name.c_str()) { ConstructionData construction_data( - initial_url, render_tree_produced_callback, error_callback, media_module, - network_module, window_dimensions, resource_provider, kDOMMaxElementDepth, - layout_refresh_rate, options); - -#if defined(COBALT_BUILD_TYPE_DEBUG) - // Non-optimized builds require a bigger stack size. - const size_t kBaseStackSize = 2 * 1024 * 1024; -#else - const size_t kBaseStackSize = 256 * 1024; -#endif + initial_url, render_tree_produced_callback, error_callback, + window_close_callback, media_module, network_module, window_dimensions, + resource_provider, kDOMMaxElementDepth, layout_refresh_rate, options); // Start the dedicated thread and create the internal implementation // object on that thread. - size_t stack_size = kBaseStackSize + base::kAsanAdditionalStackSize; thread_.StartWithOptions( - base::Thread::Options(MessageLoop::TYPE_DEFAULT, stack_size)); + base::Thread::Options(MessageLoop::TYPE_DEFAULT, kWebModuleStackSize)); DCHECK(message_loop()); message_loop()->PostTask(
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h index a4742cb..55706e7 100644 --- a/src/cobalt/browser/web_module.h +++ b/src/cobalt/browser/web_module.h
@@ -27,6 +27,7 @@ #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "base/threading/thread_checker.h" +#include "cobalt/base/address_sanitizer.h" #include "cobalt/base/console_commands.h" #include "cobalt/base/source_location.h" #include "cobalt/css_parser/parser.h" @@ -150,6 +151,7 @@ WebModule(const GURL& initial_url, const OnRenderTreeProducedCallback& render_tree_produced_callback, const OnErrorCallback& error_callback, + const base::Closure& window_close_callback, media::MediaModule* media_module, network::NetworkModule* network_module, const math::Size& window_dimensions, @@ -180,6 +182,15 @@ debug::DebugServer* GetDebugServer(); #endif // ENABLE_DEBUG_CONSOLE +#if defined(COBALT_BUILD_TYPE_DEBUG) + // Non-optimized builds require a bigger stack size. + static const size_t kBaseStackSize = 2 * 1024 * 1024; +#else + static const size_t kBaseStackSize = 256 * 1024; +#endif + static const size_t kWebModuleStackSize = + kBaseStackSize + base::kAsanAdditionalStackSize; + private: // Data required to construct a WebModule, initialized in the constructor and // passed to |Initialize|. @@ -187,7 +198,9 @@ ConstructionData( const GURL& initial_url, const OnRenderTreeProducedCallback& render_tree_produced_callback, - const OnErrorCallback& error_callback, media::MediaModule* media_module, + const OnErrorCallback& error_callback, + const base::Closure& window_close_callback, + media::MediaModule* media_module, network::NetworkModule* network_module, const math::Size& window_dimensions, render_tree::ResourceProvider* resource_provider, @@ -196,6 +209,7 @@ : initial_url(initial_url), render_tree_produced_callback(render_tree_produced_callback), error_callback(error_callback), + window_close_callback(window_close_callback), media_module(media_module), network_module(network_module), window_dimensions(window_dimensions), @@ -207,6 +221,7 @@ GURL initial_url; OnRenderTreeProducedCallback render_tree_produced_callback; OnErrorCallback error_callback; + const base::Closure& window_close_callback; media::MediaModule* media_module; network::NetworkModule* network_module; math::Size window_dimensions;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id index f895aef..deb3c7d 100644 --- a/src/cobalt/build/build.id +++ b/src/cobalt/build/build.id
@@ -1 +1 @@ -11333 \ No newline at end of file +11565 \ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi index 3e07aab..7170bcb 100644 --- a/src/cobalt/build/config/base.gypi +++ b/src/cobalt/build/config/base.gypi
@@ -28,6 +28,12 @@ # Contains the current build configuration. 'cobalt_config%': 'gold', 'cobalt_fastbuild%': 0, + + # Contains the current font package selection. This can be used to trade + # font quality, coverage, and latency with smaller font package size. + # See content/fonts/README.md for more details. + 'cobalt_font_package%': 'unlimited', + # Build version number. 'cobalt_version%': 0, # Contains the name of the hosting OS. The value is defined by gyp_cobalt.
diff --git a/src/cobalt/content/fonts/10megabytes/fonts.xml b/src/cobalt/content/fonts/10megabytes/fonts.xml new file mode 100644 index 0000000..c0ffb0a --- /dev/null +++ b/src/cobalt/content/fonts/10megabytes/fonts.xml
@@ -0,0 +1,213 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + NOTE: Families with a "fallback" value of "true" are added to the fallback + list, regardless of whether or not they are named. Fallback fonts are chosen + based on a match: full BCP-47 language tag including script, then just + language, and finally order (the first font containing the glyph). Order of + appearance is also the tiebreaker for weight matching. + + The pages attribute indicates which character pages are contained within + the font. It is used with character fallback to allow the system to quickly + determine that a character cannot appear in a font without requiring the + full character map to be loaded into memory. Character pages are zero + indexed, and each page contains 256 characters, so character 1000 would be + contained within page 3. +--> +<familyset version="1"> + <!-- first font is default --> + <family name="sans-serif"> + <font weight="400" style="normal">Roboto-Regular.ttf</font> + </family> + <!-- Note that aliases must come after the fonts they reference. --> + <alias name="arial" to="sans-serif" /> + <alias name="helvetica" to="sans-serif" /> + <alias name="roboto" to="sans-serif" /> + <alias name="tahoma" to="sans-serif" /> + <alias name="verdana" to="sans-serif" /> + <alias name="courier" to="serif-monospace" /> + <alias name="courier new" to="serif-monospace" /> + <family name="sans-serif-smallcaps"> + <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font> + </family> + <!-- fallback fonts --> + <family name="Noto Naskh Arabic UI" fallback="true" pages="0,6-8,32,37,46,251-254"> + <font weight="400" style="normal">NotoNaskhArabicUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,18-19,45,171,254"> + <font weight="400" style="normal">NotoSansEthiopic-Regular.ttf</font> + </family> + <family fallback="true" pages="0,5,32,37,251,254"> + <font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font> + </family> + <family fallback="true" pages="0,2-3,14,32,37,254"> + <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,5,251,254"> + <font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font> + </family> + <family fallback="true" pages="0,5,16,45,254"> + <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf</font> + </family> + <family fallback="true" pages="0,2,9,28,32,34,37,168,254"> + <font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf</font> + </family> + <!-- Gujarati should come after Devanagari --> + <family fallback="true" pages="0,9-10,32,34,37,168,254"> + <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font> + </family> + <!-- Gurmukhi should come after Devanagari --> + <family fallback="true" pages="0,9-10,32,34,37-38,168,254"> + <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,9,11,32,34,37,254"> + <font weight="400" style="normal">NotoSansTamilUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,3,9,13,32,34,37,254"> + <font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,9,32,34,37,254"> + <font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,9,12,32,34,37,254"> + <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,9,12,32,34,37,254"> + <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,9,11,32,34,37,254"> + <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,9,13,32,34,37,254"> + <font weight="400" style="normal">NotoSansSinhala-Regular.ttf</font> + </family> + <family fallback="true" pages="0,23,25,32,37"> + <font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,3,14,32,37"> + <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font> + </family> + <family fallback="true" pages="0,6-7,32,37,253-254"> + <font weight="400" style="normal">NotoSansThaana-Regular.ttf</font> + </family> + <family fallback="true" pages="0,3,170"> + <font weight="400" style="normal">NotoSansCham-Regular.ttf</font> + </family> + <family fallback="true" pages="0,27,32,37,254"> + <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font> + </family> + <family fallback="true" pages="0,166,254,360-362"> + <font weight="400" style="normal">NotoSansBamum-Regular.ttf</font> + </family> + <family fallback="true" pages="0,27,254"> + <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font> + </family> + <family fallback="true" pages="0,26,32,169,254"> + <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font> + </family> + <family fallback="true" pages="0,23,254"> + <font weight="400" style="normal">NotoSansBuhid-Regular.ttf</font> + </family> + <family fallback="true" pages="0-3,20-22,24,254"> + <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font> + </family> + <family fallback="true" pages="0,19,254"> + <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font> + </family> + <family fallback="true" pages="0-3,29,44,254"> + <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font> + </family> + <family fallback="true" pages="0,44,254"> + <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font> + </family> + <family fallback="true" pages="0,23,254"> + <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font> + </family> + <family fallback="true" pages="0,32,37,169,254"> + <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font> + </family> + <family fallback="true" pages="0,169,254"> + <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font> + </family> + <family fallback="true" pages="0,28,37,254"> + <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font> + </family> + <family fallback="true" pages="0,9,25,254"> + <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font> + </family> + <family fallback="true" pages="0,2,164,254"> + <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font> + </family> + <family fallback="true" pages="0,6,8,254"> + <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font> + </family> + <family fallback="true" pages="0,170-171,254"> + <font weight="400" style="normal">NotoSansMeeteiMayek-Regular.ttf</font> + </family> + <family fallback="true" pages="0,25,254"> + <font weight="400" style="normal">NotoSansNewTaiLue-Regular.ttf</font> + </family> + <family fallback="true" pages="0,6-7,32,46,253-254"> + <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font> + </family> + <family fallback="true" pages="0,28,254"> + <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font> + </family> + <family fallback="true" pages="0,169,254"> + <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font> + </family> + <family fallback="true" pages="0,32,37,168,254"> + <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font> + </family> + <family fallback="true" pages="0,27-28,254"> + <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font> + </family> + <family fallback="true" pages="0,9,32,37,168,254"> + <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font> + </family> + <family fallback="true" pages="0,3,6-7,32,34,37-38,254"> + <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font> + </family> + <family fallback="true" pages="0,23,254"> + <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font> + </family> + <family fallback="true" pages="0,26,32,34,37,254"> + <font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font> + </family> + <family fallback="true" pages="0,32,37,167,170,254"> + <font weight="400" style="normal">NotoSansTaiViet-Regular.ttf</font> + </family> + <family fallback="true" pages="0,15,32,37,254"> + <font weight="400" style="normal">NotoSansTibetan-Regular.ttf</font> + </family> + <family fallback="true" pages="0,3,32,45,254"> + <font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font> + </family> + <family fallback="true" pages="0,165-166,254"> + <font weight="400" style="normal">NotoSansVai-Regular.ttf</font> + </family> + <family fallback="true" pages="0,160-164,254"> + <font weight="400" style="normal">NotoSansYi-Regular.ttf</font> + </family> + <family fallback="true" pages="32-43"> + <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font> + </family> + <family fallback="true" lang="ja" pages="0,32,34-35,46-159,249-250,254-255,498,512-523,525-527,530-538,540-543,545-547,550,552,554-559,561,563-568,570,572-573,575-579,582-584,586-594,596-608,610-612,614-618,620,622-625,627-628,630-631,633-638,640,642-646,649-655,658,660-664,666,669-678,681,695-696,760-761"> + <font weight="400" style="normal">NotoSansJP-Regular.otf</font> + </family> + <family fallback="true" pages="0,32-33,35-39,41,43,48,50,224,254-255,496-502,4068"> + <font weight="400" style="normal">NotoEmoji-Regular.ttf</font> + </family> + <family fallback="true" pages="0,14,17,32,48-51,77-159,172-215,249-250,254-255,260"> + <font weight="400" style="normal">DroidSansFallback.ttf</font> + </family> + <!-- + Tai Le and Mongolian are intentionally kept last, to make sure they don't override + the East Asian punctuation for Chinese. + --> + <family fallback="true" pages="0,16,25,48,254"> + <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font> + </family> + <family fallback="true" pages="0,24,32,36-37,48,254"> + <font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font> + </family> +</familyset>
diff --git a/src/cobalt/content/fonts/README.md b/src/cobalt/content/fonts/README.md index acee96c..5305139 100644 --- a/src/cobalt/content/fonts/README.md +++ b/src/cobalt/content/fonts/README.md
@@ -1,29 +1,32 @@ -# Generating a minimal font for devices with small space requirements +## Description -[GlyphIGo](https://github.com/pettarin/glyphIgo) was used to generate a subset -of the Roboto font +This directory contains a few different set of font packages one can select +to be packaged with cobalt. -`cobalt/content/fonts` contains a script called `create_minimized_roboto.sh` -that can help recreate minimized font if needed +## How to use -Steps: +To use this: -1. `cd src/cobalt/content/fonts` -1. `./create_minimized_roboto.sh` -1. Download `fontforge` using apt. `sudo apt install fontforge` -1. In `fontforge`, navigate the menu: `Encoding`->`Reencode`->`Glyph Order`. -Scroll to the top, find the first glyph. By spec, this glyph is called -`.notdef`, and is used when this font is the default font and there glyph for a -character we're looking for is missing in the file. Often this will be blank -after the last step, which can be undesired. -1. Copy `.notdef` glyph from a different font. - 1. Open a different font. - 1. Find the `.notdef` glyph. - 1. Select the glyph without opening it. - 1. Navigate the menu: `Edit`->`Copy` from the font you want to copy from. - 1. Switch focus to the minimized font. - 1. Select `.notdef` glyph. - 1. Navigate the menu: `Edit`->`Paste`. -1. Export the font using the menu: `File`->`Generate Fonts...`, make sure that -the file name is correct. -1. Fix any errors if found, or if you can. +1. Select one of the profiles below. +2. Add a variable named `cobalt_font_package` in your platform's +`gyp_configuration.gypi` file. + +Example: + + 'variables': { + 'cobalt_font_package': '10megabytes', + } + + + +## Profiles + +1. `10megabytes`: Use this set of fonts if the target space allocated for fonts +is approximately 10 megabytes. This directory contains DroidSansFallback, which +will render many Chinese, and Korean characters at lower quality. The benefit +of using this font is space savings at the cost of reduced quality. +1. `minimal`: Use this if minimizing space is a goal, and Cobalt should rely +on web fonts. +1. `unlimited`: This font set is preferred, and default. This will enable the +use the fonts with highest quality and coverage, without the network latency of +fetching fonts from the server.
diff --git a/src/cobalt/content/fonts/CarroisGothicSC-Regular.ttf b/src/cobalt/content/fonts/all_fonts/CarroisGothicSC-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/CarroisGothicSC-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/CarroisGothicSC-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/ComingSoon.ttf b/src/cobalt/content/fonts/all_fonts/ComingSoon.ttf similarity index 100% rename from src/cobalt/content/fonts/ComingSoon.ttf rename to src/cobalt/content/fonts/all_fonts/ComingSoon.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/CutiveMono.ttf b/src/cobalt/content/fonts/all_fonts/CutiveMono.ttf similarity index 100% rename from src/cobalt/content/fonts/CutiveMono.ttf rename to src/cobalt/content/fonts/all_fonts/CutiveMono.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/DancingScript-Bold.ttf b/src/cobalt/content/fonts/all_fonts/DancingScript-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/DancingScript-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/DancingScript-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/DancingScript-Regular.ttf b/src/cobalt/content/fonts/all_fonts/DancingScript-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/DancingScript-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/DancingScript-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/DroidSansFallback.ttf b/src/cobalt/content/fonts/all_fonts/DroidSansFallback.ttf similarity index 100% rename from src/cobalt/content/fonts/DroidSansFallback.ttf rename to src/cobalt/content/fonts/all_fonts/DroidSansFallback.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/DroidSansMono.ttf b/src/cobalt/content/fonts/all_fonts/DroidSansMono.ttf similarity index 100% rename from src/cobalt/content/fonts/DroidSansMono.ttf rename to src/cobalt/content/fonts/all_fonts/DroidSansMono.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/MTLmr3m.ttf b/src/cobalt/content/fonts/all_fonts/MTLmr3m.ttf similarity index 100% rename from src/cobalt/content/fonts/MTLmr3m.ttf rename to src/cobalt/content/fonts/all_fonts/MTLmr3m.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/MinimalRoboto.ttf b/src/cobalt/content/fonts/all_fonts/MinimalRoboto.ttf similarity index 100% rename from src/cobalt/content/fonts/MinimalRoboto.ttf rename to src/cobalt/content/fonts/all_fonts/MinimalRoboto.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NanumGothic.ttf b/src/cobalt/content/fonts/all_fonts/NanumGothic.ttf similarity index 100% rename from src/cobalt/content/fonts/NanumGothic.ttf rename to src/cobalt/content/fonts/all_fonts/NanumGothic.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoEmoji-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoEmoji-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoEmoji-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoEmoji-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoNaskhArabicUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoNaskhArabicUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoNaskhArabicUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoNaskhArabicUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoNaskhArabicUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoNaskhArabicUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoNaskhArabicUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoNaskhArabicUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansArmenian-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansArmenian-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansArmenian-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansArmenian-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansArmenian-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansArmenian-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansArmenian-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansArmenian-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBalinese-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBalinese-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansBalinese-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansBalinese-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBamum-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBamum-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansBamum-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansBamum-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBatak-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBatak-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansBatak-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansBatak-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBengaliUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBengaliUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansBengaliUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansBengaliUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBengaliUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBengaliUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansBengaliUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansBengaliUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBuginese-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBuginese-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansBuginese-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansBuginese-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansBuhid-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansBuhid-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansBuhid-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansBuhid-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCanadianAboriginal-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCanadianAboriginal-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansCanadianAboriginal-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansCanadianAboriginal-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCham-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCham-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansCham-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansCham-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCham-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCham-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansCham-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansCham-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCherokee-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCherokee-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansCherokee-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansCherokee-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansCoptic-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansCoptic-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansCoptic-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansCoptic-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansDevanagariUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansDevanagariUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansDevanagariUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansDevanagariUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansDevanagariUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansDevanagariUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansDevanagariUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansDevanagariUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansEthiopic-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansEthiopic-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansEthiopic-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansEthiopic-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansEthiopic-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansEthiopic-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansEthiopic-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansEthiopic-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGeorgian-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGeorgian-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansGeorgian-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansGeorgian-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGeorgian-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGeorgian-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansGeorgian-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansGeorgian-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGlagolitic-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGlagolitic-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansGlagolitic-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansGlagolitic-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGujaratiUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGujaratiUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansGujaratiUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansGujaratiUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGujaratiUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGujaratiUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansGujaratiUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansGujaratiUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGurmukhiUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGurmukhiUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansGurmukhiUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansGurmukhiUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansGurmukhiUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansGurmukhiUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansGurmukhiUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansGurmukhiUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansHanunoo-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansHanunoo-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansHanunoo-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansHanunoo-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansHebrew-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansHebrew-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansHebrew-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansHebrew-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansHebrew-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansHebrew-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansHebrew-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansHebrew-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansJP-Regular.otf b/src/cobalt/content/fonts/all_fonts/NotoSansJP-Regular.otf similarity index 100% rename from src/cobalt/content/fonts/NotoSansJP-Regular.otf rename to src/cobalt/content/fonts/all_fonts/NotoSansJP-Regular.otf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansJavanese-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansJavanese-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansJavanese-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansJavanese-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKR-Regular.otf b/src/cobalt/content/fonts/all_fonts/NotoSansKR-Regular.otf similarity index 100% rename from src/cobalt/content/fonts/NotoSansKR-Regular.otf rename to src/cobalt/content/fonts/all_fonts/NotoSansKR-Regular.otf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKannadaUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKannadaUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansKannadaUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansKannadaUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKannadaUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKannadaUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansKannadaUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansKannadaUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKayahLi-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKayahLi-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansKayahLi-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansKayahLi-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKhmerUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKhmerUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansKhmerUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansKhmerUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansKhmerUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansKhmerUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansKhmerUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansKhmerUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLaoUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLaoUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansLaoUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansLaoUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLaoUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLaoUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansLaoUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansLaoUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLepcha-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLepcha-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansLepcha-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansLepcha-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLimbu-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLimbu-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansLimbu-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansLimbu-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansLisu-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansLisu-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansLisu-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansLisu-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMalayalamUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMalayalamUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansMalayalamUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansMalayalamUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMalayalamUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMalayalamUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansMalayalamUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansMalayalamUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMandaic-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMandaic-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansMandaic-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansMandaic-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMeeteiMayek-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMeeteiMayek-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansMeeteiMayek-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansMeeteiMayek-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMongolian-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMongolian-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansMongolian-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansMongolian-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMyanmarUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMyanmarUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansMyanmarUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansMyanmarUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansMyanmarUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansMyanmarUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansMyanmarUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansMyanmarUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansNKo-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansNKo-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansNKo-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansNKo-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansNewTaiLue-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansNewTaiLue-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansNewTaiLue-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansNewTaiLue-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansOlChiki-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansOlChiki-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansOlChiki-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansOlChiki-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansOriyaUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansOriyaUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansOriyaUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansOriyaUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansOriyaUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansOriyaUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansOriyaUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansOriyaUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansRejang-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansRejang-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansRejang-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansRejang-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSC-Regular.otf b/src/cobalt/content/fonts/all_fonts/NotoSansSC-Regular.otf similarity index 100% rename from src/cobalt/content/fonts/NotoSansSC-Regular.otf rename to src/cobalt/content/fonts/all_fonts/NotoSansSC-Regular.otf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSaurashtra-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSaurashtra-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansSaurashtra-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansSaurashtra-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSinhala-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSinhala-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansSinhala-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansSinhala-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSinhala-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSinhala-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansSinhala-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansSinhala-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSundanese-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSundanese-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansSundanese-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansSundanese-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSylotiNagri-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSylotiNagri-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansSylotiNagri-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansSylotiNagri-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSymbols-Regular-Subsetted.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSymbols-Regular-Subsetted.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansSymbols-Regular-Subsetted.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansSymbols-Regular-Subsetted.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansSyriacEstrangela-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansSyriacEstrangela-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansSyriacEstrangela-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansSyriacEstrangela-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTC-Regular.otf b/src/cobalt/content/fonts/all_fonts/NotoSansTC-Regular.otf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTC-Regular.otf rename to src/cobalt/content/fonts/all_fonts/NotoSansTC-Regular.otf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTagbanwa-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTagbanwa-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTagbanwa-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTagbanwa-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTaiLe-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTaiLe-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTaiLe-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTaiLe-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTaiTham-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTaiTham-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTaiTham-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTaiTham-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTaiViet-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTaiViet-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTaiViet-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTaiViet-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTamilUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTamilUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTamilUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTamilUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTamilUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTamilUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTamilUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTamilUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTeluguUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTeluguUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTeluguUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTeluguUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTeluguUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTeluguUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTeluguUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTeluguUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansThaana-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansThaana-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansThaana-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansThaana-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansThaana-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansThaana-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansThaana-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansThaana-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansThaiUI-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansThaiUI-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansThaiUI-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansThaiUI-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansThaiUI-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansThaiUI-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansThaiUI-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansThaiUI-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTibetan-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTibetan-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTibetan-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTibetan-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansTifinagh-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansTifinagh-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansTifinagh-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansTifinagh-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansVai-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansVai-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansVai-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansVai-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSansYi-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSansYi-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSansYi-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSansYi-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSerif-Bold.ttf b/src/cobalt/content/fonts/all_fonts/NotoSerif-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSerif-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSerif-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSerif-BoldItalic.ttf b/src/cobalt/content/fonts/all_fonts/NotoSerif-BoldItalic.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSerif-BoldItalic.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSerif-BoldItalic.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSerif-Italic.ttf b/src/cobalt/content/fonts/all_fonts/NotoSerif-Italic.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSerif-Italic.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSerif-Italic.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/NotoSerif-Regular.ttf b/src/cobalt/content/fonts/all_fonts/NotoSerif-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/NotoSerif-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/NotoSerif-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/Roboto-Bold.ttf b/src/cobalt/content/fonts/all_fonts/Roboto-Bold.ttf similarity index 100% rename from src/cobalt/content/fonts/Roboto-Bold.ttf rename to src/cobalt/content/fonts/all_fonts/Roboto-Bold.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/Roboto-BoldItalic.ttf b/src/cobalt/content/fonts/all_fonts/Roboto-BoldItalic.ttf similarity index 100% rename from src/cobalt/content/fonts/Roboto-BoldItalic.ttf rename to src/cobalt/content/fonts/all_fonts/Roboto-BoldItalic.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/Roboto-Italic.ttf b/src/cobalt/content/fonts/all_fonts/Roboto-Italic.ttf similarity index 100% rename from src/cobalt/content/fonts/Roboto-Italic.ttf rename to src/cobalt/content/fonts/all_fonts/Roboto-Italic.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/Roboto-Regular.ttf b/src/cobalt/content/fonts/all_fonts/Roboto-Regular.ttf similarity index 100% rename from src/cobalt/content/fonts/Roboto-Regular.ttf rename to src/cobalt/content/fonts/all_fonts/Roboto-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/minimal/fonts.xml b/src/cobalt/content/fonts/minimal/fonts.xml new file mode 100644 index 0000000..1381b81 --- /dev/null +++ b/src/cobalt/content/fonts/minimal/fonts.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<familyset version="1"> + <!-- Ideally, this font should only be used if there are no other fonts in + our final image. --> + <family name="Minimal Roboto"> + <font weight="400" style="normal">MinimalRoboto.ttf</font> + </family> + <family name="sans-serif-smallcaps"> + <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font> + </family> +</familyset>
diff --git a/src/cobalt/content/fonts/scripts/README.md b/src/cobalt/content/fonts/scripts/README.md new file mode 100644 index 0000000..acee96c --- /dev/null +++ b/src/cobalt/content/fonts/scripts/README.md
@@ -0,0 +1,29 @@ +# Generating a minimal font for devices with small space requirements + +[GlyphIGo](https://github.com/pettarin/glyphIgo) was used to generate a subset +of the Roboto font + +`cobalt/content/fonts` contains a script called `create_minimized_roboto.sh` +that can help recreate minimized font if needed + +Steps: + +1. `cd src/cobalt/content/fonts` +1. `./create_minimized_roboto.sh` +1. Download `fontforge` using apt. `sudo apt install fontforge` +1. In `fontforge`, navigate the menu: `Encoding`->`Reencode`->`Glyph Order`. +Scroll to the top, find the first glyph. By spec, this glyph is called +`.notdef`, and is used when this font is the default font and there glyph for a +character we're looking for is missing in the file. Often this will be blank +after the last step, which can be undesired. +1. Copy `.notdef` glyph from a different font. + 1. Open a different font. + 1. Find the `.notdef` glyph. + 1. Select the glyph without opening it. + 1. Navigate the menu: `Edit`->`Copy` from the font you want to copy from. + 1. Switch focus to the minimized font. + 1. Select `.notdef` glyph. + 1. Navigate the menu: `Edit`->`Paste`. +1. Export the font using the menu: `File`->`Generate Fonts...`, make sure that +the file name is correct. +1. Fix any errors if found, or if you can.
diff --git a/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf b/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf new file mode 100644 index 0000000..251d6a7 --- /dev/null +++ b/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf Binary files differ
diff --git a/src/cobalt/content/fonts/create_minimized_roboto.sh b/src/cobalt/content/fonts/scripts/create_minimized_roboto.sh similarity index 100% rename from src/cobalt/content/fonts/create_minimized_roboto.sh rename to src/cobalt/content/fonts/scripts/create_minimized_roboto.sh
diff --git a/src/cobalt/content/fonts/minimized_roboto_subset_chars.txt b/src/cobalt/content/fonts/scripts/minimized_roboto_subset_chars.txt similarity index 78% rename from src/cobalt/content/fonts/minimized_roboto_subset_chars.txt rename to src/cobalt/content/fonts/scripts/minimized_roboto_subset_chars.txt index 75498f5..54fdd68 100644 --- a/src/cobalt/content/fonts/minimized_roboto_subset_chars.txt +++ b/src/cobalt/content/fonts/scripts/minimized_roboto_subset_chars.txt
@@ -1 +1 @@ -abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 (),.-/! \ No newline at end of file +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ()[]{},.-/!#'"<>:
diff --git a/src/cobalt/content/fonts/fonts.xml b/src/cobalt/content/fonts/unlimited/fonts.xml similarity index 100% rename from src/cobalt/content/fonts/fonts.xml rename to src/cobalt/content/fonts/unlimited/fonts.xml
diff --git a/src/cobalt/debug/debug_web_server.cc b/src/cobalt/debug/debug_web_server.cc index 0bc80b7..5ec3d06 100644 --- a/src/cobalt/debug/debug_web_server.cc +++ b/src/cobalt/debug/debug_web_server.cc
@@ -137,10 +137,10 @@ } DebugWebServer::~DebugWebServer() { - net::HttpServer* server = server_.get(); - server_->AddRef(); - server_ = NULL; - http_server_thread_.message_loop()->ReleaseSoon(FROM_HERE, server); + // Destroy the server on its own thread then stop the thread. + http_server_thread_.message_loop()->PostTask( + FROM_HERE, + base::Bind(&DebugWebServer::StopServer, base::Unretained(this))); http_server_thread_.Stop(); } @@ -320,5 +320,10 @@ } } +void DebugWebServer::StopServer() { + DCHECK(thread_checker_.CalledOnValidThread()); + server_ = NULL; +} + } // namespace debug } // namespace cobalt
diff --git a/src/cobalt/debug/debug_web_server.h b/src/cobalt/debug/debug_web_server.h index ac2a593..9f55c16 100644 --- a/src/cobalt/debug/debug_web_server.h +++ b/src/cobalt/debug/debug_web_server.h
@@ -79,11 +79,14 @@ void StartServer(int port); + void StopServer(); + void SendErrorResponseOverWebSocket(int id, const std::string& message); base::ThreadChecker thread_checker_; base::Thread http_server_thread_; scoped_ptr<net::StreamListenSocketFactory> factory_; + // net::HttpServer is a ref-counted object, so we have to use scoped_refptr. scoped_refptr<net::HttpServer> server_; GetDebugServerCallback get_debug_server_callback_;
diff --git a/src/cobalt/dom/font_cache.h b/src/cobalt/dom/font_cache.h index 469d8e0..dd74c4e 100644 --- a/src/cobalt/dom/font_cache.h +++ b/src/cobalt/dom/font_cache.h
@@ -39,20 +39,21 @@ namespace dom { // The font cache is typically owned by dom::Document and handles the following: +// - Tracking of font faces, which it uses to determine if a specified +// font family is local or remote, and for url determination in requesting +// remote typefaces. // - Creation and caching of font lists, which it provides to the used // style provider as requested. Font lists handle most layout-related font // cache interactions. Layout objects only interact with the font cache // through their font lists. -// - Tracking of font faces, which it uses to determine if a specified -// font family is local or remote, and for url determination in requesting -// remote typefaces. // - Retrieval of typefaces, either locally from the resource provider or -// remotely from the remote typeface cache. -// - Caching the indices of the glyphs that the typeface provides for specific -// characters, so that only the first query of a specific font character -// necessitates the glyph lookup. -// - Determination of the fallback typeface for a specific character, and -// caching of that information for subsequent lookups. +// remotely from the remote typeface cache, and caching of both typefaces +// and fonts to facilitate sharing of them across font lists. +// - Determination of the fallback typeface for a specific character using a +// specific font style, and caching of that information for subsequent +// lookups. +// - Creation of glyph buffers, which is accomplished by passing the request +// to the resource provider. // NOTE: The font cache is not thread-safe and must only used within a single // thread. class FontCache {
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc index 3e23ed9..054f995 100644 --- a/src/cobalt/dom/window.cc +++ b/src/cobalt/dom/window.cc
@@ -39,9 +39,6 @@ #include "cobalt/dom/storage.h" #include "cobalt/dom/window_timers.h" #include "cobalt/script/javascript_engine.h" -#if defined(OS_STARBOARD) -#include "starboard/system.h" -#endif namespace cobalt { namespace dom { @@ -85,6 +82,7 @@ const std::string& default_security_policy, CspEnforcementType csp_enforcement_mode, const base::Closure& csp_policy_changed_callback, + const base::Closure& window_close_callback, int csp_insecure_allowed_token) : width_(width), height_(height), @@ -123,7 +121,8 @@ new Storage(this, Storage::kLocalStorage, local_storage_database))), ALLOW_THIS_IN_INITIALIZER_LIST( session_storage_(new Storage(this, Storage::kSessionStorage, NULL))), - screen_(new Screen(width, height)) { + screen_(new Screen(width, height)), + window_close_callback_(window_close_callback) { #if defined(ENABLE_TEST_RUNNER) test_runner_ = new TestRunner(); #endif // ENABLE_TEST_RUNNER @@ -140,11 +139,9 @@ // https://www.w3.org/TR/html5/browsers.html#dom-window-close void Window::Close() { -#if defined(OS_STARBOARD) - SbSystemRequestStop(0); -#else - LOG(WARNING) << "window.close is not supported on this platform."; -#endif + if (!window_close_callback_.is_null()) { + window_close_callback_.Run(); + } } const scoped_refptr<Navigator>& Window::navigator() const { return navigator_; }
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h index 8240112..7853ada 100644 --- a/src/cobalt/dom/window.h +++ b/src/cobalt/dom/window.h
@@ -107,6 +107,7 @@ const std::string& default_security_policy, dom::CspEnforcementType csp_enforcement_mode, const base::Closure& csp_policy_changed_callback, + const base::Closure& window_close_callback, int csp_insecure_allowed_token = 0); // Web API: Window @@ -277,6 +278,8 @@ scoped_refptr<Screen> screen_; + base::Closure window_close_callback_; + #if defined(ENABLE_TEST_RUNNER) scoped_refptr<TestRunner> test_runner_; #endif // ENABLE_TEST_RUNNER
diff --git a/src/cobalt/dom/window_test.cc b/src/cobalt/dom/window_test.cc index 43650c0..8879146 100644 --- a/src/cobalt/dom/window_test.cc +++ b/src/cobalt/dom/window_test.cc
@@ -61,7 +61,8 @@ base::Unretained(&mock_error_callback_)), NULL, network_bridge::PostSender(), std::string() /* default security policy */, kCspEnforcementEnable, - base::Closure() /* csp_policy_changed */)) {} + base::Closure() /* csp_policy_changed */, + base::Closure() /* window_close */)) {} ~WindowTest() OVERRIDE {}
diff --git a/src/cobalt/layout/layout.cc b/src/cobalt/layout/layout.cc index 46ca1c1..bd61bde 100644 --- a/src/cobalt/layout/layout.cc +++ b/src/cobalt/layout/layout.cc
@@ -78,7 +78,7 @@ *initial_containing_block = initial_containing_block_creation_results.box; // Generate boxes. - { + if (document->html()) { TRACE_EVENT0("cobalt::layout", kBenchmarkStatBoxGeneration); base::StopWatch stop_watch_box_generation( LayoutStatTracker::kStopWatchTypeBoxGeneration,
diff --git a/src/cobalt/layout_tests/layout_snapshot.cc b/src/cobalt/layout_tests/layout_snapshot.cc index 97b7689..5fb8bce 100644 --- a/src/cobalt/layout_tests/layout_snapshot.cc +++ b/src/cobalt/layout_tests/layout_snapshot.cc
@@ -85,8 +85,9 @@ url, base::Bind(&WebModuleOnRenderTreeProducedCallback, &results, &run_loop, MessageLoop::current()), base::Bind(&WebModuleErrorCallback, &run_loop, MessageLoop::current()), - stub_media_module.get(), &network_module, viewport_size, - resource_provider, 60.0f, web_module_options); + base::Closure() /* window_close_callback */, stub_media_module.get(), + &network_module, viewport_size, resource_provider, 60.0f, + web_module_options); run_loop.Run();
diff --git a/src/cobalt/layout_tests/web_platform_tests.cc b/src/cobalt/layout_tests/web_platform_tests.cc index 14e32ae..d984a55 100644 --- a/src/cobalt/layout_tests/web_platform_tests.cc +++ b/src/cobalt/layout_tests/web_platform_tests.cc
@@ -176,8 +176,9 @@ url, base::Bind(&WebModuleOnRenderTreeProducedCallback, &results, &run_loop, MessageLoop::current()), base::Bind(&WebModuleErrorCallback, &run_loop, MessageLoop::current()), - media_module.get(), &network_module, kDefaultViewportSize, - &resource_provider, 60.0f, web_module_options); + base::Closure() /* window_close_callback */, media_module.get(), + &network_module, kDefaultViewportSize, &resource_provider, 60.0f, + web_module_options); run_loop.Run(); const std::string extract_results = "document.getElementById(\"__testharness__results__\").textContent;";
diff --git a/src/cobalt/loader/embedded_resources/splash_screen.css b/src/cobalt/loader/embedded_resources/splash_screen.css index 0af40bf..7602576 100644 --- a/src/cobalt/loader/embedded_resources/splash_screen.css +++ b/src/cobalt/loader/embedded_resources/splash_screen.css
@@ -4,11 +4,11 @@ } #splash { - background-color: #e62d27; + background-color: #e62117; background-image: url("h5vcc-embedded://you_tube_logo.png"); background-position: center center; background-repeat: no-repeat; - background-size: 60%; + background-size: 100%; height: 100%; left: 0; position: absolute;
diff --git a/src/cobalt/loader/embedded_resources/you_tube_logo.png b/src/cobalt/loader/embedded_resources/you_tube_logo.png index 0d2082d..a964097 100644 --- a/src/cobalt/loader/embedded_resources/you_tube_logo.png +++ b/src/cobalt/loader/embedded_resources/you_tube_logo.png Binary files differ
diff --git a/src/cobalt/media/media_module_starboard.cc b/src/cobalt/media/media_module_starboard.cc index 4c54544..f4cf154 100644 --- a/src/cobalt/media/media_module_starboard.cc +++ b/src/cobalt/media/media_module_starboard.cc
@@ -16,21 +16,14 @@ #include "cobalt/media/media_module.h" -#include "base/bind.h" #include "base/compiler_specific.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/math/size.h" #include "cobalt/media/shell_media_platform_starboard.h" #include "cobalt/system_window/starboard/system_window.h" -#include "media/audio/null_audio_streamer.h" -#include "media/audio/shell_audio_sink.h" #include "media/base/filter_collection.h" #include "media/base/media_log.h" #include "media/base/message_loop_factory.h" -#include "media/filters/shell_audio_decoder_impl.h" -#include "media/filters/shell_raw_audio_decoder_stub.h" -#include "media/filters/shell_raw_video_decoder_stub.h" -#include "media/filters/shell_video_decoder_impl.h" #include "media/player/web_media_player_impl.h" #include "starboard/media.h" #include "starboard/window.h" @@ -76,14 +69,6 @@ message_loop_factory->GetMessageLoop(MessageLoopFactory::kPipeline); scoped_ptr<FilterCollection> filter_collection(new FilterCollection); - ::media::ShellAudioStreamer* streamer = NULL; - if (options_.use_null_audio_streamer) { - DLOG(INFO) << "Use Null audio"; - streamer = ::media::NullAudioStreamer::GetInstance(); - } else { - DLOG(INFO) << "Use Pulse audio"; - streamer = ::media::ShellAudioStreamer::Instance(); - } SbWindow window = kSbWindowInvalid; if (system_window_) { window = polymorphic_downcast<SystemWindowStarboard*>(system_window_) @@ -91,8 +76,8 @@ } return make_scoped_ptr<WebMediaPlayer>(new ::media::WebMediaPlayerImpl( window, client, this, media_platform_.GetVideoFrameProvider(), - filter_collection.Pass(), new ::media::ShellAudioSink(streamer), - message_loop_factory.Pass(), new ::media::MediaLog)); + filter_collection.Pass(), NULL, message_loop_factory.Pass(), + new ::media::MediaLog)); } private:
diff --git a/src/cobalt/render_tree/node_visitor_test.cc b/src/cobalt/render_tree/node_visitor_test.cc index ad7c3b2..cc6a84f 100644 --- a/src/cobalt/render_tree/node_visitor_test.cc +++ b/src/cobalt/render_tree/node_visitor_test.cc
@@ -101,7 +101,7 @@ } }; -void SetBounds(const cobalt::math::Rect&) {} +bool SetBounds(const cobalt::math::Rect&) { return false; } } // namespace
diff --git a/src/cobalt/render_tree/punch_through_video_node.h b/src/cobalt/render_tree/punch_through_video_node.h index 7261ab7..22dd0f9 100644 --- a/src/cobalt/render_tree/punch_through_video_node.h +++ b/src/cobalt/render_tree/punch_through_video_node.h
@@ -41,7 +41,7 @@ // support punch out video rendering. class PunchThroughVideoNode : public Node { public: - typedef base::Callback<void(const math::Rect&)> SetBoundsCB; + typedef base::Callback<bool(const math::Rect&)> SetBoundsCB; struct Builder { Builder(const math::RectF& rect, const SetBoundsCB& set_bounds_cb)
diff --git a/src/cobalt/renderer/copy_font_data.gypi b/src/cobalt/renderer/copy_font_data.gypi index 2ce0512..405ad41 100644 --- a/src/cobalt/renderer/copy_font_data.gypi +++ b/src/cobalt/renderer/copy_font_data.gypi
@@ -17,15 +17,192 @@ { 'includes': [ '../build/contents_dir.gypi' ], - 'variables': { - 'fonts_dir': '<(static_contents_source_dir)/fonts', + 'source_all_fonts_dir': '<(static_contents_source_dir)/fonts/all_fonts', }, 'copies': [ { - 'destination': '<(static_contents_output_data_dir)', - 'files': [ '<@(fonts_dir)' ], + 'destination': '<(static_contents_output_data_dir)/fonts/', + 'files': [ + '<(static_contents_source_dir)/fonts/<(cobalt_font_package)/fonts.xml', + ], + 'conditions': [ + [ 'cobalt_font_package == "minimal"', { + 'files+': [ + '<(source_all_fonts_dir)/MinimalRoboto.ttf', + '<(source_all_fonts_dir)/CarroisGothicSC-Regular.ttf', + ], + }], # minimal + [ 'cobalt_font_package == "10megabytes"', { + 'files+': [ + '<(source_all_fonts_dir)/NotoSansTagbanwa-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSinhala-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansNewTaiLue-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSundanese-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMandaic-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansGurmukhiUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansDevanagariUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMongolian-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBamum-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBuhid-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansCherokee-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansArmenian-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansJP-Regular.otf', + '<(source_all_fonts_dir)/NotoSansEthiopic-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansGlagolitic-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBatak-Regular.ttf', + '<(source_all_fonts_dir)/Roboto-Regular.ttf', + '<(source_all_fonts_dir)/NotoNaskhArabicUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBuginese-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansVai-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTifinagh-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansCham-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansJavanese-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTeluguUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTaiLe-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMeeteiMayek-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKannadaUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSyriacEstrangela-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBengaliUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansThaiUI-Regular.ttf', + '<(source_all_fonts_dir)/CarroisGothicSC-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansNKo-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansGeorgian-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSymbols-Regular-Subsetted.ttf', + '<(source_all_fonts_dir)/NotoSansCoptic-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansYi-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTaiTham-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansOlChiki-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansOriyaUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSylotiNagri-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansRejang-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansCanadianAboriginal-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansLisu-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTibetan-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKayahLi-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansLaoUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansHanunoo-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTaiViet-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansHebrew-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBalinese-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTamilUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansGujaratiUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMalayalamUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansLepcha-Regular.ttf', + '<(source_all_fonts_dir)/NotoEmoji-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansThaana-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKhmerUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSaurashtra-Regular.ttf', + '<(source_all_fonts_dir)/DroidSansFallback.ttf', + '<(source_all_fonts_dir)/NotoSansLimbu-Regular.ttf', + ], + }], # 10megabytes + [ 'cobalt_font_package == "unlimited"', { + 'files+': [ + '<(source_all_fonts_dir)/NotoSansTagbanwa-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSinhala-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansNewTaiLue-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSundanese-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMandaic-Regular.ttf', + '<(source_all_fonts_dir)/NotoSerif-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansTeluguUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansMyanmarUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansGurmukhiUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansDevanagariUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMongolian-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansArmenian-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansBamum-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBuhid-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansEthiopic-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansDevanagariUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansCherokee-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansArmenian-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansJP-Regular.otf', + '<(source_all_fonts_dir)/NotoSansOriyaUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansEthiopic-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansGlagolitic-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBatak-Regular.ttf', + '<(source_all_fonts_dir)/Roboto-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTC-Regular.otf', + '<(source_all_fonts_dir)/NotoSerif-Regular.ttf', + '<(source_all_fonts_dir)/NotoNaskhArabicUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBuginese-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansVai-Regular.ttf', + '<(source_all_fonts_dir)/MTLmr3m.ttf', + '<(source_all_fonts_dir)/NanumGothic.ttf', + '<(source_all_fonts_dir)/ComingSoon.ttf', + '<(source_all_fonts_dir)/NotoSansTifinagh-Regular.ttf', + '<(source_all_fonts_dir)/DancingScript-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansCham-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSC-Regular.otf', + '<(source_all_fonts_dir)/NotoSansHebrew-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansJavanese-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTeluguUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTaiLe-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMeeteiMayek-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKannadaUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKhmerUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansSyriacEstrangela-Regular.ttf', + '<(source_all_fonts_dir)/NotoSerif-BoldItalic.ttf', + '<(source_all_fonts_dir)/NotoSansBengaliUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansThaiUI-Regular.ttf', + '<(source_all_fonts_dir)/CutiveMono.ttf', + '<(source_all_fonts_dir)/DroidSansMono.ttf', + '<(source_all_fonts_dir)/CarroisGothicSC-Regular.ttf', + '<(source_all_fonts_dir)/Roboto-Italic.ttf', + '<(source_all_fonts_dir)/NotoSansNKo-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansGeorgian-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSymbols-Regular-Subsetted.ttf', + '<(source_all_fonts_dir)/NotoSansCoptic-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansYi-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTaiTham-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMyanmarUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansMalayalamUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansGujaratiUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansLaoUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansOlChiki-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansOriyaUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSylotiNagri-Regular.ttf', + '<(source_all_fonts_dir)/Roboto-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansRejang-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansThaiUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansCanadianAboriginal-Regular.ttf', + '<(source_all_fonts_dir)/Roboto-BoldItalic.ttf', + '<(source_all_fonts_dir)/NotoSansLisu-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTibetan-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKayahLi-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansLaoUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansHanunoo-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTaiViet-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKannadaUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansSinhala-Bold.ttf', + '<(source_all_fonts_dir)/NotoSerif-Italic.ttf', + '<(source_all_fonts_dir)/NotoSansGurmukhiUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansHebrew-Regular.ttf', + '<(source_all_fonts_dir)/DancingScript-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansBalinese-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTamilUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansGujaratiUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansGeorgian-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansMalayalamUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansLepcha-Regular.ttf', + '<(source_all_fonts_dir)/NotoEmoji-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansTamilUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansThaana-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKhmerUI-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansSaurashtra-Regular.ttf', + '<(source_all_fonts_dir)/NotoSansKR-Regular.otf', + '<(source_all_fonts_dir)/NotoSansCham-Bold.ttf', + '<(source_all_fonts_dir)/DroidSansFallback.ttf', + '<(source_all_fonts_dir)/NotoSansBengaliUI-Bold.ttf', + '<(source_all_fonts_dir)/MinimalRoboto.ttf', + '<(source_all_fonts_dir)/NotoSansLimbu-Regular.ttf', + '<(source_all_fonts_dir)/NotoNaskhArabicUI-Bold.ttf', + '<(source_all_fonts_dir)/NotoSansThaana-Bold.ttf', + ], + }], # unlimited + ], }, ], }
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl index 6fcae22..0a0d63b 100644 --- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl
@@ -11,7 +11,7 @@ // Stage 0: YUV to RGB output_Stage0 = vec4( texture2D(uSampler0_Stage0, vMatrixCoord_Stage0).aaaa.r, - texture2D(uSampler1_Stage0, vMatrixCoord_Stage0).ba, + texture2D(uSampler1_Stage0, vMatrixCoord_Stage0).ra, 1.0) * uYUVMatrix_Stage0; } gl_FragColor = output_Stage0;
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 12475b8..d0f5377 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
@@ -240,18 +240,23 @@ void RenderTreeNodeVisitor::Visit( render_tree::PunchThroughVideoNode* punch_through_video_node) { - SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 0, 0)); - SbBlitterSetBlending(context_, false); SbBlitterRect blitter_rect = RectFToBlitterRect(render_state_.transform.TransformRect( punch_through_video_node->data().rect)); - SbBlitterFillRect(context_, blitter_rect); - if (!punch_through_video_node->data().set_bounds_cb.is_null()) { - punch_through_video_node->data().set_bounds_cb.Run( - math::Rect(blitter_rect.x, blitter_rect.y, blitter_rect.width, - blitter_rect.height)); + if (punch_through_video_node->data().set_bounds_cb.is_null()) { + return; } + bool render_punch_through = + punch_through_video_node->data().set_bounds_cb.Run( + math::Rect(blitter_rect.x, blitter_rect.y, blitter_rect.width, + blitter_rect.height)); + if (!render_punch_through) { + return; + } + SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 0, 0)); + SbBlitterSetBlending(context_, false); + SbBlitterFillRect(context_, blitter_rect); } namespace {
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc index 6dc87b7..6f821ed 100644 --- a/src/cobalt/renderer/rasterizer/pixel_test.cc +++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -113,7 +113,7 @@ namespace { -void SetBounds(const math::Rect&) {} +bool SetBounds(bool result, const math::Rect&) { return result; } } // namespace @@ -2749,14 +2749,30 @@ RoundedCorners(50, 50))); } -TEST_F(PixelTest, PunchThroughVideoNodePunchesThrough) { +// If SetBoundsCB() returns false, the PunchThroughVideoNode should have no +// effect. +TEST_F(PixelTest, PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse) { CompositionNode::Builder builder; builder.AddChild(new RectNode(RectF(25, 25, 150, 150), scoped_ptr<Brush>(new SolidColorBrush( ColorRGBA(0.5f, 0.5f, 1.0f, 1.0f))))); builder.AddChild(new PunchThroughVideoNode(PunchThroughVideoNode::Builder( - RectF(50, 50, 100, 100), base::Bind(SetBounds)))); + RectF(50, 50, 100, 100), base::Bind(SetBounds, false)))); + + TestTree(new CompositionNode(builder.Pass())); +} + +// If SetBoundsCB() returns true, the PunchThroughVideoNode should trigger the +// painting of a solid rectangle with RGBA(0, 0, 0, 0). +TEST_F(PixelTest, PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsTrue) { + CompositionNode::Builder builder; + builder.AddChild(new RectNode(RectF(25, 25, 150, 150), + scoped_ptr<Brush>(new SolidColorBrush( + ColorRGBA(0.5f, 0.5f, 1.0f, 1.0f))))); + + builder.AddChild(new PunchThroughVideoNode(PunchThroughVideoNode::Builder( + RectF(50, 50, 100, 100), base::Bind(SetBounds, true)))); TestTree(new CompositionNode(builder.Pass())); }
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc index b0b493f..ab9fc7d 100644 --- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc +++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -697,9 +697,6 @@ const math::RectF& math_rect = punch_through_video_node->data().rect; - SkPaint paint; - paint.setXfermodeMode(SkXfermode::kSrc_Mode); - paint.setARGB(0, 0, 0, 0); SkRect sk_rect = SkRect::MakeXYWH(math_rect.x(), math_rect.y(), math_rect.width(), math_rect.height()); SkMatrix total_matrix = draw_state_.render_target->getTotalMatrix(); @@ -707,13 +704,22 @@ SkRect sk_rect_transformed; total_matrix.mapRect(&sk_rect_transformed, sk_rect); - if (!punch_through_video_node->data().set_bounds_cb.is_null()) { - punch_through_video_node->data().set_bounds_cb.Run( - math::Rect(static_cast<int>(sk_rect_transformed.x()), - static_cast<int>(sk_rect_transformed.y()), - static_cast<int>(sk_rect_transformed.width()), - static_cast<int>(sk_rect_transformed.height()))); + if (punch_through_video_node->data().set_bounds_cb.is_null()) { + return; } + bool render_punch_through = + punch_through_video_node->data().set_bounds_cb.Run( + math::Rect(static_cast<int>(sk_rect_transformed.x()), + static_cast<int>(sk_rect_transformed.y()), + static_cast<int>(sk_rect_transformed.width()), + static_cast<int>(sk_rect_transformed.height()))); + if (!render_punch_through) { + return; + } + + SkPaint paint; + paint.setXfermodeMode(SkXfermode::kSrc_Mode); + paint.setARGB(0, 0, 0, 0); draw_state_.render_target->drawRect(sk_rect, paint);
diff --git a/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png b/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png new file mode 100644 index 0000000..d26f087 --- /dev/null +++ b/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThrough-expected.png b/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsTrue-expected.png similarity index 100% rename from src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThrough-expected.png rename to src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsTrue-expected.png Binary files differ
diff --git a/src/cobalt/script/mozjs/conversion_helpers.h b/src/cobalt/script/mozjs/conversion_helpers.h index 3d54ec6..19a8ec8 100644 --- a/src/cobalt/script/mozjs/conversion_helpers.h +++ b/src/cobalt/script/mozjs/conversion_helpers.h
@@ -71,7 +71,6 @@ size_t length = in_string.length(); jschar* inflated_buffer = js::InflateUTF8String(context, in_string.c_str(), &length); - DCHECK(inflated_buffer); if (!inflated_buffer) { LOG(ERROR) << "Failed to inflate UTF8 string.";
diff --git a/src/cobalt/script/mozjs/mozjs.gyp b/src/cobalt/script/mozjs/mozjs.gyp index b29d99b..6e856f5 100644 --- a/src/cobalt/script/mozjs/mozjs.gyp +++ b/src/cobalt/script/mozjs/mozjs.gyp
@@ -73,5 +73,30 @@ '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib', ], }, + + { + 'target_name': 'mozjs_engine_test', + 'type': '<(gtest_target_type)', + 'sources': [ + '<(DEPTH)/third_party/mozjs/test/jscustomallocator_test.cc', + ], + 'dependencies': [ + '<(DEPTH)/base/base.gyp:run_all_unittests', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib', + ], + }, + + { + 'target_name': 'mozjs_engine_test_deploy', + 'type': 'none', + 'dependencies': [ + 'mozjs_engine_test', + ], + 'variables': { + 'executable_name': 'mozjs_engine_test', + }, + 'includes': [ '../../../starboard/build/deploy.gypi' ], + }, ], }
diff --git a/src/cobalt/script/mozjs/mozjs_engine.cc b/src/cobalt/script/mozjs/mozjs_engine.cc index 1b79cf7..39f47bb 100644 --- a/src/cobalt/script/mozjs/mozjs_engine.cc +++ b/src/cobalt/script/mozjs/mozjs_engine.cc
@@ -19,7 +19,11 @@ #include <algorithm> #include "base/logging.h" +#include "cobalt/base/c_val.h" +#include "cobalt/base/poller.h" +#include "cobalt/browser/web_module.h" #include "cobalt/script/mozjs/mozjs_global_environment.h" +#include "third_party/mozjs/cobalt_config/include/jscustomallocator.h" #include "third_party/mozjs/js/src/jsapi.h" namespace cobalt { @@ -38,6 +42,64 @@ CheckAccessStub, MozjsGlobalEnvironment::CheckEval }; + +#if defined(__LB_SHELL__FOR_RELEASE__) +const int kPollerPeriodMs = 2000; +#else // #if defined(__LB_SHELL__FOR_RELEASE__) +const int kPollerPeriodMs = 20; +#endif // #if defined(__LB_SHELL__FOR_RELEASE__) + +class EngineStats { + public: + EngineStats(); + + static EngineStats* GetInstance() { + return Singleton<EngineStats, + StaticMemorySingletonTraits<EngineStats> >::get(); + } + + void EngineCreated() { + base::AutoLock auto_lock(lock_); + ++engine_count_; + } + + void EngineDestroyed() { + base::AutoLock auto_lock(lock_); + --engine_count_; + } + + void Update() { + base::AutoLock auto_lock(lock_); + allocated_memory_ = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + mapped_memory_ = MemoryAllocatorReporter::Get()->GetCurrentBytesMapped(); + memory_sum_ = allocated_memory_ + mapped_memory_; + } + + private: + base::Lock lock_; + base::CVal<size_t, base::CValPublic> allocated_memory_; + base::CVal<size_t, base::CValPublic> mapped_memory_; + base::CVal<size_t, base::CValPublic> memory_sum_; + base::CVal<size_t> engine_count_; + + // Repeating timer to query the used bytes. + scoped_ptr<base::PollerWithThread> poller_; +}; + +EngineStats::EngineStats() + : allocated_memory_("Memory.JS.AllocatedMemory", 0, + "JS memory occupied by the Mozjs allocator."), + mapped_memory_("Memory.JS.MappedMemory", 0, "JS mapped memory."), + memory_sum_("Memory.JS", 0, + "Total memory occupied by the Mozjs allocator and heap."), + engine_count_("Count.JS.Engine", 0, + "Total JavaScript engine registered.") { + poller_.reset(new base::PollerWithThread( + base::Bind(&EngineStats::Update, base::Unretained(this)), + base::TimeDelta::FromMilliseconds(kPollerPeriodMs))); +} + } // namespace MozjsEngine::MozjsEngine() { @@ -47,6 +109,12 @@ JS_NewRuntime(kGarbageCollectionThresholdBytes, JS_NO_HELPER_THREADS); CHECK(runtime_); + // Sets the size of the native stack that should not be exceeded. + // Setting three quarters of the web module stack size to ensure that native + // stack won't exceed the stack size. + JS_SetNativeStackQuota(runtime_, + browser::WebModule::kWebModuleStackSize / 4 * 3); + JS_SetRuntimePrivate(runtime_, this); JS_SetSecurityCallbacks(runtime_, &security_callbacks); @@ -68,10 +136,13 @@ // Callback to be called during garbage collection during the sweep phase. JS_SetFinalizeCallback(runtime_, &MozjsEngine::FinalizeCallback); + + EngineStats::GetInstance()->EngineCreated(); } MozjsEngine::~MozjsEngine() { DCHECK(thread_checker_.CalledOnValidThread()); + EngineStats::GetInstance()->EngineDestroyed(); JS_DestroyRuntime(runtime_); }
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.cc b/src/cobalt/script/mozjs/mozjs_global_environment.cc index 25fa34b..9a79991 100644 --- a/src/cobalt/script/mozjs/mozjs_global_environment.cc +++ b/src/cobalt/script/mozjs/mozjs_global_environment.cc
@@ -195,33 +195,16 @@ const scoped_refptr<SourceCode>& source_code, std::string* out_result_utf8) { DCHECK(thread_checker_.CalledOnValidThread()); - MozjsSourceCode* mozjs_source_code = - base::polymorphic_downcast<MozjsSourceCode*>(source_code.get()); - - const std::string& script = mozjs_source_code->source_utf8(); - const base::SourceLocation location = mozjs_source_code->location(); JSAutoRequest auto_request(context_); JSAutoCompartment auto_compartment(context_, global_object_proxy_); JSExceptionState* previous_exception_state = JS_SaveExceptionState(context_); JS::RootedValue result_value(context_); + std::string error_message; last_error_message_ = &error_message; - JS::RootedObject global_object( - context_, js::GetProxyTargetObject(global_object_proxy_)); - size_t length = script.size(); - jschar* inflated_buffer = - js::InflateUTF8String(context_, script.c_str(), &length); - DCHECK(inflated_buffer); - bool success = false; - if (inflated_buffer) { - success = JS_EvaluateUCScript(context_, global_object, inflated_buffer, - length, location.file_path.c_str(), - location.line_number, result_value.address()); - js_free(inflated_buffer); - } - + bool success = EvaluateScriptInternal(source_code, &result_value); if (out_result_utf8) { if (success) { MozjsExceptionState exception_state(context_); @@ -233,8 +216,61 @@ DLOG(ERROR) << "Script execution failed."; } } - JS_RestoreExceptionState(context_, previous_exception_state); last_error_message_ = NULL; + JS_RestoreExceptionState(context_, previous_exception_state); + return success; +} + +bool MozjsGlobalEnvironment::EvaluateScript( + const scoped_refptr<SourceCode>& source_code, + const scoped_refptr<Wrappable>& owning_object, + base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) { + DCHECK(thread_checker_.CalledOnValidThread()); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, global_object_proxy_); + JSExceptionState* previous_exception_state = JS_SaveExceptionState(context_); + JS::RootedValue result_value(context_); + if (!EvaluateScriptInternal(source_code, &result_value)) { + return false; + } + if (out_opaque_handle) { + JS::RootedObject js_object(context_); + JS_ValueToObject(context_, result_value, js_object.address()); + MozjsObjectHandleHolder mozjs_object_holder(js_object, context_, + wrapper_factory()); + out_opaque_handle->emplace(owning_object.get(), mozjs_object_holder); + } + JS_RestoreExceptionState(context_, previous_exception_state); + return true; +} + +bool MozjsGlobalEnvironment::EvaluateScriptInternal( + const scoped_refptr<SourceCode>& source_code, + JS::MutableHandleValue out_result) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(global_object_proxy_); + MozjsSourceCode* mozjs_source_code = + base::polymorphic_downcast<MozjsSourceCode*>(source_code.get()); + + const std::string& script = mozjs_source_code->source_utf8(); + const base::SourceLocation location = mozjs_source_code->location(); + + JS::RootedObject global_object( + context_, js::GetProxyTargetObject(global_object_proxy_)); + + size_t length = script.size(); + jschar* inflated_buffer = + js::InflateUTF8String(context_, script.c_str(), &length); + bool success = false; + if (inflated_buffer) { + success = JS_EvaluateUCScript(context_, global_object, inflated_buffer, + length, location.file_path.c_str(), + location.line_number, out_result.address()); + js_free(inflated_buffer); + } else { + DLOG(ERROR) << "Malformed UTF-8 script."; + } + return success; } @@ -321,7 +357,7 @@ if (global_object_proxy_ && garbage_collection_count_ == 1) { DCHECK(!opaque_root_state_); JSAutoRequest auto_request(context_); - JSAutoCompartment auto_comparment(context_, global_object_proxy_); + JSAutoCompartment auto_compartment(context_, global_object_proxy_); // Get the current state of opaque root relationships. Keep this object // alive for the duration of the GC phase to ensure that reachability // between roots and reachable objects is maintained.
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.h b/src/cobalt/script/mozjs/mozjs_global_environment.h index 54f75de..d13d7f0 100644 --- a/src/cobalt/script/mozjs/mozjs_global_environment.h +++ b/src/cobalt/script/mozjs/mozjs_global_environment.h
@@ -56,10 +56,7 @@ bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8, const scoped_refptr<Wrappable>& owning_object, base::optional<OpaqueHandleHolder::Reference>* - out_opaque_handle) OVERRIDE { - NOTIMPLEMENTED(); - return false; - } + out_opaque_handle) OVERRIDE; std::vector<StackFrame> GetStackTrace(int max_frames = 0) OVERRIDE; @@ -133,7 +130,10 @@ // with an error that eval() is disabled. static JSBool CheckEval(JSContext* context); - protected: + private: + bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code, + JS::MutableHandleValue out_result); + static void ReportErrorHandler(JSContext* context, const char* message, JSErrorReport* report);
diff --git a/src/glimp/entry_points/gles_2_0.cc b/src/glimp/entry_points/gles_2_0.cc index 10391ca..884318a 100644 --- a/src/glimp/entry_points/gles_2_0.cc +++ b/src/glimp/entry_points/gles_2_0.cc
@@ -281,7 +281,12 @@ } void GL_APIENTRY glCullFace(GLenum mode) { - SB_NOTIMPLEMENTED(); + gles::Context* context = GetCurrentContext(); + if (!context) { + return; + } + + return context->CullFace(mode); } void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers) {
diff --git a/src/glimp/gles/context.cc b/src/glimp/gles/context.cc index a104230..2057fcb 100644 --- a/src/glimp/gles/context.cc +++ b/src/glimp/gles/context.cc
@@ -21,6 +21,7 @@ #include "glimp/egl/error.h" #include "glimp/egl/surface.h" #include "glimp/gles/blend_state.h" +#include "glimp/gles/cull_face_state.h" #include "glimp/gles/draw_mode.h" #include "glimp/gles/index_data_type.h" #include "glimp/gles/pixel_format.h" @@ -299,9 +300,13 @@ draw_state_.scissor.enabled = true; draw_state_dirty_flags_.scissor_dirty = true; break; + case GL_CULL_FACE: + draw_state_.cull_face_state.enabled = true; + draw_state_.cull_face_state.mode = CullFaceState::kBack; + draw_state_dirty_flags_.cull_face_dirty = true; + break; case GL_DEPTH_TEST: case GL_DITHER: - case GL_CULL_FACE: case GL_STENCIL_TEST: case GL_POLYGON_OFFSET_FILL: case GL_SAMPLE_ALPHA_TO_COVERAGE: @@ -323,9 +328,12 @@ draw_state_.scissor.enabled = false; draw_state_dirty_flags_.scissor_dirty = true; break; + case GL_CULL_FACE: + draw_state_.cull_face_state.enabled = false; + draw_state_dirty_flags_.cull_face_dirty = true; + break; case GL_DEPTH_TEST: case GL_DITHER: - case GL_CULL_FACE: case GL_STENCIL_TEST: case GL_POLYGON_OFFSET_FILL: case GL_SAMPLE_ALPHA_TO_COVERAGE: @@ -426,6 +434,31 @@ draw_state_dirty_flags_.blend_state_dirty = true; } +namespace { +CullFaceState::Mode CullFaceModeFromEnum(GLenum mode) { + switch (mode) { + case GL_FRONT: + return CullFaceState::kFront; + case GL_BACK: + return CullFaceState::kBack; + case GL_FRONT_AND_BACK: + return CullFaceState::kFrontAndBack; + default: + return CullFaceState::kModeInvalid; + } +} +} // namespace + +void Context::CullFace(GLenum mode) { + CullFaceState::Mode cull_face_mode = CullFaceModeFromEnum(mode); + if (cull_face_mode == CullFaceState::kModeInvalid) { + SetError(GL_INVALID_ENUM); + return; + } + draw_state_.cull_face_state.mode = cull_face_mode; + draw_state_dirty_flags_.cull_face_dirty = true; +} + GLuint Context::CreateProgram() { GLIMP_TRACE_EVENT0(__FUNCTION__); nb::scoped_ptr<ProgramImpl> program_impl = impl_->CreateProgram();
diff --git a/src/glimp/gles/context.h b/src/glimp/gles/context.h index e028ed5..7d2d919 100644 --- a/src/glimp/gles/context.h +++ b/src/glimp/gles/context.h
@@ -95,6 +95,8 @@ void BlendFunc(GLenum sfactor, GLenum dfactor); + void CullFace(GLenum mode); + GLuint CreateProgram(); void DeleteProgram(GLuint program); void AttachShader(GLuint program, GLuint shader);
diff --git a/src/glimp/gles/cull_face_state.h b/src/glimp/gles/cull_face_state.h new file mode 100644 index 0000000..b68d6b0 --- /dev/null +++ b/src/glimp/gles/cull_face_state.h
@@ -0,0 +1,45 @@ +/* + * Copyright 2016 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 GLIMP_GLES_CULL_FACE_STATE_H_ +#define GLIMP_GLES_CULL_FACE_STATE_H_ + +namespace glimp { +namespace gles { + +// Describes GL cull face state, which can be modified via commands like +// glCullFace(). +// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCullFace.xml +struct CullFaceState { + // When enabled, the initial face culling value should be kBack. + enum Mode { + kFront, + kBack, + kFrontAndBack, + kModeInvalid, + }; + + // Default state is face culling off. + CullFaceState() : enabled(false), mode(kBack) {} + + Mode mode; + bool enabled; +}; + +} // namespace gles +} // namespace glimp + +#endif // GLIMP_GLES_CULL_FACE_STATE_H_
diff --git a/src/glimp/gles/draw_state.h b/src/glimp/gles/draw_state.h index 96f5ec1..db9c2d9 100644 --- a/src/glimp/gles/draw_state.h +++ b/src/glimp/gles/draw_state.h
@@ -24,6 +24,7 @@ #include "glimp/egl/surface.h" #include "glimp/gles/blend_state.h" #include "glimp/gles/buffer.h" +#include "glimp/gles/cull_face_state.h" #include "glimp/gles/framebuffer.h" #include "glimp/gles/program.h" #include "glimp/gles/sampler.h" @@ -156,6 +157,9 @@ // existing pixels in the output framebuffer. BlendState blend_state; + // Defines whether face culling is enabled, and upon which face if so. + CullFaceState cull_face_state; + // The currently bound array buffer, set by calling // glBindBuffer(GL_ARRAY_BUFFER). nb::scoped_refptr<Buffer> array_buffer; @@ -190,6 +194,7 @@ scissor_dirty = true; viewport_dirty = true; blend_state_dirty = true; + cull_face_dirty = true; array_buffer_dirty = true; element_array_buffer_dirty = true; used_program_dirty = true; @@ -205,6 +210,7 @@ bool scissor_dirty; bool viewport_dirty; bool blend_state_dirty; + bool cull_face_dirty; bool array_buffer_dirty; bool element_array_buffer_dirty; bool used_program_dirty;
diff --git a/src/glimp/glimp_common.gypi b/src/glimp/glimp_common.gypi index 4f00bfe..ef1a68c 100644 --- a/src/glimp/glimp_common.gypi +++ b/src/glimp/glimp_common.gypi
@@ -45,6 +45,7 @@ 'gles/context_impl.h', 'gles/convert_pixel_data.cc', 'gles/convert_pixel_data.h', + 'gles/cull_face_state.h', 'gles/draw_mode.h', 'gles/draw_state.cc', 'gles/draw_state.h',
diff --git a/src/media/base/pipeline.h b/src/media/base/pipeline.h index 3f5aaf6..0912c6b 100644 --- a/src/media/base/pipeline.h +++ b/src/media/base/pipeline.h
@@ -51,7 +51,9 @@ // playing. class MEDIA_EXPORT Pipeline : public base::RefCountedThreadSafe<Pipeline> { public: - typedef base::Callback<void(const gfx::Rect&)> SetBoundsCB; + // Return true if the punch through box should be rendered. Return false if + // no punch through box should be rendered. + typedef base::Callback<bool(const gfx::Rect&)> SetBoundsCB; // Buffering states the pipeline transitions between during playback. // kHaveMetadata:
diff --git a/src/media/base/sbplayer_pipeline.cc b/src/media/base/sbplayer_pipeline.cc index ead7b85..971f574 100644 --- a/src/media/base/sbplayer_pipeline.cc +++ b/src/media/base/sbplayer_pipeline.cc
@@ -118,12 +118,13 @@ base::Lock lock_; player_ = player; } - void SetBounds(const gfx::Rect& rect) { + bool SetBounds(const gfx::Rect& rect) { base::AutoLock auto_lock(lock_); - if (SbPlayerIsValid(player_)) { - SbPlayerSetBounds(player_, rect.x(), rect.y(), rect.width(), - rect.height()); + if (!SbPlayerIsValid(player_)) { + return false; } + SbPlayerSetBounds(player_, rect.x(), rect.y(), rect.width(), rect.height()); + return true; } private: @@ -725,7 +726,7 @@ video_read_in_progress_ = false; if (buffer->IsEndOfStream()) { - SbPlayerWriteEndOfStream(player_, kSbMediaTypeAudio); + SbPlayerWriteEndOfStream(player_, kSbMediaTypeVideo); return; } SbMediaVideoSampleInfo video_info;
diff --git a/src/media/player/web_media_player.h b/src/media/player/web_media_player.h index 77a9c0c..ef6b89a 100644 --- a/src/media/player/web_media_player.h +++ b/src/media/player/web_media_player.h
@@ -32,7 +32,9 @@ class WebMediaPlayer { public: - typedef base::Callback<void(const gfx::Rect&)> SetBoundsCB; + // Return true if the punch through box should be rendered. Return false if + // no punch through box should be rendered. + typedef base::Callback<bool(const gfx::Rect&)> SetBoundsCB; enum NetworkState { kNetworkStateEmpty,
diff --git a/src/nb/allocator.h b/src/nb/allocator.h index c5ddf7c..75ac4ed 100644 --- a/src/nb/allocator.h +++ b/src/nb/allocator.h
@@ -42,14 +42,21 @@ // Will return NULL if the allocation fails. virtual void* Allocate(std::size_t size, std::size_t alignment) = 0; - // Allocates a range of memory of the given size for the given alignment. - // Returns a pointer that may not be aligned but points to a memory area that - // is still large enough when the pointer is subsequently aligned to the given - // alignment. It can allocate up to size + alignment - 1 bytes. This allows a - // reuse allocator to use the padding area as a free block. Will return NULL - // if the allocation fails. - virtual void* AllocateForAlignment(std::size_t size, - std::size_t alignment) = 0; + // When supported, allocates a range of memory of the given size for the given + // alignment. Returns a pointer that may not be aligned but points to a memory + // area that is still large enough when the pointer is subsequently aligned to + // the given alignment. This allows a reuse allocator to use the padding area + // as a free block. |size| will be set to the actual size allocated on + // successful allocations. Will return NULL if the allocation fails. In the + // case that the underlying block size is inconvenient or impossible to be + // retreived, the |size| can remain unchanged for a successful allocation. The + // user may lose the ability to combine two adjacent allocations in this case. + // Note that the coding style recommends that in/out parameters to be placed + // after input parameters but |size| is kept in the left for consistency. + virtual void* AllocateForAlignment(std::size_t* /*size*/, + std::size_t /*alignment*/) { + return 0; + } // Frees memory previously allocated via any call to Allocate(). virtual void Free(void* memory) = 0;
diff --git a/src/nb/allocator_decorator.cc b/src/nb/allocator_decorator.cc index daa5320..18578b1 100644 --- a/src/nb/allocator_decorator.cc +++ b/src/nb/allocator_decorator.cc
@@ -68,7 +68,7 @@ return impl_->Allocate(size, alignment); } -void* AllocatorDecorator::AllocateForAlignment(std::size_t size, +void* AllocatorDecorator::AllocateForAlignment(std::size_t* size, std::size_t alignment) { ScopedLock scoped_lock(lock_); return impl_->AllocateForAlignment(size, alignment);
diff --git a/src/nb/allocator_decorator.h b/src/nb/allocator_decorator.h index 13969ad..78a8407 100644 --- a/src/nb/allocator_decorator.h +++ b/src/nb/allocator_decorator.h
@@ -34,7 +34,7 @@ void* Allocate(std::size_t size); void* Allocate(std::size_t size, std::size_t alignment); - void* AllocateForAlignment(std::size_t size, std::size_t alignment); + void* AllocateForAlignment(std::size_t* size, std::size_t alignment); void Free(void* memory); std::size_t GetCapacity() const; std::size_t GetAllocated() const;
diff --git a/src/nb/fixed_no_free_allocator.cc b/src/nb/fixed_no_free_allocator.cc index 3722da6..53a615f 100644 --- a/src/nb/fixed_no_free_allocator.cc +++ b/src/nb/fixed_no_free_allocator.cc
@@ -27,28 +27,6 @@ next_memory_ = memory_start_; } -void* FixedNoFreeAllocator::Allocate(std::size_t size, - std::size_t alignment, - bool align_pointer) { - // Find the next aligned memory available. - uint8_t* aligned_next_memory = - AsPointer(AlignUp(AsInteger(next_memory_), alignment)); - - if (aligned_next_memory + size < aligned_next_memory) { - // "aligned_next_memory + size" overflows. - return NULL; - } - - if (aligned_next_memory + size > memory_end_) { - // We don't have enough memory available to make this allocation. - return NULL; - } - - void* memory_pointer = align_pointer ? aligned_next_memory : next_memory_; - next_memory_ = aligned_next_memory + size; - return memory_pointer; -} - void FixedNoFreeAllocator::Free(void* memory) { // Nothing to do here besides ensure that the freed memory belongs to us. SB_DCHECK(memory >= memory_start_); @@ -67,4 +45,30 @@ SB_NOTIMPLEMENTED(); } +void* FixedNoFreeAllocator::Allocate(std::size_t* size, + std::size_t alignment, + bool align_pointer) { + // Find the next aligned memory available. + uint8_t* aligned_next_memory = + AsPointer(AlignUp(AsInteger(next_memory_), alignment)); + + if (aligned_next_memory + *size < aligned_next_memory) { + // "aligned_next_memory + size" overflows. + return NULL; + } + + if (aligned_next_memory + *size > memory_end_) { + // We don't have enough memory available to make this allocation. + return NULL; + } + + if (!align_pointer) { + *size += AsInteger(aligned_next_memory) - AsInteger(next_memory_); + } + + void* memory_pointer = align_pointer ? aligned_next_memory : next_memory_; + next_memory_ = aligned_next_memory + *size; + return memory_pointer; +} + } // namespace nb
diff --git a/src/nb/fixed_no_free_allocator.h b/src/nb/fixed_no_free_allocator.h index 696a7c0..31bfc60 100644 --- a/src/nb/fixed_no_free_allocator.h +++ b/src/nb/fixed_no_free_allocator.h
@@ -37,22 +37,23 @@ class FixedNoFreeAllocator : public Allocator { public: FixedNoFreeAllocator(void* memory_start, std::size_t memory_size); - void* Allocate(std::size_t size) { return Allocate(size, 1, true); } + void* Allocate(std::size_t size) { return Allocate(&size, 1, true); } void* Allocate(std::size_t size, std::size_t alignment) { - return Allocate(size, alignment, true); + return Allocate(&size, alignment, true); } - void* AllocateForAlignment(std::size_t size, std::size_t alignment) { + void* AllocateForAlignment(std::size_t* size, std::size_t alignment) { return Allocate(size, alignment, false); } - void* Allocate(std::size_t size, std::size_t alignment, bool align_pointer); void Free(void* memory); std::size_t GetCapacity() const; std::size_t GetAllocated() const; void PrintAllocations() const; private: + void* Allocate(std::size_t* size, std::size_t alignment, bool align_pointer); + // The start of our memory range, as passed in to the constructor. void* const memory_start_;
diff --git a/src/nb/memory_pool.cc b/src/nb/memory_pool.cc index 840042c..4ae9a7e 100644 --- a/src/nb/memory_pool.cc +++ b/src/nb/memory_pool.cc
@@ -23,15 +23,21 @@ MemoryPool::MemoryPool(void* buffer, std::size_t size, bool thread_safe, - bool verify_full_capacity) + bool verify_full_capacity, + std::size_t small_allocation_threshold) : no_free_allocator_(buffer, size), reuse_allocator_( - scoped_ptr<Allocator>(new ReuseAllocator(&no_free_allocator_)), + scoped_ptr<Allocator>(new ReuseAllocator(&no_free_allocator_, + size, + small_allocation_threshold)), thread_safe) { SB_DCHECK(buffer); SB_DCHECK(size != 0U); - if (verify_full_capacity) { + // This is redundant if ReuseAllocator::Allcator() can allocate the difference + // between the requested size and the last free block from the fallback + // allocator and combine the blocks. + if (verify_full_capacity && small_allocation_threshold == 0) { void* p = Allocate(size); SB_DCHECK(p); Free(p);
diff --git a/src/nb/memory_pool.h b/src/nb/memory_pool.h index cef03db..b81e893 100644 --- a/src/nb/memory_pool.h +++ b/src/nb/memory_pool.h
@@ -29,30 +29,16 @@ // as necessary. class MemoryPool : public Allocator { public: - // When |verify_full_capacity| is true, the ctor tries to allocate the whole - // budget and free it immediately. This can: - // 1. Ensure the |size| is accurate after accounting for all implicit - // alignment enforced by the underlying allocators. - // 2. The |reuse_allocator_| contains a free block of the whole budget. As - // the |reuse_allocator_| doesn't support extending of free block, an - // allocation that is larger than the both biggest free block in the - // |reuse_allocator_| and the remaining memory inside the - // |no_free_allocator_| will fail even if the combination of both can - // fulfill the allocation. - // Note that when |verify_full_capacity| is true, GetHighWaterMark() always - // return the budget, which makes memory usage tracking useless. MemoryPool(void* buffer, std::size_t size, bool thread_safe, - bool verify_full_capacity = false); + bool verify_full_capacity = false, + std::size_t small_allocation_threshold = 0); void* Allocate(std::size_t size) { return reuse_allocator_.Allocate(size); } void* Allocate(std::size_t size, std::size_t alignment) { return reuse_allocator_.Allocate(size, alignment); } - void* AllocateForAlignment(std::size_t size, std::size_t alignment) { - return reuse_allocator_.AllocateForAlignment(size, alignment); - } void Free(void* memory) { reuse_allocator_.Free(memory); } std::size_t GetCapacity() const { return reuse_allocator_.GetCapacity(); } std::size_t GetAllocated() const { return reuse_allocator_.GetAllocated(); }
diff --git a/src/nb/pointer_arithmetic.h b/src/nb/pointer_arithmetic.h index 411308c..cb1539a 100644 --- a/src/nb/pointer_arithmetic.h +++ b/src/nb/pointer_arithmetic.h
@@ -31,7 +31,7 @@ return reinterpret_cast<uint8_t*>(integer_value); } -// Helper method for subclasses to align addresses up to a specified value. +// Helper method to align addresses up to a specified value. // Returns the the smallest value that is greater than or equal to value, but // aligned to alignment. template <typename T> @@ -42,9 +42,20 @@ template <typename T> T* AlignUp(T* value, uintptr_t alignment) { - uintptr_t decremented_value = AsInteger(value) - 1; - return reinterpret_cast<T*>(decremented_value + alignment - - (decremented_value % alignment)); + return reinterpret_cast<T*>(AlignUp(AsInteger(value), alignment)); +} + +// Helper method to align addresses down to a specified value. +// Returns the the largest value that is less than or equal to value, but +// aligned to alignment. +template <typename T> +T AlignDown(T value, T alignment) { + return value / alignment * alignment; +} + +template <typename T> +T* AlignDown(T* value, uintptr_t alignment) { + return reinterpret_cast<T*>(AlignDown(AsInteger(value), alignment)); } // Helper method for subclasses to determine if a given address or value
diff --git a/src/nb/reuse_allocator.cc b/src/nb/reuse_allocator.cc index 61a40a6..70898ae 100644 --- a/src/nb/reuse_allocator.cc +++ b/src/nb/reuse_allocator.cc
@@ -24,10 +24,104 @@ namespace nb { -ReuseAllocator::ReuseAllocator(Allocator* fallback_allocator) { - fallback_allocator_ = fallback_allocator; - capacity_ = 0; - total_allocated_ = 0; +// Minimum block size to avoid extremely small blocks inside the block list and +// to ensure that a zero sized allocation will return a non-zero sized block. +const std::size_t kMinBlockSizeBytes = 16; + +bool ReuseAllocator::MemoryBlock::Merge(const MemoryBlock& other) { + if (AsInteger(address_) + size_ == AsInteger(other.address_)) { + size_ += other.size_; + return true; + } + if (AsInteger(other.address_) + other.size_ == AsInteger(address_)) { + address_ = other.address_; + size_ += other.size_; + return true; + } + return false; +} + +bool ReuseAllocator::MemoryBlock::CanFullfill(std::size_t request_size, + std::size_t alignment) const { + const std::size_t extra_bytes_for_alignment = + AlignUp(AsInteger(address_), alignment) - AsInteger(address_); + const std::size_t aligned_size = request_size + extra_bytes_for_alignment; + return size_ >= aligned_size; +} + +void ReuseAllocator::MemoryBlock::Allocate(std::size_t request_size, + std::size_t alignment, + bool allocate_from_front, + MemoryBlock* allocated, + MemoryBlock* free) const { + SB_DCHECK(allocated); + SB_DCHECK(free); + SB_DCHECK(CanFullfill(request_size, alignment)); + + // First we assume that the block is just enough to fulfill the allocation and + // leaves no free block. + allocated->address_ = address_; + allocated->size_ = size_; + free->address_ = NULL; + free->size_ = 0; + + if (allocate_from_front) { + // |address_| + // | <- allocated_size -> | <- remaining_size -> | + // ------------------------------------------------------- + // | <- request_size -> | | + // |aligned_address| |end_of_allocation| |address_ + size_| + std::size_t aligned_address = AlignUp(AsInteger(address_), alignment); + std::size_t end_of_allocation = aligned_address + request_size; + std::size_t allocated_size = end_of_allocation - AsInteger(address_); + std::size_t remaining_size = size_ - allocated_size; + if (remaining_size < kMinBlockSizeBytes) { + return; + } + allocated->size_ = allocated_size; + free->address_ = AsPointer(end_of_allocation); + free->size_ = remaining_size; + } else { + // |address_| + // | <- remaining_size -> | <- allocated_size -> | + // ------------------------------------------------------- + // | <- request_size -> | | + // |aligned_address| |address_ + size_| + std::size_t aligned_address = + AlignDown(AsInteger(address_) + size_ - request_size, alignment); + std::size_t allocated_size = AsInteger(address_) + size_ - aligned_address; + std::size_t remaining_size = size_ - allocated_size; + if (remaining_size < kMinBlockSizeBytes) { + return; + } + allocated->address_ = AsPointer(aligned_address); + allocated->size_ = allocated_size; + free->address_ = address_; + free->size_ = remaining_size; + } +} + +ReuseAllocator::ReuseAllocator(Allocator* fallback_allocator) + : fallback_allocator_(fallback_allocator), + small_allocation_threshold_(0), + capacity_(0), + total_allocated_(0) {} + +ReuseAllocator::ReuseAllocator(Allocator* fallback_allocator, + std::size_t capacity, + std::size_t small_allocation_threshold) + : fallback_allocator_(fallback_allocator), + small_allocation_threshold_(small_allocation_threshold), + capacity_(0), + total_allocated_(0) { + // If |small_allocation_threshold_| is non-zero, this class will use last-fit + // strategy to fulfill small allocations. Pre-allocator full capacity so + // last-fit makes sense. + if (small_allocation_threshold_ > 0) { + void* p = Allocate(capacity, 1); + SB_DCHECK(p); + Free(p); + } } ReuseAllocator::~ReuseAllocator() { @@ -44,18 +138,14 @@ } } -void ReuseAllocator::AddFreeBlock(void* address, std::size_t size) { - MemoryBlock new_block; - new_block.address = address; - new_block.size = size; - +ReuseAllocator::FreeBlockSet::iterator ReuseAllocator::AddFreeBlock( + MemoryBlock block_to_add) { if (free_blocks_.size() == 0) { - free_blocks_.insert(new_block); - return; + return free_blocks_.insert(block_to_add).first; } // See if we can merge this block with one on the right or left. - FreeBlockSet::iterator it = free_blocks_.lower_bound(new_block); + FreeBlockSet::iterator it = free_blocks_.lower_bound(block_to_add); // lower_bound will return an iterator to our neighbor on the right, // if one exists. FreeBlockSet::iterator right_to_erase = free_blocks_.end(); @@ -63,9 +153,7 @@ if (it != free_blocks_.end()) { MemoryBlock right_block = *it; - if (AsInteger(new_block.address) + new_block.size == - AsInteger(right_block.address)) { - new_block.size += right_block.size; + if (block_to_add.Merge(right_block)) { right_to_erase = it; } } @@ -75,10 +163,7 @@ it--; MemoryBlock left_block = *it; // Are we contiguous with the block to our left? - if (AsInteger(left_block.address) + left_block.size == - AsInteger(new_block.address)) { - new_block.address = left_block.address; - new_block.size += left_block.size; + if (block_to_add.Merge(left_block)) { left_to_erase = it; } } @@ -90,7 +175,7 @@ free_blocks_.erase(left_to_erase); } - free_blocks_.insert(new_block); + return free_blocks_.insert(block_to_add).first; } void ReuseAllocator::RemoveFreeBlock(FreeBlockSet::iterator it) { @@ -101,11 +186,6 @@ return Allocate(size, 1); } -void* ReuseAllocator::AllocateForAlignment(std::size_t size, - std::size_t alignment) { - return Allocate(size, alignment); -} - void* ReuseAllocator::Allocate(std::size_t size, std::size_t alignment) { if (alignment == 0) { alignment = 1; @@ -113,15 +193,14 @@ // Try to satisfy request from free list. // First look for a block that is appropriately aligned. - // If we can't, look for a block that is big enough that we can - // carve out an aligned block. + // If we can't, look for a block that is big enough that we can carve out an + // aligned block. // If there is no such block, allocate more from our fallback allocator. void* user_address = 0; - // Keeping things rounded and aligned will help us - // avoid creating tiny and/or badly misaligned free blocks. - // Also ensure even for a 0-byte request we return a unique block. - const std::size_t kMinBlockSizeBytes = 16; + // Keeping things rounded and aligned will help us avoid creating tiny and/or + // badly misaligned free blocks. Also ensure even for a 0-byte request we + // return a unique block. const std::size_t kMinAlignment = 16; size = std::max(size, kMinBlockSizeBytes); size = AlignUp(size, kMinBlockSizeBytes); @@ -130,68 +209,59 @@ // Worst case how much memory we need. MemoryBlock allocated_block; - // Start looking through the free list. - // If this is slow, we can store another map sorted by size. - for (FreeBlockSet::iterator it = free_blocks_.begin(); - it != free_blocks_.end(); ++it) { - MemoryBlock block = *it; - const std::size_t extra_bytes_for_alignment = - (alignment - AsInteger(block.address) % alignment) % alignment; - const std::size_t aligned_size = size + extra_bytes_for_alignment; - if (block.size >= aligned_size) { - // The block is big enough. We may waste some space due to alignment. - RemoveFreeBlock(it); - const std::size_t remaining_bytes = block.size - aligned_size; - if (remaining_bytes >= kMinBlockSizeBytes) { - AddFreeBlock(AsPointer(AsInteger(block.address) + aligned_size), - remaining_bytes); - allocated_block.size = aligned_size; - } else { - allocated_block.size = block.size; + bool scan_from_front = size > small_allocation_threshold_; + FreeBlockSet::iterator free_block_iter = free_blocks_.end(); + + if (scan_from_front) { + // Start looking through the free list from the front. + for (FreeBlockSet::iterator it = free_blocks_.begin(); + it != free_blocks_.end(); ++it) { + if (it->CanFullfill(size, alignment)) { + free_block_iter = it; + break; } - user_address = AlignUp(block.address, alignment); - allocated_block.address = block.address; - SB_DCHECK(allocated_block.size <= block.size); - break; + } + } else { + // Start looking through the free list from the back. + for (FreeBlockSet::reverse_iterator it = free_blocks_.rbegin(); + it != free_blocks_.rend(); ++it) { + if (it->CanFullfill(size, alignment)) { + free_block_iter = it.base(); + --free_block_iter; + break; + } } } - if (user_address == 0) { - // No free blocks found. - // Allocate one from the fallback allocator. - size = AlignUp(size, alignment); - void* ptr = fallback_allocator_->AllocateForAlignment(size, alignment); + if (free_block_iter == free_blocks_.end()) { + // No free blocks found, allocate one from the fallback allocator. + std::size_t block_size = size; + void* ptr = + fallback_allocator_->AllocateForAlignment(&block_size, alignment); if (ptr == NULL) { return NULL; } - uint8_t* memory_address = reinterpret_cast<uint8_t*>(ptr); - user_address = AlignUp(memory_address, alignment); - allocated_block.size = size; - allocated_block.address = user_address; - - if (memory_address != user_address) { - std::size_t alignment_padding_size = - AsInteger(user_address) - AsInteger(memory_address); - if (alignment_padding_size >= kMinBlockSizeBytes) { - // Register the memory range skipped for alignment as a free block for - // later use. - AddFreeBlock(memory_address, alignment_padding_size); - capacity_ += alignment_padding_size; - } else { - // The memory range skipped for alignment is too small for a free block. - // Adjust the allocated block to include the alignment padding. - allocated_block.size += alignment_padding_size; - allocated_block.address = AsPointer(AsInteger(allocated_block.address) - - alignment_padding_size); - } - } - - capacity_ += allocated_block.size; + free_block_iter = AddFreeBlock(MemoryBlock(ptr, block_size)); + capacity_ += block_size; fallback_allocations_.push_back(ptr); } + + MemoryBlock block = *free_block_iter; + // The block is big enough. We may waste some space due to alignment. + RemoveFreeBlock(free_block_iter); + + MemoryBlock free_block; + block.Allocate(size, alignment, scan_from_front, &allocated_block, + &free_block); + if (free_block.size() > 0) { + SB_DCHECK(free_block.address()); + AddFreeBlock(free_block); + } + user_address = AlignUp(allocated_block.address(), alignment); + SB_DCHECK(allocated_blocks_.find(user_address) == allocated_blocks_.end()); allocated_blocks_[user_address] = allocated_block; - total_allocated_ += allocated_block.size; + total_allocated_ += allocated_block.size(); return user_address; } @@ -205,10 +275,10 @@ // Mark this block as free and remove it from the allocated set. const MemoryBlock& block = (*it).second; - AddFreeBlock(block.address, block.size); + AddFreeBlock(block); - SB_DCHECK(block.size <= total_allocated_); - total_allocated_ -= block.size; + SB_DCHECK(block.size() <= total_allocated_); + total_allocated_ -= block.size(); allocated_blocks_.erase(it); } @@ -218,7 +288,7 @@ SizesHistogram sizes_histogram; for (AllocatedBlockMap::const_iterator iter = allocated_blocks_.begin(); iter != allocated_blocks_.end(); ++iter) { - std::size_t block_size = iter->second.size; + std::size_t block_size = iter->second.size(); if (sizes_histogram.find(block_size) == sizes_histogram.end()) { sizes_histogram[block_size] = 0; }
diff --git a/src/nb/reuse_allocator.h b/src/nb/reuse_allocator.h index 6f4f16a..7686930 100644 --- a/src/nb/reuse_allocator.h +++ b/src/nb/reuse_allocator.h
@@ -30,16 +30,32 @@ // maintaining all allocation meta data is outside of the allocated memory. // It is passed a fallback allocator that it can request additional memory // from as needed. +// The default allocation strategy for the allocator is first-fit, i.e. it will +// scan for free blocks sorted by addresses and allocate from the first free +// block that can fulfill the allocation. However, in some situations the +// majority of the allocations can be small ones with some large allocations. +// This may cause serious fragmentations and the failure of large allocations. +// If |small_allocation_threshold| in the ctor is set to a non-zero value, the +// class will allocate small allocations whose sizes are less than or equal to +// the threshold using last-fit, i.e. it will scan from the back to the front +// for free blocks. This way the allocation for large blocks and small blocks +// are separated thus cause much less fragmentations. class ReuseAllocator : public Allocator { public: explicit ReuseAllocator(Allocator* fallback_allocator); + // When |small_allocation_threshold| is non-zero, this class will allocate + // its full capacity from the |fallback_allocator| in the ctor so it is + // possible for the class to use the last-fit allocation strategy. See the + // class comment above for more details. + ReuseAllocator(Allocator* fallback_allocator, + std::size_t capacity, + std::size_t small_allocation_threshold); virtual ~ReuseAllocator(); // Search free memory blocks for an existing one, and if none are large // enough, allocate a new one from no-free memory and return that. void* Allocate(std::size_t size); void* Allocate(std::size_t size, std::size_t alignment); - void* AllocateForAlignment(std::size_t size, std::size_t alignment); // Marks the memory block as being free and it will then become recyclable void Free(void* memory); @@ -50,29 +66,67 @@ void PrintAllocations() const; private: - // We will allocate from the given allocator whenever we can't find - // pre-used memory to allocate. - Allocator* fallback_allocator_; + class MemoryBlock { + public: + MemoryBlock() : address_(0), size_(0) {} + MemoryBlock(void* address, std::size_t size) + : address_(address), size_(size) {} - struct MemoryBlock { - void* address; - std::size_t size; + void* address() const { return address_; } + std::size_t size() const { return size_; } + + void set_address(void* address) { address_ = address; } + void set_size(std::size_t size) { size_ = size; } + bool operator<(const MemoryBlock& other) const { - return address < other.address; + return address_ < other.address_; } + // If the current block and |other| can be combined into a continuous memory + // block, store the conmbined block in the current block and return true. + // Otherwise return false. + bool Merge(const MemoryBlock& other); + // Return true if the current block can be used to fulfill an allocation + // with the given size and alignment. + bool CanFullfill(std::size_t request_size, std::size_t alignment) const; + // Allocate a block from this block with the given size and alignment. + // Store the allocated block in |allocated|. If the rest space is large + // enough to form a block, it will be stored into |free|. Otherwise the + // whole block is stored into |allocated|. + // Note that the call of this function has to ensure that CanFulfill() is + // already called on this block and returns true. + void Allocate(std::size_t request_size, + std::size_t alignment, + bool allocate_from_front, + MemoryBlock* allocated, + MemoryBlock* free) const; + + private: + void* address_; + std::size_t size_; }; + // Freelist sorted by address. typedef std::set<MemoryBlock> FreeBlockSet; // Map from pointers we returned to the user, back to memory blocks. typedef std::map<void*, MemoryBlock> AllocatedBlockMap; - void AddFreeBlock(void* address, std::size_t size); - void RemoveFreeBlock(FreeBlockSet::iterator); + + FreeBlockSet::iterator AddFreeBlock(MemoryBlock block_to_add); + void RemoveFreeBlock(FreeBlockSet::iterator it); FreeBlockSet free_blocks_; AllocatedBlockMap allocated_blocks_; - // A list of allocations made from the fallback allocator. We keep track - // of this so that we can free them all upon our destruction. + // We will allocate from the given allocator whenever we can't find pre-used + // memory to allocate. + Allocator* fallback_allocator_; + + // Any allocations with size less than or equal to the following threshold + // will be allocated from the back of the pool. See the comment of the class + // for more details. + std::size_t small_allocation_threshold_; + + // A list of allocations made from the fallback allocator. We keep track of + // this so that we can free them all upon our destruction. std::vector<void*> fallback_allocations_; // How much we have allocated from the fallback allocator.
diff --git a/src/nb/reuse_allocator_benchmark.cc b/src/nb/reuse_allocator_benchmark.cc index 4117d5c..5e48ba7 100644 --- a/src/nb/reuse_allocator_benchmark.cc +++ b/src/nb/reuse_allocator_benchmark.cc
@@ -177,17 +177,14 @@ class DefaultAllocator : public nb::Allocator { public: - void* Allocate(std::size_t size) { return Allocate(size, 0); } - void* Allocate(std::size_t size, std::size_t alignment) { + void* Allocate(std::size_t size) SB_OVERRIDE { return Allocate(size, 0); } + void* Allocate(std::size_t size, std::size_t alignment) SB_OVERRIDE { return SbMemoryAllocateAligned(alignment, size); } - void* AllocateForAlignment(std::size_t size, std::size_t alignment) { - return SbMemoryAllocateAligned(alignment, size); - } - void Free(void* memory) { SbMemoryFree(memory); } - std::size_t GetCapacity() const { return 0; } - std::size_t GetAllocated() const { return 0; } - void PrintAllocations() const {} + void Free(void* memory) SB_OVERRIDE { SbMemoryFree(memory); } + std::size_t GetCapacity() const SB_OVERRIDE { return 0; } + std::size_t GetAllocated() const SB_OVERRIDE { return 0; } + void PrintAllocations() const SB_OVERRIDE {} }; void MemoryPlaybackTest(const std::string& filename) {
diff --git a/src/nb/reuse_allocator_test.cc b/src/nb/reuse_allocator_test.cc index 658c81a..4d42361 100644 --- a/src/nb/reuse_allocator_test.cc +++ b/src/nb/reuse_allocator_test.cc
@@ -18,6 +18,7 @@ #include "nb/fixed_no_free_allocator.h" #include "nb/scoped_ptr.h" +#include "starboard/configuration.h" #include "starboard/types.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,14 +33,21 @@ public: static const int kBufferSize = 1 * 1024 * 1024; - ReuseAllocatorTest() { + ReuseAllocatorTest() { ResetAllocator(0); } + + protected: + void ResetAllocator(size_t small_allocation_threshold) { buffer_.reset(new uint8_t[kBufferSize]); fallback_allocator_.reset( new nb::FixedNoFreeAllocator(buffer_.get(), kBufferSize)); - allocator_.reset(new nb::ReuseAllocator(fallback_allocator_.get())); + if (small_allocation_threshold == 0) { + allocator_.reset(new nb::ReuseAllocator(fallback_allocator_.get())); + } else { + allocator_.reset(new nb::ReuseAllocator( + fallback_allocator_.get(), kBufferSize, small_allocation_threshold)); + } } - protected: nb::scoped_array<uint8_t> buffer_; nb::scoped_ptr<nb::FixedNoFreeAllocator> fallback_allocator_; nb::scoped_ptr<nb::ReuseAllocator> allocator_; @@ -99,3 +107,32 @@ allocator_->Free(test_p); allocator_->Free(blocks[0]); } + +TEST_F(ReuseAllocatorTest, SmallAlloc) { + // Recreate allocator with small allocation threshold to 256. + ResetAllocator(256); + + const std::size_t kBlockSizes[] = {117, 193, 509, 1111}; + const std::size_t kAlignment = 16; + void* blocks[] = {NULL, NULL, NULL, NULL}; + for (int i = 0; i < SB_ARRAY_SIZE(kBlockSizes); ++i) { + blocks[i] = allocator_->Allocate(kBlockSizes[i], kAlignment); + } + // The two small allocs should be in the back in reverse order. + EXPECT_GT(reinterpret_cast<uintptr_t>(blocks[0]), + reinterpret_cast<uintptr_t>(blocks[1])); + // Small allocs should has higher address than other allocs. + EXPECT_GT(reinterpret_cast<uintptr_t>(blocks[1]), + reinterpret_cast<uintptr_t>(blocks[3])); + // Non-small allocs are allocated from the front and the first one has the + // lowest address. + EXPECT_LT(reinterpret_cast<uintptr_t>(blocks[2]), + reinterpret_cast<uintptr_t>(blocks[3])); + for (int i = 0; i < SB_ARRAY_SIZE(kBlockSizes); ++i) { + allocator_->Free(blocks[i]); + } + // Should have one single free block equals to the capacity. + void* test_p = allocator_->Allocate(allocator_->GetCapacity()); + EXPECT_TRUE(test_p != NULL); + allocator_->Free(test_p); +}
diff --git a/src/starboard/event.h b/src/starboard/event.h index c602259..cec1884 100644 --- a/src/starboard/event.h +++ b/src/starboard/event.h
@@ -26,6 +26,43 @@ extern "C" { #endif +// The Starboard Application life cycle +// ------------------------------------ +// +// * +// | _________________________ +// Start | | +// | | Resume +// V V | +// [ STARTED ] --Pause--> [ PAUSED ] --Suspend--> [ SUSPENDED ] +// ^ | | +// | Unpause Stop +// |_____________________| | +// V +// [ STOPPED ] +// +// The first event that a Starboard application will receive is Start +// (kSbEventTypeStart). This puts the application in the STARTED state; it is in +// the foreground and can expect to do all the normal things it might want to +// do. Once in the STARTED state, it may receive a Pause event, putting the +// application into the PAUSED state. +// +// In the PAUSED state, the application is still visible, but has lost focus, or +// it is partially obscured by a modal dialog, or it is on its way to being shut +// down. The application should pause activity in this state. In this state, it +// can receive Unpause to be brought back to the foreground state, STARTED, or +// Suspend to be pushed further in the background to the SUSPENDED state. +// +// In the SUSPENDED state, the application is generally not visible. It should +// immediately release all graphics and video resources, and shut down all +// background activity (timers, rendering, etc). Additionally, the application +// should flush storage to ensure that if the application is killed, the storage +// will be up-to-date. The application may be killed at this point, but will +// ideally receive a Stop event for a more graceful shutdown. +// +// Note that the application is always expected to transition through PAUSED to +// SUSPENDED before receiving Stop or being killed. + // An enumeration of all possible event types dispatched directly by the // system. Each event is accompanied by a void* data argument, and each event // must define the type of the value pointed to by that data argument, if any. @@ -33,28 +70,43 @@ // The first event that an application receives on startup. Applications // should perform initialization and prepare to react to subsequent events. // Applications that wish to run and then exit must call SbSystemRequestStop() - // to terminate. SbEventStartData is passed as the data argument. + // to terminate. This event will only be sent once for a given process launch. + // SbEventStartData is passed as the data argument. kSbEventTypeStart, - // The operating system will put the application into a suspended state after - // this event is handled. This is an opportunity for the application to - // partially tear down and release some resources. Some platforms will - // terminate the application if work is done while suspended. Can only be + // A dialog will be raised or the application will otherwise be put into a + // background-but-visible or partially-obscured state (PAUSED). Graphics and + // video resources will still be available, but the application should pause + // foreground activity like animations and video playback. Can only be // received after a Start event. The only events that should be dispatched - // after a Suspend event are Resume or Stop. No data argument. + // after a Pause event are Unpause or Suspend. No data argument. + kSbEventTypePause, + + // The application is returning to the foreground (STARTED) after having been + // put in the PAUSED (e.g. partially-obscured) state. The application should + // unpause foreground activity like animations and video playback. Can only be + // received after a Pause or Resume event. No data argument. + kSbEventTypeUnpause, + + // The operating system will put the application into a Suspended state after + // this event is handled. The application is expected to stop periodic + // background work, release ALL graphics and video resources, and flush any + // pending SbStorage writes. Some platforms will terminate the application if + // work is done or resources are retained after suspension. Can only be + // received after a Pause event. The only events that should be dispatched + // after a Suspend event are Resume or Stop. On some platforms, the process + // may also be killed after Suspend without a Stop event. No data argument. kSbEventTypeSuspend, - // The operating system has restored the application to normal execution after - // a Pause event. This is the first even the application will receive coming - // out of Pause, and it will only be received immediately after a Pause event. - // No data argument. + // The operating system has restored the application to the PAUSED state from + // the SUSPENDED state. This is the first event the application will receive + // coming out of SUSPENDED, and it will only be received after a Suspend + // event. The application will now be in the PAUSED state. No data argument. kSbEventTypeResume, // The operating system will shut the application down entirely after this - // event is handled. This is an opportunity for the application to save any - // state that it wishes to before its process space is revoked. Can only be - // recieved after a Start event. May be received after a Pause event. No data - // argument. + // event is handled. Can only be recieved after a Suspend event, in the + // SUSPENDED state. No data argument. kSbEventTypeStop, // A user input event, including keyboard, mouse, gesture, or something else.
diff --git a/src/starboard/linux/x64directfb/main.cc b/src/starboard/linux/x64directfb/main.cc index f6d023a..2a7616c 100644 --- a/src/starboard/linux/x64directfb/main.cc +++ b/src/starboard/linux/x64directfb/main.cc
@@ -17,11 +17,15 @@ #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/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp index 25c0476..cca05bb 100644 --- a/src/starboard/linux/x64directfb/starboard_platform.gyp +++ b/src/starboard/linux/x64directfb/starboard_platform.gyp
@@ -236,6 +236,8 @@ '<(DEPTH)/starboard/shared/pthread/thread_yield.cc', '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc', '<(DEPTH)/starboard/shared/signal/crash_signals.h', + '<(DEPTH)/starboard/shared/signal/suspend_signals.cc', + '<(DEPTH)/starboard/shared/signal/suspend_signals.h', '<(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',
diff --git a/src/starboard/linux/x64x11/main.cc b/src/starboard/linux/x64x11/main.cc index 1331c05..7feb245 100644 --- a/src/starboard/linux/x64x11/main.cc +++ b/src/starboard/linux/x64x11/main.cc
@@ -16,12 +16,16 @@ #include "starboard/configuration.h" #include "starboard/shared/signal/crash_signals.h" +#include "starboard/shared/signal/suspend_signals.h" #include "starboard/shared/x11/application_x11.h" int main(int argc, char** argv) { tzset(); starboard::shared::signal::InstallCrashSignalHandlers(); + starboard::shared::signal::InstallSuspendSignalHandlers(); starboard::shared::x11::ApplicationX11 application; int result = application.Run(argc, argv); + starboard::shared::signal::UninstallSuspendSignalHandlers(); + starboard::shared::signal::UninstallCrashSignalHandlers(); return result; }
diff --git a/src/starboard/linux/x64x11/starboard_platform.gyp b/src/starboard/linux/x64x11/starboard_platform.gyp index 65712a4..6276a96 100644 --- a/src/starboard/linux/x64x11/starboard_platform.gyp +++ b/src/starboard/linux/x64x11/starboard_platform.gyp
@@ -199,6 +199,8 @@ '<(DEPTH)/starboard/shared/pthread/thread_yield.cc', '<(DEPTH)/starboard/shared/signal/crash_signals.h', '<(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/starboard/application.cc', '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc', '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc',
diff --git a/src/starboard/nplb/memory_set_test.cc b/src/starboard/nplb/memory_set_test.cc index 2a647b4..0874104 100644 --- a/src/starboard/nplb/memory_set_test.cc +++ b/src/starboard/nplb/memory_set_test.cc
@@ -31,7 +31,7 @@ void* result = SbMemorySet(memory, 0xCD, kSize); EXPECT_EQ(memory, result); for (int i = 0; i < kSize; ++i) { - EXPECT_EQ(data[i], '\xCD'); + ASSERT_EQ('\xCD', data[i]); } SbMemoryFree(memory); @@ -47,7 +47,7 @@ void* result = SbMemorySet(memory, 0xCD, 0); EXPECT_EQ(memory, result); for (int i = 0; i < kSize; ++i) { - EXPECT_EQ(data[i], static_cast<char>(i)); + ASSERT_EQ(static_cast<char>(i), data[i]); } SbMemoryFree(memory); @@ -63,7 +63,7 @@ void* result = SbMemorySet(memory, 0x6789ABCD, kSize); EXPECT_EQ(memory, result); for (int i = 0; i < kSize; ++i) { - EXPECT_EQ(data[i], '\xCD'); + ASSERT_EQ('\xCD', data[i]); } SbMemoryFree(memory);
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc index 52c348b..de94895 100644 --- a/src/starboard/nplb/system_get_property_test.cc +++ b/src/starboard/nplb/system_get_property_test.cc
@@ -74,7 +74,7 @@ if (IsCEDevice(SbSystemGetDeviceType())) { BasicTest(kSbSystemPropertyBrandName, true, true, __LINE__); BasicTest(kSbSystemPropertyModelName, true, true, __LINE__); - BasicTest(kSbSystemPropertyModelYear, true, true, __LINE__); + BasicTest(kSbSystemPropertyModelYear, false, true, __LINE__); } else { BasicTest(kSbSystemPropertyBrandName, false, true, __LINE__); BasicTest(kSbSystemPropertyModelName, false, true, __LINE__);
diff --git a/src/starboard/nplb/thread_yield_test.cc b/src/starboard/nplb/thread_yield_test.cc index c6a07d1..17a4ed5 100644 --- a/src/starboard/nplb/thread_yield_test.cc +++ b/src/starboard/nplb/thread_yield_test.cc
@@ -65,11 +65,11 @@ // thread gets started first, I hope to make this inherently flaky test not // flaky. // -// Note: This test ended up EVER so slightly flaky, but within most -// tolerances. If it fails on you randomly and inconsistently, it was probably -// just a flake. -TEST(SbThreadYieldTest, FLAKY_SunnyDayRace) { - const int kTrials = 30; +// Note: This test may still be flaky, but it should be a lot less flaky than +// before. If this test starts flaking again, tag it with FLAKY_ again. +TEST(SbThreadYieldTest, SunnyDayRace) { + const int kTrials = 20; + int passes = 0; for (int trial = 0; trial < kTrials; ++trial) { // Pin to CPU 0 to make sure the threads don't get distributed onto other // cores. @@ -106,8 +106,15 @@ } } - EXPECT_LT(average_unyielder, average_yielder) << "Trial " << trial; + // If unyielders took less time then yielders, on average, then we consider + // the trial a pass. + if (average_unyielder < average_yielder) { + ++passes; + } } + + // We expect at least 2/3 of the trials to pass. + EXPECT_LT(kTrials * 2 / 3, passes); } } // namespace
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp index d5b6b23..f22110b 100644 --- a/src/starboard/raspi/1/starboard_platform.gyp +++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -206,6 +206,8 @@ '<(DEPTH)/starboard/shared/pthread/thread_yield.cc', '<(DEPTH)/starboard/shared/signal/crash_signals.cc', '<(DEPTH)/starboard/shared/signal/crash_signals.h', + '<(DEPTH)/starboard/shared/signal/suspend_signals.cc', + '<(DEPTH)/starboard/shared/signal/suspend_signals.h', '<(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',
diff --git a/src/starboard/raspi/shared/main.cc b/src/starboard/raspi/shared/main.cc index 1745d23..737c678 100644 --- a/src/starboard/raspi/shared/main.cc +++ b/src/starboard/raspi/shared/main.cc
@@ -17,11 +17,15 @@ #include "starboard/configuration.h" #include "starboard/raspi/shared/application_dispmanx.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::raspi::shared::ApplicationDispmanx application; int result = application.Run(argc, argv); + starboard::shared::signal::UninstallSuspendSignalHandlers(); + starboard::shared::signal::UninstallCrashSignalHandlers(); return result; }
diff --git a/src/starboard/shared/signal/crash_signals.cc b/src/starboard/shared/signal/crash_signals.cc index 5c20870..a3e9b2e 100644 --- a/src/starboard/shared/signal/crash_signals.cc +++ b/src/starboard/shared/signal/crash_signals.cc
@@ -18,6 +18,7 @@ #include "starboard/configuration.h" #include "starboard/log.h" +#include "starboard/shared/signal/signal_internal.h" #include "starboard/system.h" namespace starboard { @@ -26,48 +27,44 @@ namespace { -const int kSignalsToTrap[] = { - SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, +const int kCrashSignalsToTrap[] = { + SIGABRT, SIGFPE, SIGILL, SIGSEGV, }; -const char* GetSignalName(int signal_id) { - switch (signal_id) { - case SIGABRT: - return "SIGABRT"; - case SIGFPE: - return "SIGFPE"; - case SIGILL: - return "SIGILL"; - case SIGINT: - return "SIGINT"; - case SIGSEGV: - return "SIGSEGV"; - default: - return "UNKNOWN SIGNAL"; - } -} +const int kStopSignalsToTrap[] = { + SIGTERM, SIGINT, +}; void DumpStackSignalSafe(int signal_id) { - const char* signal_name = GetSignalName(signal_id); - SbLogRawFormatF("\nCaught signal: %s (%d)\n", signal_name, signal_id); - SbLogFlush(); + LogSignalCaught(signal_id); SbLogRawDumpStack(1); UninstallCrashSignalHandlers(); SbSystemBreakIntoDebugger(); } +void Stop(int signal_id) { + LogSignalCaught(signal_id); + SbSystemRequestStop(0); +} + } // namespace void InstallCrashSignalHandlers() { - for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) { - ::signal(kSignalsToTrap[i], &DumpStackSignalSafe); + for (int i = 0; i < SB_ARRAY_SIZE_INT(kCrashSignalsToTrap); ++i) { + ::signal(kCrashSignalsToTrap[i], &DumpStackSignalSafe); + } + for (int i = 0; i < SB_ARRAY_SIZE_INT(kStopSignalsToTrap); ++i) { + ::signal(kStopSignalsToTrap[i], &Stop); } } void UninstallCrashSignalHandlers() { - for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) { - ::signal(kSignalsToTrap[i], SIG_DFL); + for (int i = 0; i < SB_ARRAY_SIZE_INT(kCrashSignalsToTrap); ++i) { + ::signal(kCrashSignalsToTrap[i], SIG_DFL); + } + for (int i = 0; i < SB_ARRAY_SIZE_INT(kStopSignalsToTrap); ++i) { + ::signal(kStopSignalsToTrap[i], SIG_DFL); } }
diff --git a/src/starboard/shared/signal/crash_signals_sigaction.cc b/src/starboard/shared/signal/crash_signals_sigaction.cc index 735e506..4bf5b59 100644 --- a/src/starboard/shared/signal/crash_signals_sigaction.cc +++ b/src/starboard/shared/signal/crash_signals_sigaction.cc
@@ -18,7 +18,7 @@ #include "starboard/configuration.h" #include "starboard/log.h" -#include "starboard/memory.h" +#include "starboard/shared/signal/signal_internal.h" #include "starboard/system.h" namespace starboard { @@ -27,42 +27,26 @@ namespace { -const int kSignalsToTrap[] = { - SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, +const int kCrashSignalsToTrap[] = { + SIGABRT, SIGFPE, SIGILL, SIGSEGV, }; -const char* GetSignalName(int signal_id) { - switch (signal_id) { - case SIGABRT: - return "SIGABRT"; - case SIGFPE: - return "SIGFPE"; - case SIGILL: - return "SIGILL"; - case SIGINT: - return "SIGINT"; - case SIGSEGV: - return "SIGSEGV"; - default: - return "UNKNOWN SIGNAL"; - } -} - -typedef void (*SignalHandlerFunction)(int); +const int kStopSignalsToTrap[] = { + SIGTERM, SIGINT, +}; void SetSignalHandler(int signal_id, SignalHandlerFunction handler) { - struct sigaction action = {0}; + struct sigaction action = {0}; - action.sa_handler = handler; - action.sa_flags = 0; - ::sigemptyset(&action.sa_mask); + action.sa_handler = handler; + action.sa_flags = 0; + ::sigemptyset(&action.sa_mask); - ::sigaction(signal_id, &action, NULL); + ::sigaction(signal_id, &action, NULL); } void DumpStackSignalSafe(int signal_id) { - const char* signal_name = GetSignalName(signal_id); - SbLogRawFormatF("\nCaught signal: %s (%d)\n", signal_name, signal_id); + LogSignalCaught(signal_id); SbLogFlush(); SbLogRawDumpStack(1); @@ -70,17 +54,28 @@ SbSystemBreakIntoDebugger(); } +void Stop(int signal_id) { + LogSignalCaught(signal_id); + SbSystemRequestStop(0); +} + } // namespace void InstallCrashSignalHandlers() { - for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) { - SetSignalHandler(kSignalsToTrap[i], &DumpStackSignalSafe); + for (int i = 0; i < SB_ARRAY_SIZE_INT(kCrashSignalsToTrap); ++i) { + SetSignalHandler(kCrashSignalsToTrap[i], &DumpStackSignalSafe); + } + for (int i = 0; i < SB_ARRAY_SIZE_INT(kStopSignalsToTrap); ++i) { + SetSignalHandler(kStopSignalsToTrap[i], &Stop); } } void UninstallCrashSignalHandlers() { - for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) { - SetSignalHandler(kSignalsToTrap[i], SIG_DFL); + for (int i = 0; i < SB_ARRAY_SIZE_INT(kCrashSignalsToTrap); ++i) { + SetSignalHandler(kCrashSignalsToTrap[i], SIG_DFL); + } + for (int i = 0; i < SB_ARRAY_SIZE_INT(kStopSignalsToTrap); ++i) { + SetSignalHandler(kStopSignalsToTrap[i], SIG_DFL); } }
diff --git a/src/starboard/shared/signal/signal_internal.h b/src/starboard/shared/signal/signal_internal.h new file mode 100644 index 0000000..f511ab0 --- /dev/null +++ b/src/starboard/shared/signal/signal_internal.h
@@ -0,0 +1,62 @@ +// Copyright 2016 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 STARBOARD_SHARED_SIGNAL_SIGNAL_INTERNAL_H_ +#define STARBOARD_SHARED_SIGNAL_SIGNAL_INTERNAL_H_ + +#include <signal.h> + +#include "starboard/log.h" +#include "starboard/shared/internal_only.h" + +namespace starboard { +namespace shared { +namespace signal { + +inline const char* GetSignalName(int signal_id) { + switch (signal_id) { + case SIGABRT: + return "SIGABRT"; + case SIGCONT: + return "SIGCONT"; + case SIGFPE: + return "SIGFPE"; + case SIGILL: + return "SIGILL"; + case SIGINT: + return "SIGINT"; + case SIGSEGV: + return "SIGSEGV"; + case SIGTSTP: + return "SIGTSTP"; + case SIGTERM: + return "SIGTERM"; + default: + return "UNKNOWN SIGNAL"; + } +} + +inline void LogSignalCaught(int signal_id) { + const char* signal_name = GetSignalName(signal_id); + SbLogRawFormatF("\nCaught signal: %s (%d)\n", signal_name, signal_id); + SbLogFlush(); +} + +typedef void (*SignalHandlerFunction)(int); + +} // namespace signal +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_SIGNAL_SIGNAL_INTERNAL_H_
diff --git a/src/starboard/shared/signal/suspend_signals.cc b/src/starboard/shared/signal/suspend_signals.cc new file mode 100644 index 0000000..0ea0f09 --- /dev/null +++ b/src/starboard/shared/signal/suspend_signals.cc
@@ -0,0 +1,73 @@ +// Copyright 2016 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 "starboard/shared/signal/suspend_signals.h" + +#include <signal.h> + +#include "starboard/configuration.h" +#include "starboard/log.h" +#include "starboard/memory.h" +#include "starboard/shared/signal/signal_internal.h" +#include "starboard/shared/starboard/application.h" +#include "starboard/system.h" + +namespace starboard { +namespace shared { +namespace signal { + +namespace { + +void SetSignalHandler(int signal_id, SignalHandlerFunction handler) { + struct sigaction action = {0}; + + action.sa_handler = handler; + action.sa_flags = 0; + ::sigemptyset(&action.sa_mask); + + ::sigaction(signal_id, &action, NULL); +} + +void SuspendDone(void* /*context*/) { + SetSignalHandler(SIGTSTP, SIG_DFL); + raise(SIGTSTP); +} + +void Suspend(int signal_id) { + LogSignalCaught(signal_id); + starboard::Application::Get()->Suspend(NULL, &SuspendDone); +} + +void Resume(int signal_id) { + LogSignalCaught(signal_id); + SetSignalHandler(SIGTSTP, &Suspend); + // TODO: Resume or Unpause based on state. + starboard::Application::Get()->Unpause(NULL, NULL); +} + +} // namespace + +void InstallSuspendSignalHandlers() { + SetSignalHandler(SIGTSTP, &Suspend); + SetSignalHandler(SIGCONT, &Resume); +} + +void UninstallSuspendSignalHandlers() { + SetSignalHandler(SIGTSTP, SIG_DFL); + SetSignalHandler(SIGCONT, SIG_DFL); +} + +} // namespace signal +} // namespace shared +} // namespace starboard
diff --git a/src/starboard/shared/signal/suspend_signals.h b/src/starboard/shared/signal/suspend_signals.h new file mode 100644 index 0000000..730f8ad --- /dev/null +++ b/src/starboard/shared/signal/suspend_signals.h
@@ -0,0 +1,31 @@ +// Copyright 2016 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 STARBOARD_SHARED_SIGNAL_SUSPEND_SIGNALS_H_ +#define STARBOARD_SHARED_SIGNAL_SUSPEND_SIGNALS_H_ + +#include "starboard/shared/internal_only.h" + +namespace starboard { +namespace shared { +namespace signal { + +void InstallSuspendSignalHandlers(); +void UninstallSuspendSignalHandlers(); + +} // namespace signal +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_SIGNAL_SUSPEND_SIGNALS_H_
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc index b7ca314..26e08db 100644 --- a/src/starboard/shared/starboard/application.cc +++ b/src/starboard/shared/starboard/application.cc
@@ -35,7 +35,7 @@ event.type = type; event.data = data; SbEventHandle(&event); - if (destructor && event.data) { + if (destructor) { destructor(event.data); } } @@ -57,7 +57,10 @@ Application* Application::g_instance = NULL; Application::Application() - : error_level_(0), thread_(SbThreadGetCurrent()), start_link_(NULL) { + : error_level_(0), + thread_(SbThreadGetCurrent()), + start_link_(NULL), + state_(kStateUnstarted) { Application* old_instance = reinterpret_cast<Application*>(SbAtomicAcquire_CompareAndSwapPtr( reinterpret_cast<SbAtomicPtr*>(&g_instance), @@ -80,6 +83,7 @@ int Application::Run(int argc, char** argv) { Initialize(); DispatchStart(argc, argv, start_link_); + state_ = kStateStarted; for (;;) { if (!DispatchAndDelete(GetNextEvent())) { @@ -91,6 +95,22 @@ return error_level_; } +void Application::Pause(void* context, EventHandledCallback callback) { + Inject(new Event(kSbEventTypePause, context, callback)); +} + +void Application::Unpause(void* context, EventHandledCallback callback) { + Inject(new Event(kSbEventTypeUnpause, context, callback)); +} + +void Application::Suspend(void* context, EventHandledCallback callback) { + Inject(new Event(kSbEventTypeSuspend, context, callback)); +} + +void Application::Resume(void* context, EventHandledCallback callback) { + Inject(new Event(kSbEventTypeResume, context, callback)); +} + void Application::Stop(int error_level) { Event* event = new Event(kSbEventTypeStop, NULL, NULL); event->error_level = error_level; @@ -134,18 +154,100 @@ return true; } - bool should_continue = true; - if (event->event->type == kSbEventTypeStop) { - should_continue = false; - error_level_ = event->error_level; + // Ensure that we go through the the appropriate lifecycle events based on the + // current state. + switch (event->event->type) { + case kSbEventTypePause: + if (state() != kStateStarted) { + delete event; + return true; + } + break; + case kSbEventTypeUnpause: + if (state() == kStateStarted) { + delete event; + return true; + } + + if (state() == kStateSuspended) { + Inject(new Event(kSbEventTypeResume, NULL, NULL)); + Inject(event); + return true; + } + break; + case kSbEventTypeSuspend: + if (state() == kStateSuspended) { + delete event; + return true; + } + + if (state() == kStateStarted) { + Inject(new Event(kSbEventTypePause, NULL, NULL)); + Inject(event); + return true; + } + break; + case kSbEventTypeResume: + if (state() == kStateStarted || state() == kStatePaused) { + delete event; + return true; + } + break; + case kSbEventTypeStop: + if (state() == kStateStarted) { + Inject(new Event(kSbEventTypePause, NULL, NULL)); + Inject(new Event(kSbEventTypeSuspend, NULL, NULL)); + Inject(event); + return true; + } + + if (state() == kStatePaused) { + Inject(new Event(kSbEventTypeSuspend, NULL, NULL)); + Inject(event); + return true; + } + error_level_ = event->error_level; + break; + case kSbEventTypeScheduled: { + TimedEvent* timed_event = + reinterpret_cast<TimedEvent*>(event->event->data); + timed_event->callback(timed_event->context); + delete event; + return true; + } + default: + break; } - if (event->event->type == kSbEventTypeScheduled) { - TimedEvent* timed_event = reinterpret_cast<TimedEvent*>(event->event->data); - timed_event->callback(timed_event->context); - } else { - SbEventHandle(event->event); + SbEventHandle(event->event); + + bool should_continue = true; + switch (event->event->type) { + case kSbEventTypePause: + SB_DCHECK(state() == kStateStarted); + state_ = kStatePaused; + break; + case kSbEventTypeUnpause: + SB_DCHECK(state() == kStatePaused); + state_ = kStateStarted; + break; + case kSbEventTypeSuspend: + SB_DCHECK(state() == kStatePaused); + state_ = kStateSuspended; + break; + case kSbEventTypeResume: + SB_DCHECK(state() == kStateSuspended); + state_ = kStatePaused; + break; + case kSbEventTypeStop: + SB_DCHECK(state() == kStateSuspended); + state_ = kStateStopped; + should_continue = false; + break; + default: + break; } + delete event; return should_continue; }
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h index 2c990a0..7328f2e 100644 --- a/src/starboard/shared/starboard/application.h +++ b/src/starboard/shared/starboard/application.h
@@ -38,6 +38,32 @@ // dispatching events to the Starboard event handler, SbEventHandle. class Application { public: + // You can use a void(void *) function to signal that a state-transition event + // has completed. + typedef SbEventDataDestructor EventHandledCallback; + + // Enumeration of states that the application can be in. + enum State { + // The initial Unstarted state. + kStateUnstarted, + + // The normal foreground, fully-visible state after receiving the initial + // START event or after UNPAUSE from Paused. + kStateStarted, + + // The background-but-visible or partially-obscured state after receiving an + // PAUSE event from Started or RESUME event from Suspended. + kStatePaused, + + // The fully-obscured or about-to-be-terminated state after receiving a + // SUSPEND event in Paused. + kStateSuspended, + + // The completely terminated state after receiving the STOP event in the + // Suspended state. + kStateStopped, + }; + // Structure to keep track of scheduled events, also used as the data argument // for kSbEventTypeScheduled Events. struct TimedEvent { @@ -75,8 +101,6 @@ // deleting the event and calling the destructor on its data when it is // deleted. struct Event { - Event(SbEvent* event, SbEventDataDestructor destructor) - : event(event), destructor(destructor), error_level(0) {} Event(SbEventType type, void* data, SbEventDataDestructor destructor) : event(new SbEvent()), destructor(destructor), error_level(0) { event->type = type; @@ -90,7 +114,7 @@ event->data = data; } ~Event() { - if (destructor && event->data) { + if (destructor) { destructor(event->data); } if (event) { @@ -120,8 +144,45 @@ // initialization and teardown events. Returns the resulting error level. int Run(int argc, char** argv); + // Signals that the application should transition from STARTED to PAUSED as + // soon as possible. Does nothing if already PAUSED or SUSPENDED. May be + // called from an external thread. + // + // |context|: A context value to pass to |callback| on event completion. Must + // not be NULL if callback is not NULL. + // |callback|: A function to call on event completion, from the main thread. + void Pause(void* context, EventHandledCallback callback); + + // Signals that the application should transition to STARTED as soon as + // possible, moving through all required state transitions to get there. Does + // nothing if already STARTED. May be called from an external thread. + // + // |context|: A context value to pass to |callback| on event completion. Must + // not be NULL if callback is not NULL. + // |callback|: A function to call on event completion, from the main thread. + void Unpause(void* context, EventHandledCallback callback); + + // Signals that the application should transition to SUSPENDED as soon as + // possible, moving through all required state transitions to get there. Does + // nothing if already SUSPENDED. May be called from an external thread. + // + // |context|: A context value to pass to |callback| on event completion. Must + // not be NULL if callback is not NULL. + // |callback|: A function to call on event completion, from the main thread. + void Suspend(void* context, EventHandledCallback callback); + + // Signals that the application should transition to PAUSED from SUSPENDED as + // soon as possible. Does nothing if already PAUSED or STARTED. May be called + // from an external thread. + // + // |context|: A context value to pass to |callback| on event completion. Must + // not be NULL if callback is not NULL. + // |callback|: A function to call on event completion, from the main thread. + void Resume(void* context, EventHandledCallback callback); + // Signals that the application should gracefully terminate as soon as - // possible. May be called from an external thread. + // possible. Will transition through PAUSED and SUSPENDED to STOPPED as + // appropriate for the current state. May be called from an external thread. void Stop(int error_level); // Schedules an event into the event queue. May be called from an external @@ -199,10 +260,14 @@ // event that initializes and starts Cobalt. void SetStartLink(const char* start_link); + // Returns whether the current thread is the Application thread. bool IsCurrentThread() const { return SbThreadIsEqual(thread_, SbThreadGetCurrent()); } + // Returns the current application state. + State state() const { return state_; } + private: // Dispatches |event| to the system event handler, taking ownership of the // event. Returns whether to keep servicing the event queue, i.e. false means @@ -222,6 +287,10 @@ // The deep link included in the Start event sent to Cobalt. Initially NULL, // derived classes may set it during initialization using |SetStartLink|. char* start_link_; + + // The current state that the application is in based on what events it has + // actually processed. Should only be accessed on the main thread. + State state_; }; } // namespace starboard
diff --git a/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc b/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc index 09b2402..cd88dd8 100644 --- a/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc +++ b/src/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc
@@ -106,7 +106,7 @@ &is_playing, &is_eos_reached, context_); if (is_playing) { int frames_to_consume = - std::min(kMaxFramesToConsumePerRequest, frames_in_buffer / 2); + std::min(kMaxFramesToConsumePerRequest, frames_in_buffer); SbThreadSleep(frames_to_consume * kSbTimeSecond / sampling_frequency_hz_); consume_frame_func_(frames_to_consume, context_);
diff --git a/src/starboard/shared/starboard/queue_application.h b/src/starboard/shared/starboard/queue_application.h index fa5ac0e..b48d8a7 100644 --- a/src/starboard/shared/starboard/queue_application.h +++ b/src/starboard/shared/starboard/queue_application.h
@@ -54,10 +54,13 @@ virtual bool MayHaveSystemEvents() = 0; // Returns an event if one exists, otherwise returns NULL. - virtual Event* PollNextSystemEvent() = 0; + virtual Event* PollNextSystemEvent() { + return WaitForSystemEventWithTimeout(SbTime()); + } // Waits for an event until the timeout |time| runs out. If an event occurs - // in this time, it is returned, otherwise NULL is returned. + // in this time, it is returned, otherwise NULL is returned. If |time| is zero + // or negative, then this should function effectively like a no-wait poll. virtual Event* WaitForSystemEventWithTimeout(SbTime time) = 0; // Wakes up any thread waiting within a call to @@ -65,6 +68,20 @@ virtual void WakeSystemEventWait() = 0; private: + // Specialization of Queue for starboard events. It differs in that it has + // the responsibility of deleting heap allocated starboard events in its + // destructor. Note the non-virtual destructor, which is intentional and + // safe, as Queue has no virtual functions and EventQueue is never used + // polymorphically. + class EventQueue : public Queue<Event*> { + public: + ~EventQueue() { + while (Event* event = Poll()) { + delete event; + } + } + }; + class TimedEventQueue { public: TimedEventQueue(); @@ -99,7 +116,7 @@ TimedEventQueue timed_event_queue_; // The queue of events that have not yet been dispatched. - Queue<Event*> event_queue_; + EventQueue event_queue_; }; } // namespace starboard
diff --git a/src/starboard/shared/stub/player_set_volume.cc b/src/starboard/shared/stub/player_set_volume.cc new file mode 100644 index 0000000..5a45e91 --- /dev/null +++ b/src/starboard/shared/stub/player_set_volume.cc
@@ -0,0 +1,17 @@ +// Copyright 2016 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 "starboard/player.h" + +void SbPlayerSetVolume(SbPlayer /*player*/, double /*volume*/) {}
diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc index bfde70b..1457e73 100644 --- a/src/starboard/shared/x11/application_x11.cc +++ b/src/starboard/shared/x11/application_x11.cc
@@ -556,23 +556,18 @@ return key_modifiers; } -bool XNextEventPoll(Display* display, XEvent* out_event) { - if (XPending(display) == 0) { - return false; - } - - XNextEvent(display, out_event); - return true; -} - bool XNextEventTimed(Display* display, XEvent* out_event, SbTime duration) { if (XPending(display) == 0) { + if (duration <= SbTime()) { + return false; + } + int fd = ConnectionNumber(display); fd_set read_set; FD_ZERO(&read_set); FD_SET(fd, &read_set); struct timeval tv; - SbTime clamped_duration = std::max(duration, (SbTime)0); + SbTime clamped_duration = std::max(duration, SbTime()); ToTimevalDuration(clamped_duration, &tv); if (select(fd + 1, &read_set, NULL, NULL, &tv) == 0) { return false; @@ -762,20 +757,10 @@ return display_; } -shared::starboard::Application::Event* ApplicationX11::PollNextSystemEvent() { - SB_DCHECK(display_); - - XEvent x_event; - - if (XNextEventPoll(display_, &x_event)) { - return XEventToEvent(&x_event); - } - - return NULL; -} - shared::starboard::Application::Event* ApplicationX11::WaitForSystemEventWithTimeout(SbTime time) { + SB_DCHECK(display_); + XEvent x_event; if (XNextEventTimed(display_, &x_event, time)) { @@ -878,6 +863,18 @@ data->key_location = XKeyEventToSbKeyLocation(x_key_event); data->key_modifiers = XKeyEventToSbKeyModifiers(x_key_event); return new Event(kSbEventTypeInput, data, &DeleteDestructor<SbInputData>); + } else if (x_event->type == FocusIn) { + Unpause(NULL, NULL); + return NULL; + } else if (x_event->type == FocusOut) { + Pause(NULL, NULL); + return NULL; + } else if (x_event->type == MapNotify) { + Resume(NULL, NULL); + return NULL; + } else if (x_event->type == UnmapNotify) { + Suspend(NULL, NULL); + return NULL; } SB_DLOG(INFO) << "Unrecognized event type = " << x_event->type;
diff --git a/src/starboard/shared/x11/application_x11.h b/src/starboard/shared/x11/application_x11.h index 11b4aca..8bd9940 100644 --- a/src/starboard/shared/x11/application_x11.h +++ b/src/starboard/shared/x11/application_x11.h
@@ -63,7 +63,6 @@ // --- QueueApplication overrides --- bool MayHaveSystemEvents() SB_OVERRIDE; - Event* PollNextSystemEvent() SB_OVERRIDE; Event* WaitForSystemEventWithTimeout(SbTime time) SB_OVERRIDE; void WakeSystemEventWait() SB_OVERRIDE;
diff --git a/src/starboard/shared/x11/window_internal.cc b/src/starboard/shared/x11/window_internal.cc index 3885bf6..b17082a 100644 --- a/src/starboard/shared/x11/window_internal.cc +++ b/src/starboard/shared/x11/window_internal.cc
@@ -78,7 +78,8 @@ } XSetWindowAttributes swa = {0}; - swa.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask; + swa.event_mask = + KeyPressMask | KeyReleaseMask | StructureNotifyMask | FocusChangeMask; swa.colormap = XCreateColormap(display, root_window, x_visual_info.visual, AllocNone); // Setting border_pixel to 0 is required if the requested window depth (e.g.
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp index 1ac0c82..707fecd 100644 --- a/src/starboard/stub/starboard_platform.gyp +++ b/src/starboard/stub/starboard_platform.gyp
@@ -109,6 +109,7 @@ '<(DEPTH)/starboard/shared/stub/player_seek.cc', '<(DEPTH)/starboard/shared/stub/player_set_bounds.cc', '<(DEPTH)/starboard/shared/stub/player_set_pause.cc', + '<(DEPTH)/starboard/shared/stub/player_set_volume.cc', '<(DEPTH)/starboard/shared/stub/player_write_end_of_stream.cc', '<(DEPTH)/starboard/shared/stub/player_write_sample.cc', '<(DEPTH)/starboard/shared/stub/socket_accept.cc',
diff --git a/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h b/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h index b8d70d1..4dcd88e 100644 --- a/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h +++ b/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h
@@ -12,7 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +#ifndef gc_JSCUSTOMALLOCATOR_H +#define gc_JSCUSTOMALLOCATOR_H + +#include <algorithm> + #include "jstypes.h" +#include "memory_allocator_reporter.h" #include "starboard/memory.h" #include "starboard/string.h" @@ -20,25 +26,58 @@ #define JS_OOM_POSSIBLY_FAIL_REPORT(cx) do {} while(0) static JS_INLINE void* js_malloc(size_t bytes) { - return SbMemoryAllocate(bytes); -} - -static JS_INLINE void* js_calloc(size_t bytes) { - return SbMemoryCalloc(bytes, 1); + size_t reservation_bytes = AllocationMetadata::GetReservationBytes(bytes); + MemoryAllocatorReporter::Get()->UpdateAllocatedBytes(reservation_bytes); + void* metadata = SbMemoryAllocate(reservation_bytes); + AllocationMetadata::SetSizeToBaseAddress(metadata, reservation_bytes); + return AllocationMetadata::GetUserAddressFromBaseAddress(metadata); } static JS_INLINE void* js_calloc(size_t nmemb, size_t size) { - return SbMemoryCalloc(nmemb, size); + size_t total_size = nmemb * size; + void* memory = js_malloc(total_size); + if (memory) { + SbMemorySet(memory, 0, total_size); + } + return memory; } -static JS_INLINE void* js_realloc(void* p, size_t bytes) { - return SbMemoryReallocate(p, bytes); +static JS_INLINE void* js_calloc(size_t bytes) { + return js_calloc(bytes, 1); } static JS_INLINE void js_free(void* p) { - SbMemoryFree(p); + if (p == NULL) { + return; + } + + AllocationMetadata* metadata = + AllocationMetadata::GetMetadataFromUserAddress(p); + MemoryAllocatorReporter::Get()->UpdateAllocatedBytes(-static_cast<ssize_t>( + AllocationMetadata::GetSizeOfAllocationFromMetadata(metadata))); + SbMemoryFree(metadata); +} + +static JS_INLINE void* js_realloc(void* p, size_t bytes) { + AllocationMetadata* metadata = + AllocationMetadata::GetMetadataFromUserAddress(p); + size_t current_size = + AllocationMetadata::GetSizeOfAllocationFromMetadata(metadata); + size_t adjusted_size = AllocationMetadata::GetReservationBytes(bytes); + + MemoryAllocatorReporter::Get()->UpdateAllocatedBytes( + static_cast<ssize_t>(adjusted_size - current_size)); + void* new_ptr = SbMemoryReallocate(metadata, adjusted_size); + AllocationMetadata::SetSizeToBaseAddress(new_ptr, adjusted_size); + return AllocationMetadata::GetUserAddressFromBaseAddress(new_ptr); } static JS_INLINE char* js_strdup(char* s) { - return SbStringDuplicate(s); + size_t length = SbStringGetLength(s) + 1; + + char* new_ptr = reinterpret_cast<char*>(js_malloc(length)); + SbStringCopy(new_ptr, s, length); + return new_ptr; } + +#endif /* gc_JSCUSTOMALLOCATOR_H */
diff --git a/src/third_party/mozjs/js/src/gc/Memory.cpp b/src/third_party/mozjs/js/src/gc/Memory.cpp index b9e5199..9c55ba1 100644 --- a/src/third_party/mozjs/js/src/gc/Memory.cpp +++ b/src/third_party/mozjs/js/src/gc/Memory.cpp
@@ -7,6 +7,7 @@ #include "gc/Memory.h" #include "jscntxt.h" +#include "memory_allocator_reporter.h" #include "js/HeapAPI.h" @@ -324,13 +325,23 @@ JS_ASSERT(flags == 0); JS_ASSERT(fd == -1); JS_ASSERT(offset == 0); - return SbMemoryMap(length, prot, "mozjs::gc::MapMemory"); + + void* result = SbMemoryMap(length, prot, "mozjs::gc::MapMemory"); + if (result != SB_MEMORY_MAP_FAILED) { + MemoryAllocatorReporter::Get()->UpdateMappedBytes(length); + } + return result; } static inline bool UnmapMemory(void* region, size_t length) { - return SbMemoryUnmap(region, length); + bool success = SbMemoryUnmap(region, length); + if (success) { + MemoryAllocatorReporter::Get()->UpdateMappedBytes( + -static_cast<ssize_t>(length)); + } + return success; } #else
diff --git a/src/third_party/mozjs/js/src/jsstarboard-time.cpp b/src/third_party/mozjs/js/src/jsstarboard-time.cpp index d5049e2..92d309b 100644 --- a/src/third_party/mozjs/js/src/jsstarboard-time.cpp +++ b/src/third_party/mozjs/js/src/jsstarboard-time.cpp
@@ -15,8 +15,11 @@ #include "jsstarboard-time.h" #include "mozilla/Assertions.h" +#include "starboard/configuration.h" #include "unicode/timezone.h" +// If the Starboard platform has this quirk, do not use these functions. +#if !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT) SbTime getDSTOffset(int64_t utc_time_us) { // UDate is in milliseconds from the epoch. UDate udate = utc_time_us / kSbTimeMillisecond; @@ -41,4 +44,4 @@ delete current_zone; return raw_offset_ms * kSbTimeMillisecond; } - +#endif
diff --git a/src/third_party/mozjs/js/src/jsutil.cpp b/src/third_party/mozjs/js/src/jsutil.cpp index bd3e182..142f724 100644 --- a/src/third_party/mozjs/js/src/jsutil.cpp +++ b/src/third_party/mozjs/js/src/jsutil.cpp
@@ -41,32 +41,6 @@ js_free(addr); } -class Compressor -{ - /* Number of bytes we should hand to zlib each compressMore() call. */ - static const size_t CHUNKSIZE = 2048; - z_stream zs; - const unsigned char *inp; - size_t inplen; - size_t outbytes; - - public: - enum Status { - MOREOUTPUT, - DONE, - CONTINUE, - OOM - }; - - Compressor(const unsigned char *inp, size_t inplen); - ~Compressor(); - bool init(); - void setOutput(unsigned char *out, size_t outlen); - size_t outWritten() const { return outbytes; } - /* Compress some of the input. Return true if it should be called again. */ - Status compressMore(); -}; - Compressor::Compressor(const unsigned char *inp, size_t inplen) : inp(inp), inplen(inplen),
diff --git a/src/third_party/mozjs/js/src/jsutil.h b/src/third_party/mozjs/js/src/jsutil.h index 9306a26..9dcfa8f 100644 --- a/src/third_party/mozjs/js/src/jsutil.h +++ b/src/third_party/mozjs/js/src/jsutil.h
@@ -17,6 +17,10 @@ #include "js/Utility.h" +#ifdef USE_ZLIB +#include "zlib.h" +#endif + /* Forward declarations. */ struct JSContext; @@ -262,6 +266,32 @@ #ifdef USE_ZLIB +class Compressor +{ + /* Number of bytes we should hand to zlib each compressMore() call. */ + static const size_t CHUNKSIZE = 2048; + z_stream zs; + const unsigned char *inp; + size_t inplen; + size_t outbytes; + + public: + enum Status { + MOREOUTPUT, + DONE, + CONTINUE, + OOM + }; + + Compressor(const unsigned char *inp, size_t inplen); + ~Compressor(); + bool init(); + void setOutput(unsigned char *out, size_t outlen); + size_t outWritten() const { return outbytes; } + /* Compress some of the input. Return true if it should be called again. */ + Status compressMore(); +}; + /* * Decompress a string. The caller must know the length of the output and * allocate |out| to a string of that length.
diff --git a/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp b/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp new file mode 100644 index 0000000..93d42df --- /dev/null +++ b/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp
@@ -0,0 +1,83 @@ +// Copyright 2016 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 "memory_allocator_reporter.h" + +#include "starboard/once.h" + +namespace { +// Control to initialize s_instance. +SbOnceControl s_instance_control = SB_ONCE_INITIALIZER; +MemoryAllocatorReporter* s_instance = NULL; + +void Initialize() { + s_instance = new MemoryAllocatorReporter(); +} + +void* OffsetPointer(void* base, ssize_t offset) { + uintptr_t base_as_int = reinterpret_cast<uintptr_t>(base); + return reinterpret_cast<void*>(base_as_int + offset); +} +} // namespace + +AllocationMetadata* AllocationMetadata::GetMetadataFromUserAddress(void* ptr) { + if (ptr == NULL) { + return NULL; + } + + // The metadata lives just in front of the data. + void* meta_addr = + OffsetPointer(ptr, -static_cast<ssize_t>(sizeof(AllocationMetadata))); + return reinterpret_cast<AllocationMetadata*>(meta_addr); +} + +void* AllocationMetadata::GetUserAddressFromBaseAddress(void* base_ptr) { + void* adjusted_base = + OffsetPointer(base_ptr, static_cast<ssize_t>(sizeof(AllocationMetadata))); + return adjusted_base; +} + +void AllocationMetadata::SetSizeToBaseAddress(void* base_ptr, size_t size) { + if (base_ptr) { + AllocationMetadata* metadata = + reinterpret_cast<AllocationMetadata*>(base_ptr); + metadata->set_size_requested(size); + } +} + +void MemoryAllocatorReporter::UpdateAllocatedBytes(ssize_t bytes) { + starboard::ScopedLock lock(mutex_); + current_bytes_allocated_ += bytes; +} + +ssize_t MemoryAllocatorReporter::GetCurrentBytesAllocated() { + starboard::ScopedLock lock(mutex_); + return current_bytes_allocated_; +} + +void MemoryAllocatorReporter::UpdateMappedBytes(ssize_t bytes) { + starboard::ScopedLock lock(mutex_); + current_bytes_mapped_ += bytes; +} + +ssize_t MemoryAllocatorReporter::GetCurrentBytesMapped() { + starboard::ScopedLock lock(mutex_); + return current_bytes_mapped_; +} + +// static +MemoryAllocatorReporter* MemoryAllocatorReporter::Get() { + SbOnce(&s_instance_control, &Initialize); + return s_instance; +}
diff --git a/src/third_party/mozjs/js/src/memory_allocator_reporter.h b/src/third_party/mozjs/js/src/memory_allocator_reporter.h new file mode 100644 index 0000000..e0d679f --- /dev/null +++ b/src/third_party/mozjs/js/src/memory_allocator_reporter.h
@@ -0,0 +1,62 @@ +// Copyright 2016 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 MemoryAllocatorReporter_h +#define MemoryAllocatorReporter_h + +#include <sys/types.h> + +#include "starboard/mutex.h" + +class AllocationMetadata { + public: + static AllocationMetadata* GetMetadataFromUserAddress(void* ptr); + static void* GetUserAddressFromBaseAddress(void* base_ptr); + static size_t GetReservationBytes(size_t bytes_requested) { + return sizeof(AllocationMetadata) + bytes_requested; + } + static size_t GetSizeOfAllocationFromMetadata(AllocationMetadata* metadata) { + return metadata ? metadata->size_requested() : 0; + } + static void SetSizeToBaseAddress(void* base_ptr, size_t size); + + size_t size_requested() { return size_requested_; } + void set_size_requested(size_t size) { size_requested_ = size; } + + private: + // Bytes requested by the underlying allocator. + size_t size_requested_; +}; + +// Reporter that is used to report memory allocation. +class MemoryAllocatorReporter { + public: + static MemoryAllocatorReporter* Get(); + + MemoryAllocatorReporter() + : current_bytes_allocated_(0), current_bytes_mapped_(0) {} + + void UpdateAllocatedBytes(ssize_t bytes); + ssize_t GetCurrentBytesAllocated(); + + void UpdateMappedBytes(ssize_t bytes); + ssize_t GetCurrentBytesMapped(); + + private: + starboard::Mutex mutex_; + ssize_t current_bytes_allocated_; + ssize_t current_bytes_mapped_; +}; + +#endif /* MemoryAllocatorReporter_h */
diff --git a/src/third_party/mozjs/js/src/vm/DateTime.cpp b/src/third_party/mozjs/js/src/vm/DateTime.cpp index cfca247..a78a121 100644 --- a/src/third_party/mozjs/js/src/vm/DateTime.cpp +++ b/src/third_party/mozjs/js/src/vm/DateTime.cpp
@@ -8,8 +8,16 @@ #if defined(STARBOARD) #include "jsstarboard-time.h" +#include "starboard/configuration.h" #include "starboard/time_zone.h" -#else +// For Starboard platforms that don't have support for getting the timezone +// name, fall back to using localtime for conversion between UTC<->localtime. +#if !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT) +#define USE_STARBOARD_TIME +#endif // !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT) +#endif // defined(STARBOARD) + +#if !defined(USE_STARBOARD_TIME) #include <time.h> #endif @@ -17,7 +25,7 @@ using mozilla::UnspecifiedNaN; -#if !defined(STARBOARD) +#if !defined(USE_STARBOARD_TIME) static bool ComputeLocalTime(time_t local, struct tm *ptm) { @@ -131,7 +139,7 @@ // local seconds' frame of reference and then subtract. return local_secs - (utc_secs + SecondsPerDay); } -#endif // defined(STARBOARD) +#endif // defined(USE_STARBOARD_TIME) void js::DateTimeInfo::updateTimeZoneAdjustment() @@ -140,7 +148,7 @@ * The difference between local standard time and UTC will never change for * a given time zone. */ -#if defined(STARBOARD) +#if defined(USE_STARBOARD_TIME) utcToLocalStandardOffsetSeconds = getTZOffset() / kSbTimeSecond; #else utcToLocalStandardOffsetSeconds = UTCToLocalStandardOffsetSeconds(); @@ -179,7 +187,7 @@ updateTimeZoneAdjustment(); } -#if defined(STARBOARD) +#if defined(USE_STARBOARD_TIME) int64_t js::DateTimeInfo::computeDSTOffsetMilliseconds(int64_t utcSeconds) { @@ -219,7 +227,7 @@ return diff * msPerSecond; } -#endif // defined(STARBOARD) +#endif // defined(USE_STARBOARD_TIME) int64_t js::DateTimeInfo::getDSTOffsetMilliseconds(int64_t utcMilliseconds)
diff --git a/src/third_party/mozjs/mozjs.gypi b/src/third_party/mozjs/mozjs.gypi index 9fb9822..6b85ee0 100644 --- a/src/third_party/mozjs/mozjs.gypi +++ b/src/third_party/mozjs/mozjs.gypi
@@ -82,6 +82,7 @@ 'js/src/jsweakmap.cpp', 'js/src/jsworkers.cpp', 'js/src/jswrapper.cpp', + 'js/src/memory_allocator_reporter.cpp', 'js/src/perf/jsperf.cpp', 'js/src/perf/pm_stub.cpp', 'js/src/prmjtime.cpp',
diff --git a/src/third_party/mozjs/test/jscustomallocator_test.cc b/src/third_party/mozjs/test/jscustomallocator_test.cc new file mode 100644 index 0000000..e6702e1 --- /dev/null +++ b/src/third_party/mozjs/test/jscustomallocator_test.cc
@@ -0,0 +1,178 @@ +/* + * Copyright 2016 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 "jscustomallocator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const size_t kSize = 1024 * 128; + +TEST(JSCustomallocator, JSMalloc) { + void* memory = js_malloc(kSize); + EXPECT_NE(static_cast<void*>(NULL), memory); + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + js_free(memory); + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSCallocWithNumber) { + void* memory = js_calloc(5, kSize); + EXPECT_NE(static_cast<void*>(NULL), memory); + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(5 * kSize)); + js_free(memory); + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSCalloc) { + void* memory = js_calloc(kSize); + EXPECT_NE(static_cast<void*>(NULL), memory); + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + js_free(memory); + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSReallocSmaller) { + void* memory = js_malloc(kSize); + ASSERT_NE(static_cast<void*>(NULL), memory); + char* data = static_cast<char*>(memory); + for (int i = 0; i < kSize; ++i) { + data[i] = i; + } + + for (int i = 0; i < kSize; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + + memory = js_realloc(memory, kSize / 2); + data = static_cast<char*>(memory); + ASSERT_NE(static_cast<void*>(NULL), memory); + for (int i = 0; i < kSize / 2; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize / 2)); + + js_free(memory); + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSReallocBigger) { + void* memory = js_malloc(kSize); + ASSERT_NE(static_cast<void*>(NULL), memory); + char* data = static_cast<char*>(memory); + for (int i = 0; i < kSize; ++i) { + data[i] = i; + } + + for (int i = 0; i < kSize; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + + memory = js_realloc(memory, kSize * 2); + ASSERT_NE(static_cast<void*>(NULL), memory); + data = static_cast<char*>(memory); + for (int i = 0; i < kSize; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + for (int i = kSize; i < kSize * 2; ++i) { + data[i] = i; + } + + for (int i = kSize; i < kSize * 2; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize * 2)); + + js_free(memory); + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSReallocNULL) { + void* memory = js_realloc(NULL, kSize); + EXPECT_NE(static_cast<void*>(NULL), memory); + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + + js_free(memory); + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSStrdup) { + const char* input = "abcedfg123456"; + char* dupe = js_strdup(const_cast<char*>(input)); + const char* kNull = NULL; + EXPECT_NE(kNull, dupe); + EXPECT_EQ(0, SbStringCompareNoCase(input, dupe)); + EXPECT_EQ(SbStringGetLength(input), SbStringGetLength(dupe)); + + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, AllocationMetadata::GetReservationBytes( + SbStringGetLength(dupe) + 1)); + + js_free(dupe); + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +} // namespace
diff --git a/src/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp index 526e3be..77a5de6 100644 --- a/src/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp +++ b/src/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp
@@ -88,7 +88,7 @@ fsBuilder->codeAppend(".r,\n\t\t"); fsBuilder->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].getType()); if (yuvEffect.fNV12) { - fsBuilder->codeAppend(".ba,\n\t\t"); + fsBuilder->codeAppend(".ra,\n\t\t"); } else { fsBuilder->codeAppend(".r,\n\t\t"); fsBuilder->appendTextureLookup(samplers[2], coords[0].c_str(), coords[0].getType());