diff --git a/DEPS b/DEPS index 863812c..236bcac 100644 --- a/DEPS +++ b/DEPS
@@ -43,7 +43,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '2b8fdcf7910bee068f4735015e8e122dc8e56abd', + 'v8_revision': 'ceae85175c53e9676e869d460eddfce62ebce738', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -267,7 +267,7 @@ 'src/third_party/catapult': Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' + - '908ae8031f4a9b3ff663779e0375988b864c5ce9', + 'fa891414e695f7125512449f7c49c217f85e6d8f', 'src/third_party/openh264/src': Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'b37cda248234162033e3e11b0335f3131cdfe488',
diff --git a/WATCHLISTS b/WATCHLISTS index b6ed2f0..a5b5a64 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1472,7 +1472,8 @@ 'dennisjeffrey@chromium.org'], 'remoting': ['chromoting-reviews@chromium.org'], 'rlz_id': ['gab+watch@chromium.org', - 'robertshield+watch@chromium.org'], + 'robertshield+watch@chromium.org', + 'alito+watch@chromium.org'], 'safe_browsing': ['grt+watch@chromium.org'], 'sandbox': ['rickyz+watch@chromium.org'], 'scheduler': ['scheduler-bugs@chromium.org'],
diff --git a/ash/system/ime/ime_observer.h b/ash/system/ime/ime_observer.h index a7f938c84..1707062 100644 --- a/ash/system/ime/ime_observer.h +++ b/ash/system/ime/ime_observer.h
@@ -14,6 +14,12 @@ // Notify the observer that the IME state has changed, and should be // refreshed. virtual void OnIMERefresh() = 0; + + // Notify the observer that the IME menu activation state has changed, and + // should be refreshed. |is_active| represents whether the new IME menu is + // active, and IME related items in system tray should be removed if + // |is_active| is true. + virtual void OnIMEMenuActivationChanged(bool is_active) = 0; }; } // namespace ash
diff --git a/ash/system/ime/tray_ime_chromeos.cc b/ash/system/ime/tray_ime_chromeos.cc index 4896a59..fad9d20 100644 --- a/ash/system/ime/tray_ime_chromeos.cc +++ b/ash/system/ime/tray_ime_chromeos.cc
@@ -236,7 +236,8 @@ tray_label_(NULL), default_(NULL), detailed_(NULL), - keyboard_suppressed_(false) { + keyboard_suppressed_(false), + is_visible_(true) { Shell::GetInstance()->system_tray_notifier()->AddIMEObserver(this); Shell::GetInstance()->system_tray_notifier()->AddVirtualKeyboardObserver( this); @@ -273,7 +274,7 @@ void TrayIME::UpdateTrayLabel(const IMEInfo& current, size_t count) { if (tray_label_) { - bool visible = count > 1; + bool visible = count > 1 && is_visible_; tray_label_->SetVisible(visible); // Do not change label before hiding because this change is noticeable. if (!visible) @@ -368,9 +369,17 @@ Update(); } +void TrayIME::OnIMEMenuActivationChanged(bool is_active) { + is_visible_ = !is_active; + if (is_visible_) + OnIMERefresh(); + else + Update(); +} + bool TrayIME::ShouldDefaultViewBeVisible() { - return ime_list_.size() > 1 || property_list_.size() > 1 || - ShouldShowKeyboardToggle(); + return is_visible_ && (ime_list_.size() > 1 || property_list_.size() > 1 || + ShouldShowKeyboardToggle()); } } // namespace ash
diff --git a/ash/system/ime/tray_ime_chromeos.h b/ash/system/ime/tray_ime_chromeos.h index 7cf60cc..aad4afb 100644 --- a/ash/system/ime/tray_ime_chromeos.h +++ b/ash/system/ime/tray_ime_chromeos.h
@@ -69,6 +69,7 @@ // Overridden from IMEObserver. void OnIMERefresh() override; + void OnIMEMenuActivationChanged(bool is_active) override; // Whether the default view should be shown. bool ShouldDefaultViewBeVisible(); @@ -82,6 +83,8 @@ IMEInfoList ime_list_; IMEInfo current_ime_; IMEPropertyInfoList property_list_; + // Whether the IME label and tray items should be visible. + bool is_visible_; DISALLOW_COPY_AND_ASSIGN(TrayIME); };
diff --git a/ash/system/tray/system_tray_notifier.cc b/ash/system/tray/system_tray_notifier.cc index ec5bd8d..9432bf8 100644 --- a/ash/system/tray/system_tray_notifier.cc +++ b/ash/system/tray/system_tray_notifier.cc
@@ -275,6 +275,12 @@ OnIMERefresh()); } +void SystemTrayNotifier::NotifyRefreshIMEMenu(bool is_active) { + FOR_EACH_OBSERVER(IMEObserver, + ime_observers_, + OnIMEMenuActivationChanged(is_active)); +} + void SystemTrayNotifier::NotifyLocaleChanged( LocaleObserver::Delegate* delegate, const std::string& cur_locale,
diff --git a/ash/system/tray/system_tray_notifier.h b/ash/system/tray/system_tray_notifier.h index 6e92a7d..44e7c29 100644 --- a/ash/system/tray/system_tray_notifier.h +++ b/ash/system/tray/system_tray_notifier.h
@@ -126,6 +126,7 @@ void NotifySystemClockTimeUpdated(); void NotifySystemClockCanSetTimeChanged(bool can_set_time); void NotifyRefreshIME(); + void NotifyRefreshIMEMenu(bool is_active); void NotifyLocaleChanged(LocaleObserver::Delegate* delegate, const std::string& cur_locale, const std::string& from_locale,
diff --git a/base/BUILD.gn b/base/BUILD.gn index cfe258b..1fcd718 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -526,14 +526,14 @@ "metrics/histogram_delta_serialization.h", "metrics/histogram_flattener.h", "metrics/histogram_macros.h", - "metrics/histogram_persistence.cc", - "metrics/histogram_persistence.h", "metrics/histogram_samples.cc", "metrics/histogram_samples.h", "metrics/histogram_snapshot_manager.cc", "metrics/histogram_snapshot_manager.h", "metrics/metrics_hashes.cc", "metrics/metrics_hashes.h", + "metrics/persistent_histogram_allocator.cc", + "metrics/persistent_histogram_allocator.h", "metrics/persistent_memory_allocator.cc", "metrics/persistent_memory_allocator.h", "metrics/sample_map.cc", @@ -1738,6 +1738,7 @@ "metrics/histogram_snapshot_manager_unittest.cc", "metrics/histogram_unittest.cc", "metrics/metrics_hashes_unittest.cc", + "metrics/persistent_histogram_allocator_unittest.cc", "metrics/persistent_memory_allocator_unittest.cc", "metrics/sample_map_unittest.cc", "metrics/sample_vector_unittest.cc",
diff --git a/base/base.gyp b/base/base.gyp index 3f03dd8..d4e5be3 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -490,6 +490,7 @@ 'metrics/histogram_snapshot_manager_unittest.cc', 'metrics/histogram_unittest.cc', 'metrics/metrics_hashes_unittest.cc', + 'metrics/persistent_histogram_allocator_unittest.cc', 'metrics/persistent_memory_allocator_unittest.cc', 'metrics/sample_map_unittest.cc', 'metrics/sample_vector_unittest.cc',
diff --git a/base/base.gypi b/base/base.gypi index efcd8a3..4bf8ae61 100644 --- a/base/base.gypi +++ b/base/base.gypi
@@ -406,14 +406,14 @@ 'metrics/histogram_delta_serialization.h', 'metrics/histogram_flattener.h', 'metrics/histogram_macros.h', - 'metrics/histogram_persistence.cc', - 'metrics/histogram_persistence.h', 'metrics/histogram_samples.cc', 'metrics/histogram_samples.h', 'metrics/histogram_snapshot_manager.cc', 'metrics/histogram_snapshot_manager.h', 'metrics/metrics_hashes.cc', 'metrics/metrics_hashes.h', + 'metrics/persistent_histogram_allocator.cc', + 'metrics/persistent_histogram_allocator.h', 'metrics/persistent_memory_allocator.cc', 'metrics/persistent_memory_allocator.h', 'metrics/sample_map.cc',
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h index 9ba5e25c..006e1fd3 100644 --- a/base/memory/weak_ptr.h +++ b/base/memory/weak_ptr.h
@@ -161,10 +161,9 @@ // function that makes calling this easier. template<typename Derived> static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { - using convertible = - std::is_convertible<Derived*, internal::SupportsWeakPtrBase*>; - static_assert(convertible::value, - "AsWeakPtr argument must inherit from SupportsWeakPtr"); + static_assert( + std::is_base_of<internal::SupportsWeakPtrBase, Derived>::value, + "AsWeakPtr argument must inherit from SupportsWeakPtr"); return AsWeakPtrImpl<Derived>(t, *t); }
diff --git a/base/memory/weak_ptr_unittest.nc b/base/memory/weak_ptr_unittest.nc index bad1c97e..32deca9 100644 --- a/base/memory/weak_ptr_unittest.nc +++ b/base/memory/weak_ptr_unittest.nc
@@ -129,7 +129,7 @@ WeakPtr<Unrelated> ptr = AsWeakPtr(&f); } -#elif defined(NCTEST_AMBIGUOUS_ANCESTORS) // [r"fatal error: ambiguous conversion from derived class 'base::MultiplyDerivedProducer' to base class 'base::internal::SupportsWeakPtrBase':"] +#elif defined(NCTEST_AMBIGUOUS_ANCESTORS) // [r"fatal error: member 'AsWeakPtr' found in multiple base classes of different types"] void WontCompile() { MultiplyDerivedProducer f;
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index ea4f816..e8d851bf9 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc
@@ -19,8 +19,8 @@ #include "base/debug/alias.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" -#include "base/metrics/histogram_persistence.h" #include "base/metrics/metrics_hashes.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/metrics/persistent_memory_allocator.h" #include "base/metrics/sample_vector.h" #include "base/metrics/statistics_recorder.h" @@ -122,8 +122,8 @@ // Allocate the correct Histogram object off the heap (in case persistent // memory is not available). - virtual HistogramBase* HeapAlloc(const BucketRanges* ranges) { - return new Histogram(name_, minimum_, maximum_, ranges); + virtual scoped_ptr<HistogramBase> HeapAlloc(const BucketRanges* ranges) { + return make_scoped_ptr(new Histogram(name_, minimum_, maximum_, ranges)); } // Perform any required datafill on the just-created histogram. If @@ -151,7 +151,7 @@ // been added by other processes and they must be fetched and recognized // locally in order to be found by FindHistograms() below. If the persistent // memory segment is not shared between processes, this call does nothing. - ImportPersistentHistograms(); + PersistentHistogramAllocator::ImportGlobalHistograms(); HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_); if (!histogram) { @@ -176,14 +176,13 @@ // that is off by default. If the allocator doesn't exist or if // allocating from it fails, code below will allocate the histogram from // the process heap. - PersistentMemoryAllocator::Reference histogram_ref = 0; - HistogramBase* tentative_histogram = nullptr; - PersistentMemoryAllocator* allocator = - GetPersistentHistogramMemoryAllocator(); + PersistentHistogramAllocator::Reference histogram_ref = 0; + scoped_ptr<HistogramBase> tentative_histogram; + PersistentHistogramAllocator* allocator = + PersistentHistogramAllocator::GetGlobalAllocator(); if (allocator) { flags_ |= HistogramBase::kIsPersistent; - tentative_histogram = AllocatePersistentHistogram( - allocator, + tentative_histogram = allocator->AllocateHistogram( histogram_type_, name_, minimum_, @@ -202,14 +201,20 @@ tentative_histogram = HeapAlloc(registered_ranges); } - FillHistogram(tentative_histogram); - histogram = - StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); + FillHistogram(tentative_histogram.get()); + + // Register this histogram with the StatisticsRecorder. Keep a copy of + // the pointer value to tell later whether the locally created histogram + // was registered or deleted. The type is "void" because it could point + // to released memory after the following line. + const void* tentative_histogram_ptr = tentative_histogram.get(); + histogram = StatisticsRecorder::RegisterOrDeleteDuplicate( + tentative_histogram.release()); // Persistent histograms need some follow-up processing. if (histogram_ref) { - FinalizePersistentHistogram(histogram_ref, - histogram == tentative_histogram); + allocator->FinalizeHistogram(histogram_ref, + histogram == tentative_histogram_ptr); } } @@ -267,7 +272,7 @@ flags); } -HistogramBase* Histogram::PersistentGet( +scoped_ptr<HistogramBase> Histogram::PersistentCreate( const std::string& name, Sample minimum, Sample maximum, @@ -277,8 +282,9 @@ uint32_t counts_size, HistogramSamples::Metadata* meta, HistogramSamples::Metadata* logged_meta) { - return new Histogram(name, minimum, maximum, ranges, counts, logged_counts, - counts_size, meta, logged_meta); + return make_scoped_ptr(new Histogram( + name, minimum, maximum, ranges, counts, logged_counts, counts_size, + meta, logged_meta)); } // Calculate what range of values are held in each bucket. @@ -732,8 +738,9 @@ return ranges; } - HistogramBase* HeapAlloc(const BucketRanges* ranges) override { - return new LinearHistogram(name_, minimum_, maximum_, ranges); + scoped_ptr<HistogramBase> HeapAlloc(const BucketRanges* ranges) override { + return make_scoped_ptr( + new LinearHistogram(name_, minimum_, maximum_, ranges)); } void FillHistogram(HistogramBase* base_histogram) override { @@ -792,7 +799,7 @@ flags); } -HistogramBase* LinearHistogram::PersistentGet( +scoped_ptr<HistogramBase> LinearHistogram::PersistentCreate( const std::string& name, Sample minimum, Sample maximum, @@ -802,8 +809,9 @@ uint32_t counts_size, HistogramSamples::Metadata* meta, HistogramSamples::Metadata* logged_meta) { - return new LinearHistogram(name, minimum, maximum, ranges, counts, - logged_counts, counts_size, meta, logged_meta); + return make_scoped_ptr(new LinearHistogram( + name, minimum, maximum, ranges, counts, logged_counts, counts_size, + meta, logged_meta)); } HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( @@ -921,8 +929,8 @@ return ranges; } - HistogramBase* HeapAlloc(const BucketRanges* ranges) override { - return new BooleanHistogram(name_, ranges); + scoped_ptr<HistogramBase> HeapAlloc(const BucketRanges* ranges) override { + return make_scoped_ptr(new BooleanHistogram(name_, ranges)); } private: @@ -938,15 +946,15 @@ return FactoryGet(std::string(name), flags); } -HistogramBase* BooleanHistogram::PersistentGet( +scoped_ptr<HistogramBase> BooleanHistogram::PersistentCreate( const std::string& name, const BucketRanges* ranges, HistogramBase::AtomicCount* counts, HistogramBase::AtomicCount* logged_counts, HistogramSamples::Metadata* meta, HistogramSamples::Metadata* logged_meta) { - return new BooleanHistogram(name, ranges, counts, logged_counts, meta, - logged_meta); + return make_scoped_ptr(new BooleanHistogram( + name, ranges, counts, logged_counts, meta, logged_meta)); } HistogramType BooleanHistogram::GetHistogramType() const { @@ -1018,8 +1026,8 @@ return bucket_ranges; } - HistogramBase* HeapAlloc(const BucketRanges* ranges) override { - return new CustomHistogram(name_, ranges); + scoped_ptr<HistogramBase> HeapAlloc(const BucketRanges* ranges) override { + return make_scoped_ptr(new CustomHistogram(name_, ranges)); } private: @@ -1044,7 +1052,7 @@ return FactoryGet(std::string(name), custom_ranges, flags); } -HistogramBase* CustomHistogram::PersistentGet( +scoped_ptr<HistogramBase> CustomHistogram::PersistentCreate( const std::string& name, const BucketRanges* ranges, HistogramBase::AtomicCount* counts, @@ -1052,8 +1060,8 @@ uint32_t counts_size, HistogramSamples::Metadata* meta, HistogramSamples::Metadata* logged_meta) { - return new CustomHistogram(name, ranges, counts, logged_counts, counts_size, - meta, logged_meta); + return make_scoped_ptr(new CustomHistogram( + name, ranges, counts, logged_counts, counts_size, meta, logged_meta)); } HistogramType CustomHistogram::GetHistogramType() const {
diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h index ea59de64..5111b8f 100644 --- a/base/metrics/histogram.h +++ b/base/metrics/histogram.h
@@ -104,6 +104,8 @@ typedef std::vector<Count> Counts; + ~Histogram() override; + //---------------------------------------------------------------------------- // For a valid histogram, input should follow these restrictions: // minimum > 0 (if a minimum below 1 is specified, it will implicitly be @@ -139,16 +141,17 @@ uint32_t bucket_count, int32_t flags); - // Get a histogram using data in persistent storage. - static HistogramBase* PersistentGet(const std::string& name, - Sample minimum, - Sample maximum, - const BucketRanges* ranges, - HistogramBase::AtomicCount* counts, - HistogramBase::AtomicCount* logged_counts, - uint32_t counts_size, - HistogramSamples::Metadata* meta, - HistogramSamples::Metadata* logged_meta); + // Create a histogram using data in persistent storage. + static scoped_ptr<HistogramBase> PersistentCreate( + const std::string& name, + Sample minimum, + Sample maximum, + const BucketRanges* ranges, + HistogramBase::AtomicCount* counts, + HistogramBase::AtomicCount* logged_counts, + uint32_t counts_size, + HistogramSamples::Metadata* meta, + HistogramSamples::Metadata* logged_meta); static void InitializeBucketRanges(Sample minimum, Sample maximum, @@ -237,8 +240,6 @@ HistogramSamples::Metadata* meta, HistogramSamples::Metadata* logged_meta); - ~Histogram() override; - // HistogramBase implementation: bool SerializeInfoImpl(base::Pickle* pickle) const override; @@ -350,16 +351,17 @@ uint32_t bucket_count, int32_t flags); - // Get a histogram using data in persistent storage. - static HistogramBase* PersistentGet(const std::string& name, - Sample minimum, - Sample maximum, - const BucketRanges* ranges, - HistogramBase::AtomicCount* counts, - HistogramBase::AtomicCount* logged_counts, - uint32_t counts_size, - HistogramSamples::Metadata* meta, - HistogramSamples::Metadata* logged_meta); + // Create a histogram using data in persistent storage. + static scoped_ptr<HistogramBase> PersistentCreate( + const std::string& name, + Sample minimum, + Sample maximum, + const BucketRanges* ranges, + HistogramBase::AtomicCount* counts, + HistogramBase::AtomicCount* logged_counts, + uint32_t counts_size, + HistogramSamples::Metadata* meta, + HistogramSamples::Metadata* logged_meta); struct DescriptionPair { Sample sample; @@ -440,13 +442,14 @@ // call sites. static HistogramBase* FactoryGet(const char* name, int32_t flags); - // Get a histogram using data in persistent storage. - static HistogramBase* PersistentGet(const std::string& name, - const BucketRanges* ranges, - HistogramBase::AtomicCount* counts, - HistogramBase::AtomicCount* logged_counts, - HistogramSamples::Metadata* meta, - HistogramSamples::Metadata* logged_meta); + // Create a histogram using data in persistent storage. + static scoped_ptr<HistogramBase> PersistentCreate( + const std::string& name, + const BucketRanges* ranges, + HistogramBase::AtomicCount* counts, + HistogramBase::AtomicCount* logged_counts, + HistogramSamples::Metadata* meta, + HistogramSamples::Metadata* logged_meta); HistogramType GetHistogramType() const override; @@ -489,14 +492,15 @@ const std::vector<Sample>& custom_ranges, int32_t flags); - // Get a histogram using data in persistent storage. - static HistogramBase* PersistentGet(const std::string& name, - const BucketRanges* ranges, - HistogramBase::AtomicCount* counts, - HistogramBase::AtomicCount* logged_counts, - uint32_t counts_size, - HistogramSamples::Metadata* meta, - HistogramSamples::Metadata* logged_meta); + // Create a histogram using data in persistent storage. + static scoped_ptr<HistogramBase> PersistentCreate( + const std::string& name, + const BucketRanges* ranges, + HistogramBase::AtomicCount* counts, + HistogramBase::AtomicCount* logged_counts, + uint32_t counts_size, + HistogramSamples::Metadata* meta, + HistogramSamples::Metadata* logged_meta); // Overridden from Histogram: HistogramType GetHistogramType() const override;
diff --git a/base/metrics/histogram_persistence.cc b/base/metrics/histogram_persistence.cc deleted file mode 100644 index f18d175..0000000 --- a/base/metrics/histogram_persistence.cc +++ /dev/null
@@ -1,516 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/metrics/histogram_persistence.h" - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/metrics/histogram.h" -#include "base/metrics/histogram_base.h" -#include "base/metrics/histogram_samples.h" -#include "base/metrics/statistics_recorder.h" -#include "base/synchronization/lock.h" - -namespace base { - -namespace { - -// Enumerate possible creation results for reporting. -enum CreateHistogramResultType { - // Everything was fine. - CREATE_HISTOGRAM_SUCCESS = 0, - - // Pointer to metadata was not valid. - CREATE_HISTOGRAM_INVALID_METADATA_POINTER, - - // Histogram metadata was not valid. - CREATE_HISTOGRAM_INVALID_METADATA, - - // Ranges information was not valid. - CREATE_HISTOGRAM_INVALID_RANGES_ARRAY, - - // Counts information was not valid. - CREATE_HISTOGRAM_INVALID_COUNTS_ARRAY, - - // Could not allocate histogram memory due to corruption. - CREATE_HISTOGRAM_ALLOCATOR_CORRUPT, - - // Could not allocate histogram memory due to lack of space. - CREATE_HISTOGRAM_ALLOCATOR_FULL, - - // Could not allocate histogram memory due to unknown error. - CREATE_HISTOGRAM_ALLOCATOR_ERROR, - - // Histogram was of unknown type. - CREATE_HISTOGRAM_UNKNOWN_TYPE, - - // Instance has detected a corrupt allocator (recorded only once). - CREATE_HISTOGRAM_ALLOCATOR_NEWLY_CORRUPT, - - // Always keep this at the end. - CREATE_HISTOGRAM_MAX -}; - -// Name of histogram for storing results of local operations. -const char kResultHistogram[] = "UMA.CreatePersistentHistogram.Result"; - -// Type identifiers used when storing in persistent memory so they can be -// identified during extraction; the first 4 bytes of the SHA1 of the name -// is used as a unique integer. A "version number" is added to the base -// so that, if the structure of that object changes, stored older versions -// will be safely ignored. -enum : uint32_t { - kTypeIdHistogram = 0xF1645910 + 2, // SHA1(Histogram) v2 - kTypeIdRangesArray = 0xBCEA225A + 1, // SHA1(RangesArray) v1 - kTypeIdCountsArray = 0x53215530 + 1, // SHA1(CountsArray) v1 -}; - -// This data must be held in persistent memory in order for processes to -// locate and use histograms created elsewhere. All elements must be of a -// fixed width to ensure 32/64-bit interoperability. -struct PersistentHistogramData { - int32_t histogram_type; - int32_t flags; - int32_t minimum; - int32_t maximum; - uint32_t bucket_count; - PersistentMemoryAllocator::Reference ranges_ref; - uint32_t ranges_checksum; - PersistentMemoryAllocator::Reference counts_ref; - HistogramSamples::Metadata samples_metadata; - HistogramSamples::Metadata logged_metadata; - - // Space for the histogram name will be added during the actual allocation - // request. This must be the last field of the structure. A zero-size array - // or a "flexible" array would be preferred but is not (yet) valid C++. - char name[1]; -}; - -// The object held here will obviously not be destructed at process exit -// but that's okay since PersistentMemoryAllocator objects are explicitly -// forbidden from doing anything essential at exit anyway due to the fact -// that they depend on data managed elsewhere and which could be destructed -// first. -PersistentMemoryAllocator* g_allocator = nullptr; - -// Take an array of range boundaries and create a proper BucketRanges object -// which is returned to the caller. A return of nullptr indicates that the -// passed boundaries are invalid. -BucketRanges* CreateRangesFromData(HistogramBase::Sample* ranges_data, - uint32_t ranges_checksum, - size_t count) { - scoped_ptr<BucketRanges> ranges(new BucketRanges(count)); - DCHECK_EQ(count, ranges->size()); - for (size_t i = 0; i < count; ++i) { - if (i > 0 && ranges_data[i] <= ranges_data[i - 1]) - return nullptr; - ranges->set_range(i, ranges_data[i]); - } - - ranges->ResetChecksum(); - if (ranges->checksum() != ranges_checksum) - return nullptr; - - return ranges.release(); -} - -// Calculate the number of bytes required to store all of a histogram's -// "counts". This will return zero (0) if |bucket_count| is not valid. -size_t CalculateRequiredCountsBytes(size_t bucket_count) { - // 2 because each "sample count" also requires a backup "logged count" - // used for calculating the delta during snapshot operations. - const unsigned kBytesPerBucket = 2 * sizeof(HistogramBase::AtomicCount); - - // If the |bucket_count| is such that it would overflow the return type, - // perhaps as the result of a malicious actor, then return zero to - // indicate the problem to the caller. - if (bucket_count > std::numeric_limits<uint32_t>::max() / kBytesPerBucket) - return 0; - - return bucket_count * kBytesPerBucket; -} - -} // namespace - -const Feature kPersistentHistogramsFeature{ - "PersistentHistograms", FEATURE_DISABLED_BY_DEFAULT -}; - -// Get the histogram in which create results are stored. This is copied almost -// exactly from the STATIC_HISTOGRAM_POINTER_BLOCK macro but with added code -// to prevent recursion (a likely occurance because the creation of a new -// histogram can end up calling this.) -HistogramBase* GetCreateHistogramResultHistogram() { - static base::subtle::AtomicWord atomic_histogram_pointer = 0; - HistogramBase* histogram_pointer( - reinterpret_cast<HistogramBase*>( - base::subtle::Acquire_Load(&atomic_histogram_pointer))); - if (!histogram_pointer) { - // It's possible for multiple threads to make it here in parallel but - // they'll always return the same result as there is a mutex in the Get. - // The purpose of the "initialized" variable is just to ensure that - // the same thread doesn't recurse which is also why it doesn't have - // to be atomic. - static bool initialized = false; - if (!initialized) { - initialized = true; - if (g_allocator) { - DLOG(WARNING) << "Creating the results-histogram inside persistent" - << " memory can cause future allocations to crash if" - << " that memory is ever released (for testing)."; - } - - histogram_pointer = LinearHistogram::FactoryGet( - kResultHistogram, 1, CREATE_HISTOGRAM_MAX, CREATE_HISTOGRAM_MAX + 1, - HistogramBase::kUmaTargetedHistogramFlag); - base::subtle::Release_Store( - &atomic_histogram_pointer, - reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); - } - } - return histogram_pointer; -} - -// Record the result of a histogram creation. -void RecordCreateHistogramResult(CreateHistogramResultType result) { - HistogramBase* result_histogram = GetCreateHistogramResultHistogram(); - if (result_histogram) - result_histogram->Add(result); -} - -void SetPersistentHistogramMemoryAllocator( - PersistentMemoryAllocator* allocator) { - // Releasing or changing an allocator is extremely dangerous because it - // likely has histograms stored within it. If the backing memory is also - // also released, future accesses to those histograms will seg-fault. - CHECK(!g_allocator); - g_allocator = allocator; -} - -PersistentMemoryAllocator* GetPersistentHistogramMemoryAllocator() { - return g_allocator; -} - -PersistentMemoryAllocator* -ReleasePersistentHistogramMemoryAllocatorForTesting() { - PersistentMemoryAllocator* allocator = g_allocator; - if (!allocator) - return nullptr; - - // Before releasing the memory, it's necessary to have the Statistics- - // Recorder forget about the histograms contained therein; otherwise, - // some operations will try to access them and the released memory. - PersistentMemoryAllocator::Iterator iter; - PersistentMemoryAllocator::Reference ref; - uint32_t type_id; - allocator->CreateIterator(&iter); - while ((ref = allocator->GetNextIterable(&iter, &type_id)) != 0) { - if (type_id == kTypeIdHistogram) { - PersistentHistogramData* histogram_data = - allocator->GetAsObject<PersistentHistogramData>( - ref, kTypeIdHistogram); - DCHECK(histogram_data); - StatisticsRecorder::ForgetHistogramForTesting(histogram_data->name); - - // If a test breaks here then a memory region containing a histogram - // actively used by this code is being released back to the test. - // If that memory segment were to be deleted, future calls to create - // persistent histograms would crash. To avoid this, have the test call - // the method GetCreateHistogramResultHistogram() *before* setting the - // (temporary) memory allocator via SetPersistentMemoryAllocator() so - // that the histogram is instead allocated from the process heap. - DCHECK_NE(kResultHistogram, histogram_data->name); - } - } - - g_allocator = nullptr; - return allocator; -}; - -HistogramBase* CreatePersistentHistogram( - PersistentMemoryAllocator* allocator, - PersistentHistogramData* histogram_data_ptr) { - if (!histogram_data_ptr) { - RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA_POINTER); - NOTREACHED(); - return nullptr; - } - - // Copy the histogram_data to local storage because anything in persistent - // memory cannot be trusted as it could be changed at any moment by a - // malicious actor that shares access. The contents of histogram_data are - // validated below; the local copy is to ensure that the contents cannot - // be externally changed between validation and use. - PersistentHistogramData histogram_data = *histogram_data_ptr; - - HistogramBase::Sample* ranges_data = - allocator->GetAsObject<HistogramBase::Sample>(histogram_data.ranges_ref, - kTypeIdRangesArray); - if (!ranges_data || histogram_data.bucket_count < 2 || - histogram_data.bucket_count + 1 > - std::numeric_limits<uint32_t>::max() / - sizeof(HistogramBase::Sample) || - allocator->GetAllocSize(histogram_data.ranges_ref) < - (histogram_data.bucket_count + 1) * sizeof(HistogramBase::Sample)) { - RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); - NOTREACHED(); - return nullptr; - } - // To avoid racy destruction at shutdown, the following will be leaked. - const BucketRanges* ranges = CreateRangesFromData( - ranges_data, - histogram_data.ranges_checksum, - histogram_data.bucket_count + 1); - if (!ranges) { - RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); - NOTREACHED(); - return nullptr; - } - ranges = StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); - - HistogramBase::AtomicCount* counts_data = - allocator->GetAsObject<HistogramBase::AtomicCount>( - histogram_data.counts_ref, kTypeIdCountsArray); - size_t counts_bytes = - CalculateRequiredCountsBytes(histogram_data.bucket_count); - if (!counts_data || !counts_bytes || - allocator->GetAllocSize(histogram_data.counts_ref) < counts_bytes) { - RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_COUNTS_ARRAY); - NOTREACHED(); - return nullptr; - } - - // After the main "counts" array is a second array using for storing what - // was previously logged. This is used to calculate the "delta" during - // snapshot operations. - HistogramBase::AtomicCount* logged_data = - counts_data + histogram_data.bucket_count; - - std::string name(histogram_data_ptr->name); - HistogramBase* histogram = nullptr; - switch (histogram_data.histogram_type) { - case HISTOGRAM: - histogram = Histogram::PersistentGet( - name, - histogram_data.minimum, - histogram_data.maximum, - ranges, - counts_data, - logged_data, - histogram_data.bucket_count, - &histogram_data_ptr->samples_metadata, - &histogram_data_ptr->logged_metadata); - DCHECK(histogram); - break; - case LINEAR_HISTOGRAM: - histogram = LinearHistogram::PersistentGet( - name, - histogram_data.minimum, - histogram_data.maximum, - ranges, - counts_data, - logged_data, - histogram_data.bucket_count, - &histogram_data_ptr->samples_metadata, - &histogram_data_ptr->logged_metadata); - DCHECK(histogram); - break; - case BOOLEAN_HISTOGRAM: - histogram = BooleanHistogram::PersistentGet( - name, - ranges, - counts_data, - logged_data, - &histogram_data_ptr->samples_metadata, - &histogram_data_ptr->logged_metadata); - DCHECK(histogram); - break; - case CUSTOM_HISTOGRAM: - histogram = CustomHistogram::PersistentGet( - name, - ranges, - counts_data, - logged_data, - histogram_data.bucket_count, - &histogram_data_ptr->samples_metadata, - &histogram_data_ptr->logged_metadata); - DCHECK(histogram); - break; - default: - NOTREACHED(); - } - - if (histogram) { - DCHECK_EQ(histogram_data.histogram_type, histogram->GetHistogramType()); - histogram->SetFlags(histogram_data.flags); - RecordCreateHistogramResult(CREATE_HISTOGRAM_SUCCESS); - } else { - RecordCreateHistogramResult(CREATE_HISTOGRAM_UNKNOWN_TYPE); - } - - return histogram; -} - -HistogramBase* GetPersistentHistogram( - PersistentMemoryAllocator* allocator, - int32_t ref) { - // Unfortunately, the above "pickle" methods cannot be used as part of the - // persistance because the deserialization methods always create local - // count data (these must referenced the persistent counts) and always add - // it to the local list of known histograms (these may be simple references - // to histograms in other processes). - PersistentHistogramData* histogram_data = - allocator->GetAsObject<PersistentHistogramData>(ref, kTypeIdHistogram); - size_t length = allocator->GetAllocSize(ref); - if (!histogram_data || - reinterpret_cast<char*>(histogram_data)[length - 1] != '\0') { - RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA); - NOTREACHED(); - return nullptr; - } - return CreatePersistentHistogram(allocator, histogram_data); -} - -HistogramBase* GetNextPersistentHistogram( - PersistentMemoryAllocator* allocator, - PersistentMemoryAllocator::Iterator* iter) { - PersistentMemoryAllocator::Reference ref; - uint32_t type_id; - while ((ref = allocator->GetNextIterable(iter, &type_id)) != 0) { - if (type_id == kTypeIdHistogram) - return GetPersistentHistogram(allocator, ref); - } - return nullptr; -} - -void FinalizePersistentHistogram(PersistentMemoryAllocator::Reference ref, - bool registered) { - // If the created persistent histogram was registered then it needs to - // be marked as "iterable" in order to be found by other processes. - if (registered) - GetPersistentHistogramMemoryAllocator()->MakeIterable(ref); - // If it wasn't registered then a race condition must have caused - // two to be created. The allocator does not support releasing the - // acquired memory so just change the type to be empty. - else - GetPersistentHistogramMemoryAllocator()->SetType(ref, 0); -} - -HistogramBase* AllocatePersistentHistogram( - PersistentMemoryAllocator* allocator, - HistogramType histogram_type, - const std::string& name, - int minimum, - int maximum, - const BucketRanges* bucket_ranges, - int32_t flags, - PersistentMemoryAllocator::Reference* ref_ptr) { - if (!allocator) - return nullptr; - - // If the allocator is corrupt, don't waste time trying anything else. - // This also allows differentiating on the dashboard between allocations - // failed due to a corrupt allocator and the number of process instances - // with one, the latter being idicated by "newly corrupt", below. - if (allocator->IsCorrupt()) { - RecordCreateHistogramResult(CREATE_HISTOGRAM_ALLOCATOR_CORRUPT); - return nullptr; - } - - // If CalculateRequiredCountsBytes() returns zero then the bucket_count - // was not valid. - size_t bucket_count = bucket_ranges->bucket_count(); - size_t counts_bytes = CalculateRequiredCountsBytes(bucket_count); - if (!counts_bytes) { - NOTREACHED(); - return nullptr; - } - - size_t ranges_bytes = (bucket_count + 1) * sizeof(HistogramBase::Sample); - PersistentMemoryAllocator::Reference ranges_ref = - allocator->Allocate(ranges_bytes, kTypeIdRangesArray); - PersistentMemoryAllocator::Reference counts_ref = - allocator->Allocate(counts_bytes, kTypeIdCountsArray); - PersistentMemoryAllocator::Reference histogram_ref = - allocator->Allocate(offsetof(PersistentHistogramData, name) + - name.length() + 1, kTypeIdHistogram); - HistogramBase::Sample* ranges_data = - allocator->GetAsObject<HistogramBase::Sample>(ranges_ref, - kTypeIdRangesArray); - PersistentHistogramData* histogram_data = - allocator->GetAsObject<PersistentHistogramData>(histogram_ref, - kTypeIdHistogram); - - // Only continue here if all allocations were successful. If they weren't - // there is no way to free the space but that's not really a problem since - // the allocations only fail because the space is full and so any future - // attempts will also fail. - if (counts_ref && ranges_data && histogram_data) { - strcpy(histogram_data->name, name.c_str()); - for (size_t i = 0; i < bucket_ranges->size(); ++i) - ranges_data[i] = bucket_ranges->range(i); - - histogram_data->histogram_type = histogram_type; - histogram_data->flags = flags; - histogram_data->minimum = minimum; - histogram_data->maximum = maximum; - histogram_data->bucket_count = static_cast<uint32_t>(bucket_count); - histogram_data->ranges_ref = ranges_ref; - histogram_data->ranges_checksum = bucket_ranges->checksum(); - histogram_data->counts_ref = counts_ref; - - // Create the histogram using resources in persistent memory. This ends up - // resolving the "ref" values stored in histogram_data instad of just - // using what is already known above but avoids duplicating the switch - // statement here and serves as a double-check that everything is - // correct before commiting the new histogram to persistent space. - HistogramBase* histogram = - CreatePersistentHistogram(allocator, histogram_data); - DCHECK(histogram); - if (ref_ptr != nullptr) - *ref_ptr = histogram_ref; - return histogram; - } - - CreateHistogramResultType result; - if (allocator->IsCorrupt()) { - RecordCreateHistogramResult(CREATE_HISTOGRAM_ALLOCATOR_NEWLY_CORRUPT); - result = CREATE_HISTOGRAM_ALLOCATOR_CORRUPT; - } else if (allocator->IsFull()) { - result = CREATE_HISTOGRAM_ALLOCATOR_FULL; - } else { - result = CREATE_HISTOGRAM_ALLOCATOR_ERROR; - } - RecordCreateHistogramResult(result); - NOTREACHED() << "error=" << result; - - return nullptr; -} - -void ImportPersistentHistograms() { - // The lock protects against concurrent access to the iterator and is created - // in a thread-safe manner when needed. - static base::LazyInstance<base::Lock>::Leaky lock = LAZY_INSTANCE_INITIALIZER; - - if (g_allocator) { - base::AutoLock auto_lock(lock.Get()); - - // Each call resumes from where it last left off so need persistant - // iterator. This class has a constructor so even the definition has - // to be protected by the lock in order to be thread-safe. - static PersistentMemoryAllocator::Iterator iter; - if (iter.is_clear()) - g_allocator->CreateIterator(&iter); - - while (true) { - HistogramBase* histogram = GetNextPersistentHistogram(g_allocator, &iter); - if (!histogram) - break; - StatisticsRecorder::RegisterOrDeleteDuplicate(histogram); - } - } -} - -} // namespace base
diff --git a/base/metrics/histogram_persistence.h b/base/metrics/histogram_persistence.h deleted file mode 100644 index 95f4878..0000000 --- a/base/metrics/histogram_persistence.h +++ /dev/null
@@ -1,91 +0,0 @@ -// Copyright (c) 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. - -#ifndef BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ -#define BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ - -#include "base/base_export.h" -#include "base/feature_list.h" -#include "base/memory/scoped_ptr.h" -#include "base/metrics/histogram_base.h" -#include "base/metrics/persistent_memory_allocator.h" - -namespace base { - -// Feature definition for enabling histogram persistence. -BASE_EXPORT extern const Feature kPersistentHistogramsFeature; - -// Histogram containing creation results. Visible for testing. -BASE_EXPORT HistogramBase* GetCreateHistogramResultHistogram(); - -// Access a PersistentMemoryAllocator for storing histograms in space that -// can be persisted or shared between processes. There is only ever one -// allocator for all such histograms created by a single process though one -// process may access the histograms created by other processes if it has a -// handle on its memory segment. This takes ownership of the object and -// should not be changed without great care as it is likely that there will -// be pointers to data held in that space. It should be called as soon as -// possible during startup to capture as many histograms as possible and -// while operating single-threaded so there are no race-conditions. -BASE_EXPORT void SetPersistentHistogramMemoryAllocator( - PersistentMemoryAllocator* allocator); -BASE_EXPORT PersistentMemoryAllocator* GetPersistentHistogramMemoryAllocator(); - -// This access to the persistent allocator is only for testing; it extracts -// the current allocator completely. This allows easy creation of histograms -// within persistent memory segments which can then be extracted and used -// in other ways. -BASE_EXPORT PersistentMemoryAllocator* -ReleasePersistentHistogramMemoryAllocatorForTesting(); - -// Recreate a Histogram from data held in persistent memory. Though this -// object will be local to the current process, the sample data will be -// shared with all other threads referencing it. This method takes a |ref| -// to the top- level histogram data and the |allocator| on which it is found. -// This method will return nullptr if any problem is detected with the data. -// The |allocator| may or may not be the same as the PersistentMemoryAllocator -// set for general use so that this method can be used to extract Histograms -// from persistent memory segments other than the default place that this -// process is creating its own histograms. The caller must take ownership of -// the returned object and destroy it when no longer needed. -BASE_EXPORT HistogramBase* GetPersistentHistogram( - PersistentMemoryAllocator* allocator, - int32_t ref); - -// Get the next histogram in persistent data based on iterator. The caller -// must take ownership of the returned object and destroy it when no longer -// needed. -BASE_EXPORT HistogramBase* GetNextPersistentHistogram( - PersistentMemoryAllocator* allocator, - PersistentMemoryAllocator::Iterator* iter); - -// Finalize the creation of the histogram, making it available to other -// processes if it is the registered instance. -void FinalizePersistentHistogram(PersistentMemoryAllocator::Reference ref, - bool register); - -// Allocate a new persistent histogram. This does *not* make the object -// iterable in the allocator; call MakeIterable(ref) directly if that is -// desired. -BASE_EXPORT HistogramBase* AllocatePersistentHistogram( - PersistentMemoryAllocator* allocator, - HistogramType histogram_type, - const std::string& name, - int minimum, - int maximum, - const BucketRanges* bucket_ranges, - int32_t flags, - PersistentMemoryAllocator::Reference* ref_ptr); - -// Import new histograms from attached PersistentMemoryAllocator. It's -// possible for other processes to create histograms in the attached memory -// segment; this adds those to the internal list of known histograms to -// avoid creating duplicates that would have to merged during reporting. -// Every call to this method resumes from the last entry it saw so it costs -// nothing if nothing new has been added. -void ImportPersistentHistograms(); - -} // namespace base - -#endif // BASE_METRICS_HISTOGRAM_PERSISTENCE_H_
diff --git a/base/metrics/histogram_samples.h b/base/metrics/histogram_samples.h index 29fbe17..30bff84 100644 --- a/base/metrics/histogram_samples.h +++ b/base/metrics/histogram_samples.h
@@ -22,7 +22,7 @@ // HistogramSamples is a container storing all samples of a histogram. All // elements must be of a fixed width to ensure 32/64-bit interoperability. // If this structure changes, bump the version number for kTypeIdHistogram -// in histogram_persistence.cc. +// in persistent_histogram_allocator.cc. class BASE_EXPORT HistogramSamples { public: struct Metadata {
diff --git a/base/metrics/histogram_unittest.cc b/base/metrics/histogram_unittest.cc index beb6a71..f621ec5 100644 --- a/base/metrics/histogram_unittest.cc +++ b/base/metrics/histogram_unittest.cc
@@ -16,7 +16,7 @@ #include "base/memory/scoped_ptr.h" #include "base/metrics/bucket_ranges.h" #include "base/metrics/histogram_macros.h" -#include "base/metrics/histogram_persistence.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/metrics/persistent_memory_allocator.h" #include "base/metrics/sample_vector.h" #include "base/metrics/statistics_recorder.h" @@ -41,7 +41,7 @@ // registered). InitializeStatisticsRecorder(); if (use_persistent_histogram_allocator_) - CreatePersistentMemoryAllocator(); + CreatePersistentHistogramAllocator(); } void TearDown() override { @@ -50,7 +50,7 @@ ASSERT_FALSE(allocator_->IsCorrupt()); } UninitializeStatisticsRecorder(); - DestroyPersistentMemoryAllocator(); + DestroyPersistentHistogramAllocator(); } void InitializeStatisticsRecorder() { @@ -63,27 +63,27 @@ statistics_recorder_ = NULL; } - void CreatePersistentMemoryAllocator() { + void CreatePersistentHistogramAllocator() { // By getting the results-histogram before any persistent allocator // is attached, that histogram is guaranteed not to be stored in // any persistent memory segment (which simplifies some tests). - GetCreateHistogramResultHistogram(); + PersistentHistogramAllocator::GetCreateHistogramResultHistogram(); if (!allocator_memory_) allocator_memory_.reset(new char[kAllocatorMemorySize]); - delete ReleasePersistentHistogramMemoryAllocatorForTesting(); + PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting(); memset(allocator_memory_.get(), 0, kAllocatorMemorySize); - SetPersistentHistogramMemoryAllocator( - new PersistentMemoryAllocator( - allocator_memory_.get(), kAllocatorMemorySize, 0, - 0, "HistogramAllocatorTest", false)); - allocator_ = GetPersistentHistogramMemoryAllocator(); + PersistentHistogramAllocator::CreateGlobalAllocatorOnPersistentMemory( + allocator_memory_.get(), kAllocatorMemorySize, 0, 0, + "HistogramAllocatorTest"); + allocator_ = + PersistentHistogramAllocator::GetGlobalAllocator()->memory_allocator(); } - void DestroyPersistentMemoryAllocator() { + void DestroyPersistentHistogramAllocator() { allocator_ = nullptr; - delete ReleasePersistentHistogramMemoryAllocatorForTesting(); + PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting(); } const bool use_persistent_histogram_allocator_; @@ -97,8 +97,7 @@ }; // Run all HistogramTest cases with both heap and persistent memory. -INSTANTIATE_TEST_CASE_P(HeapAndPersistent, HistogramTest, - testing::Bool()); +INSTANTIATE_TEST_CASE_P(HeapAndPersistent, HistogramTest, testing::Bool()); // Check for basic syntax and use. @@ -126,94 +125,6 @@ LOCAL_HISTOGRAM_ENUMERATION("Test6Histogram", 129, 130); } -// Check for basic syntax and use with persistent allocator. -TEST_P(HistogramTest, PersistentTest) { - if (!use_persistent_histogram_allocator_) - return; - - PersistentMemoryAllocator::MemoryInfo meminfo0; - allocator_->GetMemoryInfo(&meminfo0); - - // Try basic construction - HistogramBase* histogram = Histogram::FactoryGet( - "TestHistogram", 1, 1000, 10, - HistogramBase::kIsPersistent); - EXPECT_TRUE(histogram); - histogram->CheckName("TestHistogram"); - PersistentMemoryAllocator::MemoryInfo meminfo1; - allocator_->GetMemoryInfo(&meminfo1); - EXPECT_GT(meminfo0.free, meminfo1.free); - - HistogramBase* linear_histogram = LinearHistogram::FactoryGet( - "TestLinearHistogram", 1, 1000, 10, - HistogramBase::kIsPersistent); - EXPECT_TRUE(linear_histogram); - linear_histogram->CheckName("TestLinearHistogram"); - PersistentMemoryAllocator::MemoryInfo meminfo2; - allocator_->GetMemoryInfo(&meminfo2); - EXPECT_GT(meminfo1.free, meminfo2.free); - - HistogramBase* boolean_histogram = BooleanHistogram::FactoryGet( - "TestBooleanHistogram", HistogramBase::kIsPersistent); - EXPECT_TRUE(boolean_histogram); - boolean_histogram->CheckName("TestBooleanHistogram"); - PersistentMemoryAllocator::MemoryInfo meminfo3; - allocator_->GetMemoryInfo(&meminfo3); - EXPECT_GT(meminfo2.free, meminfo3.free); - - std::vector<int> custom_ranges; - custom_ranges.push_back(1); - custom_ranges.push_back(5); - HistogramBase* custom_histogram = CustomHistogram::FactoryGet( - "TestCustomHistogram", custom_ranges, - HistogramBase::kIsPersistent); - EXPECT_TRUE(custom_histogram); - custom_histogram->CheckName("TestCustomHistogram"); - PersistentMemoryAllocator::MemoryInfo meminfo4; - allocator_->GetMemoryInfo(&meminfo4); - EXPECT_GT(meminfo3.free, meminfo4.free); - - PersistentMemoryAllocator::Iterator iter; - uint32_t type; - allocator_->CreateIterator(&iter); - EXPECT_NE(0U, allocator_->GetNextIterable(&iter, &type)); // Histogram - EXPECT_NE(0U, allocator_->GetNextIterable(&iter, &type)); // LinearHistogram - EXPECT_NE(0U, allocator_->GetNextIterable(&iter, &type)); // BooleanHistogram - EXPECT_NE(0U, allocator_->GetNextIterable(&iter, &type)); // CustomHistogram - EXPECT_EQ(0U, allocator_->GetNextIterable(&iter, &type)); - - // Create a second allocator and have it access the memory of the first. - scoped_ptr<HistogramBase> recovered; - PersistentMemoryAllocator recovery( - allocator_memory_.get(), kAllocatorMemorySize, 0, - 0, std::string(), false); - recovery.CreateIterator(&iter); - - recovered.reset(GetNextPersistentHistogram(&recovery, &iter)); - ASSERT_TRUE(recovered); - recovered->CheckName("TestHistogram"); - - recovered.reset(GetNextPersistentHistogram(&recovery, &iter)); - ASSERT_TRUE(recovered); - recovered->CheckName("TestLinearHistogram"); - - recovered.reset(GetNextPersistentHistogram(&recovery, &iter)); - ASSERT_TRUE(recovered); - recovered->CheckName("TestBooleanHistogram"); - - recovered.reset(GetNextPersistentHistogram(&recovery, &iter)); - ASSERT_TRUE(recovered); - recovered->CheckName("TestCustomHistogram"); - - recovered.reset(GetNextPersistentHistogram(&recovery, &iter)); - EXPECT_FALSE(recovered); - - // Use standard macros (but with fixed samples) - LOCAL_HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1)); - LOCAL_HISTOGRAM_COUNTS("Test3Histogram", 30); - LOCAL_HISTOGRAM_ENUMERATION("Test6Histogram", 129, 130); -} - // Check that the macro correctly matches histograms by name and records their // data together. TEST_P(HistogramTest, NameMatchTest) {
diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc new file mode 100644 index 0000000..1929060 --- /dev/null +++ b/base/metrics/persistent_histogram_allocator.cc
@@ -0,0 +1,554 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/metrics/persistent_histogram_allocator.h" + +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_base.h" +#include "base/metrics/histogram_samples.h" +#include "base/metrics/statistics_recorder.h" +#include "base/synchronization/lock.h" + +// TODO(bcwhite): Order these methods to match the header file. The current +// order is only temporary in order to aid review of the transition from +// a non-class implementation. + +namespace base { + +namespace { + +// Name of histogram for storing results of local operations. +const char kResultHistogram[] = "UMA.CreatePersistentHistogram.Result"; + +// Type identifiers used when storing in persistent memory so they can be +// identified during extraction; the first 4 bytes of the SHA1 of the name +// is used as a unique integer. A "version number" is added to the base +// so that, if the structure of that object changes, stored older versions +// will be safely ignored. +enum : uint32_t { + kTypeIdHistogram = 0xF1645910 + 2, // SHA1(Histogram) v2 + kTypeIdRangesArray = 0xBCEA225A + 1, // SHA1(RangesArray) v1 + kTypeIdCountsArray = 0x53215530 + 1, // SHA1(CountsArray) v1 +}; + +// The current globally-active persistent allocator for all new histograms. +// The object held here will obviously not be destructed at process exit +// but that's best since PersistentMemoryAllocator objects (that underlie +// PersistentHistogramAllocator objects) are explicitly forbidden from doing +// anything essential at exit anyway due to the fact that they depend on data +// managed elsewhere and which could be destructed first. +PersistentHistogramAllocator* g_allocator; + +// Take an array of range boundaries and create a proper BucketRanges object +// which is returned to the caller. A return of nullptr indicates that the +// passed boundaries are invalid. +scoped_ptr<BucketRanges> CreateRangesFromData( + HistogramBase::Sample* ranges_data, + uint32_t ranges_checksum, + size_t count) { + // To avoid racy destruction at shutdown, the following may be leaked. + scoped_ptr<BucketRanges> ranges(new BucketRanges(count)); + DCHECK_EQ(count, ranges->size()); + for (size_t i = 0; i < count; ++i) { + if (i > 0 && ranges_data[i] <= ranges_data[i - 1]) + return nullptr; + ranges->set_range(i, ranges_data[i]); + } + + ranges->ResetChecksum(); + if (ranges->checksum() != ranges_checksum) + return nullptr; + + return ranges; +} + +// Calculate the number of bytes required to store all of a histogram's +// "counts". This will return zero (0) if |bucket_count| is not valid. +size_t CalculateRequiredCountsBytes(size_t bucket_count) { + // 2 because each "sample count" also requires a backup "logged count" + // used for calculating the delta during snapshot operations. + const unsigned kBytesPerBucket = 2 * sizeof(HistogramBase::AtomicCount); + + // If the |bucket_count| is such that it would overflow the return type, + // perhaps as the result of a malicious actor, then return zero to + // indicate the problem to the caller. + if (bucket_count > std::numeric_limits<uint32_t>::max() / kBytesPerBucket) + return 0; + + return bucket_count * kBytesPerBucket; +} + +} // namespace + +const Feature kPersistentHistogramsFeature{ + "PersistentHistograms", FEATURE_DISABLED_BY_DEFAULT +}; + +// This data will be held in persistent memory in order for processes to +// locate and use histograms created elsewhere. +struct PersistentHistogramAllocator::PersistentHistogramData { + int32_t histogram_type; + int32_t flags; + int32_t minimum; + int32_t maximum; + uint32_t bucket_count; + PersistentMemoryAllocator::Reference ranges_ref; + uint32_t ranges_checksum; + PersistentMemoryAllocator::Reference counts_ref; + HistogramSamples::Metadata samples_metadata; + HistogramSamples::Metadata logged_metadata; + + // Space for the histogram name will be added during the actual allocation + // request. This must be the last field of the structure. A zero-size array + // or a "flexible" array would be preferred but is not (yet) valid C++. + char name[1]; +}; + +PersistentHistogramAllocator::PersistentHistogramAllocator( + scoped_ptr<PersistentMemoryAllocator> memory) + : memory_allocator_(std::move(memory)) {} + +PersistentHistogramAllocator::~PersistentHistogramAllocator() {} + +void PersistentHistogramAllocator::CreateIterator(Iterator* iter) { + memory_allocator_->CreateIterator(&iter->memory_iter); +} + +void PersistentHistogramAllocator::CreateTrackingHistograms(StringPiece name) { + memory_allocator_->CreateTrackingHistograms(name); +} + +void PersistentHistogramAllocator::UpdateTrackingHistograms() { + memory_allocator_->UpdateTrackingHistograms(); +} + +// static +HistogramBase* +PersistentHistogramAllocator::GetCreateHistogramResultHistogram() { + // Get the histogram in which create-results are stored. This is copied + // almost exactly from the STATIC_HISTOGRAM_POINTER_BLOCK macro but with + // added code to prevent recursion (a likely occurance because the creation + // of a new a histogram can end up calling this.) + static base::subtle::AtomicWord atomic_histogram_pointer = 0; + HistogramBase* histogram_pointer = + reinterpret_cast<HistogramBase*>( + base::subtle::Acquire_Load(&atomic_histogram_pointer)); + if (!histogram_pointer) { + // It's possible for multiple threads to make it here in parallel but + // they'll always return the same result as there is a mutex in the Get. + // The purpose of the "initialized" variable is just to ensure that + // the same thread doesn't recurse which is also why it doesn't have + // to be atomic. + static bool initialized = false; + if (!initialized) { + initialized = true; + if (g_allocator) { + DLOG(WARNING) << "Creating the results-histogram inside persistent" + << " memory can cause future allocations to crash if" + << " that memory is ever released (for testing)."; + } + + histogram_pointer = LinearHistogram::FactoryGet( + kResultHistogram, 1, CREATE_HISTOGRAM_MAX, CREATE_HISTOGRAM_MAX + 1, + HistogramBase::kUmaTargetedHistogramFlag); + base::subtle::Release_Store( + &atomic_histogram_pointer, + reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); + } + } + return histogram_pointer; +} + +// static +void PersistentHistogramAllocator::RecordCreateHistogramResult( + CreateHistogramResultType result) { + HistogramBase* result_histogram = GetCreateHistogramResultHistogram(); + if (result_histogram) + result_histogram->Add(result); +} + +// static +void PersistentHistogramAllocator::SetGlobalAllocator( + scoped_ptr<PersistentHistogramAllocator> allocator) { + // Releasing or changing an allocator is extremely dangerous because it + // likely has histograms stored within it. If the backing memory is also + // also released, future accesses to those histograms will seg-fault. + CHECK(!g_allocator); + g_allocator = allocator.release(); +} + +// static +PersistentHistogramAllocator* +PersistentHistogramAllocator::GetGlobalAllocator() { + return g_allocator; +} + +// static +scoped_ptr<PersistentHistogramAllocator> +PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting() { + PersistentHistogramAllocator* histogram_allocator = g_allocator; + if (!histogram_allocator) + return nullptr; + PersistentMemoryAllocator* memory_allocator = + histogram_allocator->memory_allocator(); + + // Before releasing the memory, it's necessary to have the Statistics- + // Recorder forget about the histograms contained therein; otherwise, + // some operations will try to access them and the released memory. + PersistentMemoryAllocator::Iterator iter; + PersistentMemoryAllocator::Reference ref; + uint32_t type_id; + memory_allocator->CreateIterator(&iter); + while ((ref = memory_allocator->GetNextIterable(&iter, &type_id)) != 0) { + if (type_id == kTypeIdHistogram) { + PersistentHistogramData* histogram_data = + memory_allocator->GetAsObject<PersistentHistogramData>( + ref, kTypeIdHistogram); + DCHECK(histogram_data); + StatisticsRecorder::ForgetHistogramForTesting(histogram_data->name); + + // If a test breaks here then a memory region containing a histogram + // actively used by this code is being released back to the test. + // If that memory segment were to be deleted, future calls to create + // persistent histograms would crash. To avoid this, have the test call + // the method GetCreateHistogramResultHistogram() *before* setting + // the (temporary) memory allocator via SetGlobalAllocator() so that + // histogram is instead allocated from the process heap. + DCHECK_NE(kResultHistogram, histogram_data->name); + } + } + + g_allocator = nullptr; + return make_scoped_ptr(histogram_allocator); +}; + +// static +void PersistentHistogramAllocator::CreateGlobalAllocatorOnPersistentMemory( + void* base, + size_t size, + size_t page_size, + uint64_t id, + StringPiece name) { + SetGlobalAllocator(make_scoped_ptr(new PersistentHistogramAllocator( + make_scoped_ptr(new PersistentMemoryAllocator( + base, size, page_size, id, name, false))))); +} + +// static +void PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory( + size_t size, + uint64_t id, + StringPiece name) { + SetGlobalAllocator(make_scoped_ptr(new PersistentHistogramAllocator( + make_scoped_ptr(new LocalPersistentMemoryAllocator(size, id, name))))); +} + +// static +void PersistentHistogramAllocator::CreateGlobalAllocatorOnSharedMemory( + size_t size, + const SharedMemoryHandle& handle) { + scoped_ptr<SharedMemory> shm(new SharedMemory(handle, /*readonly=*/false)); + if (!shm->Map(size)) { + NOTREACHED(); + return; + } + + SetGlobalAllocator(make_scoped_ptr(new PersistentHistogramAllocator( + make_scoped_ptr(new SharedPersistentMemoryAllocator( + std::move(shm), 0, StringPiece(), /*readonly=*/false))))); +} + +// static +scoped_ptr<HistogramBase> PersistentHistogramAllocator::CreateHistogram( + PersistentHistogramData* histogram_data_ptr) { + if (!histogram_data_ptr) { + RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA_POINTER); + NOTREACHED(); + return nullptr; + } + + // Copy the histogram_data to local storage because anything in persistent + // memory cannot be trusted as it could be changed at any moment by a + // malicious actor that shares access. The contents of histogram_data are + // validated below; the local copy is to ensure that the contents cannot + // be externally changed between validation and use. + PersistentHistogramData histogram_data = *histogram_data_ptr; + + HistogramBase::Sample* ranges_data = + memory_allocator_->GetAsObject<HistogramBase::Sample>( + histogram_data.ranges_ref, kTypeIdRangesArray); + + const uint32_t max_buckets = + std::numeric_limits<uint32_t>::max() / sizeof(HistogramBase::Sample); + size_t required_bytes = + (histogram_data.bucket_count + 1) * sizeof(HistogramBase::Sample); + size_t allocated_bytes = + memory_allocator_->GetAllocSize(histogram_data.ranges_ref); + if (!ranges_data || histogram_data.bucket_count < 2 || + histogram_data.bucket_count >= max_buckets || + allocated_bytes < required_bytes) { + RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); + NOTREACHED(); + return nullptr; + } + + scoped_ptr<const BucketRanges> created_ranges = + CreateRangesFromData(ranges_data, histogram_data.ranges_checksum, + histogram_data.bucket_count + 1); + if (!created_ranges) { + RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_RANGES_ARRAY); + NOTREACHED(); + return nullptr; + } + const BucketRanges* ranges = + StatisticsRecorder::RegisterOrDeleteDuplicateRanges( + created_ranges.release()); + + HistogramBase::AtomicCount* counts_data = + memory_allocator_->GetAsObject<HistogramBase::AtomicCount>( + histogram_data.counts_ref, kTypeIdCountsArray); + size_t counts_bytes = + CalculateRequiredCountsBytes(histogram_data.bucket_count); + if (!counts_data || !counts_bytes || + memory_allocator_->GetAllocSize(histogram_data.counts_ref) < + counts_bytes) { + RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_COUNTS_ARRAY); + NOTREACHED(); + return nullptr; + } + + // After the main "counts" array is a second array using for storing what + // was previously logged. This is used to calculate the "delta" during + // snapshot operations. + HistogramBase::AtomicCount* logged_data = + counts_data + histogram_data.bucket_count; + + std::string name(histogram_data_ptr->name); + scoped_ptr<HistogramBase> histogram; + switch (histogram_data.histogram_type) { + case HISTOGRAM: + histogram = Histogram::PersistentCreate( + name, histogram_data.minimum, histogram_data.maximum, ranges, + counts_data, logged_data, histogram_data.bucket_count, + &histogram_data_ptr->samples_metadata, + &histogram_data_ptr->logged_metadata); + DCHECK(histogram); + break; + case LINEAR_HISTOGRAM: + histogram = LinearHistogram::PersistentCreate( + name, histogram_data.minimum, histogram_data.maximum, ranges, + counts_data, logged_data, histogram_data.bucket_count, + &histogram_data_ptr->samples_metadata, + &histogram_data_ptr->logged_metadata); + DCHECK(histogram); + break; + case BOOLEAN_HISTOGRAM: + histogram = BooleanHistogram::PersistentCreate( + name, ranges, counts_data, logged_data, + &histogram_data_ptr->samples_metadata, + &histogram_data_ptr->logged_metadata); + DCHECK(histogram); + break; + case CUSTOM_HISTOGRAM: + histogram = CustomHistogram::PersistentCreate( + name, ranges, counts_data, logged_data, histogram_data.bucket_count, + &histogram_data_ptr->samples_metadata, + &histogram_data_ptr->logged_metadata); + DCHECK(histogram); + break; + default: + NOTREACHED(); + } + + if (histogram) { + DCHECK_EQ(histogram_data.histogram_type, histogram->GetHistogramType()); + histogram->SetFlags(histogram_data.flags); + RecordCreateHistogramResult(CREATE_HISTOGRAM_SUCCESS); + } else { + RecordCreateHistogramResult(CREATE_HISTOGRAM_UNKNOWN_TYPE); + } + + return histogram; +} + +scoped_ptr<HistogramBase> PersistentHistogramAllocator::GetHistogram( + Reference ref) { + // Unfortunately, the histogram "pickle" methods cannot be used as part of + // the persistance because the deserialization methods always create local + // count data (while these must reference the persistent counts) and always + // add it to the local list of known histograms (while these may be simple + // references to histograms in other processes). + PersistentHistogramData* histogram_data = + memory_allocator_->GetAsObject<PersistentHistogramData>( + ref, kTypeIdHistogram); + size_t length = memory_allocator_->GetAllocSize(ref); + if (!histogram_data || + reinterpret_cast<char*>(histogram_data)[length - 1] != '\0') { + RecordCreateHistogramResult(CREATE_HISTOGRAM_INVALID_METADATA); + NOTREACHED(); + return nullptr; + } + return CreateHistogram(histogram_data); +} + +scoped_ptr<HistogramBase> +PersistentHistogramAllocator::GetNextHistogramWithIgnore(Iterator* iter, + Reference ignore) { + PersistentMemoryAllocator::Reference ref; + uint32_t type_id; + while ((ref = memory_allocator_->GetNextIterable(&iter->memory_iter, + &type_id)) != 0) { + if (ref == ignore) + continue; + if (type_id == kTypeIdHistogram) + return GetHistogram(ref); + } + return nullptr; +} + +void PersistentHistogramAllocator::FinalizeHistogram(Reference ref, + bool registered) { + // If the created persistent histogram was registered then it needs to + // be marked as "iterable" in order to be found by other processes. + if (registered) + memory_allocator_->MakeIterable(ref); + // If it wasn't registered then a race condition must have caused + // two to be created. The allocator does not support releasing the + // acquired memory so just change the type to be empty. + else + memory_allocator_->SetType(ref, 0); +} + +scoped_ptr<HistogramBase> PersistentHistogramAllocator::AllocateHistogram( + HistogramType histogram_type, + const std::string& name, + int minimum, + int maximum, + const BucketRanges* bucket_ranges, + int32_t flags, + Reference* ref_ptr) { + // If the allocator is corrupt, don't waste time trying anything else. + // This also allows differentiating on the dashboard between allocations + // failed due to a corrupt allocator and the number of process instances + // with one, the latter being idicated by "newly corrupt", below. + if (memory_allocator_->IsCorrupt()) { + RecordCreateHistogramResult(CREATE_HISTOGRAM_ALLOCATOR_CORRUPT); + return nullptr; + } + + // If CalculateRequiredCountsBytes() returns zero then the bucket_count + // was not valid. + size_t bucket_count = bucket_ranges->bucket_count(); + size_t counts_bytes = CalculateRequiredCountsBytes(bucket_count); + if (!counts_bytes) { + NOTREACHED(); + return nullptr; + } + + size_t ranges_bytes = (bucket_count + 1) * sizeof(HistogramBase::Sample); + PersistentMemoryAllocator::Reference ranges_ref = + memory_allocator_->Allocate(ranges_bytes, kTypeIdRangesArray); + PersistentMemoryAllocator::Reference counts_ref = + memory_allocator_->Allocate(counts_bytes, kTypeIdCountsArray); + PersistentMemoryAllocator::Reference histogram_ref = + memory_allocator_->Allocate( + offsetof(PersistentHistogramData, name) + name.length() + 1, + kTypeIdHistogram); + HistogramBase::Sample* ranges_data = + memory_allocator_->GetAsObject<HistogramBase::Sample>(ranges_ref, + kTypeIdRangesArray); + PersistentHistogramData* histogram_data = + memory_allocator_->GetAsObject<PersistentHistogramData>(histogram_ref, + kTypeIdHistogram); + + // Only continue here if all allocations were successful. If they weren't, + // there is no way to free the space but that's not really a problem since + // the allocations only fail because the space is full or corrupt and so + // any future attempts will also fail. + if (counts_ref && ranges_data && histogram_data) { + strcpy(histogram_data->name, name.c_str()); + for (size_t i = 0; i < bucket_ranges->size(); ++i) + ranges_data[i] = bucket_ranges->range(i); + + histogram_data->histogram_type = histogram_type; + histogram_data->flags = flags; + histogram_data->minimum = minimum; + histogram_data->maximum = maximum; + histogram_data->bucket_count = static_cast<uint32_t>(bucket_count); + histogram_data->ranges_ref = ranges_ref; + histogram_data->ranges_checksum = bucket_ranges->checksum(); + histogram_data->counts_ref = counts_ref; + + // Create the histogram using resources in persistent memory. This ends up + // resolving the "ref" values stored in histogram_data instad of just + // using what is already known above but avoids duplicating the switch + // statement here and serves as a double-check that everything is + // correct before commiting the new histogram to persistent space. + scoped_ptr<HistogramBase> histogram = CreateHistogram(histogram_data); + DCHECK(histogram); + if (ref_ptr != nullptr) + *ref_ptr = histogram_ref; + + // By storing the reference within the allocator to this histogram, the + // next import (which will happen before the next histogram creation) + // will know to skip it. See also the comment in ImportGlobalHistograms(). + subtle::NoBarrier_Store(&last_created_, histogram_ref); + return histogram; + } + + CreateHistogramResultType result; + if (memory_allocator_->IsCorrupt()) { + RecordCreateHistogramResult(CREATE_HISTOGRAM_ALLOCATOR_NEWLY_CORRUPT); + result = CREATE_HISTOGRAM_ALLOCATOR_CORRUPT; + } else if (memory_allocator_->IsFull()) { + result = CREATE_HISTOGRAM_ALLOCATOR_FULL; + } else { + result = CREATE_HISTOGRAM_ALLOCATOR_ERROR; + } + RecordCreateHistogramResult(result); + NOTREACHED() << "error=" << result; + + return nullptr; +} + +// static +void PersistentHistogramAllocator::ImportGlobalHistograms() { + // The lock protects against concurrent access to the iterator and is created + // in a thread-safe manner when needed. + static base::LazyInstance<base::Lock>::Leaky lock = LAZY_INSTANCE_INITIALIZER; + + if (g_allocator) { + // TODO(bcwhite): Investigate a lock-free, thread-safe iterator. + base::AutoLock auto_lock(lock.Get()); + + // Each call resumes from where it last left off so a persistant iterator + // is needed. This class has a constructor so even the definition has to + // be protected by the lock in order to be thread-safe. + static Iterator iter; + if (iter.is_clear()) + g_allocator->CreateIterator(&iter); + + // Skip the import if it's the histogram that was last created. Should a + // race condition cause the "last created" to be overwritten before it + // is recognized here then the histogram will be created and be ignored + // when it is detected as a duplicate by the statistics-recorder. This + // simple check reduces the time of creating persistent histograms by + // about 40%. + Reference last_created = + subtle::NoBarrier_Load(&g_allocator->last_created_); + + while (true) { + scoped_ptr<HistogramBase> histogram = + g_allocator->GetNextHistogramWithIgnore(&iter, last_created); + if (!histogram) + break; + StatisticsRecorder::RegisterOrDeleteDuplicate(histogram.release()); + } + } +} + +} // namespace base
diff --git a/base/metrics/persistent_histogram_allocator.h b/base/metrics/persistent_histogram_allocator.h new file mode 100644 index 0000000..cc8d023 --- /dev/null +++ b/base/metrics/persistent_histogram_allocator.h
@@ -0,0 +1,212 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ +#define BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ + +#include "base/atomicops.h" +#include "base/base_export.h" +#include "base/feature_list.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/shared_memory.h" +#include "base/metrics/histogram_base.h" +#include "base/metrics/persistent_memory_allocator.h" +#include "base/strings/string_piece.h" + +namespace base { + +// Feature definition for enabling histogram persistence. +BASE_EXPORT extern const Feature kPersistentHistogramsFeature; + +// This class manages histograms created within a PersistentMemoryAllocator. +class BASE_EXPORT PersistentHistogramAllocator { + public: + // This iterator is used for fetching persistent histograms from an allocator. + class Iterator { + public: + bool is_clear() { return memory_iter.is_clear(); } + + private: + friend class PersistentHistogramAllocator; + + // The iterator used for stepping through persistent memory iterables. + PersistentMemoryAllocator::Iterator memory_iter; + }; + + using Reference = PersistentMemoryAllocator::Reference; + + // A PersistentHistogramAllocator is constructed from a PersistentMemory- + // Allocator object of which it takes ownership. + PersistentHistogramAllocator(scoped_ptr<PersistentMemoryAllocator> memory); + ~PersistentHistogramAllocator(); + + // Direct access to underlying memory allocator. If the segment is shared + // across threads or processes, reading data through these values does + // not guarantee consistency. Use with care. Do not write. + PersistentMemoryAllocator* memory_allocator() { + return memory_allocator_.get(); + } + + // Implement the "metadata" API of a PersistentMemoryAllocator, forwarding + // those requests to the real one. + uint64_t Id() const { return memory_allocator_->Id(); } + const char* Name() const { return memory_allocator_->Name(); } + const void* data() const { return memory_allocator_->data(); } + size_t length() const { return memory_allocator_->length(); } + size_t used() const { return memory_allocator_->used(); } + + // Recreate a Histogram from data held in persistent memory. Though this + // object will be local to the current process, the sample data will be + // shared with all other threads referencing it. This method takes a |ref| + // to where the top-level histogram data may be found in this allocator. + // This method will return null if any problem is detected with the data. + scoped_ptr<HistogramBase> GetHistogram(Reference ref); + + // Get the next histogram in persistent data based on iterator. + scoped_ptr<HistogramBase> GetNextHistogram(Iterator* iter) { + return GetNextHistogramWithIgnore(iter, 0); + } + + // Create an iterator for going through all histograms in an allocator. + void CreateIterator(Iterator* iter); + + // Allocate a new persistent histogram. The returned histogram will not + // be able to be located by other allocators until it is "finalized". + scoped_ptr<HistogramBase> AllocateHistogram( + HistogramType histogram_type, + const std::string& name, + int minimum, + int maximum, + const BucketRanges* bucket_ranges, + int32_t flags, + Reference* ref_ptr); + + // Finalize the creation of the histogram, making it available to other + // processes if |registered| (as in: added to the StatisticsRecorder) is + // True, forgetting it otherwise. + void FinalizeHistogram(Reference ref, bool registered); + + // Create internal histograms for tracking memory use and allocation sizes + // for allocator of |name| (which can simply be the result of Name()). This + // is done seperately from construction for situations such as when the + // histograms will be backed by memory provided by this very allocator. + // + // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml + // with the following histograms: + // UMA.PersistentAllocator.name.Allocs + // UMA.PersistentAllocator.name.UsedPct + void CreateTrackingHistograms(StringPiece name); + void UpdateTrackingHistograms(); + + // Manage a PersistentHistogramAllocator for globally storing histograms in + // a space that can be persisted or shared between processes. There is only + // ever one allocator for all such histograms created by a single process. + // This takes ownership of the object and should be called as soon as + // possible during startup to capture as many histograms as possible and + // while operating single-threaded so there are no race-conditions. + static void SetGlobalAllocator( + scoped_ptr<PersistentHistogramAllocator> allocator); + static PersistentHistogramAllocator* GetGlobalAllocator(); + + // This access to the persistent allocator is only for testing; it extracts + // the current allocator completely. This allows easy creation of histograms + // within persistent memory segments which can then be extracted and used + // in other ways. + static scoped_ptr<PersistentHistogramAllocator> + ReleaseGlobalAllocatorForTesting(); + + // These helper methods perform SetGlobalAllocator() calls with allocators + // of the specified type and parameters. + static void CreateGlobalAllocatorOnPersistentMemory( + void* base, + size_t size, + size_t page_size, + uint64_t id, + StringPiece name); + static void CreateGlobalAllocatorOnLocalMemory( + size_t size, + uint64_t id, + StringPiece name); + static void CreateGlobalAllocatorOnSharedMemory( + size_t size, + const SharedMemoryHandle& handle); + + // Import new histograms from the global PersistentHistogramAllocator. It's + // possible for other processes to create histograms in the active memory + // segment; this adds those to the internal list of known histograms to + // avoid creating duplicates that would have to be merged during reporting. + // Every call to this method resumes from the last entry it saw; it costs + // nothing if nothing new has been added. + static void ImportGlobalHistograms(); + + // Histogram containing creation results. Visible for testing. + static HistogramBase* GetCreateHistogramResultHistogram(); + + private: + // Enumerate possible creation results for reporting. + enum CreateHistogramResultType { + // Everything was fine. + CREATE_HISTOGRAM_SUCCESS = 0, + + // Pointer to metadata was not valid. + CREATE_HISTOGRAM_INVALID_METADATA_POINTER, + + // Histogram metadata was not valid. + CREATE_HISTOGRAM_INVALID_METADATA, + + // Ranges information was not valid. + CREATE_HISTOGRAM_INVALID_RANGES_ARRAY, + + // Counts information was not valid. + CREATE_HISTOGRAM_INVALID_COUNTS_ARRAY, + + // Could not allocate histogram memory due to corruption. + CREATE_HISTOGRAM_ALLOCATOR_CORRUPT, + + // Could not allocate histogram memory due to lack of space. + CREATE_HISTOGRAM_ALLOCATOR_FULL, + + // Could not allocate histogram memory due to unknown error. + CREATE_HISTOGRAM_ALLOCATOR_ERROR, + + // Histogram was of unknown type. + CREATE_HISTOGRAM_UNKNOWN_TYPE, + + // Instance has detected a corrupt allocator (recorded only once). + CREATE_HISTOGRAM_ALLOCATOR_NEWLY_CORRUPT, + + // Always keep this at the end. + CREATE_HISTOGRAM_MAX + }; + + // The structure used to hold histogram data in persistent memory. It is + // defined and used entirely within the .cc file. + struct PersistentHistogramData; + + // Get the next histogram in persistent data based on iterator while + // ignoring a particular reference if it is found. + scoped_ptr<HistogramBase> GetNextHistogramWithIgnore( + Iterator* iter, + Reference ignore); + + // Create a histogram based on saved (persistent) information about it. + scoped_ptr<HistogramBase> CreateHistogram( + PersistentHistogramData* histogram_data_ptr); + + // Record the result of a histogram creation. + static void RecordCreateHistogramResult(CreateHistogramResultType result); + + // The memory allocator that provides the actual histogram storage. + scoped_ptr<PersistentMemoryAllocator> memory_allocator_; + + // A reference to the last-created histogram in the allocator, used to avoid + // trying to import what was just created. + subtle::AtomicWord last_created_ = 0; + + DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocator); +}; + +} // namespace base + +#endif // BASE_METRICS_HISTOGRAM_PERSISTENCE_H_
diff --git a/base/metrics/persistent_histogram_allocator_unittest.cc b/base/metrics/persistent_histogram_allocator_unittest.cc new file mode 100644 index 0000000..64abdec7 --- /dev/null +++ b/base/metrics/persistent_histogram_allocator_unittest.cc
@@ -0,0 +1,126 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/metrics/persistent_histogram_allocator.h" + +#include "base/logging.h" +#include "base/metrics/bucket_ranges.h" +#include "base/metrics/histogram_macros.h" +#include "base/metrics/persistent_memory_allocator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +class PersistentHistogramAllocatorTest : public testing::Test { + protected: + const int32_t kAllocatorMemorySize = 64 << 10; // 64 KiB + + PersistentHistogramAllocatorTest() { CreatePersistentHistogramAllocator(); } + ~PersistentHistogramAllocatorTest() override { + DestroyPersistentHistogramAllocator(); + } + + void CreatePersistentHistogramAllocator() { + allocator_memory_.reset(new char[kAllocatorMemorySize]); + + PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting(); + memset(allocator_memory_.get(), 0, kAllocatorMemorySize); + PersistentHistogramAllocator::GetCreateHistogramResultHistogram(); + PersistentHistogramAllocator::CreateGlobalAllocatorOnPersistentMemory( + allocator_memory_.get(), kAllocatorMemorySize, 0, 0, + "PersistentHistogramAllocatorTest"); + allocator_ = + PersistentHistogramAllocator::GetGlobalAllocator()->memory_allocator(); + } + + void DestroyPersistentHistogramAllocator() { + allocator_ = nullptr; + PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting(); + } + + scoped_ptr<char[]> allocator_memory_; + PersistentMemoryAllocator* allocator_ = nullptr; + + private: + DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocatorTest); +}; + +TEST_F(PersistentHistogramAllocatorTest, CreateAndIterateTest) { + PersistentMemoryAllocator::MemoryInfo meminfo0; + allocator_->GetMemoryInfo(&meminfo0); + + // Try basic construction + HistogramBase* histogram = Histogram::FactoryGet( + "TestHistogram", 1, 1000, 10, HistogramBase::kIsPersistent); + EXPECT_TRUE(histogram); + histogram->CheckName("TestHistogram"); + PersistentMemoryAllocator::MemoryInfo meminfo1; + allocator_->GetMemoryInfo(&meminfo1); + EXPECT_GT(meminfo0.free, meminfo1.free); + + HistogramBase* linear_histogram = LinearHistogram::FactoryGet( + "TestLinearHistogram", 1, 1000, 10, HistogramBase::kIsPersistent); + EXPECT_TRUE(linear_histogram); + linear_histogram->CheckName("TestLinearHistogram"); + PersistentMemoryAllocator::MemoryInfo meminfo2; + allocator_->GetMemoryInfo(&meminfo2); + EXPECT_GT(meminfo1.free, meminfo2.free); + + HistogramBase* boolean_histogram = BooleanHistogram::FactoryGet( + "TestBooleanHistogram", HistogramBase::kIsPersistent); + EXPECT_TRUE(boolean_histogram); + boolean_histogram->CheckName("TestBooleanHistogram"); + PersistentMemoryAllocator::MemoryInfo meminfo3; + allocator_->GetMemoryInfo(&meminfo3); + EXPECT_GT(meminfo2.free, meminfo3.free); + + std::vector<int> custom_ranges; + custom_ranges.push_back(1); + custom_ranges.push_back(5); + HistogramBase* custom_histogram = CustomHistogram::FactoryGet( + "TestCustomHistogram", custom_ranges, HistogramBase::kIsPersistent); + EXPECT_TRUE(custom_histogram); + custom_histogram->CheckName("TestCustomHistogram"); + PersistentMemoryAllocator::MemoryInfo meminfo4; + allocator_->GetMemoryInfo(&meminfo4); + EXPECT_GT(meminfo3.free, meminfo4.free); + + PersistentMemoryAllocator::Iterator iter; + uint32_t type; + allocator_->CreateIterator(&iter); + EXPECT_NE(0U, allocator_->GetNextIterable(&iter, &type)); // Histogram + EXPECT_NE(0U, allocator_->GetNextIterable(&iter, &type)); // LinearHistogram + EXPECT_NE(0U, allocator_->GetNextIterable(&iter, &type)); // BooleanHistogram + EXPECT_NE(0U, allocator_->GetNextIterable(&iter, &type)); // CustomHistogram + EXPECT_EQ(0U, allocator_->GetNextIterable(&iter, &type)); + + // Create a second allocator and have it access the memory of the first. + scoped_ptr<HistogramBase> recovered; + PersistentHistogramAllocator recovery( + make_scoped_ptr(new PersistentMemoryAllocator( + allocator_memory_.get(), kAllocatorMemorySize, 0, 0, "", false))); + PersistentHistogramAllocator::Iterator histogram_iter; + recovery.CreateIterator(&histogram_iter); + + recovered = recovery.GetNextHistogram(&histogram_iter); + ASSERT_TRUE(recovered); + recovered->CheckName("TestHistogram"); + + recovered = recovery.GetNextHistogram(&histogram_iter); + ASSERT_TRUE(recovered); + recovered->CheckName("TestLinearHistogram"); + + recovered = recovery.GetNextHistogram(&histogram_iter); + ASSERT_TRUE(recovered); + recovered->CheckName("TestBooleanHistogram"); + + recovered = recovery.GetNextHistogram(&histogram_iter); + ASSERT_TRUE(recovered); + recovered->CheckName("TestCustomHistogram"); + + recovered = recovery.GetNextHistogram(&histogram_iter); + EXPECT_FALSE(recovered); +} + +} // namespace base
diff --git a/base/metrics/statistics_recorder_unittest.cc b/base/metrics/statistics_recorder_unittest.cc index 17511a4..073cbb1 100644 --- a/base/metrics/statistics_recorder_unittest.cc +++ b/base/metrics/statistics_recorder_unittest.cc
@@ -10,7 +10,7 @@ #include "base/json/json_reader.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram_macros.h" -#include "base/metrics/histogram_persistence.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/metrics/sparse_histogram.h" #include "base/metrics/statistics_recorder.h" #include "base/values.h" @@ -23,7 +23,7 @@ void SetUp() override { // Get this first so it never gets created in persistent storage and will // not appear in the StatisticsRecorder after it is re-initialized. - GetCreateHistogramResultHistogram(); + PersistentHistogramAllocator::GetCreateHistogramResultHistogram(); // Each test will have a clean state (no Histogram / BucketRanges // registered). InitializeStatisticsRecorder(); @@ -31,7 +31,7 @@ void TearDown() override { UninitializeStatisticsRecorder(); - delete ReleasePersistentHistogramMemoryAllocatorForTesting(); + PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting(); } void InitializeStatisticsRecorder() { @@ -325,8 +325,8 @@ TEST_F(StatisticsRecorderTest, IterationTest) { StatisticsRecorder::Histograms registered_histograms; LOCAL_HISTOGRAM_COUNTS("TestHistogram.IterationTest1", 30); - SetPersistentHistogramMemoryAllocator( - new LocalPersistentMemoryAllocator(64 << 10, 0, std::string())); + PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory( + 64 << 10 /* 64 KiB */, 0, ""); LOCAL_HISTOGRAM_COUNTS("TestHistogram.IterationTest2", 30); StatisticsRecorder::HistogramIterator i1 = StatisticsRecorder::begin(true);
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py index 7248ed24..df92f15 100644 --- a/build/toolchain/win/setup_toolchain.py +++ b/build/toolchain/win/setup_toolchain.py
@@ -11,6 +11,7 @@ # and the files will be written to the current directory. import errno +import json import os import re import subprocess @@ -67,35 +68,57 @@ return vs_toolchain.DetectVisualStudioPath() -def _SetupScript(target_cpu, sdk_dir): - """Returns a command (with arguments) to be used to set up the - environment.""" - # Check if we are running in the SDK command line environment and use - # the setup script from the SDK if so. |target_cpu| should be either - # 'x86' or 'x64'. - assert target_cpu in ('x86', 'x64') - if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and sdk_dir: - return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')), - '/' + target_cpu] - else: - if 'GYP_MSVS_OVERRIDE_PATH' not in os.environ: - os.environ['GYP_MSVS_OVERRIDE_PATH'] = _DetectVisualStudioPath() - # We only support x64-hosted tools. - return [os.path.normpath(os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'], - 'VC/vcvarsall.bat')), - 'amd64_x86' if target_cpu == 'x86' else 'amd64'] - - -def _LoadToolchainEnv(cpu, win_sdk_path): - """Returns a dictionary with environment variables that must be set while - running binaries from the toolchain (e.g. INCLUDE and PATH for cl.exe).""" - args = _SetupScript(cpu, win_sdk_path) +def _LoadEnvFromBat(args): + """Given a bat command, runs it and returns env vars set by it.""" + args = args[:] args.extend(('&&', 'set')) popen = subprocess.Popen( args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) variables, _ = popen.communicate() if popen.returncode != 0: raise Exception('"%s" failed with error %d' % (args, popen.returncode)) + return variables + + +def _LoadToolchainEnv(cpu, sdk_dir): + """Returns a dictionary with environment variables that must be set while + running binaries from the toolchain (e.g. INCLUDE and PATH for cl.exe).""" + # Check if we are running in the SDK command line environment and use + # the setup script from the SDK if so. |cpu| should be either + # 'x86' or 'x64'. + assert cpu in ('x86', 'x64') + if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and sdk_dir: + # Load environment from json file. + env = os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.%s.json' % cpu)) + env = json.load(open(env))['env'] + for k in env: + entries = [os.path.join(*([os.path.join(sdk_dir, 'bin')] + e)) + for e in env[k]] + env[k] = os.pathsep.join(entries) + # PATH is a bit of a special case, it's in addition to the current PATH. + env['PATH'] = env['PATH'] + os.pathsep + os.environ['PATH'] + # Augment with the current env to pick up TEMP and friends. + for k in os.environ: + if k not in env: + env[k] = os.environ[k] + + varlines = [] + for k in sorted(env.keys()): + varlines.append('%s=%s' % (str(k), str(env[k]))) + variables = '\n'.join(varlines) + + # Check that the json file contained the same environment as the .cmd file. + script = os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.cmd')) + assert _ExtractImportantEnvironment(variables) == \ + _ExtractImportantEnvironment(_LoadEnvFromBat([script, '/' + cpu])) + else: + if 'GYP_MSVS_OVERRIDE_PATH' not in os.environ: + os.environ['GYP_MSVS_OVERRIDE_PATH'] = _DetectVisualStudioPath() + # We only support x64-hosted tools. + args = [os.path.normpath(os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'], + 'VC/vcvarsall.bat')), + 'amd64_x86' if cpu == 'x86' else 'amd64'] + variables = _LoadEnvFromBat(args) return _ExtractImportantEnvironment(variables)
diff --git a/chrome/VERSION b/chrome/VERSION index f412fec..cc0759e 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=51 MINOR=0 -BUILD=2680 +BUILD=2681 PATCH=0
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc index 682271f..2696ff0b 100644 --- a/chrome/browser/chrome_browser_field_trials.cc +++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -10,7 +10,7 @@ #include "base/feature_list.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_base.h" -#include "base/metrics/histogram_persistence.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/strings/string_util.h" #include "base/time/time.h" #include "build/build_config.h" @@ -33,12 +33,12 @@ // Create persistent/shared memory and allow histograms to be stored in it. // Memory that is not actualy used won't be physically mapped by the system. // BrowserMetrics usage peaked around 95% of 2MiB as of 2016-02-20. - base::SetPersistentHistogramMemoryAllocator( - new base::LocalPersistentMemoryAllocator(3 << 20, // 3 MiB - 0x935DDD43, // SHA1(B...M...) - kAllocatorName)); - base::GetPersistentHistogramMemoryAllocator()->CreateTrackingHistograms( + base::PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory( + 3 << 20, // 3 MiB + 0x935DDD43, // SHA1(BrowserMetrics) kAllocatorName); + base::PersistentHistogramAllocator::GetGlobalAllocator() + ->CreateTrackingHistograms(kAllocatorName); } }
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index 16a742d..ed640bd5 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -334,6 +334,9 @@ previous_input_method_.Init(prefs::kLanguagePreviousInputMethod, prefs, callback); ime_menu_activated_.Init(prefs::kLanguageImeMenuActivated, prefs, callback); + // Notifies the system tray to remove the IME items. + if (switches::IsImeMenuEnabled() && ime_menu_activated_.GetValue()) + input_method::InputMethodManager::Get()->ImeMenuActivationChanged(true); xkb_auto_repeat_enabled_.Init( prefs::kLanguageXkbAutoRepeatEnabled, prefs, callback); @@ -600,7 +603,8 @@ } if (pref_name == prefs::kLanguageImeMenuActivated && - (reason == REASON_PREF_CHANGED || reason == REASON_ACTIVE_USER_CHANGED)) { + (reason == REASON_PREF_CHANGED || reason == REASON_ACTIVE_USER_CHANGED) && + switches::IsImeMenuEnabled()) { const bool activated = ime_menu_activated_.GetValue(); input_method::InputMethodManager::Get()->ImeMenuActivationChanged( activated);
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 5ec384c8..a509bbf 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -199,16 +199,26 @@ settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["settings.a11y.autoclick_delay_ms"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)["settings.a11y.caret_highlight"] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)["settings.a11y.cursor_highlight"] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["settings.a11y.enable_menu"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)["settings.a11y.focus_highlight"] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["settings.a11y.high_contrast_enabled"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["settings.a11y.large_cursor_enabled"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["settings.a11y.screen_magnifier"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)["settings.a11y.select_to_speak"] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["settings.a11y.sticky_keys_enabled"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)["settings.a11y.switch_access"] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["settings.a11y.virtual_keyboard"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["settings.clock.use_24hour_clock"] =
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html index 9c8f373e..23e5d7f06 100644 --- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html +++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
@@ -99,9 +99,9 @@ <paper-spinner id="searching-devices-spinner" active hidden$="[[computeSpinnerHidden_(justOpened_)]]"> </paper-spinner> - <a href="[[deviceMissingUrl]]"> - <span hidden$="[[!computeSpinnerHidden_(justOpened_)]]" - >[[deviceMissingText_]]</span> + <a href="[[deviceMissingUrl]]" + hidden$="[[!computeSpinnerHidden_(justOpened_)]]"> + [[deviceMissingText_]] </a> </div> <paper-menu id="sink-list"
diff --git a/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css b/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css index 42d3a1c..cdd86acc 100644 --- a/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css +++ b/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css
@@ -37,6 +37,8 @@ #header-and-arrow-container { display: flex; + overflow: hidden; + white-space: nowrap; } #header-text { @@ -44,6 +46,8 @@ color: white; font-size: 1.175em; margin: 0; + overflow: hidden; + text-overflow: ellipsis; } paper-icon-button {
diff --git a/chrome/browser/resources/options/language_options.js b/chrome/browser/resources/options/language_options.js index f982551..4117c5c 100644 --- a/chrome/browser/resources/options/language_options.js +++ b/chrome/browser/resources/options/language_options.js
@@ -265,6 +265,10 @@ if (loadTimeData.getBoolean('enableLanguageOptionsImeMenu')) $('language-options-ime-menu-template').hidden = false; + // Updates the initial checked state of the check box. + Preferences.getInstance().addEventListener( + ACTIVATE_IME_MENU_PREF, this.updateImeMenuCheckbox_.bind(this)); + // Listen to check on 'activate-ime-menu' checkbox. var checkboxImeMenu = $('activate-ime-menu'); checkboxImeMenu.addEventListener('click', @@ -1395,6 +1399,15 @@ checkbox.checked, true); } }, + + /** + * Updates the activate-ime-menu check box's checked state. + * @param {Event} e Change event. + * @private + */ + updateImeMenuCheckbox_: function(e) { + $('activate-ime-menu').checked = e.value.value; + }, }; /**
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html index 5325098..b8e37d18 100644 --- a/chrome/browser/resources/settings/a11y_page/a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -58,6 +58,23 @@ <settings-checkbox pref="{{prefs.settings.a11y.virtual_keyboard}}" i18n-values="label:onScreenKeyboardLabel"> </settings-checkbox> + <template is="dom-if" if="[[showExperimentalFeatures_]]"> + <settings-checkbox pref="{{prefs.settings.a11y.caret_highlight}}" + i18n-values="label:caretHighlightLabel"> + </settings-checkbox> + <settings-checkbox pref="{{prefs.settings.a11y.cursor_highlight}}" + i18n-values="label:cursorHighlightLabel"> + </settings-checkbox> + <settings-checkbox pref="{{prefs.settings.a11y.focus_highlight}}" + i18n-values="label:focusHighlightLabel"> + </settings-checkbox> + <settings-checkbox pref="{{prefs.settings.a11y.select_to_speak}}" + i18n-values="label:selectToSpeakLabel"> + </settings-checkbox> + <settings-checkbox pref="{{prefs.settings.a11y.switch_access}}" + i18n-values="label:switchAccessLabel"> + </settings-checkbox> + </template> </div> <div class="settings-box">
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.js b/chrome/browser/resources/settings/a11y_page/a11y_page.js index dbb55f3..109c99e 100644 --- a/chrome/browser/resources/settings/a11y_page/a11y_page.js +++ b/chrome/browser/resources/settings/a11y_page/a11y_page.js
@@ -25,6 +25,17 @@ type: Object, notify: true, }, + + /** + * Whether to show experimental accessibility features. + * @private {boolean} + */ + showExperimentalFeatures_: { + type: Boolean, + value: function() { + return loadTimeData.getBoolean('showExperimentalA11yFeatures'); + }, + } }, /** @private */
diff --git a/chrome/browser/resources/settings/advanced_page/advanced_page.html b/chrome/browser/resources/settings/advanced_page/advanced_page.html index 07482356..3623aa81 100644 --- a/chrome/browser/resources/settings/advanced_page/advanced_page.html +++ b/chrome/browser/resources/settings/advanced_page/advanced_page.html
@@ -5,6 +5,7 @@ <link rel="import" href="chrome://md-settings/passwords_and_forms_page/passwords_and_forms_page.html"> <link rel="import" href="chrome://md-settings/privacy_page/privacy_page.html"> <link rel="import" href="chrome://md-settings/reset_page/reset_page.html"> +<link rel="import" href="chrome://md-settings/settings_page/main_page_behavior.html"> <link rel="import" href="chrome://md-settings/settings_page/settings_page_visibility.html"> <link rel="import" href="chrome://md-settings/settings_page/settings_section.html"> <link rel="import" href="chrome://md-settings/site_settings/constants.html"> @@ -24,6 +25,7 @@ <dom-module id="settings-advanced-page"> <link rel="import" type="css" href="chrome://md-settings/settings_page.css"> <template> + <style include="main-page-styles"></style> <if expr="chromeos"> <template is="dom-if" if="[[showPage(pageVisibility.dateTime)]]" restamp> <settings-section page-title="[[i18n('dateTimePageTitle')]]"
diff --git a/chrome/browser/resources/settings/advanced_page/advanced_page.js b/chrome/browser/resources/settings/advanced_page/advanced_page.js index ddc47fe..e6655247 100644 --- a/chrome/browser/resources/settings/advanced_page/advanced_page.js +++ b/chrome/browser/resources/settings/advanced_page/advanced_page.js
@@ -18,6 +18,8 @@ Polymer({ is: 'settings-advanced-page', + behaviors: [I18nBehavior, SettingsPageVisibility, RoutableBehavior], + properties: { /** * Preferences state. @@ -36,11 +38,26 @@ }, }, + /** + * @type {string} Selector to get the sections. + * TODO(michaelpg): replace duplicate docs with @override once b/24294625 + * is fixed. + */ + sectionSelector: 'settings-section', + <if expr="not chromeos"> listeners: { 'dom-change': 'onDomChange_', }, +</if> + /** @override */ + attached: function() { + /** @override */ + this.scroller = this.parentElement; + }, + +<if expr="not chromeos"> /** @private */ onDomChange_: function() { var systemPage = /** @type {?SettingsSystemPageElement} */( @@ -49,6 +66,4 @@ systemPage.delegate = new settings.SystemPageDelegateImpl; }, </if> - - behaviors: [I18nBehavior, SettingsPageVisibility], });
diff --git a/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp b/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp index a8e444d..ee927f3 100644 --- a/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp
@@ -7,7 +7,9 @@ 'target_name': 'advanced_page', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', + '../settings_page/compiled_resources2.gyp:main_page_behavior', '../settings_page/compiled_resources2.gyp:settings_page_visibility', + '../settings_page/compiled_resources2.gyp:transition_behavior', '../system_page/compiled_resources2.gyp:system_page', '../system_page/compiled_resources2.gyp:system_page_delegate', ],
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html index f94aa390..7f9fc4e 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.html +++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -2,6 +2,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://md-settings/appearance_page/appearance_page.html"> <link rel="import" href="chrome://md-settings/search_page/search_page.html"> +<link rel="import" href="chrome://md-settings/settings_page/main_page_behavior.html"> <link rel="import" href="chrome://md-settings/settings_page/settings_page_visibility.html"> <link rel="import" href="chrome://md-settings/settings_page/settings_section.html"> <link rel="import" href="chrome://md-settings/on_startup_page/on_startup_page.html"> @@ -20,6 +21,7 @@ <dom-module id="settings-basic-page"> <link rel="import" type="css" href="chrome://md-settings/settings_page.css"> <template> + <style include="main-page-styles"></style> <template is="dom-if" if="[[showResetProfileBanner_]]"> <settings-reset-profile-banner on-reset-done="onResetDone_"> </settings-reset-profile-banner>
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.js b/chrome/browser/resources/settings/basic_page/basic_page.js index 0e84e86..80787fc 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.js +++ b/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -46,7 +46,20 @@ }, - behaviors: [I18nBehavior, SettingsPageVisibility], + /** + * @type {string} Selector to get the sections. + * TODO(michaelpg): replace duplicate docs with @override once b/24294625 + * is fixed. + */ + sectionSelector: 'settings-section', + + /** @override */ + attached: function() { + /** @override */ + this.scroller = this.parentElement; + }, + + behaviors: [I18nBehavior, SettingsPageVisibility, RoutableBehavior], onResetDone_: function() { this.showResetProfileBanner_ = false;
diff --git a/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp b/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp index 6c0c9d8..b3013ed 100644 --- a/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp
@@ -8,7 +8,9 @@ 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', + '../settings_page/compiled_resources2.gyp:main_page_behavior', '../settings_page/compiled_resources2.gyp:settings_page_visibility', + '../settings_page/compiled_resources2.gyp:transition_behavior', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], },
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.css b/chrome/browser/resources/settings/settings_main/settings_main.css index 2624d9aed..7932a8d 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.css +++ b/chrome/browser/resources/settings/settings_main/settings_main.css
@@ -6,10 +6,6 @@ box-sizing: border-box; height: 100%; overflow: auto; - padding: 24px 16px; -} - -#pageContainer.expanded { padding: 0 16px; }
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.js b/chrome/browser/resources/settings/settings_main/settings_main.js index 0b46de37..766e9dde 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.js +++ b/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -43,35 +43,8 @@ } }, - listeners: { - 'expand-animation-complete': 'onExpandAnimationComplete_', - }, - /** @private */ currentRouteChanged_: function(newRoute, oldRoute) { this.showAdvancedPage_ = newRoute.page == 'advanced'; - - var pageContainer = this.$.pageContainer; - if (!oldRoute) { - pageContainer.classList.toggle('expanded', newRoute.section); - return; - } - - // For contraction only, apply new styling immediately. - if (!newRoute.section && oldRoute.section) { - pageContainer.classList.remove('expanded'); - - // TODO(tommycli): Save and restore scroll position. crbug.com/537359. - pageContainer.scrollTop = 0; - } - }, - - /** @private */ - onExpandAnimationComplete_: function() { - if (this.currentRoute.section) { - var pageContainer = this.$.pageContainer; - pageContainer.classList.add('expanded'); - pageContainer.scrollTop = 0; - } }, });
diff --git a/chrome/browser/resources/settings/settings_page.css b/chrome/browser/resources/settings/settings_page.css index 9e44ff94..78d34a06 100644 --- a/chrome/browser/resources/settings/settings_page.css +++ b/chrome/browser/resources/settings/settings_page.css
@@ -5,8 +5,13 @@ :host { display: block; height: 100%; - margin: auto; + margin: 24px auto; max-width: 960px; min-width: 622px; + position: relative; width: 80%; } + +:host > * { + margin-bottom: 16px; +}
diff --git a/chrome/browser/resources/settings/settings_page/compiled_resources2.gyp b/chrome/browser/resources/settings/settings_page/compiled_resources2.gyp index c422dff..af8bcca3 100644 --- a/chrome/browser/resources/settings/settings_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/settings_page/compiled_resources2.gyp
@@ -4,6 +4,16 @@ { 'targets': [ { + 'target_name': 'main_page_behavior', + 'dependencies': [ + 'settings_section', + 'transition_behavior', + '<(EXTERNS_GYP):settings_private', + '<(EXTERNS_GYP):web_animations', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { 'target_name': 'settings_animated_pages', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', @@ -23,5 +33,17 @@ ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], }, + { + 'target_name': 'settings_section', + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'transition_behavior', + 'dependencies': [ + '<(EXTERNS_GYP):settings_private', + '<(EXTERNS_GYP):web_animations', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, ], }
diff --git a/chrome/browser/resources/settings/settings_page/main_page_behavior.html b/chrome/browser/resources/settings/settings_page/main_page_behavior.html new file mode 100644 index 0000000..3d1c94f --- /dev/null +++ b/chrome/browser/resources/settings/settings_page/main_page_behavior.html
@@ -0,0 +1,18 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://md-settings/settings_page/transition_behavior.html"> +<script src="chrome://md-settings/settings_page/main_page_behavior.js"></script> + +<dom-module id="main-page-styles"> + <template> + <style> + .expanding, + .collapsing { + z-index: 2; + } + + .expanded { + min-height: 100%; + } + </style> + </template> +</dom-module>
diff --git a/chrome/browser/resources/settings/settings_page/main_page_behavior.js b/chrome/browser/resources/settings/settings_page/main_page_behavior.js new file mode 100644 index 0000000..99dbc67 --- /dev/null +++ b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
@@ -0,0 +1,379 @@ +// Copyright 2016 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. + +// Fast out, slow in. +var EASING_FUNCTION = 'cubic-bezier(0.4, 0, 0.2, 1)'; +var EXPAND_DURATION = 350; + +/** + * Provides animations to expand and collapse individual sections in a page. + * Expanded sections take up the full height of the container. At most one + * section should be expanded at any given time. + * @polymerBehavior Polymer.MainPageBehavior + */ +var MainPageBehaviorImpl = { + /** + * @type {string} Selector to get the sections. Derived elements + * must override. + */ + sectionSelector: '', + + /** @type {?Element} The scrolling container. Elements must set this. */ + scroller: null, + + /** + * Hides or unhides the sections not being expanded. + * @param {string} sectionName The section to keep visible. + * @param {boolean} hidden Whether the sections should be hidden. + * @private + */ + toggleOtherSectionsHidden_: function(sectionName, hidden) { + var sections = Polymer.dom(this.root).querySelectorAll( + this.sectionSelector + ':not([section=' + sectionName + '])'); + for (var section of sections) + section.hidden = hidden; + }, + + /** + * Animates the card in |section|, expanding it to fill the page. + * @param {!SettingsSectionElement} section + */ + expandSection: function(section) { + // If another section's card is expanding, cancel that animation first. + var expanding = this.$$('.expanding'); + if (expanding) { + if (expanding == section) + return; + + if (this.animations['section']) { + // Cancel the animation, then call startExpandSection_. + this.cancelAnimation('section', function() { + this.startExpandSection_(section); + }.bind(this)); + } else { + // The animation must have finished but its promise hasn't resolved yet. + // When it resolves, collapse that section's card before expanding + // this one. + setTimeout(function() { + this.collapseSection( + /** @type {!SettingsSectionElement} */(expanding)); + this.finishAnimation('section', function() { + this.startExpandSection_(section); + }.bind(this)); + }.bind(this)); + } + + return; + } + + if (this.$$('.collapsing') && this.animations['section']) { + // Finish the collapse animation before expanding. + this.finishAnimation('section', function() { + this.startExpandSection_(section); + }.bind(this)); + return; + } + + this.startExpandSection_(section); + }, + + /** + * Helper function to set up and start the expand animation. + * @param {!SettingsSectionElement} section + */ + startExpandSection_: function(section) { + if (section.classList.contains('expanded')) + return; + + // Freeze the scroller and save its position. + this.listScrollTop_ = this.scroller.scrollTop; + + var scrollerWidth = this.scroller.clientWidth; + this.scroller.style.overflow = 'hidden'; + // Adjust width to compensate for scroller. + var scrollbarWidth = this.scroller.clientWidth - scrollerWidth; + this.scroller.style.width = 'calc(100% - ' + scrollbarWidth + 'px)'; + + // Freezes the section's height so its card can be removed from the flow. + this.freezeSection_(section); + + // Expand the section's card to fill the parent. + var animationPromise = this.playExpandSection_(section); + + animationPromise.then(function() { + this.scroller.scrollTop = 0; + this.toggleOtherSectionsHidden_(section.section, true); + }.bind(this), function() { + // Animation was canceled; restore the section. + this.unfreezeSection_(section); + }.bind(this)).then(function() { + this.scroller.style.overflow = ''; + this.scroller.style.width = ''; + }.bind(this)); + }, + + /** + * Animates the card in |section|, collapsing it back into its section. + * @param {!SettingsSectionElement} section + */ + collapseSection: function(section) { + // If the section's card is still expanding, cancel the expand animation. + if (section.classList.contains('expanding')) { + if (this.animations['section']) { + this.cancelAnimation('section'); + } else { + // The animation must have finished but its promise hasn't finished + // resolving; try again asynchronously. + this.async(function() { + this.collapseSection(section); + }); + } + return; + } + + if (!section.classList.contains('expanded')) + return; + + this.toggleOtherSectionsHidden_(section.section, false); + + var scrollerWidth = this.scroller.clientWidth; + this.scroller.style.overflow = 'hidden'; + // Adjust width to compensate for scroller. + var scrollbarWidth = this.scroller.clientWidth - scrollerWidth; + this.scroller.style.width = 'calc(100% - ' + scrollbarWidth + 'px)'; + + this.playCollapseSection_(section).then(function() { + this.unfreezeSection_(section); + this.scroller.style.overflow = ''; + this.scroller.style.width = ''; + section.classList.remove('collapsing'); + }.bind(this)); + }, + + /** + * Freezes a section's height so its card can be removed from the flow without + * affecting the layout of the surrounding sections. + * @param {!SettingsSectionElement} section + * @private + */ + freezeSection_: function(section) { + var card = section.$.card; + section.style.height = section.clientHeight + 'px'; + + var cardHeight = card.offsetHeight; + var cardWidth = card.offsetWidth; + // If the section is not displayed yet (e.g., navigated directly to a + // sub-page), cardHeight and cardWidth are 0, so do not set the height or + // width explicitly. + // TODO(michaelpg): Improve this logic when refactoring + // settings-animated-pages. + if (cardHeight && cardWidth) { + // TODO(michaelpg): Temporary hack to store the height the section should + // collapse to when it closes. + card.origHeight_ = cardHeight; + + card.style.height = cardHeight + 'px'; + card.style.width = cardWidth + 'px'; + } else { + // Set an invalid value so we don't try to use it later. + card.origHeight_ = NaN; + } + + // Place the section's card at its current position but removed from the + // flow. + card.style.top = card.getBoundingClientRect().top + 'px'; + section.classList.add('frozen'); + }, + + /** + * After freezeSection_, restores the section to its normal height. + * @param {!SettingsSectionElement} section + * @private + */ + unfreezeSection_: function(section) { + if (!section.classList.contains('frozen')) + return; + var card = section.$.card; + section.classList.remove('frozen'); + card.style.top = ''; + card.style.height = ''; + card.style.width = ''; + section.style.height = ''; + }, + + /** + * Expands the card in |section| to fill the page. + * @param {!SettingsSectionElement} section + * @return {!Promise} + * @private + */ + playExpandSection_: function(section) { + var card = section.$.card; + + // The card should start at the top of the page. + var targetTop = this.parentElement.getBoundingClientRect().top; + + section.classList.add('expanding'); + + // Expand the card, using minHeight. (The card must span the container's + // client height, so it must be at least 100% in case the card is too short. + // If the card is already taller than the container's client height, we + // don't want to shrink the card to 100% or the content will overflow, so + // we can't use height, and animating height wouldn't look right anyway.) + var keyframes = [{ + top: card.style.top, + minHeight: card.style.height, + easing: EASING_FUNCTION, + }, { + top: targetTop + 'px', + minHeight: 'calc(100% - ' + targetTop + 'px)', + }]; + var options = /** @type {!KeyframeEffectOptions} */({ + duration: EXPAND_DURATION + }); + // TODO(michaelpg): Change elevation of sections. + var promise; + if (keyframes[0].top && keyframes[0].minHeight) + promise = this.animateElement('section', card, keyframes, options); + else + promise = Promise.resolve(); + + promise.then(function() { + section.classList.add('expanded'); + card.style.top = ''; + this.style.margin = 'auto'; + section.$.header.hidden = true; + section.style.height = ''; + }.bind(this), function() { + // The animation was canceled; catch the error and continue. + }).then(function() { + // Whether finished or canceled, clean up the animation. + section.classList.remove('expanding'); + card.style.height = ''; + }); + + return promise; + }, + + /** + * Collapses the card in |section| back to its normal position. + * @param {!SettingsSectionElement} section + * @return {!Promise} + * @private + */ + playCollapseSection_: function(section) { + var card = section.$.card; + var cardStyle = getComputedStyle(card); + + this.style.margin = ''; + section.$.header.hidden = false; + + var startingTop = this.parentElement.getBoundingClientRect().top; + + var cardHeightStart = card.clientHeight; + + section.classList.add('collapsing'); + section.classList.remove('expanding', 'expanded'); + + // If we navigated here directly, we don't know the original height of the + // section, so we skip the animation. + // TODO(michaelpg): remove this condition once sliding is implemented. + if (isNaN(card.origHeight_)) + return Promise.resolve(); + + // Restore the section to its proper height to make room for the card. + section.style.height = section.clientHeight + card.origHeight_ + 'px'; + + // TODO(michaelpg): this should be in collapseSection(), but we need to wait + // until the full page height is available (setting the section height). + this.scroller.scrollTop = this.listScrollTop_; + + // The card is unpositioned, so use its position as the ending state, + // but account for scroll. + var targetTop = card.getBoundingClientRect().top - this.scroller.scrollTop; + + var keyframes = [{ + top: startingTop + 'px', + minHeight: cardHeightStart + 'px', + easing: EASING_FUNCTION, + }, { + top: targetTop + 'px', + minHeight: card.origHeight_ + 'px', + }]; + var options = /** @type {!KeyframeEffectOptions} */({ + duration: EXPAND_DURATION + }); + var promise = this.animateElement('section', card, keyframes, options); + return promise; + }, +}; + +/** @polymerBehavior */ +var MainPageBehavior = [ + TransitionBehavior, + MainPageBehaviorImpl +]; + +/** + * TODO(michaelpg): integrate slide animations. + * @polymerBehavior RoutableBehavior + */ +var RoutableBehaviorImpl = { + properties: { + /** Contains the current route. */ + currentRoute: { + type: Object, + notify: true, + observer: 'currentRouteChanged_', + }, + }, + + /** @private */ + currentRouteChanged_: function(newRoute, oldRoute) { + // route.section is only non-empty when the user is within a subpage. + // When the user is not in a subpage, but on the Basic page, route.section + // is an empty string. + var newRouteIsSubpage = newRoute && newRoute.section; + var oldRouteIsSubpage = oldRoute && oldRoute.section; + + if (!oldRoute && newRouteIsSubpage) { + // Allow the page to load before expanding the section. TODO(michaelpg): + // Time this better when refactoring settings-animated-pages. + setTimeout(function() { + var section = this.getSection_(newRoute.section); + if (section) + this.expandSection(section); + }.bind(this)); + return; + } + + if (!newRouteIsSubpage && oldRouteIsSubpage) { + var section = this.getSection_(oldRoute.section); + if (section) + this.collapseSection(section); + } else if (newRouteIsSubpage && + (!oldRouteIsSubpage || newRoute.section != oldRoute.section)) { + var section = this.getSection_(newRoute.section); + if (section) + this.expandSection(section); + } + }, + + /** + * Helper function to get a section from the local DOM. + * @param {string} section Section name of the element to get. + * @return {?SettingsSectionElement} + * @private + */ + getSection_: function(section) { + return /** @type {?SettingsSectionElement} */( + this.$$('[section=' + section + ']')); + }, +}; + +/** @polymerBehavior */ +var RoutableBehavior = [ + MainPageBehavior, + RoutableBehaviorImpl +];
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.css b/chrome/browser/resources/settings/settings_page/settings_section.css index f0c37a91..85d6e91 100644 --- a/chrome/browser/resources/settings/settings_page/settings_section.css +++ b/chrome/browser/resources/settings/settings_page/settings_section.css
@@ -7,15 +7,9 @@ * Common styles for Settings pages. */ :host { - display: block; -} - -:host(.expanded) { - height: 100%; -} - -:host(.expanded) #header { - display: none; + display: flex; + flex-direction: column; + position: relative; } #header { @@ -28,31 +22,28 @@ font-weight: 500; } -paper-material { +#card { background-color: white; - box-sizing: border-box; overflow: hidden; } -paper-material, -#placeholder { - margin-bottom: 16px; +#card { + flex: 1; } -:host(.neon-animating) paper-material { - position: fixed; - z-index: 1; -} - -:host(.expanded) paper-material { +:host(.expanded) { margin-bottom: 0; - min-height: 100%; } -#placeholder { - visibility: hidden; +:host(.expanded) #header { + display: none; } -:host(:not(.neon-animating)) #placeholder { - position: absolute; +:host(.frozen) #card { + position: fixed; + width: 100%; +} + +:host(.expanded.frozen) #card { + position: relative; }
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.html b/chrome/browser/resources/settings/settings_page/settings_section.html index 344dc76..ed4e263 100644 --- a/chrome/browser/resources/settings/settings_page/settings_section.html +++ b/chrome/browser/resources/settings/settings_page/settings_section.html
@@ -11,7 +11,6 @@ <paper-material id="card" animated> <content id="content"></content> </paper-material> - <div id="placeholder"></div> </template> <script src="settings_section.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.js b/chrome/browser/resources/settings/settings_page/settings_section.js index 1365dad..1149e2ea 100644 --- a/chrome/browser/resources/settings/settings_page/settings_section.js +++ b/chrome/browser/resources/settings/settings_page/settings_section.js
@@ -16,18 +16,11 @@ Polymer({ is: 'settings-section', - behaviors: [ - Polymer.NeonAnimationRunnerBehavior, - ], - properties: { /** * The current active route. */ - currentRoute: { - type: Object, - observer: 'currentRouteChanged_', - }, + currentRoute: Object, /** * The section is expanded to a full-page view when this property matches @@ -43,143 +36,5 @@ * Title for the page header and navigation menu. */ pageTitle: String, - - animationConfig: { - value: function() { - return { - collapse: { - name: 'collapse-card-animation', - node: this, - }, - expand: { - name: 'expand-card-animation', - node: this, - }, - }; - }, - }, }, - - listeners: { - 'expand-animation-complete': 'onExpandAnimationComplete_', - }, - - /** @private */ - currentRouteChanged_: function(newRoute, oldRoute) { - var newExpanded = newRoute.section == this.section; - var oldExpanded = oldRoute && oldRoute.section == this.section; - - var visible = newExpanded || this.currentRoute.section == ''; - - // If the user navigates directly to a subpage, skip all the animations. - if (!oldRoute) { - if (newExpanded) { - // If we navigate directly to a subpage, skip animations. - this.classList.add('expanded'); - } else if (!visible) { - this.hidden = true; - this.$.card.elevation = 0; - } - - return; - } - - if (newExpanded && !oldExpanded) { - this.playAnimation('expand'); - } else if (oldExpanded && !newExpanded) { - // For contraction, we defer the animation to allow - // settings-animated-pages to reflow the new page correctly. - this.async(function() { - this.playAnimation('collapse'); - }.bind(this)); - } - - this.$.card.elevation = visible ? 1 : 0; - - // Remove 'hidden' class immediately, but defer adding it if we are invisble - // until the animation is complete. - if (visible) - this.hidden = false; - }, - - /** @private */ - onExpandAnimationComplete_: function() { - this.hidden = this.currentRoute.section != '' && - this.currentRoute.section != this.section; - }, -}); - -Polymer({ - is: 'expand-card-animation', - - behaviors: [ - Polymer.NeonAnimationBehavior - ], - - configure: function(config) { - var section = config.node; - var card = section.$.card; - var containerRect = section.offsetParent.getBoundingClientRect(); - var cardRect = card.getBoundingClientRect(); - - // Set placeholder height so the page does not reflow during animation. - // TODO(tommycli): For URLs that directly load subpages, this does not work. - var placeholder = section.$.placeholder; - placeholder.style.top = card.offsetTop + 'px'; - placeholder.style.height = card.offsetHeight + 'px'; - - section.classList.add('neon-animating'); - - this._effect = new KeyframeEffect(card, [ - {'top': cardRect.top + 'px', 'height': cardRect.height + 'px'}, - {'top': containerRect.top + 'px', 'height': containerRect.height + 'px'}, - ], this.timingFromConfig(config)); - return this._effect; - }, - - complete: function(config) { - var section = config.node; - section.classList.remove('neon-animating'); - section.classList.add('expanded'); - - // This event fires on itself as well, but that is benign. - var sections = section.parentNode.querySelectorAll('settings-section'); - for (var i = 0; i < sections.length; ++i) { - sections[i].fire('expand-animation-complete'); - } - } -}); - -Polymer({ - is: 'collapse-card-animation', - - behaviors: [ - Polymer.NeonAnimationBehavior - ], - - configure: function(config) { - var section = config.node; - var oldRect = section.offsetParent.getBoundingClientRect(); - - section.classList.remove('expanded'); - - var card = section.$.card; - var placeholder = section.$.placeholder; - placeholder.style.top = card.offsetTop + 'px'; - placeholder.style.height = card.offsetHeight + 'px'; - - var newRect = card.getBoundingClientRect(); - - section.classList.add('neon-animating'); - - this._effect = new KeyframeEffect(card, [ - {'top': oldRect.top + 'px', 'height': oldRect.height + 'px'}, - {'top': newRect.top + 'px', 'height': newRect.height + 'px'}, - ], this.timingFromConfig(config)); - return this._effect; - }, - - complete: function(config) { - config.node.classList.remove('neon-animating'); - } });
diff --git a/chrome/browser/resources/settings/settings_page/transition_behavior.html b/chrome/browser/resources/settings/settings_page/transition_behavior.html new file mode 100644 index 0000000..c7c60bd0 --- /dev/null +++ b/chrome/browser/resources/settings/settings_page/transition_behavior.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<script src="chrome://md-settings/settings_page/transition_behavior.js"></script>
diff --git a/chrome/browser/resources/settings/settings_page/transition_behavior.js b/chrome/browser/resources/settings/settings_page/transition_behavior.js new file mode 100644 index 0000000..0aecfb39 --- /dev/null +++ b/chrome/browser/resources/settings/settings_page/transition_behavior.js
@@ -0,0 +1,86 @@ +// Copyright 2016 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. + +/** + * Adds convenience functions to control native Web Animations. The + * implementation details may change as Chrome support evolves. + * @polymerBehavior + */ +var TransitionBehavior = { + ready: function() { + /** + * @type {!Object<!Animation>} + * Map of running animations by animation name. Animation names are + * arbitrary but used to prevent multiple animations of the same type (e.g., + * expand/collapse section) from running simultaneously. + */ + this.animations = {}; + + /** + * @private {!Object<!Promise>} + * Map of Promises for each running animation. Key names and existence + * should correspond with |animations|. + */ + this.promises_ = {}; + }, + + /** + * Calls el.animate(keyframes, opt_options). Returns a Promise which is + * resolved when the transition ends, or rejected when the transition is + * canceled. If an animation with the same name is in progress, that + * animation is finished immediately before creating the new animation. + * @param {string} name Name of the animation, used to finish this animation + * when playing the same type of animation again. + * @param {!HTMLElement} el The element to animate. + * @param {!Array|!Object} keyframes Keyframes, as in Element.animate. + * @param {number|!KeyframeEffectOptions=} opt_options Options, as in + * Element.animate. + * @return {!Promise} A promise which is resolved when the animation finishes + * or rejected if the animation is canceled. + */ + animateElement: function(name, el, keyframes, opt_options) { + if (this.animations[name]) + this.animations[name].finish(); + + var animation = el.animate(keyframes, opt_options); + this.animations[name] = animation; + + this.promises_[name] = new Promise(function(resolve, reject) { + animation.addEventListener('finish', function() { + this.animations[name] = undefined; + resolve(); + }.bind(this)); + + animation.addEventListener('cancel', function() { + this.animations[name] = undefined; + reject(); + }.bind(this)); + }.bind(this)); + return this.promises_[name]; + }, + + /** + * Finishes the ongoing named animation, waits for the animation's Promise + * to be resolved, then calls the callback. + * @param {string} name Name of the animation passed to animateElement. + * @param {function()=} opt_callback Called once the animation finishes. + */ + finishAnimation: function(name, opt_callback) { + if (opt_callback) + this.promises_[name].then(opt_callback); + this.animations[name].finish(); + }, + + /** + * Cancels the ongoing named animation, waits for the animation's Promise + * to be rejected, then calls the callback. + * @param {string} name Name of the animation passed to animateElement. + * @param {function()=} opt_callback Called once the animation cancels. + */ + cancelAnimation: function(name, opt_callback) { + if (opt_callback) + this.promises_[name].catch(opt_callback); + this.animations[name].cancel(); + }, +};
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index d69f466..a70b4501 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -140,9 +140,21 @@ <structure name="IDR_SETTINGS_CR_SETTINGS_PAGE_CSS" file="settings_page.css" type="chrome_html" /> + <structure name="IDR_SETTINGS_MAIN_PAGE_BEHAVIOR_HTML" + file="settings_page/main_page_behavior.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_MAIN_PAGE_BEHAVIOR_JS" + file="settings_page/main_page_behavior.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_SETTINGS_SHARED_CSS_HTML" file="settings_shared_css.html" type="chrome_html" /> + <structure name="IDR_SETTINGS_TRANSITION_BEHAVIOR_HTML" + file="settings_page/transition_behavior.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_TRANSITION_BEHAVIOR_JS" + file="settings_page/transition_behavior.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_BREADCRUMB_CSS" file="settings_ui/breadcrumb.css" type="chrome_html" />
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc index b42266d..5eab3e7 100644 --- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
@@ -238,6 +238,7 @@ DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this); input_method::InputMethodManager::Get()->AddObserver(this); + input_method::InputMethodManager::Get()->AddImeMenuObserver(this); ui::ime::InputMethodMenuManager::GetInstance()->AddObserver(this); g_browser_process->platform_part()->GetSystemClock()->AddObserver(this); @@ -1294,6 +1295,16 @@ OnShutdownPolicyChanged(reboot_on_shutdown)); } +void SystemTrayDelegateChromeOS::ImeMenuActivationChanged(bool is_active) { + GetSystemTrayNotifier()->NotifyRefreshIMEMenu(is_active); +} + +void SystemTrayDelegateChromeOS::ImeMenuListChanged() {} + +void SystemTrayDelegateChromeOS::ImeMenuItemsChanged( + const std::string& engine_id, + const std::vector<input_method::InputMethodManager::MenuItem>& items) {} + const base::string16 SystemTrayDelegateChromeOS::GetLegacySupervisedUserMessage() const { std::string user_manager_name = GetSupervisedUserManager();
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.h b/chrome/browser/ui/ash/system_tray_delegate_chromeos.h index 726ede8..a60e6e9 100644 --- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.h +++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.h
@@ -68,7 +68,8 @@ public user_manager::UserManager::UserSessionStateObserver, public SupervisedUserServiceObserver, public ShutdownPolicyHandler::Delegate, - public system::SystemClockObserver { + public system::SystemClockObserver, + public input_method::InputMethodManager::ImeMenuObserver { public: SystemTrayDelegateChromeOS(); @@ -269,6 +270,14 @@ // Overridden from ShutdownPolicyObserver::Delegate. void OnShutdownPolicyChanged(bool reboot_on_shutdown) override; + // input_method::InputMethodManager::ImeMenuObserver: + void ImeMenuActivationChanged(bool is_active) override; + void ImeMenuListChanged() override; + void ImeMenuItemsChanged( + const std::string& engine_id, + const std::vector<input_method::InputMethodManager::MenuItem>& items) + override; + // helper methods used by GetSupervisedUserMessage. const base::string16 GetLegacySupervisedUserMessage() const; const base::string16 GetChildUserMessage() const;
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 0a63f037..a9d437f0 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/command_line.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" @@ -28,6 +29,7 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/signin/easy_unlock_service.h" #include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h" +#include "chromeos/chromeos_switches.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "ui/chromeos/strings/grit/ui_chromeos_strings.h" @@ -91,6 +93,16 @@ {"delayBeforeClickVeryLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG}, {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL}, {"a11yExplanation", IDS_SETTINGS_ACCESSIBILITY_EXPLANATION}, + {"caretHighlightLabel", + IDS_OPTIONS_SETTINGS_ACCESSIBILITY_CARET_HIGHLIGHT_DESCRIPTION}, + {"cursorHighlightLabel", + IDS_OPTIONS_SETTINGS_ACCESSIBILITY_CURSOR_HIGHLIGHT_DESCRIPTION}, + {"focusHighlightLabel", + IDS_OPTIONS_SETTINGS_ACCESSIBILITY_FOCUS_HIGHLIGHT_DESCRIPTION}, + {"selectToSpeakLabel", + IDS_OPTIONS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION}, + {"switchAccessLabel", + IDS_OPTIONS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_DESCRIPTION}, #endif }; AddLocalizedStringsBulk(html_source, localized_strings, @@ -99,6 +111,10 @@ #if defined(OS_CHROMEOS) html_source->AddString("a11yLearnMoreUrl", chrome::kChromeAccessibilityHelpURL); + + html_source->AddBoolean("showExperimentalA11yFeatures", + base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kEnableExperimentalAccessibilityFeatures)); #endif }
diff --git a/chrome/installer/setup/installer_metrics.cc b/chrome/installer/setup/installer_metrics.cc index 8e5f0443..5bf860c 100644 --- a/chrome/installer/setup/installer_metrics.cc +++ b/chrome/installer/setup/installer_metrics.cc
@@ -8,29 +8,29 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/metrics/histogram_base.h" -#include "base/metrics/histogram_persistence.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/metrics/persistent_memory_allocator.h" #include "chrome/installer/util/util_constants.h" namespace installer { void BeginPersistentHistogramStorage() { - base::SetPersistentHistogramMemoryAllocator( - new base::LocalPersistentMemoryAllocator( - 1 << 20, 0, // 1 MiB - installer::kSetupHistogramAllocatorName)); - base::GetPersistentHistogramMemoryAllocator()->CreateTrackingHistograms( + base::PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory( + 1 << 20, // 1 MiB + 0, // No identifier. installer::kSetupHistogramAllocatorName); + base::PersistentHistogramAllocator::GetGlobalAllocator() + ->CreateTrackingHistograms(installer::kSetupHistogramAllocatorName); } void EndPersistentHistogramStorage(const base::FilePath& target_path) { + base::PersistentHistogramAllocator* allocator = + base::PersistentHistogramAllocator::GetGlobalAllocator(); + allocator->UpdateTrackingHistograms(); + // For atomicity, first write to a temporary file and then rename it. // The ImportantFileWriter would be good for this except it supports only // std::string for its data. - base::PersistentMemoryAllocator* allocator = - base::GetPersistentHistogramMemoryAllocator(); - allocator->UpdateTrackingHistograms(); - base::FilePath file_path = target_path .AppendASCII(allocator->Name()) .AddExtension(L".pma");
diff --git a/chrome/renderer/worker_content_settings_client_proxy.cc b/chrome/renderer/worker_content_settings_client_proxy.cc index ce38f34..a98867c 100644 --- a/chrome/renderer/worker_content_settings_client_proxy.cc +++ b/chrome/renderer/worker_content_settings_client_proxy.cc
@@ -31,20 +31,6 @@ WorkerContentSettingsClientProxy::~WorkerContentSettingsClientProxy() {} -bool WorkerContentSettingsClientProxy::allowDatabase( - const blink::WebString& name, - const blink::WebString& display_name, - unsigned long estimated_size) { - if (is_unique_origin_) - return false; - - bool result = false; - sync_message_filter_->Send(new ChromeViewHostMsg_AllowDatabase( - routing_id_, document_origin_url_, top_frame_origin_url_, - name, display_name, &result)); - return result; -} - bool WorkerContentSettingsClientProxy::requestFileSystemAccessSync() { if (is_unique_origin_) return false;
diff --git a/chrome/renderer/worker_content_settings_client_proxy.h b/chrome/renderer/worker_content_settings_client_proxy.h index 1a9739d6..1e843a23 100644 --- a/chrome/renderer/worker_content_settings_client_proxy.h +++ b/chrome/renderer/worker_content_settings_client_proxy.h
@@ -32,9 +32,6 @@ ~WorkerContentSettingsClientProxy() override; // WebWorkerContentSettingsClientProxy overrides. - bool allowDatabase(const blink::WebString& name, - const blink::WebString& display_name, - unsigned long estimated_size) override; bool requestFileSystemAccessSync() override; bool allowIndexedDB(const blink::WebString& name) override;
diff --git a/chrome/test/data/autofill/heuristics/input/140_checkout_nike.com.html b/chrome/test/data/autofill/heuristics/input/140_checkout_nike.com.html new file mode 100644 index 0000000..99f965d8 --- /dev/null +++ b/chrome/test/data/autofill/heuristics/input/140_checkout_nike.com.html
@@ -0,0 +1,613 @@ +<form id="shippingForm" name="shippingForm" action="https://secure-store.nike.com/us/checkout/html/shipping.jsp?_DARGS=/us/checkout/common/shipping.jsp.shippingForm" class="panel formValidation" method="post" novalidate=""><input name="_dyncharset" value="UTF-8" type="hidden"><input name="_dynSessConf" value="-8061397768254292283" type="hidden"><input id="copyFrom" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.copyfrom" value="" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.copyfrom" value=" " type="hidden"><input id="copyAddress" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.copyAddress" value="" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.copyAddress" value=" " type="hidden"><input id="s_copyShipToBillingAddress" name="copyShipToBillingAddress" value="true" type="hidden"><input name="_D:copyShipToBillingAddress" value=" " type="hidden"><input id="saveShipAddressToProfile" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.saveShipAddressToProfile" value="false" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.saveShipAddressToProfile" value=" " type="hidden"><input id="s_firstName" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.firstName" value="" class="js-firstName_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.firstName" value=" " type="hidden"><input id="s_lastName" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.lastName" value="" class="js-lastName_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.lastName" value=" " type="hidden"><input id="s_altFirstName" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.altFirstName" value="" class="js-altFirstName_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.altFirstName" value=" " type="hidden"><input id="s_altLastName" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.altLastName" value="" class="js-altLastName_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.altLastName" value=" " type="hidden"><input id="s_zipCode" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.postalCode" value="" class="js-zipCode_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.postalCode" value=" " type="hidden"><input id="s_address1" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.address1" value="" class="js-address1_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.address1" value=" " type="hidden"><input id="s_address2" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.address2" value="" class="js-address2_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.address2" value=" " type="hidden"><input id="s_address3" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.address3" value="" class="js-address3_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.address3" value=" " type="hidden"><input id="s_city" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.city" value="" class="js-city_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.city" value=" " type="hidden"><input id="s_county" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.county" value="" class="js-county_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.county" value=" " type="hidden"><input id="s_state" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.state" value="" class="js-state_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.state" value=" " type="hidden"><input id="s_companyName" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.companyName" value="" class="js-companyName_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.companyName" value=" " type="hidden"><input id="s_accessPointField" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.accessPointId" value="" class="js-accessPoint_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.accessPointId" value=" " type="hidden"><input id="s_cppField" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.cppId" value="" class="js-cpp_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.cppId" value=" " type="hidden"><input id="s_shippingAddressValidationCode" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.validatedCode" value="0" class="js-shippingAddressValidationCode_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.validatedCode" value=" " type="hidden"><input id="s_phoneNumber" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.phoneNumber" value="" class="js-phoneNumber_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.phoneNumber" value=" " type="hidden"><input id="s_faxNumber" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.faxNumber" value="" class="js-faxNumber_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.faxNumber" value=" " type="hidden"><input id="s_email" name="/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.email" value="" class="js-email_s" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.shippingGroup.shippingAddress.email" value=" " type="hidden"><input name="/atg/commerce/order/purchase/ShippingGroupFormHandler.captureFapiao" value="false" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.captureFapiao" value=" " type="hidden"><input name="/atg/commerce/order/purchase/ShippingGroupFormHandler.capturePreferredDeliveryDay" value="false" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.capturePreferredDeliveryDay" value=" " type="hidden"><!-- Left column and cart items --> + <div id="ch4_checkoutItems"> + <div id="ch4_checkoutHeadingOpen" class="ch4_uppercase">1. SHIPPING</div> + <div id="ch4_checkoutShippingForm"> + + <div class="shippingSection"> + + <input type="hidden" id="hasSavedAddresses" name="hasSavedAddresses" value="false"> + <div class="ch4_formAddressType ch4_uppercase"> + <input id="singleAddress" type="radio" name="selectAddressType" class="ch4_formAddressTypeRadio js-addressType" value="singleAddress" checked="" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: Home/Office Address + parseable name: selectAddressType + field signature: 3604897261 + form signature: 17034931100313024041"> + <label for="singleAddress"> + Home/Office Address</label> + </div> + <div class="ch4_formAddressType ch4_uppercase"> + <input id="militaryAddress" type="radio" name="selectAddressType" class="ch4_formAddressTypeRadio js-addressType" value="militaryAddress" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: APO/FPO + parseable name: selectAddressType + field signature: 3604897261 + form signature: 17034931100313024041"> + <label for="militaryAddress"> + APO/FPO</label> + <a href="#" class="ch4_help"><div class="ch4_toolTip" style="display: none;"><div class="ch4_toolTipArrow"></div>Nike proudly supports our service men and women overseas! Choose APO/FPO if you are shipping to someone at a Military Post Office. Note: NIKEiD products excluded.</div></a> + </div> + <div class="singleAddress" style="display:block"> + <!-- intl shopping include --> + +<!-- intl shopping studio flag = false --> +<div class="ch4_formRow"> + <div class="ch4_formLabel">First Name <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="fname" id="fname" maxlength="35" type="text" class="ch4_formTextField js-firstName ch4_formTextFieldError" required="required" data-error-invalid="You have entered an invalid character." data-error-blacklist="Blacklisted character" data-error-required="Please enter your first name." data-validate="name" value="" title="overall type: NAME_FIRST + server type: NAME_FIRST + heuristic type: NAME_FIRST + label: First Name * + parseable name: fname + field signature: 2852189818 + form signature: 17034931100313024041" data-msg="Please enter your first name."><div class="ch4_errorTip" style="left: 202px; top: 0px;"><div class="ch4_errorTipTipLeft"> </div>Please enter your first name.</div> + </div> + </div> + <div class="ch4_formRow"> + <div class="ch4_formLabel">Last Name <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="lname" id="lname" maxlength="35" type="text" class="ch4_formTextField js-lastName" required="required" data-error-invalid="You have entered an invalid character." data-error-blacklist="Blacklisted character" data-error-required="Please enter your last name." data-validate="name" value="" title="overall type: NAME_LAST + server type: NAME_LAST + heuristic type: NAME_LAST + label: Last Name * + parseable name: lname + field signature: 3030290319 + form signature: 17034931100313024041"> + </div> + </div> +<div class="ch4_formRow"> + <div class="ch4_formLabel">Address <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="address1Field" id="address1Field" maxlength="35" type="text" class="ch4_formTextField js-address1" value="" title="overall type: ADDRESS_HOME_LINE1 + server type: ADDRESS_HOME_LINE1 + heuristic type: ADDRESS_HOME_LINE1 + label: Address * + parseable name: address1Field + field signature: 3711209280 + form signature: 17034931100313024041"><br> + </div> + <div class="ch4_formExtraInfoAPO"> + We do not ship to P.O. boxes</div> + </div> + <div class="ch4_formRow"> + <div class="ch4_formLabel"> </div> + <div class="ch4_formField"> + <input name="address2Field" id="address2Field" maxlength="35" type="text" class="ch4_formTextField js-address2" value="" title="overall type: ADDRESS_HOME_LINE2 + server type: ADDRESS_HOME_LINE2 + heuristic type: ADDRESS_HOME_LINE2 + label: 1. SHIPPING + parseable name: address2Field + field signature: 3200000380 + form signature: 17034931100313024041"><br> + </div> + </div> + + <div id="hideCity" class="ch4_formRow"> + <div class="ch4_formLabel">City <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="city" id="singleCity" maxlength="35" type="text" class="ch4_formTextField js-city" value="" title="overall type: ADDRESS_HOME_CITY + server type: ADDRESS_HOME_CITY + heuristic type: ADDRESS_HOME_CITY + label: City * + parseable name: city + field signature: 2098554694 + form signature: 17034931100313024041"> + </div> + </div> + + <div id="hideState" class="ch4_formRow"> + <div class="ch4_formLabel">State <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <div class="style-select-wrapper"> + <select name="singleState" id="singleState" class="js-state" data-update="js-state_s" title="overall type: ADDRESS_HOME_STATE + server type: ADDRESS_HOME_STATE + heuristic type: ADDRESS_HOME_STATE + label: State * + parseable name: singleState + field signature: 1160507728 + form signature: 17034931100313024041"> + <option value="">Select State</option> + <option value="AL"> + Alabama</option> + <option value="AK"> + Alaska</option> + <option value="AZ"> + Arizona</option> + <option value="AR"> + Arkansas</option> + <option value="CA"> + California</option> + <option value="CO"> + Colorado</option> + <option value="CT"> + Connecticut</option> + <option value="DE"> + Delaware</option> + <option value="DC"> + District of Columbia</option> + <option value="FL"> + Florida</option> + <option value="GA"> + Georgia</option> + <option value="HI"> + Hawaii</option> + <option value="ID"> + Idaho</option> + <option value="IL"> + Illinois</option> + <option value="IN"> + Indiana</option> + <option value="IA"> + Iowa</option> + <option value="KS"> + Kansas</option> + <option value="KY"> + Kentucky</option> + <option value="LA"> + Louisiana</option> + <option value="ME"> + Maine</option> + <option value="MD"> + Maryland</option> + <option value="MA"> + Massachusetts</option> + <option value="MI"> + Michigan</option> + <option value="MN"> + Minnesota</option> + <option value="MS"> + Mississippi</option> + <option value="MO"> + Missouri</option> + <option value="MT"> + Montana</option> + <option value="NE"> + Nebraska</option> + <option value="NV"> + Nevada</option> + <option value="NH"> + New Hampshire</option> + <option value="NJ"> + New Jersey</option> + <option value="NM"> + New Mexico</option> + <option value="NY"> + New York</option> + <option value="NC"> + North Carolina</option> + <option value="ND"> + North Dakota</option> + <option value="OH"> + Ohio</option> + <option value="OK"> + Oklahoma</option> + <option value="OR"> + Oregon</option> + <option value="PA"> + Pennsylvania</option> + <option value="RI"> + Rhode Island</option> + <option value="SC"> + South Carolina</option> + <option value="SD"> + South Dakota</option> + <option value="TN"> + Tennessee</option> + <option value="TX"> + Texas</option> + <option value="UT"> + Utah</option> + <option value="VT"> + Vermont</option> + <option value="VA"> + Virginia</option> + <option value="WA"> + Washington</option> + <option value="WV"> + West Virginia</option> + <option value="WI"> + Wisconsin</option> + <option value="WY"> + Wyoming</option> + </select> + <div class="style-select"></div> + </div> +</div> + </div> + <div class="ch4_formRow"> + <div class="ch4_formLabel">ZIP Code <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="postalCodeField" id="postalCodeField" type="text" maxlength="10" class="ch4_formTextField js-zipCode" value="" title="overall type: ADDRESS_HOME_ZIP + server type: ADDRESS_HOME_ZIP + heuristic type: ADDRESS_HOME_ZIP + label: ZIP Code * + parseable name: postalCodeField + field signature: 1505678046 + form signature: 17034931100313024041"> + </div> + </div> + <input name="countryField" class="js-country" type="hidden" value="US"> + </div> + <div class="militaryAddress" style="display:none"> + <div class="ch4_formRow"> + <div class="ch4_formLabel">First Name <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="fname" id="fname_apofpo" maxlength="35" type="text" class="ch4_formTextField js-firstName" required="required" data-error-invalid="You have entered an invalid character." data-error-blacklist="Blacklisted character" data-error-required="Please enter your first name." data-validate="name" value="" title="overall type: NAME_FIRST + server type: NAME_FIRST + heuristic type: NAME_FIRST + label: First Name * + parseable name: fname + field signature: 2852189818 + form signature: 17034931100313024041"> + </div> + </div> + <div class="ch4_formRow"> + <div class="ch4_formLabel">Last Name <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="lname" id="lname_apofpo" maxlength="35" type="text" class="ch4_formTextField js-lastName" required="required" data-error-invalid="You have entered an invalid character." data-error-blacklist="Blacklisted character" data-error-required="Please enter your last name." data-validate="name" value="" title="overall type: NAME_LAST + server type: NAME_LAST + heuristic type: NAME_LAST + label: Last Name * + parseable name: lname + field signature: 3030290319 + form signature: 17034931100313024041"> + </div> + </div> +<div class="ch4_formRow"> + <div class="ch4_formLabel">Address <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="address1Field" id="address1Field_apofpo" maxlength="35" type="text" class="ch4_formTextField js-address1" value="" title="overall type: ADDRESS_HOME_LINE1 + server type: ADDRESS_HOME_LINE1 + heuristic type: ADDRESS_HOME_LINE1 + label: Address * + parseable name: address1Field + field signature: 3711209280 + form signature: 17034931100313024041"><br> + </div> + </div> + + <div class="ch4_formExtraInfoAPO"> + For Army, Navy, and Marines, enter your unit # and box #<br> + For ships, enter the ship name and hull #<br> + For Air Force, enter the PSC # and box #</div> + + <div class="ch4_formRow"> + <div class="ch4_formLabel"> </div> + <div class="ch4_formField"> + <input name="address2Field" id="address2Field_apofpo" maxlength="35" type="text" class="ch4_formTextField js-address2" value="" title="overall type: ADDRESS_HOME_LINE2 + server type: ADDRESS_HOME_LINE2 + heuristic type: ADDRESS_HOME_LINE2 + label: Enter the military command or organization name if applicable + parseable name: address2Field + field signature: 3200000380 + form signature: 17034931100313024041"><br> + </div> + <div class="ch4_formExtraInfoAPO">Enter the military command or organization name if applicable</div> + </div> + + <div class="ch4_formRow"> + <div class="ch4_formLabel">APO/FPO <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <div class="style-select-wrapper"> + <select name="apoCity" id="apoCity" class="js-city" data-update="js-city_s" title="overall type: ADDRESS_HOME_CITY + server type: NO_SERVER_DATA + heuristic type: ADDRESS_HOME_CITY + label: APO/FPO * + parseable name: apoCity + field signature: 1890694515 + form signature: 17034931100313024041"> + <option value="APO" selected="">Army Post Office</option> + <option value="FPO">Fleet Post Office</option> + </select> + <div class="style-select"></div> + </div> + </div> + </div> + + <div class="ch4_formRow"> + <div class="ch4_formLabel">Region <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <div class="style-select-wrapper"> + <select name="apoState" class="js-state" id="apoState" data-update="js-state_s" title="overall type: ADDRESS_HOME_STATE + server type: NO_SERVER_DATA + heuristic type: ADDRESS_HOME_STATE + label: Region * + parseable name: apoState + field signature: 505741244 + form signature: 17034931100313024041"> + <option value="AA" selected="">Armed Forces Americas</option> + <option value="AE">Armed Forces Europe</option> + <option value="AP">Armed Forces Pacific</option> + </select> + <div class="style-select"></div> + </div> + </div> + </div> + + <div class="ch4_formRow"> + <div class="ch4_formLabel">ZIP Code <span class="requiredColor">*</span></div> + <div class="ch4_formField"> + <input name="postalCodeField" id="postalCodeField_apofpo" type="text" maxlength="10" class="ch4_formTextField js-zipCode" value="" title="overall type: ADDRESS_HOME_ZIP + server type: ADDRESS_HOME_ZIP + heuristic type: ADDRESS_HOME_ZIP + label: ZIP Code * + parseable name: postalCodeField + field signature: 1505678046 + form signature: 17034931100313024041"> + </div> + </div> + + <input name="countryField" class="js-country" type="hidden" value="US"> + + </div> + <input type="hidden" id="idItemInCart" value="false"> + <input type="hidden" id="sgid" value="SG1125902365"> + + <div class="marginTop"> + </div> + + <div class="marginTop"> + <div class="js-shippingMethodDisplay singleAddress savedAddress " style="display:block"> + <div class="shippingMethodTitle"> + Select Shipping Method: + <span href="#" class="ch4_help " style="cursor: pointer; ': ''}"> + <div class="ch4_toolTip" style="display: none;"> + <div class="ch4_toolTipArrow"></div> + Shipping estimates don’t include weekends or holidays. <a href="http://help-en-us.nike.com/app/answers/detail/article/shipping-delivery/a_id/19279/p/3897" class="ch4_toolTipLink" target="_blank">See details</a> + </div> + </span> + +</div> + <div class="js-shippingMethodText" style="display:none"> + <span class="eddDescription">Standard</span> + <span class="eddText"> + + + (<span class="js-eddLabel" data-method="Ground Service">Arrives 2-4 Days</span>) + </span> + <span class="eddPrice"><span class="nike-orange">FREE</span></span> + + +</div> + <div class="ch4_shippingMethodSelection js-shippingMethodSelection" style="display:block"> + <div class="ch4_radioUnit cbrUnit js-radioUnit ch4_hideValid"> + <input id="Ground_Service" type="radio" name="shippingMethod_single" class="js-shippingMethod ch4_hideValid " value="Ground Service" checked="checked" no-validate="" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: Standard (Arrives 2-4 Days) FREE + parseable name: shippingMethod_single + field signature: 2416614014 + form signature: 17034931100313024041"> + <label for="Ground_Service"> + </label> + <span class="shipping-label-text"> + <span class="eddDescription">Standard</span> + <span class="eddText"> + + + (<span class="js-eddLabel" data-method="Ground Service">Arrives 2-4 Days</span>) + </span> + <span class="eddPrice"><span class="nike-orange">FREE</span></span> + + +</span> + + </div> + + + <div class="ch4_radioUnit cbrUnit js-radioUnit ch4_hideValid"> + <input id="Two_Day_Air" type="radio" name="shippingMethod_single" class="js-shippingMethod ch4_hideValid " value="Two Day Air" no-validate="" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: Standard (Arrives 2-4 Days) FREE + parseable name: shippingMethod_single + field signature: 2416614014 + form signature: 17034931100313024041"> + <label for="Two_Day_Air"> + </label> + <span class="shipping-label-text"> + <span class="eddDescription">Two-Day</span> + <span class="eddText"> + + + (<span class="js-eddLabel" data-method="Two Day Air">Arrives 2-3 Days</span>) + </span> + <span class="eddPrice">$15.00</span> + + +</span> + + </div> + + + <div class="ch4_radioUnit cbrUnit js-radioUnit ch4_hideValid"> + <input id="Next_Day_Air" type="radio" name="shippingMethod_single" class="js-shippingMethod ch4_hideValid " value="Next Day Air" no-validate="" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: Standard (Arrives 2-4 Days) FREE + parseable name: shippingMethod_single + field signature: 2416614014 + form signature: 17034931100313024041"> + <label for="Next_Day_Air"> + </label> + <span class="shipping-label-text"> + <span class="eddDescription">Next-Day</span> + <span class="eddText"> + + + (<span class="js-eddLabel" data-method="Next Day Air">Arrives 1-2 Days</span>) + </span> + <span class="eddPrice">$25.00</span> + + +</span> + + </div> + + + </div> + </div> + + <div class="js-militaryShipping militaryAddress" style="display:none"> + <input type="hidden" class="js-shippingMethodDefault" value="Military Ground Service"> + <div class="marginTop"> + <div class="shippingMethodTitle"> + Shipping Method: + <span href="#" class="ch4_help " style="cursor: pointer; ': ''}"> + <div class="ch4_toolTip" style="display: none;"> + <div class="ch4_toolTipArrow"></div> + Shipping estimates don’t include weekends or holidays. <a href="http://help-en-us.nike.com/app/answers/detail/article/shipping-delivery/a_id/19279/p/3897" class="ch4_toolTipLink" target="_blank">See details</a> + </div> + </span> + +</div> + <span class="eddDescription">Military Ground</span> + <span class="eddText"> + + + (<span class="js-eddLabel" data-method="Military Ground Service">Arrives 30-45 Days</span>) + </span> + <span class="eddPrice"><span class="nike-orange">FREE</span></span> + + +</div> + </div> + <input type="hidden" id="sgid" value="SG1125902365"> + <input type="hidden" id="shipping_method" value=""> + + + <div style="display:block" class="ch4_transitTimesMessage">Orders placed after 5pm EST begin processing the next business day.</div> + <div style="display:none" class="ch4_POBoxTransitTimesMessage">Orders placed after 10am EST begin processing the next business day.</div> + <input type="hidden" id="noPreference" name="preferredDeliveryDay" data-validate="radio" class="ch4_formShippingRadio js-formShippingRadio" value="noPreference" checked=""> + </div> + + </div> <input id="isNewMember" name="/shared/UserAttributes.isNewMember" value="" type="hidden"><input name="_D:/shared/UserAttributes.isNewMember" value=" " type="hidden"><input id="emailOptIn" name="/shared/UserAttributes.emailOptIn" value="" type="hidden"><input name="_D:/shared/UserAttributes.emailOptIn" value=" " type="hidden"><div class="shippingSection removeInnerStyle"> + <input id="isNewMember" name="/shared/UserAttributes.isNewMember" value="" type="hidden"><input name="_D:/shared/UserAttributes.isNewMember" value=" " type="hidden"><input id="emailOptIn" name="/shared/UserAttributes.emailOptIn" value="" type="hidden"><input name="_D:/shared/UserAttributes.emailOptIn" value=" " type="hidden"><div id="newMemberSection" class="ch4_formRow" style="clear:both;"> + + <input type="checkbox" id="ch4_becomeMember" name="becomeMember" class="ch4_formCheckBox revealOnCheck" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: JOIN NIKE+ FOR FREE SHIPPING ON EVERY ORDER, EVERY TIME. + parseable name: becomeMember + field signature: 2079103496 + form signature: 17034931100313024041"> + <label for="ch4_becomeMember">JOIN NIKE+ FOR FREE SHIPPING ON EVERY ORDER, EVERY TIME.</label> + <div class="ch4_formRow">ALREADY HAVE A NIKE+ ACCOUNT? <a href="https://secure-store.nike.com/us/checkout/html/checkout_login.jsp">SIGN IN</a></div> + </div> + + <div class="becomeMemberDiv" style="display:none;"> + + <div class="ch4_formRow"> + <div class="ch4_formLabel">Email <span class="requiredColor">*</span></div> + <div class="ch4_formField"><input type="text" class="ch4_formTextField" name="reqEmail" id="reqEmail" maxlength="50" title="overall type: EMAIL_ADDRESS + server type: EMAIL_ADDRESS + heuristic type: EMAIL_ADDRESS + label: Email * + parseable name: reqEmail + field signature: 1897379167 + form signature: 17034931100313024041"></div> + </div> + + <div class="ch4_formRow reqPassword"> + <div class="ch4_formLabel">Password <span class="requiredColor">*</span></div> + <div class="ch4_formField"><input id="reqPassword" title="overall type: PASSWORD + server type: PASSWORD + heuristic type: UNKNOWN_TYPE + label: Password * + parseable name: reqPassword + field signature: 3606218395 + form signature: 17034931100313024041" class="ch4_formTextField" maxlength="36" type="password" onfocus="select()" name="reqPassword"></div> + </div> + + <div class="ch4_formRow"> + <div class="ch4_formLabel">Date of Birth <span class="requiredColor">*</span></div> + <div class="ch4_formField"><div class="style-select-wrapper monthDob-wrapper"> + <select id="monthDob" name="monthDob" class="monthDob" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: Date of Birth * + parseable name: monthDob + field signature: 3353643203 + form signature: 17034931100313024041"> + <option value="">MM</option> + <option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select> + <div class="style-select"></div> + </div> + <div class="style-select-wrapper dayDob-wrapper"> + <select id="dayDob" name="dayDob" class="dayDob" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: Date of Birth * + parseable name: dayDob + field signature: 2079150250 + form signature: 17034931100313024041"> + <option value="">DD</option> + <option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="10">10</option><option value="11">11</option><option value="12">12</option><option value="13">13</option><option value="14">14</option><option value="15">15</option><option value="16">16</option><option value="17">17</option><option value="18">18</option><option value="19">19</option><option value="20">20</option><option value="21">21</option><option value="22">22</option><option value="23">23</option><option value="24">24</option><option value="25">25</option><option value="26">26</option><option value="27">27</option><option value="28">28</option><option value="29">29</option><option value="30">30</option><option value="31">31</option></select> + <div class="style-select"></div> + </div> + <div class="style-select-wrapper yearDob-wrapper"> + <select id="yearDob" name="yearDob" class="yearDob" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: Date of Birth * + parseable name: yearDob + field signature: 2918622286 + form signature: 17034931100313024041"> + <option value="">YYYY</option> + <option id="currentYear" value="2016">2016</option> + <option value="2015">2015</option><option value="2014">2014</option><option value="2013">2013</option><option value="2012">2012</option><option value="2011">2011</option><option value="2010">2010</option><option value="2009">2009</option><option value="2008">2008</option><option value="2007">2007</option><option value="2006">2006</option><option value="2005">2005</option><option value="2004">2004</option><option value="2003">2003</option><option value="2002">2002</option><option value="2001">2001</option><option value="2000">2000</option><option value="1999">1999</option><option value="1998">1998</option><option value="1997">1997</option><option value="1996">1996</option><option value="1995">1995</option><option value="1994">1994</option><option value="1993">1993</option><option value="1992">1992</option><option value="1991">1991</option><option value="1990">1990</option><option value="1989">1989</option><option value="1988">1988</option><option value="1987">1987</option><option value="1986">1986</option><option value="1985">1985</option><option value="1984">1984</option><option value="1983">1983</option><option value="1982">1982</option><option value="1981">1981</option><option value="1980">1980</option><option value="1979">1979</option><option value="1978">1978</option><option value="1977">1977</option><option value="1976">1976</option><option value="1975">1975</option><option value="1974">1974</option><option value="1973">1973</option><option value="1972">1972</option><option value="1971">1971</option><option value="1970">1970</option><option value="1969">1969</option><option value="1968">1968</option><option value="1967">1967</option><option value="1966">1966</option><option value="1965">1965</option><option value="1964">1964</option><option value="1963">1963</option><option value="1962">1962</option><option value="1961">1961</option><option value="1960">1960</option><option value="1959">1959</option><option value="1958">1958</option><option value="1957">1957</option><option value="1956">1956</option><option value="1955">1955</option><option value="1954">1954</option><option value="1953">1953</option><option value="1952">1952</option><option value="1951">1951</option><option value="1950">1950</option><option value="1949">1949</option><option value="1948">1948</option><option value="1947">1947</option><option value="1946">1946</option><option value="1945">1945</option><option value="1944">1944</option><option value="1943">1943</option><option value="1942">1942</option><option value="1941">1941</option><option value="1940">1940</option><option value="1939">1939</option><option value="1938">1938</option><option value="1937">1937</option><option value="1936">1936</option><option value="1935">1935</option><option value="1934">1934</option><option value="1933">1933</option><option value="1932">1932</option><option value="1931">1931</option><option value="1930">1930</option><option value="1929">1929</option><option value="1928">1928</option><option value="1927">1927</option><option value="1926">1926</option><option value="1925">1925</option><option value="1924">1924</option><option value="1923">1923</option><option value="1922">1922</option><option value="1921">1921</option><option value="1920">1920</option><option value="1919">1919</option><option value="1918">1918</option><option value="1917">1917</option></select> + <div class="style-select"></div> +</div> + +</div> + </div> + + <div class="ch4_formRow"> + <div class="ch4_formLabel ch4_uppercase">Gender <span class="requiredColor">*</span></div> + <div class="ch4_formField ch4_genderText"> + <input id="genderMale" type="radio" name="gender" value="male" class="ch4_formRadio" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: MALE + parseable name: gender + field signature: 570340743 + form signature: 17034931100313024041"><label for="genderMale">MALE</label> + <input id="genderFemale" type="radio" name="gender" value="female" class="ch4_formRadio" style="margin-left:10px;" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: FEMALE + parseable name: gender + field signature: 570340743 + form signature: 17034931100313024041"><label for="genderFemale">FEMALE</label> + </div> + </div> + + <div id="ch4_formCheckBoxMember"> + <input class="ch4_formCheckBox" id="receiveNikeOffers" name="receiveNikeOffers" type="checkbox" checked="checked" title="overall type: UNKNOWN_TYPE + server type: NO_SERVER_DATA + heuristic type: UNKNOWN_TYPE + label: I would like to be the first to hear about new products, innovations and exclusive offers. + parseable name: receiveNikeOffers + field signature: 3715053362 + form signature: 17034931100313024041"> + <input id="optinId" name="optinId" value="1420C" type="hidden"> + <label for="receiveNikeOffers">I would like to be the first to hear about new products, innovations and exclusive offers.</label> + </div> + + </div> + + </div> <input id="apoFlag" name="apoFlag" type="hidden" value="false"> + <input id="langLocale" name="langLocale" type="hidden" value="en_US"> + <input id="country" name="country" type="hidden" value="US"> + <input type="hidden" id="route" name="route" value="html"> + <input name="/atg/commerce/order/purchase/ShippingGroupFormHandler.applyShippingInfoErrorURL" value="shippingPageURL" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.applyShippingInfoErrorURL" value=" " type="hidden"><input type="hidden" id="returnURL" name="returnURL" value="http://store.nike.com/us/en_us/pd/lunarepic-flyknit-running-shoe/pid-10871565/pgid-10940948"> + <input name="/atg/commerce/order/purchase/ShippingGroupFormHandler.applyShippingInfoSuccessURL" value="billingPageURL" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.applyShippingInfoSuccessURL" value=" " type="hidden"><input name="/atg/commerce/order/purchase/ShippingGroupFormHandler.applyShippingInfo" value="true" type="hidden"><input name="_D:/atg/commerce/order/purchase/ShippingGroupFormHandler.applyShippingInfo" value=" " type="hidden"><div class="ch4_formButtonRow " id=""> + <span class="requiredLabel"><span class="requiredColor">*</span> Required Fields</span> + <input type="button" id="shippingSubmit" name="shipSubmit" value="NEXT STEP" class="ch4_btn ch4_btnOrange ch4_btnDropShadow" style="min-width:100px;"> + </div> + </div> + </div> + + <input name="_DARGS" value="/us/checkout/common/shipping.jsp.shippingForm" type="hidden"></form>
diff --git a/chrome/test/data/autofill/heuristics/output/140_checkout_nike.com.out b/chrome/test/data/autofill/heuristics/output/140_checkout_nike.com.out new file mode 100644 index 0000000..d63b1247 --- /dev/null +++ b/chrome/test/data/autofill/heuristics/output/140_checkout_nike.com.out
@@ -0,0 +1,28 @@ +UNKNOWN_TYPE | selectAddressType | Home/Office Address | singleAddress | selectAddressType_1-default +UNKNOWN_TYPE | selectAddressType | APO/FPO | militaryAddress | selectAddressType_1-default +NAME_FIRST | fname | First Name * | | selectAddressType_1-default +NAME_LAST | lname | Last Name * | | selectAddressType_1-default +ADDRESS_HOME_LINE1 | address1Field | Address * | | selectAddressType_1-default +ADDRESS_HOME_LINE2 | address2Field | 1. SHIPPING | | selectAddressType_1-default +ADDRESS_HOME_CITY | city | City * | | selectAddressType_1-default +ADDRESS_HOME_STATE | singleState | State * | | selectAddressType_1-default +ADDRESS_HOME_ZIP | postalCodeField | ZIP Code * | | selectAddressType_1-default +NAME_FIRST | fname | First Name * | | selectAddressType_1-default +NAME_LAST | lname | Last Name * | | selectAddressType_1-default +ADDRESS_HOME_LINE1 | address1Field | Address * | | selectAddressType_1-default +ADDRESS_HOME_LINE2 | address2Field | Enter the military command or organization name if applicable | | selectAddressType_1-default +ADDRESS_HOME_CITY | apoCity | APO/FPO * | APO | selectAddressType_1-default +ADDRESS_HOME_STATE | apoState | Region * | AA | selectAddressType_1-default +ADDRESS_HOME_ZIP | postalCodeField | ZIP Code * | | selectAddressType_1-default +UNKNOWN_TYPE | shippingMethod_single | Standard (Arrives 2-4 Days) FREE | Ground Service | selectAddressType_1-default +UNKNOWN_TYPE | shippingMethod_single | Standard (Arrives 2-4 Days) FREE | Two Day Air | selectAddressType_1-default +UNKNOWN_TYPE | shippingMethod_single | Standard (Arrives 2-4 Days) FREE | Next Day Air | selectAddressType_1-default +UNKNOWN_TYPE | becomeMember | JOIN NIKE+ FOR FREE SHIPPING ON EVERY ORDER, EVERY TIME. | on | selectAddressType_1-default +EMAIL_ADDRESS | reqEmail | Email * | | selectAddressType_1-default +UNKNOWN_TYPE | reqPassword | Password * | | selectAddressType_1-default +UNKNOWN_TYPE | monthDob | Date of Birth * | | selectAddressType_1-default +UNKNOWN_TYPE | dayDob | Date of Birth * | | selectAddressType_1-default +UNKNOWN_TYPE | yearDob | Date of Birth * | | selectAddressType_1-default +UNKNOWN_TYPE | gender | MALE | male | selectAddressType_1-default +UNKNOWN_TYPE | gender | FEMALE | female | selectAddressType_1-default +UNKNOWN_TYPE | receiveNikeOffers | I would like to be the first to hear about new products, innovations and exclusive offers. | on | selectAddressType_1-default
diff --git a/chrome/test/data/webui/md_history/history_item_test.js b/chrome/test/data/webui/md_history/history_item_test.js index e6a2af4..e088063 100644 --- a/chrome/test/data/webui/md_history/history_item_test.js +++ b/chrome/test/data/webui/md_history/history_item_test.js
@@ -3,26 +3,28 @@ // found in the LICENSE file. cr.define('md_history.history_item_test', function() { - var TEST_HISTORY_RESULTS = [ - {"time": "1000000000"}, - {"time": "100000000"}, - {"time": "9000020"}, - {"time": "9000000"}, - {"time": "1"} - ]; - - var SEARCH_HISTORY_RESULTS = [ - {"dateShort": "Feb 22, 2016", "title": "Search result"}, - {"dateShort": "Feb 21, 2016", "title": "Search result 2"}, - {"dateShort": "Feb 21, 2016", "title": "Search result 3"}, - ]; - function registerTests() { suite('history-item', function() { var element; + var TEST_HISTORY_RESULTS; + var SEARCH_HISTORY_RESULTS; suiteSetup(function() { element = $('history-list'); + TEST_HISTORY_RESULTS = [ + createHistoryEntry('2016-03-16 10:00', 'http://www.google.com'), + createHistoryEntry('2016-03-16 9:00', 'http://www.example.com'), + createHistoryEntry('2016-03-16 7:01', 'http://www.badssl.com'), + createHistoryEntry('2016-03-16 7:00', 'http://www.website.com'), + createHistoryEntry('2016-03-16 4:00', 'http://www.website.com'), + createHistoryEntry('2016-03-15 11:00', 'http://www.example.com'), + ]; + + SEARCH_HISTORY_RESULTS = [ + createSearchEntry('2016-03-16', "http://www.google.com"), + createSearchEntry('2016-03-14', "http://calendar.google.com"), + createSearchEntry('2016-03-14', "http://mail.google.com") + ]; }); setup(function() { @@ -40,6 +42,7 @@ assertFalse(items[2].item.needsTimeGap); assertTrue(items[3].item.needsTimeGap); assertFalse(items[4].item.needsTimeGap); + assertFalse(items[5].item.needsTimeGap); done(); }); @@ -68,7 +71,7 @@ items[3].onCheckboxSelected_(); element.removeDeletedHistory(1); - assertEquals(element.historyData.length, 4); + assertEquals(element.historyData.length, 5); // Checks that a new time gap separator has been inserted. assertTrue(items[2].item.needsTimeGap);
diff --git a/chrome/test/data/webui/md_history/history_list_test.js b/chrome/test/data/webui/md_history/history_list_test.js index ede3c6d..54c9bc08 100644 --- a/chrome/test/data/webui/md_history/history_list_test.js +++ b/chrome/test/data/webui/md_history/history_list_test.js
@@ -3,57 +3,30 @@ // found in the LICENSE file. cr.define('md_history.history_list_test', function() { - // Array of test history data. - var TEST_HISTORY_RESULTS = [ - { - "dateRelativeDay": "Today - Wednesday, December 9, 2015", - "title": "Google", - "url": "https://www.google.com" - }, - { - "dateRelativeDay": "Yesterday - Tuesday, December 8, 2015", - "title": "Wikipedia", - "url": "https://en.wikipedia.com" - }, - { - "dateRelativeDay": "Monday, December 7, 2015", - "title": "Example", - "url": "https://www.example.com" - }, - { - "dateRelativeDay": "Monday, December 7, 2015", - "title": "Google", - "url": "https://www.google.com" - } - ]; - - var ADDITIONAL_RESULTS = [ - { - "dateRelativeDay": "Monday, December 7, 2015", - "url": "https://en.wikipedia.com" - }, - { - "dateRelativeDay": "Monday, December 7, 2015", - "url": "https://www.youtube.com" - }, - { - "dateRelativeDay": "Sunday, December 6, 2015", - "url": "https://www.google.com" - }, - { - "dateRelativeDay": "Saturday, December 5, 2015", - "url": "https://www.example.com" - } - ]; - function registerTests() { suite('history-list', function() { var element; var toolbar; + var TEST_HISTORY_RESULTS; + var ADDITIONAL_RESULTS; suiteSetup(function() { element = $('history-list'); toolbar = $('toolbar'); + + TEST_HISTORY_RESULTS = [ + createHistoryEntry('2016-03-15', 'https://www.google.com'), + createHistoryEntry('2016-03-14', 'https://en.wikipedia.org'), + createHistoryEntry('2016-03-13 10:00', 'https://www.example.com'), + createHistoryEntry('2016-03-13 9:00', 'https://www.google.com') + ]; + + ADDITIONAL_RESULTS = [ + createHistoryEntry('2016-03-12 10:00', 'https://en.wikipedia.org'), + createHistoryEntry('2016-03-12 9:50', 'https://www.youtube.com'), + createHistoryEntry('2016-03-11', 'https://www.google.com'), + createHistoryEntry('2016-03-10', 'https://www.example.com') + ]; }); test('setting first and last items', function() { @@ -124,9 +97,9 @@ assertEquals(toBeRemoved[0].url, element.historyData[0].url); assertEquals(toBeRemoved[1].url, element.historyData[1].url); assertEquals(toBeRemoved[0].timestamps, - element.historyData[0].timestamps); + element.historyData[0].allTimestamps); assertEquals(toBeRemoved[1].timestamps, - element.historyData[1].timestamps); + element.historyData[1].allTimestamps); done(); }); @@ -162,11 +135,11 @@ assertEquals(element.historyData.length, 5); assertEquals(element.historyData[0].dateRelativeDay, - "Today - Wednesday, December 9, 2015"); + '2016-03-15'); assertEquals(element.historyData[2].dateRelativeDay, - "Monday, December 7, 2015"); + '2016-03-13'); assertEquals(element.historyData[4].dateRelativeDay, - "Sunday, December 6, 2015"); + '2016-03-11'); // Checks that the first and last items have been reset correctly. assertTrue(element.historyData[2].isFirstItem); @@ -180,7 +153,9 @@ }); test('search results display with correct item title', function(done) { - element.addNewResults(TEST_HISTORY_RESULTS, 'Google'); + element.addNewResults( + [createHistoryEntry('2016-03-15', 'https://www.google.com')], + 'Google'); flush(function() { assertTrue(element.historyData[0].isFirstItem); @@ -193,7 +168,7 @@ assertTrue(index != -1); // Check that the search term is bolded correctly in the history-item. - assertEquals(title.innerHTML, '<b>Google</b>'); + assertGT(title.innerHTML.indexOf('<b>google</b>'), -1); done(); }); }); @@ -217,6 +192,7 @@ teardown(function() { element.historyData = []; + registerMessageCallback('removeVisits', this, undefined); }); }); }
diff --git a/chrome/test/data/webui/md_history/history_supervised_user_test.js b/chrome/test/data/webui/md_history/history_supervised_user_test.js index caa1abe..a39a39f 100644 --- a/chrome/test/data/webui/md_history/history_supervised_user_test.js +++ b/chrome/test/data/webui/md_history/history_supervised_user_test.js
@@ -3,20 +3,15 @@ // found in the LICENSE file. cr.define('md_history.history_supervised_user_test', function() { - // Array of test history data. - var TEST_HISTORY_RESULTS = [ - { - "dateRelativeDay": "Today - Wednesday, December 9, 2015", - "url": "https://www.google.com" - } - ]; - function registerTests() { suite('history-list supervised-user', function() { var element; + var TEST_HISTORY_RESULTS; suiteSetup(function() { element = $('history-list'); + TEST_HISTORY_RESULTS = + [createHistoryEntry('2016-03-15', 'https://www.google.com')]; }); setup(function() {
diff --git a/chrome/test/data/webui/md_history/history_toolbar_test.js b/chrome/test/data/webui/md_history/history_toolbar_test.js index 77a9a70..b43709f6 100644 --- a/chrome/test/data/webui/md_history/history_toolbar_test.js +++ b/chrome/test/data/webui/md_history/history_toolbar_test.js
@@ -3,23 +3,17 @@ // found in the LICENSE file. cr.define('md_history.history_toolbar_test', function() { - // Array of test history data. - var TEST_HISTORY_RESULTS = [ - { - "dateRelativeDay": "Today - Wednesday, December 9, 2015", - "title": "Google", - "url": "https://www.google.com" - } - ]; - function registerTests() { suite('history-toolbar', function() { var element; var toolbar; + var TEST_HISTORY_RESULTS; suiteSetup(function() { element = $('history-list'); toolbar = $('toolbar'); + TEST_HISTORY_RESULTS = + [createHistoryEntry('2016-03-15', 'https://google.com')]; }); test('selecting checkbox causes toolbar to change', function(done) { @@ -59,6 +53,7 @@ teardown(function() { element.historyData = []; + registerMessageCallback('queryHistory', this, undefined); toolbar.count = 0; }); });
diff --git a/chrome/test/data/webui/md_history/test_util.js b/chrome/test/data/webui/md_history/test_util.js index acb77f4..d0a3fc4 100644 --- a/chrome/test/data/webui/md_history/test_util.js +++ b/chrome/test/data/webui/md_history/test_util.js
@@ -10,3 +10,48 @@ Polymer.dom.flush(); window.setTimeout(callback, 0); } + +/** + * Create a fake history result with the given timestamp. + * @param {number|string} timestamp Timestamp of the entry, as a number in ms or + * a string which can be parsed by Date.parse(). + * @param {string} urlStr The URL to set on this entry. + * @return {!HistoryEntry} An object representing a history entry. + */ +function createHistoryEntry(timestamp, urlStr) { + if (typeof timestamp === 'string') + timestamp += ' UTC'; + + var d = new Date(timestamp); + var url = new URL(urlStr); + var domain = url.host; + return { + allTimestamps: [timestamp], + // Formatting the relative day is too hard, will instead display + // YYYY-MM-DD. + dateRelativeDay: d.toISOString().split('T')[0], + dateTimeOfDay: d.getUTCHours() + ':' + d.getUTCMinutes(), + domain: domain, + starred: false, + time: d.getTime(), + title: urlStr, + url: urlStr + }; +} + +/** + * Create a fake history search result with the given timestamp. Replaces fields + * from createHistoryEntry to look like a search result. + * @param {number|string} timestamp Timestamp of the entry, as a number in ms or + * a string which can be parsed by Date.parse(). + * @param {string} urlStr The URL to set on this entry. + * @return {!HistoryEntry} An object representing a history entry. + */ +function createSearchEntry(timestamp, urlStr) { + var entry = createHistoryEntry(timestamp, urlStr); + entry.dateShort = entry.dateRelativeDay; + entry.dateTimeOfDay = ''; + entry.dateRelativeDay = ''; + + return entry; +}
diff --git a/chrome/test/data/webui/media_router/media_router_elements_browsertest.js b/chrome/test/data/webui/media_router/media_router_elements_browsertest.js index 4ee903d..c2afb9d7 100644 --- a/chrome/test/data/webui/media_router/media_router_elements_browsertest.js +++ b/chrome/test/data/webui/media_router/media_router_elements_browsertest.js
@@ -73,16 +73,6 @@ // AX_ARIA_08: http://crbug.com/591552 this.accessibilityAuditConfig.ignoreSelectors( 'requiredOwnedAriaRoleMissing', requiredOwnedAriaRoleMissingSelectors); - - // Enable when warning is resolved. - // AX_FOCUS_01: http://crbug.com/591553 - this.accessibilityAuditConfig.ignoreSelectors( - 'focusableElementNotVisibleAndNotAriaHidden', '#device-missing > A'); - - // Enable when warning is resolved. - // AX_TEXT_04: http://crbug.com/591554 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', '#device-missing > A'); }, };
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index fc7c224..ae28f4f1 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -8062.0.0 \ No newline at end of file +8069.0.0 \ No newline at end of file
diff --git a/components/autofill/core/browser/autofill_merge_unittest.cc b/components/autofill/core/browser/autofill_merge_unittest.cc index d0c5a66f..61c58a8 100644 --- a/components/autofill/core/browser/autofill_merge_unittest.cc +++ b/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -208,6 +208,7 @@ field.name = field_type; field.value = value; field.form_control_type = "text"; + field.is_focusable = true; form.fields.push_back(field); } @@ -225,6 +226,7 @@ StringToFieldType(base::UTF16ToUTF8(field->name)); field->set_heuristic_type(type); } + form_structure.IdentifySections(false); // Import the profile. scoped_ptr<CreditCard> imported_credit_card;
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index ed9d228..c5774de5 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -652,6 +652,7 @@ cached_field->second->html_mode()); field->set_previously_autofilled( cached_field->second->previously_autofilled()); + field->set_section(cached_field->second->section()); } }
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index decf823..4309d1252 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -216,6 +216,7 @@ bool operator!=(const FormData& form) const; private: + friend class AutofillMergeTest; friend class FormStructureTest; FRIEND_TEST_ALL_PREFIXES(AutofillDownloadTest, QueryAndUploadTest); FRIEND_TEST_ALL_PREFIXES(FormStructureTest, FindLongestCommonPrefix);
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 67625af..c7ec6db 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -343,8 +343,9 @@ // |should_return_local_card|. bool cc_import = ImportCreditCard(form, should_return_local_card, imported_credit_card); - // - ImportAddressProfile may eventually save or update an address profile. - bool address_import = ImportAddressProfile(form); + // - ImportAddressProfiles may eventually save or update one or more address + // profiles. + bool address_import = ImportAddressProfiles(form); if (cc_import || address_import) return true; @@ -1228,7 +1229,35 @@ NotifyPersonalDataChanged(); } -bool PersonalDataManager::ImportAddressProfile(const FormStructure& form) { +bool PersonalDataManager::ImportAddressProfiles(const FormStructure& form) { + if (!form.field_count()) + return false; + + // Relevant sections for address fields. + std::set<std::string> sections; + for (const AutofillField* field : form) { + if (field->Type().group() != CREDIT_CARD) + sections.insert(field->section()); + } + + // We save a maximum of 2 profiles per submitted form (e.g. for shipping and + // billing). + static const size_t kMaxNumAddressProfilesSaved = 2; + size_t num_saved_profiles = 0; + for (const std::string& section : sections) { + if (num_saved_profiles == kMaxNumAddressProfilesSaved) + break; + + if (ImportAddressProfileForSection(form, section)) + num_saved_profiles++; + } + + return num_saved_profiles > 0; +} + +bool PersonalDataManager::ImportAddressProfileForSection( + const FormStructure& form, + const std::string& section) { // The candidate for profile import. There are many ways for the candidate to // be rejected (see everywhere this function returns false). AutofillProfile candidate_profile; @@ -1244,12 +1273,17 @@ // Go through each |form| field and attempt to constitute a valid profile. for (const AutofillField* field : form) { + // Reject fields that are not within the specified |section|. + if (field->section() != section) + continue; + base::string16 value; base::TrimWhitespace(field->value, base::TRIM_ALL, &value); // If we don't know the type of the field, or the user hasn't entered any - // information into the field, then skip it. - if (!field->IsFieldFillable() || value.empty()) + // information into the field, or the field is non-focusable (hidden), then + // skip it. + if (!field->IsFieldFillable() || !field->is_focusable || value.empty()) continue; AutofillType field_type = field->Type(); @@ -1323,8 +1357,9 @@ base::TrimWhitespace(field->value, base::TRIM_ALL, &value); // If we don't know the type of the field, or the user hasn't entered any - // information into the field, then skip it. - if (!field->IsFieldFillable() || value.empty()) + // information into the field, or the field is non-focusable (hidden), then + // skip it. + if (!field->IsFieldFillable() || !field->is_focusable || value.empty()) continue; AutofillType field_type = field->Type();
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 8d3c52e..d8b30bc 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -361,10 +361,16 @@ // Called when the value of prefs::kAutofillEnabled changes. void EnabledPrefChanged(); - // Go through the |form| fields and attempt to extract and import an address - // profile. Returns true on extraction success. There are many reasons that - // extraction may fail (see implementation). - bool ImportAddressProfile(const FormStructure& form); + // Go through the |form| fields and attempt to extract and import valid + // address profiles. Returns true on extraction success of at least one + // profile. There are many reasons that extraction may fail (see + // implementation). + bool ImportAddressProfiles(const FormStructure& form); + + // Helper method for ImportAddressProfiles which only considers the fields for + // a specified |section|. + bool ImportAddressProfileForSection(const FormStructure& form, + const std::string& section); // Go through the |form| fields and attempt to extract a new credit card in // |imported_credit_card|, or update an existing card.
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index 11f60fb..92f05376 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -262,8 +262,8 @@ // Helper methods that simply forward the call to the private member (to avoid // having to friend every test that needs to access the private // PersonalDataManager::ImportAddressProfile or ImportCreditCard). - bool ImportAddressProfile(const FormStructure& form) { - return personal_data_->ImportAddressProfile(form); + bool ImportAddressProfiles(const FormStructure& form) { + return personal_data_->ImportAddressProfiles(form); } bool ImportCreditCard(const FormStructure& form, bool should_return_local_card, @@ -959,9 +959,9 @@ EXPECT_EQ(profile0, *results[0]); } -// ImportAddressProfile tests. +// ImportAddressProfiles tests. -TEST_F(PersonalDataManagerTest, ImportAddressProfile) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles) { FormData form; FormFieldData field; test::CreateTestFormField( @@ -984,7 +984,7 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure)); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1000,7 +1000,7 @@ EXPECT_EQ(0, expected.Compare(*results[0])); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_BadEmail) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_BadEmail) { FormData form; FormFieldData field; test::CreateTestFormField( @@ -1022,14 +1022,14 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_FALSE(ImportAddressProfile(form_structure)); + EXPECT_FALSE(ImportAddressProfiles(form_structure)); const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles(); ASSERT_EQ(0U, results.size()); } // Tests that a 'confirm email' field does not block profile import. -TEST_F(PersonalDataManagerTest, ImportAddressProfile_TwoEmails) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoEmails) { FormData form; FormFieldData field; test::CreateTestFormField( @@ -1052,13 +1052,13 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure)); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles(); ASSERT_EQ(1U, results.size()); } // Tests two email fields containing different values blocks profile import. -TEST_F(PersonalDataManagerTest, ImportAddressProfile_TwoDifferentEmails) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoDifferentEmails) { FormData form; FormFieldData field; test::CreateTestFormField( @@ -1081,13 +1081,13 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_FALSE(ImportAddressProfile(form_structure)); + EXPECT_FALSE(ImportAddressProfiles(form_structure)); const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles(); ASSERT_EQ(0U, results.size()); } // Tests that not enough filled fields will result in not importing an address. -TEST_F(PersonalDataManagerTest, ImportAddressProfile_NotEnoughFilledFields) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_NotEnoughFilledFields) { FormData form; FormFieldData field; test::CreateTestFormField( @@ -1101,7 +1101,7 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_FALSE(ImportAddressProfile(form_structure)); + EXPECT_FALSE(ImportAddressProfiles(form_structure)); const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles(); ASSERT_EQ(0U, profiles.size()); @@ -1109,7 +1109,7 @@ ASSERT_EQ(0U, cards.size()); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_MinimumAddressUSA) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressUSA) { // United States addresses must specifiy one address line, a city, state and // zip code. FormData form; @@ -1129,12 +1129,12 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure)); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles(); ASSERT_EQ(1U, profiles.size()); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_MinimumAddressGB) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressGB) { // British addresses do not require a state/province as the county is usually // not requested on forms. FormData form; @@ -1154,12 +1154,12 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure)); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles(); ASSERT_EQ(1U, profiles.size()); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_MinimumAddressGI) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressGI) { // Gibraltar has the most minimal set of requirements for a valid address. // There are no cities or provinces and no postal/zip code system. FormData form; @@ -1174,13 +1174,13 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure)); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles(); ASSERT_EQ(1U, profiles.size()); } TEST_F(PersonalDataManagerTest, - ImportAddressProfile_PhoneNumberSplitAcrossMultipleFields) { + ImportAddressProfiles_PhoneNumberSplitAcrossMultipleFields) { FormData form; FormFieldData field; test::CreateTestFormField( @@ -1212,7 +1212,7 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure)); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1228,7 +1228,7 @@ EXPECT_EQ(0, expected.Compare(*results[0])); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_MultilineAddress) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MultilineAddress) { FormData form; FormFieldData field; test::CreateTestFormField( @@ -1256,7 +1256,7 @@ form.fields.push_back(field); FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure)); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1272,7 +1272,8 @@ EXPECT_EQ(0, expected.Compare(*results[0])); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_TwoValidProfiles) { +TEST_F(PersonalDataManagerTest, + ImportAddressProfiles_TwoValidProfilesDifferentForms) { FormData form1; FormFieldData field; test::CreateTestFormField( @@ -1296,7 +1297,7 @@ FormStructure form_structure1(form1); form_structure1.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure1)); + EXPECT_TRUE(ImportAddressProfiles(form_structure1)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1334,7 +1335,7 @@ FormStructure form_structure2(form2); form_structure2.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure2)); + EXPECT_TRUE(ImportAddressProfiles(form_structure2)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1351,7 +1352,239 @@ ExpectSameElements(profiles, personal_data_->GetProfiles()); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_SameProfileWithConflict) { +TEST_F(PersonalDataManagerTest, + ImportAddressProfiles_TwoValidProfilesSameForm) { + FormData form; + FormFieldData field; + test::CreateTestFormField("First name:", "first_name", "George", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Last name:", "last_name", "Washington", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("City:", "city", "San Francisco", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("State:", "state", "California", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Zip:", "zip", "94102", "text", &field); + form.fields.push_back(field); + + // Different address. + test::CreateTestFormField("First name:", "first_name", "John", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Last name:", "last_name", "Adams", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Email:", "email", "second@gmail.com", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Address:", "address1", "22 Laussat St", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("City:", "city", "San Francisco", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("State:", "state", "California", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Zip:", "zip", "94102", "text", &field); + form.fields.push_back(field); + + FormStructure form_structure(form); + form_structure.DetermineHeuristicTypes(); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); + + // Verify that the web database has been updated and the notification sent. + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .WillOnce(QuitMainMessageLoop()); + base::MessageLoop::current()->Run(); + + AutofillProfile expected(base::GenerateGUID(), "https://www.example.com"); + test::SetProfileInfo(&expected, "George", NULL, "Washington", + "theprez@gmail.com", NULL, "21 Laussat St", NULL, + "San Francisco", "California", "94102", NULL, NULL); + AutofillProfile expected2(base::GenerateGUID(), "https://www.example.com"); + test::SetProfileInfo(&expected2, "John", NULL, "Adams", "second@gmail.com", + NULL, "22 Laussat St", NULL, "San Francisco", + "California", "94102", NULL, NULL); + + const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles(); + ASSERT_EQ(2U, results.size()); + + std::vector<AutofillProfile*> profiles; + profiles.push_back(&expected); + profiles.push_back(&expected2); + ExpectSameElements(profiles, personal_data_->GetProfiles()); +} + +TEST_F(PersonalDataManagerTest, + ImportAddressProfiles_OneValidProfileSameForm_PartsHidden) { + FormData form; + FormFieldData field; + test::CreateTestFormField("First name:", "first_name", "George", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Last name:", "last_name", "Washington", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("City:", "city", "San Francisco", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("State:", "state", "California", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Zip:", "zip", "94102", "text", &field); + form.fields.push_back(field); + + // There is an empty but hidden form section (this has been observed on sites + // where users can choose which form section they choose by unhiding it). + test::CreateTestFormField("First name:", "first_name", "", "text", + &field); + field.is_focusable = false; + form.fields.push_back(field); + test::CreateTestFormField("Last name:", "last_name", "", "text", &field); + field.is_focusable = false; + form.fields.push_back(field); + test::CreateTestFormField("Email:", "email", "", "text", + &field); + field.is_focusable = false; + form.fields.push_back(field); + test::CreateTestFormField("Address:", "address1", "", "text", + &field); + field.is_focusable = false; + form.fields.push_back(field); + test::CreateTestFormField("City:", "city", "", "text", &field); + field.is_focusable = false; + form.fields.push_back(field); + test::CreateTestFormField("State:", "state", "", "text", &field); + field.is_focusable = false; + form.fields.push_back(field); + test::CreateTestFormField("Zip:", "zip", "", "text", &field); + field.is_focusable = false; + form.fields.push_back(field); + + // Still able to do the import. + FormStructure form_structure(form); + form_structure.DetermineHeuristicTypes(); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); + + // Verify that the web database has been updated and the notification sent. + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .WillOnce(QuitMainMessageLoop()); + base::MessageLoop::current()->Run(); + + AutofillProfile expected(base::GenerateGUID(), "https://www.example.com"); + test::SetProfileInfo(&expected, "George", NULL, "Washington", + "theprez@gmail.com", NULL, "21 Laussat St", NULL, + "San Francisco", "California", "94102", NULL, NULL); + + const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles(); + ASSERT_EQ(1U, results.size()); + + std::vector<AutofillProfile*> profiles; + profiles.push_back(&expected); + ExpectSameElements(profiles, personal_data_->GetProfiles()); +} + +// A maximum of two address profiles are imported per form. +TEST_F(PersonalDataManagerTest, + ImportAddressProfiles_ThreeValidProfilesSameForm) { + FormData form; + FormFieldData field; + test::CreateTestFormField("First name:", "first_name", "George", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Last name:", "last_name", "Washington", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("City:", "city", "San Francisco", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("State:", "state", "California", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Zip:", "zip", "94102", "text", &field); + form.fields.push_back(field); + + // Different address within the same form. + test::CreateTestFormField("First name:", "first_name", "John", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Last name:", "last_name", "Adams", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Email:", "email", "second@gmail.com", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Address:", "address1", "22 Laussat St", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("City:", "city", "San Francisco", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("State:", "state", "California", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Zip:", "zip", "94102", "text", &field); + form.fields.push_back(field); + + // Yet another different address. + test::CreateTestFormField("First name:", "first_name", "David", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Last name:", "last_name", "Cameron", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Address:", "address", "10 Downing Street", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("City:", "city", "London", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Postcode:", "postcode", "SW1A 2AA", "text", + &field); + form.fields.push_back(field); + test::CreateTestFormField("Country:", "country", "United Kingdom", "text", + &field); + form.fields.push_back(field); + + FormStructure form_structure(form); + form_structure.DetermineHeuristicTypes(); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); + + // Verify that the web database has been updated and the notification sent. + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .WillOnce(QuitMainMessageLoop()); + base::MessageLoop::current()->Run(); + + // Only two are saved. + AutofillProfile expected(base::GenerateGUID(), "https://www.example.com"); + test::SetProfileInfo(&expected, "George", NULL, "Washington", + "theprez@gmail.com", NULL, "21 Laussat St", NULL, + "San Francisco", "California", "94102", NULL, NULL); + AutofillProfile expected2(base::GenerateGUID(), "https://www.example.com"); + test::SetProfileInfo(&expected2, "John", NULL, "Adams", "second@gmail.com", + NULL, "22 Laussat St", NULL, "San Francisco", + "California", "94102", NULL, NULL); + + const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles(); + ASSERT_EQ(2U, results.size()); + + std::vector<AutofillProfile*> profiles; + profiles.push_back(&expected); + profiles.push_back(&expected2); + ExpectSameElements(profiles, personal_data_->GetProfiles()); +} + +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_SameProfileWithConflict) { FormData form1; FormFieldData field; test::CreateTestFormField( @@ -1380,7 +1613,7 @@ FormStructure form_structure1(form1); form_structure1.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure1)); + EXPECT_TRUE(ImportAddressProfiles(form_structure1)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1428,7 +1661,7 @@ FormStructure form_structure2(form2); form_structure2.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure2)); + EXPECT_TRUE(ImportAddressProfiles(form_structure2)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1444,7 +1677,7 @@ EXPECT_EQ(0, expected.Compare(*results2[0])); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_MissingInfoInOld) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInOld) { FormData form1; FormFieldData field; test::CreateTestFormField( @@ -1465,7 +1698,7 @@ FormStructure form_structure1(form1); form_structure1.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure1)); + EXPECT_TRUE(ImportAddressProfiles(form_structure1)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1503,7 +1736,7 @@ FormStructure form_structure2(form2); form_structure2.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure2)); + EXPECT_TRUE(ImportAddressProfiles(form_structure2)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1520,7 +1753,7 @@ EXPECT_EQ(0, expected2.Compare(*results2[0])); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_MissingInfoInNew) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInNew) { FormData form1; FormFieldData field; test::CreateTestFormField( @@ -1547,7 +1780,7 @@ FormStructure form_structure1(form1); form_structure1.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure1)); + EXPECT_TRUE(ImportAddressProfiles(form_structure1)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1586,7 +1819,7 @@ FormStructure form_structure2(form2); form_structure2.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure2)); + EXPECT_TRUE(ImportAddressProfiles(form_structure2)); // Verify that the web database has been updated and the notification sent. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1600,7 +1833,7 @@ EXPECT_EQ(0, expected.Compare(*results2[0])); } -TEST_F(PersonalDataManagerTest, ImportAddressProfile_InsufficientAddress) { +TEST_F(PersonalDataManagerTest, ImportAddressProfiles_InsufficientAddress) { FormData form1; FormFieldData field; test::CreateTestFormField( @@ -1623,7 +1856,7 @@ FormStructure form_structure1(form1); form_structure1.DetermineHeuristicTypes(); - EXPECT_FALSE(ImportAddressProfile(form_structure1)); + EXPECT_FALSE(ImportAddressProfiles(form_structure1)); // Since no refresh is expected, reload the data from the database to make // sure no changes were written out. @@ -1640,7 +1873,7 @@ // works: if either the full name OR all the non-empty name pieces match, the // profile is a match. TEST_F(PersonalDataManagerTest, - ImportAddressProfile_ExistingVerifiedProfileWithConflict) { + ImportAddressProfiles_ExistingVerifiedProfileWithConflict) { // Start with a verified profile. AutofillProfile profile(base::GenerateGUID(), "Chrome settings"); test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison", @@ -1680,7 +1913,7 @@ FormStructure form_structure(form); form_structure.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure)); + EXPECT_TRUE(ImportAddressProfiles(form_structure)); // Wait for the refresh, which in this case is a no-op. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -1701,7 +1934,7 @@ FormStructure form_structure2(form); form_structure2.DetermineHeuristicTypes(); - EXPECT_TRUE(ImportAddressProfile(form_structure2)); + EXPECT_TRUE(ImportAddressProfiles(form_structure2)); // Wait for the refresh, which in this case is a no-op. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) @@ -2387,8 +2620,8 @@ .WillOnce(QuitMainMessageLoop()); base::MessageLoop::current()->Run(); - // Test that the address has NOT been saved. - EXPECT_TRUE(personal_data_->GetProfiles().empty()); + // Test that both addresses have been saved. + EXPECT_EQ(2U, personal_data_->GetProfiles().size()); // Test that the credit card has been saved. CreditCard expected_card(base::GenerateGUID(), "https://www.example.com");
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h index 44f45280..093c6ab 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
@@ -78,10 +78,6 @@ // requests and responses. const char* chrome_proxy_lo_fi_preview_directive(); -// Gets the Chrome-Proxy directive used by data reduction proxy Lo-Fi control -// experiment requests. -const char* chrome_proxy_lo_fi_experiment_directive(); - // Returns true if the Chrome-Proxy header is present and contains a bypass // delay. Sets |proxy_info->bypass_duration| to the specified delay if greater // than 0, and to 0 otherwise to indicate that the default proxy delay
diff --git a/components/metrics/file_metrics_provider.cc b/components/metrics/file_metrics_provider.cc index 7fad01c..fcfb7acf 100644 --- a/components/metrics/file_metrics_provider.cc +++ b/components/metrics/file_metrics_provider.cc
@@ -11,7 +11,7 @@ #include "base/logging.h" #include "base/metrics/histogram_base.h" #include "base/metrics/histogram_macros.h" -#include "base/metrics/histogram_persistence.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/metrics/persistent_memory_allocator.h" #include "base/task_runner.h" #include "base/time/time.h" @@ -47,7 +47,7 @@ // "active", it remains mapped and nothing is copied to local memory. std::vector<uint8_t> data; scoped_ptr<base::MemoryMappedFile> mapped; - scoped_ptr<base::PersistentMemoryAllocator> allocator; + scoped_ptr<base::PersistentHistogramAllocator> allocator; private: DISALLOW_COPY_AND_ASSIGN(FileInfo); @@ -174,13 +174,13 @@ base::HistogramSnapshotManager* snapshot_manager, FileInfo* file) { DCHECK(thread_checker_.CalledOnValidThread()); - base::PersistentMemoryAllocator::Iterator hist_iter; - file->allocator->CreateIterator(&hist_iter); + base::PersistentHistogramAllocator::Iterator histogram_iter; + file->allocator->CreateIterator(&histogram_iter); int histogram_count = 0; while (true) { - scoped_ptr<base::HistogramBase> histogram( - base::GetNextPersistentHistogram(file->allocator.get(), &hist_iter)); + scoped_ptr<base::HistogramBase> histogram = + file->allocator->GetNextHistogram(&histogram_iter); if (!histogram) break; if (file->type == FILE_HISTOGRAMS_ATOMIC) @@ -204,12 +204,14 @@ if (file->mapped) { DCHECK(file->data.empty()); // TODO(bcwhite): Make this do read/write when supported for "active". - file->allocator.reset(new base::FilePersistentMemoryAllocator( - std::move(file->mapped), 0, std::string())); + file->allocator.reset(new base::PersistentHistogramAllocator( + make_scoped_ptr(new base::FilePersistentMemoryAllocator( + std::move(file->mapped), 0, "")))); } else { DCHECK(!file->mapped); - file->allocator.reset(new base::PersistentMemoryAllocator( - &file->data[0], file->data.size(), 0, 0, "", true)); + file->allocator.reset(new base::PersistentHistogramAllocator( + make_scoped_ptr(new base::PersistentMemoryAllocator( + &file->data[0], file->data.size(), 0, 0, "", true)))); } }
diff --git a/components/metrics/file_metrics_provider_unittest.cc b/components/metrics/file_metrics_provider_unittest.cc index 3bffb1c..425777f 100644 --- a/components/metrics/file_metrics_provider_unittest.cc +++ b/components/metrics/file_metrics_provider_unittest.cc
@@ -9,8 +9,8 @@ #include "base/files/scoped_temp_dir.h" #include "base/metrics/histogram.h" #include "base/metrics/histogram_flattener.h" -#include "base/metrics/histogram_persistence.h" #include "base/metrics/histogram_snapshot_manager.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/metrics/persistent_memory_allocator.h" #include "base/metrics/statistics_recorder.h" #include "base/test/test_simple_task_runner.h" @@ -103,10 +103,10 @@ { // Get this first so it isn't created inside the persistent allocator. - base::GetCreateHistogramResultHistogram(); + base::PersistentHistogramAllocator::GetCreateHistogramResultHistogram(); - base::SetPersistentHistogramMemoryAllocator( - new base::LocalPersistentMemoryAllocator(64 << 10, 0, kMetricsName)); + base::PersistentHistogramAllocator::CreateGlobalAllocatorOnLocalMemory( + 64 << 10, 0, kMetricsName); base::HistogramBase* foo = base::Histogram::FactoryGet("foo", 1, 100, 10, 0); base::HistogramBase* bar = @@ -114,8 +114,10 @@ foo->Add(42); bar->Add(84); - scoped_ptr<base::PersistentMemoryAllocator> allocator( - base::ReleasePersistentHistogramMemoryAllocatorForTesting()); + scoped_ptr<base::PersistentHistogramAllocator> histogram_allocator = + base::PersistentHistogramAllocator::ReleaseGlobalAllocatorForTesting(); + base::PersistentMemoryAllocator* allocator = + histogram_allocator->memory_allocator(); base::File writer(metrics_file(), base::File::FLAG_CREATE | base::File::FLAG_WRITE); ASSERT_TRUE(writer.IsValid());
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc index d17911a0..c3ef7ec 100644 --- a/components/metrics/metrics_service.cc +++ b/components/metrics/metrics_service.cc
@@ -133,8 +133,8 @@ #include "base/location.h" #include "base/metrics/histogram_base.h" #include "base/metrics/histogram_macros.h" -#include "base/metrics/histogram_persistence.h" #include "base/metrics/histogram_samples.h" +#include "base/metrics/persistent_histogram_allocator.h" #include "base/metrics/sparse_histogram.h" #include "base/metrics/statistics_recorder.h" #include "base/rand_util.h" @@ -746,8 +746,8 @@ // If a persistent allocator is in use, update its internal histograms (such // as how much memory is being used) before reporting. - base::PersistentMemoryAllocator* allocator = - base::GetPersistentHistogramMemoryAllocator(); + base::PersistentHistogramAllocator* allocator = + base::PersistentHistogramAllocator::GetGlobalAllocator(); if (allocator) allocator->UpdateTrackingHistograms();
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 79f2c78..9fe2d47 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -710,6 +710,7 @@ if (active_version->running_status() != ServiceWorkerVersion::RUNNING) { active_version->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::SYNC, base::Bind(&BackgroundSyncManager::DispatchSyncEvent, weak_ptr_factory_.GetWeakPtr(), tag, active_version, last_chance, callback),
diff --git a/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm b/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm index a7e99a2b..3e9886b 100644 --- a/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm +++ b/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm
@@ -6,8 +6,10 @@ #include <stddef.h> +#include "base/command_line.h" #include "content/browser/gpu/gpu_data_manager_impl.h" #include "gpu/config/gpu_driver_bug_workaround_type.h" +#include "ui/base/ui_base_switches.h" namespace content { @@ -30,7 +32,11 @@ } bool BrowserCompositorOverlayCandidateValidatorMac::AllowCALayerOverlays() { - if (software_mirror_active_ || ca_layers_disabled_) + static bool overlays_disabled_at_command_line = + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableMacOverlays); + if (software_mirror_active_ || ca_layers_disabled_ || + overlays_disabled_at_command_line) return false; return true; }
diff --git a/content/browser/geofencing/geofencing_manager.cc b/content/browser/geofencing/geofencing_manager.cc index 242b588..e420d5f 100644 --- a/content/browser/geofencing/geofencing_manager.cc +++ b/content/browser/geofencing/geofencing_manager.cc
@@ -395,6 +395,7 @@ // until the callback dies. Otherwise the registration could be released when // this method returns - before the event is delivered to the service worker. active_version->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::GEOFENCING, base::Bind(&GeofencingManager::DeliverEventToRunningWorker, this, service_worker_registration, event_type, registration->region_id, registration->region,
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index dbc3da5..0472eb6 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -132,7 +132,6 @@ switches::kVModule, #if defined(OS_MACOSX) switches::kDisableRemoteCoreAnimation, - switches::kDisableMacOverlays, switches::kEnableSandboxLogging, switches::kShowMacOverlayBorders, #endif
diff --git a/content/browser/navigator_connect/navigator_connect_context_impl.cc b/content/browser/navigator_connect/navigator_connect_context_impl.cc index 5aaeba1..e943aba7 100644 --- a/content/browser/navigator_connect/navigator_connect_context_impl.cc +++ b/content/browser/navigator_connect/navigator_connect_context_impl.cc
@@ -5,6 +5,7 @@ #include "content/browser/navigator_connect/navigator_connect_context_impl.h" #include <stdint.h> +#include <vector> #include "base/stl_util.h" #include "content/browser/message_port_service.h" @@ -154,6 +155,7 @@ registration->pattern().GetOrigin(); active_version->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::SERVICE_PORT_CONNECT, base::Bind(&NavigatorConnectContextImpl::DispatchConnectEvent, this, callback, client_port_id, service_port_id, registration, make_scoped_refptr(active_version)),
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc index ca125fa5..e19a1f81 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.cc +++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -228,6 +228,7 @@ ServiceWorkerVersion::StatusCallback status_callback = base::Bind( &ServiceWorkerNotificationEventFinished, dispatch_complete_callback); service_worker_registration->active_version()->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK, base::Bind( &DispatchNotificationClickEventOnWorker, make_scoped_refptr(service_worker_registration->active_version()), @@ -299,6 +300,7 @@ dispatch_complete_callback); if (by_user) { service_worker_registration->active_version()->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::NOTIFICATION_CLOSE, base::Bind( &DispatchNotificationCloseEventOnWorker, make_scoped_refptr(service_worker_registration->active_version()),
diff --git a/content/browser/push_messaging/push_messaging_router.cc b/content/browser/push_messaging/push_messaging_router.cc index 7bc469b..dce24a9 100644 --- a/content/browser/push_messaging/push_messaging_router.cc +++ b/content/browser/push_messaging/push_messaging_router.cc
@@ -91,6 +91,7 @@ // released when this method returns - before the event is delivered to the // service worker. version->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::PUSH, base::Bind(&PushMessagingRouter::DeliverMessageToWorker, make_scoped_refptr(version), service_worker_registration, payload, deliver_message_callback),
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 65ed654..3f15cf30 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -128,7 +128,11 @@ void onContextLost() override; GLHelper* GetGLHelper() { return gl_helper_.get(); } - bool IsLost() { return !context_.get() || context_->isContextLost(); } + bool IsLost() { + return !context_ || + context_->GetGLInterface()->GetGraphicsResetStatusKHR() != + GL_NO_ERROR; + } private: GLHelperHolder();
diff --git a/content/browser/service_worker/foreign_fetch_request_handler.cc b/content/browser/service_worker/foreign_fetch_request_handler.cc index b4cce4a..be692ce 100644 --- a/content/browser/service_worker/foreign_fetch_request_handler.cc +++ b/content/browser/service_worker/foreign_fetch_request_handler.cc
@@ -4,6 +4,8 @@ #include "content/browser/service_worker/foreign_fetch_request_handler.h" +#include <string> + #include "base/macros.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_url_request_job.h" @@ -120,8 +122,8 @@ ServiceWorkerURLRequestJob* job = new ServiceWorkerURLRequestJob( request, network_delegate, std::string(), blob_storage_context_, - resource_context, request_mode_, credentials_mode_, redirect_mode_, false, - request_context_type_, frame_type_, body_, + resource_context, request_mode_, credentials_mode_, redirect_mode_, + resource_type_, request_context_type_, frame_type_, body_, ServiceWorkerFetchType::FOREIGN_FETCH, this); job_ = job->GetWeakPtr();
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index dda9572..58862d6b 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -41,6 +41,7 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "content/public/common/referrer.h" +#include "content/public/common/resource_type.h" #include "content/public/common/security_style.h" #include "content/public/common/ssl_status.h" #include "content/public/common/web_preferences.h" @@ -226,7 +227,7 @@ // an experiration far in the future. class LongLivedResourceInterceptor : public net::URLRequestInterceptor { public: - LongLivedResourceInterceptor(const std::string& body) + explicit LongLivedResourceInterceptor(const std::string& body) : body_(body) {} ~LongLivedResourceInterceptor() override {} @@ -592,7 +593,8 @@ void StartOnIOThread(const base::Closure& done, ServiceWorkerStatusCode* result) { ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); - version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiver(BrowserThread::UI, done, result)); } void InstallOnIOThread(const base::Closure& done, @@ -600,6 +602,7 @@ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); version_->SetStatus(ServiceWorkerVersion::INSTALLING); version_->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::INSTALL, base::Bind(&self::DispatchInstallEventOnIOThread, this, done, result), CreateReceiver(BrowserThread::UI, done, result)); } @@ -631,6 +634,7 @@ version_->SetStatus(ServiceWorkerVersion::ACTIVATING); registration_->SetActiveVersion(version_.get()); version_->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::ACTIVATE, base::Bind(&self::DispatchActivateEventOnIOThread, this, done, result), CreateReceiver(BrowserThread::UI, done, result)); } @@ -654,7 +658,7 @@ ServiceWorkerHeaderMap(), Referrer(), false)); version_->SetStatus(ServiceWorkerVersion::ACTIVATED); fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( - std::move(request), version_.get(), + std::move(request), version_.get(), RESOURCE_TYPE_MAIN_FRAME, CreatePrepareReceiver(prepare_result), CreateResponseReceiver(done, blob_context_.get(), result))); fetch_dispatcher_->Run(); @@ -877,7 +881,7 @@ class WaitForLoaded : public EmbeddedWorkerInstance::Listener { public: - WaitForLoaded(const base::Closure& quit) : quit_(quit) {} + explicit WaitForLoaded(const base::Closure& quit) : quit_(quit) {} void OnThreadStarted() override { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_);
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index 770a78a..cba52e97 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -62,6 +62,7 @@ // it from being deleted while starting the worker. If the refcount of // |registration| is 1, it will be deleted after WorkerStarted is called. registration->active_version()->StartWorker( + ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(WorkerStarted, callback)); return; }
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc index 4dd83758..c6089fc5 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -103,8 +103,8 @@ scoped_ptr<ServiceWorkerURLRequestJob> job(new ServiceWorkerURLRequestJob( request, network_delegate, provider_host_->client_uuid(), blob_storage_context_, resource_context, request_mode_, credentials_mode_, - redirect_mode_, is_main_resource_load_, request_context_type_, - frame_type_, body_, ServiceWorkerFetchType::FETCH, this)); + redirect_mode_, resource_type_, request_context_type_, frame_type_, body_, + ServiceWorkerFetchType::FETCH, this)); job_ = job->GetWeakPtr(); resource_context_ = resource_context;
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index 4dd4cb34..d75ab4a 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -878,6 +878,7 @@ return; } worker->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::MESSAGE, base::Bind(&ServiceWorkerDispatcherHost:: DispatchExtendableMessageEventAfterStartWorker, this, worker, message, source_origin, sent_message_ports,
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc index 84e1b6e..9bce9ae 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -565,7 +565,8 @@ // Start up the worker. status = SERVICE_WORKER_ERROR_ABORT; - version->StartWorker(base::Bind(&SaveStatusCallback, &called, &status)); + version->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + base::Bind(&SaveStatusCallback, &called, &status)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(called);
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc index 2d7712b..d8091b8 100644 --- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc +++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -13,15 +13,37 @@ namespace content { +namespace { +using EventType = ServiceWorkerMetrics::EventType; +EventType ResourceTypeToEventType(ResourceType resource_type) { + switch (resource_type) { + case RESOURCE_TYPE_MAIN_FRAME: + return EventType::FETCH_MAIN_FRAME; + case RESOURCE_TYPE_SUB_FRAME: + return EventType::FETCH_SUB_FRAME; + case RESOURCE_TYPE_SHARED_WORKER: + return EventType::FETCH_SHARED_WORKER; + case RESOURCE_TYPE_SERVICE_WORKER: + case RESOURCE_TYPE_LAST_TYPE: + NOTREACHED() << resource_type; + return EventType::FETCH_SUB_RESOURCE; + default: + return EventType::FETCH_SUB_RESOURCE; + } +} +} // namespace + ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher( scoped_ptr<ServiceWorkerFetchRequest> request, ServiceWorkerVersion* version, + ResourceType resource_type, const base::Closure& prepare_callback, const FetchCallback& fetch_callback) : version_(version), prepare_callback_(prepare_callback), fetch_callback_(fetch_callback), request_(std::move(request)), + resource_type_(resource_type), weak_factory_(this) {} ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {} @@ -47,6 +69,7 @@ return; } version_->RunAfterStartWorker( + ResourceTypeToEventType(resource_type_), base::Bind(&ServiceWorkerFetchDispatcher::DispatchFetchEvent, weak_factory_.GetWeakPtr()), base::Bind(&ServiceWorkerFetchDispatcher::DidFail,
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h index a9af908a..efc3d29 100644 --- a/content/browser/service_worker/service_worker_fetch_dispatcher.h +++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -11,6 +11,7 @@ #include "content/common/content_export.h" #include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_types.h" +#include "content/public/common/resource_type.h" namespace content { @@ -27,6 +28,7 @@ ServiceWorkerFetchDispatcher(scoped_ptr<ServiceWorkerFetchRequest> request, ServiceWorkerVersion* version, + ResourceType resource_type, const base::Closure& prepare_callback, const FetchCallback& fetch_callback); ~ServiceWorkerFetchDispatcher(); @@ -49,6 +51,7 @@ base::Closure prepare_callback_; FetchCallback fetch_callback_; scoped_ptr<ServiceWorkerFetchRequest> request_; + ResourceType resource_type_; base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFetchDispatcher);
diff --git a/content/browser/service_worker/service_worker_handle_unittest.cc b/content/browser/service_worker/service_worker_handle_unittest.cc index 18f89fd..ae15a98e 100644 --- a/content/browser/service_worker/service_worker_handle_unittest.cc +++ b/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <vector> + #include "base/macros.h" #include "base/run_loop.h" #include "content/browser/service_worker/embedded_worker_registry.h" @@ -142,7 +144,8 @@ // Start the worker, and then... ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status);
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc index 0cbe471..f1175b2 100644 --- a/content/browser/service_worker/service_worker_job_unittest.cc +++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -643,7 +643,8 @@ scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion( registration.get(), script_url, 1L, helper_->context()->AsWeakPtr()); ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version->StartWorker(CreateReceiverOnCurrentThread(&status)); + version->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); ASSERT_EQ(SERVICE_WORKER_OK, status); @@ -1420,7 +1421,8 @@ void set_activate_event_result(blink::WebServiceWorkerEventResult result) { activate_event_result_ = result; } -private: + + private: base::Closure install_callback_; blink::WebServiceWorkerEventResult install_event_result_; blink::WebServiceWorkerEventResult activate_event_result_;
diff --git a/content/browser/service_worker/service_worker_metrics.cc b/content/browser/service_worker/service_worker_metrics.cc index 3d0967b..2ee60c7d 100644 --- a/content/browser/service_worker/service_worker_metrics.cc +++ b/content/browser/service_worker/service_worker_metrics.cc
@@ -68,11 +68,21 @@ return "Service Port Connect"; case EventType::MESSAGE: return "Message"; + case EventType::FETCH_MAIN_FRAME: + return "Fetch Main Frame"; + case EventType::FETCH_SUB_FRAME: + return "Fetch Sub Frame"; + case EventType::FETCH_SHARED_WORKER: + return "Fetch Shared Worker"; + case EventType::FETCH_SUB_RESOURCE: + return "Fetch Subresource"; + case EventType::UNKNOWN: + return "Unknown"; case EventType::NUM_TYPES: break; } NOTREACHED() << "Got unexpected event type: " << static_cast<int>(event_type); - return "Unknown"; + return "error"; } bool ServiceWorkerMetrics::ShouldExcludeSiteFromHistogram(Site site) { @@ -147,10 +157,19 @@ void ServiceWorkerMetrics::RecordStartWorkerStatus( ServiceWorkerStatusCode status, + EventType purpose, bool is_installed) { if (is_installed) { UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status, SERVICE_WORKER_ERROR_MAX_VALUE); + UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose", + static_cast<int>(purpose), + static_cast<int>(EventType::NUM_TYPES)); + if (status == SERVICE_WORKER_ERROR_TIMEOUT) { + UMA_HISTOGRAM_ENUMERATION( + "ServiceWorker.StartWorker.Timeout.StartPurpose", + static_cast<int>(purpose), static_cast<int>(EventType::NUM_TYPES)); + } } else { UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartNewWorker.Status", status, SERVICE_WORKER_ERROR_MAX_VALUE); @@ -222,6 +241,10 @@ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.InstallEvent.Time", time); break; case EventType::FETCH: + case EventType::FETCH_MAIN_FRAME: + case EventType::FETCH_SUB_FRAME: + case EventType::FETCH_SHARED_WORKER: + case EventType::FETCH_SUB_RESOURCE: if (was_handled) { UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.FetchEvent.HasResponse.Time", time); @@ -255,6 +278,7 @@ case EventType::SERVICE_PORT_CONNECT: break; + case EventType::UNKNOWN: case EventType::NUM_TYPES: NOTREACHED() << "Invalid event type"; break;
diff --git a/content/browser/service_worker/service_worker_metrics.h b/content/browser/service_worker/service_worker_metrics.h index 6e4e3a4..6ad0663 100644 --- a/content/browser/service_worker/service_worker_metrics.h +++ b/content/browser/service_worker/service_worker_metrics.h
@@ -76,7 +76,7 @@ enum class EventType { ACTIVATE, INSTALL, - FETCH, + FETCH, // Deprecated, use a more specific FETCH_ type. SYNC, NOTIFICATION_CLICK, PUSH, @@ -84,8 +84,12 @@ SERVICE_PORT_CONNECT, MESSAGE, NOTIFICATION_CLOSE, + FETCH_MAIN_FRAME, + FETCH_SUB_FRAME, + FETCH_SHARED_WORKER, + FETCH_SUB_RESOURCE, + UNKNOWN, // Used when event type is not known. // Add new events to record here. - NUM_TYPES }; @@ -122,6 +126,7 @@ // Records the result of trying to start a worker. |is_installed| indicates // whether the version has been installed. static void RecordStartWorkerStatus(ServiceWorkerStatusCode status, + EventType purpose, bool is_installed); // Records the time taken to successfully start a worker. |is_installed|
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc index ae7b436b..6f0155a 100644 --- a/content/browser/service_worker/service_worker_register_job.cc +++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -351,6 +351,7 @@ new_version()->set_pause_after_download(false); } new_version()->StartWorker( + ServiceWorkerMetrics::EventType::INSTALL, base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, weak_factory_.GetWeakPtr())); } @@ -414,6 +415,7 @@ // "Fire an event named install..." new_version()->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::INSTALL, base::Bind(&ServiceWorkerRegisterJob::DispatchInstallEvent, weak_factory_.GetWeakPtr()), base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc index e1e6e5d..d24c8c93 100644 --- a/content/browser/service_worker/service_worker_registration.cc +++ b/content/browser/service_worker/service_worker_registration.cc
@@ -287,6 +287,7 @@ // "10. Queue a task to fire an event named activate..." activating_version->RunAfterStartWorker( + ServiceWorkerMetrics::EventType::ACTIVATE, base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this, activating_version), base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this,
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc index 092d72db..9afccc134 100644 --- a/content/browser/service_worker/service_worker_url_request_job.cc +++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -28,6 +28,7 @@ #include "content/browser/streams/stream_registry.h" #include "content/common/resource_request_body.h" #include "content/common/service_worker/service_worker_types.h" +#include "content/common/service_worker/service_worker_utils.h" #include "content/public/browser/blob_handle.h" #include "content/public/browser/resource_request_info.h" #include "content/public/browser/service_worker_context.h" @@ -115,7 +116,7 @@ FetchRequestMode request_mode, FetchCredentialsMode credentials_mode, FetchRedirectMode redirect_mode, - bool is_main_resource_load, + ResourceType resource_type, RequestContextType request_context_type, RequestContextFrameType frame_type, scoped_refptr<ResourceRequestBody> body, @@ -133,7 +134,7 @@ request_mode_(request_mode), credentials_mode_(credentials_mode), redirect_mode_(redirect_mode), - is_main_resource_load_(is_main_resource_load), + resource_type_(resource_type), request_context_type_(request_context_type), frame_type_(frame_type), fall_back_required_(false), @@ -432,7 +433,7 @@ // Send a fetch event to the ServiceWorker associated to the // provider_host. fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( - CreateFetchRequest(), active_worker, + CreateFetchRequest(), active_worker, resource_type_, base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent, weak_factory_.GetWeakPtr()), base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent, @@ -455,7 +456,7 @@ scoped_ptr<ServiceWorkerFetchRequest> request( new ServiceWorkerFetchRequest()); request->mode = request_mode_; - request->is_main_resource_load = is_main_resource_load_; + request->is_main_resource_load = IsMainResourceLoad(); request->request_context_type = request_context_type_; request->frame_type = frame_type_; request->url = request_->url(); @@ -570,7 +571,7 @@ const ServiceWorkerResponse& response, const scoped_refptr<ServiceWorkerVersion>& version) { fetch_dispatcher_.reset(); - ServiceWorkerMetrics::RecordFetchEventStatus(is_main_resource_load_, status); + ServiceWorkerMetrics::RecordFetchEventStatus(IsMainResourceLoad(), status); // Check if we're not orphaned. if (!request()) { @@ -588,7 +589,7 @@ if (status != SERVICE_WORKER_OK) { RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_FETCH_EVENT_DISPATCH); - if (is_main_resource_load_) { + if (IsMainResourceLoad()) { // Using the service worker failed, so fallback to network. delegate_->MainResourceLoadFailed(); response_type_ = FALLBACK_TO_NETWORK; @@ -770,8 +771,7 @@ return; } did_record_result_ = true; - ServiceWorkerMetrics::RecordURLRequestJobResult(is_main_resource_load_, - result); + ServiceWorkerMetrics::RecordURLRequestJobResult(IsMainResourceLoad(), result); if (request()) request()->net_log().AddEvent(RequestJobResultToNetEventType(result)); } @@ -785,7 +785,7 @@ return; } RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_RESPONSE_STATUS_ZERO); - ServiceWorkerMetrics::RecordStatusZeroResponseError(is_main_resource_load_, + ServiceWorkerMetrics::RecordStatusZeroResponseError(IsMainResourceLoad(), error); } @@ -840,4 +840,8 @@ worker_ready_time_); } +bool ServiceWorkerURLRequestJob::IsMainResourceLoad() const { + return ServiceWorkerUtils::IsMainResourceType(resource_type_); +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_url_request_job.h b/content/browser/service_worker/service_worker_url_request_job.h index a3620dd..ae331bde 100644 --- a/content/browser/service_worker/service_worker_url_request_job.h +++ b/content/browser/service_worker/service_worker_url_request_job.h
@@ -103,7 +103,7 @@ FetchRequestMode request_mode, FetchCredentialsMode credentials_mode, FetchRedirectMode redirect_mode, - bool is_main_resource_load, + ResourceType resource_type, RequestContextType request_context_type, RequestContextFrameType frame_type, scoped_refptr<ResourceRequestBody> body, @@ -227,6 +227,8 @@ // calls it. void OnStartCompleted() const; + bool IsMainResourceLoad() const; + // Not owned. Delegate* delegate_; @@ -261,7 +263,7 @@ FetchRequestMode request_mode_; FetchCredentialsMode credentials_mode_; FetchRedirectMode redirect_mode_; - const bool is_main_resource_load_; + const ResourceType resource_type_; RequestContextType request_context_type_; RequestContextFrameType frame_type_; bool fall_back_required_;
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc index 39b07600c..6fbc6d6 100644 --- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc +++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -174,7 +174,7 @@ request, network_delegate, provider_host_->client_uuid(), blob_storage_context_, resource_context_, FETCH_REQUEST_MODE_NO_CORS, FETCH_CREDENTIALS_MODE_OMIT, FetchRedirectMode::FOLLOW_MODE, - true /* is_main_resource_load */, REQUEST_CONTEXT_TYPE_HYPERLINK, + RESOURCE_TYPE_MAIN_FRAME, REQUEST_CONTEXT_TYPE_HYPERLINK, REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL, scoped_refptr<ResourceRequestBody>(), ServiceWorkerFetchType::FETCH, delegate_);
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 6c427f25..76b73bb 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -303,7 +303,11 @@ kDestructedStartingWorkerTimeoutThresholdSeconds)) { DCHECK(timeout_timer_.IsRunning()); DCHECK(!embedded_worker_->devtools_attached()); - RecordStartWorkerResult(SERVICE_WORKER_ERROR_TIMEOUT); + + // RecordStartWorkerResult must be in start_callbacks_. + DCHECK(!start_callbacks_.empty()); + RecordStartWorkerResult(ServiceWorkerMetrics::EventType::UNKNOWN, + SERVICE_WORKER_ERROR_TIMEOUT); } if (context_) @@ -361,20 +365,21 @@ return info; } -void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) { +void ServiceWorkerVersion::StartWorker(ServiceWorkerMetrics::EventType purpose, + const StatusCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!context_) { - RecordStartWorkerResult(SERVICE_WORKER_ERROR_ABORT); + RecordStartWorkerResult(purpose, SERVICE_WORKER_ERROR_ABORT); RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_ABORT)); return; } if (is_redundant()) { - RecordStartWorkerResult(SERVICE_WORKER_ERROR_REDUNDANT); + RecordStartWorkerResult(purpose, SERVICE_WORKER_ERROR_REDUNDANT); RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_REDUNDANT)); return; } if (IsDisabled()) { - RecordStartWorkerResult(SERVICE_WORKER_ERROR_DISABLED_WORKER); + RecordStartWorkerResult(purpose, SERVICE_WORKER_ERROR_DISABLED_WORKER); RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_DISABLED_WORKER)); // Show a message in DevTools for developers. @@ -390,7 +395,7 @@ if (context_->wrapper()->resource_context() && !GetContentClient()->browser()->AllowServiceWorker( scope_, scope_, context_->wrapper()->resource_context(), -1, -1)) { - RecordStartWorkerResult(SERVICE_WORKER_ERROR_DISALLOWED); + RecordStartWorkerResult(purpose, SERVICE_WORKER_ERROR_DISALLOWED); RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_DISALLOWED)); return; } @@ -400,11 +405,9 @@ // Ensure the live registration during starting worker so that the worker can // get associated with it in SWDispatcherHost::OnSetHostedVersionId(). context_->storage()->FindRegistrationForId( - registration_id_, - scope_.GetOrigin(), + registration_id_, scope_.GetOrigin(), base::Bind(&ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker, - weak_factory_.GetWeakPtr(), - callback)); + weak_factory_.GetWeakPtr(), purpose, callback)); } void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) { @@ -514,6 +517,7 @@ } void ServiceWorkerVersion::RunAfterStartWorker( + ServiceWorkerMetrics::EventType purpose, const base::Closure& task, const StatusCallback& error_callback) { if (running_status() == RUNNING) { @@ -521,7 +525,8 @@ task.Run(); return; } - StartWorker(base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), + StartWorker(purpose, + base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), error_callback, task)); } @@ -543,12 +548,13 @@ OnBeginEvent(); if (running_status() != RUNNING) { // Schedule calling this method after starting the worker. - StartWorker(base::Bind( - &RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), - base::Bind(&RunErrorMessageCallback, sent_message_ports, callback), - base::Bind(&self::DispatchMessageEventInternal, - weak_factory_.GetWeakPtr(), message, sent_message_ports, - callback))); + StartWorker(ServiceWorkerMetrics::EventType::MESSAGE, + base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), + base::Bind(&RunErrorMessageCallback, + sent_message_ports, callback), + base::Bind(&self::DispatchMessageEventInternal, + weak_factory_.GetWeakPtr(), message, + sent_message_ports, callback))); return; } @@ -578,12 +584,13 @@ if (running_status() != RUNNING) { // Schedule calling this method after starting the worker. - StartWorker(base::Bind( - &RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), - base::Bind(&RunErrorMessageCallback, sent_message_ports, callback), - base::Bind(&self::DispatchCrossOriginMessageEvent, - weak_factory_.GetWeakPtr(), client, message, - sent_message_ports, callback))); + StartWorker(ServiceWorkerMetrics::EventType::MESSAGE, + base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), + base::Bind(&RunErrorMessageCallback, + sent_message_ports, callback), + base::Bind(&self::DispatchCrossOriginMessageEvent, + weak_factory_.GetWeakPtr(), client, + message, sent_message_ports, callback))); return; } @@ -1276,6 +1283,7 @@ } void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker( + ServiceWorkerMetrics::EventType purpose, const StatusCallback& callback, ServiceWorkerStatusCode status, const scoped_refptr<ServiceWorkerRegistration>& registration) { @@ -1292,12 +1300,12 @@ } } if (status != SERVICE_WORKER_OK) { - RecordStartWorkerResult(status); + RecordStartWorkerResult(purpose, status); RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); return; } if (is_redundant()) { - RecordStartWorkerResult(SERVICE_WORKER_ERROR_REDUNDANT); + RecordStartWorkerResult(purpose, SERVICE_WORKER_ERROR_REDUNDANT); RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_REDUNDANT)); return; } @@ -1316,7 +1324,7 @@ if (start_callbacks_.empty()) { start_callbacks_.push_back( base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), purpose)); } break; } @@ -1508,6 +1516,7 @@ } void ServiceWorkerVersion::RecordStartWorkerResult( + ServiceWorkerMetrics::EventType purpose, ServiceWorkerStatusCode status) { base::TimeTicks start_time = start_time_; ClearTick(&start_time_); @@ -1515,7 +1524,7 @@ if (context_) context_->UpdateVersionFailureCount(version_id_, status); - ServiceWorkerMetrics::RecordStartWorkerStatus(status, + ServiceWorkerMetrics::RecordStartWorkerStatus(status, purpose, IsInstalled(prestart_status_)); if (status == SERVICE_WORKER_OK && !start_time.is_null() &&
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index 9fcc5ff..a38a487 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h
@@ -164,7 +164,9 @@ // Starts an embedded worker for this version. // This returns OK (success) if the worker is already running. - void StartWorker(const StatusCallback& callback); + // |purpose| is recorded in UMA. + void StartWorker(ServiceWorkerMetrics::EventType purpose, + const StatusCallback& callback); // Stops an embedded worker for this version. // This returns OK (success) if the worker is already stopped. @@ -184,7 +186,9 @@ // worker is running, or |error_callback| if starting the worker failed. // If the worker is already running, |task| is executed synchronously (before // this method returns). - void RunAfterStartWorker(const base::Closure& task, + // |purpose| is used for UMA. + void RunAfterStartWorker(ServiceWorkerMetrics::EventType purpose, + const base::Closure& task, const StatusCallback& error_callback); // Call this while the worker is running before dispatching an event to the @@ -555,6 +559,7 @@ const std::vector<url::Origin>& origins); void DidEnsureLiveRegistrationForStartWorker( + ServiceWorkerMetrics::EventType purpose, const StatusCallback& callback, ServiceWorkerStatusCode status, const scoped_refptr<ServiceWorkerRegistration>& registration); @@ -585,7 +590,8 @@ // RecordStartWorkerResult is added as a start callback by StartTimeoutTimer // and records metrics about startup. - void RecordStartWorkerResult(ServiceWorkerStatusCode status); + void RecordStartWorkerResult(ServiceWorkerMetrics::EventType purpose, + ServiceWorkerStatusCode status); bool MaybeTimeOutRequest(const RequestInfo& info); void SetAllRequestExpirations(const base::TimeTicks& expiration);
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc index 8744b98d..628d625 100644 --- a/content/browser/service_worker/service_worker_version_unittest.cc +++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -252,7 +252,7 @@ // Make sure worker is running. scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner); - version_->RunAfterStartWorker(runner->QuitClosure(), + version_->RunAfterStartWorker(event_type, runner->QuitClosure(), CreateReceiverOnCurrentThread(&status)); runner->Run(); EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status); @@ -387,15 +387,18 @@ ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED; ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED; ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status1)); - version_->StartWorker(CreateReceiverOnCurrentThread(&status2)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status1)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status2)); EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status()); base::RunLoop().RunUntilIdle(); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); // Call StartWorker() after it's started. - version_->StartWorker(CreateReceiverOnCurrentThread(&status3)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status3)); base::RunLoop().RunUntilIdle(); // All should just succeed. @@ -422,7 +425,8 @@ status2 = SERVICE_WORKER_ERROR_FAILED; status3 = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status1)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status1)); EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status()); base::RunLoop().RunUntilIdle(); @@ -433,7 +437,8 @@ version_->StopWorker(CreateReceiverOnCurrentThread(&status2)); // And try calling StartWorker while StopWorker is in queue. - version_->StartWorker(CreateReceiverOnCurrentThread(&status3)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status3)); EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status()); base::RunLoop().RunUntilIdle(); @@ -468,7 +473,8 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) { // Start the worker. ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); version_->SetStatus(ServiceWorkerVersion::ACTIVATED); @@ -501,7 +507,8 @@ TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) { // Start worker. ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status()); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); @@ -592,7 +599,8 @@ // Verify the timer is running after the worker is started. ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_TRUE(version_->timeout_timer_.IsRunning()); @@ -607,7 +615,8 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_TRUE(version_->timeout_timer_.IsRunning()); @@ -658,7 +667,8 @@ TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) { ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); ASSERT_EQ(ServiceWorkerVersion::STARTING, version_->running_status()); @@ -690,7 +700,8 @@ version_->AddListener(&listener); ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -782,10 +793,10 @@ // Stale time is not deferred. version_->RunAfterStartWorker( - base::Bind(&base::DoNothing), + ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(&base::DoNothing), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); version_->RunAfterStartWorker( - base::Bind(&base::DoNothing), + ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(&base::DoNothing), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(stale_time, version_->stale_time_); @@ -809,7 +820,8 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); + version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH, + base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); base::RunLoop().RunUntilIdle(); // Create a request. @@ -836,7 +848,8 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); base::RunLoop().RunUntilIdle(); // Create a request that should expire Now(). @@ -861,7 +874,8 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); base::RunLoop().RunUntilIdle(); // Create a request that should expire Now(). @@ -889,7 +903,8 @@ SERVICE_WORKER_ERROR_NETWORK; // dummy value version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); + version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH, + base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); base::RunLoop().RunUntilIdle(); // Create a fetch request that should expire sometime later. @@ -932,8 +947,8 @@ TEST_F(ServiceWorkerFailToStartTest, RendererCrash) { ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value - version_->StartWorker( - CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); // Callback has not completed yet. @@ -957,7 +972,8 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value // Start starting the worker. - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); // Callback has not completed yet. @@ -981,7 +997,8 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) { // Start a worker. ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1010,7 +1027,8 @@ // Try to start the worker again. It should work. status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1027,7 +1045,8 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) { // Start a worker. ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1039,7 +1058,8 @@ // Worker is now stalled in stopping. Add a start worker requset. ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&start_status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&start_status)); // Simulate timeout. The worker should stop and get restarted. EXPECT_TRUE(version_->timeout_timer_.IsRunning()); @@ -1058,7 +1078,8 @@ version_->SetStatus(ServiceWorkerVersion::INSTALLING); // Start a worker. ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1133,7 +1154,8 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1166,7 +1188,8 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1190,7 +1213,8 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1215,7 +1239,8 @@ // Activate and start worker. version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1265,16 +1290,19 @@ int64_t id = version_->version_id(); set_start_mode(MessageReceiverDisallowStart::StartMode::FAIL); // Fail once. - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, context->GetVersionFailureCount(id)); // Fail again. - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(2, context->GetVersionFailureCount(id)); // Succeed. It should choose the "new process". set_start_mode(MessageReceiverDisallowStart::StartMode::SUCCEED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(helper_->new_render_process_id(), version_->embedded_worker()->process_id()); @@ -1285,22 +1313,26 @@ // (2) Fail three times. The worker should be disabled. set_start_mode(MessageReceiverDisallowStart::StartMode::FAIL); // Fail once. - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, context->GetVersionFailureCount(id)); // Fail again. - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(2, context->GetVersionFailureCount(id)); // Fail again. - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(3, context->GetVersionFailureCount(id)); // The worker should be disabled. EXPECT_TRUE(version_->IsDisabled()); set_start_mode(MessageReceiverDisallowStart::StartMode::SUCCEED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_ERROR_DISABLED_WORKER, status); EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status()); @@ -1319,7 +1351,8 @@ // Activate and start worker. version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1396,7 +1429,8 @@ // Activate and start worker. version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status()); @@ -1432,7 +1466,8 @@ // Activate and start worker. version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - version_->StartWorker(CreateReceiverOnCurrentThread(&status)); + version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC, + CreateReceiverOnCurrentThread(&status)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(SERVICE_WORKER_OK, status); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc index 3a1745f..028e874d 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
@@ -249,7 +249,7 @@ gles2_helper_.get(), gles2_share_group.get(), transfer_buffer_.get(), bind_generates_resources, lose_context_when_out_of_memory_, support_client_side_arrays, command_buffer_.get())); - setGLInterface(real_gl_.get()); + SetGLInterface(real_gl_.get()); if (!real_gl_->Initialize( mem_limits_.start_transfer_buffer_size, @@ -266,7 +266,7 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableGpuClientTracing)) { trace_gl_.reset(new gpu::gles2::GLES2TraceImplementation(GetGLInterface())); - setGLInterface(trace_gl_.get()); + SetGLInterface(trace_gl_.get()); } return true; } @@ -296,7 +296,7 @@ // issued on this context might not be visible to other contexts in the // share group. gl->Flush(); - setGLInterface(NULL); + SetGLInterface(nullptr); } trace_gl_.reset(); @@ -306,7 +306,7 @@ real_gl_.reset(); command_buffer_.reset(); - host_ = NULL; + host_ = nullptr; } gpu::ContextSupport*
diff --git a/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc b/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc index ebeff78..97b5063 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc +++ b/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc
@@ -27,18 +27,6 @@ ~EmbeddedSharedWorkerContentSettingsClientProxy() { } -bool EmbeddedSharedWorkerContentSettingsClientProxy::allowDatabase( - const blink::WebString& name, - const blink::WebString& display_name, - unsigned long estimated_size) { - if (is_unique_origin_) - return false; - bool result = false; - thread_safe_sender_->Send(new WorkerProcessHostMsg_AllowDatabase( - routing_id_, origin_url_, name, display_name, &result)); - return result; -} - bool EmbeddedSharedWorkerContentSettingsClientProxy::requestFileSystemAccessSync() { if (is_unique_origin_)
diff --git a/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h b/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h index e87e30d..b93d989a 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h +++ b/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h
@@ -27,9 +27,6 @@ ~EmbeddedSharedWorkerContentSettingsClientProxy() override; // WebWorkerContentSettingsClientProxy overrides. - bool allowDatabase(const blink::WebString& name, - const blink::WebString& display_name, - unsigned long estimated_size) override; bool requestFileSystemAccessSync() override; bool allowIndexedDB(const blink::WebString& name) override;
diff --git a/content/renderer/webgraphicscontext3d_provider_impl.cc b/content/renderer/webgraphicscontext3d_provider_impl.cc index 855bd3d..1fcdb63 100644 --- a/content/renderer/webgraphicscontext3d_provider_impl.cc +++ b/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -16,9 +16,15 @@ WebGraphicsContext3DProviderImpl::~WebGraphicsContext3DProviderImpl() {} blink::WebGraphicsContext3D* WebGraphicsContext3DProviderImpl::context3d() { + DCHECK_EQ(!!provider_->WebContext3D(), !!provider_->ContextGL()); return provider_->WebContext3D(); } +gpu::gles2::GLES2Interface* WebGraphicsContext3DProviderImpl::contextGL() { + DCHECK_EQ(!!provider_->WebContext3D(), !!provider_->ContextGL()); + return provider_->ContextGL(); +} + GrContext* WebGraphicsContext3DProviderImpl::grContext() { return provider_->GrContext(); }
diff --git a/content/renderer/webgraphicscontext3d_provider_impl.h b/content/renderer/webgraphicscontext3d_provider_impl.h index 769dd56..de155bd 100644 --- a/content/renderer/webgraphicscontext3d_provider_impl.h +++ b/content/renderer/webgraphicscontext3d_provider_impl.h
@@ -14,6 +14,12 @@ class ContextProviderWebContext; } +namespace gpu { +namespace gles2 { +class GLES2Interface; +} +} + namespace content { class CONTENT_EXPORT WebGraphicsContext3DProviderImpl @@ -25,6 +31,7 @@ // WebGraphicsContext3DProvider implementation. blink::WebGraphicsContext3D* context3d() override; + gpu::gles2::GLES2Interface* contextGL() override; GrContext* grContext() override; private:
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index fb60b51..36ab240e 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -212,6 +212,17 @@ 'swarming': False, 'os_type': 'win', }, + 'Win7 Release (NVIDIA GeForce 730)': { + 'swarming_dimensions': { + 'gpu': '10de:0f02', + 'os': 'Windows-2008ServerR2-SP1' + }, + 'build_config': 'Release', + # This bot is a one-off and doesn't have similar slaves in the + # swarming pool. + 'swarming': False, + 'os_type': 'win', + }, 'Win7 x64 Release (NVIDIA)': { 'swarming_dimensions': { 'gpu': '10de:104a', @@ -341,6 +352,17 @@ 'swarming': False, 'os_type': 'linux', }, + 'Linux Release (NVIDIA GeForce 730)': { + 'swarming_dimensions': { + 'gpu': '10de:0f02', + 'os': 'Linux' + }, + 'build_config': 'Release', + # This bot is a one-off and doesn't have similar slaves in the + # swarming pool. + 'swarming': False, + 'os_type': 'linux', + }, 'Linux Debug (NVIDIA)': { 'swarming_dimensions': { 'gpu': '10de:104a',
diff --git a/google_apis/gcm/BUILD.gn b/google_apis/gcm/BUILD.gn index f63aefb..6073e1d 100644 --- a/google_apis/gcm/BUILD.gn +++ b/google_apis/gcm/BUILD.gn
@@ -106,21 +106,23 @@ } # A standalone MCS (mobile connection server) client. -executable("mcs_probe") { - testonly = true - sources = [ - "tools/mcs_probe.cc", - ] +if (!is_ios) { + executable("mcs_probe") { + testonly = true + sources = [ + "tools/mcs_probe.cc", + ] - deps = [ - ":gcm", - ":test_support", - "//base", - "//build/config/sanitizers:deps", - "//net", - "//net:test_support", - "//third_party/protobuf:protobuf_lite", - ] + deps = [ + ":gcm", + ":test_support", + "//base", + "//build/config/sanitizers:deps", + "//net", + "//net:test_support", + "//third_party/protobuf:protobuf_lite", + ] + } } test("gcm_unit_tests") {
diff --git a/gpu/blink/webgraphicscontext3d_impl.cc b/gpu/blink/webgraphicscontext3d_impl.cc index 64a9f96..d260e94 100644 --- a/gpu/blink/webgraphicscontext3d_impl.cc +++ b/gpu/blink/webgraphicscontext3d_impl.cc
@@ -1216,14 +1216,14 @@ gl_->WaitSync(reinterpret_cast<GLsync>(sync), flags, timeout); } -bool WebGraphicsContext3DImpl::isContextLost() { - return getGraphicsResetStatusARB() != GL_NO_ERROR; -} - blink::WGC3Denum WebGraphicsContext3DImpl::getGraphicsResetStatusARB() { return gl_->GetGraphicsResetStatusKHR(); } +::gpu::gles2::GLES2Interface* WebGraphicsContext3DImpl::getGLES2Interface() { + return gl_; +} + ::gpu::gles2::GLES2ImplementationErrorMessageCallback* WebGraphicsContext3DImpl::getErrorMessageCallback() { if (!client_error_message_callback_) {
diff --git a/gpu/blink/webgraphicscontext3d_impl.h b/gpu/blink/webgraphicscontext3d_impl.h index 91881ba..ab5ab3a 100644 --- a/gpu/blink/webgraphicscontext3d_impl.h +++ b/gpu/blink/webgraphicscontext3d_impl.h
@@ -937,9 +937,11 @@ blink::WGC3Dbitfield flags, blink::WGC3Duint64 timeout) override; - bool isContextLost() override; blink::WGC3Denum getGraphicsResetStatusARB() override; + // WebGraphicsContext3D implementation. + ::gpu::gles2::GLES2Interface* getGLES2Interface() override; + ::gpu::gles2::GLES2Interface* GetGLInterface() { return gl_; } @@ -959,9 +961,7 @@ getErrorMessageCallback(); virtual void OnErrorMessage(const std::string& message, int id); - void setGLInterface(::gpu::gles2::GLES2Interface* gl) { - gl_ = gl; - } + void SetGLInterface(::gpu::gles2::GLES2Interface* gl) { gl_ = gl; } bool initialized_; bool initialize_failed_;
diff --git a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc index cc18157..5daf178 100644 --- a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc
@@ -136,7 +136,7 @@ } real_gl_ = context_->GetImplementation(); - setGLInterface(real_gl_); + SetGLInterface(real_gl_); real_gl_->TraceBeginCHROMIUM("WebGraphicsContext3D", "InProcessContext"); @@ -149,7 +149,9 @@ WebGraphicsContext3DInProcessCommandBufferImpl::InitializeOnCurrentThread() { if (!MaybeInitializeGL()) return false; - return context_ && !isContextLost(); + return context_ && + context_->GetImplementation()->GetGraphicsResetStatusKHR() == + GL_NO_ERROR; } void WebGraphicsContext3DInProcessCommandBufferImpl::SetLock(base::Lock* lock) {
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm index 8156acd..f507cd4 100644 --- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm +++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
@@ -4,7 +4,7 @@ #include "ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h" -#import <UIKit/UIkit.h> +#import <UIKit/UIKit.h> #include <utility>
diff --git a/media/mojo/common/mojo_shared_buffer_video_frame.h b/media/mojo/common/mojo_shared_buffer_video_frame.h index 11f96f7..69562c8a 100644 --- a/media/mojo/common/mojo_shared_buffer_video_frame.h +++ b/media/mojo/common/mojo_shared_buffer_video_frame.h
@@ -82,7 +82,6 @@ // can be transferred across a mojo connection. friend struct mojo::TypeConverter<mojo::StructPtr<interfaces::VideoFrame>, scoped_refptr<VideoFrame>>; - friend class MojoDecryptorService; MojoSharedBufferVideoFrame(VideoPixelFormat format, const gfx::Size& coded_size,
diff --git a/media/mojo/interfaces/BUILD.gn b/media/mojo/interfaces/BUILD.gn index 8931fb34..5d336ff3 100644 --- a/media/mojo/interfaces/BUILD.gn +++ b/media/mojo/interfaces/BUILD.gn
@@ -6,7 +6,6 @@ mojom("interfaces") { sources = [ - "audio_decoder.mojom", "content_decryption_module.mojom", "decryptor.mojom", "demuxer_stream.mojom",
diff --git a/media/mojo/interfaces/audio_decoder.mojom b/media/mojo/interfaces/audio_decoder.mojom deleted file mode 100644 index c0d2378..0000000 --- a/media/mojo/interfaces/audio_decoder.mojom +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2016 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. - -module media.interfaces; - -import "media/mojo/interfaces/media_types.mojom"; - -interface AudioDecoder { - // Status of a decode operation. See media::AudioDecoder for description. - enum DecodeStatus { - OK, // We're all good. - ABORTED, // We aborted as a result of Reset() or destruction. - ERROR, // A decoding error occurred. - }; - - // Initializes the AudioDecoder with the audio codec configuration and CDM id. - // For the unencrypted streams the |cdm_id| is ignored. Executed the callback - // with whether the initialization succeeded, and whether the pipeline needs - // bitstream conversion. - Initialize(AudioDecoderConfig config, int32 cdm_id) - => (bool success, bool needs_bitstream_conversion); - - // Sends the |buffer| to the underlying codec. Should be called only after - // Initialize() succeeds. The callback with the status is called after the - // decoder has accepted corresponding DecoderBuffer, indicating that the - // pipeline can send next buffer to decode. - // If |buffer| is an EOS buffer then the decoder must be flushed, i.e. all - // pending buffers should be processed, the corresponding decoded buffers - // should be returned to the proxy, and only then the service should return - // DecoderStatus. - Decode(DecoderBuffer buffer) => (DecodeStatus status); - - // Resets decoder state. Should be called only if Initialize() succeeds. - // All pending Decode() requests will be finished or aborted, then the method - // executes the callback. - Reset() => (); -}; - -interface AudioDecoderClient { - // Sends the decoded audio buffer back to the proxy. - OnBufferDecoded(AudioBuffer buffer); -};
diff --git a/media/mojo/interfaces/decryptor.mojom b/media/mojo/interfaces/decryptor.mojom index 84f16dd..d063e6b 100644 --- a/media/mojo/interfaces/decryptor.mojom +++ b/media/mojo/interfaces/decryptor.mojom
@@ -51,12 +51,10 @@ // been successfully initialized. // At most one decrypt-and-decode call is allowed at any time for a // |stream_type|. - // For video, ReleaseSharedBuffer() must be called when the VideoFrame - // is shared memory based and the memory is no longer needed. DecryptAndDecodeAudio(DecoderBuffer encrypted) => (Status status, array<AudioBuffer>? audio_buffers); - DecryptAndDecodeVideo(DecoderBuffer encrypted) - => (Status status, VideoFrame? video_frame); + DecryptAndDecodeVideo( + DecoderBuffer encrypted) => (Status status, VideoFrame? video_frame); // Resets the decoder for |stream_type| to a clean initialized state and // cancels any pending decrypt-and-decode operations immediately with ERROR. @@ -72,7 +70,4 @@ // After this operation, the decoder is set to an uninitialized state. // The decoder can be reinitialized after it is deinitialized. DeinitializeDecoder(DemuxerStream.Type stream_type); - - // Releases the shared memory. - ReleaseSharedBuffer(handle<shared_buffer> buffer, uint64 buffer_size); };
diff --git a/media/mojo/services/mojo_decryptor.cc b/media/mojo/services/mojo_decryptor.cc index 838f623..38f694e 100644 --- a/media/mojo/services/mojo_decryptor.cc +++ b/media/mojo/services/mojo_decryptor.cc
@@ -15,7 +15,6 @@ #include "media/base/decoder_buffer.h" #include "media/base/video_frame.h" #include "media/mojo/common/media_type_converters.h" -#include "media/mojo/common/mojo_shared_buffer_video_frame.h" #include "media/mojo/interfaces/decryptor.mojom.h" #include "mojo/shell/public/cpp/connect.h" @@ -184,27 +183,9 @@ } scoped_refptr<VideoFrame> frame(video_frame.To<scoped_refptr<VideoFrame>>()); - - // If using shared memory, ensure that ReleaseSharedBuffer() is called when - // |frame| is destroyed. - if (frame->storage_type() == VideoFrame::STORAGE_MOJO_SHARED_BUFFER) { - MojoSharedBufferVideoFrame* mojo_frame = - static_cast<MojoSharedBufferVideoFrame*>(frame.get()); - mojo_frame->SetMojoSharedBufferDoneCB(base::Bind( - &MojoDecryptor::ReleaseSharedBuffer, weak_factory_.GetWeakPtr())); - } - video_decode_cb.Run(static_cast<Decryptor::Status>(status), frame); } -void MojoDecryptor::ReleaseSharedBuffer(mojo::ScopedSharedBufferHandle buffer, - size_t buffer_size) { - DVLOG(1) << __FUNCTION__; - DCHECK(thread_checker_.CalledOnValidThread()); - - remote_decryptor_->ReleaseSharedBuffer(std::move(buffer), buffer_size); -} - void MojoDecryptor::CreateDataPipes() { // Allocate DataPipe size based on video content. Video can get quite large; // at 4K, VP9 delivers packets which are ~1MB in size; so allow for 50%
diff --git a/media/mojo/services/mojo_decryptor.h b/media/mojo/services/mojo_decryptor.h index b8c0dab7..131c0d0 100644 --- a/media/mojo/services/mojo_decryptor.h +++ b/media/mojo/services/mojo_decryptor.h
@@ -57,10 +57,6 @@ interfaces::Decryptor::Status status, interfaces::VideoFramePtr video_frame); - // Called when done with a VideoFrame in order to reuse the shared memory. - void ReleaseSharedBuffer(mojo::ScopedSharedBufferHandle buffer, - size_t buffer_size); - // To pass DecoderBuffers to and from the MojoDecryptorService, 2 data pipes // are required (one each way). At initialization both pipes are created, // and then the handles are passed to the MojoDecryptorService.
diff --git a/media/mojo/services/mojo_decryptor_service.cc b/media/mojo/services/mojo_decryptor_service.cc index 2759a30..07cb1cc 100644 --- a/media/mojo/services/mojo_decryptor_service.cc +++ b/media/mojo/services/mojo_decryptor_service.cc
@@ -18,7 +18,6 @@ #include "media/base/video_decoder_config.h" #include "media/base/video_frame.h" #include "media/mojo/common/media_type_converters.h" -#include "media/mojo/common/mojo_shared_buffer_video_frame.h" #include "media/mojo/interfaces/demuxer_stream.mojom.h" namespace media { @@ -113,12 +112,6 @@ static_cast<media::Decryptor::StreamType>(stream_type)); } -void MojoDecryptorService::ReleaseSharedBuffer( - mojo::ScopedSharedBufferHandle buffer, - uint64_t buffer_size) { - in_use_video_frames_.erase(buffer.get().value()); -} - void MojoDecryptorService::OnDecryptDone( const DecryptCallback& callback, media::Decryptor::Status status, @@ -181,15 +174,6 @@ return; } - // If |frame| has shared memory that will be passed back, keep a reference - // to it until the other side is done with the memory. - if (frame->storage_type() == VideoFrame::STORAGE_MOJO_SHARED_BUFFER) { - MojoSharedBufferVideoFrame* mojo_frame = - static_cast<MojoSharedBufferVideoFrame*>(frame.get()); - in_use_video_frames_.insert( - std::make_pair(mojo_frame->Handle().value(), frame)); - } - callback.Run(static_cast<Decryptor::Status>(status), interfaces::VideoFrame::From(frame)); }
diff --git a/media/mojo/services/mojo_decryptor_service.h b/media/mojo/services/mojo_decryptor_service.h index e81bc512..b5bf2ff2 100644 --- a/media/mojo/services/mojo_decryptor_service.h +++ b/media/mojo/services/mojo_decryptor_service.h
@@ -53,8 +53,6 @@ const DecryptAndDecodeVideoCallback& callback) final; void ResetDecoder(interfaces::DemuxerStream::Type stream_type) final; void DeinitializeDecoder(interfaces::DemuxerStream::Type stream_type) final; - void ReleaseSharedBuffer(mojo::ScopedSharedBufferHandle buffer, - uint64_t buffer_size) final; private: // Callback executed once Decrypt() is done. @@ -94,11 +92,6 @@ scoped_refptr<MediaKeys> cdm_; media::Decryptor* decryptor_; - // Keep a reference to VideoFrames until ReleaseSharedBuffer() is called - // to release it. - std::unordered_map<MojoHandle, scoped_refptr<VideoFrame>> - in_use_video_frames_; - base::WeakPtr<MojoDecryptorService> weak_this_; base::WeakPtrFactory<MojoDecryptorService> weak_factory_;
diff --git a/net/BUILD.gn b/net/BUILD.gn index b9310d9..758ef55 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -574,23 +574,25 @@ ] } -executable("dump_cache") { - testonly = true - sources = [ - "tools/dump_cache/dump_cache.cc", - "tools/dump_cache/dump_files.cc", - "tools/dump_cache/dump_files.h", - ] +if (!is_ios) { + executable("dump_cache") { + testonly = true + sources = [ + "tools/dump_cache/dump_cache.cc", + "tools/dump_cache/dump_files.cc", + "tools/dump_cache/dump_files.h", + ] - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ - ":net", - ":test_support", - "//base", - "//build/config/sanitizers:deps", - ] + deps = [ + ":net", + ":test_support", + "//base", + "//build/config/sanitizers:deps", + ] + } } source_set("test_support") { @@ -1707,40 +1709,43 @@ } # !is_android && !is_win && !is_mac +if (!is_ios) { + # TODO(crbug.com/594965): this should be converted to "app" template and + # enabled on iOS too. + executable("net_perftests") { + testonly = true + sources = [ + "base/mime_sniffer_perftest.cc", + "cookies/cookie_monster_perftest.cc", + "disk_cache/blockfile/disk_cache_perftest.cc", + "extras/sqlite/sqlite_persistent_cookie_store_perftest.cc", + "proxy/proxy_resolver_perftest.cc", + "udp/udp_socket_perftest.cc", + ] -executable("net_perftests") { - testonly = true - sources = [ - "base/mime_sniffer_perftest.cc", - "cookies/cookie_monster_perftest.cc", - "disk_cache/blockfile/disk_cache_perftest.cc", - "extras/sqlite/sqlite_persistent_cookie_store_perftest.cc", - "proxy/proxy_resolver_perftest.cc", - "udp/udp_socket_perftest.cc", - ] + # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + deps = [ + ":extras", + ":net", + ":test_support", + "//base", + "//base:i18n", + "//base/test:test_support_perf", + "//build/config/sanitizers:deps", + "//testing/gtest", + "//url", + ] - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ - ":extras", - ":net", - ":test_support", - "//base", - "//base:i18n", - "//base/test:test_support_perf", - "//build/config/sanitizers:deps", - "//testing/gtest", - "//url", - ] + if (enable_websockets) { + sources += [ "websockets/websocket_frame_perftest.cc" ] + } - if (enable_websockets) { - sources += [ "websockets/websocket_frame_perftest.cc" ] - } - - if (use_v8_in_net) { - deps += [ ":net_with_v8" ] - } else { - sources -= [ "proxy/proxy_resolver_perftest.cc" ] + if (use_v8_in_net) { + deps += [ ":net_with_v8" ] + } else { + sources -= [ "proxy/proxy_resolver_perftest.cc" ] + } } }
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 727ace6..1ea18f8 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -247,6 +247,10 @@ # define SK_SUPPORT_LEGACY_CREATESHADER_PTR #endif +#ifndef SK_SUPPORT_LEGACY_SETSHADER_PTR +# define SK_SUPPORT_LEGACY_SETSHADER_PTR +#endif + ///////////////////////// Imported from BUILD.gn and skia_common.gypi /* In some places Skia can use static initializers for global initialization,
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 5788b63cf2..928e9b864 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -1259,6 +1259,426 @@ } ] }, + "Linux Release (NVIDIA GeForce 730)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + }, + "test": "angle_end2end_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + }, + "test": "angle_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" + ], + "name": "tab_capture_end2end_tests", + "test": "browser_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + }, + "test": "content_gl_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + }, + "test": "gl_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + }, + "test": "gles2_conform_test", + "use_xvfb": false + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "context_lost_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "gpu_process_launch_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "gpu_rasterization", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "gpu_rasterization_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "hardware_accelerated_feature_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "maps_pixel_test", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "memory_test", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "memory_test", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "screenshot_sync_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "trace_test", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.0", + "--webgl2-only=true" + ], + "isolate_name": "telemetry_gpu_test", + "name": "webgl2_conformance_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle" + ], + "isolate_name": "telemetry_gpu_test", + "name": "webgl_conformance_angle_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "webgl_conformance_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Linux" + } + ] + } + } + ] + }, "Linux Release (NVIDIA)": { "gtest_tests": [ { @@ -7174,6 +7594,486 @@ } ] }, + "Win7 Release (NVIDIA GeForce 730)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "angle_end2end_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "angle_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "audio_unittests", + "use_xvfb": false + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" + ], + "name": "tab_capture_end2end_tests", + "test": "browser_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "content_gl_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-angle=d3d9" + ], + "name": "gles2_conform_d3d9_test", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gles2_conform_test", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-angle=gl", + "--disable-gpu-sandbox" + ], + "name": "gles2_conform_gl_test", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gles2_conform_test", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gles2_conform_test", + "use_xvfb": false + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "context_lost_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "gpu_process_launch_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "gpu_rasterization", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "gpu_rasterization_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "hardware_accelerated_feature_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "maps_pixel_test", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "memory_test", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "memory_test", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "win", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "screenshot_sync_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "trace_test", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.0", + "--webgl2-only=true" + ], + "isolate_name": "telemetry_gpu_test", + "name": "webgl2_conformance_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9" + ], + "isolate_name": "telemetry_gpu_test", + "name": "webgl_conformance_d3d9_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=gl" + ], + "isolate_name": "telemetry_gpu_test", + "name": "webgl_conformance_gl_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_test", + "name": "webgl_conformance_tests", + "override_compile_targets": [ + "telemetry_gpu_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:0f02", + "os": "Windows-2008ServerR2-SP1" + } + ] + } + } + ] + }, "Win7 Release (NVIDIA)": { "gtest_tests": [ {
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index eca6e81..9ef239e6 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1347,8 +1347,6 @@ crbug.com/594672 virtual/trustedeventsdefaultaction/fast/events/scale-and-scroll-iframe-body.html [ Failure Pass ] crbug.com/594672 virtual/trustedeventsdefaultaction/fast/events/updateLayoutForHitTest.html [ Failure Pass ] -crbug.com/589525 svg/text/combining-character-queries.html [ NeedsRebaseline ] - crbug.com/593888 [ Linux Debug ] fast/dom/htmlcollection-reachable.html [ Timeout ] crbug.com/593568 [ Win Debug ] virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/definite-cross-sizes.html b/third_party/WebKit/LayoutTests/css3/flexbox/definite-cross-sizes.html index f6f2a165..d78de16a 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/definite-cross-sizes.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/definite-cross-sizes.html
@@ -81,11 +81,11 @@ </div> </div> -<p>Tests that we get an definite size in a nested flexbox where only the outer one has an explicit height and has an opposite direction. TODO: This is currently considered indefinite pending crbug.com/346275</p> +<p>Tests that we get an definite size in a nested flexbox where only the outer one has an explicit height and has an opposite direction.</p> <div class="flexbox" style="height: 50px;" data-expected-height="50"> - <div class="flexbox column flex-one" data-expected-height="50"> - <div data-expected-height="50"> - <div style="height: 50%" data-expected-height="50"> <!-- TODO: should be 25 pending the above bug --> + <div class="flexbox column" data-expected-height="50"> + <div class="flex-one" data-expected-height="50"> + <div style="height: 50%" data-expected-height="25"> <div class="rect" data-expected-height="50"></div> </div> </div>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/definite-main-size.html b/third_party/WebKit/LayoutTests/css3/flexbox/definite-main-size.html new file mode 100644 index 0000000..4827a28 --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/flexbox/definite-main-size.html
@@ -0,0 +1,72 @@ +<!DOCTYPE html> + +<title>CSS Flexbox: Definite main sizes</title> + +<style> +.rect { + width: 50px; + height: 50px; + background-color: green; +} + +.flexbox { + border: 3px solid black; +} + +.flexbox > div > div { + overflow: hidden; +} + +</style> + +<link rel="stylesheet" href="resources/flexbox.css"> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#definite-sizes"> +<link rel="author" title="Google Inc." href="https://www.google.com/"> + +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../../resources/check-layout-th.js"></script> + +<body onload="checkLayout('.flexbox')" style="height: 800px;"> +<div id=log></div> + +<p>Simple case of percentage resolution:</p> +<div class="flexbox" style="width: 300px;"> + <div class="flex-one" data-expected-width="250"> + <div style="width: 50%;" data-expected-width="125"> + <div class="rect"></div> + </div> + </div> + <div class="rect flex-none"></div> +</div> + +<p>auto flex-basis. However, as this is a width, we follow regular width +rules and resolve the percentage:</p> +<div class="flexbox" style="width: 300px;"> + <div data-expected-width="50"> + <div style="width: 50%;" data-expected-width="25"> + <div class="rect"></div> + </div> + </div> + <div class="rect flex-none"></div> +</div> + +<p>Simple case of percentage resolution, columns:</p> +<div class="flexbox column" style="height: 300px;"> + <div class="flex-one" data-expected-height="250"> + <div style="height: 50%;" data-expected-height="125"> + <div class="rect"></div> + </div> + </div> + <div class="rect flex-none"></div> +</div> + +<p>auto flex-basis, we should ignore the percentage height here:</p> +<div class="flexbox column" style="height: 300px;"> + <div data-expected-height="50"> + <div style="height: 50%;" data-expected-height="50"> + <div class="rect"></div> + </div> + </div> + <div class="rect flex-none"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-padding.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-padding.html index 7c3fd5f4..bf0119c 100644 --- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-padding.html +++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-padding.html
@@ -94,14 +94,14 @@ containersize: horizontalContainerSize, flexitemcolumn: [30, 100, 110, 10], flexitemrow: [100, 50, 40, 10], - childcolumn: [20, 20, 118, 23], + childcolumn: [20, 70, 118, 23], childrow: [90, 20, 48, 23] }, ltr : { containersize: horizontalContainerSize, flexitemcolumn: [30, 100, 40, 10], flexitemrow: [100, 50, 40, 10], - childcolumn: [20, 20, 48, 23], + childcolumn: [20, 70, 48, 23], childrow: [90, 20, 48, 23] } }, @@ -110,14 +110,14 @@ containersize: horizontalContainerSize, flexitemcolumn: [100, 50, 40, 60], flexitemrow: [30, 100, 40, 10], - childcolumn: [20, 20, 48, 73], + childcolumn: [90, 20, 48, 73], childrow: [20, 70, 48, 23] }, ltr : { containersize: horizontalContainerSize, flexitemcolumn: [100, 50, 40, 10], flexitemrow: [30, 100, 40, 10], - childcolumn: [20, 20, 48, 23], + childcolumn: [90, 20, 48, 23], childrow: [20, 70, 48, 23] } }, @@ -126,14 +126,14 @@ containersize: horizontalContainerSize, flexitemcolumn: [100, 50, 40, 60], flexitemrow: [30, 100, 110, 10], - childcolumn: [20, 20, 118, 73], + childcolumn: [90, 20, 48, 73], childrow: [20, 70, 118, 23] }, ltr : { containersize: horizontalContainerSize, flexitemcolumn: [100, 50, 40, 10], flexitemrow: [30, 100, 110, 10], - childcolumn: [20, 20, 118, 23], + childcolumn: [90, 20, 48, 23], childrow: [20, 70, 118, 23] } } @@ -145,14 +145,14 @@ containersize: horizontalContainerSize, flexitemcolumn: [30, 100, 90, 10], flexitemrow: [100, 50, 20, 10], - childcolumn: [20, 20, 92, 23], + childcolumn: [20, 70, 92, 23], childrow: [90, 20, 22, 23] }, ltr : { containersize: horizontalContainerSize, flexitemcolumn: [30, 100, 40, 10], flexitemrow: [100, 50, 40, 10], - childcolumn: [20, 20, 48, 23], + childcolumn: [20, 70, 48, 23], childrow: [90, 20, 48, 23] } }, @@ -161,14 +161,14 @@ containersize: verticalContainerSize, flexitemcolumn: [100, 30, 10, 90], flexitemrow: [50, 100, 10, 20], - childcolumn: [20, 20, 23, 92], + childcolumn: [70, 20, 23, 92], childrow: [20, 90, 23, 22] }, ltr : { containersize: verticalContainerSize, flexitemcolumn: [100, 30, 10, 40], flexitemrow: [50, 100, 10, 40], - childcolumn: [20, 20, 23, 48], + childcolumn: [70, 20, 23, 48], childrow: [20, 90, 23, 48] } }, @@ -177,14 +177,14 @@ containersize: verticalContainerSize, flexitemcolumn: [100, 30, 30, 90], flexitemrow: [50, 100, 80, 20], - childcolumn: [20, 20, 97, 92], + childcolumn: [70, 20, 47, 92], childrow: [20, 90, 97, 22] }, ltr : { containersize: verticalContainerSize, flexitemcolumn: [100, 30, 30, 40], flexitemrow: [50, 100, 80, 40], - childcolumn: [20, 20, 97, 48], + childcolumn: [70, 20, 47, 48], childrow: [20, 90, 97, 48] } }
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/enabling-and-selection-expected.txt b/third_party/WebKit/LayoutTests/editing/execCommand/enabling-and-selection-expected.txt index 4bb14071..b25473d4 100644 --- a/third_party/WebKit/LayoutTests/editing/execCommand/enabling-and-selection-expected.txt +++ b/third_party/WebKit/LayoutTests/editing/execCommand/enabling-and-selection-expected.txt
@@ -11,9 +11,9 @@ PASS whenEnabled('Cut') is 'editable range' PASS whenEnabled('RemoveFormat') is 'editable range' PASS whenEnabled('Delete') is 'editable' -PASS whenEnabled('FontName') is 'editable' -PASS whenEnabled('FontSize') is 'editable' -PASS whenEnabled('FontSizeDelta') is 'editable' +PASS whenEnabled('FontName') is 'richly editable' +PASS whenEnabled('FontSize') is 'richly editable' +PASS whenEnabled('FontSizeDelta') is 'richly editable' PASS whenEnabled('ForwardDelete') is 'editable' PASS whenEnabled('InsertHTML') is 'editable' PASS whenEnabled('InsertParagraph') is 'editable'
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/script-tests/enabling-and-selection.js b/third_party/WebKit/LayoutTests/editing/execCommand/script-tests/enabling-and-selection.js index 4b1c516e..43e6460 100644 --- a/third_party/WebKit/LayoutTests/editing/execCommand/script-tests/enabling-and-selection.js +++ b/third_party/WebKit/LayoutTests/editing/execCommand/script-tests/enabling-and-selection.js
@@ -85,9 +85,9 @@ shouldBe("whenEnabled('RemoveFormat')", "'editable range'"); shouldBe("whenEnabled('Delete')", "'editable'"); -shouldBe("whenEnabled('FontName')", "'editable'"); -shouldBe("whenEnabled('FontSize')", "'editable'"); -shouldBe("whenEnabled('FontSizeDelta')", "'editable'"); +shouldBe("whenEnabled('FontName')", "'richly editable'"); +shouldBe("whenEnabled('FontSize')", "'richly editable'"); +shouldBe("whenEnabled('FontSizeDelta')", "'richly editable'"); shouldBe("whenEnabled('ForwardDelete')", "'editable'"); shouldBe("whenEnabled('InsertHTML')", "'editable'"); shouldBe("whenEnabled('InsertParagraph')", "'editable'");
diff --git a/third_party/WebKit/LayoutTests/fast/forms/plaintext-mode-1-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/plaintext-mode-1-expected.txt index 85d528e..0a78d2b0 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/plaintext-mode-1-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/forms/plaintext-mode-1-expected.txt
@@ -5,9 +5,9 @@ Success: document.queryCommandEnabled("CreateLink") == false Success: document.queryCommandEnabled("Cut") == true Success: document.queryCommandEnabled("Delete") == true -Success: document.queryCommandEnabled("FontName") == true -Success: document.queryCommandEnabled("FontSize") == true -Success: document.queryCommandEnabled("FontSizeDelta") == true +Success: document.queryCommandEnabled("FontName") == false +Success: document.queryCommandEnabled("FontSize") == false +Success: document.queryCommandEnabled("FontSizeDelta") == false Success: document.queryCommandEnabled("ForeColor") == false Success: document.queryCommandEnabled("ForwardDelete") == true Success: document.queryCommandEnabled("Indent") == false
diff --git a/third_party/WebKit/LayoutTests/fast/forms/plaintext-mode-1.html b/third_party/WebKit/LayoutTests/fast/forms/plaintext-mode-1.html index 4f9851f9..82ecc4f 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/plaintext-mode-1.html +++ b/third_party/WebKit/LayoutTests/fast/forms/plaintext-mode-1.html
@@ -38,9 +38,9 @@ assert("document.queryCommandEnabled", "CreateLink", false); assert("document.queryCommandEnabled", "Cut", true); assert("document.queryCommandEnabled", "Delete", true); -assert("document.queryCommandEnabled", "FontName", true); // Shouldn't this be false? -assert("document.queryCommandEnabled", "FontSize", true); // Shouldn't this be false? -assert("document.queryCommandEnabled", "FontSizeDelta", true); // Shouldn't this be false? +assert("document.queryCommandEnabled", "FontName", false); +assert("document.queryCommandEnabled", "FontSize", false); +assert("document.queryCommandEnabled", "FontSizeDelta", false); assert("document.queryCommandEnabled", "ForeColor", false); assert("document.queryCommandEnabled", "ForwardDelete", true); assert("document.queryCommandEnabled", "Indent", false);
diff --git a/third_party/WebKit/LayoutTests/fast/overflow/resources/transformed-frame-scrolledIntoView-frame.html b/third_party/WebKit/LayoutTests/fast/overflow/resources/transformed-frame-scrolledIntoView-frame.html new file mode 100644 index 0000000..a5e6076 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/overflow/resources/transformed-frame-scrolledIntoView-frame.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<style> +::-webkit-scrollbar { + width: 0; + height: 0; +} + +#green { + position: absolute; + left: 0; + top: 150px; + width: 100px; + height: 100px; + background: green; +} + +#bloat { + height: 1000px; +} +</style> +<div id="green"></div> +<div id="bloat"></div>
diff --git a/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView-expected.png b/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView-expected.png new file mode 100644 index 0000000..575ffd03 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView-expected.txt b/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView-expected.txt new file mode 100644 index 0000000..f818729 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView-expected.txt
@@ -0,0 +1,18 @@ +layer at (0,0) size 800x600 scrollY 200.00 scrollHeight 2016 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x2016 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x2016 + LayoutBlockFlow {BODY} at (8,8) size 784x2000 + LayoutBlockFlow {DIV} at (0,0) size 784x2000 +layer at (0,400) size 300x200 + LayoutIFrame (positioned) {IFRAME} at (0,400) size 300x200 + layer at (0,0) size 300x200 scrollY 50.00 scrollHeight 1016 + LayoutView at (0,0) size 300x200 + layer at (0,0) size 300x1016 backgroundClip at (0,0) size 300x200 clip at (0,0) size 300x200 + LayoutBlockFlow {HTML} at (0,0) size 300x1016 + LayoutBlockFlow {BODY} at (8,8) size 284x1000 + LayoutBlockFlow {DIV} at (0,0) size 284x1000 + layer at (0,150) size 100x100 backgroundClip at (0,0) size 300x200 clip at (0,0) size 300x200 + LayoutBlockFlow (positioned) {DIV} at (0,150) size 100x100 [bgcolor=#008000] +scrolled to 0,200 +frame '<!--framePath //<!--frame0-->-->' scrolled to 0,50
diff --git a/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView.html b/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView.html new file mode 100644 index 0000000..8cb7b15 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/overflow/transformed-frame-scrollIntoView.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<style> +::-webkit-scrollbar { + width: 0; + height: 0; +} + +#frame { + position: absolute; + left: 0; + top: 400px; + width: 300px; + height: 200px; + border: 0; + transform-origin: 0 0; + transform: scale(2); +} + +#bloat { + height: 2000px +} +</style> +<iframe id="frame" src="resources/transformed-frame-scrolledIntoView-frame.html"></iframe> +<div id="bloat"> +</div> +<script> +if (window.testRunner) { + testRunner.waitUntilDone(); + testRunner.dumpChildFrameScrollPositions(); +} +document.getElementById('frame').contentWindow.addEventListener('load', function() { + document.getElementById('frame').contentDocument.getElementById('green').scrollIntoViewIfNeeded(false); + if (window.testRunner) + testRunner.notifyDone(); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setVariableValue-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setVariableValue-expected.txt deleted file mode 100644 index 633edf35..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setVariableValue-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -Closure returns: {"type":"string","value":"ttttrue52013"} - (expected: 'ttttrue52013') -Debugger.setVariableValue OK -Closure returns: {"type":"string","value":"ttttrue42013"} - (expected: 'ttttrue42013') -Expected error: {"code":-32000,"message":"Either call frame or function object must be specified"} -Expected error -Expected error -
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setVariableValue.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setVariableValue.html deleted file mode 100644 index f4d9e23..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setVariableValue.html +++ /dev/null
@@ -1,181 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script> -<script> - -function test() -{ - // A general-purpose engine for sending a sequence of protocol commands. - // The clients provide requests and response handlers, while the engine catches - // errors and makes sure that once there's nothing to do completeTest() is called. - // @param step is an object with command, params and callback fields - function runRequestSeries(step) { - processStep(step); - - function processStep(s) { - try { - processStepOrFail(s); - } catch (e) { - InspectorTest.log(e.stack); - InspectorTest.completeTest(); - } - } - - function processStepOrFail(s) { - if (!s) { - InspectorTest.completeTest(); - return; - } - if (!s.command) { - // A simple loopback step. - var next = s.callback(); - processStep(next); - return; - } - - var innerCallback = function(response) { - var next; - if ("error" in response) { - if (!("errorHandler" in s)) { - // Error message is not logged intentionally, it may be platform-specific. - InspectorTest.log("Protocol command '" + s.command + "' failed"); - InspectorTest.completeTest(); - return; - } - try { - next = s.errorHandler(response.error); - } catch (e) { - InspectorTest.log(e.stack); - InspectorTest.completeTest(); - return; - } - } else { - try { - next = s.callback(response.result); - } catch (e) { - InspectorTest.log(e.stack); - InspectorTest.completeTest(); - return; - } - } - processStep(next); - } - InspectorTest.sendCommand(s.command, s.params, innerCallback); - } - } - - var firstStep = { callback: enableDebugger }; - - runRequestSeries(firstStep); - - function enableDebugger() { - return { command: "Debugger.enable", params: {}, callback: evalFunction }; - } - - // Testing function/closure scopes. - - function evalFunction(response) { - var expression = "(function(p){var r=5;with({year:2013}){return function Closure(q){return p+q+r+year};}})('ttt')"; - return { command: "Runtime.evaluate", params: {expression: expression}, callback: callbackEvalFunction }; - } - - function callbackEvalFunction(result) { - var id = result.result.objectId; - if (id === undefined) - throw new Error("objectId is expected"); - return createCheckFunctionStepChain(id); - } - - function createCheckFunctionStepChain(functionObjectId) { - var params = { - objectId: functionObjectId, - functionDeclaration: "function(){return this(true);}" - }; - return { - command: "Runtime.callFunctionOn", params: params, callback: callbackLogClosureEval - }; - - function callbackLogClosureEval(result) { - InspectorTest.log("Closure returns: " + JSON.stringify(result.result)); - InspectorTest.log(" (expected: 'ttttrue52013')"); - - var params = { - functionObjectId: functionObjectId, - scopeNumber: 1, - variableName: "r", - newValue: { value: 4 } - }; - return { - command: "Debugger.setVariableValue", params: params, callback: setVariableCallback - }; - } - - function setVariableCallback() { - InspectorTest.log("Debugger.setVariableValue OK"); - - var params = { - objectId: functionObjectId, - functionDeclaration: "function(){return this(true);}" - }; - return { - command: "Runtime.callFunctionOn", params: params, callback: callbackLogClosureEval2 - }; - - } - - function callbackLogClosureEval2(result) { - InspectorTest.log("Closure returns: " + JSON.stringify(result.result)); - InspectorTest.log(" (expected: 'ttttrue42013')"); - - var params = { - // No target is specified - scopeNumber: 1, - variableName: "r", - newValue: { value: 4 } - }; - return { - command: "Debugger.setVariableValue", params: params, errorHandler: setVariableErrorCallback3 - }; - } - - function setVariableErrorCallback3(error) { - InspectorTest.log("Expected error: " + JSON.stringify(error)); - - var params = { - functionObjectId: functionObjectId, - scopeNumber: 100, // Wrong scope number - variableName: "r", - newValue: { value: 4 } - }; - return { - command: "Debugger.setVariableValue", params: params, errorHandler: setVariableErrorCallback4 - }; - } - - function setVariableErrorCallback4(error) { - InspectorTest.log("Expected error"); - - var params = { - functionObjectId: functionObjectId, - scopeNumber: 1, - variableName: "bad", // Wrong variable name - newValue: { value: 4 } - }; - return { - command: "Debugger.setVariableValue", params: params, errorHandler: setVariableErrorCallback5 - }; - } - - function setVariableErrorCallback5(error) { - InspectorTest.log("Expected error"); - - // End of test. - return; - } - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/syntax-highlight-css-expected.txt b/third_party/WebKit/LayoutTests/inspector/syntax-highlight-css-expected.txt index 4ac8729..0c14fa20 100644 --- a/third_party/WebKit/LayoutTests/inspector/syntax-highlight-css-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/syntax-highlight-css-expected.txt
@@ -7,7 +7,7 @@ @import "/css/fireball_unicode.css"; html {}: cm-css-def, *, cm-css-string, *, cm-css-tag, * @media screen { body { color: red; } }: cm-css-def, *, cm-css-attribute, *, cm-css-tag, *, cm-css-property, *, cm-css-keyword, * @font-face { font-family: "MyHelvetica"; }: cm-css-def, *, cm-css-property, *, cm-css-string, * -p { color: color; red: red; color: #000; color: #FFF; color: #123AbC; color: #faebfe; color:papayawhip; }: cm-css-tag, *, cm-css-property, *, cm-css-variable, *, cm-css-property, *, cm-css-variable-3, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-keyword, * +p { color: color; red: red; color: #000; color: #FFF; color: #123AbC; color: #faebfe; color:papayawhip; }: cm-css-tag, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-variable-3, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-atom, *, cm-css-property, *, cm-css-keyword, * p { margin: -10px !important; }: cm-css-tag, *, cm-css-property, *, cm-css-number, *, cm-css-keyword, * $margin-left: $offsetBefore + 12px + $offsetAfter;: cm-css-variable-2, *, cm-css-variable-2, *, cm-css-number, *, cm-css-variable-2, * $type: monster; @@ -45,5 +45,5 @@ background-color: lighten($navbar-color, 10%); } } -}: cm-css-builtin, *, *, cm-css-variable-2, *, cm-css-number, *, *, cm-css-variable-2, *, cm-css-number, *, *, cm-css-variable-2, *, cm-css-atom, *, *, cm-css-property, *, cm-css-variable-2, *, *, cm-css-property, *, cm-css-number, *, cm-css-atom, *, cm-css-variable-2, *, *, cm-css-tag, *, *, cm-css-def, *, cm-css-qualifier, *, cm-css-keyword, *, *, cm-css-property, *, cm-css-atom, *, *, cm-css-property, *, cm-css-variable-2, cm-css-operator, cm-css-variable-2, *, cm-css-number, *, *, cm-css-property, *, cm-css-variable, *, cm-css-variable-2, *, cm-css-number, *, *, *, cm-css-variable-3, *, *, cm-css-property, *, cm-css-variable, *, cm-css-variable-2, *, cm-css-number, *, *, *, *, *, *, * +}: cm-css-builtin, *, *, cm-css-variable-2, *, cm-css-number, *, *, cm-css-variable-2, *, cm-css-number, *, *, cm-css-variable-2, *, cm-css-atom, *, *, cm-css-property, *, cm-css-variable-2, *, *, cm-css-property, *, cm-css-number, *, cm-css-atom, *, cm-css-variable-2, *, *, cm-css-tag, *, *, cm-css-def, *, cm-css-qualifier, *, cm-css-keyword, *, *, cm-css-property, *, cm-css-atom, *, *, cm-css-property, *, cm-css-variable-2, cm-css-operator, cm-css-variable-2, *, cm-css-number, *, *, cm-css-property, *, cm-css-atom, *, cm-css-variable-2, *, cm-css-number, *, *, *, cm-css-variable-3, *, *, cm-css-property, *, cm-css-atom, *, cm-css-variable-2, *, cm-css-number, *, *, *, *, *, *, *
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/combining-character-queries-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/combining-character-queries-expected.png new file mode 100644 index 0000000..22b5ed59 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/combining-character-queries-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/combining-character-queries-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/text/combining-character-queries-expected.txt new file mode 100644 index 0000000..452a44e --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/combining-character-queries-expected.txt
@@ -0,0 +1,538 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x521 + LayoutBlockFlow {HTML} at (0,0) size 800x521 + LayoutBlockFlow {BODY} at (8,8) size 784x505 + LayoutSVGRoot {svg} at (44,19) size 410x358 + LayoutSVGContainer {g} at (48,19) size 384x358 + LayoutSVGRect {rect} at (58,19) size 18x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=11.00] [width=18.00] [height=49.00] + LayoutSVGText {text} at (57,59) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (57.00,67.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (76,19) size 11x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=68.00] [y=11.00] [width=10.50] [height=49.00] + LayoutSVGText {text} at (71,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (71.25,67.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (86,19) size 11x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=78.50] [y=11.00] [width=10.50] [height=49.00] + LayoutSVGText {text} at (81,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (81.75,67.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (97,19) size 7x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=89.00] [y=11.00] [width=7.00] [height=49.00] + LayoutSVGText {text} at (90,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (90.50,67.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (104,19) size 7x49 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=96.00] [y=11.00] [width=7.00] [height=49.00] + LayoutSVGText {text} at (97,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (97.50,67.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (111,19) size 7x49 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=103.00] [y=11.00] [width=7.00] [height=49.00] + LayoutSVGText {text} at (104,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (104.50,67.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (208,26) size 16x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=18.00] [width=16.00] [height=40.00] + LayoutSVGText {text} at (206,57) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (206.00,65.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (224,26) size 9x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=216.00] [y=18.00] [width=9.00] [height=40.00] + LayoutSVGText {text} at (218,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (218.50,65.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (233,26) size 9x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=225.00] [y=18.00] [width=9.00] [height=40.00] + LayoutSVGText {text} at (227,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (227.50,65.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (242,26) size 5x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=234.00] [y=18.00] [width=5.00] [height=40.00] + LayoutSVGText {text} at (234,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (234.50,65.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (247,26) size 5x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=239.00] [y=18.00] [width=5.00] [height=40.00] + LayoutSVGText {text} at (239,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (239.50,65.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (252,26) size 5x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=244.00] [y=18.00] [width=5.00] [height=40.00] + LayoutSVGText {text} at (244,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (244.50,65.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (358,26) size 18x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=18.00] [width=18.00] [height=40.00] + LayoutSVGText {text} at (357,57) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (357.00,65.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (376,26) size 10x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=368.00] [y=18.00] [width=9.50] [height=40.00] + LayoutSVGText {text} at (370,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (370.75,65.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (385,26) size 10x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=377.50] [y=18.00] [width=9.50] [height=40.00] + LayoutSVGText {text} at (380,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (380.25,65.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (395,26) size 6x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=387.00] [y=18.00] [width=6.00] [height=40.00] + LayoutSVGText {text} at (388,57) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (388.00,65.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (401,26) size 6x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=393.00] [y=18.00] [width=6.00] [height=40.00] + LayoutSVGText {text} at (394,57) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (394.00,65.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (407,26) size 6x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=399.00] [y=18.00] [width=6.00] [height=40.00] + LayoutSVGText {text} at (400,57) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (400.00,65.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=100.00] [y=86.00] [width=0.00] [height=49.00] + LayoutSVGText {text} at (98,134) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (98.00,142.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (90,94) size 18x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=82.00] [y=86.00] [width=18.00] [height=49.00] + LayoutSVGText {text} at (89,134) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (89.00,142.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=82.00] [y=86.00] [width=0.00] [height=49.00] + LayoutSVGText {text} at (80,134) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (80.00,142.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (69,94) size 11x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=61.00] [y=86.00] [width=10.50] [height=49.00] + LayoutSVGText {text} at (64,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (64.25,142.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (79,94) size 11x49 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=71.50] [y=86.00] [width=10.50] [height=49.00] + LayoutSVGText {text} at (74,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (74.75,142.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=61.00] [y=86.00] [width=0.00] [height=49.00] + LayoutSVGText {text} at (59,134) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (59.00,142.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (48,94) size 7x49 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=40.00] [y=86.00] [width=7.00] [height=49.00] + LayoutSVGText {text} at (41,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (41.50,142.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (55,94) size 7x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=47.00] [y=86.00] [width=7.00] [height=49.00] + LayoutSVGText {text} at (48,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (48.50,142.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (62,94) size 7x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=54.00] [y=86.00] [width=7.00] [height=49.00] + LayoutSVGText {text} at (55,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (55.50,142.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=250.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (248,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (248.00,140.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (242,101) size 16x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=234.00] [y=93.00] [width=16.00] [height=40.00] + LayoutSVGText {text} at (240,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (240.00,140.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=234.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (232,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (232.00,140.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (224,101) size 9x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=216.00] [y=93.00] [width=9.00] [height=40.00] + LayoutSVGText {text} at (218,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (218.50,140.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (233,101) size 9x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=225.00] [y=93.00] [width=9.00] [height=40.00] + LayoutSVGText {text} at (227,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (227.50,140.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=216.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (214,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (214.00,140.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (209,101) size 5x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=201.00] [y=93.00] [width=5.00] [height=40.00] + LayoutSVGText {text} at (201,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (201.50,140.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (214,101) size 5x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=206.00] [y=93.00] [width=5.00] [height=40.00] + LayoutSVGText {text} at (206,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (206.50,140.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (219,101) size 5x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.00] [y=93.00] [width=5.00] [height=40.00] + LayoutSVGText {text} at (211,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (211.50,140.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=400.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (398,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (398.00,140.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (390,101) size 18x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=382.00] [y=93.00] [width=18.00] [height=40.00] + LayoutSVGText {text} at (389,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (389.00,140.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=382.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (380,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (380.00,140.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (371,101) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=363.00] [y=93.00] [width=9.50] [height=40.00] + LayoutSVGText {text} at (365,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (365.75,140.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (380,101) size 10x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=372.50] [y=93.00] [width=9.50] [height=40.00] + LayoutSVGText {text} at (375,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (375.25,140.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=363.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (361,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (361.00,140.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (353,101) size 6x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=345.00] [y=93.00] [width=6.00] [height=40.00] + LayoutSVGText {text} at (346,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (346.00,140.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (359,101) size 6x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=351.00] [y=93.00] [width=6.00] [height=40.00] + LayoutSVGText {text} at (352,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (352.00,140.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (365,101) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=357.00] [y=93.00] [width=6.00] [height=40.00] + LayoutSVGText {text} at (358,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (358.00,140.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,169) size 11x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=161.00] [width=11.00] [height=49.00] + LayoutSVGText {text} at (53,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (53.50,217.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (69,169) size 5x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=61.00] [y=161.00] [width=4.50] [height=49.00] + LayoutSVGText {text} at (61,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (61.25,217.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (73,169) size 5x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=65.50] [y=161.00] [width=4.50] [height=49.00] + LayoutSVGText {text} at (65,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (65.75,217.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (78,169) size 10x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=70.00] [y=161.00] [width=10.00] [height=49.00] + LayoutSVGText {text} at (73,209) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (73.00,217.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (88,169) size 18x49 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=80.00] [y=161.00] [width=18.00] [height=49.00] + LayoutSVGText {text} at (87,209) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (87.00,217.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (106,169) size 18x49 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=98.00] [y=161.00] [width=18.00] [height=49.00] + LayoutSVGText {text} at (105,209) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (105.00,217.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (124,169) size 4x49 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=116.00] [y=161.00] [width=3.33] [height=49.00] + LayoutSVGText {text} at (115,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (115.67,217.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (127,169) size 4x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=119.33] [y=161.00] [width=3.33] [height=49.00] + LayoutSVGText {text} at (119,209) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (119.00,217.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (130,169) size 5x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=122.67] [y=161.00] [width=3.33] [height=49.00] + LayoutSVGText {text} at (122,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (122.33,217.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (208,176) size 11x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=168.00] [width=11.00] [height=40.00] + LayoutSVGText {text} at (203,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (203.50,215.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,176) size 5x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.00] [y=168.00] [width=4.50] [height=40.00] + LayoutSVGText {text} at (211,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (211.25,215.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (223,176) size 5x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=215.50] [y=168.00] [width=4.50] [height=40.00] + LayoutSVGText {text} at (215,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (215.75,215.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (228,176) size 9x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=220.00] [y=168.00] [width=9.00] [height=40.00] + LayoutSVGText {text} at (222,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (222.50,215.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (237,176) size 11x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=229.00] [y=168.00] [width=10.68] [height=40.00] + LayoutSVGText {text} at (232,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (232.34,215.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (247,176) size 12x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=239.68] [y=168.00] [width=10.68] [height=40.00] + LayoutSVGText {text} at (243,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (243.03,215.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (258,176) size 4x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=250.37] [y=168.00] [width=3.00] [height=40.00] + LayoutSVGText {text} at (249,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (249.87,215.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (261,176) size 4x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=253.37] [y=168.00] [width=3.00] [height=40.00] + LayoutSVGText {text} at (252,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (252.87,215.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (264,176) size 4x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=256.37] [y=168.00] [width=3.00] [height=40.00] + LayoutSVGText {text} at (255,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (255.87,215.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (358,176) size 10x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=168.00] [width=10.00] [height=40.00] + LayoutSVGText {text} at (353,207) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (353.00,215.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (368,176) size 4x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=360.00] [y=168.00] [width=3.50] [height=40.00] + LayoutSVGText {text} at (359,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (359.75,215.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (371,176) size 4x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=363.50] [y=168.00] [width=3.50] [height=40.00] + LayoutSVGText {text} at (363,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (363.25,215.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (375,176) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=367.00] [y=168.00] [width=10.00] [height=40.00] + LayoutSVGText {text} at (370,207) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (370.00,215.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (385,176) size 10x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=377.00] [y=168.00] [width=9.68] [height=40.00] + LayoutSVGText {text} at (379,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (379.84,215.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (394,176) size 11x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=386.68] [y=168.00] [width=9.68] [height=40.00] + LayoutSVGText {text} at (389,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (389.53,215.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (404,176) size 3x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=396.37] [y=168.00] [width=2.33] [height=40.00] + LayoutSVGText {text} at (395,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (395.53,215.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (406,176) size 4x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=398.70] [y=168.00] [width=2.33] [height=40.00] + LayoutSVGText {text} at (397,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (397.87,215.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (409,176) size 3x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=401.03] [y=168.00] [width=2.33] [height=40.00] + LayoutSVGText {text} at (400,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (400.20,215.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,244) size 18x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=236.00] [width=18.00] [height=49.00] + LayoutSVGText {text} at (57,284) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (57.00,292.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (76,244) size 9x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=68.00] [y=236.00] [width=9.00] [height=49.00] + LayoutSVGText {text} at (70,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (70.50,292.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (85,244) size 9x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=77.00] [y=236.00] [width=9.00] [height=49.00] + LayoutSVGText {text} at (79,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (79.50,292.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (122,244) size 7x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=114.00] [y=236.00] [width=7.00] [height=49.00] + LayoutSVGText {text} at (115,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (115.50,292.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (115,244) size 7x49 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=107.00] [y=236.00] [width=7.00] [height=49.00] + LayoutSVGText {text} at (108,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (108.50,292.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (104,244) size 11x49 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=96.50] [y=236.00] [width=10.50] [height=49.00] + LayoutSVGText {text} at (99,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (99.75,292.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (94,244) size 11x49 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=86.00] [y=236.00] [width=10.50] [height=49.00] + LayoutSVGText {text} at (89,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (89.25,292.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (129,244) size 18x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=121.00] [y=236.00] [width=18.00] [height=49.00] + LayoutSVGText {text} at (128,284) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (128.00,292.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (147,244) size 9x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=139.00] [y=236.00] [width=9.00] [height=49.00] + LayoutSVGText {text} at (141,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (141.50,292.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (156,244) size 9x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=148.00] [y=236.00] [width=9.00] [height=49.00] + LayoutSVGText {text} at (150,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (150.50,292.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (208,251) size 11x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=243.00] [width=10.68] [height=40.00] + LayoutSVGText {text} at (203,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (203.34,290.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (218,251) size 7x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=210.68] [y=243.00] [width=5.34] [height=40.00] + LayoutSVGText {text} at (211,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (211.35,290.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,251) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.03] [y=243.00] [width=5.34] [height=40.00] + LayoutSVGText {text} at (216,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (216.70,290.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (257,251) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=249.37] [y=243.00] [width=7.00] [height=40.00] + LayoutSVGText {text} at (250,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (250.87,290.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (250,251) size 8x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=242.37] [y=243.00] [width=7.00] [height=40.00] + LayoutSVGText {text} at (243,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (243.87,290.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (239,251) size 12x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=231.87] [y=243.00] [width=10.50] [height=40.00] + LayoutSVGText {text} at (235,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (235.12,290.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (229,251) size 11x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=221.37] [y=243.00] [width=10.50] [height=40.00] + LayoutSVGText {text} at (224,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (224.62,290.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (264,251) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=256.37] [y=243.00] [width=10.68] [height=40.00] + LayoutSVGText {text} at (259,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (259.71,290.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (275,251) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=267.05] [y=243.00] [width=5.34] [height=40.00] + LayoutSVGText {text} at (267,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (267.72,290.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (280,251) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=272.39] [y=243.00] [width=5.34] [height=40.00] + LayoutSVGText {text} at (273,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (273.06,290.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (358,251) size 10x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=243.00] [width=9.68] [height=40.00] + LayoutSVGText {text} at (352,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (352.84,290.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (367,251) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=359.68] [y=243.00] [width=4.84] [height=40.00] + LayoutSVGText {text} at (360,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (360.10,290.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (372,251) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=364.53] [y=243.00] [width=4.84] [height=40.00] + LayoutSVGText {text} at (364,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (364.95,290.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (405,251) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=397.37] [y=243.00] [width=7.00] [height=40.00] + LayoutSVGText {text} at (398,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (398.87,290.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (398,251) size 8x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=390.37] [y=243.00] [width=7.00] [height=40.00] + LayoutSVGText {text} at (391,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (391.87,290.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (387,251) size 12x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=379.87] [y=243.00] [width=10.50] [height=40.00] + LayoutSVGText {text} at (383,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (383.12,290.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (377,251) size 11x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=369.37] [y=243.00] [width=10.50] [height=40.00] + LayoutSVGText {text} at (372,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (372.62,290.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (412,251) size 11x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=404.37] [y=243.00] [width=9.68] [height=40.00] + LayoutSVGText {text} at (407,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (407.21,290.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (422,251) size 5x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=414.05] [y=243.00] [width=4.84] [height=40.00] + LayoutSVGText {text} at (414,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (414.47,290.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (426,251) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=418.89] [y=243.00] [width=4.84] [height=40.00] + LayoutSVGText {text} at (419,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (419.31,290.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (58,319) size 5x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=311.00] [width=5.00] [height=49.00] + LayoutSVGText {text} at (50,359) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (50.50,367.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (63,319) size 17x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=55.00] [y=311.00] [width=17.00] [height=49.00] + LayoutSVGText {text} at (61,359) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (61.50,367.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (80,319) size 5x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=72.00] [y=311.00] [width=5.00] [height=49.00] + LayoutSVGText {text} at (72,359) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (72.50,367.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (85,319) size 5x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=77.00] [y=311.00] [width=5.00] [height=49.00] + LayoutSVGText {text} at (77,359) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (77.50,367.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (208,326) size 5x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=318.00] [width=4.50] [height=40.00] + LayoutSVGText {text} at (200,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (200.25,365.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (212,326) size 28x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=204.50] [y=318.00] [width=27.00] [height=40.00] + LayoutSVGText {text} at (216,357) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (216.00,365.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (239,326) size 5x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=231.50] [y=318.00] [width=4.50] [height=40.00] + LayoutSVGText {text} at (231,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (231.75,365.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (244,326) size 5x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=236.00] [y=318.00] [width=4.50] [height=40.00] + LayoutSVGText {text} at (236,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (236.25,365.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (358,326) size 5x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=318.00] [width=5.00] [height=40.00] + LayoutSVGText {text} at (350,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (350.50,365.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (363,326) size 26x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=355.00] [y=318.00] [width=26.00] [height=40.00] + LayoutSVGText {text} at (366,357) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (366.00,365.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (389,326) size 4x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=381.00] [y=318.00] [width=3.50] [height=40.00] + LayoutSVGText {text} at (380,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (380.75,365.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (392,326) size 4x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=384.50] [y=318.00] [width=3.50] [height=40.00] + LayoutSVGText {text} at (384,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (384.25,365.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGContainer {g} at (44,19) size 410x349 + LayoutSVGText {text} at (50,11) size 60x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 60x49 + chunk 1 text run 1 at (50.00,50.00) startOffset 0 endOffset 6 width 60.00: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (200,18) size 56x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 56x40 + chunk 1 text run 1 at (200.00,50.00) startOffset 0 endOffset 6 width 49.00: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (350,18) size 59x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 59x40 + chunk 1 text run 1 at (350.00,50.00) startOffset 0 endOffset 6 width 55.00: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (40,86) size 60x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 60x49 + chunk 1 text run 1 at (40.00,125.00) startOffset 0 endOffset 3 width 21.00: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (61.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (61.00,125.00) startOffset 0 endOffset 2 width 21.00: "b\x{30C}" + chunk 1 text run 1 at (82.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (82.00,125.00) startOffset 0 endOffset 1 width 18.00: "a" + chunk 1 text run 1 at (100.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (201,93) size 55x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 55x40 + chunk 1 text run 1 at (201.00,125.00) startOffset 0 endOffset 3 width 15.00: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (216.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (216.00,125.00) startOffset 0 endOffset 2 width 18.00: "b\x{30C}" + chunk 1 text run 1 at (234.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (234.00,125.00) startOffset 0 endOffset 1 width 16.00: "a" + chunk 1 text run 1 at (250.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (345,93) size 59x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 59x40 + chunk 1 text run 1 at (345.00,125.00) startOffset 0 endOffset 3 width 18.00: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (363.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (363.00,125.00) startOffset 0 endOffset 2 width 19.00: "b\x{30C}" + chunk 1 text run 1 at (382.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (382.00,125.00) startOffset 0 endOffset 1 width 18.00: "a" + chunk 1 text run 1 at (400.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (50,144) size 91x66 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 91x66 + chunk 1 text run 1 at (50.00,200.00) startOffset 0 endOffset 9 width 76.00: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (200,168) size 82x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 82x40 + chunk 1 text run 1 at (200.00,200.00) startOffset 0 endOffset 9 width 59.37: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (350,168) size 76x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 76x40 + chunk 1 text run 1 at (350.00,200.00) startOffset 0 endOffset 9 width 53.37: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (50,236) size 122x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 122x49 + chunk 1 text run 1 at (50.00,275.00) startOffset 0 endOffset 3 width 36.00: "ff\x{30C}" + chunk 1 text run 1 at (86.00,275.00) startOffset 0 endOffset 4 width 35.00 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (121.00,275.00) startOffset 0 endOffset 3 width 36.00: "ff\x{30C}" + LayoutSVGText {text} at (200,243) size 100x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 100x40 + chunk 1 text run 1 at (200.00,275.00) startOffset 0 endOffset 3 width 21.37: "ff\x{30C}" + chunk 1 text run 1 at (221.37,275.00) startOffset 0 endOffset 4 width 35.00 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (256.37,275.00) startOffset 0 endOffset 3 width 21.37: "ff\x{30C}" + LayoutSVGText {text} at (350,243) size 96x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 96x40 + chunk 1 text run 1 at (350.00,275.00) startOffset 0 endOffset 3 width 19.37: "ff\x{30C}" + chunk 1 text run 1 at (369.37,275.00) startOffset 0 endOffset 4 width 35.00 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (404.37,275.00) startOffset 0 endOffset 3 width 19.37: "ff\x{30C}" + LayoutSVGText {text} at (36,311) size 61x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 61x49 + chunk 1 text run 1 at (50.00,350.00) startOffset 0 endOffset 1 width 5.00: "\x{30C}" + chunk 1 text run 1 at (55.00,350.00) startOffset 0 endOffset 1 width 17.00 RTL: "\x{FDB0}" + chunk 1 text run 1 at (72.00,350.00) startOffset 0 endOffset 2 width 10.00: "i\x{333}" + LayoutSVGText {text} at (186,318) size 77x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 77x40 + chunk 1 text run 1 at (200.00,350.00) startOffset 0 endOffset 1 width 4.50: "\x{30C}" + chunk 1 text run 1 at (204.50,350.00) startOffset 0 endOffset 1 width 27.00 RTL: "\x{FDB0}" + chunk 1 text run 1 at (231.50,350.00) startOffset 0 endOffset 2 width 9.00: "i\x{333}" + LayoutSVGText {text} at (336,318) size 74x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 74x40 + chunk 1 text run 1 at (350.00,350.00) startOffset 0 endOffset 1 width 5.00: "\x{30C}" + chunk 1 text run 1 at (355.00,350.00) startOffset 0 endOffset 1 width 26.00 RTL: "\x{FDB0}" + chunk 1 text run 1 at (381.00,350.00) startOffset 0 endOffset 2 width 7.00: "i\x{333}" + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/combining-character-queries-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/combining-character-queries-expected.png new file mode 100644 index 0000000..049e636 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/combining-character-queries-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/combining-character-queries-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/combining-character-queries-expected.txt new file mode 100644 index 0000000..2bbed503 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/combining-character-queries-expected.txt
@@ -0,0 +1,538 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x520 + LayoutBlockFlow {HTML} at (0,0) size 800x520 + LayoutBlockFlow {BODY} at (8,8) size 784x504 + LayoutSVGRoot {svg} at (50,18) size 391x365 + LayoutSVGContainer {g} at (56,19) size 385x364 + LayoutSVGRect {rect} at (58,19) size 18x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=11.00] [width=17.96] [height=55.00] + LayoutSVGText {text} at (56,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (56.98,73.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (75,19) size 10x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=67.96] [y=11.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (70,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (70.20,73.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (84,19) size 9x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=76.45] [y=11.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (78,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (78.69,73.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (92,19) size 6x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=84.93] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (85,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (85.16,73.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (97,19) size 5x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=89.40] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (89,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (89.63,73.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (101,19) size 6x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=93.86] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (94,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (94.10,73.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (208,27) size 16x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=19.00] [width=15.53] [height=40.00] + LayoutSVGText {text} at (205,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (205.77,66.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (223,27) size 10x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=215.53] [y=19.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (217,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (217.91,66.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (232,27) size 10x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=224.28] [y=19.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (226,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (226.66,66.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (241,27) size 6x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=233.03] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (233,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (233.62,66.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (246,27) size 6x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=238.21] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (238,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (238.80,66.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (251,27) size 6x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=243.39] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (243,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (243.98,66.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (358,26) size 20x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=18.00] [width=19.47] [height=40.00] + LayoutSVGText {text} at (357,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (357.73,65.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (377,26) size 11x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=369.47] [y=18.00] [width=9.73] [height=40.00] + LayoutSVGText {text} at (372,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (372.33,65.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (387,26) size 10x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=379.20] [y=18.00] [width=9.73] [height=40.00] + LayoutSVGText {text} at (382,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (382.06,65.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (396,26) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=388.93] [y=18.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (390,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (390.03,65.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (403,26) size 7x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=395.12] [y=18.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (396,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (396.22,65.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (409,26) size 7x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=401.32] [y=18.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (402,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (402.41,65.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=100.00] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (97,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (98.00,148.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (90,94) size 18x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=82.04] [y=86.00] [width=17.96] [height=55.00] + LayoutSVGText {text} at (89,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (89.02,148.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=82.04] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (80,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (80.04,148.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (73,94) size 9x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=65.07] [y=86.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (67,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (67.31,148.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (81,94) size 10x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=73.55] [y=86.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (75,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (75.80,148.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=65.07] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (63,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (63.07,148.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (59,94) size 6x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=51.67] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (51,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (51.90,148.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (64,94) size 5x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=56.14] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (56,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (56.37,148.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (68,94) size 6x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=60.60] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (60,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (60.84,148.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=250.00] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (248,134) size 4x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (248.00,141.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (242,102) size 16x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=234.47] [y=94.00] [width=15.53] [height=40.00] + LayoutSVGText {text} at (240,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (240.23,141.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=234.47] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (232,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (232.47,141.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (224,102) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=216.97] [y=94.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (219,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (219.34,141.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (233,102) size 10x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=225.72] [y=94.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (228,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (228.09,141.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=216.97] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (214,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (214.97,141.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (209,102) size 6x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=201.43] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (202,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (202.02,141.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (214,102) size 6x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=206.61] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (207,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (207.20,141.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (219,102) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.79] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (212,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (212.38,141.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=400.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (398,133) size 4x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (398.00,140.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (388,101) size 20x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=380.53] [y=93.00] [width=19.47] [height=40.00] + LayoutSVGText {text} at (388,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (388.27,140.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=380.53] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (378,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (378.53,140.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (368,101) size 11x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=360.73] [y=93.00] [width=9.90] [height=40.00] + LayoutSVGText {text} at (363,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (363.68,140.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (378,101) size 11x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=370.63] [y=93.00] [width=9.90] [height=40.00] + LayoutSVGText {text} at (373,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (373.58,140.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=360.73] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (358,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (358.73,140.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (350,101) size 7x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=342.15] [y=93.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (343,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (343.25,140.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (356,101) size 7x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=348.34] [y=93.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (349,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (349.44,140.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (362,101) size 7x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=354.54] [y=93.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (355,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (355.63,140.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,169) size 6x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=161.00] [width=5.97] [height=55.00] + LayoutSVGText {text} at (50,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (50.99,223.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (63,169) size 18x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=55.97] [y=161.00] [width=16.27] [height=55.00] + LayoutSVGText {text} at (62,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (62.11,223.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (80,169) size 17x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=72.24] [y=161.00] [width=16.27] [height=55.00] + LayoutSVGText {text} at (78,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (78.37,223.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (96,169) size 11x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=88.50] [y=161.00] [width=9.72] [height=55.00] + LayoutSVGText {text} at (91,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (91.37,223.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (106,169) size 1x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=98.23] [y=161.00] [width=0.42] [height=55.00] + LayoutSVGText {text} at (96,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (96.44,223.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (106,169) size 2x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=98.65] [y=161.00] [width=0.42] [height=55.00] + LayoutSVGText {text} at (96,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (96.86,223.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (107,169) size 13x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=99.06] [y=161.00] [width=12.56] [height=55.00] + LayoutSVGText {text} at (103,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (103.35,223.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (119,169) size 14x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=111.63] [y=161.00] [width=12.56] [height=55.00] + LayoutSVGText {text} at (115,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (115.91,223.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (132,169) size 13x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=124.19] [y=161.00] [width=12.56] [height=55.00] + LayoutSVGText {text} at (128,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (128.47,223.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (208,177) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=169.00] [width=11.66] [height=40.00] + LayoutSVGText {text} at (203,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (203.83,216.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,177) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.66] [y=169.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (212,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (212.09,216.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,177) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.52] [y=169.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (216,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (216.95,216.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (229,177) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=221.38] [y=169.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (223,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (223.75,216.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (238,177) size 12x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=230.13] [y=169.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (233,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (233.65,216.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (249,177) size 13x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=241.17] [y=169.00] [width=12.30] [height=40.00] + LayoutSVGText {text} at (245,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (245.32,216.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (261,177) size 4x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=253.47] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (253,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (253.09,216.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (264,177) size 4x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=256.72] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (256,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (256.34,216.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (267,177) size 5x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=259.96] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (259,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (259.58,216.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (358,176) size 6x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=168.00] [width=5.85] [height=40.00] + LayoutSVGText {text} at (350,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (350.93,215.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (363,176) size 7x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=355.85] [y=168.00] [width=5.85] [height=40.00] + LayoutSVGText {text} at (356,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (356.78,215.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (369,176) size 7x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=361.71] [y=168.00] [width=5.85] [height=40.00] + LayoutSVGText {text} at (362,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (362.63,215.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (375,176) size 11x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=367.56] [y=168.00] [width=9.72] [height=40.00] + LayoutSVGText {text} at (370,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (370.42,215.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (385,176) size 11x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=377.28] [y=168.00] [width=9.72] [height=40.00] + LayoutSVGText {text} at (380,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (380.15,215.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (395,176) size 5x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=387.01] [y=168.00] [width=4.39] [height=40.00] + LayoutSVGText {text} at (387,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (387.20,215.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (399,176) size 5x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=391.40] [y=168.00] [width=4.39] [height=40.00] + LayoutSVGText {text} at (391,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (391.59,215.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (403,176) size 6x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=395.79] [y=168.00] [width=4.39] [height=40.00] + LayoutSVGText {text} at (395,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (395.98,215.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (408,176) size 5x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=400.18] [y=168.00] [width=4.39] [height=40.00] + LayoutSVGText {text} at (400,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (400.37,215.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,244) size 2x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=236.00] [width=1.45] [height=55.00] + LayoutSVGText {text} at (48,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (48.73,298.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (59,244) size 16x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=51.45] [y=236.00] [width=15.24] [height=55.00] + LayoutSVGText {text} at (57,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (57.07,298.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (74,244) size 16x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=66.69] [y=236.00] [width=15.24] [height=55.00] + LayoutSVGText {text} at (72,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (72.31,298.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (117,244) size 8x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=109.47] [y=236.00] [width=7.10] [height=55.00] + LayoutSVGText {text} at (111,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (111.02,298.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (110,244) size 8x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=102.37] [y=236.00] [width=7.10] [height=55.00] + LayoutSVGText {text} at (103,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (103.92,298.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (100,244) size 11x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=92.15] [y=236.00] [width=10.22] [height=55.00] + LayoutSVGText {text} at (95,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (95.26,298.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (89,244) size 12x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=81.92] [y=236.00] [width=10.22] [height=55.00] + LayoutSVGText {text} at (85,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (85.03,298.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (124,244) size 3x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=116.58] [y=236.00] [width=1.45] [height=55.00] + LayoutSVGText {text} at (115,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (115.30,298.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (126,244) size 16x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=118.03] [y=236.00] [width=15.24] [height=55.00] + LayoutSVGText {text} at (123,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (123.65,298.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (141,244) size 16x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=133.26] [y=236.00] [width=15.24] [height=55.00] + LayoutSVGText {text} at (138,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (138.88,298.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (208,252) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=244.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (203,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (203.52,291.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,252) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.04] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (211,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (211.95,291.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,252) size 7x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.87] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (217,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (217.78,291.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (258,252) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=250.24] [y=244.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (251,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (251.79,291.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (251,252) size 8x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=243.14] [y=244.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (244,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (244.69,291.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (240,252) size 12x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=232.92] [y=244.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (236,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (236.03,291.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (230,252) size 11x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=222.70] [y=244.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (225,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (225.81,291.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (265,252) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=257.35] [y=244.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (260,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (260.87,291.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (276,252) size 7x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=268.39] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (269,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (269.30,291.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (282,252) size 7x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=274.21] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (275,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (275.13,291.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (358,251) size 10x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=243.00] [width=9.40] [height=40.00] + LayoutSVGText {text} at (352,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (352.70,290.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (367,251) size 8x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=359.40] [y=243.00] [width=7.27] [height=40.00] + LayoutSVGText {text} at (361,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (361.04,290.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (374,251) size 8x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=366.67] [y=243.00] [width=7.27] [height=40.00] + LayoutSVGText {text} at (368,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (368.31,290.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (409,251) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=401.49] [y=243.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (403,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (403.04,290.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (402,251) size 8x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=394.39] [y=243.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (395,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (395.94,290.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (392,251) size 11x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=384.16] [y=243.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (387,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (387.28,290.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (381,251) size 12x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=373.94] [y=243.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (377,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (377.05,290.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (416,251) size 10x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=408.59] [y=243.00] [width=9.40] [height=40.00] + LayoutSVGText {text} at (411,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (411.29,290.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (425,251) size 9x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=417.99] [y=243.00] [width=7.27] [height=40.00] + LayoutSVGText {text} at (419,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (419.63,290.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (433,251) size 8x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=425.27] [y=243.00] [width=7.27] [height=40.00] + LayoutSVGText {text} at (426,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (426.90,290.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (58,319) size 16x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=311.00] [width=15.62] [height=55.00] + LayoutSVGText {text} at (55,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (55.81,373.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (73,319) size 50x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=65.62] [y=311.00] [width=49.07] [height=55.00] + LayoutSVGText {text} at (88,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (88.15,373.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (122,319) size 26x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=114.69] [y=311.00] [width=25.28] [height=55.00] + LayoutSVGText {text} at (125,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (125.32,373.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (147,319) size 27x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=139.96] [y=311.00] [width=25.28] [height=55.00] + LayoutSVGText {text} at (150,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (150.60,373.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (208,327) size 13x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=319.00] [width=12.24] [height=40.00] + LayoutSVGText {text} at (204,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (204.12,366.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (220,327) size 50x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=212.24] [y=319.00] [width=49.07] [height=40.00] + LayoutSVGText {text} at (234,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (234.77,366.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (269,327) size 12x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=261.30] [y=319.00] [width=10.75] [height=40.00] + LayoutSVGText {text} at (264,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (264.68,366.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (280,327) size 11x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=272.05] [y=319.00] [width=10.75] [height=40.00] + LayoutSVGText {text} at (275,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (275.43,366.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (358,326) size 15x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=318.00] [width=14.83] [height=40.00] + LayoutSVGText {text} at (355,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (355.42,365.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (372,326) size 50x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=364.83] [y=318.00] [width=49.07] [height=40.00] + LayoutSVGText {text} at (387,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (387.37,365.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (421,326) size 9x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=413.90] [y=318.00] [width=7.88] [height=40.00] + LayoutSVGText {text} at (415,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (415.84,365.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (429,326) size 9x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=421.78] [y=318.00] [width=7.88] [height=40.00] + LayoutSVGText {text} at (423,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (423.72,365.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGContainer {g} at (50,18) size 391x357 + LayoutSVGText {text} at (50,10) size 50x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 50x56 + chunk 1 text run 1 at (50.00,50.00) startOffset 0 endOffset 6 width 48.33: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (200,15) size 49x44 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x44 + chunk 1 text run 1 at (200.00,50.00) startOffset 0 endOffset 6 width 48.57: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (350,16) size 58x42 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 58x42 + chunk 1 text run 1 at (350.00,50.00) startOffset 0 endOffset 6 width 57.51: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (51,86) size 50x55 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x55 + chunk 1 text run 1 at (51.67,125.00) startOffset 0 endOffset 3 width 13.40: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (65.07,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (65.07,125.00) startOffset 0 endOffset 2 width 16.97: "b\x{30C}" + chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 17.96: "a" + chunk 1 text run 1 at (100.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (201,94) size 49x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x40 + chunk 1 text run 1 at (201.43,125.00) startOffset 0 endOffset 3 width 15.53: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 2 width 17.50: "b\x{30C}" + chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 15.53: "a" + chunk 1 text run 1 at (250.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (342,93) size 58x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 58x40 + chunk 1 text run 1 at (342.15,125.00) startOffset 0 endOffset 3 width 18.58: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (360.73,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (360.73,125.00) startOffset 0 endOffset 2 width 19.81: "b\x{30C}" + chunk 1 text run 1 at (380.53,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (380.53,125.00) startOffset 0 endOffset 1 width 19.47: "a" + chunk 1 text run 1 at (400.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (42,160) size 95x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 95x56 + chunk 1 text run 1 at (50.00,200.00) startOffset 0 endOffset 9 width 86.75: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (200,169) size 64x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 64x40 + chunk 1 text run 1 at (200.00,200.00) startOffset 0 endOffset 9 width 63.20: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (350,166) size 55x42 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 55x42 + chunk 1 text run 1 at (350.00,200.00) startOffset 0 endOffset 9 width 54.57: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (42,236) size 107x55 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 107x55 + chunk 1 text run 1 at (50.00,275.00) startOffset 0 endOffset 3 width 31.92: "ff\x{30C}" + chunk 1 text run 1 at (81.92,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (116.58,275.00) startOffset 0 endOffset 3 width 31.92: "ff\x{30C}" + LayoutSVGText {text} at (200,244) size 82x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 82x40 + chunk 1 text run 1 at (200.00,275.00) startOffset 0 endOffset 3 width 22.70: "ff\x{30C}" + chunk 1 text run 1 at (222.70,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (257.35,275.00) startOffset 0 endOffset 3 width 22.70: "ff\x{30C}" + LayoutSVGText {text} at (350,243) size 83x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 83x40 + chunk 1 text run 1 at (350.00,275.00) startOffset 0 endOffset 3 width 23.94: "ff\x{30C}" + chunk 1 text run 1 at (373.94,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (408.59,275.00) startOffset 0 endOffset 3 width 23.94: "ff\x{30C}" + LayoutSVGText {text} at (50,311) size 116x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 116x56 + chunk 1 text run 1 at (50.00,350.00) startOffset 0 endOffset 1 width 15.62: "\x{30C}" + chunk 1 text run 1 at (65.62,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (114.69,350.00) startOffset 0 endOffset 2 width 50.55: "i\x{333}" + LayoutSVGText {text} at (199,319) size 84x48 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 84x48 + chunk 1 text run 1 at (200.00,350.00) startOffset 0 endOffset 1 width 12.24: "\x{30C}" + chunk 1 text run 1 at (212.24,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (261.30,350.00) startOffset 0 endOffset 2 width 21.50: "i\x{333}" + LayoutSVGText {text} at (335,318) size 95x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 95x49 + chunk 1 text run 1 at (350.00,350.00) startOffset 0 endOffset 1 width 14.83: "\x{30C}" + chunk 1 text run 1 at (364.83,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (413.90,350.00) startOffset 0 endOffset 2 width 15.76: "i\x{333}" + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.png new file mode 100644 index 0000000..a141403 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.txt new file mode 100644 index 0000000..05d135a1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/combining-character-queries-expected.txt
@@ -0,0 +1,538 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x520 + LayoutBlockFlow {HTML} at (0,0) size 800x520 + LayoutBlockFlow {BODY} at (8,8) size 784x504 + LayoutSVGRoot {svg} at (50,18) size 382x365 + LayoutSVGContainer {g} at (56,19) size 375x364 + LayoutSVGRect {rect} at (58,19) size 18x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=11.00] [width=17.96] [height=55.00] + LayoutSVGText {text} at (56,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (56.98,73.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (75,19) size 10x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=67.96] [y=11.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (70,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (70.20,73.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (84,19) size 9x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=76.45] [y=11.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (78,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (78.69,73.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (92,19) size 6x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=84.93] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (85,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (85.16,73.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (97,19) size 5x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=89.40] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (89,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (89.63,73.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (101,19) size 6x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=93.86] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (94,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (94.10,73.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (208,27) size 16x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=19.00] [width=15.53] [height=40.00] + LayoutSVGText {text} at (205,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (205.77,66.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (223,27) size 10x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=215.53] [y=19.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (217,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (217.91,66.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (232,27) size 10x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=224.28] [y=19.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (226,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (226.66,66.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (241,27) size 6x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=233.03] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (233,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (233.62,66.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (246,27) size 6x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=238.21] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (238,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (238.80,66.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (251,27) size 6x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=243.39] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (243,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (243.98,66.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (358,26) size 20x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=18.00] [width=19.47] [height=40.00] + LayoutSVGText {text} at (357,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (357.73,65.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (377,26) size 11x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=369.47] [y=18.00] [width=9.73] [height=40.00] + LayoutSVGText {text} at (372,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (372.33,65.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (387,26) size 10x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=379.20] [y=18.00] [width=9.73] [height=40.00] + LayoutSVGText {text} at (382,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (382.06,65.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (396,26) size 7x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=388.93] [y=18.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (389,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (389.85,65.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (402,26) size 7x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=394.76] [y=18.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (395,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (395.68,65.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (408,26) size 7x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=400.60] [y=18.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (401,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (401.51,65.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=100.00] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (97,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (98.00,148.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (90,94) size 18x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=82.04] [y=86.00] [width=17.96] [height=55.00] + LayoutSVGText {text} at (89,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (89.02,148.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=82.04] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (80,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (80.04,148.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (73,94) size 9x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=65.07] [y=86.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (67,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (67.31,148.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (81,94) size 10x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=73.55] [y=86.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (75,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (75.80,148.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=65.07] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (63,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (63.07,148.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (59,94) size 6x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=51.67] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (51,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (51.90,148.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (64,94) size 5x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=56.14] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (56,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (56.37,148.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (68,94) size 6x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=60.60] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (60,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (60.84,148.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=250.00] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (248,134) size 4x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (248.00,141.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (242,102) size 16x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=234.47] [y=94.00] [width=15.53] [height=40.00] + LayoutSVGText {text} at (240,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (240.23,141.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=234.47] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (232,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (232.47,141.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (224,102) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=216.97] [y=94.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (219,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (219.34,141.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (233,102) size 10x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=225.72] [y=94.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (228,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (228.09,141.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=216.97] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (214,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (214.97,141.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (209,102) size 6x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=201.43] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (202,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (202.02,141.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (214,102) size 6x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=206.61] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (207,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (207.20,141.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (219,102) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.79] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (212,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (212.38,141.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=400.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (398,133) size 4x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (398.00,140.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (388,101) size 20x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=380.53] [y=93.00] [width=19.47] [height=40.00] + LayoutSVGText {text} at (388,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (388.27,140.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=380.53] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (378,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (378.53,140.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (369,101) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=361.07] [y=93.00] [width=9.73] [height=40.00] + LayoutSVGText {text} at (363,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (363.94,140.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (378,101) size 11x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=370.80] [y=93.00] [width=9.73] [height=40.00] + LayoutSVGText {text} at (373,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (373.67,140.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=361.07] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (359,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (359.07,140.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (351,101) size 7x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=343.57] [y=93.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (344,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (344.49,140.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (357,101) size 7x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=349.40] [y=93.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (350,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (350.32,140.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (363,101) size 7x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=355.24] [y=93.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (356,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (356.15,140.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,169) size 6x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=161.00] [width=5.97] [height=55.00] + LayoutSVGText {text} at (50,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (50.99,223.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (63,169) size 14x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=55.97] [y=161.00] [width=12.36] [height=55.00] + LayoutSVGText {text} at (60,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (60.15,223.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (76,169) size 13x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=68.33] [y=161.00] [width=12.36] [height=55.00] + LayoutSVGText {text} at (72,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (72.51,223.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (88,169) size 11x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=80.69] [y=161.00] [width=9.72] [height=55.00] + LayoutSVGText {text} at (83,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (83.56,223.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (98,169) size 1x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=90.42] [y=161.00] [width=0.42] [height=55.00] + LayoutSVGText {text} at (88,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (88.63,223.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (98,169) size 2x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=90.84] [y=161.00] [width=0.42] [height=55.00] + LayoutSVGText {text} at (89,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (89.05,223.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (99,169) size 11x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=91.25] [y=161.00] [width=9.96] [height=55.00] + LayoutSVGText {text} at (94,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (94.23,223.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (109,169) size 11x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=101.21] [y=161.00] [width=9.96] [height=55.00] + LayoutSVGText {text} at (104,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (104.19,223.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (119,169) size 11x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=111.17] [y=161.00] [width=9.96] [height=55.00] + LayoutSVGText {text} at (114,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (114.15,223.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (208,177) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=169.00] [width=11.66] [height=40.00] + LayoutSVGText {text} at (203,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (203.83,216.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,177) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.66] [y=169.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (212,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (212.09,216.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,177) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.52] [y=169.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (216,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (216.95,216.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (229,177) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=221.38] [y=169.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (223,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (223.75,216.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (238,177) size 12x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=230.13] [y=169.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (233,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (233.65,216.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (249,177) size 13x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=241.17] [y=169.00] [width=12.30] [height=40.00] + LayoutSVGText {text} at (245,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (245.32,216.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (261,177) size 4x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=253.47] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (253,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (253.09,216.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (264,177) size 4x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=256.72] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (256,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (256.34,216.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (267,177) size 5x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=259.96] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (259,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (259.58,216.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (358,176) size 18x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=168.00] [width=17.56] [height=40.00] + LayoutSVGText {text} at (356,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (356.78,215.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (375,176) size 1x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=367.56] [y=168.00] [width=0.03] [height=40.00] + LayoutSVGText {text} at (365,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (365.57,215.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (375,176) size 1x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=367.59] [y=168.00] [width=0.03] [height=40.00] + LayoutSVGText {text} at (365,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (365.60,215.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (375,176) size 11x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=367.62] [y=168.00] [width=9.72] [height=40.00] + LayoutSVGText {text} at (370,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (370.48,215.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (385,176) size 11x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=377.34] [y=168.00] [width=9.72] [height=40.00] + LayoutSVGText {text} at (380,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (380.21,215.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (395,176) size 18x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=387.07] [y=168.00] [width=17.56] [height=40.00] + LayoutSVGText {text} at (393,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (393.85,215.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (412,176) size 1x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=404.63] [y=168.00] [width=0.02] [height=40.00] + LayoutSVGText {text} at (402,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (402.64,215.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (412,176) size 1x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=404.65] [y=168.00] [width=0.02] [height=40.00] + LayoutSVGText {text} at (402,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (402.66,215.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (412,176) size 1x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=404.67] [y=168.00] [width=0.02] [height=40.00] + LayoutSVGText {text} at (402,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (402.68,215.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,244) size 2x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=236.00] [width=1.45] [height=55.00] + LayoutSVGText {text} at (48,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (48.73,298.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (59,244) size 12x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=51.45] [y=236.00] [width=11.33] [height=55.00] + LayoutSVGText {text} at (55,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (55.12,298.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (70,244) size 13x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=62.78] [y=236.00] [width=11.33] [height=55.00] + LayoutSVGText {text} at (66,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (66.45,298.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (109,244) size 8x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=101.66] [y=236.00] [width=7.10] [height=55.00] + LayoutSVGText {text} at (103,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (103.21,298.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (102,244) size 8x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=94.56] [y=236.00] [width=7.10] [height=55.00] + LayoutSVGText {text} at (96,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (96.11,298.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (92,244) size 11x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=84.34] [y=236.00] [width=10.22] [height=55.00] + LayoutSVGText {text} at (87,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (87.45,298.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (82,244) size 11x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=74.11] [y=236.00] [width=10.22] [height=55.00] + LayoutSVGText {text} at (77,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (77.22,298.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (116,244) size 3x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=108.77] [y=236.00] [width=1.45] [height=55.00] + LayoutSVGText {text} at (107,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (107.49,298.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (118,244) size 12x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=110.22] [y=236.00] [width=11.33] [height=55.00] + LayoutSVGText {text} at (113,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (113.88,298.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (129,244) size 12x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=121.55] [y=236.00] [width=11.33] [height=55.00] + LayoutSVGText {text} at (125,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (125.21,298.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (208,252) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=244.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (203,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (203.52,291.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,252) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.04] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (211,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (211.95,291.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,252) size 7x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.87] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (217,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (217.78,291.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (258,252) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=250.24] [y=244.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (251,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (251.79,291.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (251,252) size 8x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=243.14] [y=244.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (244,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (244.69,291.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (240,252) size 12x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=232.92] [y=244.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (236,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (236.03,291.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (230,252) size 11x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=222.70] [y=244.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (225,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (225.81,291.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (265,252) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=257.35] [y=244.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (260,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (260.87,291.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (276,252) size 7x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=268.39] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (269,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (269.30,291.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (282,252) size 7x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=274.21] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (275,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (275.13,291.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (358,251) size 10x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=243.00] [width=9.40] [height=40.00] + LayoutSVGText {text} at (352,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (352.70,290.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (367,251) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=359.40] [y=243.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (359,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (359.83,290.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (372,251) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=364.26] [y=243.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (364,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (364.69,290.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (404,251) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=396.67] [y=243.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (398,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (398.22,290.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (397,251) size 8x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=389.57] [y=243.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (391,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (391.12,290.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (387,251) size 11x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=379.35] [y=243.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (382,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (382.46,290.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (377,251) size 11x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=369.12] [y=243.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (372,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (372.23,290.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (411,251) size 11x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=403.78] [y=243.00] [width=9.40] [height=40.00] + LayoutSVGText {text} at (406,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (406.48,290.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (421,251) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=413.17] [y=243.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (413,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (413.61,290.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (426,251) size 5x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=418.04] [y=243.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (418,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (418.47,290.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (58,319) size 16x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=311.00] [width=15.62] [height=55.00] + LayoutSVGText {text} at (55,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (55.81,373.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (73,319) size 50x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=65.62] [y=311.00] [width=49.07] [height=55.00] + LayoutSVGText {text} at (88,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (88.15,373.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (122,319) size 26x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=114.69] [y=311.00] [width=25.28] [height=55.00] + LayoutSVGText {text} at (125,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (125.32,373.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (147,319) size 27x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=139.96] [y=311.00] [width=25.28] [height=55.00] + LayoutSVGText {text} at (150,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (150.60,373.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (208,327) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=319.00] [width=11.66] [height=40.00] + LayoutSVGText {text} at (203,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (203.83,366.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,327) size 50x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.66] [y=319.00] [width=49.07] [height=40.00] + LayoutSVGText {text} at (234,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (234.19,366.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (268,327) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=260.72] [y=319.00] [width=5.06] [height=40.00] + LayoutSVGText {text} at (261,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (261.25,366.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (273,327) size 6x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=265.78] [y=319.00] [width=5.06] [height=40.00] + LayoutSVGText {text} at (266,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (266.31,366.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (358,326) size 5x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=318.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (350,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (350.43,365.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (362,326) size 50x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=354.86] [y=318.00] [width=49.07] [height=40.00] + LayoutSVGText {text} at (377,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (377.40,365.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (411,326) size 5x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=403.93] [y=318.00] [width=3.89] [height=40.00] + LayoutSVGText {text} at (403,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (403.87,365.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (415,326) size 5x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=407.82] [y=318.00] [width=3.89] [height=40.00] + LayoutSVGText {text} at (407,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (407.76,365.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGContainer {g} at (50,18) size 382x357 + LayoutSVGText {text} at (50,10) size 50x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 50x56 + chunk 1 text run 1 at (50.00,50.00) startOffset 0 endOffset 6 width 48.33: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (200,15) size 49x44 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x44 + chunk 1 text run 1 at (200.00,50.00) startOffset 0 endOffset 6 width 48.57: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (350,16) size 57x42 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 57x42 + chunk 1 text run 1 at (350.00,50.00) startOffset 0 endOffset 6 width 56.43: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (51,86) size 50x55 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x55 + chunk 1 text run 1 at (51.67,125.00) startOffset 0 endOffset 3 width 13.40: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (65.07,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (65.07,125.00) startOffset 0 endOffset 2 width 16.97: "b\x{30C}" + chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 17.96: "a" + chunk 1 text run 1 at (100.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (200,94) size 50x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 50x40 + chunk 1 text run 1 at (201.43,125.00) startOffset 0 endOffset 3 width 15.53: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 2 width 17.50: "b\x{30C}" + chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 15.53: "a" + chunk 1 text run 1 at (250.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (328,93) size 72x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 72x40 + chunk 1 text run 1 at (343.57,125.00) startOffset 0 endOffset 3 width 17.50: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (361.07,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (361.07,125.00) startOffset 0 endOffset 2 width 19.47: "b\x{30C}" + chunk 1 text run 1 at (380.53,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (380.53,125.00) startOffset 0 endOffset 1 width 19.47: "a" + chunk 1 text run 1 at (400.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (42,160) size 81x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 81x56 + chunk 1 text run 1 at (50.00,200.00) startOffset 0 endOffset 9 width 71.13: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (200,169) size 64x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 64x40 + chunk 1 text run 1 at (200.00,200.00) startOffset 0 endOffset 9 width 63.20: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (350,166) size 55x42 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 55x42 + chunk 1 text run 1 at (350.00,200.00) startOffset 0 endOffset 9 width 54.69: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (42,236) size 99x55 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 99x55 + chunk 1 text run 1 at (50.00,275.00) startOffset 0 endOffset 3 width 24.11: "ff\x{30C}" + chunk 1 text run 1 at (74.11,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (108.77,275.00) startOffset 0 endOffset 3 width 24.11: "ff\x{30C}" + LayoutSVGText {text} at (200,244) size 82x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 82x40 + chunk 1 text run 1 at (200.00,275.00) startOffset 0 endOffset 3 width 22.70: "ff\x{30C}" + chunk 1 text run 1 at (222.70,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (257.35,275.00) startOffset 0 endOffset 3 width 22.70: "ff\x{30C}" + LayoutSVGText {text} at (350,243) size 74x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 74x40 + chunk 1 text run 1 at (350.00,275.00) startOffset 0 endOffset 3 width 19.12: "ff\x{30C}" + chunk 1 text run 1 at (369.12,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (403.78,275.00) startOffset 0 endOffset 3 width 19.12: "ff\x{30C}" + LayoutSVGText {text} at (50,311) size 116x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 116x56 + chunk 1 text run 1 at (50.00,350.00) startOffset 0 endOffset 1 width 15.62: "\x{30C}" + chunk 1 text run 1 at (65.62,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (114.69,350.00) startOffset 0 endOffset 2 width 50.55: "i\x{333}" + LayoutSVGText {text} at (199,319) size 84x48 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 83x48 + chunk 1 text run 1 at (200.00,350.00) startOffset 0 endOffset 1 width 11.66: "\x{30C}" + chunk 1 text run 1 at (211.66,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (260.72,350.00) startOffset 0 endOffset 2 width 10.12: "i\x{333}" + LayoutSVGText {text} at (335,318) size 81x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 81x49 + chunk 1 text run 1 at (350.00,350.00) startOffset 0 endOffset 1 width 4.86: "\x{30C}" + chunk 1 text run 1 at (354.86,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (403.93,350.00) startOffset 0 endOffset 2 width 7.78: "i\x{333}" + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.png new file mode 100644 index 0000000..df0a4752 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.txt new file mode 100644 index 0000000..5a1ee7a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/combining-character-queries-expected.txt
@@ -0,0 +1,538 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x520 + LayoutBlockFlow {HTML} at (0,0) size 800x520 + LayoutBlockFlow {BODY} at (8,8) size 784x504 + LayoutSVGRoot {svg} at (50,18) size 391x365 + LayoutSVGContainer {g} at (56,19) size 385x364 + LayoutSVGRect {rect} at (58,19) size 18x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=11.00] [width=17.96] [height=55.00] + LayoutSVGText {text} at (56,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (56.98,73.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (75,19) size 10x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=67.96] [y=11.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (70,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (70.20,73.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (84,19) size 9x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=76.45] [y=11.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (78,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (78.69,73.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (92,19) size 6x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=84.93] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (85,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (85.16,73.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (97,19) size 5x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=89.40] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (89,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (89.63,73.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (101,19) size 6x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=93.86] [y=11.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (94,66) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (94.10,73.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (208,27) size 16x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=19.00] [width=15.53] [height=40.00] + LayoutSVGText {text} at (205,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (205.77,66.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (223,27) size 10x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=215.53] [y=19.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (217,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (217.91,66.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (232,27) size 10x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=224.28] [y=19.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (226,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (226.66,66.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (241,27) size 6x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=233.03] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (233,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (233.62,66.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (246,27) size 6x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=238.21] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (238,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (238.80,66.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (251,27) size 6x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=243.39] [y=19.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (243,59) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (243.98,66.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (358,26) size 20x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=18.00] [width=19.47] [height=40.00] + LayoutSVGText {text} at (357,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (357.73,65.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (377,26) size 11x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=369.47] [y=18.00] [width=9.73] [height=40.00] + LayoutSVGText {text} at (372,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (372.33,65.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (387,26) size 10x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=379.20] [y=18.00] [width=9.73] [height=40.00] + LayoutSVGText {text} at (382,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (382.06,65.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (396,26) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=388.93] [y=18.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (390,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (390.03,65.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (403,26) size 7x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=395.12] [y=18.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (396,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (396.22,65.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (409,26) size 7x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=401.32] [y=18.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (402,58) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (402.41,65.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=100.00] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (97,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (98.00,148.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (90,94) size 18x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=82.04] [y=86.00] [width=17.96] [height=55.00] + LayoutSVGText {text} at (89,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (89.02,148.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=82.04] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (80,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (80.04,148.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (73,94) size 9x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=65.07] [y=86.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (67,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (67.31,148.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (81,94) size 10x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=73.55] [y=86.00] [width=8.49] [height=55.00] + LayoutSVGText {text} at (75,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (75.80,148.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=65.07] [y=86.00] [width=0.00] [height=55.00] + LayoutSVGText {text} at (63,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (63.07,148.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (59,94) size 6x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=51.67] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (51,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (51.90,148.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (64,94) size 5x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=56.14] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (56,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (56.37,148.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (68,94) size 6x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=60.60] [y=86.00] [width=4.47] [height=55.00] + LayoutSVGText {text} at (60,141) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (60.84,148.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=250.00] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (248,134) size 4x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (248.00,141.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (242,102) size 16x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=234.47] [y=94.00] [width=15.53] [height=40.00] + LayoutSVGText {text} at (240,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (240.23,141.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=234.47] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (232,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (232.47,141.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (224,102) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=216.97] [y=94.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (219,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (219.34,141.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (233,102) size 10x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=225.72] [y=94.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (228,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (228.09,141.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=216.97] [y=94.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (214,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (214.97,141.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (209,102) size 6x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=201.43] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (202,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (202.02,141.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (214,102) size 6x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=206.61] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (207,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (207.20,141.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (219,102) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.79] [y=94.00] [width=5.18] [height=40.00] + LayoutSVGText {text} at (212,134) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (212.38,141.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=400.00] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (398,133) size 4x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (398.00,140.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (388,101) size 20x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=380.53] [y=93.00] [width=19.47] [height=40.00] + LayoutSVGText {text} at (388,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (388.27,140.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=380.53] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (378,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (378.53,140.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (368,101) size 11x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=360.73] [y=93.00] [width=9.90] [height=40.00] + LayoutSVGText {text} at (363,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (363.68,140.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (378,101) size 11x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=370.63] [y=93.00] [width=9.90] [height=40.00] + LayoutSVGText {text} at (373,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (373.58,140.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=360.73] [y=93.00] [width=0.00] [height=40.00] + LayoutSVGText {text} at (358,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (358.73,140.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (350,101) size 7x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=342.15] [y=93.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (343,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (343.25,140.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (356,101) size 7x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=348.34] [y=93.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (349,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (349.44,140.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (362,101) size 7x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=354.54] [y=93.00] [width=6.19] [height=40.00] + LayoutSVGText {text} at (355,133) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (355.63,140.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,169) size 6x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=161.00] [width=5.97] [height=55.00] + LayoutSVGText {text} at (50,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (50.99,223.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (63,169) size 18x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=55.97] [y=161.00] [width=16.27] [height=55.00] + LayoutSVGText {text} at (62,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (62.11,223.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (80,169) size 17x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=72.24] [y=161.00] [width=16.27] [height=55.00] + LayoutSVGText {text} at (78,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (78.37,223.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (96,169) size 11x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=88.50] [y=161.00] [width=9.72] [height=55.00] + LayoutSVGText {text} at (91,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (91.37,223.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (106,169) size 1x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=98.23] [y=161.00] [width=0.42] [height=55.00] + LayoutSVGText {text} at (96,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (96.44,223.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (106,169) size 2x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=98.65] [y=161.00] [width=0.42] [height=55.00] + LayoutSVGText {text} at (96,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (96.86,223.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (107,169) size 13x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=99.06] [y=161.00] [width=12.56] [height=55.00] + LayoutSVGText {text} at (103,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (103.35,223.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (119,169) size 14x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=111.63] [y=161.00] [width=12.56] [height=55.00] + LayoutSVGText {text} at (115,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (115.91,223.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (132,169) size 13x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=124.19] [y=161.00] [width=12.56] [height=55.00] + LayoutSVGText {text} at (128,216) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (128.47,223.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (208,177) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=169.00] [width=11.66] [height=40.00] + LayoutSVGText {text} at (203,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (203.83,216.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,177) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.66] [y=169.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (212,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (212.09,216.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,177) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.52] [y=169.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (216,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (216.95,216.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (229,177) size 10x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=221.38] [y=169.00] [width=8.75] [height=40.00] + LayoutSVGText {text} at (223,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (223.75,216.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (238,177) size 12x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=230.13] [y=169.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (233,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (233.65,216.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (249,177) size 13x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=241.17] [y=169.00] [width=12.30] [height=40.00] + LayoutSVGText {text} at (245,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (245.32,216.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (261,177) size 4x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=253.47] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (253,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (253.09,216.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (264,177) size 4x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=256.72] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (256,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (256.34,216.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (267,177) size 5x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=259.96] [y=169.00] [width=3.24] [height=40.00] + LayoutSVGText {text} at (259,209) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (259.58,216.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (358,176) size 10x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=168.00] [width=9.72] [height=40.00] + LayoutSVGText {text} at (352,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (352.86,215.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (367,176) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=359.72] [y=168.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (360,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (360.16,215.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (372,176) size 6x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=364.59] [y=168.00] [width=4.86] [height=40.00] + LayoutSVGText {text} at (365,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (365.02,215.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (377,176) size 11x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=369.45] [y=168.00] [width=9.72] [height=40.00] + LayoutSVGText {text} at (372,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (372.31,215.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (387,176) size 10x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=379.17] [y=168.00] [width=9.11] [height=40.00] + LayoutSVGText {text} at (381,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (381.73,215.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (396,176) size 11x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=388.28] [y=168.00] [width=9.74] [height=40.00] + LayoutSVGText {text} at (391,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (391.15,215.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (406,176) size 5x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=398.02] [y=168.00] [width=4.94] [height=40.00] + LayoutSVGText {text} at (398,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (398.49,215.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (410,176) size 6x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=402.96] [y=168.00] [width=4.94] [height=40.00] + LayoutSVGText {text} at (403,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (403.43,215.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (415,176) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=407.90] [y=168.00] [width=4.94] [height=40.00] + LayoutSVGText {text} at (408,208) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (408.37,215.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,244) size 2x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=236.00] [width=1.45] [height=55.00] + LayoutSVGText {text} at (48,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (48.73,298.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (59,244) size 16x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=51.45] [y=236.00] [width=15.24] [height=55.00] + LayoutSVGText {text} at (57,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (57.07,298.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (74,244) size 16x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=66.69] [y=236.00] [width=15.24] [height=55.00] + LayoutSVGText {text} at (72,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (72.31,298.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (117,244) size 8x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=109.47] [y=236.00] [width=7.10] [height=55.00] + LayoutSVGText {text} at (111,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (111.02,298.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (110,244) size 8x55 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=102.37] [y=236.00] [width=7.10] [height=55.00] + LayoutSVGText {text} at (103,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (103.92,298.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (100,244) size 11x55 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=92.15] [y=236.00] [width=10.22] [height=55.00] + LayoutSVGText {text} at (95,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (95.26,298.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (89,244) size 12x55 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=81.92] [y=236.00] [width=10.22] [height=55.00] + LayoutSVGText {text} at (85,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (85.03,298.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (124,244) size 3x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=116.58] [y=236.00] [width=1.45] [height=55.00] + LayoutSVGText {text} at (115,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (115.30,298.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (126,244) size 16x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=118.03] [y=236.00] [width=15.24] [height=55.00] + LayoutSVGText {text} at (123,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (123.65,298.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (141,244) size 16x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=133.26] [y=236.00] [width=15.24] [height=55.00] + LayoutSVGText {text} at (138,291) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (138.88,298.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (208,252) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=244.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (203,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (203.52,291.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,252) size 6x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.04] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (211,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (211.95,291.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,252) size 7x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.87] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (217,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (217.78,291.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (258,252) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=250.24] [y=244.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (251,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (251.79,291.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (251,252) size 8x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=243.14] [y=244.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (244,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (244.69,291.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (240,252) size 12x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=232.92] [y=244.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (236,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (236.03,291.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (230,252) size 11x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=222.70] [y=244.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (225,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (225.81,291.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (265,252) size 12x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=257.35] [y=244.00] [width=11.04] [height=40.00] + LayoutSVGText {text} at (260,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (260.87,291.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (276,252) size 7x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=268.39] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (269,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (269.30,291.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (282,252) size 7x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=274.21] [y=244.00] [width=5.83] [height=40.00] + LayoutSVGText {text} at (275,284) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (275.13,291.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (358,251) size 10x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=243.00] [width=9.40] [height=40.00] + LayoutSVGText {text} at (352,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (352.70,290.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (367,251) size 8x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=359.40] [y=243.00] [width=7.27] [height=40.00] + LayoutSVGText {text} at (361,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (361.04,290.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (374,251) size 8x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=366.67] [y=243.00] [width=7.27] [height=40.00] + LayoutSVGText {text} at (368,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (368.31,290.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (409,251) size 8x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=401.49] [y=243.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (403,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (403.04,290.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (402,251) size 8x40 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=394.39] [y=243.00] [width=7.10] [height=40.00] + LayoutSVGText {text} at (395,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (395.94,290.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (392,251) size 11x40 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=384.16] [y=243.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (387,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (387.28,290.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (381,251) size 12x40 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=373.94] [y=243.00] [width=10.22] [height=40.00] + LayoutSVGText {text} at (377,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (377.05,290.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (416,251) size 10x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=408.59] [y=243.00] [width=9.40] [height=40.00] + LayoutSVGText {text} at (411,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (411.29,290.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (425,251) size 9x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=417.99] [y=243.00] [width=7.27] [height=40.00] + LayoutSVGText {text} at (419,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (419.63,290.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (433,251) size 8x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=425.27] [y=243.00] [width=7.27] [height=40.00] + LayoutSVGText {text} at (426,283) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (426.90,290.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (58,319) size 16x55 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=311.00] [width=15.62] [height=55.00] + LayoutSVGText {text} at (55,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (55.81,373.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (73,319) size 50x55 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=65.62] [y=311.00] [width=49.07] [height=55.00] + LayoutSVGText {text} at (88,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (88.15,373.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (122,319) size 26x55 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=114.69] [y=311.00] [width=25.28] [height=55.00] + LayoutSVGText {text} at (125,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (125.32,373.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (147,319) size 27x55 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=139.96] [y=311.00] [width=25.28] [height=55.00] + LayoutSVGText {text} at (150,366) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (150.60,373.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (208,327) size 13x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=319.00] [width=12.24] [height=40.00] + LayoutSVGText {text} at (204,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (204.12,366.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (220,327) size 50x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=212.24] [y=319.00] [width=49.07] [height=40.00] + LayoutSVGText {text} at (234,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (234.77,366.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (269,327) size 12x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=261.30] [y=319.00] [width=10.75] [height=40.00] + LayoutSVGText {text} at (264,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (264.68,366.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (280,327) size 11x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=272.05] [y=319.00] [width=10.75] [height=40.00] + LayoutSVGText {text} at (275,359) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (275.43,366.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (358,326) size 15x40 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=318.00] [width=14.83] [height=40.00] + LayoutSVGText {text} at (355,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (355.42,365.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (372,326) size 50x40 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=364.83] [y=318.00] [width=49.07] [height=40.00] + LayoutSVGText {text} at (387,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (387.37,365.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (421,326) size 9x40 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=413.90] [y=318.00] [width=7.88] [height=40.00] + LayoutSVGText {text} at (415,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (415.84,365.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (429,326) size 9x40 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=421.78] [y=318.00] [width=7.88] [height=40.00] + LayoutSVGText {text} at (423,358) size 5x9 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x9 + chunk 1 (middle anchor) text run 1 at (423.72,365.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGContainer {g} at (50,18) size 391x357 + LayoutSVGText {text} at (50,10) size 50x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 50x56 + chunk 1 text run 1 at (50.00,50.00) startOffset 0 endOffset 6 width 48.33: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (200,15) size 49x44 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x44 + chunk 1 text run 1 at (200.00,50.00) startOffset 0 endOffset 6 width 48.57: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (350,16) size 58x42 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 58x42 + chunk 1 text run 1 at (350.00,50.00) startOffset 0 endOffset 6 width 57.51: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (51,79) size 50x62 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,6) size 49x62 + chunk 1 text run 1 at (51.67,125.00) startOffset 0 endOffset 3 width 13.40: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (65.07,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (65.07,125.00) startOffset 0 endOffset 2 width 16.97: "b\x{30C}" + chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (82.04,125.00) startOffset 0 endOffset 1 width 17.96: "a" + chunk 1 text run 1 at (100.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (200,90) size 50x44 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 50x44 + chunk 1 text run 1 at (201.43,125.00) startOffset 0 endOffset 3 width 15.53: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 2 width 17.50: "b\x{30C}" + chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 15.53: "a" + chunk 1 text run 1 at (250.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (327,91) size 73x42 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 73x42 + chunk 1 text run 1 at (342.15,125.00) startOffset 0 endOffset 3 width 18.58: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (360.73,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (360.73,125.00) startOffset 0 endOffset 2 width 19.81: "b\x{30C}" + chunk 1 text run 1 at (380.53,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (380.53,125.00) startOffset 0 endOffset 1 width 19.47: "a" + chunk 1 text run 1 at (400.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (42,160) size 95x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 95x56 + chunk 1 text run 1 at (50.00,200.00) startOffset 0 endOffset 9 width 86.75: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (200,169) size 64x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 64x40 + chunk 1 text run 1 at (200.00,200.00) startOffset 0 endOffset 9 width 63.20: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (350,168) size 63x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 63x40 + chunk 1 text run 1 at (350.00,200.00) startOffset 0 endOffset 9 width 62.84: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (42,236) size 107x55 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 107x55 + chunk 1 text run 1 at (50.00,275.00) startOffset 0 endOffset 3 width 31.92: "ff\x{30C}" + chunk 1 text run 1 at (81.92,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (116.58,275.00) startOffset 0 endOffset 3 width 31.92: "ff\x{30C}" + LayoutSVGText {text} at (200,244) size 82x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 82x40 + chunk 1 text run 1 at (200.00,275.00) startOffset 0 endOffset 3 width 22.70: "ff\x{30C}" + chunk 1 text run 1 at (222.70,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (257.35,275.00) startOffset 0 endOffset 3 width 22.70: "ff\x{30C}" + LayoutSVGText {text} at (350,243) size 83x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 83x40 + chunk 1 text run 1 at (350.00,275.00) startOffset 0 endOffset 3 width 23.94: "ff\x{30C}" + chunk 1 text run 1 at (373.94,275.00) startOffset 0 endOffset 4 width 34.65 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (408.59,275.00) startOffset 0 endOffset 3 width 23.94: "ff\x{30C}" + LayoutSVGText {text} at (50,311) size 116x56 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 116x56 + chunk 1 text run 1 at (50.00,350.00) startOffset 0 endOffset 1 width 15.62: "\x{30C}" + chunk 1 text run 1 at (65.62,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (114.69,350.00) startOffset 0 endOffset 2 width 50.55: "i\x{333}" + LayoutSVGText {text} at (199,319) size 84x48 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 84x48 + chunk 1 text run 1 at (200.00,350.00) startOffset 0 endOffset 1 width 12.24: "\x{30C}" + chunk 1 text run 1 at (212.24,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (261.30,350.00) startOffset 0 endOffset 2 width 21.50: "i\x{333}" + LayoutSVGText {text} at (335,318) size 95x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 95x49 + chunk 1 text run 1 at (350.00,350.00) startOffset 0 endOffset 1 width 14.83: "\x{30C}" + chunk 1 text run 1 at (364.83,350.00) startOffset 0 endOffset 1 width 49.07 RTL: "\x{FDB0}" + chunk 1 text run 1 at (413.90,350.00) startOffset 0 endOffset 2 width 15.76: "i\x{333}" + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/combining-character-queries-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/combining-character-queries-expected.png new file mode 100644 index 0000000..8cd1faa8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/combining-character-queries-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/combining-character-queries-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/text/combining-character-queries-expected.txt new file mode 100644 index 0000000..918ad243 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/combining-character-queries-expected.txt
@@ -0,0 +1,538 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x520 + LayoutBlockFlow {HTML} at (0,0) size 800x520 + LayoutBlockFlow {BODY} at (8,8) size 784x504 + LayoutSVGRoot {svg} at (53,19) size 384x358 + LayoutSVGContainer {g} at (57,19) size 375x358 + LayoutSVGRect {rect} at (58,19) size 16x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=11.00] [width=15.53] [height=49.00] + LayoutSVGText {text} at (55,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (55.77,67.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (73,19) size 10x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=65.53] [y=11.00] [width=8.75] [height=49.00] + LayoutSVGText {text} at (67,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (67.91,67.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (82,19) size 10x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=74.28] [y=11.00] [width=8.75] [height=49.00] + LayoutSVGText {text} at (76,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (76.66,67.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (91,19) size 6x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=83.03] [y=11.00] [width=5.18] [height=49.00] + LayoutSVGText {text} at (83,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (83.62,67.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (96,19) size 6x49 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=88.21] [y=11.00] [width=5.18] [height=49.00] + LayoutSVGText {text} at (88,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (88.80,67.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (101,19) size 6x49 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=93.39] [y=11.00] [width=5.18] [height=49.00] + LayoutSVGText {text} at (93,59) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (93.98,67.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (208,27) size 16x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=19.00] [width=15.53] [height=39.00] + LayoutSVGText {text} at (205,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (205.77,65.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (223,27) size 10x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=215.53] [y=19.00] [width=8.75] [height=39.00] + LayoutSVGText {text} at (217,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (217.91,65.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (232,27) size 10x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=224.28] [y=19.00] [width=8.75] [height=39.00] + LayoutSVGText {text} at (226,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (226.66,65.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (241,27) size 6x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=233.03] [y=19.00] [width=5.18] [height=39.00] + LayoutSVGText {text} at (233,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (233.62,65.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (246,27) size 6x39 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=238.21] [y=19.00] [width=5.18] [height=39.00] + LayoutSVGText {text} at (238,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (238.80,65.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (251,27) size 6x39 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=243.39] [y=19.00] [width=5.18] [height=39.00] + LayoutSVGText {text} at (243,57) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (243.98,65.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (358,26) size 20x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=18.00] [width=19.47] [height=39.00] + LayoutSVGText {text} at (357,56) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (357.73,64.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (377,26) size 11x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=369.47] [y=18.00] [width=9.73] [height=39.00] + LayoutSVGText {text} at (372,56) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (372.33,64.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (387,26) size 10x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=379.20] [y=18.00] [width=9.73] [height=39.00] + LayoutSVGText {text} at (382,56) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (382.06,64.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (396,26) size 7x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=388.93] [y=18.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (389,56) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (389.85,64.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (402,26) size 7x39 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=394.76] [y=18.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (395,56) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (395.68,64.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (408,26) size 7x39 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=400.60] [y=18.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (401,56) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (401.51,64.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=100.00] [y=86.00] [width=0.00] [height=49.00] + LayoutSVGText {text} at (98,134) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (98.00,142.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (90,94) size 18x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=82.09] [y=86.00] [width=17.91] [height=49.00] + LayoutSVGText {text} at (89,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (89.04,142.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=82.09] [y=86.00] [width=0.00] [height=49.00] + LayoutSVGText {text} at (80,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (80.09,142.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (72,94) size 10x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=64.59] [y=86.00] [width=8.75] [height=49.00] + LayoutSVGText {text} at (66,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (66.96,142.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (81,94) size 10x49 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=73.34] [y=86.00] [width=8.75] [height=49.00] + LayoutSVGText {text} at (75,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (75.71,142.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=64.59] [y=86.00] [width=0.00] [height=49.00] + LayoutSVGText {text} at (62,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (62.59,142.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (57,94) size 6x49 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=49.06] [y=86.00] [width=5.18] [height=49.00] + LayoutSVGText {text} at (49,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (49.64,142.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (62,94) size 6x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=54.23] [y=86.00] [width=5.18] [height=49.00] + LayoutSVGText {text} at (54,134) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (54.82,142.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (67,94) size 6x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=59.41] [y=86.00] [width=5.18] [height=49.00] + LayoutSVGText {text} at (60,134) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (60.00,142.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=250.00] [y=94.00] [width=0.00] [height=39.00] + LayoutSVGText {text} at (248,132) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (248.00,140.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (242,102) size 16x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=234.47] [y=94.00] [width=15.53] [height=39.00] + LayoutSVGText {text} at (240,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (240.23,140.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=234.47] [y=94.00] [width=0.00] [height=39.00] + LayoutSVGText {text} at (232,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (232.47,140.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (224,102) size 10x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=216.97] [y=94.00] [width=8.75] [height=39.00] + LayoutSVGText {text} at (219,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (219.34,140.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (233,102) size 10x39 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=225.72] [y=94.00] [width=8.75] [height=39.00] + LayoutSVGText {text} at (228,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (228.09,140.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=216.97] [y=94.00] [width=0.00] [height=39.00] + LayoutSVGText {text} at (214,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (214.97,140.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (209,102) size 6x39 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=201.43] [y=94.00] [width=5.18] [height=39.00] + LayoutSVGText {text} at (202,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (202.02,140.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (214,102) size 6x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=206.61] [y=94.00] [width=5.18] [height=39.00] + LayoutSVGText {text} at (207,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (207.20,140.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (219,102) size 6x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.79] [y=94.00] [width=5.18] [height=39.00] + LayoutSVGText {text} at (212,132) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (212.38,140.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=400.00] [y=93.00] [width=0.00] [height=39.00] + LayoutSVGText {text} at (398,131) size 4x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (398.00,139.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (388,101) size 20x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=380.53] [y=93.00] [width=19.47] [height=39.00] + LayoutSVGText {text} at (388,131) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (388.27,139.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=380.53] [y=93.00] [width=0.00] [height=39.00] + LayoutSVGText {text} at (378,131) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (378.53,139.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (369,101) size 10x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=361.07] [y=93.00] [width=9.73] [height=39.00] + LayoutSVGText {text} at (363,131) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (363.94,139.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (378,101) size 11x39 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=370.80] [y=93.00] [width=9.73] [height=39.00] + LayoutSVGText {text} at (373,131) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (373.67,139.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (8,8) size 0x0 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=361.07] [y=93.00] [width=0.00] [height=39.00] + LayoutSVGText {text} at (359,131) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (359.07,139.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (351,101) size 7x39 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=343.57] [y=93.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (344,131) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (344.49,139.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (357,101) size 7x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=349.40] [y=93.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (350,131) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (350.32,139.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (363,101) size 7x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=355.24] [y=93.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (356,131) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (356.15,139.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,169) size 12x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=161.00] [width=11.66] [height=49.00] + LayoutSVGText {text} at (53,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (53.83,217.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (69,169) size 6x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=61.66] [y=161.00] [width=4.86] [height=49.00] + LayoutSVGText {text} at (62,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (62.09,217.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (74,169) size 6x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=66.52] [y=161.00] [width=4.86] [height=49.00] + LayoutSVGText {text} at (66,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (66.95,217.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (79,169) size 11x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=71.38] [y=161.00] [width=10.46] [height=49.00] + LayoutSVGText {text} at (74,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (74.61,217.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (89,169) size 12x49 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=81.84] [y=161.00] [width=11.02] [height=49.00] + LayoutSVGText {text} at (85,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (85.35,217.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (100,169) size 13x49 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=92.86] [y=161.00] [width=11.66] [height=49.00] + LayoutSVGText {text} at (96,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (96.69,217.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (112,169) size 4x49 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=104.52] [y=161.00] [width=3.24] [height=49.00] + LayoutSVGText {text} at (104,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (104.14,217.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (115,169) size 4x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=107.76] [y=161.00] [width=3.24] [height=49.00] + LayoutSVGText {text} at (107,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (107.38,217.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (118,169) size 5x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=111.00] [y=161.00] [width=3.24] [height=49.00] + LayoutSVGText {text} at (110,209) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (110.62,217.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (208,177) size 12x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=169.00] [width=11.66] [height=39.00] + LayoutSVGText {text} at (203,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (203.83,215.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,177) size 6x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.66] [y=169.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (212,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (212.09,215.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,177) size 6x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.52] [y=169.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (216,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (216.95,215.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (229,177) size 10x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=221.38] [y=169.00] [width=8.75] [height=39.00] + LayoutSVGText {text} at (223,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (223.75,215.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (238,177) size 12x39 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=230.13] [y=169.00] [width=11.02] [height=39.00] + LayoutSVGText {text} at (233,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (233.64,215.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (249,177) size 12x39 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=241.15] [y=169.00] [width=11.66] [height=39.00] + LayoutSVGText {text} at (244,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (244.98,215.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (260,177) size 5x39 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=252.81] [y=169.00] [width=3.24] [height=39.00] + LayoutSVGText {text} at (252,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (252.43,215.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (264,177) size 4x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=256.05] [y=169.00] [width=3.24] [height=39.00] + LayoutSVGText {text} at (255,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (255.67,215.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (267,177) size 4x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=259.29] [y=169.00] [width=3.24] [height=39.00] + LayoutSVGText {text} at (258,207) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (258.91,215.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (358,176) size 10x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=168.00] [width=9.72] [height=39.00] + LayoutSVGText {text} at (352,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (352.86,214.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (367,176) size 5x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=359.72] [y=168.00] [width=3.89] [height=39.00] + LayoutSVGText {text} at (359,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (359.67,214.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (371,176) size 5x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=363.61] [y=168.00] [width=3.89] [height=39.00] + LayoutSVGText {text} at (363,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (363.56,214.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (375,176) size 11x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=367.50] [y=168.00] [width=9.72] [height=39.00] + LayoutSVGText {text} at (370,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (370.36,214.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (385,176) size 10x39 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=377.22] [y=168.00] [width=9.09] [height=39.00] + LayoutSVGText {text} at (379,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (379.77,214.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (394,176) size 11x39 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=386.32] [y=168.00] [width=9.72] [height=39.00] + LayoutSVGText {text} at (389,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (389.18,214.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (404,176) size 3x39 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=396.04] [y=168.00] [width=2.59] [height=39.00] + LayoutSVGText {text} at (395,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (395.34,214.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (406,176) size 4x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=398.63] [y=168.00] [width=2.59] [height=39.00] + LayoutSVGText {text} at (397,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (397.93,214.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (409,176) size 3x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=401.22] [y=168.00] [width=2.59] [height=39.00] + LayoutSVGText {text} at (400,206) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (400.52,214.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (58,244) size 12x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=236.00] [width=11.02] [height=49.00] + LayoutSVGText {text} at (53,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (53.51,292.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (69,244) size 6x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=61.02] [y=236.00] [width=5.83] [height=49.00] + LayoutSVGText {text} at (61,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (61.94,292.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (74,244) size 7x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=66.85] [y=236.00] [width=5.83] [height=49.00] + LayoutSVGText {text} at (67,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (67.76,292.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (108,244) size 9x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=100.94] [y=236.00] [width=7.25] [height=49.00] + LayoutSVGText {text} at (102,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (102.57,292.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (101,244) size 8x49 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=93.70] [y=236.00] [width=7.25] [height=49.00] + LayoutSVGText {text} at (95,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (95.32,292.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (91,244) size 11x49 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=83.19] [y=236.00] [width=10.51] [height=49.00] + LayoutSVGText {text} at (86,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (86.44,292.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (80,244) size 12x49 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=72.68] [y=236.00] [width=10.51] [height=49.00] + LayoutSVGText {text} at (75,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (75.93,292.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (116,244) size 12x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=108.19] [y=236.00] [width=11.02] [height=49.00] + LayoutSVGText {text} at (111,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (111.70,292.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (127,244) size 7x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=119.21] [y=236.00] [width=5.83] [height=49.00] + LayoutSVGText {text} at (120,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (120.13,292.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (133,244) size 6x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=125.04] [y=236.00] [width=5.83] [height=49.00] + LayoutSVGText {text} at (125,284) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (125.96,292.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (208,252) size 12x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=244.00] [width=11.02] [height=39.00] + LayoutSVGText {text} at (203,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (203.51,290.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (219,252) size 6x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=211.02] [y=244.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (211,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (211.94,290.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (224,252) size 7x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=216.85] [y=244.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (217,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (217.76,290.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (258,252) size 9x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=250.94] [y=244.00] [width=7.25] [height=39.00] + LayoutSVGText {text} at (252,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (252.57,290.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (251,252) size 8x39 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=243.70] [y=244.00] [width=7.25] [height=39.00] + LayoutSVGText {text} at (245,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (245.32,290.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (241,252) size 11x39 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=233.19] [y=244.00] [width=10.51] [height=39.00] + LayoutSVGText {text} at (236,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (236.44,290.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (230,252) size 12x39 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=222.68] [y=244.00] [width=10.51] [height=39.00] + LayoutSVGText {text} at (225,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (225.93,290.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (266,252) size 12x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=258.19] [y=244.00] [width=11.02] [height=39.00] + LayoutSVGText {text} at (261,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (261.70,290.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (277,252) size 7x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=269.21] [y=244.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (270,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (270.13,290.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (283,252) size 6x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=275.04] [y=244.00] [width=5.83] [height=39.00] + LayoutSVGText {text} at (275,282) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (275.96,290.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (358,251) size 10x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=243.00] [width=9.09] [height=39.00] + LayoutSVGText {text} at (352,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (352.55,289.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (367,251) size 5x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=359.09] [y=243.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (359,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (359.52,289.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (371,251) size 6x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=363.95] [y=243.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (364,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (364.38,289.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (405,251) size 8x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=397.08] [y=243.00] [width=7.25] [height=39.00] + LayoutSVGText {text} at (398,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (398.71,289.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (397,251) size 9x39 [fill={[type=SOLID] [color=#0000FF] [opacity=0.30]}] [x=389.84] [y=243.00] [width=7.25] [height=39.00] + LayoutSVGText {text} at (391,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (391.46,289.00) startOffset 0 endOffset 1 width 4.00: "4" + LayoutSVGRect {rect} at (387,251) size 11x39 [fill={[type=SOLID] [color=#4B0082] [opacity=0.30]}] [x=379.33] [y=243.00] [width=10.51] [height=39.00] + LayoutSVGText {text} at (382,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (382.58,289.00) startOffset 0 endOffset 1 width 4.00: "5" + LayoutSVGRect {rect} at (376,251) size 12x39 [fill={[type=SOLID] [color=#EE82EE] [opacity=0.30]}] [x=368.82] [y=243.00] [width=10.51] [height=39.00] + LayoutSVGText {text} at (372,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (372.07,289.00) startOffset 0 endOffset 1 width 4.00: "6" + LayoutSVGRect {rect} at (412,251) size 10x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=404.33] [y=243.00] [width=9.09] [height=39.00] + LayoutSVGText {text} at (406,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (406.87,289.00) startOffset 0 endOffset 1 width 4.00: "7" + LayoutSVGRect {rect} at (421,251) size 6x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=413.42] [y=243.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (413,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (413.85,289.00) startOffset 0 endOffset 1 width 4.00: "8" + LayoutSVGRect {rect} at (426,251) size 6x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=418.28] [y=243.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (418,281) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (418.71,289.00) startOffset 0 endOffset 1 width 4.00: "9" + LayoutSVGRect {rect} at (58,319) size 6x49 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=50.00] [y=311.00] [width=5.23] [height=49.00] + LayoutSVGText {text} at (50,359) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (50.61,367.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (63,319) size 27x49 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=55.23] [y=311.00] [width=26.25] [height=49.00] + LayoutSVGText {text} at (66,359) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (66.35,367.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (89,319) size 6x49 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=81.48] [y=311.00] [width=4.86] [height=49.00] + LayoutSVGText {text} at (81,359) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (81.91,367.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (94,319) size 6x49 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=86.34] [y=311.00] [width=4.86] [height=49.00] + LayoutSVGText {text} at (86,359) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (86.77,367.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (208,327) size 5x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=200.00] [y=319.00] [width=4.38] [height=39.00] + LayoutSVGText {text} at (200,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (200.19,365.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (212,327) size 27x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=204.38] [y=319.00] [width=26.25] [height=39.00] + LayoutSVGText {text} at (215,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (215.50,365.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (238,327) size 6x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=230.63] [y=319.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (231,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (231.06,365.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (243,327) size 6x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=235.49] [y=319.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (235,357) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (235.92,365.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGRect {rect} at (358,326) size 5x39 [fill={[type=SOLID] [color=#FF0000] [opacity=0.30]}] [x=350.00] [y=318.00] [width=4.86] [height=39.00] + LayoutSVGText {text} at (350,356) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (350.43,364.00) startOffset 0 endOffset 1 width 4.00: "0" + LayoutSVGRect {rect} at (362,326) size 28x39 [fill={[type=SOLID] [color=#FFA500] [opacity=0.30]}] [x=354.86] [y=318.00] [width=26.25] [height=39.00] + LayoutSVGText {text} at (365,356) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (365.99,364.00) startOffset 0 endOffset 1 width 4.00: "1" + LayoutSVGRect {rect} at (389,326) size 4x39 [fill={[type=SOLID] [color=#FFFF00] [opacity=0.30]}] [x=381.11] [y=318.00] [width=3.89] [height=39.00] + LayoutSVGText {text} at (381,356) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (381.06,364.00) startOffset 0 endOffset 1 width 4.00: "2" + LayoutSVGRect {rect} at (393,326) size 4x39 [fill={[type=SOLID] [color=#008000] [opacity=0.30]}] [x=385.00] [y=318.00] [width=3.89] [height=39.00] + LayoutSVGText {text} at (384,356) size 5x10 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 4x10 + chunk 1 (middle anchor) text run 1 at (384.94,364.00) startOffset 0 endOffset 1 width 4.00: "3" + LayoutSVGContainer {g} at (53,19) size 384x349 + LayoutSVGText {text} at (50,11) size 49x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x49 + chunk 1 text run 1 at (50.00,50.00) startOffset 0 endOffset 6 width 48.57: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (200,17) size 49x41 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x41 + chunk 1 text run 1 at (200.00,50.00) startOffset 0 endOffset 6 width 48.57: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (350,18) size 57x39 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 57x39 + chunk 1 text run 1 at (350.00,50.00) startOffset 0 endOffset 6 width 56.43: "ab\x{30C}c\x{30C}\x{30C}" + LayoutSVGText {text} at (49,86) size 51x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 51x49 + chunk 1 text run 1 at (49.06,125.00) startOffset 0 endOffset 3 width 15.53: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (64.59,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (64.59,125.00) startOffset 0 endOffset 2 width 17.50: "b\x{30C}" + chunk 1 text run 1 at (82.09,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (82.09,125.00) startOffset 0 endOffset 1 width 17.91: "a" + chunk 1 text run 1 at (100.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (201,94) size 49x39 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 49x39 + chunk 1 text run 1 at (201.43,125.00) startOffset 0 endOffset 3 width 15.53: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (216.97,125.00) startOffset 0 endOffset 2 width 17.50: "b\x{30C}" + chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (234.47,125.00) startOffset 0 endOffset 1 width 15.53: "a" + chunk 1 text run 1 at (250.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (343,93) size 57x39 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 57x39 + chunk 1 text run 1 at (343.57,125.00) startOffset 0 endOffset 3 width 17.50: "c\x{30C}\x{30C}" + chunk 1 text run 1 at (361.07,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (361.07,125.00) startOffset 0 endOffset 2 width 19.47: "b\x{30C}" + chunk 1 text run 1 at (380.53,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + chunk 1 text run 1 at (380.53,125.00) startOffset 0 endOffset 1 width 19.47: "a" + chunk 1 text run 1 at (400.00,125.00) startOffset 0 endOffset 1 width 0.00 RTL: "\x{200F}" + LayoutSVGText {text} at (50,161) size 70x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 70x49 + chunk 1 text run 1 at (50.00,200.00) startOffset 0 endOffset 9 width 64.24: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (200,169) size 68x39 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 68x39 + chunk 1 text run 1 at (200.00,200.00) startOffset 0 endOffset 9 width 62.53: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (350,168) size 60x39 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 60x39 + chunk 1 text run 1 at (350.00,200.00) startOffset 0 endOffset 9 width 53.82: "fi\x{30C} ffi\x{30C}\x{30C}" + LayoutSVGText {text} at (50,236) size 86x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 86x49 + chunk 1 text run 1 at (50.00,275.00) startOffset 0 endOffset 3 width 22.68: "ff\x{30C}" + chunk 1 text run 1 at (72.68,275.00) startOffset 0 endOffset 4 width 35.51 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (108.19,275.00) startOffset 0 endOffset 3 width 22.68: "ff\x{30C}" + LayoutSVGText {text} at (200,244) size 86x39 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 86x39 + chunk 1 text run 1 at (200.00,275.00) startOffset 0 endOffset 3 width 22.68: "ff\x{30C}" + chunk 1 text run 1 at (222.68,275.00) startOffset 0 endOffset 4 width 35.51 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (258.19,275.00) startOffset 0 endOffset 3 width 22.68: "ff\x{30C}" + LayoutSVGText {text} at (350,243) size 79x39 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 79x39 + chunk 1 text run 1 at (350.00,275.00) startOffset 0 endOffset 3 width 18.82: "ff\x{30C}" + chunk 1 text run 1 at (368.82,275.00) startOffset 0 endOffset 4 width 35.51 RTL: "\x{640}\x{640}\x{644}\x{627}" + chunk 1 text run 1 at (404.33,275.00) startOffset 0 endOffset 3 width 18.82: "ff\x{30C}" + LayoutSVGText {text} at (45,311) size 52x49 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 52x49 + chunk 1 text run 1 at (50.00,350.00) startOffset 0 endOffset 1 width 5.23: "\x{30C}" + chunk 1 text run 1 at (55.23,350.00) startOffset 0 endOffset 1 width 26.25 RTL: "\x{FDB0}" + chunk 1 text run 1 at (81.48,350.00) startOffset 0 endOffset 2 width 9.72: "i\x{333}" + LayoutSVGText {text} at (195,319) size 51x39 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 51x39 + chunk 1 text run 1 at (200.00,350.00) startOffset 0 endOffset 1 width 4.38: "\x{30C}" + chunk 1 text run 1 at (204.38,350.00) startOffset 0 endOffset 1 width 26.25 RTL: "\x{FDB0}" + chunk 1 text run 1 at (230.63,350.00) startOffset 0 endOffset 2 width 9.72: "i\x{333}" + LayoutSVGText {text} at (344,318) size 51x40 contains 1 chunk(s) + LayoutSVGInlineText {#text} at (0,0) size 50x40 + chunk 1 text run 1 at (350.00,350.00) startOffset 0 endOffset 1 width 4.86: "\x{30C}" + chunk 1 text run 1 at (354.86,350.00) startOffset 0 endOffset 1 width 26.25 RTL: "\x{FDB0}" + chunk 1 text run 1 at (381.11,350.00) startOffset 0 endOffset 2 width 7.78: "i\x{333}" + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_dictionary.py b/third_party/WebKit/Source/bindings/scripts/v8_dictionary.py index dde7e1c..a6abb31 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_dictionary.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_dictionary.py
@@ -53,13 +53,21 @@ def dictionary_context(dictionary, interfaces_info): includes.clear() includes.update(DICTIONARY_CPP_INCLUDES) + + members = [member_context(dictionary, member) + for member in sorted(dictionary.members, + key=operator.attrgetter('name'))] + + for member in members: + if member['runtime_enabled_function']: + includes.add('platform/RuntimeEnabledFeatures.h') + break + cpp_class = v8_utilities.cpp_name(dictionary) context = { 'cpp_class': cpp_class, 'header_includes': set(DICTIONARY_H_INCLUDES), - 'members': [member_context(dictionary, member) - for member in sorted(dictionary.members, - key=operator.attrgetter('name'))], + 'members': members, 'required_member_names': sorted([member.name for member in dictionary.members if member.is_required]),
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp index 99c61ae..6693b2c 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp
@@ -21,6 +21,7 @@ #include "bindings/core/v8/V8Uint8Array.h" #include "core/dom/FlexibleArrayBufferView.h" #include "core/frame/Deprecation.h" +#include "platform/RuntimeEnabledFeatures.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h index b3422f8..45c2960 100644 --- a/third_party/WebKit/Source/core/dom/Node.h +++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -233,10 +233,8 @@ virtual PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) = 0; void normalize(); - // TODO(yosin): Once we drop |Node.prototype.isSameNode()|, we should - // get rid of |isSameNodeDeprecated()|. - bool isSameNodeDeprecated(Node* other) const { return this == other; } bool isEqualNode(Node*) const; + bool isSameNode(Node* other) const { return this == other; } bool isDefaultNamespace(const AtomicString& namespaceURI) const; const AtomicString& lookupPrefix(const AtomicString& namespaceURI) const; const AtomicString& lookupNamespaceURI(const String& prefix) const;
diff --git a/third_party/WebKit/Source/core/dom/Node.idl b/third_party/WebKit/Source/core/dom/Node.idl index 12251c59..b16f9d2 100644 --- a/third_party/WebKit/Source/core/dom/Node.idl +++ b/third_party/WebKit/Source/core/dom/Node.idl
@@ -59,7 +59,8 @@ [CustomElementCallbacks] void normalize(); [NewObject, CustomElementCallbacks] Node cloneNode(optional boolean deep = false); - boolean isEqualNode(Node? node); + boolean isEqualNode(Node? otherNode); + boolean isSameNode(Node? otherNode); // historical alias of === const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01; const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02; @@ -78,8 +79,4 @@ [CustomElementCallbacks, PerWorldBindings, RaisesException] Node appendChild(Node node); [CustomElementCallbacks, PerWorldBindings, RaisesException] Node replaceChild(Node node, Node child); [CustomElementCallbacks, RaisesException] Node removeChild(Node child); - - // FIXME: isSameNode has been removed from the spec: - // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27424 - [MeasureAs=NodeIsSameNode, ImplementedAs=isSameNodeDeprecated] boolean isSameNode(Node? other); };
diff --git a/third_party/WebKit/Source/core/dom/QualifiedName.cpp b/third_party/WebKit/Source/core/dom/QualifiedName.cpp index 20917e11a..18b42cc 100644 --- a/third_party/WebKit/Source/core/dom/QualifiedName.cpp +++ b/third_party/WebKit/Source/core/dom/QualifiedName.cpp
@@ -70,14 +70,14 @@ QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n) { QualifiedNameData data = { { p.impl(), l.impl(), n.isEmpty() ? nullAtom.impl() : n.impl() }, false }; - QualifiedNameCache::AddResult addResult = qualifiedNameCache().add<QNameComponentsTranslator>(data); + QualifiedNameCache::AddResult addResult = qualifiedNameCache().addWithTranslator<QNameComponentsTranslator>(data); m_impl = addResult.isNewEntry ? adoptRef(*addResult.storedValue) : *addResult.storedValue; } QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n, bool isStatic) { QualifiedNameData data = { { p.impl(), l.impl(), n.impl() }, isStatic }; - QualifiedNameCache::AddResult addResult = qualifiedNameCache().add<QNameComponentsTranslator>(data); + QualifiedNameCache::AddResult addResult = qualifiedNameCache().addWithTranslator<QNameComponentsTranslator>(data); m_impl = addResult.isNewEntry ? adoptRef(*addResult.storedValue) : *addResult.storedValue; }
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp index 046db31..c9613857 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -1512,9 +1512,9 @@ { "DeleteWordBackward", {20, executeDeleteWordBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "DeleteWordForward", {21, executeDeleteWordForward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "FindString", {22, executeFindString, supported, enabled, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, - { "FontName", {23, executeFontName, supported, enabledInEditableText, stateNone, valueFontName, notTextInsertion, doNotAllowExecutionWhenDisabled } }, - { "FontSize", {24, executeFontSize, supported, enabledInEditableText, stateNone, valueFontSize, notTextInsertion, doNotAllowExecutionWhenDisabled } }, - { "FontSizeDelta", {25, executeFontSizeDelta, supported, enabledInEditableText, stateNone, valueFontSizeDelta, notTextInsertion, doNotAllowExecutionWhenDisabled } }, + { "FontName", {23, executeFontName, supported, enabledInRichlyEditableText, stateNone, valueFontName, notTextInsertion, doNotAllowExecutionWhenDisabled } }, + { "FontSize", {24, executeFontSize, supported, enabledInRichlyEditableText, stateNone, valueFontSize, notTextInsertion, doNotAllowExecutionWhenDisabled } }, + { "FontSizeDelta", {25, executeFontSizeDelta, supported, enabledInRichlyEditableText, stateNone, valueFontSizeDelta, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "ForeColor", {26, executeForeColor, supported, enabledInRichlyEditableText, stateNone, valueForeColor, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "FormatBlock", {27, executeFormatBlock, supported, enabledInRichlyEditableText, stateNone, valueFormatBlock, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "ForwardDelete", {28, executeForwardDelete, supported, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index 42bdd408..0d3fffc9 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -142,7 +142,6 @@ DocumentXMLEncoding = 115, // Removed from DOM4. DocumentXMLStandalone = 116, // Removed from DOM4. DocumentXMLVersion = 117, // Removed from DOM4. - NodeIsSameNode = 118, // Removed from DOM4. NavigatorProductSub = 123, NavigatorVendor = 124, NavigatorVendorSub = 125,
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp index 0b1114c..b5867e7d 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp
@@ -241,10 +241,9 @@ void InspectorDebuggerAgent::setVariableValue(ErrorString* errorString, int inScopeNumber, const String16& inVariableName, PassOwnPtr<protocol::Runtime::CallArgument> inNewValue, - const Maybe<String16>& inCallFrameId, - const Maybe<String16>& inFunctionObjectId) + const String16& inCallFrameId) { - m_v8DebuggerAgent->setVariableValue(errorString, inScopeNumber, inVariableName, inNewValue, inCallFrameId, inFunctionObjectId); + m_v8DebuggerAgent->setVariableValue(errorString, inScopeNumber, inVariableName, inNewValue, inCallFrameId); } void InspectorDebuggerAgent::getBacktrace(ErrorString* errorString,
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h index 3353951..a095471 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h
@@ -70,7 +70,7 @@ void getCollectionEntries(ErrorString*, const String16& objectId, OwnPtr<protocol::Array<protocol::Debugger::CollectionEntry>>* entries) override; void setPauseOnExceptions(ErrorString*, const String16& state) override; void evaluateOnCallFrame(ErrorString*, const String16& callFrameId, const String16& expression, const Maybe<String16>& objectGroup, const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole, const Maybe<bool>& returnByValue, const Maybe<bool>& generatePreview, OwnPtr<protocol::Runtime::RemoteObject>* result, Maybe<bool>* wasThrown, Maybe<protocol::Runtime::ExceptionDetails>*) override; - void setVariableValue(ErrorString*, int scopeNumber, const String16& variableName, PassOwnPtr<protocol::Runtime::CallArgument> newValue, const Maybe<String16>& callFrameId, const Maybe<String16>& functionObjectId) override; + void setVariableValue(ErrorString*, int scopeNumber, const String16& variableName, PassOwnPtr<protocol::Runtime::CallArgument> newValue, const String16& callFrameId) override; void getBacktrace(ErrorString*, OwnPtr<protocol::Array<protocol::Debugger::CallFrame>>* callFrames, Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) override; void setAsyncCallStackDepth(ErrorString*, int maxDepth) override; void enablePromiseTracker(ErrorString*, const Maybe<bool>& captureStacks) override;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.h b/third_party/WebKit/Source/core/layout/LayoutBlock.h index 69d5271..9f6c1833 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.h +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.h
@@ -316,7 +316,6 @@ // FIXME-BLOCKFLOW: Remove virtualization when all callers have moved to LayoutBlockFlow virtual void paintFloats(const PaintInfo&, const LayoutPoint&) const { } - virtual void paintSelection(const PaintInfo&, const LayoutPoint&) const { } protected: virtual void adjustInlineDirectionLineBounds(unsigned /* expansionOpportunityCount */, LayoutUnit& /* logicalLeft */, LayoutUnit& /* logicalWidth */) const { }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp index 438077b..fc16068 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -2678,14 +2678,6 @@ ASSERT_NOT_REACHED(); } -IntRect alignSelectionRectToDevicePixels(LayoutRect& rect) -{ - LayoutUnit roundedX = LayoutUnit(rect.x().round()); - return IntRect(roundedX, rect.y().round(), - (rect.maxX() - roundedX).round(), - snapSizeToPixel(rect.height(), rect.y())); -} - bool LayoutBlockFlow::allowsPaginationStrut() const { // The block needs to be contained by a LayoutBlockFlow (and not by e.g. a flexbox, grid, or a
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index 19a44fa5..eb0e47c 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -553,10 +553,8 @@ if (ownerElement && ownerElement->layoutObject()) { if (frameView->safeToPropagateScrollToParent()) { parentBox = ownerElement->layoutObject()->enclosingBox(); - // FIXME: This doesn't correctly convert the rect to - // absolute coordinates in the parent. - newRect.setX(rect.x() - frameView->scrollX() + frameView->x()); - newRect.setY(rect.y() - frameView->scrollY() + frameView->y()); + LayoutView* parentView = ownerElement->layoutObject()->view(); + newRect = enclosingLayoutRect(view()->localToAncestorQuad(FloatRect(rect), parentView, UseTransforms | TraverseDocumentBoundaries).boundingBox()); } else { parentBox = nullptr; } @@ -3500,7 +3498,7 @@ || (child->style()->isFlippedBlocksWritingMode() != containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode())) logicalTopPos = containerLogicalHeight - logicalHeightValue - logicalTopPos; - // Our offset is from the logical bottom edge in a flipped environment, e.g., right for vertical-rl and bottom for horizontal-bt. + // Our offset is from the logical bottom edge in a flipped environment, e.g., right for vertical-rl. if (containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) { if (child->isHorizontalWritingMode()) logicalTopPos += containerBlock->borderBottom(); @@ -4076,9 +4074,9 @@ // For overflow clip objects, we don't want to propagate overflow into unreachable areas. LayoutRect overflowRect(rect); if (hasOverflowClip() || isLayoutView()) { - // Overflow is in the block's coordinate space and thus is flipped for horizontal-bt and vertical-rl - // writing modes. At this stage that is actually a simplification, since we can treat horizontal-tb/bt as the same - // and vertical-lr/rl as the same. + // Overflow is in the block's coordinate space and thus is flipped for vertical-rl writing + // mode. At this stage that is actually a simplification, since we can treat vertical-lr/rl + // as the same. bool hasTopOverflow = !style()->isLeftToRightDirection() && !isHorizontalWritingMode(); bool hasLeftOverflow = !style()->isLeftToRightDirection() && isHorizontalWritingMode(); if (isFlexibleBox() && style()->isReverseFlexDirection()) { @@ -4342,10 +4340,10 @@ { // Because of the special coordinate system used for overflow rectangles and many other // rectangles (not quite logical, not quite physical), we need to flip the block progression - // coordinate in vertical-rl and horizontal-bt writing modes. In other words, the rectangle - // returned is physical, except for the block direction progression coordinate (y in horizontal - // writing modes, x in vertical writing modes), which is always "logical top". Apart from the - // flipping, this method does the same as clientBoxRect(). + // coordinate in vertical-rl writing mode. In other words, the rectangle returned is physical, + // except for the block direction progression coordinate (x in vertical writing mode), which is + // always "logical top". Apart from the flipping, this method does the same thing as + // clientBoxRect(). const int scrollBarWidth = verticalScrollbarWidth(); const int scrollBarHeight = horizontalScrollbarHeight(); @@ -4356,10 +4354,10 @@ LayoutRect rect(left, top, size().width() - left - right, size().height() - top - bottom); flipForWritingMode(rect); // Subtract space occupied by scrollbars. Order is important here: first flip, then subtract - // scrollbars. This may seem backwards and weird, since one would think that a horizontal - // scrollbar at the physical bottom in horizontal-bt ought to be at the logical top (physical - // bottom), between the logical top (physical bottom) border and the logical top (physical - // bottom) padding. But this is how the rest of the code expects us to behave. This is highly + // scrollbars. This may seem backwards and weird, since one would think that a vertical + // scrollbar at the physical right in vertical-rl ought to be at the logical left (physical + // right), between the logical left (physical right) border and the logical left (physical + // right) padding. But this is how the rest of the code expects us to behave. This is highly // related to https://bugs.webkit.org/show_bug.cgi?id=76129 // FIXME: when the above mentioned bug is fixed, it should hopefully be possible to call // clientBoxRect() or paddingBoxRect() in this method, rather than fiddling with the edges on
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index f3c2703..441d169 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -353,10 +353,11 @@ bool canResize() const; - // Visual and layout overflow are in the coordinate space of the box. This means that they aren't purely physical directions. - // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right - // respectively are flipped when compared to their physical counterparts. For example minX is on the left in vertical-lr, - // but it is on the right in vertical-rl. + // Visual and layout overflow are in the coordinate space of the box. This means that they + // aren't purely physical directions. For horizontal-tb and vertical-lr they will match physical + // directions, but for vertical-rl, the left/right are flipped when compared to their physical + // counterparts. For example minX is on the left in vertical-lr, but it is on the right in + // vertical-rl. LayoutRect noOverflowRect() const; LayoutRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : noOverflowRect(); } IntRect pixelSnappedLayoutOverflowRect() const { return pixelSnappedIntRect(layoutOverflowRect()); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp index 7010410..994c3a8 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -1095,18 +1095,36 @@ return childCrossSize; } +LayoutUnit LayoutFlexibleBox::mainSizeForPercentageResolution(const LayoutBox& child) +{ + // This function implements section 9.8. Definite and Indefinite Sizes, case + // 2) of the flexbox spec. + // We need to check for the flexbox to have a definite main size, and for the + // flex item to have a definite flex basis. + const Length& flexBasis = flexBasisForChild(child); + if (!mainAxisLengthIsDefinite(child, flexBasis)) + return LayoutUnit(-1); + LayoutUnit mainSize = isColumnFlow() ? computeDefiniteLogicalHeight() : computeDefiniteLogicalWidth(); + if (mainSize == LayoutUnit(-1)) + return mainSize; + + if (hasOrthogonalFlow(child)) + return child.hasOverrideLogicalContentHeight() ? child.overrideLogicalContentHeight() : LayoutUnit(-1); + return child.hasOverrideLogicalContentWidth() ? child.overrideLogicalContentWidth() : LayoutUnit(-1); +} + LayoutUnit LayoutFlexibleBox::childLogicalHeightForPercentageResolution(const LayoutBox& child) { if (!hasOrthogonalFlow(child)) return crossSizeForPercentageResolution(child); - return LayoutUnit(-1); + return mainSizeForPercentageResolution(child); } LayoutUnit LayoutFlexibleBox::childLogicalWidthForPercentageResolution(const LayoutBox& child) { if (hasOrthogonalFlow(child)) return crossSizeForPercentageResolution(child); - return LayoutUnit(-1); + return mainSizeForPercentageResolution(child); } LayoutUnit LayoutFlexibleBox::adjustChildSizeForAspectRatioCrossAxisMinAndMax(const LayoutBox& child, LayoutUnit childSize) @@ -1430,6 +1448,11 @@ LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(*child); setOverrideMainAxisSizeForChild(*child, childPreferredSize); if (childPreferredSize != mainAxisExtentForChild(*child)) { + // We will correctly handle percentage sizing even without re-laying out here, because + // if our size was already correct, then percentage resolution was also correct due + // to the way percentage sizing is defined by flexbox (ie. it requires a definite flex basis) + // TODO(cbiesinger): When flex-basis is used instead of width/height, this is not the case. That + // problem is not limited to percentages. See http://crbug.com/531656#c11 child->setChildNeedsLayout(MarkOnlyThis); } else { // To avoid double applying margin changes in updateAutoMarginsInCrossAxis, we reset the margins here.
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h index 5057496..84b00869 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
@@ -65,6 +65,7 @@ LayoutUnit computeDefiniteLogicalHeight(); LayoutUnit crossSizeForPercentageResolution(const LayoutBox& child); + LayoutUnit mainSizeForPercentageResolution(const LayoutBox& child); LayoutUnit childLogicalHeightForPercentageResolution(const LayoutBox& child); LayoutUnit childLogicalWidthForPercentageResolution(const LayoutBox& child);
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp index 26508e0..75506c8 100644 --- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp +++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
@@ -784,7 +784,7 @@ return; // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite border that applies, since - // the line is "upside down" in terms of block coordinates. vertical-rl and horizontal-bt are the flipped line modes. + // the line is "upside down" in terms of block coordinates. vertical-rl is the flipped line mode. LayoutRectOutsets logicalOutsets = style.borderImageOutsets().logicalOutsetsWithFlippedLines(style.getWritingMode()); if (!includeLogicalLeftEdge())
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h index 9f50366..9cae6501 100644 --- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h +++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h
@@ -202,9 +202,11 @@ void checkConsistency() const; void setHasBadChildList(); - // Line visual and layout overflow are in the coordinate space of the block. This means that they aren't purely physical directions. - // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right - // respectively are flipped when compared to their physical counterparts. For example minX is on the left in vertical-lr, but it is on the right in vertical-rl. + // Line visual and layout overflow are in the coordinate space of the block. This means that + // they aren't purely physical directions. For horizontal-tb and vertical-lr they will match + // physical directions, but for vertical-rl, the left/right respectively are flipped when + // compared to their physical counterparts. For example minX is on the left in vertical-lr, but + // it is on the right in vertical-rl. LayoutRect layoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const { return m_overflow ? m_overflow->layoutOverflowRect() : frameRectIncludingLineHeight(lineTop, lineBottom);
diff --git a/third_party/WebKit/Source/core/layout/line/InlineTextBox.h b/third_party/WebKit/Source/core/layout/line/InlineTextBox.h index 005a20b..60e937e 100644 --- a/third_party/WebKit/Source/core/layout/line/InlineTextBox.h +++ b/third_party/WebKit/Source/core/layout/line/InlineTextBox.h
@@ -184,8 +184,6 @@ DEFINE_INLINE_BOX_TYPE_CASTS(InlineTextBox); -void alignSelectionRectToDevicePixels(LayoutRect&); - } // namespace blink #endif // InlineTextBox_h
diff --git a/third_party/WebKit/Source/core/paint/BlockFlowPainter.h b/third_party/WebKit/Source/core/paint/BlockFlowPainter.h index 7d76d23a..47c76af 100644 --- a/third_party/WebKit/Source/core/paint/BlockFlowPainter.h +++ b/third_party/WebKit/Source/core/paint/BlockFlowPainter.h
@@ -18,7 +18,6 @@ public: BlockFlowPainter(const LayoutBlockFlow& layoutBlockFlow) : m_layoutBlockFlow(layoutBlockFlow) { } void paintFloats(const PaintInfo&, const LayoutPoint&); - void paintSelection(const PaintInfo&, const LayoutPoint&); private: const LayoutBlockFlow& m_layoutBlockFlow; };
diff --git a/third_party/WebKit/Source/core/paint/BlockPainter.cpp b/third_party/WebKit/Source/core/paint/BlockPainter.cpp index 1a2509c..6f79e75f 100644 --- a/third_party/WebKit/Source/core/paint/BlockPainter.cpp +++ b/third_party/WebKit/Source/core/paint/BlockPainter.cpp
@@ -183,9 +183,6 @@ paintContents(contentsPaintInfo, paintOffset); - if (paintPhase == PaintPhaseForeground && !paintInfo.isPrinting()) - m_layoutBlock.paintSelection(contentsPaintInfo, paintOffset); // Fill in gaps in selection on lines and between blocks. - if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) m_layoutBlock.paintFloats(contentsPaintInfo, paintOffset); }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index 20b4402..e19a8a76 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -107,7 +107,6 @@ const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); - // TODO(trchen): There is some insanity going on with tables. Double check results. switch (object.styleRef().position()) { case StaticPosition: break; @@ -130,8 +129,17 @@ default: ASSERT_NOT_REACHED(); } - if (boxModelObject.isBox()) + if (boxModelObject.isBox()) { context.paintOffset += toLayoutBox(boxModelObject).locationOffset(); + // This is a weird quirk that table cells paint as children of table rows, + // but their location have the row's location baked-in. + // Similar adjustment is done in LayoutTableCell::offsetFromContainer(). + if (boxModelObject.isTableCell()) { + LayoutObject* parentRow = boxModelObject.parent(); + ASSERT(parentRow && parentRow->isTableRow()); + context.paintOffset -= toLayoutBox(parentRow)->locationOffset(); + } + } } static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp index 22eb5bdb..42aac18 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -679,4 +679,44 @@ EXPECT_EQ(scrollerProperties->effect(), childProperties->localBorderBoxProperties()->effect); } +TEST_F(PaintPropertyTreeBuilderTest, TableCellLayoutLocation) +{ + // This test verifies that the border box space of a table cell is being correctly computed. + // Table cells have weird location adjustment in our layout/paint implementation. + setBodyInnerHTML( + "<style>" + " body {" + " margin: 0;" + " }" + " table {" + " border-spacing: 0;" + " margin: 20px;" + " padding: 40px;" + " border: 10px solid black;" + " }" + " td {" + " width: 100px;" + " height: 100px;" + " padding: 0;" + " }" + " #target {" + " position: relative;" + " width: 100px;" + " height: 100px;" + " }" + "</style>" + "<table>" + " <tr><td></td><td></td></tr>" + " <tr><td></td><td><div id='target'></div></td></tr>" + "</table>" + ); + + FrameView* frameView = document().view(); + LayoutObject& target = *document().getElementById("target")->layoutObject(); + ObjectPaintProperties* targetProperties = target.objectPaintProperties(); + + EXPECT_EQ(LayoutPoint(170, 170), targetProperties->localBorderBoxProperties()->paintOffset); + EXPECT_EQ(frameView->scrollTranslation(), targetProperties->localBorderBoxProperties()->transform); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/css.js b/third_party/WebKit/Source/devtools/front_end/cm/css.js index 2673074..91046d9 100644 --- a/third_party/WebKit/Source/devtools/front_end/cm/css.js +++ b/third_party/WebKit/Source/devtools/front_end/cm/css.js
@@ -452,8 +452,8 @@ "animation-direction", "animation-duration", "animation-fill-mode", "animation-iteration-count", "animation-name", "animation-play-state", "animation-timing-function", "appearance", "azimuth", "backface-visibility", - "background", "background-attachment", "background-clip", "background-color", - "background-image", "background-origin", "background-position", + "background", "background-attachment", "background-blend-mode", "background-clip", + "background-color", "background-image", "background-origin", "background-position", "background-repeat", "background-size", "baseline-shift", "binding", "bleed", "bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target", "border", "border-bottom", "border-bottom-color", @@ -597,11 +597,12 @@ "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret", "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch", "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote", - "col-resize", "collapse", "column", "column-reverse", "compact", "condensed", "contain", "content", + "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse", + "compact", "condensed", "contain", "content", "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop", - "cross", "crosshair", "currentcolor", "cursive", "cyclic", "dashed", "decimal", + "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal", "decimal-leading-zero", "default", "default-button", "destination-atop", - "destination-in", "destination-out", "destination-over", "devanagari", + "destination-in", "destination-out", "destination-over", "devanagari", "difference", "disc", "discard", "disclosure-closed", "disclosure-open", "document", "dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", @@ -612,23 +613,23 @@ "ethiopic-halehame-gez", "ethiopic-halehame-om-et", "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", - "ethiopic-numeric", "ew-resize", "expanded", "extends", "extra-condensed", + "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes", "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove", - "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", + "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew", "help", "hidden", "hide", "higher", "highlight", "highlighttext", - "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore", + "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore", "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis", "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert", "italic", "japanese-formal", "japanese-informal", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer", "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal", - "landscape", "lao", "large", "larger", "left", "level", "lighter", + "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten", "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem", "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian", - "lower-roman", "lowercase", "ltr", "malayalam", "match", "matrix", "matrix3d", + "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d", "media-controls-background", "media-current-time-display", "media-fullscreen-button", "media-mute-button", "media-play-button", "media-return-to-realtime-button", "media-rewind-button", @@ -637,7 +638,7 @@ "media-volume-slider-container", "media-volume-sliderthumb", "medium", "menu", "menulist", "menulist-button", "menulist-text", "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", - "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize", + "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize", "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap", "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote", @@ -651,7 +652,7 @@ "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY", "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running", - "s-resize", "sans-serif", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", + "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen", "scroll", "scrollbar", "se-resize", "searchfield", "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", "searchfield-results-decoration", @@ -659,7 +660,7 @@ "simp-chinese-formal", "simp-chinese-informal", "single", "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", - "small", "small-caps", "small-caption", "smaller", "solid", "somali", + "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali", "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square", "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table", @@ -821,4 +822,4 @@ helperType: "gss" }); -}); +}); \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/javascript.js b/third_party/WebKit/Source/devtools/front_end/cm/javascript.js index b961b890..c91910f 100644 --- a/third_party/WebKit/Source/devtools/front_end/cm/javascript.js +++ b/third_party/WebKit/Source/devtools/front_end/cm/javascript.js
@@ -13,6 +13,11 @@ })(function(CodeMirror) { "use strict"; +function expressionAllowed(stream, state, backUp) { + return /^(?:operator|sof|keyword c|case|new|[\[{}\(,;:]|=>)$/.test(state.lastType) || + (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) +} + CodeMirror.defineMode("javascript", function(config, parserConfig) { var indentUnit = config.indentUnit; var statementIndent = parserConfig.statementIndent; @@ -32,12 +37,12 @@ "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C, "var": kw("var"), "const": kw("var"), "let": kw("var"), - "async": kw("async"), "function": kw("function"), "catch": kw("catch"), + "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), "in": operator, "typeof": operator, "instanceof": operator, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, "this": kw("this"), "class": kw("class"), "super": kw("atom"), - "await": C, "yield": C, "export": kw("export"), "import": kw("import"), "extends": C + "yield": C, "export": kw("export"), "import": kw("import"), "extends": C }; // Extend the 'normal' keywords with the TypeScript language extensions @@ -45,15 +50,20 @@ var type = {type: "variable", style: "variable-3"}; var tsKeywords = { // object-like things - "interface": kw("interface"), - "extends": kw("extends"), - "constructor": kw("constructor"), + "interface": kw("class"), + "implements": C, + "namespace": C, + "module": kw("module"), + "enum": kw("module"), // scope modifiers - "public": kw("public"), - "private": kw("private"), - "protected": kw("protected"), - "static": kw("static"), + "public": kw("modifier"), + "private": kw("modifier"), + "protected": kw("modifier"), + "abstract": kw("modifier"), + + // operators + "as": operator, // types "string": type, "number": type, "boolean": type, "any": type @@ -121,8 +131,7 @@ } else if (stream.eat("/")) { stream.skipToEnd(); return ret("comment", "comment"); - } else if (state.lastType == "operator" || state.lastType == "keyword c" || - state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { + } else if (expressionAllowed(stream, state, 1)) { readRegexp(stream); stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); return ret("regexp", "string-2"); @@ -356,6 +365,7 @@ if (type == "class") return cont(pushlex("form"), className, poplex); if (type == "export") return cont(pushlex("stat"), afterExport, poplex); if (type == "import") return cont(pushlex("stat"), afterImport, poplex); + if (type == "module") return cont(pushlex("form"), pattern, pushlex("}"), expect("{"), block, poplex, poplex) return pass(pushlex("stat"), expression, expect(";"), poplex); } function expression(type) { @@ -373,7 +383,6 @@ var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); - if (type == "async") return cont(expression); if (type == "function") return cont(functiondef, maybeop); if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); @@ -452,9 +461,7 @@ if (type == "variable") {cx.marked = "property"; return cont();} } function objprop(type, value) { - if (type == "async") { - return cont(objprop); - } else if (type == "variable" || cx.style == "keyword") { + if (type == "variable" || cx.style == "keyword") { cx.marked = "property"; if (value == "get" || value == "set") return cont(getterSetter); return cont(afterprop); @@ -463,8 +470,12 @@ return cont(afterprop); } else if (type == "jsonld-keyword") { return cont(afterprop); + } else if (type == "modifier") { + return cont(objprop) } else if (type == "[") { return cont(expression, expect("]"), afterprop); + } else if (type == "spread") { + return cont(expression); } } function getterSetter(type) { @@ -513,6 +524,7 @@ return pass(pattern, maybetype, maybeAssign, vardefCont); } function pattern(type, value) { + if (type == "modifier") return cont(pattern) if (type == "variable") { register(value); return cont(); } if (type == "spread") return cont(pattern); if (type == "[") return contCommasep(pattern, "]"); @@ -525,6 +537,7 @@ } if (type == "variable") cx.marked = "property"; if (type == "spread") return cont(pattern); + if (type == "}") return pass(); return cont(expect(":"), pattern, maybeAssign); } function maybeAssign(_type, value) { @@ -647,7 +660,7 @@ lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), localVars: parserConfig.localVars, context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: 0 + indented: basecolumn || 0 }; if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") state.globalVars = parserConfig.globalVars; @@ -703,7 +716,13 @@ helperType: jsonMode ? "json" : "javascript", jsonldMode: jsonldMode, - jsonMode: jsonMode + jsonMode: jsonMode, + + expressionAllowed: expressionAllowed, + skipExpression: function(state) { + var top = state.cc[state.cc.length - 1] + if (top == expression || top == expressionNoComma) state.cc.pop() + } }; }); @@ -720,4 +739,4 @@ CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); -}); +}); \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/xml.js b/third_party/WebKit/Source/devtools/front_end/cm/xml.js index 786507d..a365739 100644 --- a/third_party/WebKit/Source/devtools/front_end/cm/xml.js +++ b/third_party/WebKit/Source/devtools/front_end/cm/xml.js
@@ -11,54 +11,56 @@ })(function(CodeMirror) { "use strict"; -CodeMirror.defineMode("xml", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; - var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag; - if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true; +var htmlConfig = { + autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, + 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, + 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, + 'track': true, 'wbr': true, 'menuitem': true}, + implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, + 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, + 'th': true, 'tr': true}, + contextGrabbers: { + 'dd': {'dd': true, 'dt': true}, + 'dt': {'dd': true, 'dt': true}, + 'li': {'li': true}, + 'option': {'option': true, 'optgroup': true}, + 'optgroup': {'optgroup': true}, + 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, + 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, + 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, + 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, + 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, + 'rp': {'rp': true, 'rt': true}, + 'rt': {'rp': true, 'rt': true}, + 'tbody': {'tbody': true, 'tfoot': true}, + 'td': {'td': true, 'th': true}, + 'tfoot': {'tbody': true}, + 'th': {'td': true, 'th': true}, + 'thead': {'tbody': true, 'tfoot': true}, + 'tr': {'tr': true} + }, + doNotIndent: {"pre": true}, + allowUnquoted: true, + allowMissing: true, + caseFold: true +} - var Kludges = parserConfig.htmlMode ? { - autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, - 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, - 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, - 'track': true, 'wbr': true}, - implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, - 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, - 'th': true, 'tr': true}, - contextGrabbers: { - 'dd': {'dd': true, 'dt': true}, - 'dt': {'dd': true, 'dt': true}, - 'li': {'li': true}, - 'option': {'option': true, 'optgroup': true}, - 'optgroup': {'optgroup': true}, - 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, - 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, - 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, - 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, - 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, - 'rp': {'rp': true, 'rt': true}, - 'rt': {'rp': true, 'rt': true}, - 'tbody': {'tbody': true, 'tfoot': true}, - 'td': {'td': true, 'th': true}, - 'tfoot': {'tbody': true}, - 'th': {'td': true, 'th': true}, - 'thead': {'tbody': true, 'tfoot': true}, - 'tr': {'tr': true} - }, - doNotIndent: {"pre": true}, - allowUnquoted: true, - allowMissing: true, - caseFold: true - } : { - autoSelfClosers: {}, - implicitlyClosed: {}, - contextGrabbers: {}, - doNotIndent: {}, - allowUnquoted: false, - allowMissing: false, - caseFold: false - }; - var alignCDATA = parserConfig.alignCDATA; +var xmlConfig = { + autoSelfClosers: {}, + implicitlyClosed: {}, + contextGrabbers: {}, + doNotIndent: {}, + allowUnquoted: false, + allowMissing: false, + caseFold: false +} + +CodeMirror.defineMode("xml", function(editorConf, config_) { + var indentUnit = editorConf.indentUnit + var config = {} + var defaults = config_.htmlMode ? htmlConfig : xmlConfig + for (var prop in defaults) config[prop] = defaults[prop] + for (var prop in config_) config[prop] = config_[prop] // Return variables for tokenizers var type, setStyle; @@ -109,6 +111,7 @@ return null; } } + inText.isInText = true; function inTag(stream, state) { var ch = stream.next(); @@ -187,7 +190,7 @@ this.tagName = tagName; this.indent = state.indented; this.startOfLine = startOfLine; - if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) + if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) this.noIndent = true; } function popContext(state) { @@ -200,8 +203,8 @@ return; } parentTagName = state.context.tagName; - if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || - !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { + if (!config.contextGrabbers.hasOwnProperty(parentTagName) || + !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { return; } popContext(state); @@ -232,9 +235,9 @@ if (type == "word") { var tagName = stream.current(); if (state.context && state.context.tagName != tagName && - Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName)) + config.implicitlyClosed.hasOwnProperty(state.context.tagName)) popContext(state); - if (state.context && state.context.tagName == tagName) { + if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) { setStyle = "tag"; return closeState; } else { @@ -268,7 +271,7 @@ var tagName = state.tagName, tagStart = state.tagStart; state.tagName = state.tagStart = null; if (type == "selfcloseTag" || - Kludges.autoSelfClosers.hasOwnProperty(tagName)) { + config.autoSelfClosers.hasOwnProperty(tagName)) { maybePopContext(state, tagName); } else { maybePopContext(state, tagName); @@ -281,12 +284,12 @@ } function attrEqState(type, stream, state) { if (type == "equals") return attrValueState; - if (!Kludges.allowMissing) setStyle = "error"; + if (!config.allowMissing) setStyle = "error"; return attrState(type, stream, state); } function attrValueState(type, stream, state) { if (type == "string") return attrContinuedState; - if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;} + if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;} setStyle = "error"; return attrState(type, stream, state); } @@ -296,12 +299,14 @@ } return { - startState: function() { - return {tokenize: inText, - state: baseState, - indented: 0, - tagName: null, tagStart: null, - context: null}; + startState: function(baseIndent) { + var state = {tokenize: inText, + state: baseState, + indented: baseIndent || 0, + tagName: null, tagStart: null, + context: null} + if (baseIndent != null) state.baseIndent = baseIndent + return state }, token: function(stream, state) { @@ -334,19 +339,19 @@ return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; // Indent the starts of attribute names. if (state.tagName) { - if (multilineTagIndentPastTag) + if (config.multilineTagIndentPastTag !== false) return state.tagStart + state.tagName.length + 2; else - return state.tagStart + indentUnit * multilineTagIndentFactor; + return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1); } - if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0; + if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0; var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter); if (tagAfter && tagAfter[1]) { // Closing tag spotted while (context) { if (context.tagName == tagAfter[2]) { context = context.prev; break; - } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) { + } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) { context = context.prev; } else { break; @@ -354,25 +359,30 @@ } } else if (tagAfter) { // Opening tag spotted while (context) { - var grabbers = Kludges.contextGrabbers[context.tagName]; + var grabbers = config.contextGrabbers[context.tagName]; if (grabbers && grabbers.hasOwnProperty(tagAfter[2])) context = context.prev; else break; } } - while (context && !context.startOfLine) + while (context && context.prev && !context.startOfLine) context = context.prev; if (context) return context.indent + indentUnit; - else return 0; + else return state.baseIndent || 0; }, electricInput: /<\/[\s\w:]+>$/, blockCommentStart: "<!--", blockCommentEnd: "-->", - configuration: parserConfig.htmlMode ? "html" : "xml", - helperType: parserConfig.htmlMode ? "html" : "xml" + configuration: config.htmlMode ? "html" : "xml", + helperType: config.htmlMode ? "html" : "xml", + + skipAttribute: function(state) { + if (state.state == attrValueState) + state.state = attrState + } }; }); @@ -381,4 +391,4 @@ if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); -}); +}); \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/jsx.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/jsx.js new file mode 100644 index 0000000..c3d227a --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/jsx.js
@@ -0,0 +1,85 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript")) + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript"], mod) + else // Plain browser env + mod(CodeMirror) +})(function(CodeMirror) { + "use strict" + + function copyContext(context) { + return {state: CodeMirror.copyState(context.mode, context.state), + mode: context.mode, + depth: context.depth, + prev: context.prev && copyContext(context.prev)} + } + + CodeMirror.defineMode("jsx", function(config) { + var xmlMode = CodeMirror.getMode(config, "xml") + var jsMode = CodeMirror.getMode(config, "javascript") + + return { + startState: function() { + return {context: {state: CodeMirror.startState(jsMode), mode: jsMode}} + }, + + copyState: function(state) { + return {context: copyContext(state.context)} + }, + + token: function(stream, state) { + var cx = state.context + if (cx.mode == xmlMode) { + if (stream.peek() == "{") { + xmlMode.skipAttribute(cx.state) + state.context = {state: CodeMirror.startState(jsMode, xmlMode.indent(cx.state, "")), + mode: jsMode, + depth: 1, + prev: state.context} + return jsMode.token(stream, state.context.state) + } else { // FIXME skip attribute + var style = xmlMode.token(stream, cx.state), cur, brace + if (/\btag\b/.test(style) && !cx.state.context && /^\/?>$/.test(stream.current())) + state.context = state.context.prev + else if (!style && (brace = (cur = stream.current()).indexOf("{")) > -1) + stream.backUp(cur.length - brace) + return style + } + } else { // jsMode + if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) { + jsMode.skipExpression(cx.state) + state.context = {state: CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), + mode: xmlMode, + prev: state.context} + return xmlMode.token(stream, state.context.state) + } else { + var style = jsMode.token(stream, cx.state) + if (!style && cx.depth != null) { + var cur = stream.current() + if (cur == "{") { + cx.depth++ + } else if (cur == "}") { + if (--cx.depth == 0) state.context = state.context.prev + } + } + return style + } + } + }, + + indent: function(state, textAfter, fullLine) { + return state.context.mode.indent(state.context.state, textAfter, fullLine) + }, + + innerMode: function(state) { + return state.context[state.context.length - 1] + } + } + }, "xml", "javascript") + + CodeMirror.defineMIME("text/jsx", "jsx") +})
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/module.json b/third_party/WebKit/Source/devtools/front_end/cm_modes/module.json index 4e8ae82..78cbd9b50 100644 --- a/third_party/WebKit/Source/devtools/front_end/cm_modes/module.json +++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/module.json
@@ -74,6 +74,14 @@ { "type": "@WebInspector.CodeMirrorMimeMode", "className": "WebInspector.DefaultCodeMirrorMimeMode", + "fileName": "jsx.js", + "mimeTypes": [ + "text/jsx" + ] + }, + { + "type": "@WebInspector.CodeMirrorMimeMode", + "className": "WebInspector.DefaultCodeMirrorMimeMode", "fileName": "stylus.js", "mimeTypes": [ "text/x-styl" @@ -94,6 +102,7 @@ "shell.js", "livescript.js", "clojure.js", - "stylus.js" + "stylus.js", + "jsx.js" ] }
diff --git a/third_party/WebKit/Source/devtools/front_end/common/ResourceType.js b/third_party/WebKit/Source/devtools/front_end/common/ResourceType.js index b27624e..4cdb4dd31 100644 --- a/third_party/WebKit/Source/devtools/front_end/common/ResourceType.js +++ b/third_party/WebKit/Source/devtools/front_end/common/ResourceType.js
@@ -215,7 +215,6 @@ WebInspector.ResourceType.mimeTypeByExtension = { // Web extensions "js": "text/javascript", - "jsx": "text/javascript", "css": "text/css", "html": "text/html", "htm": "text/html", @@ -286,6 +285,9 @@ // Stylus "styl": "text/x-styl", + // JSX + "jsx": "text/jsx", + // Image "jpeg": "image/jpeg", "jpg": "image/jpeg",
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js index 9592a28..da2f5e77 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
@@ -630,7 +630,7 @@ property.parentObject = null; this.appendChild(new WebInspector.ObjectPropertyTreeElement(property)); } else { - var scopeRef = new WebInspector.ScopeRef(i, undefined, this._remoteObject.objectId); + var scopeRef = new WebInspector.ScopeRef(i, undefined); var remoteObject = runtimeModel.createScopeRemoteObject(scope.object, scopeRef); var scopeTreeElement = new WebInspector.ScopeTreeElement(title, remoteObject); this.appendChild(scopeTreeElement);
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMetadata.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMetadata.js index 7c19cf7..5070d7a2 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMetadata.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMetadata.js
@@ -227,7 +227,7 @@ "horizontal-tb", "vertical-rl", "vertical-lr" ] }, "-webkit-writing-mode": { values: [ - "lr", "rl", "tb", "lr-tb", "rl-tb", "tb-rl", "horizontal-tb", "vertical-rl", "vertical-lr", "horizontal-bt" + "lr", "rl", "tb", "lr-tb", "rl-tb", "tb-rl", "horizontal-tb", "vertical-rl", "vertical-lr" ] }, "border-collapse": { values: [ "collapse", "separate"
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js index 98b2d784..6250aa1 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -808,12 +808,11 @@ * @param {string} variableName * @param {!RuntimeAgent.CallArgument} newValue * @param {string} callFrameId - * @param {string} functionObjectId * @param {function(string=)=} callback */ - setVariableValue: function(scopeNumber, variableName, newValue, callFrameId, functionObjectId, callback) + setVariableValue: function(scopeNumber, variableName, newValue, callFrameId, callback) { - this._agent.setVariableValue(scopeNumber, variableName, newValue, callFrameId, functionObjectId, innerCallback); + this._agent.setVariableValue(scopeNumber, variableName, newValue, callFrameId, innerCallback); /** * @param {?Protocol.Error} error @@ -1376,7 +1375,7 @@ var declarativeScope = this._type !== DebuggerAgent.ScopeType.With && this._type !== DebuggerAgent.ScopeType.Global; if (declarativeScope) - this._object = runtimeModel.createScopeRemoteObject(this._payload.object, new WebInspector.ScopeRef(this._ordinal, this._callFrame.id, undefined)); + this._object = runtimeModel.createScopeRemoteObject(this._payload.object, new WebInspector.ScopeRef(this._ordinal, this._callFrame.id)); else this._object = runtimeModel.createRemoteObject(this._payload.object);
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js index 7ef3049..8f2c0d9 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -1048,8 +1048,13 @@ */ function wrappedCallback(properties, internalProperties) { - if (this._scopeRef && Array.isArray(properties)) + if (this._scopeRef && Array.isArray(properties)) { this._savedScopeProperties = properties.slice(); + if (!this._scopeRef.callFrameId) { + for (var property of this._savedScopeProperties) + property.writable = false; + } + } callback(properties, internalProperties); } @@ -1068,7 +1073,7 @@ doSetObjectPropertyValue: function(result, argumentName, callback) { var name = /** @type {string} */ (argumentName.value); - this._debuggerModel.setVariableValue(this._scopeRef.number, name, WebInspector.RemoteObject.toCallArgument(result), this._scopeRef.callFrameId, this._scopeRef.functionId, setVariableValueCallback.bind(this)); + this._debuggerModel.setVariableValue(this._scopeRef.number, name, WebInspector.RemoteObject.toCallArgument(result), this._scopeRef.callFrameId, setVariableValueCallback.bind(this)); /** * @param {string=} error @@ -1094,17 +1099,14 @@ }; /** - * Either callFrameId or functionId (exactly one) must be defined. * @constructor * @param {number} number * @param {string=} callFrameId - * @param {string=} functionId */ -WebInspector.ScopeRef = function(number, callFrameId, functionId) +WebInspector.ScopeRef = function(number, callFrameId) { this.number = number; this.callFrameId = callFrameId; - this.functionId = functionId; } /**
diff --git a/third_party/WebKit/Source/devtools/protocol.json b/third_party/WebKit/Source/devtools/protocol.json index 0643d498..beaab1e1 100644 --- a/third_party/WebKit/Source/devtools/protocol.json +++ b/third_party/WebKit/Source/devtools/protocol.json
@@ -3703,11 +3703,10 @@ { "name": "scopeNumber", "type": "integer", "description": "0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually." }, { "name": "variableName", "type": "string", "description": "Variable name." }, { "name": "newValue", "$ref": "Runtime.CallArgument", "description": "New variable value." }, - { "name": "callFrameId", "$ref": "CallFrameId", "optional": true, "description": "Id of callframe that holds variable." }, - { "name": "functionObjectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "Object id of closure (function) that holds variable." } + { "name": "callFrameId", "$ref": "CallFrameId", "description": "Id of callframe that holds variable." } ], "hidden": true, - "description": "Changes value of variable in a callframe or a closure. Either callframe or function must be specified. Object-based scopes are not supported and must be mutated manually." + "description": "Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually." }, { "name": "getBacktrace",
diff --git a/third_party/WebKit/Source/modules/webgl/DEPS b/third_party/WebKit/Source/modules/webgl/DEPS new file mode 100644 index 0000000..8109dc0a --- /dev/null +++ b/third_party/WebKit/Source/modules/webgl/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+gpu/command_buffer/client/gles2_interface.h", +]
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp index 05bc1bd7..888b74d 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.cpp
@@ -40,7 +40,7 @@ OwnPtr<WebGraphicsContext3D> context(createWebGraphicsContext3D(canvas, attributes, 2)); if (!context) return nullptr; - OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get()); + OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get(), context->getGLES2Interface()); if (!extensionsUtil) return nullptr; if (extensionsUtil->supportsExtension("GL_EXT_debug_marker")) {
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp index 56e28c6..52b6984 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
@@ -70,7 +70,7 @@ OwnPtr<WebGraphicsContext3D> context(createWebGraphicsContext3D(canvas, attributes, 1)); if (!context) return nullptr; - OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get()); + OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get(), context->getGLES2Interface()); if (!extensionsUtil) return nullptr; if (extensionsUtil->supportsExtension("GL_EXT_debug_marker")) {
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index daa0ac8..48a944b 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -45,6 +45,7 @@ #include "core/layout/LayoutBox.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "modules/webgl/ANGLEInstancedArrays.h" #include "modules/webgl/CHROMIUMSubscribeUniform.h" #include "modules/webgl/CHROMIUMValuebuffer.h" @@ -5072,9 +5073,11 @@ Extensions3DUtil* WebGLRenderingContextBase::extensionsUtil() { if (!m_extensionsUtil) { - m_extensionsUtil = Extensions3DUtil::create(webContext()); + WebGraphicsContext3D* context = webContext(); + gpu::gles2::GLES2Interface* gl = context->getGLES2Interface(); + m_extensionsUtil = Extensions3DUtil::create(context, gl); // The only reason the ExtensionsUtil should be invalid is if the webContext is lost. - ASSERT(m_extensionsUtil->isValid() || webContext()->isContextLost()); + ASSERT(m_extensionsUtil->isValid() || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR); } return m_extensionsUtil.get(); }
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 3254fb5..ba99374 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -324,6 +324,7 @@ "//base", "//cc", "//gpu/command_buffer/client:gles2_c_lib", + "//gpu/command_buffer/client:gles2_interface", "//skia", "//third_party:jpeg", "//third_party/WebKit/Source/wtf",
diff --git a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp index 9122829..819727c 100644 --- a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp +++ b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp
@@ -5,6 +5,7 @@ #include "platform/animation/CompositorAnimationPlayer.h" #include "cc/animation/animation_id_provider.h" +#include "cc/animation/animation_timeline.h" #include "platform/animation/CompositorAnimation.h" #include "platform/animation/CompositorAnimationDelegate.h" #include "public/platform/WebLayer.h" @@ -19,6 +20,11 @@ CompositorAnimationPlayer::~CompositorAnimationPlayer() { + setAnimationDelegate(nullptr); + // Detach player from timeline, otherwise it stays there (leaks) until + // compositor shutdown. + if (m_animationPlayer->animation_timeline()) + m_animationPlayer->animation_timeline()->DetachPlayer(m_animationPlayer); } cc::AnimationPlayer* CompositorAnimationPlayer::animationPlayer() const
diff --git a/third_party/WebKit/Source/platform/blink_platform.gyp b/third_party/WebKit/Source/platform/blink_platform.gyp index 9f7ac0e..86289b0 100644 --- a/third_party/WebKit/Source/platform/blink_platform.gyp +++ b/third_party/WebKit/Source/platform/blink_platform.gyp
@@ -133,6 +133,7 @@ '<(DEPTH)/cc/cc.gyp:cc', '<(DEPTH)/device/battery/battery.gyp:device_battery_mojo_bindings', '<(DEPTH)/gpu/gpu.gyp:gles2_c_lib', + '<(DEPTH)/gpu/gpu.gyp:gles2_implementation', '<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl', '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings', '<(DEPTH)/skia/skia.gyp:skia',
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi index 4bcb240..6734a3c 100644 --- a/third_party/WebKit/Source/platform/blink_platform.gypi +++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -1230,6 +1230,7 @@ 'graphics/ImageDecodingStoreTest.cpp', 'graphics/ImageFrameGeneratorTest.cpp', 'graphics/ImageLayerChromiumTest.cpp', + 'graphics/test/MockGLES2Interface.h', 'graphics/test/MockImageDecoder.h', 'graphics/test/MockWebGraphicsContext3D.h', 'threading/BackgroundTaskRunnerTest.cpp',
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp index 90ef507..5e7d0d3 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -25,6 +25,7 @@ #include "platform/graphics/Canvas2DLayerBridge.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "platform/Histogram.h" #include "platform/RuntimeEnabledFeatures.h" #include "platform/TraceEvent.h" @@ -178,7 +179,7 @@ else accelerate = hint == PreferAcceleration || hint == PreferAccelerationAfterVisibilityChange; - if (accelerate && (!m_contextProvider || m_contextProvider->context3d()->isContextLost())) + if (accelerate && (!m_contextProvider || m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR)) accelerate = false; return accelerate; } @@ -727,7 +728,7 @@ return true; if (!m_surface) return false; - if (m_contextProvider->context3d()->isContextLost()) { + if (m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { m_surface.clear(); for (auto mailboxInfo = m_mailboxes.begin(); mailboxInfo != m_mailboxes.end(); ++mailboxInfo) { if (mailboxInfo->m_image) @@ -747,13 +748,13 @@ return false; ASSERT(isAccelerated() && !m_surface); - WebGraphicsContext3D* sharedContext = 0; + gpu::gles2::GLES2Interface* sharedGL = nullptr; m_layer->clearTexture(); m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); if (m_contextProvider) - sharedContext = m_contextProvider->context3d(); + sharedGL = m_contextProvider->contextGL(); - if (sharedContext && !sharedContext->isContextLost()) { + if (sharedGL && sharedGL->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { GrContext* grCtx = m_contextProvider->grContext(); bool surfaceIsAccelerated; RefPtr<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCount, m_opacityMode, &surfaceIsAccelerated)); @@ -819,7 +820,7 @@ void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource) { ASSERT(isAccelerated() || isHibernating()); - bool contextLost = !isHibernating() && (!m_surface || m_contextProvider->context3d()->isContextLost()); + bool contextLost = !isHibernating() && (!m_surface || m_contextProvider->contextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR); ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this); // Mailboxes are typically released in FIFO order, so we iterate
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp index 89f071d0..2508eaf 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -26,11 +26,13 @@ #include "SkSurface.h" #include "base/memory/scoped_ptr.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "platform/Task.h" #include "platform/ThreadSafeFunctional.h" #include "platform/WaitableEvent.h" #include "platform/graphics/ImageBuffer.h" #include "platform/graphics/UnacceleratedImageBufferSurface.h" +#include "platform/graphics/test/MockGLES2Interface.h" #include "platform/graphics/test/MockWebGraphicsContext3D.h" #include "public/platform/Platform.h" #include "public/platform/WebExternalBitmap.h" @@ -68,8 +70,9 @@ class MockWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider { public: - MockWebGraphicsContext3DProvider(WebGraphicsContext3D* context3d) + MockWebGraphicsContext3DProvider(WebGraphicsContext3D* context3d, gpu::gles2::GLES2Interface* gl) : m_context3d(context3d) + , m_gl(gl) { scoped_ptr<SkGLContext> glContext(SkNullGLContext::Create()); glContext->makeCurrent(); @@ -86,8 +89,14 @@ return m_grContext.get(); } + gpu::gles2::GLES2Interface* contextGL() override + { + return m_gl; + } + private: WebGraphicsContext3D* m_context3d; + gpu::gles2::GLES2Interface* m_gl; RefPtr<GrContext> m_grContext; }; @@ -153,7 +162,8 @@ void fullLifecycleTest() { MockCanvasContext mainMock; - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + MockGLES2Interface mockGL; + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); ::testing::Mock::VerifyAndClearExpectations(&mainMock); @@ -174,12 +184,13 @@ void fallbackToSoftwareIfContextLost() { MockCanvasContext mainMock; - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + MockGLES2Interface mockGL; + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); ::testing::Mock::VerifyAndClearExpectations(&mainMock); { - mainMock.fakeContextLost(); + mockGL.setIsContextLost(true); Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), IntSize(300, 150), 0, NonOpaque, Canvas2DLayerBridge::EnableAcceleration))); ::testing::Mock::VerifyAndClearExpectations(&mainMock); EXPECT_TRUE(bridge->checkSurfaceValid()); @@ -198,7 +209,8 @@ { // No fallback case - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + MockGLES2Interface mockGL; + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), IntSize(300, 150), 0, NonOpaque, Canvas2DLayerBridge::EnableAcceleration))); ::testing::Mock::VerifyAndClearExpectations(&mainMock); EXPECT_TRUE(bridge->checkSurfaceValid()); @@ -211,7 +223,8 @@ { // Fallback case - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + MockGLES2Interface mockGL; + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); GrContext* gr = mainMockProvider->grContext(); Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), IntSize(300, 150), 0, NonOpaque, Canvas2DLayerBridge::EnableAcceleration))); ::testing::Mock::VerifyAndClearExpectations(&mainMock); @@ -230,7 +243,8 @@ void noDrawOnContextLostTest() { MockCanvasContext mainMock; - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + MockGLES2Interface mockGL; + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); ::testing::Mock::VerifyAndClearExpectations(&mainMock); @@ -242,7 +256,7 @@ uint32_t genID = bridge->getOrCreateSurface()->generationID(); bridge->canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), paint); EXPECT_EQ(genID, bridge->getOrCreateSurface()->generationID()); - mainMock.fakeContextLost(); + mockGL.setIsContextLost(true); EXPECT_EQ(genID, bridge->getOrCreateSurface()->generationID()); bridge->canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), paint); EXPECT_EQ(genID, bridge->getOrCreateSurface()->generationID()); @@ -260,7 +274,8 @@ void prepareMailboxWithBitmapTest() { MockCanvasContext mainMock; - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + MockGLES2Interface mockGL; + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), IntSize(300, 150), 0, NonOpaque, Canvas2DLayerBridge::ForceAccelerationForTesting))); bridge->m_lastImageId = 1; @@ -272,13 +287,14 @@ void prepareMailboxAndLoseResourceTest() { MockCanvasContext mainMock; + MockGLES2Interface mockGL; bool lostResource = true; // Prepare a mailbox, then report the resource as lost. // This test passes by not crashing and not triggering assertions. { WebExternalTextureMailbox mailbox; - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), IntSize(300, 150), 0, NonOpaque, Canvas2DLayerBridge::ForceAccelerationForTesting))); bridge->prepareMailbox(&mailbox, 0); bridge->mailboxReleased(mailbox, lostResource); @@ -286,7 +302,7 @@ // Retry with mailbox released while bridge destruction is in progress { - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); WebExternalTextureMailbox mailbox; Canvas2DLayerBridge* rawBridge; { @@ -303,9 +319,10 @@ void accelerationHintTest() { MockCanvasContext mainMock; + MockGLES2Interface mockGL; { - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); ::testing::Mock::VerifyAndClearExpectations(&mainMock); Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), IntSize(300, 300), 0, NonOpaque, Canvas2DLayerBridge::EnableAcceleration))); ::testing::Mock::VerifyAndClearExpectations(&mainMock); @@ -319,7 +336,7 @@ ::testing::Mock::VerifyAndClearExpectations(&mainMock); { - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock)); + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(&mainMock, &mockGL)); ::testing::Mock::VerifyAndClearExpectations(&mainMock); Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainMockProvider.release(), IntSize(300, 300), 0, NonOpaque, Canvas2DLayerBridge::EnableAcceleration))); ::testing::Mock::VerifyAndClearExpectations(&mainMock); @@ -376,10 +393,9 @@ virtual ~MockLogger() { } }; - -void runCreateBridgeTask(Canvas2DLayerBridgePtr* bridgePtr, MockCanvasContext* mockCanvasContext, Canvas2DLayerBridgeTest* testHost, WaitableEvent* doneEvent) +void runCreateBridgeTask(Canvas2DLayerBridgePtr* bridgePtr, MockCanvasContext* mockCanvasContext, gpu::gles2::GLES2Interface* gl, Canvas2DLayerBridgeTest* testHost, WaitableEvent* doneEvent) { - OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(mockCanvasContext)); + OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new MockWebGraphicsContext3DProvider(mockCanvasContext, gl)); *bridgePtr = testHost->makeBridge(mainMockProvider.release(), IntSize(300, 300), Canvas2DLayerBridge::EnableAcceleration); // draw+flush to trigger the creation of a GPU surface (*bridgePtr)->didDraw(FloatRect(0, 0, 1, 1)); @@ -388,7 +404,7 @@ doneEvent->signal(); } -void postAndWaitCreateBridgeTask(const WebTraceLocation& location, WebThread* testThread, Canvas2DLayerBridgePtr* bridgePtr, MockCanvasContext* mockCanvasContext, Canvas2DLayerBridgeTest* testHost) +void postAndWaitCreateBridgeTask(const WebTraceLocation& location, WebThread* testThread, Canvas2DLayerBridgePtr* bridgePtr, MockCanvasContext* mockCanvasContext, gpu::gles2::GLES2Interface* gl, Canvas2DLayerBridgeTest* testHost) { OwnPtr<WaitableEvent> bridgeCreatedEvent = adoptPtr(new WaitableEvent()); testThread->getWebTaskRunner()->postTask( @@ -396,6 +412,7 @@ threadSafeBind(&runCreateBridgeTask, AllowCrossThreadAccess(bridgePtr), AllowCrossThreadAccess(mockCanvasContext), + AllowCrossThreadAccess(gl), AllowCrossThreadAccess(testHost), AllowCrossThreadAccess(bridgeCreatedEvent.get()))); bridgeCreatedEvent->wait(); @@ -469,12 +486,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); @@ -515,12 +533,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); @@ -567,12 +586,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); bridge->disableDeferral(DisableDeferralReasonUnknown); MockImageBuffer mockImageBuffer; EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AnyNumber()); @@ -639,12 +659,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); @@ -692,12 +713,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); MockImageBuffer mockImageBuffer; EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AnyNumber()); bridge->setImageBuffer(&mockImageBuffer); @@ -753,12 +775,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); MockImageBuffer mockImageBuffer; EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AnyNumber()); bridge->setImageBuffer(&mockImageBuffer); @@ -813,12 +836,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); @@ -868,12 +892,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); @@ -910,12 +935,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); @@ -946,12 +972,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); @@ -985,19 +1012,20 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); MockLogger* mockLoggerPtr = mockLogger.get(); bridge->setLoggerForTesting(mockLogger.release()); - mainMock.fakeContextLost(); + mockGL.setIsContextLost(true); // Test entering hibernation OwnPtr<WaitableEvent> hibernationAbortedEvent = adoptPtr(new WaitableEvent()); EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::HibernationScheduled)); @@ -1022,12 +1050,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); @@ -1061,12 +1090,13 @@ #endif { MockCanvasContext mainMock; + MockGLES2Interface mockGL; OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread")); // The Canvas2DLayerBridge has to be created on the thread that will use it // to avoid WeakPtr thread check issues. Canvas2DLayerBridgePtr bridge; - postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, this); + postAndWaitCreateBridgeTask(BLINK_FROM_HERE, testThread.get(), &bridge, &mainMock, &mockGL, this); // Register an alternate Logger for tracking hibernation events OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger);
diff --git a/third_party/WebKit/Source/platform/graphics/DEPS b/third_party/WebKit/Source/platform/graphics/DEPS index 226f05e..2556ec9 100644 --- a/third_party/WebKit/Source/platform/graphics/DEPS +++ b/third_party/WebKit/Source/platform/graphics/DEPS
@@ -4,4 +4,5 @@ "+base/message_loop", "+cc", "-cc/blink", + "+gpu/command_buffer/client/gles2_interface.h", ]
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DEPS b/third_party/WebKit/Source/platform/graphics/gpu/DEPS new file mode 100644 index 0000000..e264555 --- /dev/null +++ b/third_party/WebKit/Source/platform/graphics/gpu/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + # For tests only! + "+gpu/command_buffer/client/gles2_interface_stub.h", +]
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp index 9d2600b..3b361f7 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -30,6 +30,7 @@ #include "platform/graphics/gpu/DrawingBuffer.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "platform/RuntimeEnabledFeatures.h" #include "platform/TraceEvent.h" #include "platform/graphics/GraphicsLayer.h" @@ -97,7 +98,8 @@ return nullptr; } - OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get()); + gpu::gles2::GLES2Interface* gl = context->getGLES2Interface(); + OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get(), gl); if (!extensionsUtil->isValid()) { // This might be the first time we notice that the WebGraphicsContext3D is lost. return nullptr; @@ -118,7 +120,7 @@ if (discardFramebufferSupported) extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer"); - RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(std::move(context), extensionsUtil.release(), multisampleSupported, discardFramebufferSupported, preserve, requestedAttributes)); + RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(std::move(context), gl, extensionsUtil.release(), multisampleSupported, discardFramebufferSupported, preserve, requestedAttributes)); if (!drawingBuffer->initialize(size)) { drawingBuffer->beginDestruction(); return PassRefPtr<DrawingBuffer>(); @@ -131,12 +133,7 @@ shouldFailDrawingBufferCreationForTesting = true; } -DrawingBuffer::DrawingBuffer(PassOwnPtr<WebGraphicsContext3D> context, - PassOwnPtr<Extensions3DUtil> extensionsUtil, - bool multisampleExtensionSupported, - bool discardFramebufferSupported, - PreserveDrawingBuffer preserve, - WebGraphicsContext3D::Attributes requestedAttributes) +DrawingBuffer::DrawingBuffer(PassOwnPtr<WebGraphicsContext3D> context, gpu::gles2::GLES2Interface* gl, PassOwnPtr<Extensions3DUtil> extensionsUtil, bool multisampleExtensionSupported, bool discardFramebufferSupported, PreserveDrawingBuffer preserve, WebGraphicsContext3D::Attributes requestedAttributes) : m_preserveDrawingBuffer(preserve) , m_scissorEnabled(false) , m_texture2DBinding(0) @@ -144,6 +141,7 @@ , m_readFramebufferBinding(0) , m_activeTextureUnit(GL_TEXTURE0) , m_context(std::move(context)) + , m_gl(gl) , m_extensionsUtil(std::move(extensionsUtil)) , m_size(-1, -1) , m_requestedAttributes(requestedAttributes) @@ -320,7 +318,7 @@ void DrawingBuffer::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource) { - if (m_destructionInProgress || m_context->isContextLost() || lostResource || m_isHidden) { + if (m_destructionInProgress || m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR || lostResource || m_isHidden) { mailboxReleasedWithoutRecycling(mailbox); return; } @@ -444,7 +442,7 @@ bool DrawingBuffer::initialize(const IntSize& size) { - if (m_context->isContextLost()) { + if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { // Need to try to restore the context again later. return false; } @@ -490,7 +488,7 @@ } m_actualAttributes.antialias = multisample(); - if (m_context->isContextLost()) { + if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { // It's possible that the drawing buffer allocation provokes a context loss, so check again just in case. http://crbug.com/512302 return false; }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h index 5ea2af0..efdb7a3 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -46,11 +46,15 @@ #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" +namespace gpu { +namespace gles2 { +class GLES2Interface; +} +} + namespace WTF { - class ArrayBufferContents; - -} // namespace WTF +} namespace blink { @@ -175,6 +179,7 @@ protected: // For unittests DrawingBuffer( PassOwnPtr<WebGraphicsContext3D>, + gpu::gles2::GLES2Interface*, PassOwnPtr<Extensions3DUtil>, bool multisampleExtensionSupported, bool discardFramebufferSupported, @@ -299,6 +304,7 @@ GLenum m_activeTextureUnit; OwnPtr<WebGraphicsContext3D> m_context; + gpu::gles2::GLES2Interface* m_gl; // Lifetime is tied to the m_context. OwnPtr<Extensions3DUtil> m_extensionsUtil; IntSize m_size; WebGraphicsContext3D::Attributes m_requestedAttributes;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp index 7e9dc9f3..76d1b49 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -30,6 +30,7 @@ #include "platform/graphics/gpu/DrawingBuffer.h" +#include "gpu/command_buffer/client/gles2_interface_stub.h" #include "platform/RuntimeEnabledFeatures.h" #include "platform/graphics/ImageBuffer.h" #include "platform/graphics/UnacceleratedImageBufferSurface.h" @@ -68,9 +69,12 @@ } // namespace +class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub { +}; + class WebGraphicsContext3DForTests : public MockWebGraphicsContext3D { public: - WebGraphicsContext3DForTests() + WebGraphicsContext3DForTests(PassOwnPtr<GLES2InterfaceForTests> contextGL) : MockWebGraphicsContext3D() , m_boundTexture(0) , m_boundTextureTarget(0) @@ -78,6 +82,7 @@ , m_mostRecentlyWaitedSyncToken(0) , m_currentImageId(1) , m_allowImageChromium(true) + , m_contextGL(std::move(contextGL)) { } @@ -188,6 +193,11 @@ m_allowImageChromium = allow; } + gpu::gles2::GLES2Interface* getGLES2Interface() override + { + return m_contextGL.get(); + } + private: WebGLId m_boundTexture; WGC3Denum m_boundTextureTarget; @@ -199,6 +209,7 @@ HashMap<WGC3Duint, IntSize> m_imageSizes; HashMap<WGC3Duint, WebGLId> m_imageToTextureMap; bool m_allowImageChromium; + OwnPtr<GLES2InterfaceForTests> m_contextGL; }; static const int initialWidth = 100; @@ -207,12 +218,10 @@ class DrawingBufferForTests : public DrawingBuffer { public: - static PassRefPtr<DrawingBufferForTests> create(PassOwnPtr<WebGraphicsContext3D> context, - const IntSize& size, PreserveDrawingBuffer preserve) + static PassRefPtr<DrawingBufferForTests> create(PassOwnPtr<WebGraphicsContext3D> context, gpu::gles2::GLES2Interface* gl, const IntSize& size, PreserveDrawingBuffer preserve) { - OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get()); - RefPtr<DrawingBufferForTests> drawingBuffer = - adoptRef(new DrawingBufferForTests(context, extensionsUtil.release(), preserve)); + OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get(), gl); + RefPtr<DrawingBufferForTests> drawingBuffer = adoptRef(new DrawingBufferForTests(context, gl, extensionsUtil.release(), preserve)); if (!drawingBuffer->initialize(size)) { drawingBuffer->beginDestruction(); return PassRefPtr<DrawingBufferForTests>(); @@ -220,10 +229,8 @@ return drawingBuffer.release(); } - DrawingBufferForTests(PassOwnPtr<WebGraphicsContext3D> context, - PassOwnPtr<Extensions3DUtil> extensionsUtil, - PreserveDrawingBuffer preserve) - : DrawingBuffer(context, extensionsUtil, false /* multisampleExtensionSupported */, false /* discardFramebufferSupported */, preserve, WebGraphicsContext3D::Attributes()) + DrawingBufferForTests(PassOwnPtr<WebGraphicsContext3D> context, gpu::gles2::GLES2Interface* gl, PassOwnPtr<Extensions3DUtil> extensionsUtil, PreserveDrawingBuffer preserve) + : DrawingBuffer(context, gl, extensionsUtil, false /* multisampleExtensionSupported */, false /* discardFramebufferSupported */, preserve, WebGraphicsContext3D::Attributes()) , m_live(0) { } @@ -240,9 +247,11 @@ protected: void SetUp() override { - OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests); + OwnPtr<GLES2InterfaceForTests> gl = adoptPtr(new GLES2InterfaceForTests); + m_gl = gl.get(); + OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(gl.release())); m_context = context.get(); - m_drawingBuffer = DrawingBufferForTests::create(context.release(), + m_drawingBuffer = DrawingBufferForTests::create(context.release(), m_gl, IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve); } @@ -252,6 +261,7 @@ } WebGraphicsContext3DForTests* m_context; + gpu::gles2::GLES2Interface* m_gl; RefPtr<DrawingBufferForTests> m_drawingBuffer; }; @@ -466,12 +476,14 @@ protected: void SetUp() override { - OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests); + OwnPtr<GLES2InterfaceForTests> gl = adoptPtr(new GLES2InterfaceForTests); + m_gl = gl.get(); + OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(gl.release())); m_context = context.get(); RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(true); m_imageId0 = webContext()->nextImageIdToBeCreated(); EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId0)).Times(1); - m_drawingBuffer = DrawingBufferForTests::create(context.release(), + m_drawingBuffer = DrawingBufferForTests::create(context.release(), m_gl, IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve); testing::Mock::VerifyAndClearExpectations(webContext()); } @@ -613,11 +625,14 @@ MockWebGraphicsContext3D::getIntegerv(ptype, value); } + gpu::gles2::GLES2Interface* getGLES2Interface() override { return &m_contextGL; } + private: WebGLId m_nextRenderBufferId; WebGLId m_stencilAttachment; WebGLId m_depthAttachment; WebGLId m_depthStencilAttachment; + gpu::gles2::GLES2InterfaceStub m_contextGL; }; struct DepthStencilTestCase { @@ -713,11 +728,13 @@ protected: void SetUp() override { - OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests); + OwnPtr<GLES2InterfaceForTests> gl = adoptPtr(new GLES2InterfaceForTests); + m_gl = gl.get(); + OwnPtr<WebGraphicsContext3DForTests> context = adoptPtr(new WebGraphicsContext3DForTests(gl.release())); context->setAllowImageChromium(false); m_context = context.get(); RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(true); - m_drawingBuffer = DrawingBufferForTests::create(context.release(), + m_drawingBuffer = DrawingBufferForTests::create(context.release(), m_gl, IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve); }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp b/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp index 47af1934..4941e8d 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.cpp
@@ -4,6 +4,7 @@ #include "platform/graphics/gpu/Extensions3DUtil.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "public/platform/WebGraphicsContext3D.h" #include "wtf/text/CString.h" #include "wtf/text/StringHash.h" @@ -22,15 +23,16 @@ } // anonymous namespace -PassOwnPtr<Extensions3DUtil> Extensions3DUtil::create(WebGraphicsContext3D* context) +PassOwnPtr<Extensions3DUtil> Extensions3DUtil::create(WebGraphicsContext3D* context, gpu::gles2::GLES2Interface* gl) { - OwnPtr<Extensions3DUtil> out = adoptPtr(new Extensions3DUtil(context)); + OwnPtr<Extensions3DUtil> out = adoptPtr(new Extensions3DUtil(context, gl)); out->initializeExtensions(); return out.release(); } -Extensions3DUtil::Extensions3DUtil(WebGraphicsContext3D* context) +Extensions3DUtil::Extensions3DUtil(WebGraphicsContext3D* context, gpu::gles2::GLES2Interface* gl) : m_context(context) + , m_gl(gl) , m_isValid(true) { } @@ -41,7 +43,7 @@ void Extensions3DUtil::initializeExtensions() { - if (m_context->isContextLost()) { + if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) { // If the context is lost don't initialize the extension strings. // This will cause supportsExtension, ensureExtensionEnabled, and isExtensionEnabled to always return false. m_isValid = false;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h b/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h index ee6298c..0e36c32 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/Extensions3DUtil.h
@@ -15,6 +15,12 @@ #include "wtf/text/StringHash.h" #include "wtf/text/WTFString.h" +namespace gpu { +namespace gles2 { +class GLES2Interface; +} +} + namespace blink { class WebGraphicsContext3D; @@ -23,8 +29,8 @@ USING_FAST_MALLOC(Extensions3DUtil); WTF_MAKE_NONCOPYABLE(Extensions3DUtil); public: - // Creates a new Extensions3DUtil. If the passed WebGraphicsContext3D has been spontaneously lost, returns null. - static PassOwnPtr<Extensions3DUtil> create(WebGraphicsContext3D*); + // Creates a new Extensions3DUtil. If the passed GLES2Interface has been spontaneously lost, returns null. + static PassOwnPtr<Extensions3DUtil> create(WebGraphicsContext3D*, gpu::gles2::GLES2Interface*); ~Extensions3DUtil(); bool isValid() { return m_isValid; } @@ -36,10 +42,11 @@ static bool canUseCopyTextureCHROMIUM(GLenum destTarget, GLenum destFormat, GLenum destType, GLint level); private: - Extensions3DUtil(WebGraphicsContext3D*); + Extensions3DUtil(WebGraphicsContext3D*, gpu::gles2::GLES2Interface*); void initializeExtensions(); WebGraphicsContext3D* m_context; + gpu::gles2::GLES2Interface* m_gl; HashSet<String> m_enabledExtensions; HashSet<String> m_requestableExtensions; bool m_isValid;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp b/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp index 45067a61..0fc1996 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp
@@ -4,6 +4,7 @@ #include "platform/graphics/gpu/SharedContextRateLimiter.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "platform/graphics/gpu/Extensions3DUtil.h" #include "public/platform/Platform.h" #include "public/platform/WebGraphicsContext3D.h" @@ -28,9 +29,9 @@ if (!m_contextProvider) return; - WebGraphicsContext3D* context = m_contextProvider->context3d(); - if (context && !context->isContextLost()) { - OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context); + gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL(); + if (gl && gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { + OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(m_contextProvider->context3d(), gl); // TODO(junov): when the GLES 3.0 command buffer is ready, we could use fenceSync instead m_canUseSyncQueries = extensionsUtil->supportsExtension("GL_CHROMIUM_sync_query"); } @@ -41,11 +42,12 @@ if (!m_contextProvider) return; - WebGraphicsContext3D* context = m_contextProvider->context3d(); + gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL(); - if (!context || context->isContextLost()) + if (!gl || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) return; + WebGraphicsContext3D* context = m_contextProvider->context3d(); m_queries.append(m_canUseSyncQueries ? context->createQueryEXT() : 0); if (m_canUseSyncQueries) { context->beginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, m_queries.last()); @@ -69,8 +71,9 @@ if (!m_contextProvider) return; - WebGraphicsContext3D* context = m_contextProvider->context3d(); - if (context && !context->isContextLost()) { + gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL(); + if (gl && gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { + WebGraphicsContext3D* context = m_contextProvider->context3d(); while (m_queries.size() > 0) { context->deleteQueryEXT(m_queries.first()); m_queries.removeFirst();
diff --git a/third_party/WebKit/Source/platform/graphics/test/DEPS b/third_party/WebKit/Source/platform/graphics/test/DEPS new file mode 100644 index 0000000..67567cc --- /dev/null +++ b/third_party/WebKit/Source/platform/graphics/test/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+gpu/command_buffer/client/gles2_interface_stub.h", +]
diff --git a/third_party/WebKit/Source/platform/graphics/test/MockGLES2Interface.h b/third_party/WebKit/Source/platform/graphics/test/MockGLES2Interface.h new file mode 100644 index 0000000..ecab6e01 --- /dev/null +++ b/third_party/WebKit/Source/platform/graphics/test/MockGLES2Interface.h
@@ -0,0 +1,23 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MockGLES2Interface_h +#define MockGLES2Interface_h + +#include "gpu/command_buffer/client/gles2_interface_stub.h" + +class MockGLES2Interface : public gpu::gles2::GLES2InterfaceStub { +public: + GLenum GetGraphicsResetStatusKHR() override + { + return m_contextLost ? GL_INVALID_OPERATION : GL_NO_ERROR; + } + + void setIsContextLost(bool lost) { m_contextLost = lost; } + +private: + bool m_contextLost = false; +}; + +#endif // MockGLES2Interface_h
diff --git a/third_party/WebKit/Source/platform/graphics/test/MockWebGraphicsContext3D.h b/third_party/WebKit/Source/platform/graphics/test/MockWebGraphicsContext3D.h index d41a810..ff7c637 100644 --- a/third_party/WebKit/Source/platform/graphics/test/MockWebGraphicsContext3D.h +++ b/third_party/WebKit/Source/platform/graphics/test/MockWebGraphicsContext3D.h
@@ -47,8 +47,6 @@ virtual void synthesizeGLError(WGC3Denum) { } - virtual bool isContextLost() { return m_contextLost; } - virtual void* mapBufferSubDataCHROMIUM(WGC3Denum target, WGC3Dintptr offset, WGC3Dsizeiptr size, WGC3Denum access) { return 0; } virtual void unmapBufferSubDataCHROMIUM(const void*) { } virtual void* mapTexSubImage2DCHROMIUM(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format, WGC3Denum type, WGC3Denum access) { return 0; } @@ -285,6 +283,9 @@ virtual WebString getTranslatedShaderSourceANGLE(WebGLId) { return WebString(); } + // Don't use this, make a MockGLES2Interface instead. + virtual gpu::gles2::GLES2Interface* getGLES2Interface() { return nullptr; } + void fakeContextLost() { m_contextLost = true; } protected: unsigned m_nextTextureId;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h index 2d320b5..ff1a5aa 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -333,13 +333,11 @@ unsigned m_verticalScrollbarNeedsPaintInvalidation : 1; unsigned m_scrollCornerNeedsPaintInvalidation : 1; - // There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis + // There are 6 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis // if there is any reversed direction or writing-mode. The combinations are: // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set // horizontal-tb / ltr NO NO // horizontal-tb / rtl YES NO - // horizontal-bt / ltr NO YES - // horizontal-bt / rtl YES YES // vertical-lr / ltr NO NO // vertical-lr / rtl NO YES // vertical-rl / ltr YES NO
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp index aa5e01f8..8209374 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp
@@ -169,61 +169,6 @@ *result = makeEvalCall(errorString, function, wasThrown, exceptionDetails); } -void InjectedScript::restartFrame(ErrorString* errorString, v8::Local<v8::Object> callFrames, const String16& callFrameId) -{ - v8::HandleScope handles(m_isolate); - V8FunctionCall function(m_client, context(), v8Value(), "restartFrame"); - function.appendArgument(callFrames); - function.appendArgument(callFrameId); - OwnPtr<protocol::Value> resultValue = makeCall(function); - if (resultValue) { - if (resultValue->type() == protocol::Value::TypeString) { - resultValue->asString(errorString); - } else { - bool value; - ASSERT_UNUSED(value, resultValue->asBoolean(&value) && value); - } - return; - } - *errorString = "Internal error"; -} - -void InjectedScript::setVariableValue(ErrorString* errorString, - v8::Local<v8::Object> callFrames, - const protocol::Maybe<String16>& callFrameIdOpt, - const protocol::Maybe<String16>& functionObjectIdOpt, - int scopeNumber, - const String16& variableName, - const String16& newValueStr) -{ - v8::HandleScope handles(m_isolate); - V8FunctionCall function(m_client, context(), v8Value(), "setVariableValue"); - if (callFrameIdOpt.isJust()) { - function.appendArgument(callFrames); - function.appendArgument(callFrameIdOpt.fromJust()); - } else { - function.appendArgument(false); - function.appendArgument(false); - } - if (functionObjectIdOpt.isJust()) - function.appendArgument(functionObjectIdOpt.fromJust()); - else - function.appendArgument(false); - function.appendArgument(scopeNumber); - function.appendArgument(variableName); - function.appendArgument(newValueStr); - OwnPtr<protocol::Value> resultValue = makeCall(function); - if (!resultValue) { - *errorString = "Internal error"; - return; - } - if (resultValue->type() == protocol::Value::TypeString) { - resultValue->asString(errorString); - return; - } - // Normal return. -} - void InjectedScript::getFunctionDetails(ErrorString* errorString, const String16& functionId, OwnPtr<FunctionDetails>* result) { v8::HandleScope handles(m_isolate); @@ -531,4 +476,35 @@ m_manager->discardInjectedScript(m_contextId); } +v8::MaybeLocal<v8::Value> InjectedScript::resolveCallArgument(ErrorString* errorString, protocol::Runtime::CallArgument* callArgument) +{ + if (callArgument->hasObjectId()) { + OwnPtr<RemoteObjectId> remoteObjectId = RemoteObjectId::parse(errorString, callArgument->getObjectId("")); + if (!remoteObjectId) + return v8::MaybeLocal<v8::Value>(); + if (remoteObjectId->contextId() != m_contextId) { + *errorString = "Argument should belong to the same JavaScript world as target object"; + return v8::MaybeLocal<v8::Value>(); + } + v8::Local<v8::Value> object = findObject(*remoteObjectId); + if (object.IsEmpty()) { + *errorString = "Could not find object with given id"; + return v8::MaybeLocal<v8::Value>(); + } + return object; + } + if (callArgument->hasValue()) { + String16 value = callArgument->getValue(nullptr)->toJSONString(); + if (callArgument->getType(String16()) == "number") + value = "Number(" + value + ")"; + v8::Local<v8::Value> object; + if (!m_client->compileAndRunInternalScript(toV8String(m_isolate, value)).ToLocal(&object)) { + *errorString = "Couldn't parse value object in call argument"; + return v8::MaybeLocal<v8::Value>(); + } + return object; + } + return v8::Undefined(m_isolate); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.h b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.h index e94c78e..11cda71 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.h +++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.h
@@ -85,8 +85,6 @@ OwnPtr<protocol::Runtime::RemoteObject>* result, Maybe<bool>* wasThrown, Maybe<protocol::Runtime::ExceptionDetails>*); - void restartFrame(ErrorString*, v8::Local<v8::Object> callFrames, const String16& callFrameId); - void setVariableValue(ErrorString*, v8::Local<v8::Object> callFrames, const Maybe<String16>& callFrameIdOpt, const Maybe<String16>& functionObjectIdOpt, int scopeNumber, const String16& variableName, const String16& newValueStr); void getFunctionDetails(ErrorString*, const String16& functionId, OwnPtr<protocol::Debugger::FunctionDetails>* result); void getCollectionEntries(ErrorString*, const String16& objectId, OwnPtr<protocol::Array<protocol::Debugger::CollectionEntry>>* result); void getProperties(ErrorString*, const String16& objectId, bool ownProperties, bool accessorPropertiesOnly, bool generatePreview, OwnPtr<protocol::Array<protocol::Runtime::PropertyDescriptor>>* result, Maybe<protocol::Runtime::ExceptionDetails>*); @@ -112,6 +110,8 @@ v8::Local<v8::Context> context() const; void dispose(); + v8::MaybeLocal<v8::Value> resolveCallArgument(ErrorString*, protocol::Runtime::CallArgument*); + private: friend InjectedScript* InjectedScriptManager::injectedScriptFor(v8::Local<v8::Context>); InjectedScript(InjectedScriptManager*, v8::Local<v8::Context>, v8::Local<v8::Object>, V8DebuggerClient*, PassOwnPtr<InjectedScriptNative>, int contextId);
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js index ff7566a..52df626 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js +++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js
@@ -875,52 +875,6 @@ }, /** - * @param {!JavaScriptCallFrame} topCallFrame - * @param {string} callFrameId - * @return {*} - */ - restartFrame: function(topCallFrame, callFrameId) - { - var callFrame = this._callFrameForId(topCallFrame, callFrameId); - if (!callFrame) - return "Could not find call frame with given id"; - return callFrame.restart(); - }, - - /** - * Either callFrameId or functionObjectId must be specified. - * @param {!JavaScriptCallFrame} topCallFrame - * @param {string|boolean} callFrameId or false - * @param {string|boolean} functionObjectId or false - * @param {number} scopeNumber - * @param {string} variableName - * @param {string} newValueJsonString RuntimeAgent.CallArgument structure serialized as string - * @return {string|undefined} undefined if success or an error message - */ - setVariableValue: function(topCallFrame, callFrameId, functionObjectId, scopeNumber, variableName, newValueJsonString) - { - try { - var newValueJson = /** @type {!RuntimeAgent.CallArgument} */ (InjectedScriptHost.eval("(" + newValueJsonString + ")")); - var resolvedValue = this._resolveCallArgument(newValueJson); - if (typeof callFrameId === "string") { - var callFrame = this._callFrameForId(topCallFrame, callFrameId); - if (!callFrame) - return "Could not find call frame with given id"; - callFrame.setVariableValue(scopeNumber, variableName, resolvedValue) - } else { - var parsedFunctionId = this._parseObjectId(/** @type {string} */ (functionObjectId)); - var func = this._objectForId(parsedFunctionId); - if (typeof func !== "function") - return "Could not resolve function by id"; - InjectedScriptHost.setFunctionVariableValue(func, scopeNumber, variableName, resolvedValue); - } - } catch (e) { - return toString(e); - } - return undefined; - }, - - /** * @return {!CommandLineAPI} */ commandLineAPI: function()
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp index 0bcc44ca..8fa34af 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
@@ -643,9 +643,24 @@ return; v8::HandleScope scope(m_isolate); - v8::Local<v8::Object> callStack = m_currentCallStack.Get(m_isolate); - injectedScript->restartFrame(errorString, callStack, callFrameId); + v8::Local<v8::Context> localContext = injectedScript->context(); + + v8::TryCatch tryCatch(m_isolate); + + OwnPtr<JavaScriptCallFrame> javaScriptCallFrame = debugger().callFrameNoScopes(remoteId->frameOrdinal()); + if (!javaScriptCallFrame) { + *errorString = "Could not find call frame with given id"; + return; + } + v8::Local<v8::Value> resultValue; + v8::Local<v8::Boolean> result; + if (!javaScriptCallFrame->restart().ToLocal(&resultValue) || tryCatch.HasCaught() || !resultValue->ToBoolean(localContext).ToLocal(&result) || !result->Value()) { + *errorString = "Internal error"; + return; + } + m_currentCallStack.Reset(m_isolate, debugger().currentCallFrames()); + *newCallFrames = currentCallFrames(); *asyncStackTrace = currentAsyncStackTrace(); } @@ -921,39 +936,39 @@ void V8DebuggerAgentImpl::setVariableValue(ErrorString* errorString, int scopeNumber, const String16& variableName, - PassOwnPtr<protocol::Runtime::CallArgument> newValue, - const Maybe<String16>& callFrameId, - const Maybe<String16>& functionObjectId) + PassOwnPtr<protocol::Runtime::CallArgument> newValueArgument, + const String16& callFrameId) { if (!checkEnabled(errorString)) return; - InjectedScript* injectedScript = nullptr; - if (callFrameId.isJust()) { - if (!isPaused() || m_currentCallStack.IsEmpty()) { - *errorString = "Attempt to access callframe when debugger is not on pause"; - return; - } - OwnPtr<RemoteCallFrameId> remoteId = RemoteCallFrameId::parse(errorString, callFrameId.fromJust()); - if (!remoteId) - return; - injectedScript = m_injectedScriptManager->findInjectedScript(errorString, remoteId.get()); - if (!injectedScript) - return; - } else if (functionObjectId.isJust()) { - OwnPtr<RemoteObjectId> remoteId = RemoteObjectId::parse(errorString, functionObjectId.fromJust()); - if (!remoteId) - return; - injectedScript = m_injectedScriptManager->findInjectedScript(errorString, remoteId.get()); - if (!injectedScript) - return; - } else { - *errorString = "Either call frame or function object must be specified"; + if (!isPaused() || m_currentCallStack.IsEmpty()) { + *errorString = "Attempt to access callframe when debugger is not on pause"; return; } - String16 newValueString = protocol::toValue(newValue.get())->toJSONString(); + OwnPtr<RemoteCallFrameId> remoteId = RemoteCallFrameId::parse(errorString, callFrameId); + if (!remoteId) + return; + InjectedScript* injectedScript = m_injectedScriptManager->findInjectedScript(errorString, remoteId.get()); + if (!injectedScript) + return; + v8::HandleScope scope(m_isolate); - v8::Local<v8::Object> currentCallStack = m_currentCallStack.Get(m_isolate); - injectedScript->setVariableValue(errorString, currentCallStack, callFrameId, functionObjectId, scopeNumber, variableName, newValueString); + v8::TryCatch tryCatch(m_isolate); + + v8::Local<v8::Value> newValue; + if (!injectedScript->resolveCallArgument(errorString, newValueArgument.get()).ToLocal(&newValue)) + return; + + OwnPtr<JavaScriptCallFrame> javaScriptCallFrame = debugger().callFrameNoScopes(remoteId->frameOrdinal()); + if (!javaScriptCallFrame) { + *errorString = "Could not find call frame with given id"; + return; + } + v8::MaybeLocal<v8::Value> result = javaScriptCallFrame->setVariableValue(scopeNumber, toV8String(m_isolate, variableName), newValue); + if (tryCatch.HasCaught() || result.IsEmpty()) { + *errorString = "Internal error"; + return; + } } void V8DebuggerAgentImpl::setAsyncCallStackDepth(ErrorString* errorString, int depth)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h index 827ccc7..127a8ee 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h
@@ -136,8 +136,7 @@ int scopeNumber, const String16& variableName, PassOwnPtr<protocol::Runtime::CallArgument> newValue, - const Maybe<String16>& callFrame, - const Maybe<String16>& functionObjectId) override; + const String16& callFrame) override; void setAsyncCallStackDepth(ErrorString*, int depth) override; void enablePromiseTracker(ErrorString*, const Maybe<bool>& captureStacks) override;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp index 11a19cc9..1424ccf 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp
@@ -346,22 +346,6 @@ v8SetReturnValue(info, wrappedResult); } -void V8InjectedScriptHost::setFunctionVariableValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - if (info.Length() < 4 || !info[0]->IsFunction() || !info[1]->IsInt32() || !info[2]->IsString()) - return; - - v8::Local<v8::Value> functionValue = info[0]; - int scopeIndex = info[1].As<v8::Int32>()->Value(); - String16 variableName = toProtocolStringWithTypeCheck(info[2]); - v8::Local<v8::Value> newValue = info[3]; - - InjectedScriptHost* host = V8InjectedScriptHost::unwrap(info.GetIsolate()->GetCurrentContext(), info.Holder()); - if (!host->debugger()) - return; - v8SetReturnValue(info, host->debugger()->setFunctionVariableValue(functionValue, scopeIndex, variableName, newValue)); -} - static bool getFunctionLocation(const v8::FunctionCallbackInfo<v8::Value>& info, String16* scriptId, int* lineNumber, int* columnNumber) { if (info.Length() < 1 || !info[0]->IsFunction()) @@ -580,7 +564,6 @@ {"callFunction", V8InjectedScriptHost::callFunctionCallback}, {"suppressWarningsAndCallFunction", V8InjectedScriptHost::suppressWarningsAndCallFunctionCallback}, {"setNonEnumProperty", V8InjectedScriptHost::setNonEnumPropertyCallback}, - {"setFunctionVariableValue", V8InjectedScriptHost::setFunctionVariableValueCallback}, {"bind", V8InjectedScriptHost::bindCallback}, {"objectForId", V8InjectedScriptHost::objectForIdCallback}, {"idToObjectGroupName", V8InjectedScriptHost::idToObjectGroupNameCallback},
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8JavaScriptCallFrame.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8JavaScriptCallFrame.cpp index b6801001..f38f84c 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8JavaScriptCallFrame.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8JavaScriptCallFrame.cpp
@@ -99,29 +99,6 @@ info.GetReturnValue().Set(impl->evaluateWithExceptionDetails(info[0], info[1])); } -void restartMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.GetIsolate()->GetCurrentContext(), info.Holder()); - v8::MaybeLocal<v8::Value> result = impl->restart(); - v8::Local<v8::Value> value; - if (result.ToLocal(&value)) - info.GetReturnValue().Set(value); -} - -void setVariableValueMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.GetIsolate()->GetCurrentContext(), info.Holder()); - v8::Maybe<int32_t> maybeScopeIndex = info[0]->Int32Value(info.GetIsolate()->GetCurrentContext()); - if (maybeScopeIndex.IsNothing()) - return; - int scopeIndex = maybeScopeIndex.FromJust(); - v8::MaybeLocal<v8::Value> result = impl->setVariableValue(scopeIndex, info[1], info[2]); - v8::Local<v8::Value> value; - if (result.ToLocal(&value)) - info.GetReturnValue().Set(value); - -} - void scopeTypeMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.GetIsolate()->GetCurrentContext(), info.Holder()); @@ -184,8 +161,6 @@ const JavaScriptCallFrameWrapper::V8MethodConfiguration V8JavaScriptCallFrameMethods[] = { {"evaluateWithExceptionDetails", evaluateWithExceptionDetailsMethodCallback}, - {"restart", restartMethodCallback}, - {"setVariableValue", setVariableValueMethodCallback}, {"scopeType", scopeTypeMethodCallback}, {"scopeName", scopeNameMethodCallback}, {"scopeStartLocation", scopeStartLocationMethodCallback},
diff --git a/third_party/WebKit/Source/platform/v8_inspector/injected_script_externs.js b/third_party/WebKit/Source/platform/v8_inspector/injected_script_externs.js index 8a0323d0..4d5cdbf 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/injected_script_externs.js +++ b/third_party/WebKit/Source/platform/v8_inspector/injected_script_externs.js
@@ -128,15 +128,6 @@ InjectedScriptHostClass.prototype.setNonEnumProperty = function(obj, key, value) {} /** - * @param {!Function} functionObject - * @param {number} scopeIndex - * @param {string} variableName - * @param {*} newValue - * @return {*} - */ -InjectedScriptHostClass.prototype.setFunctionVariableValue = function(functionObject, scopeIndex, variableName, newValue) {} - -/** * @param {*} value * @param {string} groupName * @return {number} @@ -195,19 +186,6 @@ JavaScriptCallFrame.prototype.evaluateWithExceptionDetails = function(script, scopeExtension) {} /** - * @return {*} - */ -JavaScriptCallFrame.prototype.restart = function() {} - -/** - * @param {number=} scopeIndex - * @param {?string=} variableName - * @param {*=} newValue - * @return {*} - */ -JavaScriptCallFrame.prototype.setVariableValue = function(scopeIndex, variableName, newValue) {} - -/** * @param {number} scopeIndex * @return {number} */
diff --git a/third_party/WebKit/Source/web/AssociatedURLLoader.cpp b/third_party/WebKit/Source/web/AssociatedURLLoader.cpp index 71ab8d9d..570718ff 100644 --- a/third_party/WebKit/Source/web/AssociatedURLLoader.cpp +++ b/third_party/WebKit/Source/web/AssociatedURLLoader.cpp
@@ -93,7 +93,7 @@ if (equalIgnoringCase(headerName, "access-control-expose-headers")) parseAccessControlExposeHeadersAllowList(value, m_exposedHeaders); else if (!isOnAccessControlResponseHeaderWhitelist(headerName)) - m_blockedHeaders.add(name); + m_blockedHeaders.add(static_cast<String>(name)); } }
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn index 1df6a315..edeb26e 100644 --- a/third_party/WebKit/Source/web/BUILD.gn +++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -95,6 +95,7 @@ "//base:i18n", "//base/test:test_support", "//content/test:test_support", + "//gpu:test_support", "//testing/gmock", "//testing/gtest", "//third_party/WebKit/Source/core",
diff --git a/third_party/WebKit/Source/web/web_tests.gyp b/third_party/WebKit/Source/web/web_tests.gyp index abe3a93..611dde3 100644 --- a/third_party/WebKit/Source/web/web_tests.gyp +++ b/third_party/WebKit/Source/web/web_tests.gyp
@@ -56,6 +56,7 @@ '<(DEPTH)/base/base.gyp:base', '<(DEPTH)/base/base.gyp:base_i18n', '<(DEPTH)/base/base.gyp:test_support_base', + '<(DEPTH)/gpu/gpu.gyp:gpu_unittest_utils', '<(DEPTH)/testing/gmock.gyp:gmock', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/libwebp/libwebp.gyp:libwebp',
diff --git a/third_party/WebKit/Source/wtf/HashSet.h b/third_party/WebKit/Source/wtf/HashSet.h index 59fd57b..752a4c58 100644 --- a/third_party/WebKit/Source/wtf/HashSet.h +++ b/third_party/WebKit/Source/wtf/HashSet.h
@@ -93,7 +93,8 @@ // The return value is a pair of an iterator to the new value's location, // and a bool that is true if an new entry was added. - AddResult add(ValuePassInType); + template <typename IncomingValueType> + AddResult add(IncomingValueType&&); // An alternate version of add() that finds the object by hashing and // comparing with some other type, to avoid the cost of type conversion if @@ -101,8 +102,8 @@ // following function members: // static unsigned hash(const T&); // static bool equal(const ValueType&, const T&); - // static translate(ValueType&, const T&, unsigned hashCode); - template <typename HashTranslator, typename T> AddResult add(const T&); + // static translate(ValueType&, T&&, unsigned hashCode); + template <typename HashTranslator, typename T> AddResult addWithTranslator(T&&); void remove(ValuePeekInType); void remove(iterator); @@ -132,9 +133,9 @@ STATIC_ONLY(HashSetTranslatorAdapter); template <typename T> static unsigned hash(const T& key) { return Translator::hash(key); } template <typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); } - template <typename T, typename U> static void translate(T& location, const U& key, const U&, unsigned hashCode) + template <typename T, typename U, typename V> static void translate(T& location, U&& key, const V&, unsigned hashCode) { - Translator::translate(location, key, hashCode); + Translator::translate(location, std::forward<U>(key), hashCode); } }; @@ -196,17 +197,19 @@ } template <typename T, typename U, typename V, typename W> -inline typename HashSet<T, U, V, W>::AddResult HashSet<T, U, V, W>::add(ValuePassInType value) +template <typename IncomingValueType> +inline typename HashSet<T, U, V, W>::AddResult HashSet<T, U, V, W>::add(IncomingValueType&& value) { - return m_impl.add(value); + return m_impl.add(std::forward<IncomingValueType>(value)); } template <typename Value, typename HashFunctions, typename Traits, typename Allocator> template <typename HashTranslator, typename T> inline typename HashSet<Value, HashFunctions, Traits, Allocator>::AddResult -HashSet<Value, HashFunctions, Traits, Allocator>::add(const T& value) +HashSet<Value, HashFunctions, Traits, Allocator>::addWithTranslator(T&& value) { - return m_impl.template addPassingHashCode<HashSetTranslatorAdapter<HashTranslator>>(value, value); + // Forward only the first argument, because the second argument isn't actually used in HashSetTranslatorAdapter. + return m_impl.template addPassingHashCode<HashSetTranslatorAdapter<HashTranslator>>(std::forward<T>(value), value); } template <typename T, typename U, typename V, typename W>
diff --git a/third_party/WebKit/Source/wtf/HashSetTest.cpp b/third_party/WebKit/Source/wtf/HashSetTest.cpp index b21026b8..87db991 100644 --- a/third_party/WebKit/Source/wtf/HashSetTest.cpp +++ b/third_party/WebKit/Source/wtf/HashSetTest.cpp
@@ -266,6 +266,129 @@ EXPECT_EQ(0, counter); } +class MoveOnly { +public: + // kEmpty and kDeleted have special meanings when MoveOnly is used as the key of a hash table. + enum { + kEmpty = 0, + kDeleted = -1, + kMovedOut = -2 + }; + + explicit MoveOnly(int value = kEmpty, int id = 0) : m_value(value), m_id(id) { } + MoveOnly(MoveOnly&& other) + : m_value(other.m_value) + , m_id(other.m_id) + { + other.m_value = kMovedOut; + other.m_id = 0; + } + MoveOnly& operator=(MoveOnly&& other) + { + m_value = other.m_value; + m_id = other.m_id; + other.m_value = kMovedOut; + other.m_id = 0; + return *this; + } + + int value() const { return m_value; } + // id() is used for distinguishing MoveOnlys with the same value(). + int id() const { return m_id; } + +private: + MoveOnly(const MoveOnly&) = delete; + MoveOnly& operator=(const MoveOnly&) = delete; + + int m_value; + int m_id; +}; + +struct MoveOnlyHashTraits : public GenericHashTraits<MoveOnly> { + // This is actually true, but we pretend that it's false to disable the optimization. + static const bool emptyValueIsZero = false; + + static const bool hasIsEmptyValueFunction = true; + static bool isEmptyValue(const MoveOnly& value) { return value.value() == MoveOnly::kEmpty; } + static void constructDeletedValue(MoveOnly& slot, bool) { slot = MoveOnly(MoveOnly::kDeleted); } + static bool isDeletedValue(const MoveOnly& value) { return value.value() == MoveOnly::kDeleted; } +}; + +struct MoveOnlyHash { + static unsigned hash(const MoveOnly& value) { return DefaultHash<int>::Hash::hash(value.value()); } + static bool equal(const MoveOnly& left, const MoveOnly& right) + { + return DefaultHash<int>::Hash::equal(left.value(), right.value()); + } + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +} // anonymous namespace + +template <> +struct HashTraits<MoveOnly> : public MoveOnlyHashTraits { }; + +template <> +struct DefaultHash<MoveOnly> { + using Hash = MoveOnlyHash; +}; + +namespace { + +TEST(HashSetTest, MoveOnlyValue) +{ + using TheSet = HashSet<MoveOnly>; + TheSet set; + { + TheSet::AddResult addResult = set.add(MoveOnly(1, 1)); + EXPECT_TRUE(addResult.isNewEntry); + EXPECT_EQ(1, addResult.storedValue->value()); + EXPECT_EQ(1, addResult.storedValue->id()); + } + auto iter = set.find(MoveOnly(1)); + ASSERT_TRUE(iter != set.end()); + EXPECT_EQ(1, iter->value()); + + iter = set.find(MoveOnly(2)); + EXPECT_TRUE(iter == set.end()); + + for (int i = 2; i < 32; ++i) { + TheSet::AddResult addResult = set.add(MoveOnly(i, i)); + EXPECT_TRUE(addResult.isNewEntry); + EXPECT_EQ(i, addResult.storedValue->value()); + EXPECT_EQ(i, addResult.storedValue->id()); + } + + iter = set.find(MoveOnly(1)); + ASSERT_TRUE(iter != set.end()); + EXPECT_EQ(1, iter->value()); + EXPECT_EQ(1, iter->id()); + + iter = set.find(MoveOnly(7)); + ASSERT_TRUE(iter != set.end()); + EXPECT_EQ(7, iter->value()); + EXPECT_EQ(7, iter->id()); + + { + TheSet::AddResult addResult = set.add(MoveOnly(7, 777)); // With different ID for identification. + EXPECT_FALSE(addResult.isNewEntry); + EXPECT_EQ(7, addResult.storedValue->value()); + EXPECT_EQ(7, addResult.storedValue->id()); + } + + set.remove(MoveOnly(11)); + iter = set.find(MoveOnly(11)); + EXPECT_TRUE(iter == set.end()); + + MoveOnly thirteen(set.take(MoveOnly(13))); + EXPECT_EQ(13, thirteen.value()); + EXPECT_EQ(13, thirteen.id()); + iter = set.find(MoveOnly(13)); + EXPECT_TRUE(iter == set.end()); + + set.clear(); +} + } // anonymous namespace } // namespace WTF
diff --git a/third_party/WebKit/Source/wtf/HashTable.h b/third_party/WebKit/Source/wtf/HashTable.h index bc20680..373dbda 100644 --- a/third_party/WebKit/Source/wtf/HashTable.h +++ b/third_party/WebKit/Source/wtf/HashTable.h
@@ -456,16 +456,17 @@ void reserveCapacityForSize(unsigned size); - AddResult add(ValuePassInType value) + template <typename IncomingValueType> + AddResult add(IncomingValueType&& value) { - return add<IdentityTranslatorType>(Extractor::extract(value), value); + return add<IdentityTranslatorType>(Extractor::extract(value), std::forward<IncomingValueType>(value)); } // A special version of add() that finds the object by hashing and comparing // with some other type, to avoid the cost of type conversion if the object // is already in the table. template <typename HashTranslator, typename T, typename Extra> AddResult add(T&& key, Extra&&); - template <typename HashTranslator, typename T, typename Extra> AddResult addPassingHashCode(const T& key, const Extra&); + template <typename HashTranslator, typename T, typename Extra> AddResult addPassingHashCode(T&& key, Extra&&); iterator find(KeyPeekInType key) { return find<IdentityTranslatorType>(key); } const_iterator find(KeyPeekInType key) const { return find<IdentityTranslatorType>(key); } @@ -863,7 +864,7 @@ template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator> template <typename HashTranslator, typename T, typename Extra> -typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::addPassingHashCode(const T& key, const Extra& extra) +typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::addPassingHashCode(T&& key, Extra&& extra) { ASSERT(!m_accessForbidden); ASSERT(Allocator::isAllocationAllowed()); @@ -886,7 +887,7 @@ --m_deletedCount; } - HashTranslator::translate(*entry, key, extra, h); + HashTranslator::translate(*entry, std::forward<T>(key), std::forward<Extra>(extra), h); ASSERT(!isEmptyOrDeletedBucket(*entry)); ++m_keyCount;
diff --git a/third_party/WebKit/Source/wtf/ListHashSetTest.cpp b/third_party/WebKit/Source/wtf/ListHashSetTest.cpp index 3ec993f5..20d8827e 100644 --- a/third_party/WebKit/Source/wtf/ListHashSetTest.cpp +++ b/third_party/WebKit/Source/wtf/ListHashSetTest.cpp
@@ -30,14 +30,21 @@ #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" +#include <type_traits> namespace WTF { namespace { template <typename Set> -void removeFirstHelper() +class ListOrLinkedHashSetTest : public ::testing::Test { }; + +using SetTypes = ::testing::Types<ListHashSet<int>, ListHashSet<int, 1>, LinkedHashSet<int>>; +TYPED_TEST_CASE(ListOrLinkedHashSetTest, SetTypes); + +TYPED_TEST(ListOrLinkedHashSetTest, RemoveFirst) { + using Set = TypeParam; Set list; list.add(-1); list.add(0); @@ -64,20 +71,9 @@ EXPECT_TRUE(list.isEmpty()); } -TEST(ListHashSetTest, RemoveFirst) +TYPED_TEST(ListOrLinkedHashSetTest, AppendOrMoveToLastNewItems) { - removeFirstHelper<ListHashSet<int>>(); - removeFirstHelper<ListHashSet<int, 1>>(); -} - -TEST(LinkedHashSetTest, RemoveFirst) -{ - removeFirstHelper<LinkedHashSet<int>>(); -} - -template <typename Set> -void appendOrMoveToLastNewItems() -{ + using Set = TypeParam; Set list; typename Set::AddResult result = list.appendOrMoveToLast(1); EXPECT_TRUE(result.isNewEntry); @@ -98,20 +94,9 @@ ++iterator; } -TEST(ListHashSetTest, AppendOrMoveToLastNewItems) +TYPED_TEST(ListOrLinkedHashSetTest, AppendOrMoveToLastWithDuplicates) { - appendOrMoveToLastNewItems<ListHashSet<int>>(); - appendOrMoveToLastNewItems<ListHashSet<int, 1>>(); -} - -TEST(LinkedHashSetTest, AppendOrMoveToLastNewItems) -{ - appendOrMoveToLastNewItems<LinkedHashSet<int>>(); -} - -template <typename Set> -void appendOrMoveToLastWithDuplicates() -{ + using Set = TypeParam; Set list; // Add a single element twice. @@ -149,20 +134,9 @@ ++iterator; } -TEST(ListHashSetTest, AppendOrMoveToLastWithDuplicates) +TYPED_TEST(ListOrLinkedHashSetTest, PrependOrMoveToFirstNewItems) { - appendOrMoveToLastWithDuplicates<ListHashSet<int>>(); - appendOrMoveToLastWithDuplicates<ListHashSet<int, 1>>(); -} - -TEST(LinkedHashSetTest, AppendOrMoveToLastWithDuplicates) -{ - appendOrMoveToLastWithDuplicates<LinkedHashSet<int>>(); -} - -template <typename Set> -void prependOrMoveToFirstNewItems() -{ + using Set = TypeParam; Set list; typename Set::AddResult result = list.prependOrMoveToFirst(1); EXPECT_TRUE(result.isNewEntry); @@ -183,20 +157,9 @@ ++iterator; } -TEST(ListHashSetTest, PrependOrMoveToFirstNewItems) +TYPED_TEST(ListOrLinkedHashSetTest, PrependOrMoveToLastWithDuplicates) { - prependOrMoveToFirstNewItems<ListHashSet<int>>(); - prependOrMoveToFirstNewItems<ListHashSet<int, 1>>(); -} - -TEST(LinkedHashSetTest, PrependOrMoveToFirstNewItems) -{ - prependOrMoveToFirstNewItems<LinkedHashSet<int>>(); -} - -template <typename Set> -void prependOrMoveToLastWithDuplicates() -{ + using Set = TypeParam; Set list; // Add a single element twice. @@ -234,80 +197,9 @@ ++iterator; } -TEST(ListHashSetTest, PrependOrMoveToLastWithDuplicates) +TYPED_TEST(ListOrLinkedHashSetTest, Find) { - prependOrMoveToLastWithDuplicates<ListHashSet<int>>(); - prependOrMoveToLastWithDuplicates<ListHashSet<int, 1>>(); -} - -TEST(LinkedHashSetTest, PrependOrMoveToLastWithDuplicates) -{ - prependOrMoveToLastWithDuplicates<LinkedHashSet<int>>(); -} - -class DummyRefCounted : public RefCounted<DummyRefCounted> { -public: - DummyRefCounted(bool& isDeleted) : m_isDeleted(isDeleted) { m_isDeleted = false; } - ~DummyRefCounted() { m_isDeleted = true; } - void ref() - { - WTF::RefCounted<DummyRefCounted>::ref(); - ++m_refInvokesCount; - } - - static int m_refInvokesCount; - -private: - bool& m_isDeleted; -}; - -int DummyRefCounted::m_refInvokesCount = 0; - -template <typename Set> -void withRefPtr() -{ - bool isDeleted = false; - DummyRefCounted::m_refInvokesCount = 0; - RefPtr<DummyRefCounted> ptr = adoptRef(new DummyRefCounted(isDeleted)); - EXPECT_EQ(0, DummyRefCounted::m_refInvokesCount); - - Set set; - set.add(ptr); - // Referenced only once (to store a copy in the container). - EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); - EXPECT_EQ(ptr, set.first()); - EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); - - DummyRefCounted* rawPtr = ptr.get(); - - EXPECT_TRUE(set.contains(ptr)); - EXPECT_TRUE(set.contains(rawPtr)); - EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); - - ptr.clear(); - EXPECT_FALSE(isDeleted); - EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); - - set.remove(rawPtr); - EXPECT_TRUE(isDeleted); - - EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); -} - -TEST(ListHashSetTest, WithRefPtr) -{ - withRefPtr<ListHashSet<RefPtr<DummyRefCounted>>>(); - withRefPtr<ListHashSet<RefPtr<DummyRefCounted>, 1>>(); -} - -TEST(LinkedHashSetTest, WithRefPtr) -{ - withRefPtr<LinkedHashSet<RefPtr<DummyRefCounted>>>(); -} - -template <typename Set, typename SetRef, typename Iterator> -void findHelper() -{ + using Set = TypeParam; Set set; set.add(-1); set.add(0); @@ -315,33 +207,32 @@ set.add(2); set.add(3); - SetRef ref = set; - Iterator it = ref.find(2); - EXPECT_EQ(2, *it); - ++it; - EXPECT_EQ(3, *it); - --it; - --it; - EXPECT_EQ(1, *it); + { + const Set& ref = set; + typename Set::const_iterator it = ref.find(2); + EXPECT_EQ(2, *it); + ++it; + EXPECT_EQ(3, *it); + --it; + --it; + EXPECT_EQ(1, *it); + } + { + Set& ref = set; + typename Set::iterator it = ref.find(2); + EXPECT_EQ(2, *it); + ++it; + EXPECT_EQ(3, *it); + --it; + --it; + EXPECT_EQ(1, *it); + } } -TEST(ListHashSetTest, Find) +TYPED_TEST(ListOrLinkedHashSetTest, InsertBefore) { - findHelper<ListHashSet<int>, const ListHashSet<int>&, ListHashSet<int>::const_iterator>(); - findHelper<ListHashSet<int>, ListHashSet<int>&, ListHashSet<int>::iterator>(); - findHelper<ListHashSet<int, 1>, const ListHashSet<int, 1>&, ListHashSet<int, 1>::const_iterator>(); - findHelper<ListHashSet<int, 1>, ListHashSet<int, 1>&, ListHashSet<int, 1>::iterator>(); -} - -TEST(LinkedHashSetTest, Find) -{ - findHelper<LinkedHashSet<int>, const LinkedHashSet<int>&, LinkedHashSet<int>::const_iterator>(); - findHelper<LinkedHashSet<int>, LinkedHashSet<int>&, LinkedHashSet<int>::iterator>(); -} - -template <typename Set> -void insertBeforeHelper(bool canModifyWhileIterating) -{ + using Set = TypeParam; + bool canModifyWhileIterating = !std::is_same<Set, LinkedHashSet<int>>::value; Set set; set.add(-1); set.add(0); @@ -385,20 +276,10 @@ EXPECT_EQ(7u, set.size()); } -TEST(ListHashSetTest, InsertBefore) +TYPED_TEST(ListOrLinkedHashSetTest, AddReturnIterator) { - insertBeforeHelper<ListHashSet<int>>(true); - insertBeforeHelper<ListHashSet<int, 1>>(true); -} - -TEST(LinkedHashSetTest, InsertBefore) -{ - insertBeforeHelper<LinkedHashSet<int>>(false); -} - -template <typename Set> -void addReturnIterator(bool canModifyWhileIterating) -{ + using Set = TypeParam; + bool canModifyWhileIterating = !std::is_same<Set, LinkedHashSet<int>>::value; Set set; set.add(-1); set.add(0); @@ -443,20 +324,116 @@ EXPECT_EQ(4, set.last()); } -TEST(ListHashSetTest, AddReturnIterator) +TYPED_TEST(ListOrLinkedHashSetTest, Swap) { - addReturnIterator<ListHashSet<int>>(true); - addReturnIterator<ListHashSet<int, 1>>(true); + using Set = TypeParam; + int num = 10; + Set set0; + Set set1; + Set set2; + for (int i = 0; i < num; ++i) { + set1.add(i + 1); + set2.add(num - i); + } + + typename Set::iterator it1 = set1.begin(); + typename Set::iterator it2 = set2.begin(); + for (int i = 0; i < num; ++i, ++it1, ++it2) { + EXPECT_EQ(*it1, i + 1); + EXPECT_EQ(*it2, num - i); + } + EXPECT_EQ(set0.begin(), set0.end()); + EXPECT_EQ(it1, set1.end()); + EXPECT_EQ(it2, set2.end()); + + // Shift sets: 2->1, 1->0, 0->2 + set1.swap(set2); // Swap with non-empty sets. + set0.swap(set2); // Swap with an empty set. + + it1 = set0.begin(); + it2 = set1.begin(); + for (int i = 0; i < num; ++i, ++it1, ++it2) { + EXPECT_EQ(*it1, i + 1); + EXPECT_EQ(*it2, num - i); + } + EXPECT_EQ(it1, set0.end()); + EXPECT_EQ(it2, set1.end()); + EXPECT_EQ(set2.begin(), set2.end()); + + int removedIndex = num >> 1; + set0.remove(removedIndex + 1); + set1.remove(num - removedIndex); + + it1 = set0.begin(); + it2 = set1.begin(); + for (int i = 0; i < num; ++i, ++it1, ++it2) { + if (i == removedIndex) + ++i; + EXPECT_EQ(*it1, i + 1); + EXPECT_EQ(*it2, num - i); + } + EXPECT_EQ(it1, set0.end()); + EXPECT_EQ(it2, set1.end()); } -TEST(LinkedHashSetTest, AddReturnIterator) -{ - addReturnIterator<LinkedHashSet<int>>(false); -} +class DummyRefCounted : public RefCounted<DummyRefCounted> { +public: + DummyRefCounted(bool& isDeleted) : m_isDeleted(isDeleted) { m_isDeleted = false; } + ~DummyRefCounted() { m_isDeleted = true; } + void ref() + { + WTF::RefCounted<DummyRefCounted>::ref(); + ++m_refInvokesCount; + } + + static int m_refInvokesCount; + +private: + bool& m_isDeleted; +}; + +int DummyRefCounted::m_refInvokesCount = 0; template <typename Set> -void excerciseValuePeekInType() +class ListOrLinkedHashSetRefPtrTest : public ::testing::Test { }; + +using RefPtrSetTypes = ::testing::Types<ListHashSet<RefPtr<DummyRefCounted>>, ListHashSet<RefPtr<DummyRefCounted>, 1>, LinkedHashSet<RefPtr<DummyRefCounted>>>; +TYPED_TEST_CASE(ListOrLinkedHashSetRefPtrTest, RefPtrSetTypes); + +TYPED_TEST(ListOrLinkedHashSetRefPtrTest, WithRefPtr) { + using Set = TypeParam; + bool isDeleted = false; + DummyRefCounted::m_refInvokesCount = 0; + RefPtr<DummyRefCounted> ptr = adoptRef(new DummyRefCounted(isDeleted)); + EXPECT_EQ(0, DummyRefCounted::m_refInvokesCount); + + Set set; + set.add(ptr); + // Referenced only once (to store a copy in the container). + EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); + EXPECT_EQ(ptr, set.first()); + EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); + + DummyRefCounted* rawPtr = ptr.get(); + + EXPECT_TRUE(set.contains(ptr)); + EXPECT_TRUE(set.contains(rawPtr)); + EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); + + ptr.clear(); + EXPECT_FALSE(isDeleted); + EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); + + set.remove(rawPtr); + EXPECT_TRUE(isDeleted); + + EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount); +} + +TYPED_TEST(ListOrLinkedHashSetRefPtrTest, ExerciseValuePeekInType) +{ + using Set = TypeParam; Set set; bool isDeleted = false; bool isDeleted2 = false; @@ -491,17 +468,6 @@ EXPECT_EQ(0u, set.size()); } -TEST(ListHashSetTest, ExcerciseValuePeekInType) -{ - excerciseValuePeekInType<ListHashSet<RefPtr<DummyRefCounted>>>(); - excerciseValuePeekInType<ListHashSet<RefPtr<DummyRefCounted>, 1>>(); -} - -TEST(LinkedHashSetTest, ExcerciseValuePeekInType) -{ - excerciseValuePeekInType<LinkedHashSet<RefPtr<DummyRefCounted>>>(); -} - struct Simple { Simple(int value) : m_value(value) { }; int m_value; @@ -537,8 +503,17 @@ }; template <typename Set> -void translatorTest() +class ListOrLinkedHashSetTranslatorTest : public ::testing::Test { }; + +using TranslatorSetTypes = ::testing::Types< + ListHashSet<Complicated, 256, ComplicatedHashFunctions>, + ListHashSet<Complicated, 1, ComplicatedHashFunctions>, + LinkedHashSet<Complicated, ComplicatedHashFunctions>>; +TYPED_TEST_CASE(ListOrLinkedHashSetTranslatorTest, TranslatorSetTypes); + +TYPED_TEST(ListOrLinkedHashSetTranslatorTest, ComplexityTranslator) { + using Set = TypeParam; Set set; set.add(Complicated(42)); int baseLine = Complicated::s_objectsConstructed; @@ -562,17 +537,6 @@ EXPECT_EQ(baseLine, Complicated::s_objectsConstructed); } -TEST(ListHashSetTest, ComplexityTranslator) -{ - translatorTest<ListHashSet<Complicated, 256, ComplicatedHashFunctions>>(); - translatorTest<ListHashSet<Complicated, 1, ComplicatedHashFunctions>>(); -} - -TEST(LinkedHashSetTest, ComplexityTranslator) -{ - translatorTest<LinkedHashSet<Complicated, ComplicatedHashFunctions>>(); -} - struct Dummy { Dummy(bool& deleted) : deleted(deleted) { } @@ -657,68 +621,6 @@ EXPECT_EQ(ptr2, ownPtr2); } -template <typename Set> -void swapTestHelper() -{ - int num = 10; - Set set0; - Set set1; - Set set2; - for (int i = 0; i < num; ++i) { - set1.add(i + 1); - set2.add(num - i); - } - - typename Set::iterator it1 = set1.begin(); - typename Set::iterator it2 = set2.begin(); - for (int i = 0; i < num; ++i, ++it1, ++it2) { - EXPECT_EQ(*it1, i + 1); - EXPECT_EQ(*it2, num - i); - } - EXPECT_EQ(set0.begin(), set0.end()); - EXPECT_EQ(it1, set1.end()); - EXPECT_EQ(it2, set2.end()); - - // Shift sets: 2->1, 1->0, 0->2 - set1.swap(set2); // Swap with non-empty sets. - set0.swap(set2); // Swap with an empty set. - - it1 = set0.begin(); - it2 = set1.begin(); - for (int i = 0; i < num; ++i, ++it1, ++it2) { - EXPECT_EQ(*it1, i + 1); - EXPECT_EQ(*it2, num - i); - } - EXPECT_EQ(it1, set0.end()); - EXPECT_EQ(it2, set1.end()); - EXPECT_EQ(set2.begin(), set2.end()); - - int removedIndex = num >> 1; - set0.remove(removedIndex + 1); - set1.remove(num - removedIndex); - - it1 = set0.begin(); - it2 = set1.begin(); - for (int i = 0; i < num; ++i, ++it1, ++it2) { - if (i == removedIndex) - ++i; - EXPECT_EQ(*it1, i + 1); - EXPECT_EQ(*it2, num - i); - } - EXPECT_EQ(it1, set0.end()); - EXPECT_EQ(it2, set1.end()); -} - -TEST(ListHashSetTest, Swap) -{ - swapTestHelper<ListHashSet<int>>(); -} - -TEST(LinkedHashSetTest, Swap) -{ - swapTestHelper<LinkedHashSet<int>>(); -} - class CountCopy final { public: static int* const kDeletedValue; @@ -764,20 +666,26 @@ namespace { template <typename Set> -int moveConstructorCopyCount() +class ListOrLinkedHashSetCountCopyTest : public ::testing::Test { }; + +using CountCopySetTypes = ::testing::Types<ListHashSet<CountCopy>, ListHashSet<CountCopy, 1>, LinkedHashSet<CountCopy>>; +TYPED_TEST_CASE(ListOrLinkedHashSetCountCopyTest, CountCopySetTypes); + +TYPED_TEST(ListOrLinkedHashSetCountCopyTest, MoveConstructionShouldNotMakeCopy) { + using Set = TypeParam; Set set; int counter = 0; set.add(CountCopy(&counter)); counter = 0; Set other(std::move(set)); - return counter; + EXPECT_EQ(0, counter); } -template <typename Set> -int moveAssignmentCopyCount() +TYPED_TEST(ListOrLinkedHashSetCountCopyTest, MoveAssignmentShouldNotMakeACopy) { + using Set = TypeParam; Set set; int counter = 0; set.add(CountCopy(&counter)); @@ -785,19 +693,7 @@ Set other(set); counter = 0; set = std::move(other); - return counter; -} - -TEST(ListHashSetTest, MoveShouldNotMakeCopy) -{ - EXPECT_EQ(0, moveConstructorCopyCount<ListHashSet<CountCopy>>()); - EXPECT_EQ(0, moveAssignmentCopyCount<ListHashSet<CountCopy>>()); -} - -TEST(LinkedHashSetTest, MoveAssignmentShouldNotMakeACopy) -{ - EXPECT_EQ(0, moveConstructorCopyCount<LinkedHashSet<CountCopy>>()); - EXPECT_EQ(0, moveAssignmentCopyCount<LinkedHashSet<CountCopy>>()); + EXPECT_EQ(0, counter); } } // anonymous namespace
diff --git a/third_party/WebKit/Source/wtf/Partitions.cpp b/third_party/WebKit/Source/wtf/Partitions.cpp index f86bf23..bd3f40d 100644 --- a/third_party/WebKit/Source/wtf/Partitions.cpp +++ b/third_party/WebKit/Source/wtf/Partitions.cpp
@@ -189,7 +189,7 @@ { size_t signature = 16 * 1024 * 1024 - 1; base::debug::Alias(&signature); - IMMEDIATE_CRASH(); + FATAL("ParitionAlloc: out of memory with < 16M usage (error:%u)", getAllocPageErrorCode()); } void Partitions::handleOutOfMemory()
diff --git a/third_party/WebKit/Source/wtf/text/AtomicString.cpp b/third_party/WebKit/Source/wtf/text/AtomicString.cpp index cad9b6d2..120a153 100644 --- a/third_party/WebKit/Source/wtf/text/AtomicString.cpp +++ b/third_party/WebKit/Source/wtf/text/AtomicString.cpp
@@ -118,7 +118,7 @@ template<typename T, typename HashTranslator> static inline PassRefPtr<StringImpl> addToStringTable(const T& value) { - HashSet<StringImpl*>::AddResult addResult = atomicStrings().add<HashTranslator>(value); + HashSet<StringImpl*>::AddResult addResult = atomicStrings().addWithTranslator<HashTranslator>(value); // If the string is newly-translated, then we need to adopt it. // The boolean in the pair tells us if that is so.
diff --git a/third_party/WebKit/Source/wtf/text/StringHash.h b/third_party/WebKit/Source/wtf/text/StringHash.h index 5f4d843d..025f03c 100644 --- a/third_party/WebKit/Source/wtf/text/StringHash.h +++ b/third_party/WebKit/Source/wtf/text/StringHash.h
@@ -91,6 +91,11 @@ return CaseFoldingHash::hash(reinterpret_cast<const LChar*>(data), length); } + static inline unsigned hash(const char* data) + { + return CaseFoldingHash::hash(reinterpret_cast<const LChar*>(data), strlen(data)); + } + static inline bool equal(const StringImpl* a, const StringImpl* b) { return equalIgnoringCaseNonNull(a, b);
diff --git a/third_party/WebKit/public/platform/WebGraphicsContext3D.h b/third_party/WebKit/public/platform/WebGraphicsContext3D.h index cd8a5d46..89ad941 100644 --- a/third_party/WebKit/public/platform/WebGraphicsContext3D.h +++ b/third_party/WebKit/public/platform/WebGraphicsContext3D.h
@@ -35,6 +35,12 @@ #include "WebNonCopyable.h" #include "WebString.h" +namespace gpu { +namespace gles2 { +class GLES2Interface; +} +} + struct GrGLInterface; namespace blink { @@ -169,8 +175,6 @@ // getError in the order they were added. virtual void synthesizeGLError(WGC3Denum) = 0; - virtual bool isContextLost() = 0; - // GL_CHROMIUM_map_sub virtual void* mapBufferSubDataCHROMIUM(WGC3Denum target, WGC3Dintptr offset, WGC3Dsizeiptr size, WGC3Denum access) = 0; virtual void unmapBufferSubDataCHROMIUM(const void*) = 0; @@ -550,6 +554,9 @@ virtual void vertexAttribI4uiv(WGC3Duint index, const WGC3Duint *v) { } virtual void vertexAttribIPointer(WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dsizei stride, WGC3Dintptr pointer) { } virtual void waitSync(WGC3Dsync sync, WGC3Dbitfield flags, WGC3Duint64 timeout) { } + + // Prefer getting a GLES2Interface off WebGraphicsContext3DProvider if possible, and avoid using WebGraphicsContext3D at all. + virtual gpu::gles2::GLES2Interface* getGLES2Interface() = 0; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h b/third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h index c71432d..709c1d25 100644 --- a/third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h +++ b/third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h
@@ -35,6 +35,12 @@ class GrContext; +namespace gpu { +namespace gles2 { +class GLES2Interface; +} +} + namespace blink { class WebGraphicsContext3D; @@ -44,6 +50,7 @@ virtual ~WebGraphicsContext3DProvider() { } virtual WebGraphicsContext3D* context3d() = 0; + virtual gpu::gles2::GLES2Interface* contextGL() = 0; virtual GrContext* grContext() = 0; };
diff --git a/third_party/WebKit/public/web/WebWorkerContentSettingsClientProxy.h b/third_party/WebKit/public/web/WebWorkerContentSettingsClientProxy.h index 952263052..dfb44275 100644 --- a/third_party/WebKit/public/web/WebWorkerContentSettingsClientProxy.h +++ b/third_party/WebKit/public/web/WebWorkerContentSettingsClientProxy.h
@@ -18,12 +18,6 @@ public: virtual ~WebWorkerContentSettingsClientProxy() { } - // Deprecated: This function should be removed. - virtual bool allowDatabase(const WebString& name, const WebString& displayName, unsigned long estimatedSize) - { - return true; - } - virtual bool requestFileSystemAccessSync() { return true;
diff --git a/third_party/closure_compiler/externs/compiled_resources2.gyp b/third_party/closure_compiler/externs/compiled_resources2.gyp index 9efbcea..947de7d 100644 --- a/third_party/closure_compiler/externs/compiled_resources2.gyp +++ b/third_party/closure_compiler/externs/compiled_resources2.gyp
@@ -84,5 +84,9 @@ 'target_name': 'users_private', 'includes': ['../include_js.gypi'], }, + { + 'target_name': 'web_animations', + 'includes': ['../include_js.gypi'], + }, ], }
diff --git a/third_party/closure_compiler/externs/web_animations.js b/third_party/closure_compiler/externs/web_animations.js new file mode 100644 index 0000000..9eaa712 --- /dev/null +++ b/third_party/closure_compiler/externs/web_animations.js
@@ -0,0 +1,142 @@ +// Copyright 2016 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. + +/** + * @fileoverview Minimal Closure externs for Web Animations. + * "Minimal" because the web-animations spec is in flux, Chromium's support is + * changing, and the intended consumer (MD Settings) is actually using the + * web-animations-js polyfill for the time being. + * @see https://w3c.github.io/web-animations/#programming-interface + */ + +/** + * @enum {number} + * @see https://w3c.github.io/web-animations/#enumdef-fillmode + */ +var FillMode = { + 'none': 0, + 'forwards': 1, + 'backwards': 2, + 'both': 3, + 'auto': 4 +}; + +/** + * @enum {number} + * @see https://w3c.github.io/web-animations/#enumdef-playbackdirection + */ +var PlaybackDirection = { + 'normal': 0, + 'reverse': 1, + 'alternate': 2, + 'alternate-reverse': 3 +}; + +/** + * @constructor + * @param {!Event} event + */ +var EventHandlerNonNull = function(event) {}; + +/** @typedef {?EventHandlerNonNull} */ +var EventHandler; + +/** + * @constructor + * @see https://w3c.github.io/web-animations/#dictdef-keyframeanimationoptions + */ +var KeyframeAnimationOptions = function() {}; + +/** + * @constructor + * @see https://w3c.github.io/web-animations/#dictdef-keyframeeffectoptions + */ +var KeyframeEffectOptions = function() {}; + +/** @type {number} */ +KeyframeEffectOptions.prototype.delay; + +/** @type {number} */ +KeyframeEffectOptions.prototype.endDelay; + +/** @type {!FillMode} */ +KeyframeEffectOptions.prototype.fill; + +/** @type {number} */ +KeyframeEffectOptions.prototype.iterationStart; + +/** @type {number} */ +KeyframeEffectOptions.prototype.iterations; + +/** @type {number|string} */ +KeyframeEffectOptions.prototype.duration; + +/** @type {number} */ +KeyframeEffectOptions.prototype.playbackRate; + +/** @type {!PlaybackDirection} */ +KeyframeEffectOptions.prototype.direction; + +/** @type {string} */ +KeyframeEffectOptions.prototype.easing; + +/** @type {string} */ +KeyframeEffectOptions.prototype.id; + +/** + * @interface + * @extends {EventTarget} + * @see https://w3c.github.io/web-animations/#animation + */ +var Animation = function() {}; + +/** @type {string} */ +Animation.prototype.id; + +/** @type {?number} */ +Animation.prototype.startTime; + +/** @type {?number} */ +Animation.prototype.currentTime; + +/** @type {number} */ +Animation.prototype.playbackRate; + +Animation.prototype.finish = function() {}; + +Animation.prototype.play = function() {}; + +Animation.prototype.pause = function() {}; + +Animation.prototype.reverse = function() {}; + +Animation.prototype.cancel = function() {}; + +/** + * @param {boolean=} opt_useCapture + * @override + */ +Animation.prototype.addEventListener = function( + type, listener, opt_useCapture) {}; + +/** @type {EventHandler} */ +Animation.prototype.onfinish; + +/** @type {EventHandler} */ +Animation.prototype.oncancel; + +/** + * @interface + * @see https://w3c.github.io/web-animations/#animatable + */ +var Animatable = function() {}; + +Animatable.prototype = /** @lends {Element.prototype} */({ + /** + * @param {?Array<Object>|Object} effect + * @param {number|!KeyframeEffectOptions=} opt_timing + * @return {!Animation} + */ + animate: function(effect, opt_timing) {}, +});
diff --git a/third_party/libjingle/BUILD.gn b/third_party/libjingle/BUILD.gn index 962ec91..671a0bfb 100644 --- a/third_party/libjingle/BUILD.gn +++ b/third_party/libjingle/BUILD.gn
@@ -343,10 +343,6 @@ "../webrtc/api/webrtcsessiondescriptionfactory.cc", "../webrtc/api/webrtcsessiondescriptionfactory.h", "../webrtc/media/base/audiorenderer.h", - "../webrtc/media/base/capturemanager.cc", - "../webrtc/media/base/capturemanager.h", - "../webrtc/media/base/capturerenderadapter.cc", - "../webrtc/media/base/capturerenderadapter.h", "../webrtc/media/base/codec.cc", "../webrtc/media/base/codec.h", "../webrtc/media/base/cryptoparams.h", @@ -378,6 +374,8 @@ "../webrtc/media/base/videoframe.h", "../webrtc/media/base/videoframefactory.cc", "../webrtc/media/base/videoframefactory.h", + "../webrtc/media/base/videosourcebase.cc", + "../webrtc/media/base/videosourcebase.h", "../webrtc/media/engine/webrtccommon.h", "../webrtc/media/engine/webrtcvideoframe.cc", "../webrtc/media/engine/webrtcvideoframe.h",
diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp index 586368c..3c3ecfba 100644 --- a/third_party/libjingle/libjingle.gyp +++ b/third_party/libjingle/libjingle.gyp
@@ -308,10 +308,6 @@ '<(DEPTH)/third_party/webrtc/api/webrtcsessiondescriptionfactory.cc', '<(DEPTH)/third_party/webrtc/api/webrtcsessiondescriptionfactory.h', '<(DEPTH)/third_party/webrtc/media/base/audiorenderer.h', - '<(DEPTH)/third_party/webrtc/media/base/capturemanager.cc', - '<(DEPTH)/third_party/webrtc/media/base/capturemanager.h', - '<(DEPTH)/third_party/webrtc/media/base/capturerenderadapter.cc', - '<(DEPTH)/third_party/webrtc/media/base/capturerenderadapter.h', '<(DEPTH)/third_party/webrtc/media/base/codec.cc', '<(DEPTH)/third_party/webrtc/media/base/codec.h', '<(DEPTH)/third_party/webrtc/media/base/cryptoparams.h', @@ -343,6 +339,8 @@ '<(DEPTH)/third_party/webrtc/media/base/videoframe.h', '<(DEPTH)/third_party/webrtc/media/base/videoframefactory.cc', '<(DEPTH)/third_party/webrtc/media/base/videoframefactory.h', + '<(DEPTH)/third_party/webrtc/media/base/videosourcebase.cc', + '<(DEPTH)/third_party/webrtc/media/base/videosourcebase.h', '<(DEPTH)/third_party/webrtc/media/engine/webrtccommon.h', '<(DEPTH)/third_party/webrtc/media/engine/webrtcvideoframe.cc', '<(DEPTH)/third_party/webrtc/media/engine/webrtcvideoframe.h',
diff --git a/third_party/wayland-protocols/src/unstable/scaler/scaler.xml b/third_party/wayland-protocols/src/unstable/scaler/scaler.xml deleted file mode 100644 index 0e482a6..0000000 --- a/third_party/wayland-protocols/src/unstable/scaler/scaler.xml +++ /dev/null
@@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<protocol name="scaler"> - - <copyright> - Copyright © 2013-2014 Collabora, Ltd. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - </copyright> - - <interface name="wl_scaler" version="2"> - <description summary="surface cropping and scaling"> - The global interface exposing surface cropping and scaling - capabilities is used to instantiate an interface extension for a - wl_surface object. This extended interface will then allow - cropping and scaling the surface contents, effectively - disconnecting the direct relationship between the buffer and the - surface size. - </description> - - <request name="destroy" type="destructor"> - <description summary="unbind from the cropping and scaling interface"> - Informs the server that the client will not be using this - protocol object anymore. This does not affect any other objects, - wl_viewport objects included. - </description> - </request> - - <enum name="error"> - <entry name="viewport_exists" value="0" - summary="the surface already has a viewport object associated"/> - </enum> - - <request name="get_viewport"> - <description summary="extend surface interface for crop and scale"> - Instantiate an interface extension for the given wl_surface to - crop and scale its content. If the given wl_surface already has - a wl_viewport object associated, the viewport_exists - protocol error is raised. - </description> - - <arg name="id" type="new_id" interface="wl_viewport" - summary="the new viewport interface id"/> - <arg name="surface" type="object" interface="wl_surface" - summary="the surface"/> - </request> - </interface> - - <interface name="wl_viewport" version="2"> - <description summary="crop and scale interface to a wl_surface"> - An additional interface to a wl_surface object, which allows the - client to specify the cropping and scaling of the surface - contents. - - This interface allows to define the source rectangle (src_x, - src_y, src_width, src_height) from where to take the wl_buffer - contents, and scale that to destination size (dst_width, - dst_height). This state is double-buffered, and is applied on the - next wl_surface.commit. - - The two parts of crop and scale state are independent: the source - rectangle, and the destination size. Initially both are unset, that - is, no scaling is applied. The whole of the current wl_buffer is - used as the source, and the surface size is as defined in - wl_surface.attach. - - If the destination size is set, it causes the surface size to become - dst_width, dst_height. The source (rectangle) is scaled to exactly - this size. This overrides whatever the attached wl_buffer size is, - unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface - has no content and therefore no size. Otherwise, the size is always - at least 1x1 in surface coordinates. - - If the source rectangle is set, it defines what area of the - wl_buffer is taken as the source. If the source rectangle is set and - the destination size is not set, the surface size becomes the source - rectangle size rounded up to the nearest integer. If the source size - is already exactly integers, this results in cropping without scaling. - - The coordinate transformations from buffer pixel coordinates up to - the surface-local coordinates happen in the following order: - 1. buffer_transform (wl_surface.set_buffer_transform) - 2. buffer_scale (wl_surface.set_buffer_scale) - 3. crop and scale (wl_viewport.set*) - This means, that the source rectangle coordinates of crop and scale - are given in the coordinates after the buffer transform and scale, - i.e. in the coordinates that would be the surface-local coordinates - if the crop and scale was not applied. - - If the source rectangle is partially or completely outside of the - wl_buffer, then the surface contents are undefined (not void), and - the surface size is still dst_width, dst_height. - - The x, y arguments of wl_surface.attach are applied as normal to - the surface. They indicate how many pixels to remove from the - surface size from the left and the top. In other words, they are - still in the surface-local coordinate system, just like dst_width - and dst_height are. - - If the wl_surface associated with the wl_viewport is destroyed, - the wl_viewport object becomes inert. - - If the wl_viewport object is destroyed, the crop and scale - state is removed from the wl_surface. The change will be applied - on the next wl_surface.commit. - </description> - - <request name="destroy" type="destructor"> - <description summary="remove scaling and cropping from the surface"> - The associated wl_surface's crop and scale state is removed. - The change is applied on the next wl_surface.commit. - </description> - </request> - - <enum name="error"> - <entry name="bad_value" value="0" - summary="negative or zero values in width or height"/> - </enum> - - <request name="set"> - <description summary="set the crop and scale state"> - Set both source rectangle and destination size of the associated - wl_surface. See wl_viewport for the description, and relation to - the wl_buffer size. - - The bad_value protocol error is raised if src_width or - src_height is negative, or if dst_width or dst_height is not - positive. - - The crop and scale state is double-buffered state, and will be - applied on the next wl_surface.commit. - - Arguments dst_x and dst_y do not exist here, use the x and y - arguments to wl_surface.attach. The x, y, dst_width, and dst_height - define the surface-local coordinate system irrespective of the - attached wl_buffer size. - </description> - - <arg name="src_x" type="fixed" summary="source rectangle x"/> - <arg name="src_y" type="fixed" summary="source rectangle y"/> - <arg name="src_width" type="fixed" summary="source rectangle width"/> - <arg name="src_height" type="fixed" summary="source rectangle height"/> - <arg name="dst_width" type="int" summary="surface width"/> - <arg name="dst_height" type="int" summary="surface height"/> - </request> - - <request name="set_source" since="2"> - <description summary="set the source rectangle for cropping"> - Set the source rectangle of the associated wl_surface. See - wl_viewport for the description, and relation to the wl_buffer - size. - - If width is -1.0 and height is -1.0, the source rectangle is unset - instead. Any other pair of values for width and height that - contains zero or negative values raises the bad_value protocol - error. - - The crop and scale state is double-buffered state, and will be - applied on the next wl_surface.commit. - </description> - - <arg name="x" type="fixed" summary="source rectangle x"/> - <arg name="y" type="fixed" summary="source rectangle y"/> - <arg name="width" type="fixed" summary="source rectangle width"/> - <arg name="height" type="fixed" summary="source rectangle height"/> - </request> - - <request name="set_destination" since="2"> - <description summary="set the surface size for scaling"> - Set the destination size of the associated wl_surface. See - wl_viewport for the description, and relation to the wl_buffer - size. - - If width is -1 and height is -1, the destination size is unset - instead. Any other pair of values for width and height that - contains zero or negative values raises the bad_value protocol - error. - - The crop and scale state is double-buffered state, and will be - applied on the next wl_surface.commit. - - Arguments x and y do not exist here, use the x and y arguments to - wl_surface.attach. The x, y, width, and height define the - surface-local coordinate system irrespective of the attached - wl_buffer size. - </description> - - <arg name="width" type="int" summary="surface width"/> - <arg name="height" type="int" summary="surface height"/> - </request> - </interface> -</protocol>
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index c2650ed4..fe46c46 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -29,16 +29,7 @@ def main(args): mbw = MetaBuildWrapper() - mbw.ParseArgs(args) - - try: - ret = mbw.args.func() - if ret: - mbw.DumpInputFiles() - return ret - except Exception: - mbw.DumpInputFiles() - raise + return mbw.Main(args) class MetaBuildWrapper(object): @@ -59,6 +50,21 @@ self.common_dev_configs = [] self.unsupported_configs = [] + def Main(self, args): + self.ParseArgs(args) + try: + ret = self.args.func() + if ret: + self.DumpInputFiles() + return ret + except KeyboardInterrupt: + self.Print('interrupted, exiting', stream=sys.stderr) + return 130 + except Exception as e: + self.DumpInputFiles() + self.Print(str(e)) + return 1 + def ParseArgs(self, argv): def AddCommonOptions(subp): subp.add_argument('-b', '--builder', @@ -326,27 +332,28 @@ if not mixin in referenced_mixins: errs.append('Unreferenced mixin "%s".' % mixin) - # Check that 'chromium' bots which build public artifacts do not include - # the chrome_with_codecs 'mixin'. - if not 'chromium' in self.masters: - errs.append('Missing "chromium" master. Please update this proprietary ' - 'codecs check with the name of the master responsible for ' - 'public build artifacts.') - else: - for builder in self.masters['chromium']: - config = self.masters['chromium'][builder] - def RecurseMixins(current_mixin): - if current_mixin == 'chrome_with_codecs': - errs.append('Public artifact builder "%s" can not contain the ' - '"chrome_with_codecs" mixin.' % builder) - return - if not 'mixins' in self.mixins[current_mixin]: - return - for mixin in self.mixins[current_mixin]['mixins']: - RecurseMixins(mixin) + # If we're checking the Chromium config, check that the 'chromium' bots + # which build public artifacts do not include the chrome_with_codecs mixin. + if self.args.config_file == self.default_config: + if 'chromium' in self.masters: + for builder in self.masters['chromium']: + config = self.masters['chromium'][builder] + def RecurseMixins(current_mixin): + if current_mixin == 'chrome_with_codecs': + errs.append('Public artifact builder "%s" can not contain the ' + '"chrome_with_codecs" mixin.' % builder) + return + if not 'mixins' in self.mixins[current_mixin]: + return + for mixin in self.mixins[current_mixin]['mixins']: + RecurseMixins(mixin) - for mixin in self.configs[config]: - RecurseMixins(mixin) + for mixin in self.configs[config]: + RecurseMixins(mixin) + else: + errs.append('Missing "chromium" master. Please update this ' + 'proprietary codecs check with the name of the master ' + 'responsible for public build artifacts.') if errs: raise MBErr(('mb config file %s has problems:' % self.args.config_file) + @@ -1304,11 +1311,4 @@ if __name__ == '__main__': - try: - sys.exit(main(sys.argv[1:])) - except MBErr as e: - print(e) - sys.exit(1) - except KeyboardInterrupt: - print("interrupted, exiting", stream=sys.stderr) - sys.exit(130) + sys.exit(main(sys.argv[1:]))
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 8bf8d44f..bbf6a6c 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -9,140 +9,503 @@ # is not necessarily so (i.e., we might have mac, win, and linux # bots all using the 'gn_release_bot' config). 'configs': { - 'android_cast_gyp_debug_static_bot': ['android', 'cast', 'gyp', 'debug_static_bot'], - 'android_clang_asan_gyp_debug_bot': ['android', 'clang', 'asan', 'gyp', 'debug_bot'], - 'android_clang_asan_gyp_debug_trybot': ['android', 'clang', 'asan', 'gyp', 'debug_trybot'], - 'android_gn_debug_bot': ['android', 'gn', 'debug_bot'], - 'android_gn_debug_static_bot': ['android', 'gn', 'debug_static_bot'], - 'android_gn_debug_static_bot_arm64': ['android', 'gn', 'debug_static_bot', 'arm64'], - 'android_gn_debug_static_bot_mipsel': ['android', 'gn', 'debug_static_bot', 'mipsel'], - 'android_gn_debug_static_bot_x64': ['android', 'gn', 'debug_static_bot', 'x64'], - 'android_gn_debug_static_bot_x86': ['android', 'gn', 'debug_static_bot', 'x86'], - 'android_gn_debug_trybot': ['android', 'gn', 'debug_trybot'], - 'android_gn_debug_trybot_mipsel': ['android', 'gn', 'debug_trybot', 'mipsel'], - 'android_gn_debug_trybot_x64': ['android', 'gn', 'debug_trybot', 'x64'], - 'android_gn_debug_trybot_x86': ['android', 'gn', 'debug_trybot', 'x86'], - 'android_gn_release_bot': ['android', 'gn', 'release_bot'], - 'android_gn_release_trybot': ['android', 'gn', 'release_trybot'], - 'android_without_codecs_gyp_release_bot_minimal_symbols': ['android_without_codecs', 'gyp', 'release_bot_minimal_symbols'], - 'cast_gn_release_bot': ['cast', 'gn', 'release_bot'], - 'cast_gn_release_trybot': ['cast', 'gn', 'release_trybot'], - 'chromeos_gn_debug_bot': ['chromeos', 'gn', 'debug_bot'], - 'chromeos_ozone_gn_release_bot': ['chromeos', 'ozone', 'gn', 'release_bot'], - 'chromeos_ozone_gn_release_trybot': ['chromeos', 'ozone', 'gn', 'release_trybot'], - 'dev_gn_debug': ['gn', 'debug', 'shared', 'full_symbols'], - 'dev_gn_release': ['gn', 'release', 'shared'], - 'dev_gyp_debug': ['gyp', 'debug', 'shared', 'full_symbols'], - 'dev_gyp_release': ['gyp', 'release', 'shared'], - 'embedded_gyp_debug_bot': ['embedded', 'gyp', 'debug_bot'], + 'android_cast_gyp_debug_static_bot': [ + 'android', 'cast', 'gyp', 'debug_static_bot', + ], + + 'android_clang_asan_gyp_debug_bot': [ + 'android', 'clang', 'asan', 'gyp', 'debug_bot', + ], + + 'android_clang_asan_gyp_debug_trybot': [ + 'android', 'clang', 'asan', 'gyp', 'debug_trybot', + ], + + 'android_gn_debug_bot': [ + 'android', 'gn', 'debug_bot', + ], + + 'android_gn_debug_static_bot': [ + 'android', 'gn', 'debug_static_bot', + ], + + 'android_gn_debug_static_bot_arm64': [ + 'android', 'gn', 'debug_static_bot', 'arm64', + ], + + 'android_gn_debug_static_bot_mipsel': [ + 'android', 'gn', 'debug_static_bot', 'mipsel', + ], + + 'android_gn_debug_static_bot_x64': [ + 'android', 'gn', 'debug_static_bot', 'x64', + ], + + 'android_gn_debug_static_bot_x86': [ + 'android', 'gn', 'debug_static_bot', 'x86', + ], + + 'android_gn_debug_trybot': [ + 'android', 'gn', 'debug_trybot', + ], + + 'android_gn_debug_trybot_mipsel': [ + 'android', 'gn', 'debug_trybot', 'mipsel', + ], + + 'android_gn_debug_trybot_x64': [ + 'android', 'gn', 'debug_trybot', 'x64', + ], + + 'android_gn_debug_trybot_x86': [ + 'android', 'gn', 'debug_trybot', 'x86', + ], + + 'android_gn_release_bot': [ + 'android', 'gn', 'release_bot', + ], + + 'android_gn_release_trybot': [ + 'android', 'gn', 'release_trybot', + ], + + 'android_without_codecs_gyp_release_bot_minimal_symbols': [ + 'android_without_codecs', 'gyp', 'release_bot_minimal_symbols', + ], + + 'cast_gn_release_bot': [ + 'cast', 'gn', 'release_bot', + ], + + 'cast_gn_release_trybot': [ + 'cast', 'gn', 'release_trybot', + ], + + 'chromeos_gn_debug_bot': [ + 'chromeos', 'gn', 'debug_bot', + ], + + 'chromeos_ozone_gn_release_bot': [ + 'chromeos', 'ozone', 'gn', 'release_bot', + ], + + 'chromeos_ozone_gn_release_trybot': [ + 'chromeos', 'ozone', 'gn', 'release_trybot', + ], + + 'dev_gn_debug': [ + 'gn', 'debug', 'shared', 'full_symbols', + ], + + 'dev_gn_release': [ + 'gn', 'release', 'shared', + ], + + 'dev_gyp_debug': [ + 'gyp', 'debug', 'shared', 'full_symbols', + ], + + 'dev_gyp_release': [ + 'gyp', 'release', 'shared', + ], + + 'embedded_gyp_debug_bot': [ + 'embedded', 'gyp', 'debug_bot', + ], # This is the "deployment" config for the blimp builds. Currently # we want them to be debug, non-optimized builds (and we don't need any # chrome branding), so we don't use the "official" mixin. - 'gn_blimp_debug': ['gn', 'blimp', 'debug'], + 'gn_blimp_debug': [ + 'gn', 'blimp', 'debug', + ], - 'gn_cfi_release_bot': ['gn', 'cfi', 'release_bot'], - 'gn_cfi_release_trybot': ['gn', 'cfi', 'release_trybot'], - 'gn_cfi_diag_release_bot': ['gn', 'cfi', 'cfi_diag', 'release_bot'], - 'gn_debug_bot': ['gn', 'debug_bot'], - 'gn_debug_bot_minimal_symbols': ['gn', 'debug_bot_minimal_symbols'], - 'gn_debug_bot_minimal_symbols_x86': ['gn', 'debug_bot_minimal_symbols', 'x86'], - 'gn_debug_static_bot': ['gn', 'debug_static_bot'], - 'gn_linux_upload': ['gn_linux_upload', 'official', 'goma'], - 'gn_official': ['gn', 'official'], - 'gn_official_goma': ['gn', 'official', 'goma'], - 'gn_official_goma_minimal_symbols_android': ['gn', 'official', 'goma', 'minimal_symbols', 'android'], - 'gn_official_goma_minimal_symbols_android_arm64': ['gn', 'official', 'goma', 'minimal_symbols', 'android', 'arm64'], - 'gn_release_bot': ['gn', 'release_bot'], - 'gn_release_bot_minimal_symbols': ['gn', 'release_bot_minimal_symbols'], - 'gn_release_bot_minimal_symbols_x86': ['gn', 'release_bot_minimal_symbols', 'x86'], - 'gn_release_trybot': ['gn', 'release_trybot'], - 'gn_release_trybot_x86': ['gn', 'release_trybot', 'x86'], - 'gyp_official_goma': ['gyp', 'official', 'goma'], - 'gyp_official_goma_chromeos': ['gyp', 'official', 'goma', 'chromeos'], - 'gyp_official_goma_x86': ['gyp', 'official', 'goma', 'x86'], - 'gyp_official_goma_minimal_symbols_x64': ['gyp', 'official', 'goma', 'minimal_symbols', 'x64'], - 'gyp_official_goma_minimal_symbols_x86': ['gyp', 'official', 'goma', 'minimal_symbols', 'x86'], - 'gyp_release_bot_android': ['gyp', 'release_bot', 'android'], - 'gyp_release_trybot': ['gyp', 'release_trybot'], - 'gyp_release_trybot_x64': ['gyp', 'release_trybot', 'x64'], - 'gn_release_libfuzzer_asan': ['gn', 'release', 'libfuzzer', 'asan', 'proprietary_codecs', 'pdf_xfa'], - 'gn_release_libfuzzer_msan': ['gn', 'release', 'libfuzzer', 'msan', 'proprietary_codecs', 'pdf_xfa'], - 'gn_release_drmemory_drfuzz_x86': ['gn', 'release', 'drmemory', 'drfuzz', 'x86', 'proprietary_codecs'], - 'gn_release_drmemory_drfuzz': ['gn', 'release', 'drmemory', 'drfuzz', 'proprietary_codecs'], - 'gyp_valgrind_release_bot': ['gyp', 'valgrind', 'release_bot'], - 'gyp_valgrind_chromeos_release_bot': ['gyp', 'chromeos', 'valgrind', 'release_bot'], - 'gyp_drmemory_shared_release_x86': ['gyp', 'drmemory', 'shared', 'release', 'x86'], - 'gyp_drmemory_shared_release_x64': ['gyp', 'drmemory', 'shared', 'release', 'x64'], + 'gn_cfi_release_bot': [ + 'gn', 'cfi', 'release_bot', + ], + + 'gn_cfi_release_trybot': [ + 'gn', 'cfi', 'release_trybot', + ], + + 'gn_cfi_diag_release_bot': [ + 'gn', 'cfi', 'cfi_diag', 'release_bot', + ], + + 'gn_debug_bot': [ + 'gn', 'debug_bot', + ], + + 'gn_debug_bot_minimal_symbols': [ + 'gn', 'debug_bot_minimal_symbols', + ], + + 'gn_debug_bot_minimal_symbols_x86': [ + 'gn', 'debug_bot_minimal_symbols', 'x86', + ], + + 'gn_debug_static_bot': [ + 'gn', 'debug_static_bot', + ], + + 'gn_linux_upload': [ + 'gn_linux_upload', 'official', 'goma', + ], + + 'gn_official': [ + 'gn', 'official', + ], + + 'gn_official_goma': [ + 'gn', 'official', 'goma', + ], + + 'gn_official_goma_minimal_symbols_android': [ + 'gn', 'official', 'goma', 'minimal_symbols', 'android', + ], + + 'gn_official_goma_minimal_symbols_android_arm64': [ + 'gn', 'official', 'goma', 'minimal_symbols', 'android', 'arm64', + ], + + 'gn_release_bot': [ + 'gn', 'release_bot', + ], + + 'gn_release_bot_minimal_symbols': [ + 'gn', 'release_bot_minimal_symbols', + ], + + 'gn_release_bot_minimal_symbols_x86': [ + 'gn', 'release_bot_minimal_symbols', 'x86', + ], + + 'gn_release_trybot': [ + 'gn', 'release_trybot', + ], + + 'gn_release_trybot_x86': [ + 'gn', 'release_trybot', 'x86', + ], + + 'gyp_official_goma': [ + 'gyp', 'official', 'goma', + ], + + 'gyp_official_goma_chromeos': [ + 'gyp', 'official', 'goma', 'chromeos', + ], + + 'gyp_official_goma_x86': [ + 'gyp', 'official', 'goma', 'x86', + ], + + 'gyp_official_goma_minimal_symbols_x64': [ + 'gyp', 'official', 'goma', 'minimal_symbols', 'x64', + ], + + 'gyp_official_goma_minimal_symbols_x86': [ + 'gyp', 'official', 'goma', 'minimal_symbols', 'x86', + ], + + 'gyp_release_bot_android': [ + 'gyp', 'release_bot', 'android', + ], + + 'gyp_release_trybot': [ + 'gyp', 'release_trybot', + ], + + 'gyp_release_trybot_x64': [ + 'gyp', 'release_trybot', 'x64', + ], + + 'gn_release_libfuzzer_asan': [ + 'gn', 'release', 'libfuzzer', 'asan', 'proprietary_codecs', 'pdf_xfa', + ], + + 'gn_release_libfuzzer_msan': [ + 'gn', 'release', 'libfuzzer', 'msan', 'proprietary_codecs', 'pdf_xfa', + ], + + 'gn_release_drmemory_drfuzz_x86': [ + 'gn', 'release', 'drmemory', 'drfuzz', 'x86', 'proprietary_codecs', + ], + 'gn_release_drmemory_drfuzz': [ + 'gn', 'release', 'drmemory', 'drfuzz', 'proprietary_codecs', + ], + + 'gyp_valgrind_release_bot': [ + 'gyp', 'valgrind', 'release_bot', + ], + + 'gyp_valgrind_chromeos_release_bot': [ + 'gyp', 'chromeos', 'valgrind', 'release_bot', + ], + + 'gyp_drmemory_shared_release_x86': [ + 'gyp', 'drmemory', 'shared', 'release', 'x86', + ], + + 'gyp_drmemory_shared_release_x64': [ + 'gyp', 'drmemory', 'shared', 'release', 'x64', + ], # This is just for completeness; any bot that uses this config # should never actually run MB. - 'none': ['none'], + 'none': [ + 'none', + ], - 'noswarming_gn_release_bot': ['noswarming', 'gn', 'release_bot'], - 'noswarming_gyp_release_bot': ['noswarming', 'gyp', 'release_bot'], - 'noswarming_gyp_release_bot_mac_strip': ['noswarming', 'gyp', 'release_bot', 'mac_strip'], - 'noswarming_gyp_release_bot_x86': ['noswarming', 'gyp', 'release_bot', 'x86'], + 'noswarming_gn_release_bot': [ + 'noswarming', 'gn', 'release_bot', + ], - 'swarming_android_gn_release_bot_minimal_symbols': ['swarming', 'android', 'gn', 'release_bot_minimal_symbols'], - 'swarming_android_gyp_debug_static_bot': ['swarming', 'android', 'gyp', 'debug_static_bot'], - 'swarming_android_gyp_debug_static_bot_arm64': ['swarming', 'android', 'gyp', 'debug_static_bot', 'arm64'], - 'swarming_android_gyp_debug_trybot': ['swarming', 'android', 'gyp', 'debug_trybot'], - 'swarming_android_gyp_debug_trybot_arm64': ['swarming', 'android', 'gyp', 'debug_trybot', 'arm64'], - 'swarming_android_gyp_release_bot_minimal_symbols': ['swarming', 'android', 'gyp', 'release_bot_minimal_symbols'], - 'swarming_android_gyp_release_trybot': ['swarming', 'android', 'gyp', 'release_trybot'], - 'swarming_asan_lsan_gyp_release_trybot': ['swarming', 'asan', 'lsan', 'release_trybot'], - 'swarming_msan_gyp_release_trybot': ['swarming', 'chromeos', 'msan', 'gyp', 'release_trybot'], - 'swarming_deterministic_gyp_release_bot': ['swarming', 'deterministic', 'gyp', 'release_bot'], - 'swarming_gpu_fyi_tests_gn_debug_bot': ['swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn', 'debug_bot', 'angle_deqp_tests'], - 'swarming_gpu_fyi_tests_gn_debug_trybot': ['swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn', 'debug_trybot', 'angle_deqp_tests'], - 'swarming_gpu_fyi_tests_gn_release_bot': ['swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn', 'release_bot', 'angle_deqp_tests'], - 'swarming_gpu_fyi_tests_gn_release_trybot': ['swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn', 'release_trybot', 'angle_deqp_tests'], - 'swarming_gpu_tests_gn_debug_bot': ['swarming', 'gpu_tests', 'gn', 'debug_bot'], - 'swarming_gpu_tests_gn_release_bot': ['swarming', 'gpu_tests', 'gn', 'release_bot'], - 'swarming_gpu_tests_gn_release_trybot': ['swarming', 'gpu_tests', 'gn', 'release_trybot'], - 'swarming_gn_debug_bot': ['swarming', 'gn', 'debug_bot'], - 'swarming_gn_debug_bot_minimal_symbols_x64': ['swarming', 'gn', 'debug_bot_minimal_symbols', 'x64'], - 'swarming_gn_debug_bot_x64': ['swarming', 'gn', 'debug_bot', 'x64'], - 'swarming_gn_debug_trybot': ['swarming', 'gn', 'debug_trybot'], - 'swarming_gn_non_oilpan_debug_bot_minimal_symbols_x64': ['swarming', 'gn', 'non_oilpan', 'debug_bot_minimal_symbols', 'x64'], - 'swarming_gn_non_oilpan_debug_bot_x64': ['swarming', 'gn', 'non_oilpan', 'debug_bot_minimal_symbols', 'x64'], - 'swarming_gn_non_oilpan_release_bot_x64': ['swarming', 'gn', 'non_oilpan', 'release_bot', 'x64'], - 'swarming_gn_non_oilpan_release_trybot_minimal_symbols_x64': ['swarming', 'gn', 'non_oilpan', 'release_trybot', 'minimal_symbols', 'x64'], - 'swarming_gn_release_bot': ['swarming', 'gn', 'release_bot'], - 'swarming_gn_release_bot_x64': ['swarming', 'gn', 'release_bot', 'x64'], - 'swarming_gn_release_trybot': ['swarming', 'gn', 'release_bot'], - 'swarming_gn_release_trybot_minimal_symbols_x64': ['swarming', 'gn', 'release_trybot', 'minimal_symbols', 'x64'], - 'swarming_gyp_asan_lsan_release_bot_x64': ['swarming', 'gyp', 'asan', 'lsan', 'release_bot', 'x64'], - 'swarming_gyp_debug_bot_minimal_symbols_x64': ['swarming', 'gyp', 'debug_bot_minimal_symbols', 'x64'], - 'swarming_gyp_debug_bot_minimal_symbols_x86': ['swarming', 'gyp', 'debug_bot_minimal_symbols', 'x86'], - 'swarming_gyp_debug_bot_no_symbols_x86': ['swarming', 'gyp', 'debug_bot', 'no_symbols', 'x86'], - 'swarming_gyp_debug_bot_x64': ['swarming', 'gyp', 'debug_bot', 'x64'], - 'swarming_gyp_debug_trybot_x86': ['swarming', 'gyp', 'debug_trybot', 'x86'], - 'swarming_gyp_msan_release_bot_x64': ['swarming', 'gyp', 'msan', 'release_bot', 'x64'], - 'swarming_gyp_non_oilpan_asan_lsan_release_bot_x64': ['swarming', 'gyp', 'non_oilpan', 'asan', 'lsan', 'release_bot', 'x64'], - 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x64': ['swarming', 'gyp', 'non_oilpan', 'debug_bot_minimal_symbols', 'x64'], - 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x86': ['swarming', 'gyp', 'non_oilpan', 'debug_bot_minimal_symbols', 'x86'], - 'swarming_gyp_non_oilpan_debug_bot_x64': ['swarming', 'gyp', 'non_oilpan', 'debug_bot_minimal_symbols', 'x64'], - 'swarming_gyp_non_oilpan_release_bot_minimal_symbols_x86': ['swarming', 'gyp', 'non_oilpan', 'release_bot', 'minimal_symbols', 'x86'], - 'swarming_gyp_non_oilpan_release_bot_x64': ['swarming', 'gyp', 'non_oilpan', 'release_bot', 'x64'], - 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x64': ['swarming', 'gyp', 'non_oilpan', 'release_trybot', 'minimal_symbols', 'x64'], - 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x86': ['swarming', 'gyp', 'non_oilpan', 'release_trybot', 'minimal_symbols', 'x86'], - 'swarming_gyp_release_bot': ['swarming', 'gyp', 'release_bot'], - 'swarming_gyp_release_bot_arm': ['swarming', 'gyp', 'release_bot', 'arm', 'crosscompile'], - 'swarming_gyp_release_bot_minimal_symbols_x64': ['swarming', 'gyp', 'release_bot_minimal_symbols', 'x64'], - 'swarming_gyp_release_bot_minimal_symbols_x86': ['swarming', 'gyp', 'release_bot_minimal_symbols', 'x86'], - 'swarming_gyp_release_bot_x64': ['swarming', 'gyp', 'release_bot', 'x64'], - 'swarming_gyp_release_trybot_arm': ['swarming', 'gyp', 'release_trybot', 'arm', 'crosscompile'], - 'swarming_gyp_release_trybot_minimal_symbols_x64': ['swarming', 'gyp', 'release_trybot', 'minimal_symbols', 'x64'], - 'swarming_gyp_release_trybot_minimal_symbols_x86': ['swarming', 'gyp', 'release_trybot', 'minimal_symbols', 'x86'], - 'swarming_tsan_gyp_release_trybot': ['swarming', 'disable_nacl', 'tsan', 'gyp', 'release_trybot'], + 'noswarming_gyp_release_bot': [ + 'noswarming', 'gyp', 'release_bot', + ], - # Configurations that build with proprietary codecs enabled. - 'gn_debug_bot_minimal_symbols_chrome_with_codecs': ['gn', 'debug_bot_minimal_symbols', 'chrome_with_codecs'], - 'gn_debug_static_bot_chrome_with_codecs': ['gn', 'debug_static_bot', 'chrome_with_codecs'], - 'gn_release_bot_chrome_with_codecs': ['gn', 'release_bot', 'chrome_with_codecs'], - 'gn_release_bot_minimal_symbols_chrome_with_codecs': ['gn', 'release_bot_minimal_symbols', 'chrome_with_codecs'], + 'noswarming_gyp_release_bot_mac_strip': [ + 'noswarming', 'gyp', 'release_bot', 'mac_strip', + ], + + 'noswarming_gyp_release_bot_x86': [ + 'noswarming', 'gyp', 'release_bot', 'x86', + ], + + 'swarming_android_gn_release_bot_minimal_symbols': [ + 'swarming', 'android', 'gn', 'release_bot_minimal_symbols', + ], + + 'swarming_android_gyp_debug_static_bot': [ + 'swarming', 'android', 'gyp', 'debug_static_bot', + ], + + 'swarming_android_gyp_debug_static_bot_arm64': [ + 'swarming', 'android', 'gyp', 'debug_static_bot', 'arm64', + ], + + 'swarming_android_gyp_debug_trybot': [ + 'swarming', 'android', 'gyp', 'debug_trybot', + ], + + 'swarming_android_gyp_debug_trybot_arm64': [ + 'swarming', 'android', 'gyp', 'debug_trybot', 'arm64', + ], + + 'swarming_android_gyp_release_bot_minimal_symbols': [ + 'swarming', 'android', 'gyp', 'release_bot_minimal_symbols', + ], + + 'swarming_android_gyp_release_trybot': [ + 'swarming', 'android', 'gyp', 'release_trybot', + ], + + 'swarming_asan_lsan_gyp_release_trybot': [ + 'swarming', 'asan', 'lsan', 'release_trybot', + ], + + 'swarming_msan_gyp_release_trybot': [ + 'swarming', 'chromeos', 'msan', 'gyp', 'release_trybot', + ], + + 'swarming_deterministic_gyp_release_bot': [ + 'swarming', 'deterministic', 'gyp', 'release_bot', + ], + + 'swarming_gpu_fyi_tests_gn_debug_bot': [ + 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn', + 'debug_bot', 'angle_deqp_tests', + ], + + 'swarming_gpu_fyi_tests_gn_debug_trybot': [ + 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn', + 'debug_trybot', 'angle_deqp_tests', + ], + + 'swarming_gpu_fyi_tests_gn_release_bot': [ + 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn', + 'release_bot', 'angle_deqp_tests', + ], + + 'swarming_gpu_fyi_tests_gn_release_trybot': [ + 'swarming', 'gpu_tests', 'gn', 'release_trybot', + ], + + 'swarming_gpu_tests_gn_debug_bot': [ + 'swarming', 'gpu_tests', 'gn', 'debug_bot', + ], + + 'swarming_gpu_tests_gn_release_bot': [ + 'swarming', 'gpu_tests', 'gn', 'release_bot', + ], + + 'swarming_gpu_tests_gn_release_trybot': [ + 'swarming', 'gpu_tests', 'gn', 'release_trybot', + ], + + 'swarming_gn_debug_bot': [ + 'swarming', 'gn', 'debug_bot', + ], + + 'swarming_gn_debug_bot_minimal_symbols_x64': [ + 'swarming', 'gn', 'debug_bot_minimal_symbols', 'x64', + ], + + 'swarming_gn_debug_bot_x64': [ + 'swarming', 'gn', 'debug_bot', 'x64', + ], + + 'swarming_gn_debug_trybot': [ + 'swarming', 'gn', 'debug_trybot', + ], + + 'swarming_gn_non_oilpan_debug_bot_minimal_symbols_x64': [ + 'swarming', 'gn', 'non_oilpan', 'debug_bot_minimal_symbols', 'x64', + ], + + 'swarming_gn_non_oilpan_debug_bot_x64': [ + 'swarming', 'gn', 'non_oilpan', 'debug_bot_minimal_symbols', 'x64', + ], + + 'swarming_gn_non_oilpan_release_bot_x64': [ + 'swarming', 'gn', 'non_oilpan', 'release_bot', 'x64', + ], + + 'swarming_gn_non_oilpan_release_trybot_minimal_symbols_x64': [ + 'swarming', 'gn', 'non_oilpan', 'release_trybot', 'minimal_symbols', + 'x64', + ], + + 'swarming_gn_release_bot': [ + 'swarming', 'gn', 'release_bot', + ], + + 'swarming_gn_release_bot_x64': [ + 'swarming', 'gn', 'release_bot', 'x64', + ], + + 'swarming_gn_release_trybot': [ + 'swarming', 'gn', 'release_bot', + ], + + 'swarming_gn_release_trybot_minimal_symbols_x64': [ + 'swarming', 'gn', 'release_trybot', 'minimal_symbols', 'x64', + ], + + 'swarming_gyp_asan_lsan_release_bot_x64': [ + 'swarming', 'gyp', 'asan', 'lsan', 'release_bot', 'x64', + ], + + 'swarming_gyp_debug_bot_minimal_symbols_x64': [ + 'swarming', 'gyp', 'debug_bot_minimal_symbols', 'x64', + ], + + 'swarming_gyp_debug_bot_minimal_symbols_x86': [ + 'swarming', 'gyp', 'debug_bot_minimal_symbols', 'x86', + ], + + 'swarming_gyp_debug_bot_no_symbols_x86': [ + 'swarming', 'gyp', 'debug_bot', 'no_symbols', 'x86', + ], + + 'swarming_gyp_debug_bot_x64': [ + 'swarming', 'gyp', 'debug_bot', 'x64', + ], + + 'swarming_gyp_debug_trybot_x86': [ + 'swarming', 'gyp', 'debug_trybot', 'x86', + ], + + 'swarming_gyp_msan_release_bot_x64': [ + 'swarming', 'gyp', 'msan', 'release_bot', 'x64', + ], + + 'swarming_gyp_non_oilpan_asan_lsan_release_bot_x64': [ + 'swarming', 'gyp', 'non_oilpan', 'asan', 'lsan', 'release_bot', 'x64', + ], + + 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x64': [ + 'swarming', 'gyp', 'non_oilpan', 'debug_bot_minimal_symbols', 'x64', + ], + + 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x86': [ + 'swarming', 'gyp', 'non_oilpan', 'debug_bot_minimal_symbols', 'x86', + ], + + 'swarming_gyp_non_oilpan_debug_bot_x64': [ + 'swarming', 'gyp', 'non_oilpan', 'debug_bot_minimal_symbols', 'x64', + ], + + 'swarming_gyp_non_oilpan_release_bot_minimal_symbols_x86': [ + 'swarming', 'gyp', 'non_oilpan', 'release_bot', 'minimal_symbols', 'x86', + ], + + 'swarming_gyp_non_oilpan_release_bot_x64': [ + 'swarming', 'gyp', 'non_oilpan', 'release_bot', 'x64', + ], + + 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x64': [ + 'swarming', 'gyp', 'non_oilpan', 'release_trybot', 'minimal_symbols', + 'x64', + ], + + 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x86': [ + 'swarming', 'gyp', 'non_oilpan', 'release_trybot', 'minimal_symbols', + 'x86', + ], + + 'swarming_gyp_release_bot': [ + 'swarming', 'gyp', 'release_bot', + ], + + 'swarming_gyp_release_bot_arm': [ + 'swarming', 'gyp', 'release_bot', 'arm', 'crosscompile', + ], + + 'swarming_gyp_release_bot_minimal_symbols_x64': [ + 'swarming', 'gyp', 'release_bot_minimal_symbols', 'x64', + ], + + 'swarming_gyp_release_bot_minimal_symbols_x86': [ + 'swarming', 'gyp', 'release_bot_minimal_symbols', 'x86', + ], + + 'swarming_gyp_release_bot_x64': [ + 'swarming', 'gyp', 'release_bot', 'x64', + ], + + 'swarming_gyp_release_trybot_arm': [ + 'swarming', 'gyp', 'release_trybot', 'arm', 'crosscompile', + ], + + 'swarming_gyp_release_trybot_minimal_symbols_x64': [ + 'swarming', 'gyp', 'release_trybot', 'minimal_symbols', 'x64', + ], + + 'swarming_gyp_release_trybot_minimal_symbols_x86': [ + 'swarming', 'gyp', 'release_trybot', 'minimal_symbols', 'x86', + ], + + 'swarming_tsan_gyp_release_trybot': [ + 'swarming', 'disable_nacl', 'tsan', 'gyp', 'release_trybot', + ], + + 'gn_debug_bot_minimal_symbols_chrome_with_codecs': [ + 'gn', 'debug_bot_minimal_symbols', 'chrome_with_codecs', + ], + + 'gn_debug_static_bot_chrome_with_codecs': [ + 'gn', 'debug_static_bot', 'chrome_with_codecs', + ], + + 'gn_release_bot_chrome_with_codecs': [ + 'gn', 'release_bot', 'chrome_with_codecs', + ], + + 'gn_release_bot_minimal_symbols_chrome_with_codecs': [ + 'gn', 'release_bot_minimal_symbols', 'chrome_with_codecs', + ], # This indicates that we haven't yet set up this bot w/ MB. This is # different from 'none' in that a bot set to 'none' should never do @@ -150,7 +513,9 @@ # added the entries yet. # 'tbd': ['none'], - 'win_clang_debug_bot': ['gn', 'clang', 'debug_bot_minimal_symbols'], + 'win_clang_debug_bot': [ + 'gn', 'clang', 'debug_bot_minimal_symbols', + ], }, # This is a list of configs that do not actually exist on any bot @@ -179,10 +544,10 @@ # This is a dict mapping a given 'mixin' name to a dict of settings that # mb should use. See //tools/mb/docs/user_guide.md for more information. 'mixins': { - # We build Android with codecs on most bots to ensure maximum test coverage, - # but use 'android_without_codecs' on bots responsible for building publicly - # advertised non-Official Android builds -- which are not allowed to have - # proprietary codecs enabled. + # We build Android with codecs on most bots to ensure maximum test + # coverage, but use 'android_without_codecs' on bots responsible for + # building publicly advertised non-Official Android builds -- + # which are not allowed to have proprietary codecs enabled. 'android': { 'mixins': ['android_without_codecs', 'chrome_with_codecs'], }, @@ -221,10 +586,13 @@ 'gyp_defines': 'asan=1', }, - # Removes dependencies on X11 and audio libraries for a containerized build. + # Removes dependencies on X11 and audio libraries for a containerized + # build. 'blimp': { - 'gn_args': "use_aura=true use_ozone=true use_alsa=false use_pulseaudio=false use_cups=false use_glib=false", - 'gyp_defines': 'use_aura=1 use_ozone=1 use_alsa=0 use_pulseaudio=0 use_cups=0 use_glib=0', + 'gn_args': ('use_aura=true use_ozone=true use_alsa=false ' + 'use_pulseaudio=false use_cups=false use_glib=false'), + 'gyp_defines': ('use_aura=1 use_ozone=1 use_alsa=0 ' + 'use_pulseaudio=0 use_cups=0 use_glib=0'), }, 'cast': { @@ -364,8 +732,10 @@ }, 'msan': { - 'gn_args': 'is_msan=true msan_track_origins=2 use_prebuilt_instrumented_libraries=true', - 'gyp_defines': 'msan=1 msan_track_origins=2 use_prebuilt_instrumented_libraries=1', + 'gn_args': ('is_msan=true msan_track_origins=2 ' + 'use_prebuilt_instrumented_libraries=true'), + 'gyp_defines': ('msan=1 msan_track_origins=2 ' + 'use_prebuilt_instrumented_libraries=1'), }, 'no_symbols': { @@ -394,7 +764,8 @@ }, 'official': { - 'gn_args': 'is_chrome_branded=true is_official_build=true is_debug=false', + 'gn_args': ('is_chrome_branded=true is_official_build=true ' + 'is_debug=false'), 'gyp_defines': 'branding=Chrome buildtype=Official', }, @@ -482,8 +853,8 @@ 'masters': { # Take care when changing any of these builders to ensure that you do not # include a configuration with 'chrome_with_codecs' since these builders - # generated publicly advertised non-Official builds which are not allowed to - # have proprietary codecs enabled. + # generated publicly advertised non-Official builds which are not allowed + # to have proprietary codecs enabled. 'chromium': { 'Win': 'noswarming_gyp_release_bot', 'Mac': 'noswarming_gyp_release_bot_mac_strip', @@ -506,7 +877,8 @@ 'Lollipop Tablet Tester': 'android_gn_debug_static_bot', 'Marshmallow 64 bit Tester': 'android_gn_debug_static_bot_arm64', 'Marshmallow Tablet Tester': 'android_gn_debug_static_bot', - 'Android Swarm Builder': 'swarming_android_gn_release_bot_minimal_symbols', + 'Android Swarm Builder': + 'swarming_android_gn_release_bot_minimal_symbols', }, 'chromium.chrome': { 'Google Chrome Win': 'gyp_official_goma_minimal_symbols_x86', @@ -520,7 +892,8 @@ 'Linux ChromiumOS GN (dbg)': 'chromeos_gn_debug_bot', }, 'chromium.linux': { - 'Android Arm64 Builder (dbg)': 'swarming_android_gyp_debug_static_bot_arm64', + 'Android Arm64 Builder (dbg)': + 'swarming_android_gyp_debug_static_bot_arm64', 'Android Builder': 'swarming_android_gyp_release_bot_minimal_symbols', 'Android Builder (dbg)': 'swarming_android_gyp_debug_static_bot', 'Android Clang Builder (dbg)': 'android_clang_asan_gyp_debug_bot', @@ -548,7 +921,8 @@ }, 'chromium.perf': { 'Android Builder': 'gn_official_goma_minimal_symbols_android', - 'Android arm64 Builder': 'gn_official_goma_minimal_symbols_android_arm64', + 'Android arm64 Builder': + 'gn_official_goma_minimal_symbols_android_arm64', 'Win Builder': 'gyp_official_goma_minimal_symbols_x86', 'Win x64 Builder': 'gyp_official_goma_minimal_symbols_x64', 'Mac Builder': 'gyp_official_goma', @@ -566,11 +940,14 @@ 'WebKit Win7': 'none', 'WebKit Win10': 'none', 'WebKit Win x64 Builder': 'swarming_gyp_release_bot_minimal_symbols_x64', - 'WebKit Win non-Oilpan': 'swarming_gyp_non_oilpan_release_bot_minimal_symbols_x86', + 'WebKit Win non-Oilpan': + 'swarming_gyp_non_oilpan_release_bot_minimal_symbols_x86', 'WebKit Win Builder (dbg)': 'swarming_gyp_debug_bot_minimal_symbols_x86', 'WebKit Win7 (dbg)': 'none', - 'WebKit Win non-Oilpan (dbg)': 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x86', - 'WebKit Win x64 Builder (dbg)': 'swarming_gyp_debug_bot_minimal_symbols_x64', + 'WebKit Win non-Oilpan (dbg)': + 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x86', + 'WebKit Win x64 Builder (dbg)': + 'swarming_gyp_debug_bot_minimal_symbols_x64', 'WebKit Mac Builder': 'swarming_gyp_release_bot_x64', 'WebKit Mac10.11 (retina)': 'swarming_gyp_release_bot_x64', 'WebKit Mac10.10': 'none', @@ -581,9 +958,11 @@ 'WebKit Mac non-Oilpan (dbg)': 'swarming_gyp_non_oilpan_debug_bot_x64', 'WebKit Linux': 'swarming_gn_release_bot_x64', 'WebKit Linux Trusty': 'swarming_gn_release_bot_x64', - 'WebKit Linux non-Oilpan Builder': 'swarming_gn_non_oilpan_release_bot_x64', + 'WebKit Linux non-Oilpan Builder': + 'swarming_gn_non_oilpan_release_bot_x64', 'WebKit Linux ASAN': 'swarming_gyp_asan_lsan_release_bot_x64', - 'WebKit Linux non-Oilpan ASAN': 'swarming_gyp_non_oilpan_asan_lsan_release_bot_x64', + 'WebKit Linux non-Oilpan ASAN': + 'swarming_gyp_non_oilpan_asan_lsan_release_bot_x64', 'WebKit Linux MSAN': 'swarming_gyp_msan_release_bot_x64', 'WebKit Linux Leak': 'swarming_gn_release_bot_x64', 'WebKit Linux non-Oilpan Leak': 'swarming_gn_non_oilpan_release_bot_x64', @@ -632,7 +1011,8 @@ 'Windows Browser (DrMemory full) (10)': 'none', 'Windows Browser (DrMemory full) (11)': 'none', 'Windows Browser (DrMemory full) (12)': 'none', - 'Chromium Windows Builder (DrMemory x64)': 'gyp_drmemory_shared_release_x64', + 'Chromium Windows Builder (DrMemory x64)': + 'gyp_drmemory_shared_release_x64', 'Windows Unit (DrMemory x64)': 'none', }, 'chromium.fyi': { @@ -694,7 +1074,8 @@ 'tryserver.blink': { 'linux_blink_dbg': 'swarming_gn_debug_bot_minimal_symbols_x64', 'linux_blink_compile_dbg': 'swarming_gn_debug_bot_minimal_symbols_x64', - 'linux_blink_compile_rel': 'swarming_gn_release_trybot_minimal_symbols_x64', + 'linux_blink_compile_rel': + 'swarming_gn_release_trybot_minimal_symbols_x64', 'linux_blink_rel': 'swarming_gn_release_trybot_minimal_symbols_x64', 'mac_blink_dbg': 'swarming_gyp_debug_bot_minimal_symbols_x64', 'mac_blink_compile_dbg': 'swarming_gyp_debug_bot_minimal_symbols_x64', @@ -702,18 +1083,29 @@ 'mac_blink_rel': 'swarming_gyp_release_trybot_minimal_symbols_x64', 'win_blink_dbg': 'swarming_gyp_debug_bot_minimal_symbols_x86', 'win_blink_compile_dbg': 'swarming_gyp_debug_bot_minimal_symbols_x86', - 'win_blink_compile_rel': 'swarming_gyp_release_trybot_minimal_symbols_x86', + 'win_blink_compile_rel': + 'swarming_gyp_release_trybot_minimal_symbols_x86', 'win_blink_rel': 'swarming_gyp_release_trybot_minimal_symbols_x86', - 'linux_blink_oilpan_dbg': 'swarming_gn_non_oilpan_debug_bot_minimal_symbols_x64', - 'linux_blink_oilpan_rel': 'swarming_gn_non_oilpan_release_trybot_minimal_symbols_x64', - 'linux_blink_oilpan_compile_rel': 'swarming_gn_non_oilpan_release_trybot_minimal_symbols_x64', - 'mac_blink_oilpan_dbg': 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x64', - 'mac_blink_oilpan_rel': 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x64', - 'mac_blink_oilpan_compile_rel': 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x64', - 'win_blink_oilpan_dbg': 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x86', - 'win_blink_oilpan_rel': 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x86', - 'win_blink_oilpan_compile_rel': 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x86', - 'linux_blink_rel_ng': 'swarming_gn_release_trybot_minimal_symbols_x64', + 'linux_blink_oilpan_dbg': + 'swarming_gn_non_oilpan_debug_bot_minimal_symbols_x64', + 'linux_blink_oilpan_rel': + 'swarming_gn_non_oilpan_release_trybot_minimal_symbols_x64', + 'linux_blink_oilpan_compile_rel': + 'swarming_gn_non_oilpan_release_trybot_minimal_symbols_x64', + 'mac_blink_oilpan_dbg': + 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x64', + 'mac_blink_oilpan_rel': + 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x64', + 'mac_blink_oilpan_compile_rel': + 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x64', + 'win_blink_oilpan_dbg': + 'swarming_gyp_non_oilpan_debug_bot_minimal_symbols_x86', + 'win_blink_oilpan_rel': + 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x86', + 'win_blink_oilpan_compile_rel': + 'swarming_gyp_non_oilpan_release_trybot_minimal_symbols_x86', + 'linux_blink_rel_ng': + 'swarming_gn_release_trybot_minimal_symbols_x64', 'blink_presubmit': 'none', }, 'tryserver.chromium.android': { @@ -743,7 +1135,8 @@ 'linux_chromium_rel_ng': 'swarming_gpu_tests_gn_release_trybot', 'linux_chromium_cfi_rel_ng': 'gn_cfi_release_trybot', 'linux_chromium_gn_chromeos_rel': 'chromeos_ozone_gn_release_trybot', - 'linux_blink_oilpan_rel': 'swarming_gn_non_oilpan_release_trybot_minimal_symbols_x64', + 'linux_blink_oilpan_rel': + 'swarming_gn_non_oilpan_release_trybot_minimal_symbols_x64', 'linux_chromium_compile_dbg_ng': 'swarming_gn_debug_trybot', 'linux_chromium_dbg_ng': 'swarming_gn_debug_trybot', 'linux_chromium_gn_chromeos_dbg': 'chromeos_gn_debug_bot', @@ -760,7 +1153,8 @@ 'cast_shell_linux': 'cast_gn_release_trybot', 'linux_deterministic': 'swarming_deterministic_gyp_release_bot', 'linux_ecs_ozone': 'embedded_gyp_debug_bot', - 'linux_optional_gpu_tests_rel': 'swarming_gpu_fyi_tests_gn_release_trybot', + 'linux_optional_gpu_tests_rel': + 'swarming_gpu_fyi_tests_gn_release_trybot', }, 'tryserver.chromium.mac': { 'mac_chromium_gn_dbg': 'gn_debug_static_bot', @@ -769,8 +1163,10 @@ 'mac_chromium_clang_upload': 'gn_release_bot', }, 'tryserver.chromium.perf': { - 'android_perf_bisect_builder': 'gn_official_goma_minimal_symbols_android', - 'android_arm64_perf_bisect_builder': 'gn_official_goma_minimal_symbols_android_arm64', + 'android_perf_bisect_builder': + 'gn_official_goma_minimal_symbols_android', + 'android_arm64_perf_bisect_builder': + 'gn_official_goma_minimal_symbols_android_arm64', 'linux_perf_bisect_builder': 'gn_official_goma', 'mac_perf_bisect_builder': 'gyp_official_goma', 'win_perf_bisect_builder': 'gyp_official_goma_minimal_symbols_x86', @@ -792,11 +1188,14 @@ 'android_nexus5_perf_bisect': 'gn_official_goma_minimal_symbols_android', 'android_nexus6_perf_bisect': 'gn_official_goma_minimal_symbols_android', 'android_nexus7_perf_bisect': 'gn_official_goma_minimal_symbols_android', - 'android_nexus9_perf_bisect': 'gn_official_goma_minimal_symbols_android_arm64', + 'android_nexus9_perf_bisect': + 'gn_official_goma_minimal_symbols_android_arm64', 'android_s5_perf_bisect': 'gn_official_goma_minimal_symbols_android', 'android_s5_perf_cq': 'gn_official_goma_minimal_symbols_android', - 'android_nexus5X_perf_bisect': 'gn_official_goma_minimal_symbols_android', - 'android_webview_aosp_perf_bisect': 'gn_official_goma_minimal_symbols_android', + 'android_nexus5X_perf_bisect': + 'gn_official_goma_minimal_symbols_android', + 'android_webview_aosp_perf_bisect': + 'gn_official_goma_minimal_symbols_android', 'linux_perf_cq': 'gn_official_goma', 'mac_retina_perf_cq': 'gyp_official_goma', 'winx64_10_perf_cq': 'gyp_official_goma_minimal_symbols_x64',
diff --git a/tools/mb/mb_unittest.py b/tools/mb/mb_unittest.py index 6a0218c..f3d42b23 100755 --- a/tools/mb/mb_unittest.py +++ b/tools/mb/mb_unittest.py
@@ -198,17 +198,11 @@ mbw.files[path] = contents return mbw - def check(self, args, mbw=None, files=None, out=None, err=None, ret=None, - exception=None): + def check(self, args, mbw=None, files=None, out=None, err=None, ret=None): if not mbw: mbw = self.fake_mbw(files) - mbw.ParseArgs(args) - actual_ret = None - if exception is not None: - self.assertRaisesRegexp(Exception, exception, mbw.args.func) - else: - actual_ret = mbw.args.func() + actual_ret = mbw.Main(args) self.assertEqual(actual_ret, ret) if out is not None: @@ -446,12 +440,14 @@ sys.stdout = orig_stdout def test_validate(self): - self.check(['validate'], ret=0) + mbw = self.fake_mbw() + mbw.files[mbw.default_config] = TEST_CONFIG + self.check(['validate'], mbw=mbw, ret=0) def test_bad_validate(self): mbw = self.fake_mbw() mbw.files[mbw.default_config] = TEST_BAD_CONFIG - self.check(['validate'], mbw=mbw, exception=TEST_BAD_CONFIG_ERR) + self.check(['validate'], mbw=mbw, ret=1) if __name__ == '__main__':
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index a5fa035..60140b33 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -45951,6 +45951,15 @@ </summary> </histogram> +<histogram name="ServiceWorker.StartWorker.Purpose" + enum="ServiceWorkerMetrics.EventType"> + <owner>falken@chromium.org</owner> + <summary> + The purpose for starting up a service worker. Recorded only for installed + workers. + </summary> +</histogram> + <histogram name="ServiceWorker.StartWorker.Status" enum="ServiceWorkerStatusCode"> <owner>falken@chromium.org</owner> @@ -45971,6 +45980,15 @@ </summary> </histogram> +<histogram name="ServiceWorker.StartWorker.Timeout.StartPurpose" + enum="ServiceWorkerMetrics.EventType"> + <owner>falken@chromium.org</owner> + <summary> + Records the start purpose for a service worker that timed out while starting + up. Recorded only for installed workers. + </summary> +</histogram> + <histogram name="ServiceWorker.StartWorker.TimeoutPhase" enum="EmbeddedWorkerStartingPhase"> <owner>falken@chromium.org</owner> @@ -80171,13 +80189,19 @@ <enum name="ServiceWorkerMetrics.EventType" type="int"> <int value="0" label="ACTIVATE"/> <int value="1" label="INSTALL"/> - <int value="2" label="FETCH"/> + <int value="2" label="FETCH (deprecated)"/> <int value="3" label="SYNC"/> <int value="4" label="NOTIFICATION_CLICK"/> <int value="5" label="PUSH"/> <int value="6" label="GEOFENCING"/> <int value="7" label="SERVICE_PORT_CONNECT"/> <int value="8" label="MESSAGE"/> + <int value="9" label="NOTIFICATION_CLOSE"/> + <int value="10" label="FETCH_MAIN_FRAME"/> + <int value="11" label="FETCH_SUB_FRAME"/> + <int value="12" label="FETCH_SHARED_WORKER"/> + <int value="13" label="FETCH_SUB_RESOURCE"/> + <int value="14" label="UNKOWN"/> </enum> <enum name="ServiceWorkerReadResponseResult" type="int">
diff --git a/ui/file_manager/video_player/js/test_util.js b/ui/file_manager/video_player/js/test_util.js index 2415cd6..9e5d019 100644 --- a/ui/file_manager/video_player/js/test_util.js +++ b/ui/file_manager/video_player/js/test_util.js
@@ -14,7 +14,7 @@ var contentWindow = window.background.appWindows[appId].contentWindow; if (contentWindow && contentWindow.document.title === filename) { - var element = contentWindow.document.querySelector('video[src]'); + var element = contentWindow.document.querySelector('video'); if (element && testFunction(element)) return true; }
diff --git a/ui/file_manager/video_player/js/video_player.js b/ui/file_manager/video_player/js/video_player.js index bed41ba5..469e09e9 100644 --- a/ui/file_manager/video_player/js/video_player.js +++ b/ui/file_manager/video_player/js/video_player.js
@@ -376,8 +376,11 @@ this.videoElement_ = document.createElement('video'); getRequiredElement('video-container').appendChild(this.videoElement_); + var videoUrl = video.toURL(); this.controls.attachMedia(this.videoElement_); - this.videoElement_.src = video.toURL(); + var source = document.createElement('source'); + source.src = videoUrl; + this.videoElement_.appendChild(source); media.isAvailableForCast().then(function(result) { if (result) @@ -388,9 +391,17 @@ videoPlayerElement.setAttribute('castable', true); }); - videoElementInitializePromise = Promise.resolve(); + videoElementInitializePromise = this.searchSubtitle_(videoUrl) + .then(function(subltitleUrl) { + if (subltitleUrl) { + var track = document.createElement('track'); + track.src = subltitleUrl; + track.kind = 'subtitles'; + track.default = true; + this.videoElement_.appendChild(track); + } + }.bind(this)); } - videoElementInitializePromise .then(function() { var handler = function(currentPos) { @@ -413,8 +424,16 @@ chrome.power.releaseKeepAwake(); this.updateInactivityWatcherState_(); }.wrap(this)); - - this.videoElement_.load(); + // TODO(ryoh): + // If you modify the video element that is already inserted, + // you have to call load() method. + // https://dev.w3.org/html5/spec-author-view/video.html + // But we always create new video element (see above), + // we don't have to call load(). + // If you call load() method here, + // you can't see subtitles. + // (It might be a bug: https://crbug.com/594537) + //this.videoElement_.load(); callback(); }.bind(this)) // In case of error. @@ -433,6 +452,24 @@ }; /** + * Search subtile file corresponding to a video. + * @param {string} url a url of a video. + * @return {string} a url of subtitle file, or an empty string. + */ +VideoPlayer.prototype.searchSubtitle_ = function(url) { + var baseUrl = util.splitExtension(url)[0]; + var resolveLocalFileSystemWithExtension = function(extension) { + return new Promise( + window.webkitResolveLocalFileSystemURL.bind(null, baseUrl + extension)); + }; + return resolveLocalFileSystemWithExtension('.vtt').then(function(subtitle) { + return subtitle.toURL(); + }).catch(function() { + return ''; + }); +}; + +/** * Plays the first video. */ VideoPlayer.prototype.playFirstVideo = function() {