diff --git a/.gitignore b/.gitignore index a7d022e9..6334517 100644 --- a/.gitignore +++ b/.gitignore
@@ -38,6 +38,10 @@ .pydevproject .checkstyle cscope.* +GPATH +GRTAGS +GSYMS +GTAGS Session.vim tags Thumbs.db @@ -148,6 +152,7 @@ /components/leveldb_proto_test_support.xml /components/rappor.xml /components/resources/default_100_percent/google_chrome +/components/resources/default_200_percent/google_chrome /components/search_engines/prepopulated_engines.xml /components/suggestions.xml /components/variations.xml
diff --git a/BUILD.gn b/BUILD.gn index b169525..2b19ec1 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -177,7 +177,10 @@ "//ui/touch_selection:ui_touch_selection_unittests", ] } else { - deps += [ "//ios/net:ios_net_unittests" ] + deps += [ + "//ios/net:ios_net_unittests", + "//ios/third_party/gcdwebserver", + ] } deps += root_extra_deps
diff --git a/DEPS b/DEPS index b14694d8..8d7cd348 100644 --- a/DEPS +++ b/DEPS
@@ -59,7 +59,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '35902e725aa6cc83a317c3b6fdd1926b81b8e44b', + 'pdfium_revision': '1f439a7a3b7c44235ecdac9a411add8fb62b0d83', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other.
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn index 9d9b467..c4b6609 100644 --- a/base/trace_event/BUILD.gn +++ b/base/trace_event/BUILD.gn
@@ -27,7 +27,6 @@ "process_memory_dump.h", "process_memory_maps.cc", "process_memory_maps.h", - "process_memory_maps_dump_provider.cc", "process_memory_maps_dump_provider.h", "process_memory_totals.cc", "process_memory_totals.h", @@ -76,6 +75,7 @@ sources += [ "malloc_dump_provider.cc", "malloc_dump_provider.h", + "process_memory_maps_dump_provider.cc", ] } @@ -111,7 +111,6 @@ "memory_profiler_allocation_context_unittest.cc", "memory_profiler_allocation_register_unittest.cc", "process_memory_dump_unittest.cc", - "process_memory_maps_dump_provider_unittest.cc", "process_memory_totals_dump_provider_unittest.cc", "trace_config_memory_test_util.h", "trace_config_unittest.cc", @@ -124,6 +123,10 @@ "winheap_dump_provider_win_unittest.cc", ] + if (is_linux || is_android) { + sources += [ "process_memory_maps_dump_provider_unittest.cc" ] + } + deps = [ "//base/test:test_support", "//testing/gmock",
diff --git a/base/trace_event/process_memory_maps_dump_provider.cc b/base/trace_event/process_memory_maps_dump_provider.cc index 335dd829a..19f8d89 100644 --- a/base/trace_event/process_memory_maps_dump_provider.cc +++ b/base/trace_event/process_memory_maps_dump_provider.cc
@@ -4,6 +4,7 @@ #include "base/trace_event/process_memory_maps_dump_provider.h" +#include "base/files/scoped_file.h" #include "base/format_macros.h" #include "base/logging.h" #include "base/strings/string_util.h" @@ -13,7 +14,6 @@ namespace base { namespace trace_event { -#if defined(OS_LINUX) || defined(OS_ANDROID) // static FILE* ProcessMemoryMapsDumpProvider::proc_smaps_for_testing = nullptr; @@ -134,7 +134,6 @@ } } // namespace -#endif // defined(OS_LINUX) || defined(OS_ANDROID) // static ProcessMemoryMapsDumpProvider* ProcessMemoryMapsDumpProvider::GetInstance() { @@ -157,23 +156,17 @@ return true; uint32 res = 0; - -#if defined(OS_LINUX) || defined(OS_ANDROID) if (UNLIKELY(proc_smaps_for_testing)) { res = ReadLinuxProcSmapsFile(proc_smaps_for_testing, pmd->process_mmaps()); } else { ScopedFILE smaps_file(fopen("/proc/self/smaps", "r")); res = ReadLinuxProcSmapsFile(smaps_file.get(), pmd->process_mmaps()); } -#else - LOG(ERROR) << "ProcessMemoryMaps dump provider is supported only on Linux"; -#endif if (res > 0) { pmd->set_has_process_mmaps(); return true; } - return false; }
diff --git a/base/trace_event/process_memory_maps_dump_provider.h b/base/trace_event/process_memory_maps_dump_provider.h index 74529bd..f302a48d 100644 --- a/base/trace_event/process_memory_maps_dump_provider.h +++ b/base/trace_event/process_memory_maps_dump_provider.h
@@ -9,10 +9,6 @@ #include "base/memory/singleton.h" #include "base/trace_event/memory_dump_provider.h" -#if defined(OS_LINUX) || defined(OS_ANDROID) -#include "base/files/scoped_file.h" -#endif - namespace base { namespace trace_event { @@ -29,7 +25,7 @@ friend struct DefaultSingletonTraits<ProcessMemoryMapsDumpProvider>; FRIEND_TEST_ALL_PREFIXES(ProcessMemoryMapsDumpProviderTest, ParseProcSmaps); -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_NACL) static FILE* proc_smaps_for_testing; #endif
diff --git a/base/trace_event/process_memory_maps_dump_provider_unittest.cc b/base/trace_event/process_memory_maps_dump_provider_unittest.cc index 8fcc9cc..cce33eba 100644 --- a/base/trace_event/process_memory_maps_dump_provider_unittest.cc +++ b/base/trace_event/process_memory_maps_dump_provider_unittest.cc
@@ -13,7 +13,6 @@ namespace base { namespace trace_event { -#if defined(OS_LINUX) || defined(OS_ANDROID) namespace { const char kTestSmaps1[] = "00400000-004be000 r-xp 00000000 fc:01 1234 /file/1\n" @@ -184,7 +183,6 @@ EXPECT_EQ(4 * 1024UL, regions_2[0].byte_stats_private_dirty_resident); EXPECT_EQ(0 * 1024UL, regions_2[0].byte_stats_swapped); } -#endif // defined(OS_LINUX) || defined(OS_ANDROID) } // namespace trace_event } // namespace base
diff --git a/base/trace_event/trace_event.gypi b/base/trace_event/trace_event.gypi index 27184189..8fcf5d2 100644 --- a/base/trace_event/trace_event.gypi +++ b/base/trace_event/trace_event.gypi
@@ -27,7 +27,6 @@ 'trace_event/process_memory_dump.h', 'trace_event/process_memory_maps.cc', 'trace_event/process_memory_maps.h', - 'trace_event/process_memory_maps_dump_provider.cc', 'trace_event/process_memory_maps_dump_provider.h', 'trace_event/process_memory_totals.cc', 'trace_event/process_memory_totals.h', @@ -64,14 +63,6 @@ 'trace_event/winheap_dump_provider_win.cc', 'trace_event/winheap_dump_provider_win.h', ], - 'conditions': [ - ['OS == "linux" or OS == "android"', { - 'trace_event_sources': [ - 'trace_event/malloc_dump_provider.cc', - 'trace_event/malloc_dump_provider.h', - ], - }], - ], 'trace_event_test_sources' : [ 'trace_event/java_heap_dump_provider_android_unittest.cc', 'trace_event/memory_allocator_dump_unittest.cc', @@ -79,7 +70,6 @@ 'trace_event/memory_profiler_allocation_context_unittest.cc', 'trace_event/memory_profiler_allocation_register_unittest.cc', 'trace_event/process_memory_dump_unittest.cc', - 'trace_event/process_memory_maps_dump_provider_unittest.cc', 'trace_event/process_memory_totals_dump_provider_unittest.cc', 'trace_event/trace_config_memory_test_util.h', 'trace_event/trace_config_unittest.cc', @@ -91,5 +81,17 @@ 'trace_event/trace_event_win_unittest.cc', 'trace_event/winheap_dump_provider_win_unittest.cc', ], + 'conditions': [ + ['OS == "linux" or OS == "android"', { + 'trace_event_sources': [ + 'trace_event/malloc_dump_provider.cc', + 'trace_event/malloc_dump_provider.h', + 'trace_event/process_memory_maps_dump_provider.cc', + ], + 'trace_event_test_sources' : [ + 'trace_event/process_memory_maps_dump_provider_unittest.cc', + ], + }], + ], }, }
diff --git a/chrome/browser/android/favicon_helper.cc b/chrome/browser/android/favicon_helper.cc index 67f0c3ef..182348f 100644 --- a/chrome/browser/android/favicon_helper.cc +++ b/chrome/browser/android/favicon_helper.cc
@@ -31,8 +31,8 @@ #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/color_analysis.h" #include "ui/gfx/color_utils.h" -#include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gfx/image/image_skia_rep.h" using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; @@ -68,6 +68,16 @@ j_icon_url.obj()); } +size_t GetLargestSizeIndex(const std::vector<gfx::Size>& sizes) { + DCHECK(!sizes.empty()); + size_t ret = 0; + for (size_t i = 1; i < sizes.size(); ++i) { + if (sizes[ret].GetArea() < sizes[i].GetArea()) + ret = i; + } + return ret; +} + void OnFaviconDownloaded( const ScopedJavaGlobalRef<jobject>& j_availability_callback, Profile* profile, @@ -79,10 +89,9 @@ const std::vector<gfx::Size>& original_sizes) { bool success = !bitmaps.empty(); if (success) { - gfx::Image image = gfx::Image(CreateFaviconImageSkia(bitmaps, - original_sizes, - gfx::kFaviconSize, - nullptr)); + // Only keep the largest favicon available. + gfx::Image image = gfx::Image(gfx::ImageSkia( + gfx::ImageSkiaRep(bitmaps[GetLargestSizeIndex(original_sizes)], 0))); favicon_base::SetFaviconColorSpace(&image); favicon::FaviconService* service = FaviconServiceFactory::GetForProfile( profile, ServiceAccessType::IMPLICIT_ACCESS);
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc index aa7486c..3e28ea2 100644 --- a/chrome/browser/browser_shutdown.cc +++ b/chrome/browser/browser_shutdown.cc
@@ -19,6 +19,7 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "chrome/browser/about_flags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/lifetime/application_lifetime.h" @@ -30,6 +31,7 @@ #include "chrome/common/pref_names.h" #include "chrome/common/switch_utils.h" #include "components/metrics/metrics_service.h" +#include "components/tracing/tracing_switches.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" @@ -112,7 +114,7 @@ #if !defined(OS_CHROMEOS) // Start the shutdown tracing. Note that On ChromeOS this has already been // called in AttemptUserExit(). - chrome::StartShutdownTracing(); + StartShutdownTracing(); #endif g_shutdown_type = type; @@ -218,7 +220,7 @@ #if defined(OS_WIN) if (!browser_util::IsBrowserAlreadyRunning() && - g_shutdown_type != browser_shutdown::END_SESSION) { + g_shutdown_type != END_SESSION) { upgrade_util::SwapNewChromeExeIfPresent(); } #endif @@ -346,4 +348,17 @@ return g_trying_to_quit; } +void StartShutdownTracing() { + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kTraceShutdown)) { + base::trace_event::TraceConfig trace_config( + command_line.GetSwitchValueASCII(switches::kTraceShutdown), ""); + base::trace_event::TraceLog::GetInstance()->SetEnabled( + trace_config, + base::trace_event::TraceLog::RECORDING_MODE); + } + TRACE_EVENT0("shutdown", "StartShutdownTracing"); +} + } // namespace browser_shutdown
diff --git a/chrome/browser/browser_shutdown.h b/chrome/browser/browser_shutdown.h index 1d10200..080a4b1 100644 --- a/chrome/browser/browser_shutdown.h +++ b/chrome/browser/browser_shutdown.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_BROWSER_SHUTDOWN_H__ -#define CHROME_BROWSER_BROWSER_SHUTDOWN_H__ +#ifndef CHROME_BROWSER_BROWSER_SHUTDOWN_H_ +#define CHROME_BROWSER_BROWSER_SHUTDOWN_H_ class PrefRegistrySimple; @@ -68,6 +68,11 @@ // General accessor. bool IsTryingToQuit(); +// Starts to collect shutdown traces. On ChromeOS this will start immediately +// on AttemptUserExit() and all other systems will start once all tabs are +// closed. +void StartShutdownTracing(); + } // namespace browser_shutdown -#endif // CHROME_BROWSER_BROWSER_SHUTDOWN_H__ +#endif // CHROME_BROWSER_BROWSER_SHUTDOWN_H_
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index 1b6481f..1cd1713d 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -75,7 +75,6 @@ ::switches::kDisableAcceleratedVideoDecode, ::switches::kDisableBlinkFeatures, ::switches::kDisableCastStreamingHWEncoding, - ::switches::kDisableCompositorAnimationTimelines, ::switches::kDisableDistanceFieldText, ::switches::kDisableGpu, ::switches::kDisableGpuMemoryBufferVideoFrames, @@ -97,6 +96,7 @@ ::switches::kDisableTouchDragDrop, ::switches::kDisableZeroCopy, ::switches::kEnableBlinkFeatures, + ::switches::kEnableCompositorAnimationTimelines, ::switches::kDisableDisplayList2dCanvas, ::switches::kEnableDisplayList2dCanvas, ::switches::kForceDisplayList2dCanvas,
diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime.cc index 06a900869..448b492 100644 --- a/chrome/browser/lifetime/application_lifetime.cc +++ b/chrome/browser/lifetime/application_lifetime.cc
@@ -5,14 +5,12 @@ #include "chrome/browser/lifetime/application_lifetime.h" #include "base/bind.h" -#include "base/command_line.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/prefs/pref_service.h" #include "base/process/process.h" #include "base/process/process_handle.h" -#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" @@ -31,9 +29,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/user_manager.h" #include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" -#include "components/tracing/tracing_switches.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/notification_service.h" @@ -50,10 +46,6 @@ #include "base/win/win_util.h" #endif -#if defined(USE_ASH) -#include "ash/shell.h" -#endif - namespace chrome { namespace { @@ -148,7 +140,7 @@ void AttemptUserExit() { #if defined(OS_CHROMEOS) - StartShutdownTracing(); + browser_shutdown::StartShutdownTracing(); chromeos::BootTimesRecorder::Get()->AddLogoutTimeMarker("LogoutStarted", false); @@ -180,19 +172,6 @@ #endif } -void StartShutdownTracing() { - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kTraceShutdown)) { - base::trace_event::TraceConfig trace_config( - command_line.GetSwitchValueASCII(switches::kTraceShutdown), ""); - base::trace_event::TraceLog::GetInstance()->SetEnabled( - trace_config, - base::trace_event::TraceLog::RECORDING_MODE); - } - TRACE_EVENT0("shutdown", "StartShutdownTracing"); -} - // The Android implementation is in application_lifetime_android.cc #if !defined(OS_ANDROID) void AttemptRestart() { @@ -388,25 +367,6 @@ HandleAppExitingForPlatform(); } -bool ShouldStartShutdown(Browser* browser) { - if (BrowserList::GetInstance(browser->host_desktop_type())->size() > 1) - return false; -#if defined(OS_WIN) - // On Windows 8 the desktop and ASH environments could be active - // at the same time. - // We should not start the shutdown process in the following cases:- - // 1. If the desktop type of the browser going away is ASH and there - // are browser windows open in the desktop. - // 2. If the desktop type of the browser going away is desktop and the ASH - // environment is still active. - if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_NATIVE) - return !ash::Shell::HasInstance(); - else if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH) - return BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->empty(); -#endif - return true; -} - void DisableShutdownForTesting(bool disable_shutdown_for_testing) { g_disable_shutdown_for_testing = disable_shutdown_for_testing; if (!g_disable_shutdown_for_testing && !WillKeepAlive())
diff --git a/chrome/browser/lifetime/application_lifetime.h b/chrome/browser/lifetime/application_lifetime.h index 3cf1854..a0acd684 100644 --- a/chrome/browser/lifetime/application_lifetime.h +++ b/chrome/browser/lifetime/application_lifetime.h
@@ -18,11 +18,6 @@ // SIGTERM to start actual exit process. void AttemptUserExit(); -// Starts to collect shutdown traces. On ChromeOS this will start immediately -// on AttemptUserExit() and all other systems will start once all tabs are -// closed. -void StartShutdownTracing(); - // Starts a user initiated restart process. On platforms other than // chromeos, this sets a restart bit in the preference so that // chrome will be restarted at the end of shutdown process. On @@ -112,10 +107,6 @@ // processing required. void HandleAppExitingForPlatform(); -// Returns true if we can start the shutdown sequence for the browser, i.e. the -// last browser window is being closed. -bool ShouldStartShutdown(Browser* browser); - // Disable browser shutdown for unit tests. void DisableShutdownForTesting(bool disable_shutdown_for_testing);
diff --git a/chrome/browser/sync/glue/bookmark_change_processor.cc b/chrome/browser/sync/glue/bookmark_change_processor.cc index c93cb70..d612240 100644 --- a/chrome/browser/sync/glue/bookmark_change_processor.cc +++ b/chrome/browser/sync/glue/bookmark_change_processor.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/undo/bookmark_undo_service_factory.h" #include "components/bookmarks/browser/bookmark_client.h"
diff --git a/chrome/browser/sync/glue/bookmark_change_processor.h b/chrome/browser/sync/glue/bookmark_change_processor.h index 6ec5b5c..9c69cc5 100644 --- a/chrome/browser/sync/glue/bookmark_change_processor.h +++ b/chrome/browser/sync/glue/bookmark_change_processor.h
@@ -9,7 +9,6 @@ #include "base/compiler_specific.h" #include "chrome/browser/sync/glue/bookmark_model_associator.h" -#include "chrome/browser/sync/glue/sync_backend_host.h" #include "components/bookmarks/browser/bookmark_model_observer.h" #include "components/bookmarks/browser/bookmark_node.h" #include "components/sync_driver/change_processor.h"
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller.cc b/chrome/browser/sync/glue/bookmark_data_type_controller.cc index f2d687c..99a8073 100644 --- a/chrome/browser/sync/glue/bookmark_data_type_controller.cc +++ b/chrome/browser/sync/glue/bookmark_data_type_controller.cc
@@ -5,30 +5,22 @@ #include "chrome/browser/sync/glue/bookmark_data_type_controller.h" #include "base/metrics/histogram.h" -#include "chrome/browser/bookmarks/bookmark_model_factory.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/sync/glue/chrome_report_unrecoverable_error.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/history/core/browser/history_service.h" #include "components/sync_driver/sync_api_component_factory.h" #include "components/sync_driver/sync_client.h" -#include "content/public/browser/browser_thread.h" using bookmarks::BookmarkModel; -using content::BrowserThread; namespace browser_sync { BookmarkDataTypeController::BookmarkDataTypeController( + const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, + const base::Closure& error_callback, sync_driver::SyncClient* sync_client) - : FrontendDataTypeController( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - base::Bind(&ChromeReportUnrecoverableError), - sync_client), + : FrontendDataTypeController(ui_thread, error_callback, sync_client), history_service_observer_(this), - bookmark_model_observer_(this) { -} + bookmark_model_observer_(this) {} syncer::ModelType BookmarkDataTypeController::type() const { return syncer::BOOKMARKS; @@ -99,7 +91,6 @@ void BookmarkDataTypeController::OnHistoryServiceLoaded( history::HistoryService* service) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(state_, MODEL_STARTING); history_service_observer_.RemoveAll();
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller.h b/chrome/browser/sync/glue/bookmark_data_type_controller.h index 07c3843b..30d8cde0 100644 --- a/chrome/browser/sync/glue/bookmark_data_type_controller.h +++ b/chrome/browser/sync/glue/bookmark_data_type_controller.h
@@ -13,8 +13,6 @@ #include "components/history/core/browser/history_service_observer.h" #include "components/sync_driver/frontend_data_type_controller.h" -class ProfileSyncService; - namespace browser_sync { // A class that manages the startup and shutdown of bookmark sync. @@ -22,7 +20,10 @@ public bookmarks::BaseBookmarkModelObserver, public history::HistoryServiceObserver { public: - explicit BookmarkDataTypeController(sync_driver::SyncClient* sync_client); + BookmarkDataTypeController( + const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, + const base::Closure& error_callback, + sync_driver::SyncClient* sync_client); // FrontendDataTypeController: syncer::ModelType type() const override;
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc index 86f584c..7cd3b0a 100644 --- a/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc +++ b/chrome/browser/sync/glue/bookmark_data_type_controller_unittest.cc
@@ -113,7 +113,9 @@ profile_sync_factory_.reset( new ProfileSyncComponentsFactoryMock(model_associator_, change_processor_)); - bookmark_dtc_ = new BookmarkDataTypeController(this); + bookmark_dtc_ = + new BookmarkDataTypeController(base::ThreadTaskRunnerHandle::Get(), + base::Bind(&base::DoNothing), this); } protected:
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc index 9955676..5bb4f9a 100644 --- a/chrome/browser/sync/glue/bookmark_model_associator.cc +++ b/chrome/browser/sync/glue/bookmark_model_associator.cc
@@ -17,7 +17,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/thread_task_runner_handle.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/glue/bookmark_change_processor.h" #include "chrome/browser/undo/bookmark_undo_service_factory.h" #include "components/bookmarks/browser/bookmark_client.h"
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.cc b/chrome/browser/sync/profile_sync_components_factory_impl.cc index 207a0a7..098bb8a 100644 --- a/chrome/browser/sync/profile_sync_components_factory_impl.cc +++ b/chrome/browser/sync/profile_sync_components_factory_impl.cc
@@ -208,8 +208,9 @@ // Bookmark sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::BOOKMARKS)) { - sync_service->RegisterDataTypeController( - new BookmarkDataTypeController(sync_client)); + sync_service->RegisterDataTypeController(new BookmarkDataTypeController( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), + base::Bind(&ChromeReportUnrecoverableError), sync_client)); } const bool history_disabled =
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 24e66d5..584a1d6 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -219,6 +219,7 @@ #if defined(USE_ASH) #include "ash/ash_switches.h" +#include "ash/shell.h" #endif using base::TimeDelta; @@ -713,7 +714,7 @@ bool should_quit_if_last_browser = browser_shutdown::IsTryingToQuit() || !chrome::WillKeepAlive(); - if (should_quit_if_last_browser && chrome::ShouldStartShutdown(this)) + if (should_quit_if_last_browser && ShouldStartShutdown()) browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE); // Don't use GetForProfileIfExisting here, we want to force creation of the @@ -2601,6 +2602,25 @@ return window_ && window_->ShouldHideUIForFullscreen(); } +bool Browser::ShouldStartShutdown() const { + if (BrowserList::GetInstance(host_desktop_type())->size() > 1) + return false; +#if defined(OS_WIN) + // On Windows 8 the desktop and ASH environments could be active + // at the same time. + // We should not start the shutdown process in the following cases:- + // 1. If the desktop type of the browser going away is ASH and there + // are browser windows open in the desktop. + // 2. If the desktop type of the browser going away is desktop and the ASH + // environment is still active. + if (host_desktop_type() == chrome::HOST_DESKTOP_TYPE_NATIVE) + return !ash::Shell::HasInstance(); + if (host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH) + return BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->empty(); +#endif + return true; +} + bool Browser::MaybeCreateBackgroundContents( int route_id, int main_frame_route_id,
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index e296569..b421e4b 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -826,6 +826,10 @@ bool ShouldHideUIForFullscreen() const; + // Returns true if we can start the shutdown sequence for the browser, i.e. + // the last browser window is being closed. + bool ShouldStartShutdown() const; + // Creates a BackgroundContents if appropriate; return true if one was // created. bool MaybeCreateBackgroundContents(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 0f7b2378..dc03b79d 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1226,7 +1226,6 @@ switches::kDisableAcceleratedVideoDecode, switches::kDisableBlinkFeatures, switches::kDisableBreakpad, - switches::kDisableCompositorAnimationTimelines, switches::kDisablePreferCompositingToLCDText, switches::kDisableDatabases, switches::kDisableDelayAgnosticAec, @@ -1265,6 +1264,7 @@ switches::kDomAutomationController, switches::kEnableBlinkFeatures, switches::kEnableBrowserSideNavigation, + switches::kEnableCompositorAnimationTimelines, switches::kEnableCredentialManagerAPI, switches::kEnableDisplayList2dCanvas, switches::kEnableDistanceFieldText,
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 374f228..aa0cc6d9 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -83,10 +83,6 @@ // features. const char kDisableBlinkFeatures[] = "disable-blink-features"; -// Disables new cc/animation system (Project Heaviside). crbug.com/394772 -const char kDisableCompositorAnimationTimelines[] = - "disable-compositor-animation-timelines"; - // Disable the creation of compositing layers when it would prevent LCD text. const char kDisablePreferCompositingToLCDText[] = "disable-prefer-compositing-to-lcd-text"; @@ -293,6 +289,10 @@ const char kDisableAcceleratedJpegDecoding[] = "disable-accelerated-jpeg-decoding"; +// Enables new cc/animation system (Project Heaviside). crbug.com/394772 +const char kEnableCompositorAnimationTimelines[] = + "enable-compositor-animation-timelines"; + // Enables LCD text. const char kEnableLCDText[] = "enable-lcd-text";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index fb2b2d6..fe4a2fcd 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -28,13 +28,12 @@ CONTENT_EXPORT extern const char kDefaultTileHeight[]; CONTENT_EXPORT extern const char kDisable2dCanvasAntialiasing[]; CONTENT_EXPORT extern const char kDisable3DAPIs[]; +CONTENT_EXPORT extern const char kDisableBlinkFeatures[]; CONTENT_EXPORT extern const char kDisableAccelerated2dCanvas[]; CONTENT_EXPORT extern const char kDisableAcceleratedJpegDecoding[]; CONTENT_EXPORT extern const char kDisableAcceleratedMjpegDecode[]; CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[]; extern const char kDisableBackingStoreLimit[]; -CONTENT_EXPORT extern const char kDisableBlinkFeatures[]; -CONTENT_EXPORT extern const char kDisableCompositorAnimationTimelines[]; CONTENT_EXPORT extern const char kDisablePreferCompositingToLCDText[]; CONTENT_EXPORT extern const char kDisableDatabases[]; CONTENT_EXPORT extern const char kDisableDelayAgnosticAec[]; @@ -96,6 +95,7 @@ CONTENT_EXPORT extern const char kDomAutomationController[]; extern const char kEnable2dCanvasClipAntialiasing[]; CONTENT_EXPORT extern const char kEnableAggressiveDOMStorageFlushing[]; +CONTENT_EXPORT extern const char kEnableCompositorAnimationTimelines[]; CONTENT_EXPORT extern const char kEnableCredentialManagerAPI[]; CONTENT_EXPORT extern const char kEnablePreferCompositingToLCDText[]; CONTENT_EXPORT extern const char kEnableBlinkFeatures[];
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 04df33c0..2e97735 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -246,10 +246,10 @@ settings.accelerated_animation_enabled = compositor_deps_->IsThreadedAnimationEnabled(); - settings.use_compositor_animation_timelines = - !cmd->HasSwitch(switches::kDisableCompositorAnimationTimelines); - blink::WebRuntimeFeatures::enableCompositorAnimationTimelines( - settings.use_compositor_animation_timelines); + if (cmd->HasSwitch(switches::kEnableCompositorAnimationTimelines)) { + settings.use_compositor_animation_timelines = true; + blink::WebRuntimeFeatures::enableCompositorAnimationTimelines(true); + } settings.default_tile_size = CalculateDefaultTileSize(widget_); if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index a72214d..c8ca4bdb 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -653,8 +653,8 @@ *base::CommandLine::ForCurrentProcess(); cc::LayerSettings layer_settings; - layer_settings.use_compositor_animation_timelines = - !command_line.HasSwitch(switches::kDisableCompositorAnimationTimelines); + if (command_line.HasSwitch(switches::kEnableCompositorAnimationTimelines)) + layer_settings.use_compositor_animation_timelines = true; cc_blink::WebLayerImpl::SetLayerSettings(layer_settings); cc::SetClientNameForMetrics("Renderer");
diff --git a/ios/third_party/gcdwebserver/BUILD.gn b/ios/third_party/gcdwebserver/BUILD.gn new file mode 100644 index 0000000..da07148 --- /dev/null +++ b/ios/third_party/gcdwebserver/BUILD.gn
@@ -0,0 +1,59 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +config("public_config") { + ldflags = [ "-lz" ] + libs = [ + "CFNetwork.framework", + "MobileCoreServices.framework", + ] + include_dirs = [ + "src/GCDWebServer/Core", + "src/GCDWebServer/Requests", + "src/GCDWebServer/Responses", + ] +} + +config("internal_config") { + visibility = [ ":gcdwebserver" ] + cflags_objc = [ "-fobjc-arc" ] +} + +source_set("gcdwebserver") { + testonly = true + + sources = [ + "src/GCDWebServer/Core/GCDWebServer.h", + "src/GCDWebServer/Core/GCDWebServer.m", + "src/GCDWebServer/Core/GCDWebServerConnection.h", + "src/GCDWebServer/Core/GCDWebServerConnection.m", + "src/GCDWebServer/Core/GCDWebServerFunctions.h", + "src/GCDWebServer/Core/GCDWebServerFunctions.m", + "src/GCDWebServer/Core/GCDWebServerHTTPStatusCodes.h", + "src/GCDWebServer/Core/GCDWebServerPrivate.h", + "src/GCDWebServer/Core/GCDWebServerRequest.h", + "src/GCDWebServer/Core/GCDWebServerRequest.m", + "src/GCDWebServer/Core/GCDWebServerResponse.h", + "src/GCDWebServer/Core/GCDWebServerResponse.m", + "src/GCDWebServer/Requests/GCDWebServerDataRequest.h", + "src/GCDWebServer/Requests/GCDWebServerDataRequest.m", + "src/GCDWebServer/Requests/GCDWebServerFileRequest.h", + "src/GCDWebServer/Requests/GCDWebServerFileRequest.m", + "src/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.h", + "src/GCDWebServer/Requests/GCDWebServerMultiPartFormRequest.m", + "src/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.h", + "src/GCDWebServer/Requests/GCDWebServerURLEncodedFormRequest.m", + "src/GCDWebServer/Responses/GCDWebServerDataResponse.h", + "src/GCDWebServer/Responses/GCDWebServerDataResponse.m", + "src/GCDWebServer/Responses/GCDWebServerErrorResponse.h", + "src/GCDWebServer/Responses/GCDWebServerErrorResponse.m", + "src/GCDWebServer/Responses/GCDWebServerFileResponse.h", + "src/GCDWebServer/Responses/GCDWebServerFileResponse.m", + "src/GCDWebServer/Responses/GCDWebServerStreamedResponse.h", + "src/GCDWebServer/Responses/GCDWebServerStreamedResponse.m", + ] + + public_configs = [ ":public_config" ] + configs += [ ":internal_config" ] +}
diff --git a/ios/third_party/gcdwebserver/gcdwebserver.gyp b/ios/third_party/gcdwebserver/gcdwebserver.gyp index 117c6a2d..28f7738 100644 --- a/ios/third_party/gcdwebserver/gcdwebserver.gyp +++ b/ios/third_party/gcdwebserver/gcdwebserver.gyp
@@ -4,6 +4,7 @@ { 'targets' : [ { + # GN version: //ios/third_party/gcdwebserver 'target_name' : 'gcdwebserver', 'type': 'static_library', 'include_dirs': [
diff --git a/media/midi/midi_message_queue.cc b/media/midi/midi_message_queue.cc index d35acc2..20fcc87 100644 --- a/media/midi/midi_message_queue.cc +++ b/media/midi/midi_message_queue.cc
@@ -20,10 +20,6 @@ return (data & 0x80) == 0; } -bool IsFirstStatusByte(uint8 data) { - return !IsDataByte(data) && data != kEndOfSysEx; -} - bool IsSystemRealTimeMessage(uint8 data) { return 0xf8 <= data; } @@ -51,74 +47,79 @@ message->clear(); while (true) { + // Check if |next_message_| is already a complete MIDI message or not. + if (!next_message_.empty()) { + const uint8 status_byte = next_message_.front(); + const size_t target_len = GetMidiMessageLength(status_byte); + if (target_len == 0) { + DCHECK_EQ(kSysEx, status_byte); + if (next_message_.back() == kEndOfSysEx) { + // OK, this is a complete SysEx message. + std::swap(*message, next_message_); + DCHECK(next_message_.empty()); + return; + } + } else if (next_message_.size() == target_len) { + // OK, this is a complete non-SysEx message. + std::swap(*message, next_message_); + DCHECK(next_message_.empty()); + if (allow_running_status_ && !IsSystemMessage(status_byte)) { + // Speculatively keep the status byte in case of running status. + // If this assumption is not true, |next_message_| will be cleared + // anyway. Note that system common messages should reset the + // running status. + next_message_.push_back(status_byte); + } + return; + } else if (next_message_.size() > target_len) { + NOTREACHED(); + } + } + if (queue_.empty()) return; - const uint8 next = queue_.front(); - queue_.pop_front(); - - // "System Real Time Messages" is a special kind of MIDI messages, which can - // appear at arbitrary byte position of MIDI stream. Here we reorder + // "System Real Time Messages" is a special MIDI message, which can appear + // at an arbitrary byte position of MIDI stream. Here we reorder // "System Real Time Messages" prior to |next_message_| so that each message // can be clearly separated as a complete MIDI message. + const uint8 next = queue_.front(); if (IsSystemRealTimeMessage(next)) { message->push_back(next); + queue_.pop_front(); return; } - // Here |next_message_[0]| may contain the previous status byte when - // |allow_running_status_| is true. Following condition fixes up - // |next_message_| if running status condition is not fulfilled. - if (!next_message_.empty() && - ((next_message_[0] == kSysEx && IsFirstStatusByte(next)) || - (next_message_[0] != kSysEx && !IsDataByte(next)))) { - // An invalid data sequence is found or running status condition is not - // fulfilled. - next_message_.clear(); - } - if (next_message_.empty()) { - if (IsFirstStatusByte(next)) { + const size_t target_len = GetMidiMessageLength(next); + // If |target_len| is zero, it means either |next| is not a valid status + // byte or |next| is a valid status byte but the message length is + // unpredictable. For the latter case, only SysEx can be accepted. + if (target_len > 0 || next == kSysEx) { next_message_.push_back(next); - } else { - // MIDI protocol doesn't provide any error correction mechanism in - // physical layers, and incoming messages can be corrupted, and should - // be corrected here. } + // Consume |next| always, since if |next| isn't status byte, which means + // that |next| is just corrupted data, or a data byte followed by + // reserved message, which we are unable to understand and deal with + // anyway. + queue_.pop_front(); continue; } - // Here we can assume |next_message_| starts with a valid status byte. - const uint8 status_byte = next_message_[0]; - next_message_.push_back(next); + const uint8 status_byte = next_message_.front(); - if (status_byte == kSysEx) { - if (next == kEndOfSysEx) { - std::swap(*message, next_message_); - next_message_.clear(); - return; - } - continue; - } - - DCHECK(IsDataByte(next)); - DCHECK_NE(kSysEx, status_byte); - const size_t target_len = GetMidiMessageLength(status_byte); - if (next_message_.size() < target_len) - continue; - if (next_message_.size() == target_len) { - std::swap(*message, next_message_); + // If we receive a new non-data byte before completing the pending message, + // drop the pending message and respin the loop to re-evaluate |next|. + // This also clears the running status byte speculatively added above, as + // well as any broken incomplete messages. + if (!IsDataByte(next) && !(status_byte == kSysEx && next == kEndOfSysEx)) { next_message_.clear(); - if (allow_running_status_ && !IsSystemMessage(status_byte)) { - // Speculatively keep the status byte in case of running status. If this - // assumption is not true, |next_message_| will be cleared anyway. - // Note that system common messages should reset the running status. - next_message_.push_back(status_byte); - } - return; + continue; } - NOTREACHED(); + // OK to consume this byte. + next_message_.push_back(next); + queue_.pop_front(); } }
diff --git a/media/midi/midi_message_queue_unittest.cc b/media/midi/midi_message_queue_unittest.cc index d25a692..4abdc5b 100644 --- a/media/midi/midi_message_queue_unittest.cc +++ b/media/midi/midi_message_queue_unittest.cc
@@ -11,10 +11,17 @@ namespace { const uint8 kGMOn[] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 }; +const uint8 kPartialGMOn1st[] = { 0xf0 }; +const uint8 kPartialGMOn2nd[] = { 0x7e, 0x7f, 0x09, 0x01 }; +const uint8 kPartialGMOn3rd[] = { 0xf7 }; const uint8 kGSOn[] = { 0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7, }; const uint8 kNoteOn[] = { 0x90, 0x3c, 0x7f }; +const uint8 kPartialNoteOn1st[] = { 0x90 }; +const uint8 kPartialNoteOn2nd[] = { 0x3c }; +const uint8 kPartialNoteOn3rd[] = { 0x7f }; + const uint8 kNoteOnWithRunningStatus[] = { 0x90, 0x3c, 0x7f, 0x3c, 0x7f, 0x3c, 0x7f, }; @@ -23,12 +30,19 @@ 0xd0, 0x01, 0x01, 0x01, }; const uint8 kTimingClock[] = { 0xf8 }; +const uint8 kSystemCommonMessageTuneRequest[] = { 0xf6 }; const uint8 kMTCFrame[] = { 0xf1, 0x00 }; -const uint8 kBrokenData1[] = { 0x90 }; +const uint8 kBrokenData1[] = { 0x92 }; const uint8 kBrokenData2[] = { 0xf7 }; const uint8 kBrokenData3[] = { 0xf2, 0x00 }; const uint8 kDataByte0[] = { 0x00 }; +const uint8 kReservedMessage1[] = { 0xf4 }; +const uint8 kReservedMessage2[] = { 0xf5 }; +const uint8 kReservedMessage1WithDataBytes[] = { + 0xf4, 0x01, 0x01, 0x01, 0x01, 0x01 +}; + template <typename T, size_t N> void Add(MidiMessageQueue* queue, const T(&array)[N]) { queue->Add(array, N); @@ -190,6 +204,369 @@ EXPECT_TRUE(message.empty()); } +TEST(MidiMessageQueueTest, Issue540016) { + const uint8 kData[] = { 0xf4, 0x3a }; + MidiMessageQueue queue(false); + Add(&queue, kData); + std::vector<uint8> message; + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, ReconstructNonSysExMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + Add(&queue, kPartialNoteOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialNoteOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialNoteOn3rd); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, ReconstructBrokenNonSysExMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + Add(&queue, kPartialNoteOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialNoteOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialGMOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialNoteOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, ReconstructSysExMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + Add(&queue, kPartialGMOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialGMOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialGMOn3rd); + queue.Get(&message); + EXPECT_MESSAGE(kGMOn, message); + + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, ReconstructBrokenSysExMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + Add(&queue, kPartialGMOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialGMOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialNoteOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialGMOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, OneByteMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + Add(&queue, kSystemCommonMessageTuneRequest); + Add(&queue, kSystemCommonMessageTuneRequest); + Add(&queue, kSystemCommonMessageTuneRequest); + Add(&queue, kSystemCommonMessageTuneRequest); + Add(&queue, kNoteOn); + Add(&queue, kSystemCommonMessageTuneRequest); + Add(&queue, kNoteOn); + Add(&queue, kNoteOn); + Add(&queue, kSystemCommonMessageTuneRequest); + + queue.Get(&message); + EXPECT_MESSAGE(kSystemCommonMessageTuneRequest, message); + queue.Get(&message); + EXPECT_MESSAGE(kSystemCommonMessageTuneRequest, message); + queue.Get(&message); + EXPECT_MESSAGE(kSystemCommonMessageTuneRequest, message); + queue.Get(&message); + EXPECT_MESSAGE(kSystemCommonMessageTuneRequest, message); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_MESSAGE(kSystemCommonMessageTuneRequest, message); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_MESSAGE(kSystemCommonMessageTuneRequest, message); + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, OneByteMessageInjectedInNonSysExMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + Add(&queue, kPartialNoteOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialNoteOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kSystemCommonMessageTuneRequest); + queue.Get(&message); + EXPECT_MESSAGE(kSystemCommonMessageTuneRequest, message); + + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialNoteOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, OneByteMessageInjectedInSysExMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + Add(&queue, kPartialGMOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialGMOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kSystemCommonMessageTuneRequest); + queue.Get(&message); + EXPECT_MESSAGE(kSystemCommonMessageTuneRequest, message); + + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kPartialGMOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, ReservedMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + Add(&queue, kReservedMessage1); + Add(&queue, kNoteOn); + Add(&queue, kReservedMessage2); + Add(&queue, kNoteOn); + Add(&queue, kReservedMessage1WithDataBytes); + Add(&queue, kNoteOn); + Add(&queue, kReservedMessage2); + Add(&queue, kReservedMessage1WithDataBytes); + Add(&queue, kNoteOn); + Add(&queue, kReservedMessage1WithDataBytes); + Add(&queue, kReservedMessage2); + Add(&queue, kNoteOn); + + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + + Add(&queue, kReservedMessage1); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kNoteOn); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kReservedMessage2); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kNoteOn); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kReservedMessage1WithDataBytes); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kNoteOn); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kReservedMessage2); + Add(&queue, kReservedMessage1WithDataBytes); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kNoteOn); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kReservedMessage1WithDataBytes); + Add(&queue, kReservedMessage2); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + Add(&queue, kNoteOn); + queue.Get(&message); + EXPECT_MESSAGE(kNoteOn, message); + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, ReservedMessageInjectedInNonSysExMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + // Inject |kReservedMessage1| + Add(&queue, kPartialNoteOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialNoteOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kReservedMessage1); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialNoteOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + // Inject |kReservedMessage2| + Add(&queue, kPartialNoteOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialNoteOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kReservedMessage2); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialNoteOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + // Inject |kReservedMessage1WithDataBytes| + Add(&queue, kPartialNoteOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialNoteOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kReservedMessage1WithDataBytes); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialNoteOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + +TEST(MidiMessageQueueTest, ReservedMessageInjectedInSysExMessage) { + MidiMessageQueue queue(true); + std::vector<uint8> message; + + // Inject |kReservedMessage1| + Add(&queue, kPartialGMOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialGMOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kReservedMessage1); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialGMOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + // Inject |kReservedMessage2| + Add(&queue, kPartialGMOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialGMOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kReservedMessage2); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialGMOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + + // Inject |kReservedMessage1WithDataBytes| + Add(&queue, kPartialGMOn1st); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialGMOn2nd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kReservedMessage1WithDataBytes); + queue.Get(&message); + EXPECT_TRUE(message.empty()); + Add(&queue, kPartialGMOn3rd); + queue.Get(&message); + EXPECT_TRUE(message.empty()); +} + } // namespace } // namespace midi } // namespace media
diff --git a/media/midi/midi_message_util.cc b/media/midi/midi_message_util.cc index e8e953d..e329ac3c 100644 --- a/media/midi/midi_message_util.cc +++ b/media/midi/midi_message_util.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/logging.h" #include "media/midi/midi_message_util.h" namespace media { @@ -16,20 +17,36 @@ return 2; if (0xe0 <= status_byte && status_byte <= 0xef) return 3; - if (status_byte == 0xf0) - return 0; - if (status_byte == 0xf1) - return 2; - if (status_byte == 0xf2) - return 3; - if (status_byte == 0xf3) - return 2; - if (0xf4 <= status_byte && status_byte <= 0xf6) - return 1; - if (status_byte == 0xf7) - return 0; - // 0xf8 <= status_byte && status_byte <= 0xff - return 1; + + switch (status_byte) { + case 0xf0: + return 0; + case 0xf1: + return 2; + case 0xf2: + return 3; + case 0xf3: + return 2; + case 0xf4: // Reserved + case 0xf5: // Reserved + return 0; + case 0xf6: + return 1; + case 0xf7: + return 0; + case 0xf8: + case 0xf9: + case 0xfa: + case 0xfb: + case 0xfc: + case 0xfd: + case 0xfe: + case 0xff: + return 1; + default: + NOTREACHED(); + return 0; + } } } // namespace midi
diff --git a/media/midi/midi_message_util.h b/media/midi/midi_message_util.h index 6533ab3..851b65c9 100644 --- a/media/midi/midi_message_util.h +++ b/media/midi/midi_message_util.h
@@ -17,8 +17,9 @@ // Returns the length of a MIDI message in bytes. Never returns 4 or greater. // Returns 0 if |status_byte| is: // - not a valid status byte, namely data byte. -// - the MIDI System Exclusive message. -// - the End of System Exclusive message. +// - MIDI System Exclusive message. +// - End of System Exclusive message. +// - Reserved System Common Message (0xf4, 0xf5) MIDI_EXPORT size_t GetMidiMessageLength(uint8 status_byte); const uint8 kSysExByte = 0xf0;
diff --git a/media/midi/midi_message_util_unittest.cc b/media/midi/midi_message_util_unittest.cc index 25dbf5e..cb284af9 100644 --- a/media/midi/midi_message_util_unittest.cc +++ b/media/midi/midi_message_util_unittest.cc
@@ -12,19 +12,28 @@ const uint8 kGMOn[] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 }; const uint8 kNoteOn[] = { 0x90, 0x3c, 0x7f }; +const uint8 kSystemCommonMessageReserved1[] = { 0xf4 }; +const uint8 kSystemCommonMessageReserved2[] = { 0xf5 }; +const uint8 kSystemCommonMessageTuneRequest[] = { 0xf6 }; const uint8 kChannelPressure[] = { 0xd0, 0x01 }; const uint8 kTimingClock[] = { 0xf8 }; -TEST(GetMidiMessageLengthTest, BasicTest) { +TEST(MidiMessageUtilTest, GetMidiMessageLength) { // Check basic functionarity EXPECT_EQ(arraysize(kNoteOn), GetMidiMessageLength(kNoteOn[0])); EXPECT_EQ(arraysize(kChannelPressure), GetMidiMessageLength(kChannelPressure[0])); EXPECT_EQ(arraysize(kTimingClock), GetMidiMessageLength(kTimingClock[0])); + EXPECT_EQ(arraysize(kSystemCommonMessageTuneRequest), + GetMidiMessageLength(kSystemCommonMessageTuneRequest[0])); // SysEx message should be mapped to 0-length EXPECT_EQ(0u, GetMidiMessageLength(kGMOn[0])); + // Any reserved message should be mapped to 0-length + EXPECT_EQ(0u, GetMidiMessageLength(kSystemCommonMessageReserved1[0])); + EXPECT_EQ(0u, GetMidiMessageLength(kSystemCommonMessageReserved2[0])); + // Any data byte should be mapped to 0-length EXPECT_EQ(0u, GetMidiMessageLength(kGMOn[1])); EXPECT_EQ(0u, GetMidiMessageLength(kNoteOn[1]));
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 7841a9b..5cf89ba 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -247,7 +247,8 @@ crbug.com/418091 [ SnowLeopard Debug ] inspector/elements/bidi-dom-tree.html [ Pass Crash ] crbug.com/449242 [ SnowLeopard Debug ] fast/css/word-spacing-characters-complex-text.html [ Pass Crash ] crbug.com/419696 [ Mac Debug ] fast/text/font-linux-normalize.html [ Crash Pass ] - +crbug.com/423739 fast/js/string-replace-2.html [ NeedsManualRebaseline ] +crbug.com/423739 fast/dom/Window/Location/location-override-valueOf.html [ NeedsManualRebaseline ] crbug.com/524859 fast/text/complex-text-opacity.html [ NeedsManualRebaseline ] # crbug.com/498021 [ Linux ] fast/text/complex-text-opacity.html [ ImageOnlyFailure ] # crbug.com/509025 [ Yosemite ] fast/text/complex-text-opacity.html [ Failure ] @@ -460,6 +461,11 @@ crbug.com/380217 [ Linux Win ] fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-large-radius.html [ Skip ] crbug.com/380217 [ Win ] fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-bottom-left.html [ Skip ] +crbug.com/533448 svg/W3C-SVG-1.1/text-align-06-b.svg [ NeedsRebaseline ] +crbug.com/533448 [ Linux Mac Win7 ] svg/batik/text/verticalText.svg [ NeedsRebaseline ] +crbug.com/533448 svg/batik/text/verticalTextOnPath.svg [ NeedsRebaseline ] +crbug.com/533448 svg/text/text-selection-align-06-b.svg [ NeedsRebaseline ] + crbug.com/405389 imported/csswg-test/css-shapes-1/shape-outside/supported-shapes/polygon/shape-outside-polygon-017.html [ ImageOnlyFailure ] crbug.com/424365 imported/csswg-test/css-shapes-1/shape-outside/shape-image/shape-image-010.html [ ImageOnlyFailure ] crbug.com/424365 imported/csswg-test/css-shapes-1/shape-outside/shape-image/shape-image-024.html [ ImageOnlyFailure ]
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt index f4d76ed2..975207b 100644 --- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -298,7 +298,7 @@ word-break: normal word-spacing: 0px word-wrap: normal -writing-mode: lr-tb +writing-mode: horizontal-tb x: 0px y: 0px z-index: auto
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt index e2d96f7..dd20990 100644 --- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -298,7 +298,7 @@ word-break: normal word-spacing: 0px word-wrap: normal -writing-mode: lr-tb +writing-mode: horizontal-tb x: 0px y: 0px z-index: auto
diff --git a/third_party/WebKit/LayoutTests/fast/selectors/style-sharing-attribute-selector-expected.txt b/third_party/WebKit/LayoutTests/fast/selectors/style-sharing-attribute-selector-expected.txt new file mode 100644 index 0000000..b7da77e --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/selectors/style-sharing-attribute-selector-expected.txt
@@ -0,0 +1,14 @@ +Style sharing based on attribute selectors + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +Attribute selector in nested functional syntax +PASS getComputedStyle(firstDiv).color is black +PASS getComputedStyle(secondDiv).color is green +PASS internals.isSharingStyle(firstDiv, secondDiv) is false +PASS successfullyParsed is true + +TEST COMPLETE +This text should be black +This text should be green
diff --git a/third_party/WebKit/LayoutTests/fast/selectors/style-sharing-attribute-selector.html b/third_party/WebKit/LayoutTests/fast/selectors/style-sharing-attribute-selector.html new file mode 100644 index 0000000..8a5354ba --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/selectors/style-sharing-attribute-selector.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<script src="../../resources/js-test.js"></script> +<style> + #t1 > :-webkit-any(:not([myattr])) { color: green } +</style> +<div id="t1"> + <div myattr>This text should be black</div> + <div>This text should be green</div> +</div> +<script> +description("Style sharing based on attribute selectors"); + +var black = "rgb(0, 0, 0)"; +var green = "rgb(0, 128, 0)"; + + +debug("Attribute selector in nested functional syntax"); + +var firstDiv = t1.querySelector("div"); +var secondDiv = t1.querySelector("div+div"); + +shouldBe("getComputedStyle(firstDiv).color", "black"); +shouldBe("getComputedStyle(secondDiv).color", "green"); +if (window.internals) + shouldBeFalse("internals.isSharingStyle(firstDiv, secondDiv)"); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/prefixed-parsing.html b/third_party/WebKit/LayoutTests/fast/writing-mode/prefixed-parsing.html index 2be29cd..630bbd0 100644 --- a/third_party/WebKit/LayoutTests/fast/writing-mode/prefixed-parsing.html +++ b/third_party/WebKit/LayoutTests/fast/writing-mode/prefixed-parsing.html
@@ -35,6 +35,22 @@ <div style="unicode-bidi: -webkit-plaintext" data-expected="plaintext"></div> </div> +<div data-property="writingMode"> + <div title="Initial value of writingMode" data-expected="horizontal-tb"></div> + <div style="-webkit-writing-mode: vertical-lr" data-expected="vertical-lr"> + <div style="-webkit-writing-mode: horizontal-tb" data-expected="horizontal-tb"></div> + </div> + <div style="-webkit-writing-mode: vertical-rl" data-expected="vertical-rl"></div> +</div> + +<div data-property="webkitWritingMode"> + <div title="Initial value of webkitWritingMode" data-expected="horizontal-tb"></div> + <div style="writing-mode: vertical-lr" data-expected="vertical-lr"> + <div style="writing-mode: horizontal-tb" data-expected="horizontal-tb"></div> + </div> + <div style="writing-mode: vertical-rl" data-expected="vertical-rl"></div> +</div> + <script> Array.prototype.forEach.call(document.querySelectorAll("[data-property]"), function (element) { var property = element.dataset.property;
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-001-expected.txt b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-001-expected.txt deleted file mode 100644 index d094d13c..0000000 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-001-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This is a testharness.js-based test. -FAIL writing-mode initial value assert_equals: expected "horizontal-tb" but got "lr-tb" -FAIL -webkit-writing-mode: vertical-rl assert_equals: expected "vertical-rl" but got "lr-tb" -FAIL -webkit-writing-mode: vertical-lr assert_equals: expected "vertical-lr" but got "lr-tb" -FAIL writing-mode should inherit assert_equals: expected "vertical-rl" but got "lr-tb" -FAIL -webkit-writing-mode: horizontal-tb assert_equals: expected "horizontal-tb" but got "lr-tb" -FAIL -webkit-writing-mode: initial assert_equals: expected "horizontal-tb" but got "lr-tb" -FAIL -webkit-writing-mode: inherit assert_equals: expected "vertical-rl" but got "lr-tb" -FAIL -webkit-writing-mode: foo assert_equals: expected "vertical-rl" but got "lr-tb" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-sideways-lr-001-expected.txt b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-sideways-lr-001-expected.txt index 7274ec7..c44a99aa 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-sideways-lr-001-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-sideways-lr-001-expected.txt
@@ -1,4 +1,4 @@ This is a testharness.js-based test. -FAIL -webkit-writing-mode: sideways-lr assert_equals: expected "sideways-lr" but got "lr-tb" +FAIL -webkit-writing-mode: sideways-lr assert_equals: expected "sideways-lr" but got "horizontal-tb" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-sideways-rl-001-expected.txt b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-sideways-rl-001-expected.txt index 4a139fe9..9f630972 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-sideways-rl-001-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-sideways-rl-001-expected.txt
@@ -1,4 +1,4 @@ This is a testharness.js-based test. -FAIL -webkit-writing-mode: sideways-rl assert_equals: expected "sideways-rl" but got "lr-tb" +FAIL -webkit-writing-mode: sideways-rl assert_equals: expected "sideways-rl" but got "horizontal-tb" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-svg1-001-expected.txt b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-svg1-001-expected.txt index 8001b3e..d18fccf 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-svg1-001-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-svg1-001-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. -FAIL -webkit-writing-mode: lr assert_equals: expected "lr" but got "lr-tb" -FAIL -webkit-writing-mode: rl assert_equals: expected "rl" but got "lr-tb" -FAIL -webkit-writing-mode: tb assert_equals: expected "tb" but got "lr-tb" +FAIL -webkit-writing-mode: lr assert_equals: expected "lr" but got "horizontal-tb" +FAIL -webkit-writing-mode: rl assert_equals: expected "rl" but got "horizontal-tb" +FAIL -webkit-writing-mode: tb assert_equals: expected "tb" but got "horizontal-tb" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-svg1-002-expected.txt b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-svg1-002-expected.txt index 3a55955..ba354b2 100644 --- a/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-svg1-002-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/csswg-test/css-writing-modes-3/writing-mode-parsing-svg1-002-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. -PASS -webkit-writing-mode: lr-tb -FAIL -webkit-writing-mode: rl-tb assert_equals: expected "rl-tb" but got "lr-tb" -FAIL -webkit-writing-mode: tb-rl assert_equals: expected "tb-rl" but got "lr-tb" +FAIL -webkit-writing-mode: lr-tb assert_equals: expected "lr-tb" but got "horizontal-tb" +FAIL -webkit-writing-mode: rl-tb assert_equals: expected "rl-tb" but got "horizontal-tb" +FAIL -webkit-writing-mode: tb-rl assert_equals: expected "tb-rl" but got "horizontal-tb" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt b/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt index 9b31585..a6f751d3 100644 --- a/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
@@ -298,7 +298,7 @@ word-break: normal word-spacing: 0px word-wrap: normal -writing-mode: lr-tb +writing-mode: horizontal-tb x: 0px y: 0px z-index: auto
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h index ede7402..cfaa62d 100644 --- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h +++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -2679,8 +2679,14 @@ ASSERT(isValueID()); switch (m_value.valueID) { case CSSValueHorizontalTb: + case CSSValueLr: + case CSSValueLrTb: + case CSSValueRl: + case CSSValueRlTb: return TopToBottomWritingMode; case CSSValueVerticalRl: + case CSSValueTb: + case CSSValueTbRl: return RightToLeftWritingMode; case CSSValueVerticalLr: return LeftToRightWritingMode; @@ -4128,56 +4134,6 @@ return TA_START; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(SVGWritingMode e) - : CSSValue(PrimitiveClass) -{ - init(UnitType::ValueID); - switch (e) { - case WM_LRTB: - m_value.valueID = CSSValueLrTb; - break; - case WM_LR: - m_value.valueID = CSSValueLr; - break; - case WM_RLTB: - m_value.valueID = CSSValueRlTb; - break; - case WM_RL: - m_value.valueID = CSSValueRl; - break; - case WM_TBRL: - m_value.valueID = CSSValueTbRl; - break; - case WM_TB: - m_value.valueID = CSSValueTb; - break; - } -} - -template<> inline CSSPrimitiveValue::operator SVGWritingMode() const -{ - ASSERT(isValueID()); - switch (m_value.valueID) { - case CSSValueLrTb: - return WM_LRTB; - case CSSValueLr: - return WM_LR; - case CSSValueRlTb: - return WM_RLTB; - case CSSValueRl: - return WM_RL; - case CSSValueTbRl: - return WM_TBRL; - case CSSValueTb: - return WM_TB; - default: - break; - } - - ASSERT_NOT_REACHED(); - return WM_LRTB; -} - template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EVectorEffect e) : CSSValue(PrimitiveClass) {
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in index 2a13af6f..f94f37f 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.in +++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -97,6 +97,7 @@ -webkit-locale inherited, custom_value text-orientation inherited, custom_value -webkit-text-orientation inherited, custom_value +writing-mode inherited, custom_value -webkit-writing-mode inherited, custom_value text-rendering inherited, font, type_name=TextRenderingMode zoom custom_all @@ -396,7 +397,6 @@ word-spacing interpolable, inherited, initial=initialLetterWordSpacing, converter=convertSpacing // UAs must treat 'word-wrap' as an alternate name for the 'overflow-wrap' property. So using the same handlers. word-wrap inherited, name_for_methods=OverflowWrap -writing-mode inherited, svg, type_name=SVGWritingMode z-index interpolable, type_name=int, custom_all // Non-standard direction aware properties
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp index 152de0b..ee540e2a 100644 --- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp +++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -2340,6 +2340,7 @@ } case CSSPropertyPointerEvents: return cssValuePool().createValue(style.pointerEvents()); + case CSSPropertyWritingMode: case CSSPropertyWebkitWritingMode: return cssValuePool().createValue(style.writingMode()); case CSSPropertyWebkitTextCombine: @@ -2563,8 +2564,6 @@ return CSSPrimitiveValue::create(svgStyle.dominantBaseline()); case CSSPropertyTextAnchor: return CSSPrimitiveValue::create(svgStyle.textAnchor()); - case CSSPropertyWritingMode: - return CSSPrimitiveValue::create(svgStyle.writingMode()); case CSSPropertyClipPath: if (!svgStyle.clipperResource().isEmpty()) return CSSURIValue::create(serializeAsFragmentIdentifier(svgStyle.clipperResource()));
diff --git a/third_party/WebKit/Source/core/css/RuleSet.cpp b/third_party/WebKit/Source/core/css/RuleSet.cpp index b0572ea0..54db1e85 100644 --- a/third_party/WebKit/Source/core/css/RuleSet.cpp +++ b/third_party/WebKit/Source/core/css/RuleSet.cpp
@@ -50,16 +50,16 @@ // ----------------------------------------------------------------- +static bool containsUncommonAttributeSelector(const CSSSelector&); + static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector) { const CSSSelectorList* selectorList = selector->selectorList(); if (!selectorList) return false; for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) { - for (const CSSSelector* component = selector; component; component = component->tagHistory()) { - if (component->isAttributeSelector()) - return true; - } + if (containsUncommonAttributeSelector(*selector)) + return true; } return false; } @@ -70,7 +70,7 @@ return attribute == typeAttr || attribute == readonlyAttr; } -static inline bool containsUncommonAttributeSelector(const CSSSelector& selector) +static bool containsUncommonAttributeSelector(const CSSSelector& selector) { const CSSSelector* current = &selector; for (; current; current = current->tagHistory()) {
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp index 2ffe6bc..b40d7b9 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp +++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
@@ -609,7 +609,7 @@ const unsigned size = shorthand.length(); // Begin by collecting the properties into a vector. - WillBeHeapVector<const CSSValue*> values(size); + WillBeHeapVector<RawPtrWillBeMember<const CSSValue>> values(size); // If the below loop succeeds, there should always be at minimum 1 layer. size_t numLayers = 1U; @@ -662,7 +662,7 @@ ASSERT(shorthand.properties()[propertyIndex + 1] == CSSPropertyBackgroundRepeatY || shorthand.properties()[propertyIndex + 1] == CSSPropertyWebkitMaskRepeatY); const CSSValue* yValue = values[propertyIndex + 1]->isValueList() ? - toCSSValueList(values[propertyIndex + 1])->item(layer) : values[propertyIndex + 1]; + toCSSValueList(values[propertyIndex + 1])->item(layer) : values[propertyIndex + 1].get(); // FIXME: At some point we need to fix this code to avoid returning an invalid shorthand,
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp index 7596cee..104d718 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp
@@ -690,7 +690,9 @@ case CSSPropertyWebkitWritingMode: return valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt; case CSSPropertyWritingMode: - return valueID == CSSValueLrTb || valueID == CSSValueRlTb || valueID == CSSValueTbRl + return valueID == CSSValueHorizontalTb + || valueID == CSSValueVerticalRl || valueID == CSSValueVerticalLr + || valueID == CSSValueLrTb || valueID == CSSValueRlTb || valueID == CSSValueTbRl || valueID == CSSValueLr || valueID == CSSValueRl || valueID == CSSValueTb; case CSSPropertyWhiteSpace: // normal | pre | nowrap return valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap;
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSPropertyPriority.h b/third_party/WebKit/Source/core/css/resolver/CSSPropertyPriority.h index f9894b24..58a6fbb7 100644 --- a/third_party/WebKit/Source/core/css/resolver/CSSPropertyPriority.h +++ b/third_party/WebKit/Source/core/css/resolver/CSSPropertyPriority.h
@@ -41,7 +41,7 @@ template<> inline CSSPropertyID CSSPropertyPriorityData<HighPropertyPriority>::last() { - static_assert(CSSPropertyZoom == CSSPropertyColor + 18, "CSSPropertyZoom should be the end of the high priority property range"); + static_assert(CSSPropertyZoom == CSSPropertyColor + 19, "CSSPropertyZoom should be the end of the high priority property range"); static_assert(CSSPropertyTextRendering == CSSPropertyZoom - 1, "CSSPropertyTextRendering should be immediately before CSSPropertyZoom"); return CSSPropertyZoom; }
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp index 979f32cc..5791ab7 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -803,6 +803,11 @@ state.document().setHasAnnotatedRegions(true); } +void StyleBuilderFunctions::applyValueCSSPropertyWritingMode(StyleResolverState& state, CSSValue* value) +{ + state.setWritingMode(*toCSSPrimitiveValue(value)); +} + void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(StyleResolverState& state, CSSValue* value) { state.setWritingMode(*toCSSPrimitiveValue(value));
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp index 02b6ce1..d2cf3d5b 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.cpp +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -2489,7 +2489,7 @@ { ASSERT(m_frame == m_frame->localFrameRoot()); - WillBeHeapVector<LocalFrame*> newHoverFrameChain; + WillBeHeapVector<RawPtrWillBeMember<LocalFrame>> newHoverFrameChain; LocalFrame* newHoverFrameInDocument = innerElement ? innerElement->document().frame() : nullptr; // Insert the ancestors of the frame having the new hovered node to the frame chain // The frame chain doesn't include the main frame to avoid the redundant work that cleans the hover state. @@ -2549,7 +2549,7 @@ // - Dispatch mouseover/mouseenter events of the entered frames into the inside. // Insert the ancestors of the frame having the new target node to the entered frame chain - WillBeHeapVector<LocalFrame*> enteredFrameChain; + WillBeHeapVector<RawPtrWillBeMember<LocalFrame>> enteredFrameChain; LocalFrame* enteredFrameInDocument = targetedEvent.hitTestResult().innerNodeFrame(); while (enteredFrameInDocument) { enteredFrameChain.append(enteredFrameInDocument); @@ -2559,7 +2559,7 @@ size_t indexEnteredFrameChain = enteredFrameChain.size(); LocalFrame* exitedFrameInDocument = m_frame; - WillBeHeapVector<LocalFrame*> exitedFrameChain; + WillBeHeapVector<RawPtrWillBeMember<LocalFrame>> exitedFrameChain; // Insert the frame from the disagreement between last frames and entered frames while (exitedFrameInDocument) { Node* lastNodeUnderTap = exitedFrameInDocument->eventHandler().m_nodeUnderMouse.get();
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp index 48d0480..7dd1549 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -153,19 +153,6 @@ void setLastChildIsSelfCollapsingBlockWithClearance(bool value) { m_lastChildIsSelfCollapsingBlockWithClearance = value; } bool lastChildIsSelfCollapsingBlockWithClearance() const { return m_lastChildIsSelfCollapsingBlockWithClearance; } }; -static bool inNormalFlow(LayoutBox* child) -{ - LayoutBlock* curr = child->containingBlock(); - LayoutView* layoutView = child->view(); - while (curr && curr != layoutView) { - if (curr->isLayoutFlowThread()) - return true; - if (curr->isFloatingOrOutOfFlowPositioned()) - return false; - curr = curr->containingBlock(); - } - return true; -} LayoutBlockFlow::LayoutBlockFlow(ContainerNode* node) : LayoutBlock(node) @@ -1716,14 +1703,8 @@ LayoutUnit LayoutBlockFlow::applyBeforeBreak(LayoutBox& child, LayoutUnit logicalOffset) { - // FIXME: Add page break checking here when we support printing. - LayoutFlowThread* flowThread = flowThreadContainingBlock(); - bool checkColumnBreaks = flowThread; - bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight(); // FIXME: Once columns can print we have to check this. - bool checkBeforeAlways = (checkColumnBreaks && child.style()->columnBreakBefore() == PBALWAYS) - || (checkPageBreaks && child.style()->pageBreakBefore() == PBALWAYS); - if (checkBeforeAlways && inNormalFlow(&child)) { - if (checkColumnBreaks) { + if (child.hasForcedBreakBefore()) { + if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) { LayoutUnit offsetBreakAdjustment = 0; if (flowThread->addForcedColumnBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset, &child, true, &offsetBreakAdjustment)) return logicalOffset + offsetBreakAdjustment; @@ -1735,17 +1716,11 @@ LayoutUnit LayoutBlockFlow::applyAfterBreak(LayoutBox& child, LayoutUnit logicalOffset, MarginInfo& marginInfo) { - // FIXME: Add page break checking here when we support printing. - LayoutFlowThread* flowThread = flowThreadContainingBlock(); - bool checkColumnBreaks = flowThread; - bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight(); // FIXME: Once columns can print we have to check this. - bool checkAfterAlways = (checkColumnBreaks && child.style()->columnBreakAfter() == PBALWAYS) - || (checkPageBreaks && child.style()->pageBreakAfter() == PBALWAYS); - if (checkAfterAlways && inNormalFlow(&child)) { + if (child.hasForcedBreakAfter()) { // So our margin doesn't participate in the next collapsing steps. marginInfo.clearMargin(); - if (checkColumnBreaks) { + if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) { LayoutUnit offsetBreakAdjustment = 0; if (flowThread->addForcedColumnBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset, &child, false, &offsetBreakAdjustment)) return logicalOffset + offsetBreakAdjustment;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index cc1ea91..ad71db13 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -956,6 +956,7 @@ SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<LayoutBox&>(*this)); #endif const_cast<LayoutBox*>(this)->computePreferredLogicalWidths(); + ASSERT(!preferredLogicalWidthsDirty()); } return m_minPreferredLogicalWidth; @@ -968,6 +969,7 @@ SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<LayoutBox&>(*this)); #endif const_cast<LayoutBox*>(this)->computePreferredLogicalWidths(); + ASSERT(!preferredLogicalWidthsDirty()); } return m_maxPreferredLogicalWidth; @@ -1779,6 +1781,46 @@ ensureRareData().m_paginationStrut = strut; } +static bool isForcedBreakAllowed(const LayoutBox* child) +{ + // We currently only support forced breaks on in-flow block level elements, which is the minimum + // requirement according to the spec. + if (child->isInline() || child->isFloatingOrOutOfFlowPositioned()) + return false; + const LayoutBlock* curr = child->containingBlock(); + if (!curr || !curr->isLayoutBlockFlow()) + return false; + const LayoutView* layoutView = child->view(); + while (curr && curr != layoutView) { + if (curr->isLayoutFlowThread()) + return true; + if (curr->isFloatingOrOutOfFlowPositioned()) + return false; + curr = curr->containingBlock(); + } + return true; +} + +bool LayoutBox::hasForcedBreakBefore() const +{ + LayoutFlowThread* flowThread = flowThreadContainingBlock(); + bool checkColumnBreaks = flowThread; + bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight(); // TODO(mstensho): Once columns can print, we have to check this. + bool checkBeforeAlways = (checkColumnBreaks && style()->columnBreakBefore() == PBALWAYS) + || (checkPageBreaks && style()->pageBreakBefore() == PBALWAYS); + return checkBeforeAlways && isForcedBreakAllowed(this); +} + +bool LayoutBox::hasForcedBreakAfter() const +{ + LayoutFlowThread* flowThread = flowThreadContainingBlock(); + bool checkColumnBreaks = flowThread; + bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->pageLogicalHeight(); // TODO(mstensho): Once columns can print, we have to check this. + bool checkAfterAlways = (checkColumnBreaks && style()->columnBreakAfter() == PBALWAYS) + || (checkPageBreaks && style()->pageBreakAfter() == PBALWAYS); + return checkAfterAlways && isForcedBreakAllowed(this); +} + LayoutRect LayoutBox::clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const { if (style()->visibility() != VISIBLE) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index 7ec9481..bff4e10 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -590,6 +590,9 @@ m_rareData->m_paginationStrut = LayoutUnit(); } + bool hasForcedBreakBefore() const; + bool hasForcedBreakAfter() const; + LayoutRect clippedOverflowRectForPaintInvalidation(const LayoutBoxModelObject* paintInvalidationContainer, const PaintInvalidationState* = nullptr) const override; void mapRectToPaintInvalidationBacking(const LayoutBoxModelObject* paintInvalidationContainer, LayoutRect&, const PaintInvalidationState*) const override; virtual void invalidatePaintForOverhangingFloats(bool paintAllDescendants); @@ -911,9 +914,14 @@ virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const; - // This function calculates the minimum and maximum preferred widths for an object. - // These values are used in shrink-to-fit layout systems. - // These include tables, positioned objects, floats and flexible boxes. + // This function calculates the preferred widths for an object. + // + // This function is only expected to be called if + // the boolean preferredLogicalWidthsDirty is true. It also MUST clear the + // boolean before returning. + // + // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS in LayoutObject.h for more + // details about those widths. virtual void computePreferredLogicalWidths() { clearPreferredLogicalWidthsDirty(); } LayoutBoxRareData& ensureRareData() @@ -957,15 +965,15 @@ LayoutRectOutsets m_marginBoxOutsets; protected: - // The preferred logical width of the element if it were to break its lines at every - // possible opportunity. CSS 2.1 calls this width the "preferred minimum width" and - // "minimum content width". - // See https://drafts.csswg.org/css-sizing-3/#intrinsic for more information. + // The logical width of the element if it were to break its lines at every + // possible opportunity. + // + // See LayoutObject::minPreferredLogicalWidth() for more details. LayoutUnit m_minPreferredLogicalWidth; - // The preferred logical width of the element if it never breaks any lines at all. - // CSS 2.1 calls this width the "preferred width" and "maximum cell width". - // See https://drafts.csswg.org/css-sizing-3/#intrinsic for more information. + // The logical width of the element if it never breaks any lines at all. + // + // See LayoutObject::maxPreferredLogicalWidth() for more details. LayoutUnit m_maxPreferredLogicalWidth; // Our overflow information.
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h index 77815983..aab292f0 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.h +++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -155,6 +155,30 @@ // (See https://drafts.csswg.org/css-backgrounds-3/#the-background-image) // - image (LayoutImage, LayoutSVGImage) or video (LayoutVideo) objects that are placeholders for // displaying them. +// +// ***** INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS ***** +// The preferred logical widths are the intrinsic sizes of this element +// (https://drafts.csswg.org/css-sizing-3/#intrinsic). Intrinsic sizes depend +// mostly on the content and a limited set of style properties (e.g. any +// font-related property for text, 'min-width'/'max-width', +// 'min-height'/'max-height'). +// +// Those widths are used to determine the final layout logical width, which +// depends on the layout algorithm used and the available logical width. +// +// LayoutObject only has getters for the widths (minPreferredLogicalWidth and +// maxPreferredLogicalWidth). However the storage for them is in LayoutBox +// (see m_minPreferredLogicalWidth and m_maxPreferredLogicalWidth). This is +// because only boxes implementing the full box model have a need for them. +// Because LayoutBlockFlow's intrinsic widths rely on the underlying text +// content, LayoutBlockFlow may call LayoutText::computePreferredLogicalWidths. +// +// The 2 widths are computed lazily during layout when the getters are called. +// The computation is done by calling computePreferredLogicalWidths() behind the +// scene. The boolean used to control the lazy recomputation is +// preferredLogicalWidthsDirty. +// +// See the individual getters below for more details about what each width is. class CORE_EXPORT LayoutObject : public ImageResourceClient { friend class LayoutObjectChildList; WTF_MAKE_NONCOPYABLE(LayoutObject); @@ -908,7 +932,27 @@ // the rect that will be painted if this object is passed as the paintingRoot IntRect paintingRootRect(IntRect& topLevelRect); + // This function returns the minimal logical width this object can have + // without overflowing. This means that all the opportunities for wrapping + // have been taken. + // + // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS above. + // + // CSS 2.1 calls this width the "preferred minimum width" (thus this name) + // and "minimum content width" (for table). + // However CSS 3 calls it the "min-content inline size". + // https://drafts.csswg.org/css-sizing-3/#min-content-inline-size + // TODO(jchaffraix): We will probably want to rename it to match CSS 3. virtual LayoutUnit minPreferredLogicalWidth() const { return 0; } + + // This function returns the maximum logical width this object can have. + // + // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS above. + // + // CSS 2.1 calls this width the "preferred width". However CSS 3 calls it + // the "max-content inline size". + // https://drafts.csswg.org/css-sizing-3/#max-content-inline-size + // TODO(jchaffraix): We will probably want to rename it to match CSS 3. virtual LayoutUnit maxPreferredLogicalWidth() const { return 0; } const ComputedStyle* style() const { return m_style.get(); } @@ -1594,19 +1638,10 @@ // bleed into its containing block's so we have to recompute it in some cases. ADD_BOOLEAN_BITFIELD(childNeedsOverflowRecalcAfterStyleChange, ChildNeedsOverflowRecalcAfterStyleChange); - // The preferred logical widths are the intrinsic sizes of this element. - // Intrinsic sizes depend mostly on the content and a limited set of style - // properties (e.g. any font-related property for text, 'min-width'/'max-width', - // 'min-height'/'max-height'). + // This boolean marks preferred logical widths for lazy recomputation. // - // Those widths are used to determine the final layout logical width, which - // depends on the layout algorithm used and the available logical width. - // - // Blink stores them in LayoutBox (m_minPreferredLogicalWidth and - // m_maxPreferredLogicalWidth). - // - // Setting this boolean marks both widths for lazy recomputation when - // LayoutBox::minPreferredLogicalWidth() or maxPreferredLogicalWidth() is called. + // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS above about those + // widths. ADD_BOOLEAN_BITFIELD(preferredLogicalWidthsDirty, PreferredLogicalWidthsDirty); ADD_BOOLEAN_BITFIELD(shouldInvalidateOverflowForPaint, ShouldInvalidateOverflowForPaint); // TODO(wangxianzhu): Remove for slimming paint v2.
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp index 2b23d4f..e027a86 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.cpp
@@ -217,14 +217,29 @@ void LayoutSVGInlineText::updateScaledFont() { - computeNewScaledFontForStyle(this, style(), m_scalingFactor, m_scaledFont); + computeNewScaledFontForStyle(this, m_scalingFactor, m_scaledFont); } -void LayoutSVGInlineText::computeNewScaledFontForStyle(LayoutObject* layoutObject, const ComputedStyle* style, float& scalingFactor, Font& scaledFont) +void LayoutSVGInlineText::computeNewScaledFontForStyle(LayoutObject* layoutObject, float& scalingFactor, Font& scaledFont) { + const ComputedStyle* style = layoutObject->style(); ASSERT(style); ASSERT(layoutObject); + // layoutTextOnLineOrPath() expects fonts to do nothing for vertical flow so + // that it can position each glyph precisely. Make sure the selected font is + // the one for horizontal flow to not to break the assumption. + // TODO(kojii): This might be done better by obsoleting the + // 'glyph-orientation-vertical' property as recommended in: + // https://drafts.csswg.org/css-writing-modes/#glyph-orientation + if (style->font().fontDescription().orientation() != FontOrientation::Horizontal) { + FontDescription description = style->font().fontDescription(); + FontSelector* fontSelector = style->font().fontSelector(); + description.setOrientation(FontOrientation::Horizontal); + layoutObject->mutableStyleRef().setFontDescription(description); + style->font().update(fontSelector); + } + // Alter font-size to the right on-screen value to avoid scaling the glyphs themselves, except when GeometricPrecision is specified. scalingFactor = SVGLayoutSupport::calculateScreenFontSizeScalingFactor(layoutObject); if (style->effectiveZoom() == 1 && (scalingFactor == 1 || !scalingFactor)) {
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.h index 33f3f351..84610b8 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGInlineText.h
@@ -38,7 +38,7 @@ float scalingFactor() const { return m_scalingFactor; } const Font& scaledFont() const { return m_scaledFont; } void updateScaledFont(); - static void computeNewScaledFontForStyle(LayoutObject*, const ComputedStyle*, float& scalingFactor, Font& scaledFont); + static void computeNewScaledFontForStyle(LayoutObject*, float& scalingFactor, Font& scaledFont); // Preserves floating point precision for the use in DRT. It knows how to round and does a better job than enclosingIntRect. FloatRect floatLinesBoundingBox() const;
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp index 87c93ac4..81c1c29 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
@@ -416,7 +416,7 @@ // FIXME: Remove this hack, once the new text layout engine is completly landed. We want to preserve the old layout test results for now. ts << "chunk 1 "; ETextAnchor anchor = svgStyle.textAnchor(); - bool isVerticalText = svgStyle.isVerticalWritingMode(); + bool isVerticalText = !textLineLayout.style()->isHorizontalWritingMode(); if (anchor == TA_MIDDLE) { ts << "(middle anchor"; if (isVerticalText)
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextChunkBuilder.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextChunkBuilder.cpp index c1e3c195..0a5bc59 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGTextChunkBuilder.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextChunkBuilder.cpp
@@ -162,7 +162,7 @@ { const ComputedStyle& style = (*boxStart)->layoutObject().styleRef(); - ChunkLengthAccumulator lengthAccumulator(style.svgStyle().isVerticalWritingMode()); + ChunkLengthAccumulator lengthAccumulator(!style.isHorizontalWritingMode()); lengthAccumulator.processRange(boxStart, boxEnd); // Handle text-anchor as additional start offset for text paths. @@ -209,7 +209,7 @@ if (!processTextAnchor && !processTextLength) return; - bool isVerticalText = style.svgStyle().isVerticalWritingMode(); + bool isVerticalText = !style.isHorizontalWritingMode(); // Calculate absolute length of whole text chunk (starting from text box 'start', spanning 'length' text boxes). ChunkLengthAccumulator lengthAccumulator(isVerticalText);
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp index fae2e5e9..bfcbb00d 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextLayoutEngine.cpp
@@ -215,7 +215,7 @@ const ComputedStyle& style = text.styleRef(); textBox->clearTextFragments(); - m_isVerticalText = style.svgStyle().isVerticalWritingMode(); + m_isVerticalText = !style.isHorizontalWritingMode(); layoutTextOnLineOrPath(textBox, text, style); if (m_inPathLayout)
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp index 2a0ef77..cbccd506 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp
@@ -106,7 +106,7 @@ queryData->textBox = textBox; queryData->textLayoutObject = &toLayoutSVGInlineText(textBox->layoutObject()); - queryData->isVerticalText = textBox->layoutObject().style()->svgStyle().isVerticalWritingMode(); + queryData->isVerticalText = !textBox->layoutObject().style()->isHorizontalWritingMode(); // Loop over all text fragments in this text box, firing a callback for each. for (const SVGTextFragment& fragment : textBox->textFragments()) {
diff --git a/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.cpp index c2bbeae..8cf6f64 100644 --- a/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.cpp +++ b/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.cpp
@@ -247,7 +247,7 @@ float scalingFactor = 1; Font scaledFont; - LayoutSVGInlineText::computeNewScaledFontForStyle(decorationLayoutObject, &decorationStyle, scalingFactor, scaledFont); + LayoutSVGInlineText::computeNewScaledFontForStyle(decorationLayoutObject, scalingFactor, scaledFont); ASSERT(scalingFactor); float thickness = thicknessForDecoration(decoration, scaledFont);
diff --git a/third_party/WebKit/Source/core/style/SVGComputedStyle.cpp b/third_party/WebKit/Source/core/style/SVGComputedStyle.cpp index e3d82d9..c2818945 100644 --- a/third_party/WebKit/Source/core/style/SVGComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/SVGComputedStyle.cpp
@@ -154,7 +154,6 @@ // All text related properties influence layout. if (svg_inherited_flags._textAnchor != other->svg_inherited_flags._textAnchor - || svg_inherited_flags._writingMode != other->svg_inherited_flags._writingMode || svg_inherited_flags._glyphOrientationHorizontal != other->svg_inherited_flags._glyphOrientationHorizontal || svg_inherited_flags._glyphOrientationVertical != other->svg_inherited_flags._glyphOrientationVertical || svg_inherited_flags.dominantBaseline != other->svg_inherited_flags.dominantBaseline
diff --git a/third_party/WebKit/Source/core/style/SVGComputedStyle.h b/third_party/WebKit/Source/core/style/SVGComputedStyle.h index ac9f432..9145dc9 100644 --- a/third_party/WebKit/Source/core/style/SVGComputedStyle.h +++ b/third_party/WebKit/Source/core/style/SVGComputedStyle.h
@@ -65,7 +65,6 @@ static LineJoin initialJoinStyle() { return MiterJoin; } static EShapeRendering initialShapeRendering() { return SR_AUTO; } static ETextAnchor initialTextAnchor() { return TA_START; } - static SVGWritingMode initialWritingMode() { return WM_LRTB; } static EGlyphOrientation initialGlyphOrientationHorizontal() { return GO_0DEG; } static EGlyphOrientation initialGlyphOrientationVertical() { return GO_AUTO; } static float initialFillOpacity() { return 1; } @@ -116,7 +115,6 @@ void setJoinStyle(LineJoin val) { svg_inherited_flags._joinStyle = val; } void setShapeRendering(EShapeRendering val) { svg_inherited_flags._shapeRendering = val; } void setTextAnchor(ETextAnchor val) { svg_inherited_flags._textAnchor = val; } - void setWritingMode(SVGWritingMode val) { svg_inherited_flags._writingMode = val; } void setGlyphOrientationHorizontal(EGlyphOrientation val) { svg_inherited_flags._glyphOrientationHorizontal = val; } void setGlyphOrientationVertical(EGlyphOrientation val) { svg_inherited_flags._glyphOrientationVertical = val; } void setMaskType(EMaskType val) { svg_noninherited_flags.f.maskType = val; } @@ -321,7 +319,6 @@ LineJoin joinStyle() const { return (LineJoin) svg_inherited_flags._joinStyle; } EShapeRendering shapeRendering() const { return (EShapeRendering) svg_inherited_flags._shapeRendering; } ETextAnchor textAnchor() const { return (ETextAnchor) svg_inherited_flags._textAnchor; } - SVGWritingMode writingMode() const { return (SVGWritingMode) svg_inherited_flags._writingMode; } EGlyphOrientation glyphOrientationHorizontal() const { return (EGlyphOrientation) svg_inherited_flags._glyphOrientationHorizontal; } EGlyphOrientation glyphOrientationVertical() const { return (EGlyphOrientation) svg_inherited_flags._glyphOrientationVertical; } float fillOpacity() const { return fill->opacity; } @@ -376,7 +373,6 @@ bool hasSquareCapStyle() const { return capStyle() == SquareCap; } bool hasMiterJoinStyle() const { return joinStyle() == MiterJoin; } bool hasFill() const { return fillPaintType() != SVG_PAINTTYPE_NONE; } - bool isVerticalWritingMode() const { return writingMode() == WM_TBRL || writingMode() == WM_TB; } protected: // inherit @@ -392,7 +388,6 @@ && (_textAnchor == other._textAnchor) && (_colorInterpolation == other._colorInterpolation) && (_colorInterpolationFilters == other._colorInterpolationFilters) - && (_writingMode == other._writingMode) && (_glyphOrientationHorizontal == other._glyphOrientationHorizontal) && (_glyphOrientationVertical == other._glyphOrientationVertical) && (paintOrder == other.paintOrder) @@ -413,7 +408,6 @@ unsigned _textAnchor : 2; // ETextAnchor unsigned _colorInterpolation : 2; // EColorInterpolation unsigned _colorInterpolationFilters : 2; // EColorInterpolation - unsigned _writingMode : 3; // SVGWritingMode unsigned _glyphOrientationHorizontal : 3; // EGlyphOrientation unsigned _glyphOrientationVertical : 3; // EGlyphOrientation unsigned paintOrder : 3; // EPaintOrder @@ -471,7 +465,6 @@ svg_inherited_flags._joinStyle = initialJoinStyle(); svg_inherited_flags._colorInterpolation = initialColorInterpolation(); svg_inherited_flags._colorInterpolationFilters = initialColorInterpolationFilters(); - svg_inherited_flags._writingMode = initialWritingMode(); svg_inherited_flags._glyphOrientationHorizontal = initialGlyphOrientationHorizontal(); svg_inherited_flags._glyphOrientationVertical = initialGlyphOrientationVertical(); svg_inherited_flags.paintOrder = initialPaintOrder();
diff --git a/third_party/WebKit/Source/core/style/SVGComputedStyleDefs.h b/third_party/WebKit/Source/core/style/SVGComputedStyleDefs.h index eb5d21fd..eff0768e 100644 --- a/third_party/WebKit/Source/core/style/SVGComputedStyleDefs.h +++ b/third_party/WebKit/Source/core/style/SVGComputedStyleDefs.h
@@ -72,10 +72,6 @@ SR_AUTO, SR_OPTIMIZESPEED, SR_CRISPEDGES, SR_GEOMETRICPRECISION }; -enum SVGWritingMode { - WM_LRTB, WM_LR, WM_RLTB, WM_RL, WM_TBRL, WM_TB -}; - enum EGlyphOrientation { GO_0DEG, GO_90DEG, GO_180DEG, GO_270DEG, GO_AUTO };
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py index 8764f0d..53845c2 100755 --- a/tools/gn/bootstrap/bootstrap.py +++ b/tools/gn/bootstrap/bootstrap.py
@@ -250,7 +250,6 @@ 'base/trace_event/memory_profiler_allocation_context.cc', 'base/trace_event/process_memory_dump.cc', 'base/trace_event/process_memory_maps.cc', - 'base/trace_event/process_memory_maps_dump_provider.cc', 'base/trace_event/process_memory_totals.cc', 'base/trace_event/process_memory_totals_dump_provider.cc', 'base/trace_event/trace_buffer.cc', @@ -338,6 +337,7 @@ 'base/sys_info_linux.cc', 'base/threading/platform_thread_linux.cc', 'base/trace_event/malloc_dump_provider.cc', + 'base/trace_event/process_memory_maps_dump_provider.cc', ]) static_libraries['libevent']['include_dirs'].extend([ os.path.join(SRC_ROOT, 'third_party', 'libevent', 'linux')
diff --git a/tools/telemetry/telemetry/internal/backends/browser_backend.py b/tools/telemetry/telemetry/internal/backends/browser_backend.py index d5b71e8..3f765101 100644 --- a/tools/telemetry/telemetry/internal/backends/browser_backend.py +++ b/tools/telemetry/telemetry/internal/backends/browser_backend.py
@@ -141,6 +141,10 @@ self, suppressed, timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT): raise NotImplementedError() + def SimulateMemoryPressureNotification( + self, pressure_level, timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT): + raise NotImplementedError() + @property def supports_cpu_metrics(self): raise NotImplementedError()
diff --git a/tools/telemetry/telemetry/internal/backends/chrome/chrome_browser_backend.py b/tools/telemetry/telemetry/internal/backends/chrome/chrome_browser_backend.py index 75d010a..41b18a1 100644 --- a/tools/telemetry/telemetry/internal/backends/chrome/chrome_browser_backend.py +++ b/tools/telemetry/telemetry/internal/backends/chrome/chrome_browser_backend.py
@@ -329,7 +329,13 @@ def SetMemoryPressureNotificationsSuppressed( self, suppressed, timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT): - self.devtools_client.SetMemoryPressureNotificationsSuppressed(suppressed) + self.devtools_client.SetMemoryPressureNotificationsSuppressed( + suppressed, timeout) + + def SimulateMemoryPressureNotification( + self, pressure_level, timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT): + self.devtools_client.SimulateMemoryPressureNotification( + pressure_level, timeout) @property def supports_cpu_metrics(self):
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py index a7930810..2efb830 100644 --- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py +++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py
@@ -13,6 +13,7 @@ from telemetry.internal.backends.chrome_inspector import devtools_http from telemetry.internal.backends.chrome_inspector import inspector_backend from telemetry.internal.backends.chrome_inspector import inspector_websocket +from telemetry.internal.backends.chrome_inspector import memory_backend from telemetry.internal.backends.chrome_inspector import tracing_backend from telemetry.internal.backends.chrome_inspector import websocket from telemetry.internal.platform.tracing_agent import chrome_tracing_agent @@ -97,6 +98,7 @@ self._devtools_http = devtools_http.DevToolsHttp(devtools_port) self._browser_inspector_websocket = None self._tracing_backend = None + self._memory_backend = None self._app_backend = app_backend self._devtools_context_map_backend = _DevToolsContextMapBackend( self._app_backend, self) @@ -168,6 +170,9 @@ if self._tracing_backend: self._tracing_backend.Close() self._tracing_backend = None + if self._memory_backend: + self._memory_backend.Close() + self._memory_backend = None # Close the browser inspector socket last (in case the backend needs to # interact with it before closing). if self._browser_inspector_websocket: @@ -269,6 +274,13 @@ self._tracing_backend = tracing_backend.TracingBackend( self._browser_inspector_websocket, is_tracing_running) + def _CreateMemoryBackendIfNeeded(self): + assert self.supports_overriding_memory_pressure_notifications + if not self._memory_backend: + self._CreateAndConnectBrowserInspectorWebsocketIfNeeded() + self._memory_backend = memory_backend.MemoryBackend( + self._browser_inspector_websocket) + def _CreateAndConnectBrowserInspectorWebsocketIfNeeded(self): if not self._browser_inspector_websocket: self._browser_inspector_websocket = ( @@ -342,17 +354,35 @@ timeout: The timeout in seconds. Raises: - TracingTimeoutException: If more than |timeout| seconds has passed + MemoryTimeoutException: If more than |timeout| seconds has passed since the last time any data is received. - TracingUnrecoverableException: If there is a websocket error. - TracingUnexpectedResponseException: If the response contains an error + MemoryUnrecoverableException: If there is a websocket error. + MemoryUnexpectedResponseException: If the response contains an error or does not contain the expected result. """ - assert self.supports_overriding_memory_pressure_notifications - self._CreateTracingBackendIfNeeded() - return self._tracing_backend.SetMemoryPressureNotificationsSuppressed( + self._CreateMemoryBackendIfNeeded() + return self._memory_backend.SetMemoryPressureNotificationsSuppressed( suppressed, timeout) + def SimulateMemoryPressureNotification(self, pressure_level, timeout=30): + """Simulate a memory pressure notification. + + Args: + pressure level: The memory pressure level of the notification ('moderate' + or 'critical'). + timeout: The timeout in seconds. + + Raises: + MemoryTimeoutException: If more than |timeout| seconds has passed + since the last time any data is received. + MemoryUnrecoverableException: If there is a websocket error. + MemoryUnexpectedResponseException: If the response contains an error + or does not contain the expected result. + """ + self._CreateMemoryBackendIfNeeded() + return self._memory_backend.SimulateMemoryPressureNotification( + pressure_level, timeout) + class _DevToolsContextMapBackend(object): def __init__(self, app_backend, devtools_client):
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/memory_backend.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/memory_backend.py new file mode 100644 index 0000000..bb6ce09 --- /dev/null +++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/memory_backend.py
@@ -0,0 +1,90 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import json +import logging +import socket + +from telemetry.internal.backends.chrome_inspector import inspector_websocket +from telemetry.internal.backends.chrome_inspector import websocket + + +class MemoryTimeoutException(Exception): + pass + + +class MemoryUnrecoverableException(Exception): + pass + + +class MemoryUnexpectedResponseException(Exception): + pass + + +class MemoryBackend(object): + + def __init__(self, inspector_socket): + self._inspector_websocket = inspector_socket + + def SetMemoryPressureNotificationsSuppressed(self, suppressed, timeout=30): + """Enable/disable suppressing memory pressure notifications. + + Args: + suppressed: If true, memory pressure notifications will be suppressed. + timeout: The timeout in seconds. + + Raises: + MemoryTimeoutException: If more than |timeout| seconds has passed + since the last time any data is received. + MemoryUnrecoverableException: If there is a websocket error. + MemoryUnexpectedResponseException: If the response contains an error + or does not contain the expected result. + """ + self._SendMemoryRequest('setPressureNotificationsSuppressed', + {'suppressed': suppressed}, timeout) + + def SimulateMemoryPressureNotification(self, pressure_level, timeout=30): + """Simulate a memory pressure notification. + + Args: + pressure level: The memory pressure level of the notification ('moderate' + or 'critical'). + timeout: The timeout in seconds. + + Raises: + MemoryTimeoutException: If more than |timeout| seconds has passed + since the last time any data is received. + MemoryUnrecoverableException: If there is a websocket error. + MemoryUnexpectedResponseException: If the response contains an error + or does not contain the expected result. + """ + self._SendMemoryRequest('simulatePressureNotification', + {'level': pressure_level}, timeout) + + def _SendMemoryRequest(self, command, params, timeout): + method = 'Memory.%s' % command + request = { + 'method': method, + 'params': params + } + try: + response = self._inspector_websocket.SyncRequest(request, timeout) + except websocket.WebSocketTimeoutException: + raise MemoryTimeoutException + except (socket.error, websocket.WebSocketException, + inspector_websocket.WebSocketDisconnected): + raise MemoryUnrecoverableException + + if 'error' in response: + code = response['error']['code'] + if code == inspector_websocket.InspectorWebsocket.METHOD_NOT_FOUND_CODE: + logging.warning( + '%s DevTools method not supported by the browser' % method) + else: + raise MemoryUnexpectedResponseException( + 'Inspector returned unexpected response for %s:\n%s' % + (method, json.dumps(response, indent=2))) + + def Close(self): + self._inspector_websocket = None
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/memory_backend_unittest.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/memory_backend_unittest.py new file mode 100644 index 0000000..5829d1d00 --- /dev/null +++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/memory_backend_unittest.py
@@ -0,0 +1,152 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import mock +import unittest + + +from telemetry.internal.backends.chrome_inspector import inspector_websocket +from telemetry.internal.backends.chrome_inspector import memory_backend +from telemetry.testing import fakes +from telemetry.testing import simple_mock +from telemetry.testing import tab_test_case + + +class MemoryBackendTest(tab_test_case.TabTestCase): + + def setUp(self): + super(MemoryBackendTest, self).setUp() + if not self._browser.supports_overriding_memory_pressure_notifications: + self.skipTest('Browser does not support overriding memory pressure ' + 'notification signals, skipping test.') + + def testSetMemoryPressureNotificationsSuppressed(self): + def PerformCheck(suppressed): + # Check that the method sends the correct DevTools request. + with mock.patch.object(inspector_websocket.InspectorWebsocket, + 'SyncRequest') as mock_method: + self._browser.SetMemoryPressureNotificationsSuppressed(suppressed) + self.assertEqual(1, mock_method.call_count) + request = mock_method.call_args[0][0] + self.assertEqual('Memory.setPressureNotificationsSuppressed', + request['method']) + self.assertEqual(suppressed, request['params']['suppressed']) + + # Check that the request and the response from the browser are handled + # properly. + self._browser.SetMemoryPressureNotificationsSuppressed(suppressed) + + PerformCheck(True) + PerformCheck(False) + + def testSimulateMemoryPressureNotification(self): + def PerformCheck(pressure_level): + # Check that the method sends the correct DevTools request. + with mock.patch.object(inspector_websocket.InspectorWebsocket, + 'SyncRequest') as mock_method: + self._browser.SimulateMemoryPressureNotification(pressure_level) + self.assertEqual(1, mock_method.call_count) + request = mock_method.call_args[0][0] + self.assertEqual('Memory.simulatePressureNotification', + request['method']) + self.assertEqual(pressure_level, request['params']['level']) + + # Check that the request and the response from the browser are handled + # properly. + self._browser.SimulateMemoryPressureNotification(pressure_level) + + PerformCheck('moderate') + PerformCheck('critical') + + +class MemoryBackendUnitTest(unittest.TestCase): + + def setUp(self): + self._mock_timer = simple_mock.MockTimer() + self._inspector_socket = fakes.FakeInspectorWebsocket(self._mock_timer) + + def tearDown(self): + self._mock_timer.Restore() + + def testSetMemoryPressureNotificationsSuppressedSuccess(self): + response_handler = mock.Mock(return_value={'result': {}}) + self._inspector_socket.AddResponseHandler( + 'Memory.setPressureNotificationsSuppressed', response_handler) + backend = memory_backend.MemoryBackend(self._inspector_socket) + + backend.SetMemoryPressureNotificationsSuppressed(True) + self.assertEqual(1, response_handler.call_count) + self.assertTrue(response_handler.call_args[0][0]['params']['suppressed']) + + backend.SetMemoryPressureNotificationsSuppressed(False) + self.assertEqual(2, response_handler.call_count) + self.assertFalse(response_handler.call_args[0][0]['params']['suppressed']) + + def testSetMemoryPressureNotificationsSuppressedFailure(self): + response_handler = mock.Mock() + backend = memory_backend.MemoryBackend(self._inspector_socket) + self._inspector_socket.AddResponseHandler( + 'Memory.setPressureNotificationsSuppressed', response_handler) + + # If the DevTools method is missing, the backend should fail silently. + response_handler.return_value = { + 'result': {}, + 'error': { + 'code': -32601 # Method does not exist. + } + } + backend.SetMemoryPressureNotificationsSuppressed(True) + self.assertEqual(1, response_handler.call_count) + + # All other errors should raise an exception. + response_handler.return_value = { + 'result': {}, + 'error': { + 'code': -32602 # Invalid method params. + } + } + self.assertRaises(memory_backend.MemoryUnexpectedResponseException, + backend.SetMemoryPressureNotificationsSuppressed, True) + + def testSimulateMemoryPressureNotificationSuccess(self): + response_handler = mock.Mock(return_value={'result': {}}) + self._inspector_socket.AddResponseHandler( + 'Memory.simulatePressureNotification', response_handler) + backend = memory_backend.MemoryBackend(self._inspector_socket) + + backend.SimulateMemoryPressureNotification('critical') + self.assertEqual(1, response_handler.call_count) + self.assertEqual('critical', + response_handler.call_args[0][0]['params']['level']) + + backend.SimulateMemoryPressureNotification('moderate') + self.assertEqual(2, response_handler.call_count) + self.assertEqual('moderate', + response_handler.call_args[0][0]['params']['level']) + + def testSimulateMemoryPressureNotificationFailure(self): + response_handler = mock.Mock() + backend = memory_backend.MemoryBackend(self._inspector_socket) + self._inspector_socket.AddResponseHandler( + 'Memory.simulatePressureNotification', response_handler) + + # If the DevTools method is missing, the backend should fail silently. + response_handler.return_value = { + 'result': {}, + 'error': { + 'code': -32601 # Method does not exist. + } + } + backend.SimulateMemoryPressureNotification('critical') + self.assertEqual(1, response_handler.call_count) + + # All other errors should raise an exception. + response_handler.return_value = { + 'result': {}, + 'error': { + 'code': -32602 # Invalid method params. + } + } + self.assertRaises(memory_backend.MemoryUnexpectedResponseException, + backend.SimulateMemoryPressureNotification, 'critical')
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py index 8b96e6a..24696b96 100644 --- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py +++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py
@@ -3,7 +3,6 @@ # found in the LICENSE file. import json -import logging import socket import time @@ -168,45 +167,6 @@ result = response['result'] return result['dumpGuid'] if result['success'] else None - def SetMemoryPressureNotificationsSuppressed(self, suppressed, timeout=30): - """Enable/disable suppressing memory pressure notifications. - - Args: - suppressed: If true, memory pressure notifications will be suppressed. - timeout: The timeout in seconds. - - Raises: - TracingTimeoutException: If more than |timeout| seconds has passed - since the last time any data is received. - TracingUnrecoverableException: If there is a websocket error. - TracingUnexpectedResponseException: If the response contains an error - or does not contain the expected result. - """ - request = { - 'method': 'Memory.setPressureNotificationsSuppressed', - 'params': { - 'suppressed': suppressed - } - } - try: - response = self._inspector_websocket.SyncRequest(request, timeout) - except websocket.WebSocketTimeoutException: - raise TracingTimeoutException - except (socket.error, websocket.WebSocketException, - inspector_websocket.WebSocketDisconnected): - raise TracingUnrecoverableException - - if 'error' in response: - code = response['error']['code'] - if code == inspector_websocket.InspectorWebsocket.METHOD_NOT_FOUND_CODE: - logging.warning('Memory.setPressureNotificationsSuppressed DevTools ' - 'method not supported by the browser') - else: - raise TracingUnexpectedResponseException( - 'Inspector returned unexpected response for ' - 'Memory.setPressureNotificationsSuppressed:\n' + - json.dumps(response, indent=2)) - def _CollectTracingData(self, timeout): """Collects tracing data. Assumes that Tracing.end has already been sent.
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py index ccafea56..88cb8e553 100644 --- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py +++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py
@@ -4,101 +4,17 @@ import unittest -from telemetry.internal.backends.chrome_inspector import inspector_websocket from telemetry.internal.backends.chrome_inspector import tracing_backend -from telemetry.internal.backends.chrome_inspector import websocket +from telemetry.testing import fakes from telemetry.testing import simple_mock from telemetry.testing import tab_test_case from telemetry.timeline import model as model_module from telemetry.timeline import tracing_category_filter from telemetry.timeline import tracing_options -import mock - - -class FakeInspectorWebsocket(object): - _NOTIFICATION_EVENT = 1 - _NOTIFICATION_CALLBACK = 2 - - """A fake InspectorWebsocket. - - A fake that allows tests to send pregenerated data. Normal - InspectorWebsockets allow for any number of domain handlers. This fake only - allows up to 1 domain handler, and assumes that the domain of the response - always matches that of the handler. - """ - def __init__(self, mock_timer): - self._mock_timer = mock_timer - self._notifications = [] - self._response_handlers = {} - self._pending_callbacks = {} - self._handler = None - - def RegisterDomain(self, _, handler): - self._handler = handler - - def AddEvent(self, method, params, time): - if self._notifications: - assert self._notifications[-1][1] < time, ( - 'Current response is scheduled earlier than previous response.') - response = {'method': method, 'params': params} - self._notifications.append((response, time, self._NOTIFICATION_EVENT)) - - def AddAsyncResponse(self, method, result, time): - if self._notifications: - assert self._notifications[-1][1] < time, ( - 'Current response is scheduled earlier than previous response.') - response = {'method': method, 'result': result} - self._notifications.append((response, time, self._NOTIFICATION_CALLBACK)) - - def AddResponseHandler(self, method, handler): - self._response_handlers[method] = handler - - def SyncRequest(self, request, *_args, **_kwargs): - handler = self._response_handlers[request['method']] - return handler(request) if handler else None - - def AsyncRequest(self, request, callback): - self._pending_callbacks.setdefault(request['method'], []).append(callback) - - def SendAndIgnoreResponse(self, request): - pass - - def Connect(self, _): - pass - - def DispatchNotifications(self, timeout): - current_time = self._mock_timer.time() - if not self._notifications: - self._mock_timer.SetTime(current_time + timeout + 1) - raise websocket.WebSocketTimeoutException() - - response, time, kind = self._notifications[0] - if time - current_time > timeout: - self._mock_timer.SetTime(current_time + timeout + 1) - raise websocket.WebSocketTimeoutException() - - self._notifications.pop(0) - self._mock_timer.SetTime(time + 1) - if kind == self._NOTIFICATION_EVENT: - self._handler(response) - elif kind == self._NOTIFICATION_CALLBACK: - callback = self._pending_callbacks.get(response['method']).pop(0) - callback(response) - else: - raise Exception('Unexpected response type') class TracingBackendTest(tab_test_case.TabTestCase): - def setUp(self): - super(TracingBackendTest, self).setUp() - self._tracing_controller = self._browser.platform.tracing_controller - if not self._tracing_controller.IsChromeTracingSupported(): - self.skipTest('Browser does not support tracing, skipping test.') - - -class TracingBackendMemoryDumpTest(TracingBackendTest): - # Number of consecutively requested memory dumps. _REQUESTED_DUMP_COUNT = 3 @@ -114,7 +30,10 @@ ]) def setUp(self): - super(TracingBackendMemoryDumpTest, self).setUp() + super(TracingBackendTest, self).setUp() + self._tracing_controller = self._browser.platform.tracing_controller + if not self._tracing_controller.IsChromeTracingSupported(): + self.skipTest('Browser does not support tracing, skipping test.') if not self._browser.supports_memory_dumping: self.skipTest('Browser does not support memory dumping, skipping test.') @@ -178,47 +97,22 @@ self.assertEqual(len(list(model.IterGlobalMemoryDumps())), 0) -class TracingBackendMemoryPressureNotificationsTest(TracingBackendTest): - - def setUp(self): - super(TracingBackendMemoryPressureNotificationsTest, self).setUp() - if not self._browser.supports_overriding_memory_pressure_notifications: - self.skipTest('Browser does not support overriding memory pressure ' - 'notification signals, skipping test.') - - def testSetMemoryPressureNotificationsSuppressed(self): - def perform_check(suppressed): - # Check that the method sends the correct DevTools request. - with mock.patch.object(inspector_websocket.InspectorWebsocket, - 'SyncRequest') as mock_method: - self._browser.SetMemoryPressureNotificationsSuppressed(suppressed) - self.assertEqual(1, mock_method.call_count) - request = mock_method.call_args[0][0] - self.assertEqual('Memory.setPressureNotificationsSuppressed', - request['method']) - self.assertEqual(suppressed, request['params']['suppressed']) - - # Check that the request and the response from the browser are handled - # properly. - self._browser.SetMemoryPressureNotificationsSuppressed(suppressed) - - perform_check(True) - perform_check(False) - - class TracingBackendUnitTest(unittest.TestCase): + def setUp(self): self._mock_timer = simple_mock.MockTimer(tracing_backend) + self._inspector_socket = fakes.FakeInspectorWebsocket(self._mock_timer) def tearDown(self): self._mock_timer.Restore() def testCollectTracingDataTimeout(self): - inspector = FakeInspectorWebsocket(self._mock_timer) - inspector.AddEvent('Tracing.dataCollected', {'value': [{'ph': 'B'}]}, 9) - inspector.AddEvent('Tracing.dataCollected', {'value': [{'ph': 'E'}]}, 19) - inspector.AddEvent('Tracing.tracingComplete', {}, 35) - backend = tracing_backend.TracingBackend(inspector) + self._inspector_socket.AddEvent( + 'Tracing.dataCollected', {'value': [{'ph': 'B'}]}, 9) + self._inspector_socket.AddEvent( + 'Tracing.dataCollected', {'value': [{'ph': 'E'}]}, 19) + self._inspector_socket.AddEvent('Tracing.tracingComplete', {}, 35) + backend = tracing_backend.TracingBackend(self._inspector_socket) # The third response is 16 seconds after the second response, so we expect # a TracingTimeoutException. @@ -228,83 +122,42 @@ self.assertFalse(backend._has_received_all_tracing_data) def testCollectTracingDataNoTimeout(self): - inspector = FakeInspectorWebsocket(self._mock_timer) - inspector.AddEvent('Tracing.dataCollected', {'value': [{'ph': 'B'}]}, 9) - inspector.AddEvent('Tracing.dataCollected', {'value': [{'ph': 'E'}]}, 14) - inspector.AddEvent('Tracing.tracingComplete', {}, 19) - backend = tracing_backend.TracingBackend(inspector) + self._inspector_socket.AddEvent( + 'Tracing.dataCollected', {'value': [{'ph': 'B'}]}, 9) + self._inspector_socket.AddEvent( + 'Tracing.dataCollected', {'value': [{'ph': 'E'}]}, 14) + self._inspector_socket.AddEvent('Tracing.tracingComplete', {}, 19) + backend = tracing_backend.TracingBackend(self._inspector_socket) backend._CollectTracingData(10) self.assertEqual(2, len(backend._trace_events)) self.assertTrue(backend._has_received_all_tracing_data) def testCollectTracingDataFromStream(self): - inspector = FakeInspectorWebsocket(self._mock_timer) - inspector.AddEvent('Tracing.tracingComplete', {'stream': '42'}, 1) - inspector.AddAsyncResponse('IO.read', {'data': '[{},{},{'}, 2) - inspector.AddAsyncResponse('IO.read', {'data': '},{},{}]', 'eof': True}, 3) - backend = tracing_backend.TracingBackend(inspector) + self._inspector_socket.AddEvent( + 'Tracing.tracingComplete', {'stream': '42'}, 1) + self._inspector_socket.AddAsyncResponse( + 'IO.read', {'data': '[{},{},{'}, 2) + self._inspector_socket.AddAsyncResponse( + 'IO.read', {'data': '},{},{}]', 'eof': True}, 3) + backend = tracing_backend.TracingBackend(self._inspector_socket) backend._CollectTracingData(10) self.assertEqual(5, len(backend._trace_events)) self.assertTrue(backend._has_received_all_tracing_data) def testDumpMemorySuccess(self): - inspector = FakeInspectorWebsocket(self._mock_timer) - inspector.AddResponseHandler( + self._inspector_socket.AddResponseHandler( 'Tracing.requestMemoryDump', lambda req: {'result': {'success': True, 'dumpGuid': '42abc'}}) - backend = tracing_backend.TracingBackend(inspector) + backend = tracing_backend.TracingBackend(self._inspector_socket) self.assertEqual(backend.DumpMemory(), '42abc') def testDumpMemoryFailure(self): - inspector = FakeInspectorWebsocket(self._mock_timer) - inspector.AddResponseHandler( + self._inspector_socket.AddResponseHandler( 'Tracing.requestMemoryDump', lambda req: {'result': {'success': False, 'dumpGuid': '42abc'}}) - backend = tracing_backend.TracingBackend(inspector) + backend = tracing_backend.TracingBackend(self._inspector_socket) self.assertIsNone(backend.DumpMemory()) - - def testSetMemoryPressureNotificationsSuppressedSuccess(self): - response_handler = mock.Mock(return_value={'result': {}}) - inspector = FakeInspectorWebsocket(self._mock_timer) - inspector.AddResponseHandler( - 'Memory.setPressureNotificationsSuppressed', response_handler) - backend = tracing_backend.TracingBackend(inspector) - - backend.SetMemoryPressureNotificationsSuppressed(True) - self.assertEqual(1, response_handler.call_count) - self.assertTrue(response_handler.call_args[0][0]['params']['suppressed']) - - backend.SetMemoryPressureNotificationsSuppressed(False) - self.assertEqual(2, response_handler.call_count) - self.assertFalse(response_handler.call_args[0][0]['params']['suppressed']) - - def testSetMemoryPressureNotificationsSuppressedFailure(self): - response_handler = mock.Mock() - inspector = FakeInspectorWebsocket(self._mock_timer) - backend = tracing_backend.TracingBackend(inspector) - inspector.AddResponseHandler( - 'Memory.setPressureNotificationsSuppressed', response_handler) - - # If the DevTools method is missing, the backend should fail silently. - response_handler.return_value = { - 'result': {}, - 'error': { - 'code': -32601 # Method does not exist. - } - } - backend.SetMemoryPressureNotificationsSuppressed(True) - self.assertEqual(1, response_handler.call_count) - - # All other errors should raise an exception. - response_handler.return_value = { - 'result': {}, - 'error': { - 'code': -32602 # Invalid method params. - } - } - self.assertRaises(tracing_backend.TracingUnexpectedResponseException, - backend.SetMemoryPressureNotificationsSuppressed, True)
diff --git a/tools/telemetry/telemetry/internal/browser/browser.py b/tools/telemetry/telemetry/internal/browser/browser.py index 5f26aade..248a932 100644 --- a/tools/telemetry/telemetry/internal/browser/browser.py +++ b/tools/telemetry/telemetry/internal/browser/browser.py
@@ -268,6 +268,11 @@ self._browser_backend.SetMemoryPressureNotificationsSuppressed( suppressed, timeout) + def SimulateMemoryPressureNotification( + self, pressure_level, timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT): + self._browser_backend.SimulateMemoryPressureNotification( + pressure_level, timeout) + @property def supports_cpu_metrics(self): return self._browser_backend.supports_cpu_metrics
diff --git a/tools/telemetry/telemetry/testing/fakes/__init__.py b/tools/telemetry/telemetry/testing/fakes/__init__.py index 7eecc43..2502799 100644 --- a/tools/telemetry/telemetry/testing/fakes/__init__.py +++ b/tools/telemetry/telemetry/testing/fakes/__init__.py
@@ -11,6 +11,7 @@ may need to be called in tests. """ +from telemetry.internal.backends.chrome_inspector import websocket from telemetry.internal.browser import browser_options from telemetry.internal.platform import system_info from telemetry.page import shared_page_state @@ -291,3 +292,76 @@ if tab.id == identifier: return tab return None + + +class FakeInspectorWebsocket(object): + _NOTIFICATION_EVENT = 1 + _NOTIFICATION_CALLBACK = 2 + + """A fake InspectorWebsocket. + + A fake that allows tests to send pregenerated data. Normal + InspectorWebsockets allow for any number of domain handlers. This fake only + allows up to 1 domain handler, and assumes that the domain of the response + always matches that of the handler. + """ + def __init__(self, mock_timer): + self._mock_timer = mock_timer + self._notifications = [] + self._response_handlers = {} + self._pending_callbacks = {} + self._handler = None + + def RegisterDomain(self, _, handler): + self._handler = handler + + def AddEvent(self, method, params, time): + if self._notifications: + assert self._notifications[-1][1] < time, ( + 'Current response is scheduled earlier than previous response.') + response = {'method': method, 'params': params} + self._notifications.append((response, time, self._NOTIFICATION_EVENT)) + + def AddAsyncResponse(self, method, result, time): + if self._notifications: + assert self._notifications[-1][1] < time, ( + 'Current response is scheduled earlier than previous response.') + response = {'method': method, 'result': result} + self._notifications.append((response, time, self._NOTIFICATION_CALLBACK)) + + def AddResponseHandler(self, method, handler): + self._response_handlers[method] = handler + + def SyncRequest(self, request, *_args, **_kwargs): + handler = self._response_handlers[request['method']] + return handler(request) if handler else None + + def AsyncRequest(self, request, callback): + self._pending_callbacks.setdefault(request['method'], []).append(callback) + + def SendAndIgnoreResponse(self, request): + pass + + def Connect(self, _): + pass + + def DispatchNotifications(self, timeout): + current_time = self._mock_timer.time() + if not self._notifications: + self._mock_timer.SetTime(current_time + timeout + 1) + raise websocket.WebSocketTimeoutException() + + response, time, kind = self._notifications[0] + if time - current_time > timeout: + self._mock_timer.SetTime(current_time + timeout + 1) + raise websocket.WebSocketTimeoutException() + + self._notifications.pop(0) + self._mock_timer.SetTime(time + 1) + if kind == self._NOTIFICATION_EVENT: + self._handler(response) + elif kind == self._NOTIFICATION_CALLBACK: + callback = self._pending_callbacks.get(response['method']).pop(0) + callback(response) + else: + raise Exception('Unexpected response type')