diff --git a/DEPS b/DEPS index aef1cb1..8aae631 100644 --- a/DEPS +++ b/DEPS
@@ -74,7 +74,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '7ffbcf909d365eb22c5e22b776aeac7b7472fbf3', + 'skia_revision': '60b1b6e76e984228baa2e74513ea2174898c049b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -94,7 +94,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'a0aa5fdeee12bc42616fe13ef3ea62edb1b9f166', + 'swiftshader_revision': '05bcbe6b7a2dffc284b38ad0f2731d2894972cd8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -308,7 +308,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '7092a3102eae259d6ccca85a8f68d0ebf78394d2', + 'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '5c4b603461a79a731cfcb4554f244a42f7e8679d', 'condition': 'checkout_linux', }, @@ -634,7 +634,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '05591bbeae6592fd924caec8e728a4ea86cbb8c9', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '31cee3a0d51eed2417dabb7d88ec19ef59444d86', # commit position 20628 + Var('webrtc_git') + '/src.git' + '@' + '83d27683a83d8c4307ca9275779e822cb4604ccf', # commit position 20628 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/browser/aw_render_thread_context_provider.cc b/android_webview/browser/aw_render_thread_context_provider.cc index ccf24453..fb559a9 100644 --- a/android_webview/browser/aw_render_thread_context_provider.cc +++ b/android_webview/browser/aw_render_thread_context_provider.cc
@@ -67,7 +67,7 @@ context_ = gpu::GLInProcessContext::CreateWithoutInit(); context_->Initialize(service, surface, surface->IsOffscreen(), gpu::kNullSurfaceHandle, nullptr /* share_context */, - attributes, limits, nullptr, nullptr, nullptr); + attributes, limits, nullptr, nullptr, nullptr, nullptr); context_->GetImplementation()->SetLostContextCallback(base::Bind( &AwRenderThreadContextProvider::OnLostContext, base::Unretained(this)));
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc index 0f034ea7..46f061c 100644 --- a/base/allocator/partition_allocator/partition_alloc.cc +++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -53,10 +53,6 @@ } // namespace -PartitionPage* GetSentinelPageForTesting() { - return &g_sentinel_page; -} - PartitionRootBase::PartitionRootBase() = default; PartitionRootBase::~PartitionRootBase() = default; PartitionRoot::PartitionRoot() = default; @@ -75,19 +71,15 @@ nullptr; PartitionAllocHooks::FreeHook* PartitionAllocHooks::free_hook_ = nullptr; -// Find the best number of System Pages to allocate for |size| to minimize -// wasted space. Uses a heuristic that looks at number of bytes wasted after -// the last slot and attempts to account for the PTE usage of each System Page. -// // TODO(ajwong): This seems to interact badly with -// PartitionBucketPartitionPages() which rounds the value from this up to a +// get_pages_per_slot_span() which rounds the value from this up to a // multiple of kNumSystemPagesPerPartitionPage (aka 4) anyways. // http://crbug.com/776537 // // TODO(ajwong): The waste calculation seems wrong. The PTE usage should cover // both used and unsed pages. // http://crbug.com/776537 -static uint8_t PartitionBucketNumSystemPages(size_t size) { +uint8_t PartitionBucket::get_system_pages_per_slot_span() { // This works out reasonably for the current bucket sizes of the generic // allocator, and the current values of partition page size and constants. // Specifically, we have enough room to always pack the slots perfectly into @@ -100,23 +92,23 @@ // to using fewer system pages. double best_waste_ratio = 1.0f; uint16_t best_pages = 0; - if (size > kMaxSystemPagesPerSlotSpan * kSystemPageSize) { + if (this->slot_size > kMaxSystemPagesPerSlotSpan * kSystemPageSize) { // TODO(ajwong): Why is there a DCHECK here for this? // http://crbug.com/776537 - DCHECK(!(size % kSystemPageSize)); - best_pages = static_cast<uint16_t>(size / kSystemPageSize); + DCHECK(!(this->slot_size % kSystemPageSize)); + best_pages = static_cast<uint16_t>(this->slot_size / kSystemPageSize); // TODO(ajwong): Should this be checking against // kMaxSystemPagesPerSlotSpan or numeric_limits<uint8_t>::max? // http://crbug.com/776537 CHECK(best_pages < (1 << 8)); return static_cast<uint8_t>(best_pages); } - DCHECK(size <= kMaxSystemPagesPerSlotSpan * kSystemPageSize); + DCHECK(this->slot_size <= kMaxSystemPagesPerSlotSpan * kSystemPageSize); for (uint16_t i = kNumSystemPagesPerPartitionPage - 1; i <= kMaxSystemPagesPerSlotSpan; ++i) { size_t page_size = kSystemPageSize * i; - size_t num_slots = page_size / size; - size_t waste = page_size - (num_slots * size); + size_t num_slots = page_size / this->slot_size; + size_t waste = page_size - (num_slots * this->slot_size); // Leaving a page unfaulted is not free; the page will occupy an empty page // table entry. Make a simple attempt to account for that. // @@ -159,14 +151,13 @@ root->inverted_self = ~reinterpret_cast<uintptr_t>(root); } -static void PartitionBucketInitBase(PartitionBucket* bucket, - PartitionRootBase* root) { - bucket->active_pages_head = &g_sentinel_page; - bucket->empty_pages_head = nullptr; - bucket->decommitted_pages_head = nullptr; - bucket->num_full_pages = 0; - bucket->num_system_pages_per_slot_span = - PartitionBucketNumSystemPages(bucket->slot_size); +void PartitionBucket::Init(uint32_t new_slot_size) { + slot_size = new_slot_size; + active_pages_head = &g_sentinel_page; + empty_pages_head = nullptr; + decommitted_pages_head = nullptr; + num_full_pages = 0; + num_system_pages_per_slot_span = get_system_pages_per_slot_span(); } void PartitionAllocGlobalInit(void (*oom_handling_function)()) { @@ -183,10 +174,9 @@ for (i = 0; i < this->num_buckets; ++i) { PartitionBucket* bucket = &this->buckets()[i]; if (!i) - bucket->slot_size = kAllocationGranularity; + bucket->Init(kAllocationGranularity); else - bucket->slot_size = i << kBucketShift; - PartitionBucketInitBase(bucket, this); + bucket->Init(i << kBucketShift); } } @@ -235,8 +225,7 @@ PartitionBucket* bucket = &this->buckets[0]; for (i = 0; i < kGenericNumBucketedOrders; ++i) { for (j = 0; j < kGenericNumBucketsPerOrder; ++j) { - bucket->slot_size = current_size; - PartitionBucketInitBase(bucket, this); + bucket->Init(current_size); // Disable psuedo buckets so that touching them faults. if (current_size % kGenericSmallestBucket) bucket->active_pages_head = nullptr; @@ -257,7 +246,7 @@ // Use the bucket of the finest granularity for malloc(0) etc. *bucketPtr++ = &this->buckets[0]; } else if (order > kGenericMaxBucketedOrder) { - *bucketPtr++ = &g_sentinel_bucket; + *bucketPtr++ = PartitionBucket::get_sentinel_bucket(); } else { PartitionBucket* validBucket = bucket; // Skip over invalid buckets. @@ -273,7 +262,7 @@ ((kBitsPerSizeT + 1) * kGenericNumBucketsPerOrder)); // And there's one last bucket lookup that will be hit for e.g. malloc(-1), // which tries to overflow to a non-existant order. - *bucketPtr = &g_sentinel_bucket; + *bucketPtr = PartitionBucket::get_sentinel_bucket(); } #if !defined(ARCH_CPU_64_BITS) @@ -302,7 +291,7 @@ OOM_CRASH(); } -static NOINLINE void PartitionBucketFull() { +NOINLINE void PartitionBucket::OnFull() { OOM_CRASH(); } @@ -377,7 +366,7 @@ PartitionIncreaseCommittedPages(root, length); } -static ALWAYS_INLINE void* PartitionAllocPartitionPages( +ALWAYS_INLINE void* PartitionBucket::AllocNewSlotSpan( PartitionRootBase* root, int flags, uint16_t num_partition_pages) { @@ -495,37 +484,28 @@ return ret; } -// Returns a natural number of PartitionPages (calculated by -// PartitionBucketNumSystemPages()) to allocate from the current SuperPage -// when the bucket runs out of slots. -static ALWAYS_INLINE uint16_t -PartitionBucketPartitionPages(const PartitionBucket* bucket) { +ALWAYS_INLINE uint16_t PartitionBucket::get_pages_per_slot_span() { // Rounds up to nearest multiple of kNumSystemPagesPerPartitionPage. - return (bucket->num_system_pages_per_slot_span + + return (num_system_pages_per_slot_span + (kNumSystemPagesPerPartitionPage - 1)) / kNumSystemPagesPerPartitionPage; } -static ALWAYS_INLINE void PartitionPageReset(PartitionPage* page) { - DCHECK(PartitionPageStateIsDecommitted(page)); +ALWAYS_INLINE void PartitionPage::Reset() { + DCHECK(PartitionPageStateIsDecommitted(this)); - page->num_unprovisioned_slots = page->bucket->get_slots_per_span(); - DCHECK(page->num_unprovisioned_slots); + num_unprovisioned_slots = bucket->get_slots_per_span(); + DCHECK(num_unprovisioned_slots); - page->next_page = nullptr; + next_page = nullptr; } -// Each bucket allocates a slot span when it runs out of slots. -// A slot span's size is equal to PartitionBucketPartitionPages(bucket) -// number of PartitionPages. This function initializes all pages within the -// span. -static ALWAYS_INLINE void PartitionPageSetup(PartitionPage* page, - PartitionBucket* bucket) { +ALWAYS_INLINE void PartitionBucket::InitializeSlotSpan(PartitionPage* page) { // The bucket never changes. We set it up once. - page->bucket = bucket; + page->bucket = this; page->empty_cache_index = -1; - PartitionPageReset(page); + page->Reset(); // If this page has just a single slot, do not set up page offsets for any // page metadata other than the first one. This ensures that attempts to @@ -533,7 +513,7 @@ if (page->num_unprovisioned_slots == 1) return; - uint16_t num_partition_pages = PartitionBucketPartitionPages(bucket); + uint16_t num_partition_pages = get_pages_per_slot_span(); char* page_char_ptr = reinterpret_cast<char*>(page); for (uint16_t i = 1; i < num_partition_pages; ++i) { page_char_ptr += kPageMetadataSize; @@ -543,21 +523,19 @@ } } -static ALWAYS_INLINE char* PartitionPageAllocAndFillFreelist( - PartitionPage* page) { - DCHECK(page != &g_sentinel_page); +ALWAYS_INLINE char* PartitionBucket::AllocAndFillFreelist(PartitionPage* page) { + DCHECK(page != PartitionPage::get_sentinel_page()); uint16_t num_slots = page->num_unprovisioned_slots; DCHECK(num_slots); - PartitionBucket* bucket = page->bucket; // We should only get here when _every_ slot is either used or unprovisioned. // (The third state is "on the freelist". If we have a non-empty freelist, we // should not get here.) - DCHECK(num_slots + page->num_allocated_slots == bucket->get_slots_per_span()); + DCHECK(num_slots + page->num_allocated_slots == this->get_slots_per_span()); // Similarly, make explicitly sure that the freelist is empty. DCHECK(!page->freelist_head); DCHECK(page->num_allocated_slots >= 0); - size_t size = bucket->slot_size; + size_t size = this->slot_size; char* base = reinterpret_cast<char*>(PartitionPage::ToPointer(page)); char* return_object = base + (size * page->num_allocated_slots); char* firstFreelistPointer = return_object + size; @@ -602,67 +580,59 @@ freelist_pointer += size; PartitionFreelistEntry* next_entry = reinterpret_cast<PartitionFreelistEntry*>(freelist_pointer); - entry->next = PartitionFreelistMask(next_entry); + entry->next = PartitionFreelistEntry::Transform(next_entry); entry = next_entry; } - entry->next = PartitionFreelistMask(nullptr); + entry->next = PartitionFreelistEntry::Transform(nullptr); } else { page->freelist_head = nullptr; } return return_object; } -// This helper function scans a bucket's active page list for a suitable new -// active page. -// When it finds a suitable new active page (one that has free slots and is not -// empty), it is set as the new active page. If there is no suitable new -// active page, the current active page is set to &g_sentinel_page. -// As potential pages are scanned, they are tidied up according to their state. -// Empty pages are swept on to the empty page list, decommitted pages on to the -// decommitted page list and full pages are unlinked from any list. -static bool PartitionSetNewActivePage(PartitionBucket* bucket) { - PartitionPage* page = bucket->active_pages_head; - if (page == &g_sentinel_page) +bool PartitionBucket::SetNewActivePage() { + PartitionPage* page = this->active_pages_head; + if (page == PartitionPage::get_sentinel_page()) return false; PartitionPage* next_page; for (; page; page = next_page) { next_page = page->next_page; - DCHECK(page->bucket == bucket); - DCHECK(page != bucket->empty_pages_head); - DCHECK(page != bucket->decommitted_pages_head); + DCHECK(page->bucket == this); + DCHECK(page != this->empty_pages_head); + DCHECK(page != this->decommitted_pages_head); // Deal with empty and decommitted pages. if (LIKELY(PartitionPageStateIsActive(page))) { // This page is usable because it has freelist entries, or has // unprovisioned slots we can create freelist entries from. - bucket->active_pages_head = page; + this->active_pages_head = page; return true; } if (LIKELY(PartitionPageStateIsEmpty(page))) { - page->next_page = bucket->empty_pages_head; - bucket->empty_pages_head = page; + page->next_page = this->empty_pages_head; + this->empty_pages_head = page; } else if (LIKELY(PartitionPageStateIsDecommitted(page))) { - page->next_page = bucket->decommitted_pages_head; - bucket->decommitted_pages_head = page; + page->next_page = this->decommitted_pages_head; + this->decommitted_pages_head = page; } else { DCHECK(PartitionPageStateIsFull(page)); // If we get here, we found a full page. Skip over it too, and also // tag it as full (via a negative value). We need it tagged so that // free'ing can tell, and move it back into the active page list. page->num_allocated_slots = -page->num_allocated_slots; - ++bucket->num_full_pages; + ++this->num_full_pages; // num_full_pages is a uint16_t for efficient packing so guard against // overflow to be safe. - if (UNLIKELY(!bucket->num_full_pages)) - PartitionBucketFull(); + if (UNLIKELY(!this->num_full_pages)) + OnFull(); // Not necessary but might help stop accidents. page->next_page = nullptr; } } - bucket->active_pages_head = &g_sentinel_page; + this->active_pages_head = PartitionPage::get_sentinel_page(); return false; } @@ -741,7 +711,7 @@ page->freelist_head = reinterpret_cast<PartitionFreelistEntry*>(slot); PartitionFreelistEntry* next_entry = reinterpret_cast<PartitionFreelistEntry*>(slot); - next_entry->next = PartitionFreelistMask(nullptr); + next_entry->next = PartitionFreelistEntry::Transform(nullptr); DCHECK(!bucket->active_pages_head); DCHECK(!bucket->empty_pages_head); @@ -814,13 +784,13 @@ // branches. // // Note: The ordering of the conditionals matter! In particular, - // PartitionSetNewActivePage() has a side-effect even when returning + // SetNewActivePage() has a side-effect even when returning // false where it sweeps the active page list and may move things into // the empty or decommitted lists which affects the subsequent conditional. bool returnNull = flags & PartitionAllocReturnNull; if (UNLIKELY(this->is_direct_mapped())) { DCHECK(size > kGenericMaxBucketed); - DCHECK(this == &g_sentinel_bucket); + DCHECK(this == get_sentinel_bucket()); DCHECK(this->active_pages_head == &g_sentinel_page); if (size > kGenericMaxDirectMapped) { if (returnNull) @@ -828,7 +798,7 @@ PartitionExcessiveAllocationSize(); } new_page = PartitionDirectMap(root, flags, size); - } else if (LIKELY(PartitionSetNewActivePage(this))) { + } else if (LIKELY(this->SetNewActivePage())) { // First, did we find an active page in the active pages list? new_page = this->active_pages_head; DCHECK(PartitionPageStateIsActive(new_page)); @@ -860,17 +830,16 @@ void* addr = PartitionPage::ToPointer(new_page); PartitionRecommitSystemPages(root, addr, new_page->bucket->get_bytes_per_span()); - PartitionPageReset(new_page); + new_page->Reset(); } DCHECK(new_page); } else { // Third. If we get here, we need a brand new page. - uint16_t num_partition_pages = PartitionBucketPartitionPages(this); - void* rawPages = - PartitionAllocPartitionPages(root, flags, num_partition_pages); + uint16_t num_partition_pages = this->get_pages_per_slot_span(); + void* rawPages = AllocNewSlotSpan(root, flags, num_partition_pages); if (LIKELY(rawPages != nullptr)) { new_page = PartitionPage::FromPointerNoAlignmentCheck(rawPages); - PartitionPageSetup(new_page, this); + InitializeSlotSpan(new_page); } } @@ -886,7 +855,7 @@ // It seems like in many of the conditional branches above, |this| == // |new_page->bucket|. Maybe pull this into another function? PartitionBucket* bucket = new_page->bucket; - DCHECK(bucket != &g_sentinel_bucket); + DCHECK(bucket != get_sentinel_bucket()); bucket->active_pages_head = new_page; PartitionPageSetRawSize(new_page, size); @@ -894,14 +863,19 @@ // usable freelist head. if (LIKELY(new_page->freelist_head != nullptr)) { PartitionFreelistEntry* entry = new_page->freelist_head; - PartitionFreelistEntry* new_head = PartitionFreelistMask(entry->next); + PartitionFreelistEntry* new_head = + PartitionFreelistEntry::Transform(entry->next); new_page->freelist_head = new_head; new_page->num_allocated_slots++; return entry; } // Otherwise, we need to build the freelist. DCHECK(new_page->num_unprovisioned_slots); - return PartitionPageAllocAndFillFreelist(new_page); + return AllocAndFillFreelist(new_page); +} + +PartitionBucket* PartitionBucket::get_sentinel_bucket() { + return &g_sentinel_bucket; } static ALWAYS_INLINE void PartitionDecommitPage(PartitionRootBase* root, @@ -972,6 +946,10 @@ } } +PartitionPage* PartitionPage::get_sentinel_page() { + return &g_sentinel_page; +} + void PartitionPage::FreeSlowPath() { DCHECK(this != &g_sentinel_page); if (LIKELY(this->num_allocated_slots == 0)) { @@ -983,7 +961,7 @@ // If it's the current active page, change it. We bounce the page to // the empty list as a force towards defragmentation. if (LIKELY(this == bucket->active_pages_head)) - PartitionSetNewActivePage(bucket); + bucket->SetNewActivePage(); DCHECK(bucket->active_pages_head != this); PartitionPageSetRawSize(this, 0); @@ -1181,14 +1159,14 @@ size_t slotIndex = (reinterpret_cast<char*>(entry) - ptr) / slot_size; DCHECK(slotIndex < num_slots); slot_usage[slotIndex] = 0; - entry = PartitionFreelistMask(entry->next); + entry = PartitionFreelistEntry::Transform(entry->next); #if !defined(OS_WIN) // If we have a slot where the masked freelist entry is 0, we can // actually discard that freelist entry because touching a discarded // page is guaranteed to return original content or 0. // (Note that this optimization won't fire on big endian machines // because the masking function is negation.) - if (!PartitionFreelistMask(entry)) + if (!PartitionFreelistEntry::Transform(entry)) last_slot = slotIndex; #endif } @@ -1229,7 +1207,7 @@ continue; auto* entry = reinterpret_cast<PartitionFreelistEntry*>( ptr + (slot_size * slotIndex)); - *entry_ptr = PartitionFreelistMask(entry); + *entry_ptr = PartitionFreelistEntry::Transform(entry); entry_ptr = reinterpret_cast<PartitionFreelistEntry**>(entry); num_new_entries++; #if !defined(OS_WIN) @@ -1239,7 +1217,8 @@ // Terminate the freelist chain. *entry_ptr = nullptr; // The freelist head is stored unmasked. - page->freelist_head = PartitionFreelistMask(page->freelist_head); + page->freelist_head = + PartitionFreelistEntry::Transform(page->freelist_head); DCHECK(num_new_entries == num_slots - page->num_allocated_slots); // Discard the memory. DiscardSystemPages(begin_ptr, unprovisioned_bytes);
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h index 157ceff..5ee7c3b 100644 --- a/base/allocator/partition_allocator/partition_alloc.h +++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -230,8 +230,31 @@ struct PartitionBucket; struct PartitionRootBase; +// TODO(ajwong): Introduce an EncodedFreelistEntry type and then replace +// Transform() with Encode()/Decode() such that the API provides some static +// type safety. +// +// https://crbug.com/787153 struct PartitionFreelistEntry { PartitionFreelistEntry* next; + + static ALWAYS_INLINE PartitionFreelistEntry* Transform( + PartitionFreelistEntry* ptr) { +// We use bswap on little endian as a fast mask for two reasons: +// 1) If an object is freed and its vtable used where the attacker doesn't +// get the chance to run allocations between the free and use, the vtable +// dereference is likely to fault. +// 2) If the attacker has a linear buffer overflow and elects to try and +// corrupt a freelist pointer, partial pointer overwrite attacks are +// thwarted. +// For big endian, similar guarantees are arrived at with a negation. +#if defined(ARCH_CPU_BIG_ENDIAN) + uintptr_t masked = ~reinterpret_cast<uintptr_t>(ptr); +#else + uintptr_t masked = ByteSwapUintPtrT(reinterpret_cast<uintptr_t>(ptr)); +#endif + return reinterpret_cast<PartitionFreelistEntry*>(masked); + } }; // Some notes on page states. A page can be in one of four major states: @@ -295,6 +318,11 @@ } ALWAYS_INLINE size_t get_raw_size() const; + + ALWAYS_INLINE void Reset(); + + // TODO(ajwong): Can this be made private? https://crbug.com/787153 + BASE_EXPORT static PartitionPage* get_sentinel_page(); }; static_assert(sizeof(PartitionPage) <= kPageMetadataSize, "PartitionPage must be able to fit in a metadata slot"); @@ -310,6 +338,7 @@ unsigned num_full_pages : 24; // Public API. + void Init(uint32_t new_slot_size); // Note the matching Free() functions are in PartitionPage. BASE_EXPORT void* Alloc(PartitionRootBase* root, int flags, size_t size); @@ -328,6 +357,60 @@ // TODO(ajwong): Chagne to CheckedMul. https://crbug.com/787153 return static_cast<uint16_t>(get_bytes_per_span() / slot_size); } + + // TODO(ajwong): Can this be made private? https://crbug.com/787153 + static PartitionBucket* get_sentinel_bucket(); + + // This helper function scans a bucket's active page list for a suitable new + // active page. When it finds a suitable new active page (one that has + // free slots and is not empty), it is set as the new active page. If there + // is no suitable new active page, the current active page is set to + // PartitionPage::get_sentinel_page(). As potential pages are scanned, they + // are tidied up according to their state. Empty pages are swept on to the + // empty page list, decommitted pages on to the decommitted page list and full + // pages are unlinked from any list. + // + // This is where the guts of the bucket maintenance is done! + bool SetNewActivePage(); + + private: + static void OutOfMemory(const PartitionRootBase* root); + static void OutOfMemoryWithLotsOfUncommitedPages(); + + static NOINLINE void OnFull(); + + // Returns a natural number of PartitionPages (calculated by + // get_system_pages_per_slot_span()) to allocate from the current + // SuperPage when the bucket runs out of slots. + ALWAYS_INLINE uint16_t get_pages_per_slot_span(); + + // Returns the number of system pages in a slot span. + // + // The calculation attemps to find the best number of System Pages to + // allocate for the given slot_size to minimize wasted space. It uses a + // heuristic that looks at number of bytes wasted after the last slot and + // attempts to account for the PTE usage of each System Page. + uint8_t get_system_pages_per_slot_span(); + + // Allocates a new slot span with size |num_partition_pages| from the + // current extent. Metadata within this slot span will be uninitialized. + // Returns nullptr on error. + ALWAYS_INLINE void* AllocNewSlotSpan(PartitionRootBase* root, + int flags, + uint16_t num_partition_pages); + + // Each bucket allocates a slot span when it runs out of slots. + // A slot span's size is equal to get_pages_per_slot_span() number of + // PartitionPages. This function initializes all PartitionPage within the + // span to point to the first PartitionPage which holds all the metadata + // for the span and registers this bucket as the owner of the span. It does + // NOT put the slots into the bucket's freelist. + ALWAYS_INLINE void InitializeSlotSpan(PartitionPage* page); + + // Allocates one slot from the given |page| and then adds the remainder to + // the current bucket. If the |page| was freshly allocated, it must have been + // passed through InitializeSlotSpan() first. + ALWAYS_INLINE char* AllocAndFillFreelist(PartitionPage* page); }; // An "extent" is a span of consecutive superpages. We link to the partition's @@ -555,24 +638,6 @@ static FreeHook* free_hook_; }; -ALWAYS_INLINE PartitionFreelistEntry* PartitionFreelistMask( - PartitionFreelistEntry* ptr) { -// We use bswap on little endian as a fast mask for two reasons: -// 1) If an object is freed and its vtable used where the attacker doesn't -// get the chance to run allocations between the free and use, the vtable -// dereference is likely to fault. -// 2) If the attacker has a linear buffer overflow and elects to try and -// corrupt a freelist pointer, partial pointer overwrite attacks are -// thwarted. -// For big endian, similar guarantees are arrived at with a negation. -#if defined(ARCH_CPU_BIG_ENDIAN) - uintptr_t masked = ~reinterpret_cast<uintptr_t>(ptr); -#else - uintptr_t masked = ByteSwapUintPtrT(reinterpret_cast<uintptr_t>(ptr)); -#endif - return reinterpret_cast<PartitionFreelistEntry*>(masked); -} - ALWAYS_INLINE size_t PartitionCookieSizeAdjustAdd(size_t size) { #if DCHECK_IS_ON() // Add space for cookies, checking for integer overflow. TODO(palmer): @@ -728,8 +793,8 @@ // All large allocations must go through the slow path to correctly // update the size metadata. DCHECK(page->get_raw_size() == 0); - PartitionFreelistEntry* new_head = - PartitionFreelistMask(static_cast<PartitionFreelistEntry*>(ret)->next); + PartitionFreelistEntry* new_head = PartitionFreelistEntry::Transform( + static_cast<PartitionFreelistEntry*>(ret)->next); page->freelist_head = new_head; page->num_allocated_slots++; } else { @@ -802,9 +867,10 @@ PartitionPage::FromPointer(freelist_head))); CHECK(ptr != freelist_head); // Catches an immediate double free. // Look for double free one level deeper in debug. - DCHECK(!freelist_head || ptr != PartitionFreelistMask(freelist_head->next)); + DCHECK(!freelist_head || + ptr != PartitionFreelistEntry::Transform(freelist_head->next)); PartitionFreelistEntry* entry = static_cast<PartitionFreelistEntry*>(ptr); - entry->next = PartitionFreelistMask(freelist_head); + entry->next = PartitionFreelistEntry::Transform(freelist_head); freelist_head = entry; --this->num_allocated_slots; if (UNLIKELY(this->num_allocated_slots <= 0)) { @@ -973,8 +1039,6 @@ PartitionRootGeneric partition_root_; }; -BASE_EXPORT PartitionPage* GetSentinelPageForTesting(); - } // namespace base #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_H_
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index 5bd790e..3c774825 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -139,7 +139,8 @@ bucket->active_pages_head->num_allocated_slots)); EXPECT_EQ(nullptr, bucket->active_pages_head->freelist_head); EXPECT_TRUE(bucket->active_pages_head); - EXPECT_TRUE(bucket->active_pages_head != GetSentinelPageForTesting()); + EXPECT_TRUE(bucket->active_pages_head != + PartitionPage::get_sentinel_page()); return bucket->active_pages_head; } @@ -380,7 +381,7 @@ // Check that the most basic of allocate / free pairs work. TEST_F(PartitionAllocTest, Basic) { PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; - PartitionPage* seedPage = GetSentinelPageForTesting(); + PartitionPage* seedPage = PartitionPage::get_sentinel_page(); EXPECT_FALSE(bucket->empty_pages_head); EXPECT_FALSE(bucket->decommitted_pages_head); @@ -445,7 +446,7 @@ PartitionPage* page = GetFullPage(kTestAllocSize); FreeFullPage(page); EXPECT_TRUE(bucket->empty_pages_head); - EXPECT_EQ(GetSentinelPageForTesting(), bucket->active_pages_head); + EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head); EXPECT_EQ(nullptr, page->next_page); EXPECT_EQ(0, page->num_allocated_slots); @@ -464,7 +465,7 @@ FreeFullPage(page); EXPECT_EQ(0, page->num_allocated_slots); EXPECT_TRUE(bucket->empty_pages_head); - EXPECT_EQ(GetSentinelPageForTesting(), bucket->active_pages_head); + EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head); // Allocate a new page, it should pull from the freelist. page = GetFullPage(kTestAllocSize); @@ -560,7 +561,7 @@ EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->active_pages_head); for (i = 0; i < numToFillFreeListPage; ++i) FreeFullPage(pages[i]); - EXPECT_EQ(GetSentinelPageForTesting(), bucket->active_pages_head); + EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head); EXPECT_TRUE(bucket->empty_pages_head); // Allocate / free in a different bucket size so we get control of a @@ -578,7 +579,7 @@ for (i = 0; i < numToFillFreeListPage; ++i) FreeFullPage(pages[i]); - EXPECT_EQ(GetSentinelPageForTesting(), bucket->active_pages_head); + EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head); EXPECT_TRUE(bucket->empty_pages_head); } @@ -1301,14 +1302,14 @@ EXPECT_TRUE(bucket->empty_pages_head); EXPECT_TRUE(bucket->empty_pages_head->next_page); - EXPECT_EQ(GetSentinelPageForTesting(), bucket->active_pages_head); + EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head); // At this moment, we have two decommitted pages, on the empty list. ptr = generic_allocator.root()->Alloc(size, type_name); EXPECT_TRUE(ptr); generic_allocator.root()->Free(ptr); - EXPECT_EQ(GetSentinelPageForTesting(), bucket->active_pages_head); + EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head); EXPECT_TRUE(bucket->empty_pages_head); EXPECT_TRUE(bucket->decommitted_pages_head);
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc index 3f21bbe..cddef1a 100644 --- a/cc/paint/oop_pixeltest.cc +++ b/cc/paint/oop_pixeltest.cc
@@ -61,7 +61,7 @@ auto result = context_->Initialize( nullptr, nullptr, is_offscreen, gpu::kNullSurfaceHandle, nullptr, attribs, gpu::SharedMemoryLimits(), &gpu_memory_buffer_manager_, - &image_factory_, base::ThreadTaskRunnerHandle::Get()); + &image_factory_, nullptr, base::ThreadTaskRunnerHandle::Get()); ASSERT_EQ(result, gpu::ContextResult::kSuccess); ASSERT_TRUE(context_->GetCapabilities().supports_oop_raster);
diff --git a/cc/paint/transfer_cache_unittest.cc b/cc/paint/transfer_cache_unittest.cc index 3d6d016..25145930 100644 --- a/cc/paint/transfer_cache_unittest.cc +++ b/cc/paint/transfer_cache_unittest.cc
@@ -57,7 +57,7 @@ auto result = context_->Initialize( nullptr, nullptr, is_offscreen, gpu::kNullSurfaceHandle, nullptr, attribs, gpu::SharedMemoryLimits(), &gpu_memory_buffer_manager_, - &image_factory_, base::ThreadTaskRunnerHandle::Get()); + &image_factory_, nullptr, base::ThreadTaskRunnerHandle::Get()); ASSERT_EQ(result, gpu::ContextResult::kSuccess); ASSERT_TRUE(context_->GetCapabilities().supports_oop_raster);
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc index 2952964..aa79b74 100644 --- a/cc/test/test_in_process_context_provider.cc +++ b/cc/test/test_in_process_context_provider.cc
@@ -47,7 +47,7 @@ auto result = context->Initialize( nullptr, nullptr, is_offscreen, gpu::kNullSurfaceHandle, shared_context, attribs, gpu::SharedMemoryLimits(), gpu_memory_buffer_manager, - image_factory, std::move(task_runner)); + image_factory, nullptr, std::move(task_runner)); DCHECK_EQ(result, gpu::ContextResult::kSuccess); return context;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java index 8e6615f6..f666b3f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -285,7 +285,15 @@ if (mBookmarkModel == null) return; if (mBookmarkModel.isBookmarkModelLoaded()) { + BookmarkUIState searchState = null; + if (!mStateStack.isEmpty() + && mStateStack.peek().mState == BookmarkUIState.STATE_SEARCHING) { + searchState = mStateStack.pop(); + } + setState(BookmarkUIState.createStateFromUrl(url, mBookmarkModel)); + + if (searchState != null) setState(searchState); } else { mInitialUrl = url; } @@ -330,8 +338,9 @@ } mStateStack.push(state); - if (state.mState != BookmarkUIState.STATE_LOADING) { - // Loading state may be pushed to the stack but should never be stored in preferences. + if (state.mState == BookmarkUIState.STATE_FOLDER) { + // Loading and searching states may be pushed to the stack but should never be stored in + // preferences. BookmarkUtils.setLastUsedUrl(mActivity, state.mUrl); // If a loading state is replaced by another loading state, do not notify this change. if (mNativePage != null) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java index f840f61..ebfb21c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -27,7 +27,6 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.RetryOnFailure; @@ -320,7 +319,6 @@ @Test @MediumTest - @DisabledTest(message = "crbug.com/791485") public void testSearchBookmarks_Delete() throws Exception { BookmarkPromoHeader.forcePromoStateForTests(BookmarkPromoHeader.PromoState.PROMO_NONE); BookmarkId testFolder = addFolder(TEST_FOLDER_TITLE); @@ -331,12 +329,14 @@ BookmarkItemsAdapter adapter = ((BookmarkItemsAdapter) mItemsContainer.getAdapter()); BookmarkManager manager = (BookmarkManager) adapter.getDelegateForTesting(); - Assert.assertEquals(BookmarkUIState.STATE_FOLDER, manager.getCurrentState()); + Assert.assertEquals("Wrong state, should be in folder", BookmarkUIState.STATE_FOLDER, + manager.getCurrentState()); assertBookmarkItems("Wrong number of items before starting search.", 3, adapter, manager); // Start searching without entering a query. ThreadUtils.runOnUiThreadBlocking(manager::openSearchUI); - Assert.assertEquals(BookmarkUIState.STATE_SEARCHING, manager.getCurrentState()); + Assert.assertEquals("Wrong state, should be searching", BookmarkUIState.STATE_SEARCHING, + manager.getCurrentState()); // Select the folder and delete it. ThreadUtils.runOnUiThreadBlocking( @@ -348,12 +348,14 @@ R.id.selection_mode_delete_menu_id))); // Search should be exited and the folder should be gone. - Assert.assertEquals(BookmarkUIState.STATE_FOLDER, manager.getCurrentState()); + Assert.assertEquals("Wrong state, should be in folder", BookmarkUIState.STATE_FOLDER, + manager.getCurrentState()); assertBookmarkItems("Wrong number of items before starting search.", 2, adapter, manager); // Start searching, enter a query. ThreadUtils.runOnUiThreadBlocking(manager::openSearchUI); - Assert.assertEquals(BookmarkUIState.STATE_SEARCHING, manager.getCurrentState()); + Assert.assertEquals("Wrong state, should be searching", BookmarkUIState.STATE_SEARCHING, + manager.getCurrentState()); searchBookmarks("Google"); assertBookmarkItems( "Wrong number of items after searching.", 1, mItemsContainer.getAdapter(), manager); @@ -362,7 +364,8 @@ removeBookmark(testBookmark); // The user should still be searching, and the bookmark should be gone. - Assert.assertEquals(BookmarkUIState.STATE_SEARCHING, manager.getCurrentState()); + Assert.assertEquals("Wrong state, should be searching", BookmarkUIState.STATE_SEARCHING, + manager.getCurrentState()); assertBookmarkItems( "Wrong number of items after searching.", 0, mItemsContainer.getAdapter(), manager); @@ -370,7 +373,8 @@ ThreadUtils.runOnUiThreadBlocking(() -> manager.getUndoControllerForTests().onAction(null)); // The user should still be searching, and the bookmark should reappear. - Assert.assertEquals(BookmarkUIState.STATE_SEARCHING, manager.getCurrentState()); + Assert.assertEquals("Wrong state, should be searching", BookmarkUIState.STATE_SEARCHING, + manager.getCurrentState()); assertBookmarkItems( "Wrong number of items after searching.", 1, mItemsContainer.getAdapter(), manager); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java index 20c9415..8909e91 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
@@ -212,8 +212,7 @@ public void testControlsVisibleAfterExitingVr() throws InterruptedException { mVrTestFramework.loadUrlAndAwaitInitialization( VrTestFramework.getHtmlTestFile("generic_webvr_page"), PAGE_LOAD_TIMEOUT_S); - VrTransitionUtils.enterPresentationAndWait( - mVrTestFramework.getFirstTabCvc(), mVrTestFramework.getFirstTabWebContents()); + VrTransitionUtils.enterPresentationOrFail(mVrTestFramework.getFirstTabCvc()); VrTransitionUtils.forceExitVr(); // The hiding of the controls may only propagate after VR has exited, so give it a chance // to propagate. In the worst case this test will erroneously pass, but should never
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index cd99f48..daa64c6 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3318,6 +3318,11 @@ flag_descriptions::kEnableNetworkServiceDescription, kOsAll, FEATURE_VALUE_TYPE(features::kNetworkService)}, + {"network-service-in-process", + flag_descriptions::kEnableNetworkServiceInProcessName, + flag_descriptions::kEnableNetworkServiceInProcessDescription, kOsAll, + FEATURE_VALUE_TYPE(features::kNetworkServiceInProcess)}, + {"out-of-blink-cors", flag_descriptions::kEnableOutOfBlinkCORSName, flag_descriptions::kEnableOutOfBlinkCORSDescription, kOsAll, FEATURE_VALUE_TYPE(features::kOutOfBlinkCORS)},
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc index 01425032..f70e6cee 100644 --- a/chrome/browser/autofill/form_structure_browsertest.cc +++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -5,6 +5,7 @@ #include <algorithm> #include <vector> +#include "base/bind.h" #include "base/command_line.h" #include "base/feature_list.h" #include "base/files/file_enumerator.h" @@ -28,6 +29,10 @@ #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/common/autofill_features.h" #include "content/public/common/content_switches.h" +#include "net/http/http_status_code.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" #include "url/gurl.h" #if defined(OS_MACOSX) @@ -37,21 +42,15 @@ namespace autofill { namespace { +using net::test_server::BasicHttpResponse; +using net::test_server::HttpRequest; +using net::test_server::HttpResponse; + const base::FilePath::CharType kTestName[] = FILE_PATH_LITERAL("heuristics"); -// Convert the |html| snippet to a data URI. -GURL HTMLToDataURI(const std::string& html) { - // GURL requires data URLs to be UTF-8 and will fail below if it's not. - CHECK(base::IsStringUTF8(html)) << "Input file is not UTF-8."; - - // Strip `\n`, `\t`, `\r` from |html| to match old `data:` URL behavior. - std::string stripped_html; - for (const auto& character : html) { - if (character == '\n' || character == '\t' || character == '\r') - continue; - stripped_html.push_back(character); - } - return GURL(std::string("data:text/html;charset=utf-8,") + stripped_html); +const std::set<base::FilePath::StringType>& GetFailingTestNames() { + static auto* failing_test_names = new std::set<base::FilePath::StringType>{}; + return *failing_test_names; } const base::FilePath& GetTestDataDir() { @@ -65,16 +64,17 @@ return dir; } -const std::vector<base::FilePath> GetTestFiles() { - base::FilePath dir; - CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &dir)); - dir = dir.AppendASCII("components") - .AppendASCII("test") - .AppendASCII("data") - .AppendASCII("autofill") - .Append(kTestName) - .AppendASCII("input"); - base::FileEnumerator input_files(dir, false, base::FileEnumerator::FILES); +const base::FilePath GetInputDir() { + static base::FilePath input_dir = GetTestDataDir() + .AppendASCII("autofill") + .Append(kTestName) + .AppendASCII("input"); + return input_dir; +} + +std::vector<base::FilePath> GetTestFiles() { + base::FileEnumerator input_files(GetInputDir(), false, + base::FileEnumerator::FILES); std::vector<base::FilePath> files; for (base::FilePath input_file = input_files.Next(); !input_file.empty(); input_file = input_files.Next()) { @@ -89,14 +89,20 @@ return files; } -const std::set<base::FilePath::StringType>& GetFailingTestNames() { - // TODO(crbug.com/789944): Reenable these tests. - static std::set<base::FilePath::StringType>* failing_test_names = - new std::set<base::FilePath::StringType>{ - FILE_PATH_LITERAL("067_register_rei.com.html"), - FILE_PATH_LITERAL("074_register_threadless.com.html"), - }; - return *failing_test_names; +std::string FormStructuresToString( + const std::vector<std::unique_ptr<FormStructure>>& forms) { + std::string forms_string; + for (const auto& form : forms) { + for (const auto& field : *form) { + forms_string += field->Type().ToString(); + forms_string += " | " + base::UTF16ToUTF8(field->name); + forms_string += " | " + base::UTF16ToUTF8(field->label); + forms_string += " | " + base::UTF16ToUTF8(field->value); + forms_string += " | " + field->section(); + forms_string += "\n"; + } + } + return forms_string; } } // namespace @@ -113,21 +119,24 @@ ~FormStructureBrowserTest() override; // InProcessBrowserTest - void SetUpCommandLine(base::CommandLine* command_line) override { - // Suppress most output logs because we can't really control the output for - // arbitrary test sites. - command_line->AppendSwitchASCII(switches::kLoggingLevel, "2"); - } + void SetUpCommandLine(base::CommandLine* command_line) override; + + // BrowserTestBase + void SetUpOnMainThread() override; // DataDrivenTest: void GenerateResults(const std::string& input, std::string* output) override; - // Serializes the given |forms| into a string. - std::string FormStructuresToString( - const std::vector<std::unique_ptr<FormStructure>>& forms); - private: + std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request); + base::test::ScopedFeatureList feature_list_; + + // The response content to be returned by the embedded test server. Note that + // this is populated in the main thread as a part of the setup in the + // GenerateResults method but it is consumed later in the IO thread by the + // embedded test server to generate the response. + std::string html_content_; DISALLOW_COPY_AND_ASSIGN(FormStructureBrowserTest); }; @@ -140,11 +149,42 @@ FormStructureBrowserTest::~FormStructureBrowserTest() { } +void FormStructureBrowserTest::SetUpCommandLine( + base::CommandLine* command_line) { + InProcessBrowserTest::SetUpCommandLine(command_line); + // Suppress most output logs because we can't really control the output for + // arbitrary test sites. + command_line->AppendSwitchASCII(switches::kLoggingLevel, "2"); +} + +void FormStructureBrowserTest::SetUpOnMainThread() { + InProcessBrowserTest::SetUpOnMainThread(); + + embedded_test_server()->RegisterRequestHandler(base::BindRepeating( + &FormStructureBrowserTest::HandleRequest, base::Unretained(this))); + ASSERT_TRUE(embedded_test_server()->Start()); +} + void FormStructureBrowserTest::GenerateResults(const std::string& input, std::string* output) { - ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), - HTMLToDataURI(input))); + // Cache the content to be returned by the embedded test server. This data + // is readonly after this point. + html_content_.clear(); + html_content_.reserve(input.length()); + for (const char c : input) { + // Strip `\n`, `\t`, `\r` from |html| to match old `data:` URL behavior. + // TODO(crbug/239819): the tests expect weird concatenation behavior based + // legacy data URL behavior. Fix this so the the tests better represent + // the parsing being done in the wild. + if (c != '\r' && c != '\n' && c != '\t') + html_content_.push_back(c); + } + // Navigate to the test html content. + ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/test.html"))); + + // Dump the form fields (and their inferred field types). content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); ContentAutofillDriver* autofill_driver = @@ -158,20 +198,13 @@ *output = FormStructuresToString(forms); } -std::string FormStructureBrowserTest::FormStructuresToString( - const std::vector<std::unique_ptr<FormStructure>>& forms) { - std::string forms_string; - for (const auto& form : forms) { - for (const auto& field : *form) { - forms_string += field->Type().ToString(); - forms_string += " | " + base::UTF16ToUTF8(field->name); - forms_string += " | " + base::UTF16ToUTF8(field->label); - forms_string += " | " + base::UTF16ToUTF8(field->value); - forms_string += " | " + field->section(); - forms_string += "\n"; - } - } - return forms_string; +std::unique_ptr<HttpResponse> FormStructureBrowserTest::HandleRequest( + const HttpRequest& request) { + auto response = std::make_unique<BasicHttpResponse>(); + response->set_code(net::HTTP_OK); + response->set_content(html_content_); + response->set_content_type("text/html; charset=utf-8"); + return std::move(response); } IN_PROC_BROWSER_TEST_P(FormStructureBrowserTest, DataDrivenHeuristics) {
diff --git a/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source.cc b/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source.cc index 445beb9..aaf7e7eb 100644 --- a/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source.cc +++ b/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/debug_daemon_client.h" -#include "components/feedback/anonymizer_tool.h" #include "content/public/browser/browser_thread.h" namespace system_logs { @@ -65,10 +64,8 @@ // DebugDaemonClient, which does not use the SystemLogsResponse alias. auto response = std::make_unique<SystemLogsResponse>(); // Return an empty result if the call to GetLog() failed. - if (result.has_value()) { - response->emplace(log_name, - feedback::AnonymizerTool().Anonymize(result.value())); - } + if (result.has_value()) + response->emplace(log_name, result.value()); callback.Run(std::move(response)); }
diff --git a/chrome/browser/chromeos/system_logs/single_log_file_log_source.cc b/chrome/browser/chromeos/system_logs/single_log_file_log_source.cc index d59944f..84e92bdc 100644 --- a/chrome/browser/chromeos/system_logs/single_log_file_log_source.cc +++ b/chrome/browser/chromeos/system_logs/single_log_file_log_source.cc
@@ -169,8 +169,7 @@ num_bytes_read_ += size_read; // Pass it back to the callback. - AppendToSystemLogsResponse(result, source_name(), - anonymizer_.Anonymize(result_string)); + AppendToSystemLogsResponse(result, source_name(), result_string); // If the file was rotated, close the file handle and call this function // again, to read from the new file.
diff --git a/chrome/browser/chromeos/system_logs/single_log_file_log_source.h b/chrome/browser/chromeos/system_logs/single_log_file_log_source.h index 28f44540..2a1c22ff 100644 --- a/chrome/browser/chromeos/system_logs/single_log_file_log_source.h +++ b/chrome/browser/chromeos/system_logs/single_log_file_log_source.h
@@ -11,7 +11,6 @@ #include "base/files/file.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "components/feedback/anonymizer_tool.h" #include "components/feedback/system_logs/system_logs_source.h" namespace base { @@ -97,9 +96,6 @@ // was originally opened for reading. ino_t file_inode_; - // For removing PII from log results. - feedback::AnonymizerTool anonymizer_; - base::WeakPtrFactory<SingleLogFileLogSource> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SingleLogFileLogSource);
diff --git a/chrome/browser/chromeos/system_logs/single_log_file_log_source_unittest.cc b/chrome/browser/chromeos/system_logs/single_log_file_log_source_unittest.cc index f6d42c1a..1597e32 100644 --- a/chrome/browser/chromeos/system_logs/single_log_file_log_source_unittest.cc +++ b/chrome/browser/chromeos/system_logs/single_log_file_log_source_unittest.cc
@@ -270,32 +270,6 @@ EXPECT_EQ("Goodbye world\n", latest_response()); } -TEST_F(SingleLogFileLogSourceTest, Anonymize) { - InitializeSource(SingleLogFileLogSource::SupportedSource::kUiLatest); - - EXPECT_TRUE(AppendToFile(base::FilePath("ui/ui.LATEST"), - "My MAC address is: 11:22:33:44:55:66\n")); - FetchFromSource(); - - EXPECT_EQ(1, num_callback_calls()); - EXPECT_EQ("My MAC address is: 11:22:33:00:00:01\n", latest_response()); - - // Suppose the write operation is not atomic, and the MAC address is written - // across two separate writes. - EXPECT_TRUE(AppendToFile(base::FilePath("ui/ui.LATEST"), - "Your MAC address is: AB:88:C")); - FetchFromSource(); - - EXPECT_EQ(2, num_callback_calls()); - EXPECT_EQ("", latest_response()); - - EXPECT_TRUE(AppendToFile(base::FilePath("ui/ui.LATEST"), "D:99:EF:77\n")); - FetchFromSource(); - - EXPECT_EQ(3, num_callback_calls()); - EXPECT_EQ("Your MAC address is: ab:88:cd:00:00:02\n", latest_response()); -} - TEST_F(SingleLogFileLogSourceTest, HandleLogFileRotation) { InitializeSource(SingleLogFileLogSource::SupportedSource::kMessages);
diff --git a/chrome/browser/component_updater/cros_component_installer.cc b/chrome/browser/component_updater/cros_component_installer.cc index 5c27da1..b519d4d 100644 --- a/chrome/browser/component_updater/cros_component_installer.cc +++ b/chrome/browser/component_updater/cros_component_installer.cc
@@ -40,7 +40,11 @@ {"star-cups-driver", \ {{"env_version", "1.1"}, \ {"sha2hashstr", \ - "6d24de30f671da5aee6d463d9e446cafe9ddac672800a9defe86877dcde6c466"}}}}; + "6d24de30f671da5aee6d463d9e446cafe9ddac672800a9defe86877dcde6c466"}}}, \ + {"cros-cellular", \ + {{"env_version", "1.0"}, \ + {"sha2hashstr", \ + "5714811c04f0a63aac96b39096faa759ace4c04e9b68291e7c9716128f5a2722"}}}}; using content::BrowserThread;
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index e447142..6a09eb6 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -1838,9 +1838,8 @@ CloseDevToolsWindow(); } -// Flaky on multiple platforms. See http://crbug.com/432444 IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, - DISABLED_PauseInSharedWorkerInitialization) { + PauseInSharedWorkerInitialization) { ASSERT_TRUE(spawned_test_server()->Start()); GURL url = spawned_test_server()->GetURL(kReloadSharedWorkerTestPage); ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index d7c25a0..39599ce5 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -464,6 +464,11 @@ "Enables the network service, which makes network requests through a " "separate service. Note: most features don't work with this yet."; +const char kEnableNetworkServiceInProcessName[] = + "Runs network service in-process"; +const char kEnableNetworkServiceInProcessDescription[] = + "Runs the network service in the browser process."; + const char kEnableNewPrintPreview[] = "Enable new Print Preview UI"; const char kEnableNewPrintPreviewDescription[] = "If enabled, Print Preview will display a newer UI";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 6141903..61132b4 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -298,6 +298,9 @@ extern const char kEnableNetworkServiceName[]; extern const char kEnableNetworkServiceDescription[]; +extern const char kEnableNetworkServiceInProcessName[]; +extern const char kEnableNetworkServiceInProcessDescription[]; + extern const char kEnableNewPrintPreview[]; extern const char kEnableNewPrintPreviewDescription[];
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index d144111c..e842932 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -34,7 +34,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/data_usage/tab_id_annotator.h" #include "chrome/browser/data_use_measurement/chrome_data_use_ascriber.h" -#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" #include "chrome/browser/net/chrome_network_delegate.h" #include "chrome/browser/net/dns_probe_service.h" #include "chrome/browser/net/proxy_service_factory.h" @@ -724,24 +723,10 @@ void IOThread::SetUpProxyService( content::URLRequestContextBuilderMojo* builder) const { - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - - // TODO(eroman): Figure out why this doesn't work in single-process mode. - // Should be possible now that a private isolate is used. - // http://crbug.com/474654 - if (!command_line.HasSwitch(switches::kWinHttpProxyResolver)) { - if (command_line.HasSwitch(switches::kSingleProcess)) { - LOG(ERROR) << "Cannot use V8 Proxy resolver in single process mode."; - } else { - builder->SetMojoProxyResolverFactory( - ChromeMojoProxyResolverFactory::CreateWithStrongBinding()); #if defined(OS_CHROMEOS) - builder->SetDhcpFetcherFactory( - base::MakeUnique<chromeos::DhcpProxyScriptFetcherFactoryChromeos>()); + builder->SetDhcpFetcherFactory( + base::MakeUnique<chromeos::DhcpProxyScriptFetcherFactoryChromeos>()); #endif - } - } builder->set_pac_quick_check_enabled(WpadQuickCheckEnabled()); builder->set_pac_sanitize_url_policy(
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index 33e4ce8e..5144df5 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -35,8 +35,8 @@ #include "net/base/network_change_notifier.h" #include "net/nqe/network_quality_estimator.h" -class PrefService; class PrefRegistrySimple; +class PrefService; class SystemNetworkContextManager; #if defined(OS_ANDROID) @@ -210,8 +210,7 @@ bool WpadQuickCheckEnabled() const; bool PacHttpsUrlStrippingEnabled() const; - // Configures |builder|'s ProxyService based on prefs, policies, and the - // command line. + // Configures |builder|'s ProxyService based on prefs and policies. void SetUpProxyService(content::URLRequestContextBuilderMojo* builder) const; // Gets a pointer to the NetworkService. Can only be called on the UI thread.
diff --git a/chrome/browser/io_thread_browsertest.cc b/chrome/browser/io_thread_browsertest.cc index 29082fab..b4e8d4a 100644 --- a/chrome/browser/io_thread_browsertest.cc +++ b/chrome/browser/io_thread_browsertest.cc
@@ -301,52 +301,4 @@ connection_listener_->WaitForConnections(); } -class IOThreadBrowserTestWithPacFileURL : public IOThreadBrowserTest { - public: - IOThreadBrowserTestWithPacFileURL() { - EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - } - - ~IOThreadBrowserTestWithPacFileURL() override {} - - void SetUpCommandLine(base::CommandLine* command_line) override { - base::FilePath pac_file_path; - ASSERT_TRUE( - base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &pac_file_path)); - - std::string pac_script = base::StringPrintf( - "function FindProxyForURL(url, host){ return 'PROXY %s;'; }", - net::HostPortPair::FromURL(embedded_test_server()->base_url()) - .ToString() - .c_str()); - ASSERT_EQ( - static_cast<int>(pac_script.size()), - base::WriteFile(pac_file_path, pac_script.c_str(), pac_script.size())); - - command_line->AppendSwitchASCII( - switches::kProxyPacUrl, net::FilePathToFileURL(pac_file_path).spec()); - } - - protected: - base::ScopedTempDir temp_dir_; -}; - -// Make sure the system URLRequestContext can hadle fetching PAC scripts from -// file URLs. -IN_PROC_BROWSER_TEST_F(IOThreadBrowserTestWithPacFileURL, FilePac) { - TestURLFetcherDelegate fetcher_delegate; - std::unique_ptr<net::URLFetcher> fetcher = - net::URLFetcher::Create(GURL("http://foo.test:12345/echoheader?Foo"), - net::URLFetcher::GET, &fetcher_delegate); - fetcher->AddExtraRequestHeader("Foo: Bar"); - fetcher->SetRequestContext( - g_browser_process->io_thread()->system_url_request_context_getter()); - fetcher->Start(); - fetcher_delegate.WaitForCompletion(); - EXPECT_EQ(200, fetcher->GetResponseCode()); - std::string response; - ASSERT_TRUE(fetcher->GetResponseAsString(&response)); - EXPECT_EQ("Bar", response); -} - } // namespace
diff --git a/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc b/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc index afe11d0b..253ec38 100644 --- a/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc +++ b/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc
@@ -14,23 +14,12 @@ #include "content/public/common/service_manager_connection.h" #include "mojo/public/cpp/bindings/strong_binding.h" -namespace { - -void BindConnectorOnUIThread(service_manager::mojom::ConnectorRequest request) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindConnectorRequest(std::move(request)); -} - -} // namespace - ChromeMojoProxyResolverFactory::ChromeMojoProxyResolverFactory() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } ChromeMojoProxyResolverFactory::~ChromeMojoProxyResolverFactory() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } proxy_resolver::mojom::ProxyResolverFactoryPtr @@ -45,34 +34,16 @@ const std::string& pac_script, proxy_resolver::mojom::ProxyResolverRequest req, proxy_resolver::mojom::ProxyResolverFactoryRequestClientPtr client) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - InitServiceManagerConnector(); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Bind a ProxyResolverFactory backed by the proxy resolver service, have it // create a ProxyResolverFactory and then destroy the factory, to avoid // keeping the service alive after all resolvers have been destroyed. proxy_resolver::mojom::ProxyResolverFactoryPtr resolver_factory; - service_manager_connector_->BindInterface( - proxy_resolver::mojom::kProxyResolverServiceName, - mojo::MakeRequest(&resolver_factory)); + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(proxy_resolver::mojom::kProxyResolverServiceName, + mojo::MakeRequest(&resolver_factory)); resolver_factory->CreateResolver(pac_script, std::move(req), std::move(client)); } - -void ChromeMojoProxyResolverFactory::InitServiceManagerConnector() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (service_manager_connector_) - return; - - // The existing ServiceManagerConnection retrieved with - // ServiceManagerConnection::GetForProcess() lives on the UI thread, so we - // can't access it from here. We create our own connector so it can be used - // right away and will bind it on the UI thread. - service_manager::mojom::ConnectorRequest request; - service_manager_connector_ = service_manager::Connector::Create(&request); - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&BindConnectorOnUIThread, base::Passed(&request))); -}
diff --git a/chrome/browser/net/chrome_mojo_proxy_resolver_factory.h b/chrome/browser/net/chrome_mojo_proxy_resolver_factory.h index c3e21ab1..8e5199b 100644 --- a/chrome/browser/net/chrome_mojo_proxy_resolver_factory.h +++ b/chrome/browser/net/chrome_mojo_proxy_resolver_factory.h
@@ -17,7 +17,7 @@ // Starts the service as needed, and maintains no active mojo pipes to it, // so that it's automatically shut down as needed. // -// ChromeMojoProxyResolverFactories must be created and used only on the IO +// ChromeMojoProxyResolverFactories must be created and used only on the UI // thread. class ChromeMojoProxyResolverFactory : public proxy_resolver::mojom::ProxyResolverFactory { @@ -38,9 +38,6 @@ override; private: - // Initializes the ServiceManager's connector if it hasn't been already. - void InitServiceManagerConnector(); - std::unique_ptr<service_manager::Connector> service_manager_connector_; DISALLOW_COPY_AND_ASSIGN(ChromeMojoProxyResolverFactory);
diff --git a/chrome/browser/net/chrome_mojo_proxy_resolver_factory_browsertest.cc b/chrome/browser/net/chrome_mojo_proxy_resolver_factory_browsertest.cc index 74a0833..2723a07 100644 --- a/chrome/browser/net/chrome_mojo_proxy_resolver_factory_browsertest.cc +++ b/chrome/browser/net/chrome_mojo_proxy_resolver_factory_browsertest.cc
@@ -110,34 +110,6 @@ DISALLOW_COPY_AND_ASSIGN(TestServiceManagerListener); }; -// Creates a ProxyResolverFactory on the IO thread that can then be used on the -// UI thread. -proxy_resolver::mojom::ProxyResolverFactoryPtr -CreateResolverFactoryOnIOThread() { - base::RunLoop run_loop; - proxy_resolver::mojom::ProxyResolverFactoryPtrInfo resolver_factory_info; - - content::BrowserThread::PostTaskAndReply( - content::BrowserThread::IO, FROM_HERE, - base::Bind( - [](mojo::InterfacePtrInfo< - proxy_resolver::mojom::ProxyResolverFactory>* - resolver_factory_info) { - // Getting the InterfacePtr to an InterfacePtrInfo allows it to be - // passed to another thread. - *resolver_factory_info = - ChromeMojoProxyResolverFactory::CreateWithStrongBinding() - .PassInterface(); - }, - &resolver_factory_info), - run_loop.QuitClosure()); - run_loop.Run(); - - proxy_resolver::mojom::ProxyResolverFactoryPtr resolver_factory; - resolver_factory.Bind(std::move(resolver_factory_info)); - return resolver_factory; -} - // Dummy consumer of a ProxyResolverFactory. It just calls CreateResolver, and // keeps Mojo objects alive from when CreateResolver() is called until it's // destroyed. @@ -206,7 +178,7 @@ ServiceLifecycle) { // Set up the ProxyResolverFactory. proxy_resolver::mojom::ProxyResolverFactoryPtr resolver_factory = - CreateResolverFactoryOnIOThread(); + ChromeMojoProxyResolverFactory::CreateWithStrongBinding(); // Create a resolver, this should create and start the service. std::unique_ptr<DumbProxyResolverFactoryRequestClient> resolver_client1 = @@ -246,7 +218,7 @@ DestroyFactory) { // Set up the ProxyResolverFactory. proxy_resolver::mojom::ProxyResolverFactoryPtr resolver_factory = - CreateResolverFactoryOnIOThread(); + ChromeMojoProxyResolverFactory::CreateWithStrongBinding(); // Create a resolver, this should create and start the service. std::unique_ptr<DumbProxyResolverFactoryRequestClient> resolver_client1 = @@ -288,7 +260,7 @@ DestroyAndCreateService) { // Set up the ProxyResolverFactory. proxy_resolver::mojom::ProxyResolverFactoryPtr resolver_factory = - CreateResolverFactoryOnIOThread(); + ChromeMojoProxyResolverFactory::CreateWithStrongBinding(); // Create a resolver, this should create and start the service. std::unique_ptr<DumbProxyResolverFactoryRequestClient> resolver_client =
diff --git a/chrome/browser/net/default_network_context_params.cc b/chrome/browser/net/default_network_context_params.cc index 795f1875..fa76267f 100644 --- a/chrome/browser/net/default_network_context_params.cc +++ b/chrome/browser/net/default_network_context_params.cc
@@ -6,17 +6,22 @@ #include <string> +#include "base/command_line.h" #include "base/feature_list.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" #include "chrome/common/channel_info.h" +#include "chrome/common/chrome_switches.h" #include "components/policy/core/common/policy_namespace.h" #include "components/policy/core/common/policy_service.h" #include "components/policy/policy_constants.h" #include "components/version_info/version_info.h" #include "content/public/common/content_features.h" +#include "content/public/common/content_switches.h" #include "content/public/common/user_agent.h" +#include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h" content::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams() { content::mojom::NetworkContextParamsPtr network_context_params = @@ -34,6 +39,23 @@ quic_user_agent_id.append(content::BuildOSCpuInfo()); network_context_params->quic_user_agent_id = quic_user_agent_id; + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + + // TODO(eroman): Figure out why this doesn't work in single-process mode, + // or if it does work, now. + // Should be possible now that a private isolate is used. + // http://crbug.com/474654 + if (!command_line.HasSwitch(switches::kWinHttpProxyResolver)) { + if (command_line.HasSwitch(switches::kSingleProcess)) { + LOG(ERROR) << "Cannot use V8 Proxy resolver in single process mode."; + } else { + network_context_params->proxy_resolver_factory = + ChromeMojoProxyResolverFactory::CreateWithStrongBinding() + .PassInterface(); + } + } + bool http_09_on_non_default_ports_enabled = false; const base::Value* value = g_browser_process->policy_service()
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc index 3ef47eea..02fbd773 100644 --- a/chrome/browser/net/network_context_configuration_browsertest.cc +++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/network_session_configurator/common/network_switches.h" #include "components/prefs/pref_service.h" @@ -43,6 +44,9 @@ #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" +#include "net/test/spawned_test_server/spawned_test_server.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" @@ -119,6 +123,16 @@ } } + // Returns, as a string, a PAC script that will use the EmbeddedTestServer as + // a proxy. + std::string GetPacScript() const { + return base::StringPrintf( + "function FindProxyForURL(url, host){ return 'PROXY %s;'; }", + net::HostPortPair::FromURL(embedded_test_server()->base_url()) + .ToString() + .c_str()); + } + content::mojom::URLLoaderFactory* loader_factory() const { return loader_factory_; } @@ -183,10 +197,34 @@ } } + // Sends a request and expects it to be handled by embedded_test_server() + // acting as a proxy; + void TestProxyConfigured() { + std::unique_ptr<content::ResourceRequest> request = + std::make_unique<content::ResourceRequest>(); + // This URL should be directed to the test server because of the proxy. + request->url = GURL("http://jabberwocky.test:1872/echo"); + + content::SimpleURLLoaderTestHelper simple_loader_helper; + std::unique_ptr<content::SimpleURLLoader> simple_loader = + content::SimpleURLLoader::Create(std::move(request), + TRAFFIC_ANNOTATION_FOR_TESTS); + + simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + loader_factory(), simple_loader_helper.GetCallback()); + simple_loader_helper.WaitForCallback(); + + EXPECT_EQ(net::OK, simple_loader->NetError()); + ASSERT_TRUE(simple_loader_helper.response_body()); + EXPECT_EQ(*simple_loader_helper.response_body(), "Echo"); + } + private: content::mojom::NetworkContext* network_context_ = nullptr; content::mojom::URLLoaderFactory* loader_factory_ = nullptr; base::test::ScopedFeatureList feature_list_; + + DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationBrowserTest); }; IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, BasicRequest) { @@ -381,24 +419,7 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, ProxyConfig) { SetProxyPref(embedded_test_server()->host_port_pair()); - - std::unique_ptr<content::ResourceRequest> request = - std::make_unique<content::ResourceRequest>(); - // This URL should be directed to the test server because of the proxy. - request->url = GURL("http://jabberwocky.com:1872/echo"); - - content::SimpleURLLoaderTestHelper simple_loader_helper; - std::unique_ptr<content::SimpleURLLoader> simple_loader = - content::SimpleURLLoader::Create(std::move(request), - TRAFFIC_ANNOTATION_FOR_TESTS); - - simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( - loader_factory(), simple_loader_helper.GetCallback()); - simple_loader_helper.WaitForCallback(); - - EXPECT_EQ(net::OK, simple_loader->NetError()); - ASSERT_TRUE(simple_loader_helper.response_body()); - EXPECT_EQ(*simple_loader_helper.response_body(), "Echo"); + TestProxyConfigured(); } class NetworkContextConfigurationFixedPortBrowserTest @@ -450,16 +471,147 @@ switches::kProxyServer, embedded_test_server()->host_port_pair().ToString()); } + + private: + DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationProxyOnStartBrowserTest); }; // Test that when there's a proxy configuration at startup, the initial requests // use that configuration. IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationProxyOnStartBrowserTest, TestInitialProxyConfig) { + TestProxyConfigured(); +} + +// Make sure the system URLRequestContext can handle fetching PAC scripts from +// http URLs. +class NetworkContextConfigurationHttpPacBrowserTest + : public NetworkContextConfigurationBrowserTest { + public: + NetworkContextConfigurationHttpPacBrowserTest() + : pac_test_server_(net::test_server::EmbeddedTestServer::TYPE_HTTP) {} + + ~NetworkContextConfigurationHttpPacBrowserTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + pac_test_server_.RegisterRequestHandler(base::Bind( + &NetworkContextConfigurationHttpPacBrowserTest::HandlePacRequest, + GetPacScript())); + EXPECT_TRUE(pac_test_server_.Start()); + + command_line->AppendSwitchASCII(switches::kProxyPacUrl, + pac_test_server_.base_url().spec().c_str()); + } + + static std::unique_ptr<net::test_server::HttpResponse> HandlePacRequest( + const std::string& pac_script, + const net::test_server::HttpRequest& request) { + std::unique_ptr<net::test_server::BasicHttpResponse> response = + std::make_unique<net::test_server::BasicHttpResponse>(); + response->set_content(pac_script); + return response; + } + + private: + net::test_server::EmbeddedTestServer pac_test_server_; + + DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationHttpPacBrowserTest); +}; + +IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationHttpPacBrowserTest, HttpPac) { + TestProxyConfigured(); +} + +// Make sure the system URLRequestContext can handle fetching PAC scripts from +// file URLs. +class NetworkContextConfigurationFilePacBrowserTest + : public NetworkContextConfigurationBrowserTest { + public: + NetworkContextConfigurationFilePacBrowserTest() {} + + ~NetworkContextConfigurationFilePacBrowserTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + const char kPacFileName[] = "foo.pac"; + + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + base::FilePath pac_file_path = + temp_dir_.GetPath().AppendASCII(kPacFileName); + + std::string pac_script = GetPacScript(); + ASSERT_EQ( + static_cast<int>(pac_script.size()), + base::WriteFile(pac_file_path, pac_script.c_str(), pac_script.size())); + + command_line->AppendSwitchASCII( + switches::kProxyPacUrl, net::FilePathToFileURL(pac_file_path).spec()); + } + + private: + base::ScopedTempDir temp_dir_; + + DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationFilePacBrowserTest); +}; + +IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationFilePacBrowserTest, FilePac) { + TestProxyConfigured(); +} + +// Make sure the system URLRequestContext can handle fetching PAC scripts from +// data URLs. +class NetworkContextConfigurationDataPacBrowserTest + : public NetworkContextConfigurationBrowserTest { + public: + NetworkContextConfigurationDataPacBrowserTest() {} + ~NetworkContextConfigurationDataPacBrowserTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + std::string contents; + // Read in kPACScript contents. + command_line->AppendSwitchASCII(switches::kProxyPacUrl, + "data:," + GetPacScript()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationDataPacBrowserTest); +}; + +IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationDataPacBrowserTest, DataPac) { + TestProxyConfigured(); +} + +// Make sure the system URLRequestContext can handle fetching PAC scripts from +// ftp URLs. Unlike the other PAC tests, this test uses a PAC script that +// results in an error, since the spawned test server is designed so that it can +// run remotely (So can't just write a script to a local file and have the +// server serve it). +class NetworkContextConfigurationFtpPacBrowserTest + : public NetworkContextConfigurationBrowserTest { + public: + NetworkContextConfigurationFtpPacBrowserTest() + : ftp_server_(net::SpawnedTestServer::TYPE_FTP, + base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))) { + EXPECT_TRUE(ftp_server_.Start()); + } + ~NetworkContextConfigurationFtpPacBrowserTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII( + switches::kProxyPacUrl, + ftp_server_.GetURL("bad_server.pac").spec().c_str()); + } + + private: + net::SpawnedTestServer ftp_server_; + + DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationFtpPacBrowserTest); +}; + +IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationFtpPacBrowserTest, FtpPac) { std::unique_ptr<content::ResourceRequest> request = std::make_unique<content::ResourceRequest>(); // This URL should be directed to the test server because of the proxy. - request->url = GURL("http://jabberwocky.com:1872/echo"); + request->url = GURL("http://jabberwocky.test:1872/echo"); content::SimpleURLLoaderTestHelper simple_loader_helper; std::unique_ptr<content::SimpleURLLoader> simple_loader = @@ -470,9 +622,7 @@ loader_factory(), simple_loader_helper.GetCallback()); simple_loader_helper.WaitForCallback(); - EXPECT_EQ(net::OK, simple_loader->NetError()); - ASSERT_TRUE(simple_loader_helper.response_body()); - EXPECT_EQ(*simple_loader_helper.response_body(), "Echo"); + EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, simple_loader->NetError()); } // Instiates tests with a prefix indicating which NetworkContext is being @@ -505,5 +655,13 @@ NetworkContextConfigurationFixedPortBrowserTest); INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE( NetworkContextConfigurationProxyOnStartBrowserTest); +INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE( + NetworkContextConfigurationHttpPacBrowserTest); +INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE( + NetworkContextConfigurationFilePacBrowserTest); +INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE( + NetworkContextConfigurationDataPacBrowserTest); +INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE( + NetworkContextConfigurationFtpPacBrowserTest); } // namespace
diff --git a/chrome/browser/net/proxy_browsertest.cc b/chrome/browser/net/proxy_browsertest.cc index 3411515b..9d8b9fc 100644 --- a/chrome/browser/net/proxy_browsertest.cc +++ b/chrome/browser/net/proxy_browsertest.cc
@@ -179,107 +179,6 @@ VerifyProxyScript(browser()); } -// Fetch PAC script via a file:// URL. -class FileProxyScriptBrowserTest : public InProcessBrowserTest { - public: - FileProxyScriptBrowserTest() {} - ~FileProxyScriptBrowserTest() override {} - - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitchASCII(switches::kProxyPacUrl, - ui_test_utils::GetTestUrl( - base::FilePath(base::FilePath::kCurrentDirectory), - base::FilePath(kPACScript)).spec()); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FileProxyScriptBrowserTest); -}; - -IN_PROC_BROWSER_TEST_F(FileProxyScriptBrowserTest, Verify) { - VerifyProxyScript(browser()); -} - -// Fetch PAC script via an ftp:// URL. -class FtpProxyScriptBrowserTest : public InProcessBrowserTest { - public: - FtpProxyScriptBrowserTest() - : ftp_server_(net::SpawnedTestServer::TYPE_FTP, - base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))) {} - ~FtpProxyScriptBrowserTest() override {} - - void SetUp() override { - ASSERT_TRUE(ftp_server_.Start()); - InProcessBrowserTest::SetUp(); - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - base::FilePath pac_script_path(kPACScript); - command_line->AppendSwitchASCII( - switches::kProxyPacUrl, - ftp_server_.GetURL(pac_script_path.MaybeAsASCII()).spec()); - } - - private: - net::SpawnedTestServer ftp_server_; - - DISALLOW_COPY_AND_ASSIGN(FtpProxyScriptBrowserTest); -}; - -IN_PROC_BROWSER_TEST_F(FtpProxyScriptBrowserTest, Verify) { - VerifyProxyScript(browser()); -} - -// Fetch PAC script via a data: URL. -class DataProxyScriptBrowserTest : public InProcessBrowserTest { - public: - DataProxyScriptBrowserTest() {} - ~DataProxyScriptBrowserTest() override {} - - void SetUpCommandLine(base::CommandLine* command_line) override { - std::string contents; - // Read in kPACScript contents. - ASSERT_TRUE(base::ReadFileToString(ui_test_utils::GetTestFilePath( - base::FilePath(base::FilePath::kCurrentDirectory), - base::FilePath(kPACScript)), - &contents)); - command_line->AppendSwitchASCII(switches::kProxyPacUrl, - std::string("data:,") + contents); - } - - private: - DISALLOW_COPY_AND_ASSIGN(DataProxyScriptBrowserTest); -}; - -IN_PROC_BROWSER_TEST_F(DataProxyScriptBrowserTest, Verify) { - VerifyProxyScript(browser()); -} - -// Fetch PAC script via a data: URL. -class OutOfProcessProxyResolverBrowserTest : public InProcessBrowserTest { - public: - OutOfProcessProxyResolverBrowserTest() {} - ~OutOfProcessProxyResolverBrowserTest() override {} - - void SetUpCommandLine(base::CommandLine* command_line) override { - std::string contents; - // Read in kPACScript contents. - ASSERT_TRUE(base::ReadFileToString(ui_test_utils::GetTestFilePath( - base::FilePath(base::FilePath::kCurrentDirectory), - base::FilePath(kPACScript)), - &contents)); - command_line->AppendSwitchASCII( - switches::kProxyPacUrl, "data:," + contents); - } - - private: - DISALLOW_COPY_AND_ASSIGN(OutOfProcessProxyResolverBrowserTest); -}; - -IN_PROC_BROWSER_TEST_F(OutOfProcessProxyResolverBrowserTest, Verify) { - VerifyProxyScript(browser()); -} - // Fetch PAC script via a hanging http:// URL. class HangingPacRequestProxyScriptBrowserTest : public InProcessBrowserTest { public:
diff --git a/chrome/browser/printing/cloud_print/privet_http_impl.cc b/chrome/browser/printing/cloud_print/privet_http_impl.cc index e8c7f0b..ae282e6 100644 --- a/chrome/browser/printing/cloud_print/privet_http_impl.cc +++ b/chrome/browser/printing/cloud_print/privet_http_impl.cc
@@ -113,7 +113,7 @@ return privet_client_; } -void PrivetInfoOperationImpl::OnError(PrivetURLFetcher* fetcher, +void PrivetInfoOperationImpl::OnError(int response_code, PrivetURLFetcher::ErrorType error) { callback_.Run(nullptr); } @@ -173,14 +173,14 @@ return privet_client_; } -void PrivetRegisterOperationImpl::OnError(PrivetURLFetcher* fetcher, +void PrivetRegisterOperationImpl::OnError(int response_code, PrivetURLFetcher::ErrorType error) { ongoing_ = false; int visible_http_code = -1; FailureReason reason = FAILURE_NETWORK; if (error == PrivetURLFetcher::RESPONSE_CODE_ERROR) { - visible_http_code = fetcher->response_code(); + visible_http_code = response_code; reason = FAILURE_HTTP_ERROR; } else if (error == PrivetURLFetcher::JSON_PARSE_ERROR) { reason = FAILURE_MALFORMED_RESPONSE; @@ -218,7 +218,6 @@ } void PrivetRegisterOperationImpl::OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) { privet_client_->RefreshPrivetToken(callback); } @@ -319,9 +318,8 @@ } void PrivetRegisterOperationImpl::Cancelation::OnError( - PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) { -} + int response_code, + PrivetURLFetcher::ErrorType error) {} void PrivetRegisterOperationImpl::Cancelation::OnParsedJson( PrivetURLFetcher* fetcher, @@ -359,9 +357,8 @@ return privet_client_; } -void PrivetJSONOperationImpl::OnError( - PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) { +void PrivetJSONOperationImpl::OnError(int response_code, + PrivetURLFetcher::ErrorType error) { callback_.Run(nullptr); } @@ -372,7 +369,6 @@ } void PrivetJSONOperationImpl::OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) { privet_client_->RefreshPrivetToken(callback); } @@ -611,9 +607,8 @@ return privet_client_; } -void PrivetLocalPrintOperationImpl::OnError( - PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) { +void PrivetLocalPrintOperationImpl::OnError(int response_code, + PrivetURLFetcher::ErrorType error) { delegate_->OnPrivetPrintingError(this, -1); } @@ -626,7 +621,6 @@ } void PrivetLocalPrintOperationImpl::OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) { privet_client_->RefreshPrivetToken(callback); }
diff --git a/chrome/browser/printing/cloud_print/privet_http_impl.h b/chrome/browser/printing/cloud_print/privet_http_impl.h index 23011b9..d70977b 100644 --- a/chrome/browser/printing/cloud_print/privet_http_impl.h +++ b/chrome/browser/printing/cloud_print/privet_http_impl.h
@@ -34,8 +34,7 @@ PrivetHTTPClient* GetHTTPClient() override; - void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override; + void OnError(int response_code, PrivetURLFetcher::ErrorType error) override; void OnParsedJson(PrivetURLFetcher* fetcher, const base::DictionaryValue& value, bool has_error) override; @@ -60,15 +59,13 @@ void Cancel() override; void CompleteRegistration() override; - void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override; + void OnError(int response_code, PrivetURLFetcher::ErrorType error) override; void OnParsedJson(PrivetURLFetcher* fetcher, const base::DictionaryValue& value, bool has_error) override; void OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) override; PrivetHTTPClient* GetHTTPClient() override; @@ -79,8 +76,7 @@ Cancelation(PrivetHTTPClient* privet_client, const std::string& user); ~Cancelation() override; - void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override; + void OnError(int response_code, PrivetURLFetcher::ErrorType error) override; void OnParsedJson(PrivetURLFetcher* fetcher, const base::DictionaryValue& value, @@ -131,13 +127,11 @@ PrivetHTTPClient* GetHTTPClient() override; - void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override; + void OnError(int response_code, PrivetURLFetcher::ErrorType error) override; void OnParsedJson(PrivetURLFetcher* fetcher, const base::DictionaryValue& value, bool has_error) override; void OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) override; private: @@ -172,13 +166,11 @@ PrivetHTTPClient* GetHTTPClient() override; // PrivetURLFetcher::Delegate: - void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override; + void OnError(int response_code, PrivetURLFetcher::ErrorType error) override; void OnParsedJson(PrivetURLFetcher* fetcher, const base::DictionaryValue& value, bool has_error) override; void OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) override; private:
diff --git a/chrome/browser/printing/cloud_print/privet_http_unittest.cc b/chrome/browser/printing/cloud_print/privet_http_unittest.cc index 233ae95..13f22abb 100644 --- a/chrome/browser/printing/cloud_print/privet_http_unittest.cc +++ b/chrome/browser/printing/cloud_print/privet_http_unittest.cc
@@ -6,6 +6,7 @@ #include <memory> #include <utility> +#include <vector> #include "base/json/json_reader.h" #include "base/json/json_writer.h" @@ -1056,13 +1057,11 @@ } void OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) override { callback.Run("abc"); } - void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override { + void OnError(int response_code, PrivetURLFetcher::ErrorType error) override { done_ = true; success_ = false; error_ = error; @@ -1077,8 +1076,7 @@ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_); } - bool OnRawData(PrivetURLFetcher* fetcher, - bool response_is_file, + bool OnRawData(bool response_is_file, const std::string& data_string, const base::FilePath& data_file) override { done_ = true;
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher.cc b/chrome/browser/printing/cloud_print/privet_url_fetcher.cc index 15a630d1..0b1de91 100644 --- a/chrome/browser/printing/cloud_print/privet_url_fetcher.cc +++ b/chrome/browser/printing/cloud_print/privet_url_fetcher.cc
@@ -8,6 +8,7 @@ #include <algorithm> #include <limits> +#include <map> #include <memory> #include "base/bind.h" @@ -58,13 +59,11 @@ } // namespace void PrivetURLFetcher::Delegate::OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const TokenCallback& callback) { - OnError(fetcher, TOKEN_ERROR); + OnError(0, TOKEN_ERROR); } -bool PrivetURLFetcher::Delegate::OnRawData(PrivetURLFetcher* fetcher, - bool response_is_file, +bool PrivetURLFetcher::Delegate::OnRawData(bool response_is_file, const std::string& data_string, const base::FilePath& data_file) { return false; @@ -191,16 +190,15 @@ url_fetcher_->Start(); } else { - delegate_->OnError(this, UNKNOWN_ERROR); + delegate_->OnError(0, UNKNOWN_ERROR); } } void PrivetURLFetcher::Start() { DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. - if (!url_.is_valid()) { - return delegate_->OnError(this, UNKNOWN_ERROR); - } + if (!url_.is_valid()) + return delegate_->OnError(0, UNKNOWN_ERROR); if (!send_empty_privet_token_) { std::string privet_access_token; @@ -256,7 +254,7 @@ bool PrivetURLFetcher::OnURLFetchCompleteDoNotParseData( const net::URLFetcher* source) { if (source->GetStatus().status() == net::URLRequestStatus::CANCELED) { - delegate_->OnError(this, REQUEST_CANCELED); + delegate_->OnError(0, REQUEST_CANCELED); return true; } @@ -268,7 +266,7 @@ if (source->GetResponseCode() != net::HTTP_OK && source->GetResponseCode() != net::HTTP_PARTIAL_CONTENT && source->GetResponseCode() != net::HTTP_BAD_REQUEST) { - delegate_->OnError(this, RESPONSE_CODE_ERROR); + delegate_->OnError(response_code(), RESPONSE_CODE_ERROR); return true; } @@ -276,21 +274,20 @@ base::FilePath response_file_path; if (!source->GetResponseAsFilePath(true, &response_file_path)) { - delegate_->OnError(this, UNKNOWN_ERROR); + delegate_->OnError(0, UNKNOWN_ERROR); return true; } - return delegate_->OnRawData(this, true, std::string(), response_file_path); - } else { - std::string response_str; - - if (!source->GetResponseAsString(&response_str)) { - delegate_->OnError(this, UNKNOWN_ERROR); - return true; - } - - return delegate_->OnRawData(this, false, response_str, base::FilePath()); + return delegate_->OnRawData(true, std::string(), response_file_path); } + + std::string response_str; + if (!source->GetResponseAsString(&response_str)) { + delegate_->OnError(0, UNKNOWN_ERROR); + return true; + } + + return delegate_->OnRawData(false, response_str, base::FilePath()); } void PrivetURLFetcher::OnURLFetchCompleteParseData( @@ -298,27 +295,27 @@ // Response contains error description. bool is_error_response = false; if (source->GetResponseCode() != net::HTTP_OK) { - delegate_->OnError(this, RESPONSE_CODE_ERROR); + delegate_->OnError(response_code(), RESPONSE_CODE_ERROR); return; } std::string response_str; if (!source->GetResponseAsString(&response_str)) { - delegate_->OnError(this, UNKNOWN_ERROR); + delegate_->OnError(0, UNKNOWN_ERROR); return; } base::JSONReader json_reader(base::JSON_ALLOW_TRAILING_COMMAS); std::unique_ptr<base::Value> value = json_reader.ReadToValue(response_str); if (!value) { - delegate_->OnError(this, JSON_PARSE_ERROR); + delegate_->OnError(0, JSON_PARSE_ERROR); return; } const base::DictionaryValue* dictionary_value = NULL; if (!value->GetAsDictionary(&dictionary_value)) { - delegate_->OnError(this, JSON_PARSE_ERROR); + delegate_->OnError(0, JSON_PARSE_ERROR); return; } @@ -367,13 +364,12 @@ void PrivetURLFetcher::RequestTokenRefresh() { delegate_->OnNeedPrivetToken( - this, base::Bind(&PrivetURLFetcher::RefreshToken, weak_factory_.GetWeakPtr())); } void PrivetURLFetcher::RefreshToken(const std::string& token) { if (token.empty()) { - delegate_->OnError(this, TOKEN_ERROR); + delegate_->OnError(0, TOKEN_ERROR); } else { SetTokenForHost(GetHostString(), token); Try();
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher.h b/chrome/browser/printing/cloud_print/privet_url_fetcher.h index 5c5816e4..4309d248 100644 --- a/chrome/browser/printing/cloud_print/privet_url_fetcher.h +++ b/chrome/browser/printing/cloud_print/privet_url_fetcher.h
@@ -46,20 +46,18 @@ // If you do not implement this method for PrivetV1 callers, you will always // get a TOKEN_ERROR error when your token is invalid. - virtual void OnNeedPrivetToken( - PrivetURLFetcher* fetcher, - const TokenCallback& callback); + virtual void OnNeedPrivetToken(const TokenCallback& callback); - virtual void OnError(PrivetURLFetcher* fetcher, ErrorType error) = 0; + // |response_code| is only needed for RESPONSE_CODE_ERROR. + virtual void OnError(int response_code, ErrorType error) = 0; virtual void OnParsedJson(PrivetURLFetcher* fetcher, const base::DictionaryValue& value, bool has_error) = 0; // If this method is returns true, the data will not be parsed as JSON, and - // |OnParsedJson| will not be called. Otherwise, |OnParsedJson| will be + // OnParsedJson() will not be called. Otherwise, OnParsedJson() will be // called. - virtual bool OnRawData(PrivetURLFetcher* fetcher, - bool response_is_file, + virtual bool OnRawData(bool response_is_file, const std::string& data_string, const base::FilePath& data_file); }; @@ -87,11 +85,11 @@ void SendEmptyPrivetToken(); - // Set the contents of the Range header. |OnRawData| must return true if this + // Set the contents of the Range header. OnRawData() must return true if this // is called. void SetByteRange(int start, int end); - // Save the response to a file. |OnRawData| must return true if this is + // Save the response to a file. OnRawData() must return true if this is // called. void SaveResponseToFile();
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc b/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc index 016fb20..1bc11ec 100644 --- a/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc +++ b/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
@@ -40,8 +40,7 @@ ~MockPrivetURLFetcherDelegate() override { } - void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override { + void OnError(int response_code, PrivetURLFetcher::ErrorType error) override { OnErrorInternal(error); } @@ -57,12 +56,10 @@ MOCK_METHOD1(OnParsedJsonInternal, void(bool has_error)); virtual void OnNeedPrivetToken( - PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) { } - bool OnRawData(PrivetURLFetcher* fetcher, - bool response_is_file, + bool OnRawData(bool response_is_file, const std::string& data, const base::FilePath& response_file) { if (!raw_mode_) return false; @@ -130,7 +127,7 @@ TEST_F(PrivetURLFetcherTest, FetchSuccess) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); fetcher->SetResponseString(kSampleParsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); @@ -141,7 +138,7 @@ const base::DictionaryValue* value = delegate_.saved_value(); int hello_value; - ASSERT_TRUE(value != NULL); + ASSERT_TRUE(value); ASSERT_TRUE(value->GetInteger("hello", &hello_value)); EXPECT_EQ(2, hello_value); } @@ -149,7 +146,7 @@ TEST_F(PrivetURLFetcherTest, HTTP503Retry) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); fetcher->SetResponseString(kSampleParsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); @@ -160,7 +157,7 @@ RunFor(base::TimeDelta::FromSeconds(7)); fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); fetcher->SetResponseString(kSampleParsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); @@ -173,7 +170,7 @@ TEST_F(PrivetURLFetcherTest, ResponseCodeError) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); fetcher->SetResponseString(kSampleParsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); @@ -187,7 +184,7 @@ TEST_F(PrivetURLFetcherTest, JsonParseError) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); fetcher->SetResponseString(kSampleUnparsableJSON); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); @@ -201,7 +198,7 @@ TEST_F(PrivetURLFetcherTest, Header) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); net::HttpRequestHeaders headers; fetcher->GetExtraRequestHeaders(&headers); @@ -218,7 +215,7 @@ privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); net::HttpRequestHeaders headers; fetcher->GetExtraRequestHeaders(&headers); @@ -235,7 +232,7 @@ privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); net::HttpRequestHeaders headers; fetcher->GetExtraRequestHeaders(&headers); @@ -247,7 +244,7 @@ TEST_F(PrivetURLFetcherTest, FetchHasError) { privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); fetcher->SetResponseString(kSampleJSONWithError); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); @@ -261,7 +258,7 @@ delegate_.SetRawMode(true); privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); fetcher->SetResponseString(kSampleJSONWithError); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); @@ -276,7 +273,7 @@ privet_urlfetcher_->SetByteRange(200, 300); privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); net::HttpRequestHeaders headers; fetcher->GetExtraRequestHeaders(&headers); @@ -290,7 +287,7 @@ privet_urlfetcher_->SaveResponseToFile(); privet_urlfetcher_->Start(); net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher != NULL); + ASSERT_TRUE(fetcher); fetcher->SetResponseFilePath( base::FilePath(FILE_PATH_LITERAL("sample/file"))); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.cc b/chrome/browser/ui/search_engines/template_url_table_model.cc index d764a177..cb9726f0 100644 --- a/chrome/browser/ui/search_engines/template_url_table_model.cc +++ b/chrome/browser/ui/search_engines/template_url_table_model.cc
@@ -16,11 +16,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/table_model_observer.h" -// Group IDs used by TemplateURLTableModel. -static const int kMainGroupID = 0; -static const int kOtherGroupID = 1; -static const int kExtensionGroupID = 2; - TemplateURLTableModel::TemplateURLTableModel( TemplateURLService* template_url_service) : observer_(NULL), template_url_service_(template_url_service) { @@ -96,41 +91,6 @@ observer_ = observer; } -bool TemplateURLTableModel::HasGroups() { - return true; -} - -TemplateURLTableModel::Groups TemplateURLTableModel::GetGroups() { - Groups groups; - - Group search_engine_group; - search_engine_group.title = - l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_MAIN_SEPARATOR); - search_engine_group.id = kMainGroupID; - groups.push_back(search_engine_group); - - Group other_group; - other_group.title = - l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_OTHER_SEPARATOR); - other_group.id = kOtherGroupID; - groups.push_back(other_group); - - Group extension_group; - extension_group.title = - l10n_util::GetStringUTF16(IDS_SEARCH_ENGINES_EDITOR_EXTENSIONS_SEPARATOR); - extension_group.id = kExtensionGroupID; - groups.push_back(extension_group); - - return groups; -} - -int TemplateURLTableModel::GetGroupID(int row) { - DCHECK(row >= 0 && row < RowCount()); - if (row < last_search_engine_index_) - return kMainGroupID; - return row < last_other_engine_index_ ? kOtherGroupID : kExtensionGroupID; -} - void TemplateURLTableModel::Remove(int index) { // Remove the observer while we modify the model, that way we don't need to // worry about the model calling us back when we mutate it.
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.h b/chrome/browser/ui/search_engines/template_url_table_model.h index 1646f6c..354eeeb 100644 --- a/chrome/browser/ui/search_engines/template_url_table_model.h +++ b/chrome/browser/ui/search_engines/template_url_table_model.h
@@ -44,9 +44,6 @@ int RowCount() override; base::string16 GetText(int row, int column) override; void SetObserver(ui::TableModelObserver* observer) override; - bool HasGroups() override; - Groups GetGroups() override; - int GetGroupID(int row) override; // Removes the entry at the specified index. void Remove(int index);
diff --git a/chrome/browser/vr/elements/text.cc b/chrome/browser/vr/elements/text.cc index ec70ddf..b5a610b 100644 --- a/chrome/browser/vr/elements/text.cc +++ b/chrome/browser/vr/elements/text.cc
@@ -13,6 +13,10 @@ #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/render_text.h" +namespace { +constexpr float kCursorWidthRatio = 0.07f; +} + namespace vr { class TextTexture : public UiTexture { @@ -29,11 +33,20 @@ } void SetMultiLine(bool multiline) { SetAndDirty(&multiline_, multiline); } + void SetCursorEnabled(bool enabled) { + SetAndDirty(&cursor_enabled_, enabled); + } + + void SetCursorPosition(int position) { + SetAndDirty(&cursor_position_, position); + } void SetTextWidth(float width) { SetAndDirty(&text_width_, width); } gfx::SizeF GetDrawnSize() const override { return size_; } + gfx::Rect get_cursor_bounds() { return cursor_bounds_; } + // This method does all text preparation for the element other than drawing to // the texture. This allows for deeper unit testing of the Text element // without having to mock canvases and simulate frame rendering. The state of @@ -56,6 +69,9 @@ TextAlignment alignment_ = kTextAlignmentCenter; bool multiline_ = true; SkColor color_ = SK_ColorBLACK; + bool cursor_enabled_ = false; + int cursor_position_ = 0; + gfx::Rect cursor_bounds_; DISALLOW_COPY_AND_ASSIGN(TextTexture); }; @@ -81,6 +97,25 @@ texture_->SetMultiLine(multiline); } +void Text::SetCursorEnabled(bool enabled) { + texture_->SetCursorEnabled(enabled); +} + +void Text::SetCursorPosition(int position) { + texture_->SetCursorPosition(position); +} + +gfx::RectF Text::GetCursorBounds() { + // Note that gfx:: cursor bounds always indicate a one-pixel width, so we + // override the width here to be a percentage of height for the sake of + // arbitrary texture sizes. + gfx::Rect bounds = texture_->get_cursor_bounds(); + float scale = size().width() / texture_->GetDrawnSize().width(); + return gfx::RectF( + bounds.CenterPoint().x() * scale, bounds.CenterPoint().y() * scale, + bounds.height() * scale * kCursorWidthRatio, bounds.height() * scale); +} + void Text::OnSetSize(gfx::SizeF size) { texture_->SetTextWidth(size.width()); } @@ -113,6 +148,13 @@ text_, fonts, color_, &text_bounds, alignment_, multiline_ ? kWrappingBehaviorWrap : kWrappingBehaviorNoWrap); + if (cursor_enabled_) { + DCHECK(!multiline_); + lines.front()->SetCursorEnabled(true); + lines.front()->SetCursorPosition(cursor_position_); + cursor_bounds_ = lines.front()->GetUpdatedCursorBounds(); + } + // Note, there is no padding here whatsoever. size_ = gfx::SizeF(text_bounds.size());
diff --git a/chrome/browser/vr/elements/text.h b/chrome/browser/vr/elements/text.h index 6eb63c42..43a9641 100644 --- a/chrome/browser/vr/elements/text.h +++ b/chrome/browser/vr/elements/text.h
@@ -10,6 +10,7 @@ #include "chrome/browser/vr/elements/textured_element.h" #include "chrome/browser/vr/elements/ui_texture.h" #include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkRect.h" namespace gfx { class RenderText; @@ -30,6 +31,16 @@ void SetTextAlignment(UiTexture::TextAlignment alignment); void SetMultiLine(bool multiline); + // This text element does not typically feature a cursor, but since the cursor + // position is deterined while laying out text, a parent may wish to supply + // cursor parameters and determine where the cursor was last drawn. + void SetCursorEnabled(bool enabled); + void SetCursorPosition(int position); + + // Returns the most recently computed cursor position, in DMM, relative to the + // corner of the element. + gfx::RectF GetCursorBounds(); + void OnSetSize(gfx::SizeF size) override; std::vector<std::unique_ptr<gfx::RenderText>> LayOutTextForTest(
diff --git a/chrome/browser/vr/elements/text_input.cc b/chrome/browser/vr/elements/text_input.cc index cbd93505..b110e7a 100644 --- a/chrome/browser/vr/elements/text_input.cc +++ b/chrome/browser/vr/elements/text_input.cc
@@ -5,93 +5,59 @@ #include "chrome/browser/vr/elements/text_input.h" #include "base/memory/ptr_util.h" -#include "cc/paint/skia_paint_canvas.h" +#include "chrome/browser/vr/elements/rect.h" +#include "chrome/browser/vr/elements/text.h" #include "chrome/browser/vr/elements/ui_texture.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font_list.h" #include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/rect_f.h" -#include "ui/gfx/render_text.h" + +namespace { +constexpr int kCursorBlinkHalfPeriodMs = 600; +} namespace vr { -class TextInputTexture : public UiTexture { - public: - TextInputTexture(float font_height, float text_width) - : font_height_(font_height), text_width_(text_width) {} - ~TextInputTexture() override {} - - void SetText(const base::string16& text) { SetAndDirty(&text_, text); } - - void SetCursorPosition(int position) { - SetAndDirty(&cursor_position_, position); - } - - void SetColor(SkColor color) { SetAndDirty(&color_, color); } - - void SetCursorVisible(bool visible) { - SetAndDirty(&cursor_visible_, visible); - } - - void Draw(SkCanvas* sk_canvas, const gfx::Size& texture_size) override { - cc::SkiaPaintCanvas paint_canvas(sk_canvas); - gfx::Canvas gfx_canvas(&paint_canvas, 1.0f); - gfx::Canvas* canvas = &gfx_canvas; - - gfx::FontList font_list; - float pixels_per_meter = texture_size.width() / text_width_; - int pixel_font_height = static_cast<int>(font_height_ * pixels_per_meter); - GetDefaultFontList(pixel_font_height, text_, &font_list); - gfx::Rect text_bounds(texture_size.width(), pixel_font_height); - size_ = gfx::SizeF(text_bounds.size()); - - std::unique_ptr<gfx::RenderText> render_text(CreateRenderText()); - render_text->SetText(text_); - render_text->SetFontList(font_list); - render_text->SetColor(color_); - render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); - render_text->SetDisplayRect(text_bounds); - if (cursor_visible_) { - render_text->SetCursorEnabled(true); - render_text->SetCursorPosition(cursor_position_); - } - render_text->Draw(canvas); - - if (cursor_visible_) { - auto bounds = render_text->GetUpdatedCursorBounds(); - canvas->DrawRect(gfx::RectF(bounds), 0xFF000080); - } - } - - private: - gfx::Size GetPreferredTextureSize(int width) const override { - return gfx::Size(width, width * font_height_ / text_width_); - } - - gfx::SizeF GetDrawnSize() const override { return size_; } - - gfx::SizeF size_; - base::string16 text_; - int cursor_position_ = 0; - float font_height_; - float text_width_; - SkColor color_ = SK_ColorBLACK; - bool cursor_visible_ = false; - - DISALLOW_COPY_AND_ASSIGN(TextInputTexture); -}; - TextInput::TextInput(int maximum_width_pixels, float font_height_meters, - float text_width_meters, OnFocusChangedCallback focus_changed_callback, OnInputEditedCallback input_edit_callback) - : TexturedElement(maximum_width_pixels), - texture_(base::MakeUnique<TextInputTexture>(font_height_meters, - text_width_meters)), - focus_changed_callback_(focus_changed_callback), + : focus_changed_callback_(focus_changed_callback), input_edit_callback_(input_edit_callback) { - SetSize(text_width_meters, font_height_meters); + auto text = base::MakeUnique<Text>(maximum_width_pixels, font_height_meters); + text->set_type(kTypeTextInputHint); + text->set_draw_phase(kPhaseForeground); + text->set_hit_testable(false); + text->set_x_anchoring(LEFT); + text->set_x_centering(LEFT); + text->SetSize(1, 1); + text->SetMultiLine(false); + text->SetTextAlignment(UiTexture::kTextAlignmentLeft); + hint_element_ = text.get(); + this->AddChild(std::move(text)); + + text = base::MakeUnique<Text>(maximum_width_pixels, font_height_meters); + text->set_type(kTypeTextInputText); + text->set_draw_phase(kPhaseForeground); + text->set_hit_testable(false); + text->set_x_anchoring(LEFT); + text->set_x_centering(LEFT); + text->SetSize(1, 1); + text->SetMultiLine(false); + text->SetTextAlignment(UiTexture::kTextAlignmentLeft); + text->SetCursorEnabled(true); + text_element_ = text.get(); + this->AddChild(std::move(text)); + + auto cursor = base::MakeUnique<Rect>(); + cursor->set_type(kTypeTextInputCursor); + cursor->set_draw_phase(kPhaseForeground); + cursor->set_hit_testable(false); + cursor->set_x_anchoring(LEFT); + cursor->set_y_anchoring(BOTTOM); + cursor->SetColor(SK_ColorBLUE); + cursor_element_ = cursor.get(); + text_element_->AddChild(std::move(cursor)); + + set_bounds_contain_children(true); } TextInput::~TextInput() {} @@ -105,20 +71,28 @@ } void TextInput::OnButtonUp(const gfx::PointF& position) { + RequestFocus(); +} + +void TextInput::OnFocusChanged(bool focused) { + focused_ = focused; + + // Update the keyboard with the current text. + if (delegate_ && focused) + delegate_->UpdateInput(text_info_); + + focus_changed_callback_.Run(focused); +} + +void TextInput::RequestFocus() { if (!delegate_) return; delegate_->RequestFocus(id()); } -void TextInput::OnFocusChanged(bool focused) { - focused_ = focused; - texture_->SetCursorVisible(focused); - // Update the keyboard with the current text. - if (delegate_ && focused) - delegate_->UpdateInput(text_info_); - - focus_changed_callback_.Run(focused); +void TextInput::SetHintText(const base::string16& text) { + hint_element_->SetText(text); } void TextInput::OnInputEdited(const TextInputInfo& info) { @@ -127,33 +101,61 @@ void TextInput::OnInputCommitted(const TextInputInfo& info) {} -void TextInput::SetColor(SkColor color) { - texture_->SetColor(color); +void TextInput::SetTextColor(SkColor color) { + text_element_->SetColor(color); +} + +void TextInput::SetCursorColor(SkColor color) { + cursor_element_->SetColor(color); } void TextInput::UpdateInput(const TextInputInfo& info) { if (text_info_ == info) return; - text_info_ = info; - texture_->SetText(info.text); - texture_->SetCursorPosition(info.selection_end); if (delegate_ && focused_) delegate_->UpdateInput(info); + + text_element_->SetText(info.text); + text_element_->SetCursorPosition(info.selection_end); + hint_element_->SetVisible(info.text.empty()); } bool TextInput::OnBeginFrame(const base::TimeTicks& time, const gfx::Vector3dF& look_at) { - base::TimeDelta delta = time - base::TimeTicks(); - if (focused_) - texture_->SetCursorVisible(delta.InMilliseconds() / 500 % 2); - - return false; + return SetCursorBlinkState(time); } -UiTexture* TextInput::GetTexture() const { - return texture_.get(); +void TextInput::OnSetSize(gfx::SizeF size) { + hint_element_->SetSize(size.width(), size.height()); + text_element_->SetSize(size.width(), size.height()); +} + +void TextInput::OnSetName() { + hint_element_->set_owner_name_for_test(name()); + text_element_->set_owner_name_for_test(name()); + cursor_element_->set_owner_name_for_test(name()); +} + +void TextInput::LayOutChildren() { + // To avoid re-rendering a texture when the cursor blinks, the texture is a + // separate element. Once the text has been laid out, we can position the + // cursor appropriately relative to the text field. + gfx::RectF bounds = text_element_->GetCursorBounds(); + cursor_element_->SetTranslate(bounds.x(), bounds.y(), 0); + cursor_element_->SetSize(bounds.width(), bounds.height()); +} + +bool TextInput::SetCursorBlinkState(const base::TimeTicks& time) { + base::TimeDelta delta = time - base::TimeTicks(); + bool visible = + focused_ && delta.InMilliseconds() / kCursorBlinkHalfPeriodMs % 2; + if (cursor_visible_ == visible) + return false; + cursor_visible_ = visible; + cursor_element_->SetVisible(visible); + return true; } } // namespace vr
diff --git a/chrome/browser/vr/elements/text_input.h b/chrome/browser/vr/elements/text_input.h index f998643..67d0bc6 100644 --- a/chrome/browser/vr/elements/text_input.h +++ b/chrome/browser/vr/elements/text_input.h
@@ -5,9 +5,8 @@ #ifndef CHROME_BROWSER_VR_ELEMENTS_TEXT_INPUT_H_ #define CHROME_BROWSER_VR_ELEMENTS_TEXT_INPUT_H_ -#include <memory> - #include "base/callback.h" +#include "base/macros.h" #include "chrome/browser/vr/elements/textured_element.h" #include "chrome/browser/vr/elements/ui_texture.h" #include "chrome/browser/vr/model/text_input_info.h" @@ -16,12 +15,10 @@ namespace vr { -class TextInputTexture; +class Rect; +class Text; -// TODO(cjgrant): This class must be refactored to reuse Text and Rect elements -// for the text and cursor. It exists as-is to facilitate initial integration of -// the keyboard and omnibox. -class TextInput : public TexturedElement { +class TextInput : public UiElement { public: // Called when this element recieves focus. typedef base::RepeatingCallback<void(bool)> OnFocusChangedCallback; @@ -30,7 +27,6 @@ OnInputEditedCallback; TextInput(int maximum_width_pixels, float font_height_meters, - float text_width_meters, OnFocusChangedCallback focus_changed_callback, OnInputEditedCallback input_edit_callback); ~TextInput() override; @@ -41,22 +37,33 @@ void OnInputEdited(const TextInputInfo& info) override; void OnInputCommitted(const TextInputInfo& info) override; - void SetTextInputDelegate(TextInputDelegate* text_input_delegate); - void SetColor(SkColor color); + void RequestFocus(); void UpdateInput(const TextInputInfo& info); + void SetHintText(const base::string16& text); + void SetTextColor(SkColor color); + void SetCursorColor(SkColor color); + void SetTextInputDelegate(TextInputDelegate* text_input_delegate); + bool OnBeginFrame(const base::TimeTicks& time, - const gfx::Vector3dF& look_at) override; + const gfx::Vector3dF& look_at) final; + void OnSetSize(gfx::SizeF size) final; + void OnSetName() final; private: - UiTexture* GetTexture() const override; + void LayOutChildren() final; + bool SetCursorBlinkState(const base::TimeTicks& time); - std::unique_ptr<TextInputTexture> texture_; OnFocusChangedCallback focus_changed_callback_; OnInputEditedCallback input_edit_callback_; TextInputDelegate* delegate_ = nullptr; TextInputInfo text_info_; bool focused_ = false; + bool cursor_visible_ = false; + + Text* hint_element_ = nullptr; + Text* text_element_ = nullptr; + Rect* cursor_element_ = nullptr; DISALLOW_COPY_AND_ASSIGN(TextInput); };
diff --git a/chrome/browser/vr/elements/ui_element_type.cc b/chrome/browser/vr/elements/ui_element_type.cc index c2d209c..9d2fda7 100644 --- a/chrome/browser/vr/elements/ui_element_type.cc +++ b/chrome/browser/vr/elements/ui_element_type.cc
@@ -24,6 +24,9 @@ "kTypeOmniboxSuggestionIcon", "kTypeOmniboxSuggestionContentText", "kTypeOmniboxSuggestionDescriptionText", + "kTypeTextInputHint", + "kTypeTextInputText", + "kTypeTextInputCursor", }; static_assert(
diff --git a/chrome/browser/vr/elements/ui_element_type.h b/chrome/browser/vr/elements/ui_element_type.h index 1ecdd6d..627c410 100644 --- a/chrome/browser/vr/elements/ui_element_type.h +++ b/chrome/browser/vr/elements/ui_element_type.h
@@ -24,6 +24,9 @@ kTypeOmniboxSuggestionIcon, kTypeOmniboxSuggestionContentText, kTypeOmniboxSuggestionDescriptionText, + kTypeTextInputHint, + kTypeTextInputText, + kTypeTextInputCursor, // This must be last. kNumUiElementTypes,
diff --git a/chrome/browser/vr/model/color_scheme.cc b/chrome/browser/vr/model/color_scheme.cc index 2474154f..c399653 100644 --- a/chrome/browser/vr/model/color_scheme.cc +++ b/chrome/browser/vr/model/color_scheme.cc
@@ -116,6 +116,7 @@ normal_scheme.omnibox_text = 0xFF595959; normal_scheme.omnibox_suggestion_content = 0xFF595959; normal_scheme.omnibox_suggestion_description = 0xFF5595FE; + normal_scheme.cursor = 0xFF5595FE; g_fullscreen_scheme.Get() = normal_scheme; ColorScheme& fullscreen_scheme = g_fullscreen_scheme.Get();
diff --git a/chrome/browser/vr/model/color_scheme.h b/chrome/browser/vr/model/color_scheme.h index e094bc39..bda98a5 100644 --- a/chrome/browser/vr/model/color_scheme.h +++ b/chrome/browser/vr/model/color_scheme.h
@@ -108,6 +108,8 @@ SkColor omnibox_text; SkColor omnibox_suggestion_content; SkColor omnibox_suggestion_description; + + SkColor cursor; }; } // namespace vr
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc index d70b00c2..e0a0fa88 100644 --- a/chrome/browser/vr/testapp/vr_test_context.cc +++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -11,11 +11,13 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/vr/controller_mesh.h" +#include "chrome/browser/vr/keyboard_delegate.h" #include "chrome/browser/vr/model/model.h" #include "chrome/browser/vr/model/omnibox_suggestions.h" #include "chrome/browser/vr/model/toolbar_state.h" #include "chrome/browser/vr/speech_recognizer.h" #include "chrome/browser/vr/test/constants.h" +#include "chrome/browser/vr/text_input_delegate.h" #include "chrome/browser/vr/ui.h" #include "chrome/browser/vr/ui_element_renderer.h" #include "chrome/browser/vr/ui_input_manager.h" @@ -56,6 +58,31 @@ } // namespace +// This stub delegate does nothing today, but can be expanded to offer +// legitimate keyboard support if required. +class TestKeyboardDelegate : KeyboardDelegate { + public: + // KeyboardDelegate implemenation. + void ShowKeyboard() override {} + void HideKeyboard() override {} + void SetTransform(const gfx::Transform&) override {} + bool HitTest(const gfx::Point3F& ray_origin, + const gfx::Point3F& ray_target, + gfx::Point3F* hit_position) override { + return false; + } + void Draw(const CameraModel&) override {} + + // Testapp-specific hooks. + void SetUiInterface(vr::KeyboardUiInterface* keyboard) { + keyboard_interface_ = keyboard; + } + void UpdateInput(const vr::TextInputInfo& info) {} + + private: + vr::KeyboardUiInterface* keyboard_interface_ = nullptr; +}; + VrTestContext::VrTestContext() : view_scale_factor_(kDefaultViewScaleFactor) { base::FilePath pak_path; PathService::Get(base::DIR_MODULE, &pak_path); @@ -64,7 +91,19 @@ base::i18n::InitializeICU(); - ui_ = base::MakeUnique<Ui>(this, nullptr, nullptr, nullptr, UiInitialState()); + text_input_delegate_ = base::MakeUnique<vr::TextInputDelegate>(); + keyboard_delegate_ = base::MakeUnique<vr::TestKeyboardDelegate>(); + + ui_ = base::MakeUnique<Ui>(this, nullptr, nullptr, text_input_delegate_.get(), + UiInitialState()); + + text_input_delegate_->SetRequestFocusCallback( + base::BindRepeating(&vr::Ui::RequestFocus, base::Unretained(ui_.get()))); + text_input_delegate_->SetUpdateInputCallback( + base::BindRepeating(&TestKeyboardDelegate::UpdateInput, + base::Unretained(keyboard_delegate_.get()))); + keyboard_delegate_->SetUiInterface(ui_.get()); + model_ = ui_->model_for_test(); ToolbarState state(GURL("https://dangerous.com/dir/file.html"), @@ -107,8 +146,6 @@ if (model_->web_vr_has_produced_frames()) { ui_->ui_renderer()->DrawWebVrOverlayForeground(render_info); } - - // TODO(cjgrant): Render viewport-aware elements. } void VrTestContext::HandleInput(ui::Event* event) { @@ -149,6 +186,10 @@ case ui::DomCode::US_R: ui_->OnWebVrFrameAvailable(); break; + case ui::DomCode::US_A: { + CreateFakeTextInput(); + break; + } default: break; } @@ -307,10 +348,24 @@ return texture_id; } +void VrTestContext::CreateFakeTextInput() { + // Every time this method is called, change the number of suggestions shown. + const std::string text = + "what is the actual meaning of life when considering all factors"; + + static int len = 0; + len = (len + 1) % text.size(); + + TextInputInfo info; + info.text = base::UTF8ToUTF16(text.substr(0, len)); + info.selection_start = len; + info.selection_end = len; + ui_->OnInputEdited(info); +} + void VrTestContext::CreateFakeOmniboxSuggestions() { // Every time this method is called, change the number of suggestions shown. static int num_suggestions = 0; - num_suggestions = (num_suggestions + 1) % 4; auto result = base::MakeUnique<OmniboxSuggestions>(); for (int i = 0; i < num_suggestions; i++) { @@ -323,6 +378,9 @@ } model_->omnibox_input_active = true; ui_->SetOmniboxSuggestions(std::move(result)); + + num_suggestions++; + num_suggestions %= 5; } void VrTestContext::CreateFakeVoiceSearchResult() {
diff --git a/chrome/browser/vr/testapp/vr_test_context.h b/chrome/browser/vr/testapp/vr_test_context.h index e23d41b..3ae5024 100644 --- a/chrome/browser/vr/testapp/vr_test_context.h +++ b/chrome/browser/vr/testapp/vr_test_context.h
@@ -20,6 +20,8 @@ namespace vr { +class TextInputDelegate; +class TestKeyboardDelegate; class Ui; struct Model; @@ -56,6 +58,7 @@ unsigned int CreateFakeContentTexture(); void CreateFakeOmniboxSuggestions(); void CreateFakeVoiceSearchResult(); + void CreateFakeTextInput(); void CycleWebVrModes(); void ToggleSplashScreen(); gfx::Transform ProjectionMatrix() const; @@ -86,6 +89,9 @@ ControllerModel last_controller_model_; + std::unique_ptr<TextInputDelegate> text_input_delegate_; + std::unique_ptr<TestKeyboardDelegate> keyboard_delegate_; + DISALLOW_COPY_AND_ASSIGN(VrTestContext); };
diff --git a/chrome/browser/vr/text_input_unittest.cc b/chrome/browser/vr/text_input_unittest.cc index 094ad9b3..07db52c7 100644 --- a/chrome/browser/vr/text_input_unittest.cc +++ b/chrome/browser/vr/text_input_unittest.cc
@@ -85,7 +85,7 @@ base::MakeUnique<StrictMock<MockTextInputDelegate>>(); text_input_info_ = base::MakeUnique<TextInputInfo>(); auto text_input = UiSceneCreator::CreateTextInput( - 512, 1, 1, model_, text_input_info_.get(), text_input_delegate_.get()); + 512, 1, model_, text_input_info_.get(), text_input_delegate_.get()); text_input_ = text_input.get(); scene_->AddUiElement(k2dBrowsingForeground, std::move(text_input)); EXPECT_TRUE(OnBeginFrame());
diff --git a/chrome/browser/vr/ui_input_manager_unittest.cc b/chrome/browser/vr/ui_input_manager_unittest.cc index 8c2bf22..c8ccd58d 100644 --- a/chrome/browser/vr/ui_input_manager_unittest.cc +++ b/chrome/browser/vr/ui_input_manager_unittest.cc
@@ -57,7 +57,6 @@ MockTextInput() : TextInput(512, 1, - 1, base::RepeatingCallback<void(bool)>(), base::RepeatingCallback<void(const TextInputInfo&)>()) {} ~MockTextInput() override = default;
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc index ea269b53..518ca00 100644 --- a/chrome/browser/vr/ui_scene_creator.cc +++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -982,12 +982,11 @@ std::unique_ptr<TextInput> UiSceneCreator::CreateTextInput( int maximum_width_pixels, float font_height_meters, - float text_width_meters, Model* model, TextInputInfo* text_input_model, TextInputDelegate* text_input_delegate) { auto text_input = base::MakeUnique<TextInput>( - maximum_width_pixels, font_height_meters, text_width_meters, + maximum_width_pixels, font_height_meters, base::BindRepeating( [](Model* model, bool focused) { model->editing_input = focused; }, base::Unretained(model)), @@ -996,9 +995,8 @@ *model = text_input_info; }, base::Unretained(text_input_model))); - text_input->set_draw_phase(kPhaseForeground); + text_input->set_draw_phase(kPhaseNone); text_input->SetTextInputDelegate(text_input_delegate); - text_input->set_hit_testable(true); text_input->AddBinding(base::MakeUnique<Binding<TextInputInfo>>( base::BindRepeating([](TextInputInfo* info) { return *info; }, base::Unretained(text_input_model)), @@ -1121,7 +1119,7 @@ float width = kOmniboxWidthDMM - 2 * kOmniboxTextMarginDMM; auto omnibox_text_field = - CreateTextInput(1024, kOmniboxTextHeightDMM, width, model_, + CreateTextInput(1024, kOmniboxTextHeightDMM, model_, &model_->omnibox_text_field_info, text_input_delegate_); omnibox_text_field->AddBinding( VR_BIND(TextInputInfo, Model, model_, omnibox_text_field_info, @@ -1131,6 +1129,21 @@ omnibox_text_field->set_x_anchoring(LEFT); omnibox_text_field->set_x_centering(LEFT); omnibox_text_field->SetTranslate(kOmniboxTextMarginDMM, 0, 0); + omnibox_text_field->AddBinding(base::MakeUnique<Binding<bool>>( + base::BindRepeating([](Model* m) { return m->omnibox_input_active; }, + base::Unretained(model_)), + base::BindRepeating( + [](TextInput* e, const bool& v) { + if (v) { + e->RequestFocus(); + } + }, + base::Unretained(omnibox_text_field.get())))); + BindColor(model_, omnibox_text_field.get(), &ColorScheme::omnibox_text, + &TextInput::SetTextColor); + BindColor(model_, omnibox_text_field.get(), &ColorScheme::cursor, + &TextInput::SetCursorColor); + scene_->AddUiElement(kOmniboxContainer, std::move(omnibox_text_field)); auto close_button = Create<Button>(
diff --git a/chrome/browser/vr/ui_scene_creator.h b/chrome/browser/vr/ui_scene_creator.h index e1762c5..de5dd7a1 100644 --- a/chrome/browser/vr/ui_scene_creator.h +++ b/chrome/browser/vr/ui_scene_creator.h
@@ -33,7 +33,6 @@ static std::unique_ptr<TextInput> CreateTextInput( int maximum_width_pixels, float font_height_meters, - float text_width_meters, Model* model, TextInputInfo* text_input_model, TextInputDelegate* text_input_delegate);
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc index 3b5ed0c..7fd84f9 100644 --- a/chrome/browser/vr/ui_unittest.cc +++ b/chrome/browser/vr/ui_unittest.cc
@@ -122,7 +122,9 @@ "kAudioPermissionPromptShadow", "kAudioPermissionPrompt", "kOmniboxContainer", - "kOmniboxTextField", + "kOmniboxTextField:kTypeTextInputHint", + "kOmniboxTextField:kTypeTextInputText", + "kOmniboxTextField:kTypeTextInputCursor", "kOmniboxCloseButton", "kOmniboxCloseButton:kTypeButtonBackground", "kOmniboxCloseButton:kTypeButtonForeground",
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index d98360b..6bad5882 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -32,6 +32,8 @@ #include "components/autofill/core/browser/rationalization_util.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_constants.h" +#include "components/autofill/core/common/autofill_regex_constants.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/autofill_util.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_data_predictions.h" @@ -645,10 +647,11 @@ return false; } - // Rule out http(s)://*/search?... - // e.g. http://www.google.com/search?q=... - // http://search.yahoo.com/search?p=... - if (target_url_.path_piece() == "/search") { + // Rule out search forms. + static const base::string16 kUrlSearchActionPattern = + base::UTF8ToUTF16(kUrlSearchActionRe); + if (MatchesPattern(base::UTF8ToUTF16(target_url_.path_piece()), + kUrlSearchActionPattern)) { return false; }
diff --git a/components/autofill/core/common/autofill_regex_constants.cc b/components/autofill/core/common/autofill_regex_constants.cc index 2a3dbc1..014c096 100644 --- a/components/autofill/core/common/autofill_regex_constants.cc +++ b/components/autofill/core/common/autofill_regex_constants.cc
@@ -297,6 +297,10 @@ const char kPhoneExtensionRe[] = "\\bext|ext\\b|extension" "|ramal"; // pt-BR, pt-PT + +///////////////////////////////////////////////////////////////////////////// +// validation.cc +///////////////////////////////////////////////////////////////////////////// const char kUPIVirtualPaymentAddressRe[] = "^\\w+@(" "allbank|" // Allahabad Bank UPI @@ -348,4 +352,9 @@ "yesbank" // NuPay ")$"; +///////////////////////////////////////////////////////////////////////////// +// form_structure.cc +///////////////////////////////////////////////////////////////////////////// +const char kUrlSearchActionRe[] = "/search(/|((\\w*\\.\\w+)?$))"; + } // namespace autofill
diff --git a/components/autofill/core/common/autofill_regex_constants.h b/components/autofill/core/common/autofill_regex_constants.h index 8be7b2c..96de9e7a 100644 --- a/components/autofill/core/common/autofill_regex_constants.h +++ b/components/autofill/core/common/autofill_regex_constants.h
@@ -62,6 +62,14 @@ // - https://upipayments.co.in/virtual-payment-address-vpa/ extern const char kUPIVirtualPaymentAddressRe[]; +// Match the path values for form actions that look like generic search: +// e.g. /search +// /search/ +// /search/products... +// /products/search/ +// /blah/search_all.jsp +extern const char kUrlSearchActionRe[]; + } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEX_CONSTANTS_H_
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 73388783..1a00d7a 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -127,6 +127,7 @@ sources = [ "../../ui/events/ozone/gamepad/gamepad_event.cc", "buffer_unittest.cc", + "client_controlled_shell_surface_unittest.cc", "data_device_unittest.cc", "data_offer_unittest.cc", "data_source_unittest.cc",
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc new file mode 100644 index 0000000..2218686 --- /dev/null +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -0,0 +1,483 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/client_controlled_shell_surface.h" + +#include "ash/public/cpp/window_properties.h" +#include "ash/public/interfaces/window_pin_type.mojom.h" +#include "ash/shell.h" +#include "ash/shell_port.h" +#include "ash/system/tray/system_tray.h" +#include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "ash/wm/window_positioning_utils.h" +#include "ash/wm/window_state.h" +#include "ash/wm/window_util.h" +#include "components/exo/buffer.h" +#include "components/exo/display.h" +#include "components/exo/pointer.h" +#include "components/exo/sub_surface.h" +#include "components/exo/surface.h" +#include "components/exo/test/exo_test_base.h" +#include "components/exo/test/exo_test_helper.h" +#include "components/exo/wm_helper.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/window.h" +#include "ui/events/test/event_generator.h" +#include "ui/views/widget/widget.h" +#include "ui/wm/core/shadow.h" +#include "ui/wm/core/shadow_controller.h" +#include "ui/wm/core/shadow_types.h" + +namespace exo { +namespace { +using ClientControlledShellSurfaceTest = test::ExoTestBase; + +bool IsWidgetPinned(views::Widget* widget) { + ash::mojom::WindowPinType type = + widget->GetNativeWindow()->GetProperty(ash::kWindowPinTypeKey); + return type == ash::mojom::WindowPinType::PINNED || + type == ash::mojom::WindowPinType::TRUSTED_PINNED; +} + +wm::ShadowElevation GetShadowElevation(aura::Window* window) { + return window->GetProperty(wm::kShadowElevationKey); +} + +} // namespace + +TEST_F(ClientControlledShellSurfaceTest, SetPinned) { + gfx::Size buffer_size(256, 256); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface( + exo_test_helper()->CreateClientControlledShellSurface(surface.get())); + + shell_surface->SetPinned(ash::mojom::WindowPinType::TRUSTED_PINNED); + EXPECT_TRUE(IsWidgetPinned(shell_surface->GetWidget())); + + shell_surface->SetPinned(ash::mojom::WindowPinType::NONE); + EXPECT_FALSE(IsWidgetPinned(shell_surface->GetWidget())); + + shell_surface->SetPinned(ash::mojom::WindowPinType::PINNED); + EXPECT_TRUE(IsWidgetPinned(shell_surface->GetWidget())); + + shell_surface->SetPinned(ash::mojom::WindowPinType::NONE); + EXPECT_FALSE(IsWidgetPinned(shell_surface->GetWidget())); +} + +TEST_F(ClientControlledShellSurfaceTest, SetSystemUiVisibility) { + gfx::Size buffer_size(256, 256); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + surface->Attach(buffer.get()); + surface->Commit(); + + shell_surface->SetSystemUiVisibility(true); + EXPECT_TRUE( + ash::wm::GetWindowState(shell_surface->GetWidget()->GetNativeWindow()) + ->autohide_shelf_when_maximized_or_fullscreen()); + + shell_surface->SetSystemUiVisibility(false); + EXPECT_FALSE( + ash::wm::GetWindowState(shell_surface->GetWidget()->GetNativeWindow()) + ->autohide_shelf_when_maximized_or_fullscreen()); +} + +TEST_F(ClientControlledShellSurfaceTest, SetTopInset) { + gfx::Size buffer_size(64, 64); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + + surface->Attach(buffer.get()); + surface->Commit(); + + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + ASSERT_TRUE(window); + EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); + int top_inset_height = 20; + shell_surface->SetTopInset(top_inset_height); + surface->Commit(); + EXPECT_EQ(top_inset_height, window->GetProperty(aura::client::kTopViewInset)); +} + +TEST_F(ClientControlledShellSurfaceTest, ModalWindowDefaultActive) { + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get(), + /*is_modal=*/true); + + gfx::Size desktop_size(640, 480); + std::unique_ptr<Buffer> desktop_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(desktop_size))); + surface->Attach(desktop_buffer.get()); + surface->SetInputRegion(gfx::Rect(10, 10, 100, 100)); + ASSERT_FALSE(shell_surface->GetWidget()); + shell_surface->SetSystemModal(true); + surface->Commit(); + + EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); +} + +TEST_F(ClientControlledShellSurfaceTest, UpdateModalWindow) { + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = exo_test_helper()->CreateClientControlledShellSurface( + surface.get(), /*is_modal=*/true); + gfx::Size desktop_size(640, 480); + std::unique_ptr<Buffer> desktop_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(desktop_size))); + surface->Attach(desktop_buffer.get()); + surface->SetInputRegion(cc::Region()); + surface->Commit(); + + EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); + + // Creating a surface without input region should not make it modal. + std::unique_ptr<Display> display(new Display); + std::unique_ptr<Surface> child = display->CreateSurface(); + gfx::Size buffer_size(128, 128); + std::unique_ptr<Buffer> child_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + child->Attach(child_buffer.get()); + std::unique_ptr<SubSurface> sub_surface( + display->CreateSubSurface(child.get(), surface.get())); + surface->SetSubSurfacePosition(child.get(), gfx::Point(10, 10)); + child->Commit(); + surface->Commit(); + EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); + + // Making the surface opaque shouldn't make it modal either. + child->SetBlendMode(SkBlendMode::kSrc); + child->Commit(); + surface->Commit(); + EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); + + // Setting input regions won't make it modal either. + surface->SetInputRegion(gfx::Rect(10, 10, 100, 100)); + surface->Commit(); + EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); + + // Only SetSystemModal changes modality. + shell_surface->SetSystemModal(true); + + EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); + + shell_surface->SetSystemModal(false); + + EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); + + // If the non modal system window was active, + shell_surface->GetWidget()->Activate(); + EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); + + shell_surface->SetSystemModal(true); + EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); + + shell_surface->SetSystemModal(false); + EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); +} + +TEST_F(ClientControlledShellSurfaceTest, + ModalWindowSetSystemModalBeforeCommit) { + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = exo_test_helper()->CreateClientControlledShellSurface( + surface.get(), /*is_modal=*/true); + gfx::Size desktop_size(640, 480); + std::unique_ptr<Buffer> desktop_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(desktop_size))); + surface->Attach(desktop_buffer.get()); + surface->SetInputRegion(cc::Region()); + + // Set SetSystemModal before any commit happens. Widget is not created at + // this time. + EXPECT_FALSE(shell_surface->GetWidget()); + shell_surface->SetSystemModal(true); + + surface->Commit(); + + // It is expected that modal window is shown. + EXPECT_TRUE(shell_surface->GetWidget()); + EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + + // Now widget is created and setting modal state should be applied + // immediately. + shell_surface->SetSystemModal(false); + EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); +} + +TEST_F(ClientControlledShellSurfaceTest, SurfaceShadow) { + gfx::Size buffer_size(128, 128); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + surface->Attach(buffer.get()); + surface->Commit(); + + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + + // 1) Initial state, no shadow. + wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); + ASSERT_TRUE(shadow); + EXPECT_FALSE(shadow->layer()->visible()); + + std::unique_ptr<Display> display(new Display); + + // 2) Just creating a sub surface won't create a shadow. + std::unique_ptr<Surface> child = display->CreateSurface(); + std::unique_ptr<Buffer> child_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + child->Attach(child_buffer.get()); + std::unique_ptr<SubSurface> sub_surface( + display->CreateSubSurface(child.get(), surface.get())); + surface->Commit(); + + EXPECT_FALSE(shadow->layer()->visible()); + + // 3) Create a shadow. + shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100)); + surface->Commit(); + EXPECT_TRUE(shadow->layer()->visible()); + + gfx::Rect before = shadow->layer()->bounds(); + + // 4) Shadow bounds is independent of the sub surface. + gfx::Size new_buffer_size(256, 256); + std::unique_ptr<Buffer> new_child_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(new_buffer_size))); + child->Attach(new_child_buffer.get()); + child->Commit(); + surface->Commit(); + + EXPECT_EQ(before, shadow->layer()->bounds()); + + // 4) Updating the widget's window bounds should not change the shadow bounds. + // TODO(oshima): The following scenario only worked with Xdg/ShellSurface, + // which never uses SetShadowBounds. This is broken with correct scenario, and + // will be fixed when the bounds control is delegated to the client. + // + // window->SetBounds(gfx::Rect(10, 10, 100, 100)); + // EXPECT_EQ(before, shadow->layer()->bounds()); + + // 5) This should disable shadow. + shell_surface->SetShadowBounds(gfx::Rect()); + surface->Commit(); + + EXPECT_EQ(wm::ShadowElevation::NONE, GetShadowElevation(window)); + EXPECT_FALSE(shadow->layer()->visible()); + + // 6) This should enable non surface shadow again. + shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100)); + surface->Commit(); + + EXPECT_EQ(wm::ShadowElevation::DEFAULT, GetShadowElevation(window)); + EXPECT_TRUE(shadow->layer()->visible()); +} + +TEST_F(ClientControlledShellSurfaceTest, ShadowWithStateChange) { + gfx::Size buffer_size(64, 64); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + + // Postion the widget at 10,10 so that we get non zero offset. + const gfx::Size content_size(100, 100); + const gfx::Rect original_bounds(gfx::Point(10, 10), content_size); + shell_surface->SetGeometry(original_bounds); + surface->Attach(buffer.get()); + surface->Commit(); + + // Placing a shadow at screen origin will make the shadow's origin (-10, -10). + const gfx::Rect shadow_bounds(content_size); + + // Expected shadow position/bounds in parent coordinates. + const gfx::Point expected_shadow_origin(-10, -10); + const gfx::Rect expected_shadow_bounds(expected_shadow_origin, content_size); + + views::Widget* widget = shell_surface->GetWidget(); + aura::Window* window = widget->GetNativeWindow(); + wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); + + shell_surface->SetShadowBounds(shadow_bounds); + surface->Commit(); + EXPECT_EQ(wm::ShadowElevation::DEFAULT, GetShadowElevation(window)); + + EXPECT_TRUE(shadow->layer()->visible()); + // Origin must be in sync. + EXPECT_EQ(expected_shadow_origin, shadow->content_bounds().origin()); + + const gfx::Rect work_area = + display::Screen::GetScreen()->GetPrimaryDisplay().work_area(); + // Maximizing window hides the shadow. + widget->Maximize(); + ASSERT_TRUE(widget->IsMaximized()); + EXPECT_FALSE(shadow->layer()->visible()); + + shell_surface->SetShadowBounds(work_area); + surface->Commit(); + EXPECT_FALSE(shadow->layer()->visible()); + + // Restoring bounds will re-enable shadow. It's content size is set to work + // area,/ thus not visible until new bounds is committed. + widget->Restore(); + EXPECT_TRUE(shadow->layer()->visible()); + const gfx::Rect shadow_in_maximized(expected_shadow_origin, work_area.size()); + EXPECT_EQ(shadow_in_maximized, shadow->content_bounds()); + + // The bounds is updated. + shell_surface->SetShadowBounds(shadow_bounds); + surface->Commit(); + EXPECT_EQ(expected_shadow_bounds, shadow->content_bounds()); +} + +TEST_F(ClientControlledShellSurfaceTest, ShadowWithTransform) { + gfx::Size buffer_size(64, 64); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + + // Postion the widget at 10,10 so that we get non zero offset. + const gfx::Size content_size(100, 100); + const gfx::Rect original_bounds(gfx::Point(10, 10), content_size); + shell_surface->SetGeometry(original_bounds); + surface->Attach(buffer.get()); + surface->Commit(); + + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); + + // Placing a shadow at screen origin will make the shadow's origin (-10, -10). + const gfx::Rect shadow_bounds(content_size); + + // Shadow bounds relative to its parent should not be affected by a transform. + gfx::Transform transform; + transform.Translate(50, 50); + window->SetTransform(transform); + shell_surface->SetShadowBounds(shadow_bounds); + surface->Commit(); + EXPECT_TRUE(shadow->layer()->visible()); + EXPECT_EQ(gfx::Rect(-10, -10, 100, 100), shadow->content_bounds()); +} + +TEST_F(ClientControlledShellSurfaceTest, ShadowStartMaximized) { + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + shell_surface->Maximize(); + views::Widget* widget = shell_surface->GetWidget(); + aura::Window* window = widget->GetNativeWindow(); + + // There is no shadow when started in maximized state. + EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window)); + + // Sending a shadow bounds in maximized state won't create a shaodw. + shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100)); + surface->Commit(); + EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window)); + + // Restore the window and make sure the shadow is created, visible and + // has the latest bounds. + widget->Restore(); + wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); + ASSERT_TRUE(shadow); + EXPECT_TRUE(shadow->layer()->visible()); + EXPECT_EQ(gfx::Rect(10, 10, 100, 100), shadow->content_bounds()); +} + +TEST_F(ClientControlledShellSurfaceTest, CompositorLockInRotation) { + UpdateDisplay("800x600"); + const gfx::Size buffer_size(800, 600); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + ash::Shell* shell = ash::Shell::Get(); + shell->tablet_mode_controller()->EnableTabletModeWindowManager(true); + + // Start in maximized. + shell_surface->Maximize(); + surface->Attach(buffer.get()); + surface->Commit(); + + gfx::Rect maximum_bounds = + display::Screen::GetScreen()->GetPrimaryDisplay().bounds(); + shell_surface->SetGeometry(maximum_bounds); + shell_surface->SetOrientation(Orientation::LANDSCAPE); + surface->Commit(); + + ui::Compositor* compositor = + shell_surface->GetWidget()->GetNativeWindow()->layer()->GetCompositor(); + + EXPECT_FALSE(compositor->IsLocked()); + + UpdateDisplay("800x600/r"); + + EXPECT_TRUE(compositor->IsLocked()); + + shell_surface->SetOrientation(Orientation::PORTRAIT); + surface->Commit(); + + EXPECT_FALSE(compositor->IsLocked()); +} + +// If system tray is shown by click. It should be activated if user presses tab +// key while shell surface is active. +TEST_F(ClientControlledShellSurfaceTest, KeyboardNavigationWithSystemTray) { + const gfx::Size buffer_size(800, 600); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface()); + std::unique_ptr<ShellSurface> shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + + surface->Attach(buffer.get()); + surface->Commit(); + + EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); + + // Show system tray by perfoming a gesture tap at tray. + ash::SystemTray* system_tray = GetPrimarySystemTray(); + ui::GestureEvent tap(0, 0, 0, base::TimeTicks(), + ui::GestureEventDetails(ui::ET_GESTURE_TAP)); + system_tray->PerformAction(tap); + ASSERT_TRUE(system_tray->GetWidget()); + + // Confirm that system tray is not active at this time. + EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); + EXPECT_FALSE( + system_tray->GetSystemBubble()->bubble_view()->GetWidget()->IsActive()); + + // Send tab key event. + ui::test::EventGenerator& event_generator = GetEventGenerator(); + event_generator.PressKey(ui::VKEY_TAB, ui::EF_NONE); + event_generator.ReleaseKey(ui::VKEY_TAB, ui::EF_NONE); + + // Confirm that system tray is activated. + EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); + EXPECT_TRUE( + system_tray->GetSystemBubble()->bubble_view()->GetWidget()->IsActive()); +} + +} // namespace exo
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc index 79c51c3..e32aca6a 100644 --- a/components/exo/shell_surface_unittest.cc +++ b/components/exo/shell_surface_unittest.cc
@@ -6,13 +6,9 @@ #include "ash/accessibility/accessibility_delegate.h" #include "ash/public/cpp/shell_window_ids.h" -#include "ash/public/cpp/window_properties.h" -#include "ash/public/interfaces/window_pin_type.mojom.h" #include "ash/shell.h" #include "ash/shell_port.h" #include "ash/shell_test_api.h" -#include "ash/system/tray/system_tray.h" -#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_state.h" #include "ash/wm/wm_event.h" #include "ash/wm/workspace/workspace_window_resizer.h" @@ -29,7 +25,6 @@ #include "components/exo/test/exo_test_helper.h" #include "components/exo/wm_helper.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/base/hit_test.h" #include "ui/compositor/compositor.h" @@ -37,7 +32,6 @@ #include "ui/display/display.h" #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" -#include "ui/events/test/event_generator.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/shadow.h" #include "ui/wm/core/shadow_controller.h" @@ -59,17 +53,6 @@ return serial; } -wm::ShadowElevation GetShadowElevation(aura::Window* window) { - return window->GetProperty(wm::kShadowElevationKey); -} - -bool IsWidgetPinned(views::Widget* widget) { - ash::mojom::WindowPinType type = - widget->GetNativeWindow()->GetProperty(ash::kWindowPinTypeKey); - return type == ash::mojom::WindowPinType::PINNED || - type == ash::mojom::WindowPinType::TRUSTED_PINNED; -} - class ShellSurfaceBoundsModeTest : public ShellSurfaceTest, public testing::WithParamInterface<ShellSurface::BoundsMode> { @@ -273,48 +256,6 @@ shell_surface->GetWidget()->GetWindowBoundsInScreen().ToString()); } -TEST_F(ShellSurfaceTest, SetPinned) { - gfx::Size buffer_size(256, 256); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface( - exo_test_helper()->CreateClientControlledShellSurface(surface.get())); - - shell_surface->SetPinned(ash::mojom::WindowPinType::TRUSTED_PINNED); - EXPECT_TRUE(IsWidgetPinned(shell_surface->GetWidget())); - - shell_surface->SetPinned(ash::mojom::WindowPinType::NONE); - EXPECT_FALSE(IsWidgetPinned(shell_surface->GetWidget())); - - shell_surface->SetPinned(ash::mojom::WindowPinType::PINNED); - EXPECT_TRUE(IsWidgetPinned(shell_surface->GetWidget())); - - shell_surface->SetPinned(ash::mojom::WindowPinType::NONE); - EXPECT_FALSE(IsWidgetPinned(shell_surface->GetWidget())); -} - -TEST_F(ShellSurfaceTest, SetSystemUiVisibility) { - gfx::Size buffer_size(256, 256); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - surface->Attach(buffer.get()); - surface->Commit(); - - shell_surface->SetSystemUiVisibility(true); - EXPECT_TRUE( - ash::wm::GetWindowState(shell_surface->GetWidget()->GetNativeWindow()) - ->autohide_shelf_when_maximized_or_fullscreen()); - - shell_surface->SetSystemUiVisibility(false); - EXPECT_FALSE( - ash::wm::GetWindowState(shell_surface->GetWidget()->GetNativeWindow()) - ->autohide_shelf_when_maximized_or_fullscreen()); -} - TEST_F(ShellSurfaceTest, SetTitle) { std::unique_ptr<Surface> surface(new Surface); std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); @@ -487,26 +428,6 @@ shell_surface->host_window()->layer()->GetTargetTransform().ToString()); } -TEST_F(ShellSurfaceTest, SetTopInset) { - gfx::Size buffer_size(64, 64); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - - surface->Attach(buffer.get()); - surface->Commit(); - - aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); - ASSERT_TRUE(window); - EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset)); - int top_inset_height = 20; - shell_surface->SetTopInset(top_inset_height); - surface->Commit(); - EXPECT_EQ(top_inset_height, window->GetProperty(aura::client::kTopViewInset)); -} - void Close(int* close_call_count) { (*close_call_count)++; } @@ -615,372 +536,6 @@ EXPECT_TRUE(is_resizing); } -TEST_F(ShellSurfaceTest, ModalWindowDefaultActive) { - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get(), - /*is_modal=*/true); - - gfx::Size desktop_size(640, 480); - std::unique_ptr<Buffer> desktop_buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(desktop_size))); - surface->Attach(desktop_buffer.get()); - surface->SetInputRegion(gfx::Rect(10, 10, 100, 100)); - ASSERT_FALSE(shell_surface->GetWidget()); - shell_surface->SetSystemModal(true); - surface->Commit(); - - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); -} - -TEST_F(ShellSurfaceTest, UpdateModalWindow) { - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = exo_test_helper()->CreateClientControlledShellSurface( - surface.get(), /*is_modal=*/true); - gfx::Size desktop_size(640, 480); - std::unique_ptr<Buffer> desktop_buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(desktop_size))); - surface->Attach(desktop_buffer.get()); - surface->SetInputRegion(cc::Region()); - surface->Commit(); - - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); - - // Creating a surface without input region should not make it modal. - std::unique_ptr<Display> display(new Display); - std::unique_ptr<Surface> child = display->CreateSurface(); - gfx::Size buffer_size(128, 128); - std::unique_ptr<Buffer> child_buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - child->Attach(child_buffer.get()); - std::unique_ptr<SubSurface> sub_surface( - display->CreateSubSurface(child.get(), surface.get())); - surface->SetSubSurfacePosition(child.get(), gfx::Point(10, 10)); - child->Commit(); - surface->Commit(); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); - - // Making the surface opaque shouldn't make it modal either. - child->SetBlendMode(SkBlendMode::kSrc); - child->Commit(); - surface->Commit(); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); - - // Setting input regions won't make it modal either. - surface->SetInputRegion(gfx::Rect(10, 10, 100, 100)); - surface->Commit(); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); - - // Only SetSystemModal changes modality. - shell_surface->SetSystemModal(true); - - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); - - shell_surface->SetSystemModal(false); - - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); - - // If the non modal system window was active, - shell_surface->GetWidget()->Activate(); - EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); - - shell_surface->SetSystemModal(true); - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); - - shell_surface->SetSystemModal(false); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); -} - -TEST_F(ShellSurfaceTest, ModalWindowSetSystemModalBeforeCommit) { - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = exo_test_helper()->CreateClientControlledShellSurface( - surface.get(), /*is_modal=*/true); - gfx::Size desktop_size(640, 480); - std::unique_ptr<Buffer> desktop_buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(desktop_size))); - surface->Attach(desktop_buffer.get()); - surface->SetInputRegion(cc::Region()); - - // Set SetSystemModal before any commit happens. Widget is not created at - // this time. - EXPECT_FALSE(shell_surface->GetWidget()); - shell_surface->SetSystemModal(true); - - surface->Commit(); - - // It is expected that modal window is shown. - EXPECT_TRUE(shell_surface->GetWidget()); - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); - - // Now widget is created and setting modal state should be applied - // immediately. - shell_surface->SetSystemModal(false); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); -} - -TEST_F(ShellSurfaceTest, SurfaceShadow) { - gfx::Size buffer_size(128, 128); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - surface->Attach(buffer.get()); - surface->Commit(); - - aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); - - // 1) Initial state, no shadow. - wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); - ASSERT_TRUE(shadow); - EXPECT_FALSE(shadow->layer()->visible()); - - std::unique_ptr<Display> display(new Display); - - // 2) Just creating a sub surface won't create a shadow. - std::unique_ptr<Surface> child = display->CreateSurface(); - std::unique_ptr<Buffer> child_buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - child->Attach(child_buffer.get()); - std::unique_ptr<SubSurface> sub_surface( - display->CreateSubSurface(child.get(), surface.get())); - surface->Commit(); - - EXPECT_FALSE(shadow->layer()->visible()); - - // 3) Create a shadow. - shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100)); - surface->Commit(); - EXPECT_TRUE(shadow->layer()->visible()); - - gfx::Rect before = shadow->layer()->bounds(); - - // 4) Shadow bounds is independent of the sub surface. - gfx::Size new_buffer_size(256, 256); - std::unique_ptr<Buffer> new_child_buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(new_buffer_size))); - child->Attach(new_child_buffer.get()); - child->Commit(); - surface->Commit(); - - EXPECT_EQ(before, shadow->layer()->bounds()); - - // 4) Updating the widget's window bounds should not change the shadow bounds. - // TODO(oshima): The following scenario only worked with Xdg/ShellSurface, - // which never uses SetShadowBounds. This is broken with correct scenario, and - // will be fixed when the bounds control is delegated to the client. - // - // window->SetBounds(gfx::Rect(10, 10, 100, 100)); - // EXPECT_EQ(before, shadow->layer()->bounds()); - - // 5) This should disable shadow. - shell_surface->SetShadowBounds(gfx::Rect()); - surface->Commit(); - - EXPECT_EQ(wm::ShadowElevation::NONE, GetShadowElevation(window)); - EXPECT_FALSE(shadow->layer()->visible()); - - // 6) This should enable non surface shadow again. - shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100)); - surface->Commit(); - - EXPECT_EQ(wm::ShadowElevation::DEFAULT, GetShadowElevation(window)); - EXPECT_TRUE(shadow->layer()->visible()); -} - -TEST_F(ShellSurfaceTest, NonSurfaceShadow) { - gfx::Size buffer_size(128, 128); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - std::unique_ptr<ShellSurface> shell_surface(new ShellSurface( - surface.get(), ShellSurface::BoundsMode::SHELL, gfx::Point(), true, false, - ash::kShellWindowId_DefaultContainer)); - surface->Attach(buffer.get()); - surface->Commit(); - - aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); - - // 1) Initial state, no shadow. - wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); - ASSERT_TRUE(shadow); - EXPECT_FALSE(shadow->layer()->visible()); - - std::unique_ptr<Display> display(new Display); - - // 2) Just creating a sub surface won't create a shadow. - std::unique_ptr<Surface> child = display->CreateSurface(); - std::unique_ptr<Buffer> child_buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - child->Attach(child_buffer.get()); - std::unique_ptr<SubSurface> sub_surface( - display->CreateSubSurface(child.get(), surface.get())); - surface->Commit(); - - EXPECT_FALSE(shadow->layer()->visible()); - - // 3) Enable a shadow. - shell_surface->OnSetFrame(SurfaceFrameType::SHADOW); - surface->Commit(); - EXPECT_TRUE(shadow->layer()->visible()); - - gfx::Rect before = shadow->layer()->bounds(); - - // 4) Shadow bounds is independent of the sub surface. - gfx::Size new_buffer_size(256, 256); - std::unique_ptr<Buffer> new_child_buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(new_buffer_size))); - child->Attach(new_child_buffer.get()); - child->Commit(); - surface->Commit(); - - EXPECT_EQ(before, shadow->layer()->bounds()); - - // 4) Updating the widget's window bounds should change the non surface shadow - // bounds. - const gfx::Rect new_bounds(50, 50, 100, 100); - window->SetBounds(new_bounds); - EXPECT_NE(before, shadow->layer()->bounds()); - EXPECT_NE(new_bounds, shadow->layer()->bounds()); - - // 5) This should disable shadow. - surface->SetFrame(SurfaceFrameType::NONE); - surface->Commit(); - - EXPECT_EQ(wm::ShadowElevation::NONE, GetShadowElevation(window)); - EXPECT_FALSE(shadow->layer()->visible()); - - // 6) This should enable non surface shadow. - surface->SetFrame(SurfaceFrameType::SHADOW); - surface->Commit(); - - EXPECT_EQ(wm::ShadowElevation::DEFAULT, GetShadowElevation(window)); - EXPECT_TRUE(shadow->layer()->visible()); -} - -TEST_F(ShellSurfaceTest, ShadowWithStateChange) { - gfx::Size buffer_size(64, 64); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - - // Postion the widget at 10,10 so that we get non zero offset. - const gfx::Size content_size(100, 100); - const gfx::Rect original_bounds(gfx::Point(10, 10), content_size); - shell_surface->SetGeometry(original_bounds); - surface->Attach(buffer.get()); - surface->Commit(); - - // Placing a shadow at screen origin will make the shadow's origin (-10, -10). - const gfx::Rect shadow_bounds(content_size); - - // Expected shadow position/bounds in parent coordinates. - const gfx::Point expected_shadow_origin(-10, -10); - const gfx::Rect expected_shadow_bounds(expected_shadow_origin, content_size); - - views::Widget* widget = shell_surface->GetWidget(); - aura::Window* window = widget->GetNativeWindow(); - wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); - - shell_surface->SetShadowBounds(shadow_bounds); - surface->Commit(); - EXPECT_EQ(wm::ShadowElevation::DEFAULT, GetShadowElevation(window)); - - EXPECT_TRUE(shadow->layer()->visible()); - // Origin must be in sync. - EXPECT_EQ(expected_shadow_origin, shadow->content_bounds().origin()); - - const gfx::Rect work_area = - display::Screen::GetScreen()->GetPrimaryDisplay().work_area(); - // Maximizing window hides the shadow. - widget->Maximize(); - ASSERT_TRUE(widget->IsMaximized()); - EXPECT_FALSE(shadow->layer()->visible()); - - shell_surface->SetShadowBounds(work_area); - surface->Commit(); - EXPECT_FALSE(shadow->layer()->visible()); - - // Restoring bounds will re-enable shadow. It's content size is set to work - // area,/ thus not visible until new bounds is committed. - widget->Restore(); - EXPECT_TRUE(shadow->layer()->visible()); - const gfx::Rect shadow_in_maximized(expected_shadow_origin, work_area.size()); - EXPECT_EQ(shadow_in_maximized, shadow->content_bounds()); - - // The bounds is updated. - shell_surface->SetShadowBounds(shadow_bounds); - surface->Commit(); - EXPECT_EQ(expected_shadow_bounds, shadow->content_bounds()); -} - -TEST_F(ShellSurfaceTest, ShadowWithTransform) { - gfx::Size buffer_size(64, 64); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - - // Postion the widget at 10,10 so that we get non zero offset. - const gfx::Size content_size(100, 100); - const gfx::Rect original_bounds(gfx::Point(10, 10), content_size); - shell_surface->SetGeometry(original_bounds); - surface->Attach(buffer.get()); - surface->Commit(); - - aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); - wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); - - // Placing a shadow at screen origin will make the shadow's origin (-10, -10). - const gfx::Rect shadow_bounds(content_size); - - // Shadow bounds relative to its parent should not be affected by a transform. - gfx::Transform transform; - transform.Translate(50, 50); - window->SetTransform(transform); - shell_surface->SetShadowBounds(shadow_bounds); - surface->Commit(); - EXPECT_TRUE(shadow->layer()->visible()); - EXPECT_EQ(gfx::Rect(-10, -10, 100, 100), shadow->content_bounds()); -} - -TEST_F(ShellSurfaceTest, ShadowStartMaximized) { - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - shell_surface->Maximize(); - views::Widget* widget = shell_surface->GetWidget(); - aura::Window* window = widget->GetNativeWindow(); - - // There is no shadow when started in maximized state. - EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window)); - - // Sending a shadow bounds in maximized state won't create a shaodw. - shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100)); - surface->Commit(); - EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window)); - - // Restore the window and make sure the shadow is created, visible and - // has the latest bounds. - widget->Restore(); - wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window); - ASSERT_TRUE(shadow); - EXPECT_TRUE(shadow->layer()->visible()); - EXPECT_EQ(gfx::Rect(10, 10, 100, 100), shadow->content_bounds()); -} - TEST_P(ShellSurfaceBoundsModeTest, ToggleFullscreen) { gfx::Size buffer_size(256, 256); std::unique_ptr<Buffer> buffer( @@ -1028,80 +583,5 @@ } } -TEST_F(ShellSurfaceTest, CompositorLockInRotation) { - UpdateDisplay("800x600"); - const gfx::Size buffer_size(800, 600); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface); - auto shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - ash::Shell* shell = ash::Shell::Get(); - shell->tablet_mode_controller()->EnableTabletModeWindowManager(true); - - // Start in maximized. - shell_surface->Maximize(); - surface->Attach(buffer.get()); - surface->Commit(); - - gfx::Rect maximum_bounds = - display::Screen::GetScreen()->GetPrimaryDisplay().bounds(); - shell_surface->SetGeometry(maximum_bounds); - shell_surface->SetOrientation(Orientation::LANDSCAPE); - surface->Commit(); - - ui::Compositor* compositor = - shell_surface->GetWidget()->GetNativeWindow()->layer()->GetCompositor(); - - EXPECT_FALSE(compositor->IsLocked()); - - UpdateDisplay("800x600/r"); - - EXPECT_TRUE(compositor->IsLocked()); - - shell_surface->SetOrientation(Orientation::PORTRAIT); - surface->Commit(); - - EXPECT_FALSE(compositor->IsLocked()); -} - -// If system tray is shown by click. It should be activated if user presses tab -// key while shell surface is active. -TEST_F(ShellSurfaceTest, KeyboardNavigationWithSystemTray) { - const gfx::Size buffer_size(800, 600); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - std::unique_ptr<Surface> surface(new Surface()); - std::unique_ptr<ShellSurface> shell_surface = - exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - - surface->Attach(buffer.get()); - surface->Commit(); - - EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); - - // Show system tray by perfoming a gesture tap at tray. - ash::SystemTray* system_tray = GetPrimarySystemTray(); - ui::GestureEvent tap(0, 0, 0, base::TimeTicks(), - ui::GestureEventDetails(ui::ET_GESTURE_TAP)); - system_tray->PerformAction(tap); - ASSERT_TRUE(system_tray->GetWidget()); - - // Confirm that system tray is not active at this time. - EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); - EXPECT_FALSE( - system_tray->GetSystemBubble()->bubble_view()->GetWidget()->IsActive()); - - // Send tab key event. - ui::test::EventGenerator& event_generator = GetEventGenerator(); - event_generator.PressKey(ui::VKEY_TAB, ui::EF_NONE); - event_generator.ReleaseKey(ui::VKEY_TAB, ui::EF_NONE); - - // Confirm that system tray is activated. - EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); - EXPECT_TRUE( - system_tray->GetSystemBubble()->bubble_view()->GetWidget()->IsActive()); -} - } // namespace } // namespace exo
diff --git a/components/network_session_configurator/common/BUILD.gn b/components/network_session_configurator/common/BUILD.gn index ba484f0..ca1a132 100644 --- a/components/network_session_configurator/common/BUILD.gn +++ b/components/network_session_configurator/common/BUILD.gn
@@ -2,10 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -static_library("common") { +component("common") { + output_name = "network_session_configurator" sources = [ "network_features.cc", "network_features.h", + "network_session_configurator_export.h", "network_switch_list.h", "network_switches.cc", "network_switches.h", @@ -14,4 +16,6 @@ public_deps = [ "//base", ] + + defines = [ "NETWORK_SESSION_CONFIGURATOR_IMPLEMENTATION" ] }
diff --git a/components/network_session_configurator/common/network_features.h b/components/network_session_configurator/common/network_features.h index 1d6981d7..dbcc98c 100644 --- a/components/network_session_configurator/common/network_features.h +++ b/components/network_session_configurator/common/network_features.h
@@ -6,12 +6,13 @@ #define COMPONENTS_NETWORK_SESSION_CONFIGURATOR_COMMON_NETWORK_FEATURES_H_ #include "base/feature_list.h" +#include "network_session_configurator_export.h" namespace features { // Enables token binding // (https://www.ietf.org/id/draft-ietf-tokbind-protocol-04.txt). -extern const base::Feature kTokenBinding; +NETWORK_SESSION_CONFIGURATOR_EXPORT extern const base::Feature kTokenBinding; } // namespace features
diff --git a/components/network_session_configurator/common/network_session_configurator_export.h b/components/network_session_configurator/common/network_session_configurator_export.h new file mode 100644 index 0000000..d4a224d --- /dev/null +++ b/components/network_session_configurator/common/network_session_configurator_export.h
@@ -0,0 +1,35 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_NETWORK_SESSION_CONFIGURATOR_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_ +#define COMPONENTS_NETWORK_SESSION_CONFIGURATOR_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_ + +#if defined(COMPONENT_BUILD) + +#if defined(WIN32) + +#if defined(NETWORK_SESSION_CONFIGURATOR_IMPLEMENTATION) +#define NETWORK_SESSION_CONFIGURATOR_EXPORT __declspec(dllexport) +#else +#define NETWORK_SESSION_CONFIGURATOR_EXPORT __declspec(dllimport) +#endif // defined(NETWORK_SESSION_CONFIGURATOR_IMPLEMENTATION) + +#else // defined(WIN32) + +#if defined(NETWORK_SESSION_CONFIGURATOR_IMPLEMENTATION) +#define NETWORK_SESSION_CONFIGURATOR_EXPORT \ + __attribute__((visibility("default"))) +#else +#define NETWORK_SESSION_CONFIGURATOR_EXPORT +#endif // defined(NETWORK_SESSION_CONFIGURATOR_IMPLEMENTATION) + +#endif // defined(WIN32) + +#else // defined(COMPONENT_BUILD) + +#define NETWORK_SESSION_CONFIGURATOR_EXPORT + +#endif // defined(COMPONENT_BUILD) + +#endif // COMPONENTS_NETWORK_SESSION_CONFIGURATOR_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_
diff --git a/components/network_session_configurator/common/network_switches.h b/components/network_session_configurator/common/network_switches.h index 7a511f5..ee5ea75 100644 --- a/components/network_session_configurator/common/network_switches.h +++ b/components/network_session_configurator/common/network_switches.h
@@ -5,13 +5,16 @@ #ifndef COMPONENTS_NETWORK_SESSION_CONFIGURATOR_COMMON_NETWORK_SWITCHES_H_ #define COMPONENTS_NETWORK_SESSION_CONFIGURATOR_COMMON_NETWORK_SWITCHES_H_ +#include "network_session_configurator_export.h" + namespace base { class CommandLine; } namespace switches { -#define NETWORK_SWITCH(name, value) extern const char name[]; +#define NETWORK_SWITCH(name, value) \ + NETWORK_SESSION_CONFIGURATOR_EXPORT extern const char name[]; #include "components/network_session_configurator/common/network_switch_list.h" #undef NETWORK_SWITCH @@ -21,8 +24,9 @@ // Copies all command line switches the configurator handles from the |src| // CommandLine to the |dest| one. -void CopyNetworkSwitches(const base::CommandLine& src_command_line, - base::CommandLine* dest_command_line); +NETWORK_SESSION_CONFIGURATOR_EXPORT void CopyNetworkSwitches( + const base::CommandLine& src_command_line, + base::CommandLine* dest_command_line); } // namespace network_session_configurator
diff --git a/components/test/data/autofill/heuristics/output/018_checkout_ae.com.out b/components/test/data/autofill/heuristics/output/018_checkout_ae.com.out index 8966f63..b1c804b7 100644 --- a/components/test/data/autofill/heuristics/output/018_checkout_ae.com.out +++ b/components/test/data/autofill/heuristics/output/018_checkout_ae.com.out
@@ -3,10 +3,6 @@ UNKNOWN_TYPE | zip | Find a store | Enter ZIP/Postal | zip_1-default UNKNOWN_TYPE | username | Access your wish list | Email | username_1-default UNKNOWN_TYPE | password | Password | Password | username_1-default -NAME_FIRST | firstName | Search wish lists by name | First Name | firstName_1-default -NAME_LAST | lastName | Last Name | Last Name | firstName_1-default -EMAIL_ADDRESS | email | Or search wish lists by email | Email | firstName_1-default -UNKNOWN_TYPE | /aeo/commerce/search/formhandlers/AEOQueryFormHandler.searchRequest.question | Keyword or Style # | Keyword or Style # | /aeo/commerce/search/formhandlers/AEOQueryFormHandler.searchRequest.question_1-default ADDRESS_HOME_COUNTRY | countryType | Country Type | usa | countryType_1-default ADDRESS_HOME_COUNTRY | country | Country, APO/FPO | US | countryType_1-default NAME_FIRST | firstName | First Name | | countryType_1-default
diff --git a/components/test/data/autofill/heuristics/output/035_checkout_petco.com.out b/components/test/data/autofill/heuristics/output/035_checkout_petco.com.out index c0cc80b..fa05429 100644 --- a/components/test/data/autofill/heuristics/output/035_checkout_petco.com.out +++ b/components/test/data/autofill/heuristics/output/035_checkout_petco.com.out
@@ -1,5 +1,3 @@ -UNKNOWN_TYPE | zip | Your ZIP Code | Your ZIP Code | zip_1-default -UNKNOWN_TYPE | Ntt | Search PETCO.com | Search PETCO.com | Ntt_1-default UNKNOWN_TYPE | txtEmail | Your Email Address | Your Email Address | txtEmail_1-default NAME_FIRST | ctl00$ctl00$cphBody$cphBody$txtSA_FirstName | First Name * | | ctl00$ctl00$cphBody$cphBody$txtSA_FirstName_1-default NAME_LAST | ctl00$ctl00$cphBody$cphBody$txtSA_LastName | Last Name * | | ctl00$ctl00$cphBody$cphBody$txtSA_FirstName_1-default
diff --git a/components/test/data/autofill/heuristics/output/036_checkout_petsmart.com.out b/components/test/data/autofill/heuristics/output/036_checkout_petsmart.com.out index e3f9e226..1453706 100644 --- a/components/test/data/autofill/heuristics/output/036_checkout_petsmart.com.out +++ b/components/test/data/autofill/heuristics/output/036_checkout_petsmart.com.out
@@ -1,4 +1,3 @@ -UNKNOWN_TYPE | kw | search petsmart.com | search petsmart.com | kw_1-default ADDRESS_HOME_COUNTRY | billCountry | • Country: | US | billCountry_1-default NAME_FIRST | billFname | • First Name: | | billCountry_1-default NAME_LAST | billLname | • Last Name: | | billCountry_1-default
diff --git a/components/test/data/autofill/heuristics/output/040_checkout_urbanoutfitters.com.out b/components/test/data/autofill/heuristics/output/040_checkout_urbanoutfitters.com.out index 3baba2f..7a14a4d 100644 --- a/components/test/data/autofill/heuristics/output/040_checkout_urbanoutfitters.com.out +++ b/components/test/data/autofill/heuristics/output/040_checkout_urbanoutfitters.com.out
@@ -1,4 +1,3 @@ -UNKNOWN_TYPE | searchPhrase | | | searchPhrase_1-default UNKNOWN_TYPE | shipto | Select a Saved Shipping Address | | shipto_1-default NAME_FIRST | shippingFirstName | First Name | First Name | shipto_1-default NAME_LAST | shippingLastName | Last Name | Last Name | shipto_1-default
diff --git a/components/test/data/autofill/heuristics/output/042_checkout_williams-sonoma.com.out b/components/test/data/autofill/heuristics/output/042_checkout_williams-sonoma.com.out index c4b9d08..617ef775 100644 --- a/components/test/data/autofill/heuristics/output/042_checkout_williams-sonoma.com.out +++ b/components/test/data/autofill/heuristics/output/042_checkout_williams-sonoma.com.out
@@ -1,4 +1,3 @@ -UNKNOWN_TYPE | words | Search by keyword, recipe or item # | Enter keyword, recipe or item # | words_1-default NAME_FULL | shipTos[0].address.fullName | Full Name* | | shipTos[0].address.fullName_1-default ADDRESS_HOME_LINE1 | shipTos[0].address.addrLine1 | Address* | | shipTos[0].address.fullName_1-default ADDRESS_HOME_LINE2 | shipTos[0].address.addrLine2 | Address Line 2 | | shipTos[0].address.fullName_1-default
diff --git a/components/test/data/autofill/heuristics/output/059_register_macys.com.out b/components/test/data/autofill/heuristics/output/059_register_macys.com.out index 1608a64..142ad425 100644 --- a/components/test/data/autofill/heuristics/output/059_register_macys.com.out +++ b/components/test/data/autofill/heuristics/output/059_register_macys.com.out
@@ -1,4 +1,3 @@ -UNKNOWN_TYPE | Keyword | | | Keyword_1-default NAME_FIRST | FirstName | First Name | | FirstName_1-default NAME_LAST | LastName | Last Name | | FirstName_1-default ADDRESS_HOME_LINE1 | Address1 | Address | | FirstName_1-default
diff --git a/components/test/data/autofill/heuristics/output/060_register_mcphee.com.out b/components/test/data/autofill/heuristics/output/060_register_mcphee.com.out index aa6ed3df..725c53f8 100644 --- a/components/test/data/autofill/heuristics/output/060_register_mcphee.com.out +++ b/components/test/data/autofill/heuristics/output/060_register_mcphee.com.out
@@ -1,4 +1,3 @@ -UNKNOWN_TYPE | search_query | Search | | search_query_1-default EMAIL_ADDRESS | FormField[1][1] | * Email Address: | | FormField[1][1]_1-default UNKNOWN_TYPE | FormField[1][2] | * Password: | | FormField[1][1]_1-default UNKNOWN_TYPE | FormField[1][3] | * Confirm Password: | | FormField[1][1]_1-default
diff --git a/components/test/data/autofill/heuristics/output/061_register_myspace.com.out b/components/test/data/autofill/heuristics/output/061_register_myspace.com.out index ec0fe34..6c22a7a 100644 --- a/components/test/data/autofill/heuristics/output/061_register_myspace.com.out +++ b/components/test/data/autofill/heuristics/output/061_register_myspace.com.out
@@ -1,4 +1,3 @@ -UNKNOWN_TYPE | q | Search People | | q_1-default UNKNOWN_TYPE | accountType | Personal | 2 | accountType_1-default UNKNOWN_TYPE | accountType | Musician | 7 | accountType_1-default UNKNOWN_TYPE | accountType | Comedian | 15 | accountType_1-default
diff --git a/components/test/data/autofill/heuristics/output/063_register_officedepot.com.out b/components/test/data/autofill/heuristics/output/063_register_officedepot.com.out index 62fb696..a5c5a975 100644 --- a/components/test/data/autofill/heuristics/output/063_register_officedepot.com.out +++ b/components/test/data/autofill/heuristics/output/063_register_officedepot.com.out
@@ -1,5 +1,4 @@ UNKNOWN_TYPE | zip | | | zip_1-default -UNKNOWN_TYPE | Ntt | Search | | Ntt_1-default NAME_FIRST | addrsForm[0].firstName | *First Name: | | addrsForm[0].firstName_1-default NAME_MIDDLE_INITIAL | addrsForm[0].middleInitial | Middle Initial: | | addrsForm[0].firstName_1-default NAME_LAST | addrsForm[0].lastName | *Last Name: | | addrsForm[0].firstName_1-default
diff --git a/components/test/data/autofill/heuristics/output/064_register_officemax.com.out b/components/test/data/autofill/heuristics/output/064_register_officemax.com.out index 2264b5b..0630083 100644 --- a/components/test/data/autofill/heuristics/output/064_register_officemax.com.out +++ b/components/test/data/autofill/heuristics/output/064_register_officemax.com.out
@@ -6,4 +6,3 @@ ADDRESS_HOME_ZIP | /atg/userprofiling/ProfileFormHandler.value.zip | * Zip: | | /atg/userprofiling/ProfileFormHandler.value.maxPerks_1-default UNKNOWN_TYPE | /atg/userprofiling/ProfileFormHandler.value.password | * Password: | | /atg/userprofiling/ProfileFormHandler.value.maxPerks_1-default UNKNOWN_TYPE | /atg/userprofiling/ProfileFormHandler.value.confirmPassword | * Confirm Password: | | /atg/userprofiling/ProfileFormHandler.value.maxPerks_1-default -UNKNOWN_TYPE | freeText | Search by Keyword or Item # | Search by Keyword or Item # | freeText_1-default
diff --git a/components/test/data/autofill/heuristics/output/065_register_pyramidcollection.com.out b/components/test/data/autofill/heuristics/output/065_register_pyramidcollection.com.out index 15ecbc5..262a4f0 100644 --- a/components/test/data/autofill/heuristics/output/065_register_pyramidcollection.com.out +++ b/components/test/data/autofill/heuristics/output/065_register_pyramidcollection.com.out
@@ -1,4 +1,3 @@ -UNKNOWN_TYPE | q | search | enter keyword(s) or item number | q_1-default EMAIL_ADDRESS | E1 | Email Address * | | E1_1-default NAME_FIRST | F1 | First Name * | | E1_1-default NAME_LAST | L1 | Last Name * | | E1_1-default
diff --git a/components/test/data/autofill/heuristics/output/071_register_sourceforge.net.out b/components/test/data/autofill/heuristics/output/071_register_sourceforge.net.out index 285f7b1..4afcfce 100644 --- a/components/test/data/autofill/heuristics/output/071_register_sourceforge.net.out +++ b/components/test/data/autofill/heuristics/output/071_register_sourceforge.net.out
@@ -1,4 +1,3 @@ -UNKNOWN_TYPE | q | Find Open Source Software | | q_1-default NAME_FULL | X1mRVeMqejLnZpd1etxNGHllat2M | Name: | | X1mRVeMqejLnZpd1etxNGHllat2M_1-default EMAIL_ADDRESS | X129ZdMbfixhIflk8_zHDFWB72qk | Email: | | X1mRVeMqejLnZpd1etxNGHllat2M_1-default UNKNOWN_TYPE | X2n9HcN3dx1-mSbLywp_L-szMydw | Username: | | X1mRVeMqejLnZpd1etxNGHllat2M_1-default
diff --git a/components/viz/common/gl_helper_benchmark.cc b/components/viz/common/gl_helper_benchmark.cc index 410868e..2f77caf3 100644 --- a/components/viz/common/gl_helper_benchmark.cc +++ b/components/viz/common/gl_helper_benchmark.cc
@@ -67,15 +67,17 @@ attributes.gpu_preference = gl::PreferDiscreteGpu; context_ = gpu::GLInProcessContext::CreateWithoutInit(); - auto result = context_->Initialize(nullptr, /* service */ - nullptr, /* surface */ - true, /* offscreen */ - gpu::kNullSurfaceHandle, /* window */ - nullptr, /* share_context */ - attributes, gpu::SharedMemoryLimits(), - nullptr, /* gpu_memory_buffer_manager */ - nullptr, /* image_factory */ - base::ThreadTaskRunnerHandle::Get()); + auto result = + context_->Initialize(nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gpu::kNullSurfaceHandle, /* window */ + nullptr, /* share_context */ + attributes, gpu::SharedMemoryLimits(), + nullptr, /* gpu_memory_buffer_manager */ + nullptr, /* image_factory */ + nullptr /* gpu_channel_manager_delegate */, + base::ThreadTaskRunnerHandle::Get()); DCHECK_EQ(result, gpu::ContextResult::kSuccess); gl_ = context_->GetImplementation(); gpu::ContextSupport* support = context_->GetImplementation();
diff --git a/components/viz/common/gl_helper_unittest.cc b/components/viz/common/gl_helper_unittest.cc index ddcb914..6c184d1 100644 --- a/components/viz/common/gl_helper_unittest.cc +++ b/components/viz/common/gl_helper_unittest.cc
@@ -61,15 +61,17 @@ attributes.bind_generates_resource = false; context_ = gpu::GLInProcessContext::CreateWithoutInit(); - auto result = context_->Initialize(nullptr, /* service */ - nullptr, /* surface */ - true, /* offscreen */ - gpu::kNullSurfaceHandle, /* window */ - nullptr, /* share_context */ - attributes, gpu::SharedMemoryLimits(), - nullptr, /* gpu_memory_buffer_manager */ - nullptr, /* image_factory */ - base::ThreadTaskRunnerHandle::Get()); + auto result = + context_->Initialize(nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gpu::kNullSurfaceHandle, /* window */ + nullptr, /* share_context */ + attributes, gpu::SharedMemoryLimits(), + nullptr, /* gpu_memory_buffer_manager */ + nullptr, /* image_factory */ + nullptr /* gpu_channel_manager_delegate */, + base::ThreadTaskRunnerHandle::Get()); DCHECK_EQ(result, gpu::ContextResult::kSuccess); gl_ = context_->GetImplementation(); gpu::ContextSupport* support = context_->GetImplementation();
diff --git a/components/viz/common/gpu/in_process_context_provider.cc b/components/viz/common/gpu/in_process_context_provider.cc index 46c479fb..99a5619 100644 --- a/components/viz/common/gpu/in_process_context_provider.cc +++ b/components/viz/common/gpu/in_process_context_provider.cc
@@ -54,6 +54,7 @@ gpu::SurfaceHandle surface_handle, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, gpu::ImageFactory* image_factory, + gpu::GpuChannelManagerDelegate* gpu_channel_manager_delegate, const gpu::SharedMemoryLimits& limits, InProcessContextProvider* shared_context) : attributes_(CreateAttributes()), @@ -68,6 +69,7 @@ limits, gpu_memory_buffer_manager, image_factory, + gpu_channel_manager_delegate, base::ThreadTaskRunnerHandle::Get())), cache_controller_(std::make_unique<ContextCacheController>( context_->GetImplementation(),
diff --git a/components/viz/common/gpu/in_process_context_provider.h b/components/viz/common/gpu/in_process_context_provider.h index eeef36d..da16824 100644 --- a/components/viz/common/gpu/in_process_context_provider.h +++ b/components/viz/common/gpu/in_process_context_provider.h
@@ -22,6 +22,7 @@ namespace gpu { class GLInProcessContext; +class GpuChannelManagerDelegate; class GpuMemoryBufferManager; class ImageFactory; struct SharedMemoryLimits; @@ -33,6 +34,10 @@ namespace viz { +// A ContextProvider used in the viz process to setup command buffers between +// the compositor and gpu thread. +// TODO(kylechar): Rename VizProcessContextProvider and move to +// components/viz/service. class VIZ_COMMON_EXPORT InProcessContextProvider : public ContextProvider { public: InProcessContextProvider( @@ -40,6 +45,7 @@ gpu::SurfaceHandle surface_handle, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, gpu::ImageFactory* image_factory, + gpu::GpuChannelManagerDelegate* gpu_channel_manager_delegate, const gpu::SharedMemoryLimits& limits, InProcessContextProvider* shared_context);
diff --git a/components/viz/common/yuv_readback_unittest.cc b/components/viz/common/yuv_readback_unittest.cc index 045e934..ff5b30e5 100644 --- a/components/viz/common/yuv_readback_unittest.cc +++ b/components/viz/common/yuv_readback_unittest.cc
@@ -42,15 +42,17 @@ attributes.bind_generates_resource = false; context_ = gpu::GLInProcessContext::CreateWithoutInit(); - auto result = context_->Initialize(nullptr, /* service */ - nullptr, /* surface */ - true, /* offscreen */ - gpu::kNullSurfaceHandle, /* window */ - nullptr, /* share_context */ - attributes, gpu::SharedMemoryLimits(), - nullptr, /* gpu_memory_buffer_manager */ - nullptr, /* image_factory */ - base::ThreadTaskRunnerHandle::Get()); + auto result = + context_->Initialize(nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gpu::kNullSurfaceHandle, /* window */ + nullptr, /* share_context */ + attributes, gpu::SharedMemoryLimits(), + nullptr, /* gpu_memory_buffer_manager */ + nullptr, /* image_factory */ + nullptr /* gpu_channel_manager_delegate */, + base::ThreadTaskRunnerHandle::Get()); DCHECK_EQ(result, gpu::ContextResult::kSuccess); gl_ = context_->GetImplementation(); gpu::ContextSupport* support = context_->GetImplementation();
diff --git a/components/viz/service/display_embedder/gpu_display_provider.cc b/components/viz/service/display_embedder/gpu_display_provider.cc index b7184da3..863f533 100644 --- a/components/viz/service/display_embedder/gpu_display_provider.cc +++ b/components/viz/service/display_embedder/gpu_display_provider.cc
@@ -24,6 +24,7 @@ #include "gpu/command_buffer/service/image_factory.h" #include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/service/gpu_channel_manager.h" +#include "gpu/ipc/service/gpu_channel_manager_delegate.h" #include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "ui/base/ui_base_switches.h" @@ -66,6 +67,7 @@ CompositingModeReporterImpl* compositing_mode_reporter) : restart_id_(restart_id), gpu_service_(std::move(gpu_service)), + gpu_channel_manager_delegate_(gpu_channel_manager->delegate()), gpu_memory_buffer_manager_( base::MakeUnique<InProcessGpuMemoryBufferManager>( gpu_channel_manager)), @@ -113,8 +115,8 @@ } else { auto context_provider = base::MakeRefCounted<InProcessContextProvider>( gpu_service_, surface_handle, gpu_memory_buffer_manager_.get(), - image_factory_, gpu::SharedMemoryLimits(), - nullptr /* shared_context */); + image_factory_, gpu_channel_manager_delegate_, + gpu::SharedMemoryLimits(), nullptr /* shared_context */); // TODO(rjkroege): If there is something better to do than CHECK, add it. // TODO(danakj): Should retry if the result is kTransientFailure.
diff --git a/components/viz/service/display_embedder/gpu_display_provider.h b/components/viz/service/display_embedder/gpu_display_provider.h index 4a93727..8900ba3e 100644 --- a/components/viz/service/display_embedder/gpu_display_provider.h +++ b/components/viz/service/display_embedder/gpu_display_provider.h
@@ -20,6 +20,7 @@ namespace gpu { class GpuChannelManager; +class GpuChannelManagerDelegate; class ImageFactory; } // namespace gpu @@ -54,6 +55,7 @@ const uint32_t restart_id_; scoped_refptr<gpu::InProcessCommandBuffer::Service> gpu_service_; + gpu::GpuChannelManagerDelegate* const gpu_channel_manager_delegate_; std::unique_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_; gpu::ImageFactory* const image_factory_; CompositingModeReporterImpl* const compositing_mode_reporter_;
diff --git a/content/browser/DEPS b/content/browser/DEPS index 94e0ad4..f28416fa 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -100,6 +100,7 @@ "+third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationType.h", "+third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h", "+third_party/WebKit/public/public_features.h", + "+third_party/WebKit/public/web/devtools_frontend.mojom.h", "+third_party/WebKit/public/web/WebAXEnums.h", "+third_party/WebKit/public/web/WebConsoleMessage.h", "+third_party/WebKit/public/web/WebContextMenuData.h",
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc index 4c718787..8fd77c1 100644 --- a/content/browser/compositor/viz_process_transport_factory.cc +++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -30,6 +30,10 @@ #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" #include "ui/compositor/reflector.h" +#if defined(OS_WIN) +#include "ui/gfx/win/rendering_window_manager.h" +#endif + namespace content { namespace { @@ -149,6 +153,11 @@ void VizProcessTransportFactory::CreateLayerTreeFrameSink( base::WeakPtr<ui::Compositor> compositor) { +#if defined(OS_WIN) + gfx::RenderingWindowManager::GetInstance()->UnregisterParent( + compositor->widget()); +#endif + if (is_gpu_compositing_disabled_ || compositor->force_software_compositor()) { OnEstablishedGpuChannel(compositor, nullptr); return; @@ -165,6 +174,13 @@ } void VizProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) { +#if defined(OS_WIN) + // TODO(crbug.com/791660): Make sure that GpuProcessHost::SetChildSurface() + // doesn't crash the GPU process after parent is unregistered. + gfx::RenderingWindowManager::GetInstance()->UnregisterParent( + compositor->widget()); +#endif + compositor_data_map_.erase(compositor); } @@ -381,6 +397,11 @@ } } +#if defined(OS_WIN) + gfx::RenderingWindowManager::GetInstance()->RegisterParent( + compositor->widget()); +#endif + // TODO(crbug.com/776050): Deal with context loss. // Create interfaces for a root CompositorFrameSink. @@ -429,6 +450,11 @@ compositor->SetLayerTreeFrameSink( std::make_unique<viz::ClientLayerTreeFrameSink>( std::move(compositor_context), std::move(worker_context), ¶ms)); + +#if defined(OS_WIN) + gfx::RenderingWindowManager::GetInstance()->DoSetParentOnChild( + compositor->widget()); +#endif } bool VizProcessTransportFactory::CreateContextProviders(
diff --git a/content/browser/devtools/devtools_frontend_host_impl.cc b/content/browser/devtools/devtools_frontend_host_impl.cc index afa8104..813056c 100644 --- a/content/browser/devtools/devtools_frontend_host_impl.cc +++ b/content/browser/devtools/devtools_frontend_host_impl.cc
@@ -36,7 +36,7 @@ RenderFrameHost* frame_host, const std::string& extension_api) { DCHECK(frame_host->GetParent()); - mojom::DevToolsFrontendAssociatedPtr frontend; + blink::mojom::DevToolsFrontendAssociatedPtr frontend; frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&frontend); frontend->SetupDevToolsExtensionAPI(extension_api); } @@ -59,13 +59,13 @@ : web_contents_(WebContents::FromRenderFrameHost(frame_host)), handle_message_callback_(handle_message_callback), binding_(this) { - mojom::DevToolsFrontendAssociatedPtr frontend; + blink::mojom::DevToolsFrontendAssociatedPtr frontend; frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&frontend); std::string api_script = content::DevToolsFrontendHost::GetFrontendResource(kCompatibilityScript) .as_string() + kCompatibilityScriptSourceURL; - mojom::DevToolsFrontendHostAssociatedPtrInfo host; + blink::mojom::DevToolsFrontendHostAssociatedPtrInfo host; binding_.Bind(mojo::MakeRequest(&host)); frontend->SetupDevToolsFrontend(api_script, std::move(host)); }
diff --git a/content/browser/devtools/devtools_frontend_host_impl.h b/content/browser/devtools/devtools_frontend_host_impl.h index 054cf5a..0b4275e5 100644 --- a/content/browser/devtools/devtools_frontend_host_impl.h +++ b/content/browser/devtools/devtools_frontend_host_impl.h
@@ -6,16 +6,16 @@ #define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_IMPL_H_ #include "base/macros.h" -#include "content/common/devtools.mojom.h" #include "content/public/browser/devtools_frontend_host.h" #include "mojo/public/cpp/bindings/associated_binding.h" +#include "third_party/WebKit/public/web/devtools_frontend.mojom.h" namespace content { class WebContents; class DevToolsFrontendHostImpl : public DevToolsFrontendHost, - public mojom::DevToolsFrontendHost { + public blink::mojom::DevToolsFrontendHost { public: DevToolsFrontendHostImpl( RenderFrameHost* frame_host, @@ -25,12 +25,12 @@ void BadMessageRecieved() override; private: - // mojom::DevToolsFrontendHost implementation. + // blink::mojom::DevToolsFrontendHost implementation. void DispatchEmbedderMessage(const std::string& message) override; WebContents* web_contents_; HandleMessageCallback handle_message_callback_; - mojo::AssociatedBinding<mojom::DevToolsFrontendHost> binding_; + mojo::AssociatedBinding<blink::mojom::DevToolsFrontendHost> binding_; DISALLOW_COPY_AND_ASSIGN(DevToolsFrontendHostImpl); };
diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc index af17d6d..6a44b62 100644 --- a/content/browser/loader/resource_scheduler.cc +++ b/content/browser/loader/resource_scheduler.cc
@@ -24,6 +24,7 @@ #include "content/common/resource_messages.h" #include "content/public/browser/resource_request_info.h" #include "content/public/browser/resource_throttle.h" +#include "content/public/common/content_features.h" #include "net/base/host_port_pair.h" #include "net/base/load_flags.h" #include "net/base/request_priority.h" @@ -423,7 +424,15 @@ resource_scheduler->throttle_delayable_.GetMaxDelayableRequests( network_quality_estimator)), resource_scheduler_(resource_scheduler), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + if (base::FeatureList::IsEnabled( + features::kRendererSideResourceScheduler)) { + // When kRendererSideResourceScheduler is enabled, "layout blocking" + // concept is moved to the renderer side, so the shceduler works always + // with the normal mode. + has_html_body_ = true; + } + } ~Client() {} @@ -488,6 +497,14 @@ void OnNavigate() { has_html_body_ = false; + if (base::FeatureList::IsEnabled( + features::kRendererSideResourceScheduler)) { + // When kRendererSideResourceScheduler is enabled, "layout blocking" + // concept is moved to the renderer side, so the shceduler works always + // with the normal mode. + has_html_body_ = true; + } + is_loaded_ = false; max_delayable_requests_ = resource_scheduler_->throttle_delayable_.GetMaxDelayableRequests( @@ -960,6 +977,8 @@ bool is_loaded_; // Tracks if the main HTML parser has reached the body which marks the end of // layout-blocking resources. + // This is disabled and the is always true when kRendererSideResourceScheduler + // is enabled. bool has_html_body_; bool using_spdy_proxy_; RequestQueue pending_requests_;
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc index fb85ee0..1f862b78 100644 --- a/content/browser/service_manager/service_manager_context.cc +++ b/content/browser/service_manager/service_manager_context.cc
@@ -30,6 +30,7 @@ #include "content/browser/wake_lock/wake_lock_context_host.h" #include "content/common/service_manager/service_manager_connection_impl.h" #include "content/grit/content_resources.h" +#include "content/network/network_service_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/gpu_service_registry.h" @@ -280,6 +281,12 @@ } #endif +std::unique_ptr<service_manager::Service> CreateNetworkService() { + // TODO(jam): make in-process network service work with test interfaces. + return std::make_unique<NetworkServiceImpl>( + std::make_unique<service_manager::BinderRegistry>()); +} + } // namespace // State which lives on the IO thread and drives the ServiceManager. @@ -494,9 +501,20 @@ bool network_service_enabled = base::FeatureList::IsEnabled(features::kNetworkService); + bool network_service_in_process = + base::FeatureList::IsEnabled(features::kNetworkServiceInProcess); if (network_service_enabled) { - out_of_process_services[content::mojom::kNetworkServiceName] = - base::ASCIIToUTF16("Network Service"); + if (network_service_in_process) { + service_manager::EmbeddedServiceInfo network_service_info; + network_service_info.factory = base::BindRepeating(CreateNetworkService); + network_service_info.task_runner = + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO); + packaged_services_connection_->AddEmbeddedService( + mojom::kNetworkServiceName, network_service_info); + } else { + out_of_process_services[mojom::kNetworkServiceName] = + base::ASCIIToUTF16("Network Service"); + } } if (base::FeatureList::IsEnabled(video_capture::kMojoVideoCapture)) { @@ -541,7 +559,7 @@ RegisterCommonBrowserInterfaces(browser_connection); browser_connection->Start(); - if (network_service_enabled) { + if (network_service_enabled && !network_service_in_process) { // Start the network service process as soon as possible, since it is // critical to start up performance. browser_connection->GetConnector()->StartService(
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 1d3faaf..223ab4b 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -80,6 +80,7 @@ #include "content/public/test/test_frame_navigation_observer.h" #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" +#include "content/public/test/url_loader_interceptor.h" #include "content/shell/browser/shell.h" #include "content/shell/common/shell_switches.h" #include "content/test/content_browser_test_utils_internal.h" @@ -3100,43 +3101,6 @@ } } -namespace { -class FailingURLLoaderImpl : public mojom::URLLoader { - public: - explicit FailingURLLoaderImpl(mojom::URLLoaderClientPtr client) { - network::URLLoaderCompletionStatus status; - status.error_code = net::ERR_NOT_IMPLEMENTED; - client->OnComplete(status); - } - - void FollowRedirect() override {} - void SetPriority(net::RequestPriority priority, - int32_t intra_priority_value) override {} - void PauseReadingBodyFromNet() override {} - void ResumeReadingBodyFromNet() override {} -}; - -class FailingLoadFactory : public mojom::URLLoaderFactory { - public: - FailingLoadFactory() {} - ~FailingLoadFactory() override {} - - void CreateLoaderAndStart(mojom::URLLoaderRequest loader, - int32_t routing_id, - int32_t request_id, - uint32_t options, - const ResourceRequest& request, - mojom::URLLoaderClientPtr client, - const net::MutableNetworkTrafficAnnotationTag& - traffic_annotation) override { - new FailingURLLoaderImpl(std::move(client)); - } - - void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); } -}; - -} // namespace - // Ensure that a cross-site page ends up in the correct process when it // successfully loads after earlier encountering a network error for it. // See https://crbug.com/560511. @@ -3157,14 +3121,19 @@ GURL url_b = embedded_test_server()->GetURL("b.com", "/title3.html"); bool network_service = base::FeatureList::IsEnabled(features::kNetworkService); - FailingLoadFactory failing_factory; - StoragePartitionImpl* storage_partition = nullptr; + std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor; if (network_service) { - storage_partition = static_cast<StoragePartitionImpl*>( + StoragePartition* storage_partition = BrowserContext::GetDefaultStoragePartition( - shell()->web_contents()->GetBrowserContext())); - storage_partition->url_loader_factory_getter()->SetNetworkFactoryForTesting( - &failing_factory); + shell()->web_contents()->GetBrowserContext()); + url_loader_interceptor = std::make_unique<URLLoaderInterceptor>( + base::BindRepeating([](URLLoaderInterceptor::RequestParams* params) { + network::URLLoaderCompletionStatus status; + status.error_code = net::ERR_NOT_IMPLEMENTED; + params->client->OnComplete(status); + return true; + }), + storage_partition); } else { host_resolver()->ClearRules(); } @@ -3202,8 +3171,7 @@ // Try again after re-enabling host resolution. if (network_service) { - storage_partition->url_loader_factory_getter()->SetNetworkFactoryForTesting( - nullptr); + url_loader_interceptor.reset(); } else { host_resolver()->AddRule("*", "127.0.0.1"); }
diff --git a/content/common/devtools.mojom b/content/common/devtools.mojom index 8ef6200..2c5f2640 100644 --- a/content/common/devtools.mojom +++ b/content/common/devtools.mojom
@@ -6,38 +6,6 @@ import "ui/gfx/geometry/mojo/geometry.mojom"; -// Provides extra capabilities required for DevTools frontend to function. -// This includes communication channel from/to inspected target which implements -// remote debugging protocol. Protocol messages go through browser process. -// This interface is implemented in DevTools renderer. -// -// Instances of this interface must be associated with navigation-related -// interface, since we should setup DevToolsFrontend before the navigation -// commits in the frame. -interface DevToolsFrontend { - // Sets up a main frame as a DevTools frontend. This exposes DevToolsHost - // object (see DevToolsHost.idl for details). The |api_script| is executed - // on each navigation in the frame before the DevTools frontend starts - // loading. It makes use of DevToolsHost to expose embedder capabilities to - // DevTools (e.g. connection to the inspected target). - SetupDevToolsFrontend(string api_script, - associated DevToolsFrontendHost host); - - // Sets up a child frame to expose DevTools extension API by executing script - // |extension_api| on each navigation in the frame. This script provides - // required capabilities for DevTools extensions to function, implementing - // chrome.devtools extension API. - SetupDevToolsExtensionAPI(string extension_api); -}; - -// Provides embedder functionality to a frame serving as DevTools frontend. -// This interface is implemented in browser. -interface DevToolsFrontendHost { - // Sends a message to DevTools frontend embedder. - DispatchEmbedderMessage(string message); -}; - - // Used to send large messages in chunks from session to a host. struct DevToolsMessageChunk { // Whether this is a first chunk in a message.
diff --git a/content/network/network_context.cc b/content/network/network_context.cc index 1d5ab88..a056a3b 100644 --- a/content/network/network_context.cc +++ b/content/network/network_context.cc
@@ -34,6 +34,7 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "content/public/network/ignore_errors_cert_verifier.h" +#include "content/public/network/url_request_context_builder_mojo.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "net/dns/host_resolver.h" #include "net/dns/mapped_host_resolver.h" @@ -69,7 +70,7 @@ NetworkServiceImpl* network_service, mojom::NetworkContextRequest request, mojom::NetworkContextParamsPtr params, - std::unique_ptr<net::URLRequestContextBuilder> builder) + std::unique_ptr<URLRequestContextBuilderMojo> builder) : network_service_(network_service), params_(std::move(params)), binding_(this, std::move(request)) { @@ -203,7 +204,7 @@ std::unique_ptr<net::URLRequestContext> NetworkContext::MakeURLRequestContext( mojom::NetworkContextParams* network_context_params) { - net::URLRequestContextBuilder builder; + URLRequestContextBuilderMojo builder; const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -231,7 +232,7 @@ } void NetworkContext::ApplyContextParamsToBuilder( - net::URLRequestContextBuilder* builder, + URLRequestContextBuilderMojo* builder, mojom::NetworkContextParams* network_context_params) { // |network_service_| may be nullptr in tests. if (network_service_) @@ -241,6 +242,12 @@ if (network_context_params->context_name) builder->set_name(*network_context_params->context_name); + if (network_context_params->proxy_resolver_factory) { + builder->SetMojoProxyResolverFactory( + proxy_resolver::mojom::ProxyResolverFactoryPtr( + std::move(network_context_params->proxy_resolver_factory))); + } + if (!network_context_params->http_cache_enabled) { builder->DisableHttpCache(); } else {
diff --git a/content/network/network_context.h b/content/network/network_context.h index 015dd27..cc66fc9 100644 --- a/content/network/network_context.h +++ b/content/network/network_context.h
@@ -25,13 +25,13 @@ namespace net { class URLRequestContext; -class URLRequestContextBuilder; class HttpServerPropertiesManager; } namespace content { class NetworkServiceImpl; class URLLoader; +class URLRequestContextBuilderMojo; // A NetworkContext creates and manages access to a URLRequestContext. // @@ -42,7 +42,7 @@ // // When the network service is disabled, NetworkContexts may be created through // NetworkServiceImpl::CreateNetworkContextWithBuilder, and take in a -// URLRequestContextBuilder to seed construction of the NetworkContext's +// URLRequestContextBuilderMojo to seed construction of the NetworkContext's // URLRequestContext. When that happens, the consumer takes ownership of the // NetworkContext directly, has direct access to its URLRequestContext, and is // responsible for destroying it before the NetworkService. @@ -53,11 +53,11 @@ mojom::NetworkContextParamsPtr params); // Temporary constructor that allows creating an in-process NetworkContext - // with a pre-populated URLRequestContextBuilder. + // with a pre-populated URLRequestContextBuilderMojo. NetworkContext(NetworkServiceImpl* network_service, mojom::NetworkContextRequest request, mojom::NetworkContextParamsPtr params, - std::unique_ptr<net::URLRequestContextBuilder> builder); + std::unique_ptr<URLRequestContextBuilderMojo> builder); // Creates a NetworkContext that wraps a consumer-provided URLRequestContext // that the NetworkContext does not own. In this case, there is no @@ -115,7 +115,7 @@ // Applies the values in |network_context_params| to |builder|. void ApplyContextParamsToBuilder( - net::URLRequestContextBuilder* builder, + URLRequestContextBuilderMojo* builder, mojom::NetworkContextParams* network_context_params); NetworkServiceImpl* const network_service_;
diff --git a/content/network/network_service_impl.cc b/content/network/network_service_impl.cc index f56582b..4321d869 100644 --- a/content/network/network_service_impl.cc +++ b/content/network/network_service_impl.cc
@@ -13,6 +13,7 @@ #include "build/build_config.h" #include "content/network/network_context.h" #include "content/public/common/content_switches.h" +#include "content/public/network/url_request_context_builder_mojo.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "net/base/logging_network_change_observer.h" #include "net/base/network_change_notifier.h" @@ -138,7 +139,7 @@ NetworkServiceImpl::CreateNetworkContextWithBuilder( content::mojom::NetworkContextRequest request, content::mojom::NetworkContextParamsPtr params, - std::unique_ptr<net::URLRequestContextBuilder> builder, + std::unique_ptr<URLRequestContextBuilderMojo> builder, net::URLRequestContext** url_request_context) { std::unique_ptr<NetworkContext> network_context = std::make_unique<NetworkContext>(this, std::move(request),
diff --git a/content/network/network_service_impl.h b/content/network/network_service_impl.h index ea7aac6..2806b56 100644 --- a/content/network/network_service_impl.h +++ b/content/network/network_service_impl.h
@@ -23,12 +23,12 @@ class NetLog; class LoggingNetworkChangeObserver; class URLRequestContext; -class URLRequestContextBuilder; } // namespace net namespace content { class NetworkContext; +class URLRequestContextBuilderMojo; class CONTENT_EXPORT NetworkServiceImpl : public service_manager::Service, public NetworkService { @@ -47,7 +47,7 @@ std::unique_ptr<mojom::NetworkContext> CreateNetworkContextWithBuilder( content::mojom::NetworkContextRequest request, content::mojom::NetworkContextParamsPtr params, - std::unique_ptr<net::URLRequestContextBuilder> builder, + std::unique_ptr<URLRequestContextBuilderMojo> builder, net::URLRequestContext** url_request_context) override; static std::unique_ptr<NetworkServiceImpl> CreateForTesting();
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index fe882fea..46f2aef 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn
@@ -374,6 +374,7 @@ ":resource_type_bindings", "//mojo/common:common_custom_types", "//services/network/public/interfaces", + "//services/proxy_resolver/public/interfaces", "//url/mojo:url_mojom_gurl", "//url/mojo:url_mojom_origin", ]
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 8f8e0e1..262fa2e 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -165,6 +165,10 @@ const base::Feature kNetworkService{"NetworkService", base::FEATURE_DISABLED_BY_DEFAULT}; +// If the network service is enabled, runs it in process. +const base::Feature kNetworkServiceInProcess{"NetworkServiceInProcess", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Kill switch for Web Notification content images. const base::Feature kNotificationContentImage{"NotificationContentImage", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index d5289ad0..8da6cae 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -53,6 +53,7 @@ CONTENT_EXPORT extern const base::Feature kMediaDevicesSystemMonitorCache; CONTENT_EXPORT extern const base::Feature kMemoryCoordinator; CONTENT_EXPORT extern const base::Feature kNetworkService; +CONTENT_EXPORT extern const base::Feature kNetworkServiceInProcess; CONTENT_EXPORT extern const base::Feature kNotificationContentImage; CONTENT_EXPORT extern const base::Feature kMainThreadBusyScrollIntervention; CONTENT_EXPORT extern const base::Feature kMojoBlobs;
diff --git a/content/public/common/network_service.mojom b/content/public/common/network_service.mojom index b5333a9..0ef8af9c 100644 --- a/content/public/common/network_service.mojom +++ b/content/public/common/network_service.mojom
@@ -14,6 +14,7 @@ import "services/network/public/interfaces/cookie_manager.mojom"; import "services/network/public/interfaces/network_change_manager.mojom"; import "services/network/public/interfaces/restricted_cookie_manager.mojom"; +import "services/proxy_resolver/public/interfaces/proxy_resolver.mojom"; [Native] struct SSLInfo; @@ -29,6 +30,11 @@ // QUIC user agent. string quic_user_agent_id; + // Handles PAC script execution. If not populated, will attempt to use + // platform implementation to execute PAC scripts, if available (Only + // available on Windows and Mac). + proxy_resolver.mojom.ProxyResolverFactory? proxy_resolver_factory; + // Points to the cookie file. Currently ignored. An in-memory cookie store is // always used instead. // TODO(mmenke): Respect this parameter.
diff --git a/content/public/network/network_service.h b/content/public/network/network_service.h index 31d3112..bc161ff 100644 --- a/content/public/network/network_service.h +++ b/content/public/network/network_service.h
@@ -13,11 +13,12 @@ namespace net { class NetLog; class URLRequestContext; -class URLRequestContextBuilder; } // namespace net namespace content { +class URLRequestContextBuilderMojo; + // Allows an in-process NetworkService to be set up. class CONTENT_EXPORT NetworkService : public mojom::NetworkService { public: @@ -44,7 +45,7 @@ CreateNetworkContextWithBuilder( mojom::NetworkContextRequest request, mojom::NetworkContextParamsPtr params, - std::unique_ptr<net::URLRequestContextBuilder> builder, + std::unique_ptr<URLRequestContextBuilderMojo> builder, net::URLRequestContext** url_request_context) = 0; ~NetworkService() override {}
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 36d95599..f088918 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -97,8 +97,6 @@ "devtools/devtools_agent.h", "devtools/devtools_cpu_throttler.cc", "devtools/devtools_cpu_throttler.h", - "devtools/devtools_frontend_impl.cc", - "devtools/devtools_frontend_impl.h", "devtools/render_widget_screen_metrics_emulator.cc", "devtools/render_widget_screen_metrics_emulator.h", "devtools/render_widget_screen_metrics_emulator_delegate.h",
diff --git a/content/renderer/devtools/devtools_frontend_impl.cc b/content/renderer/devtools/devtools_frontend_impl.cc deleted file mode 100644 index 1400750e..0000000 --- a/content/renderer/devtools/devtools_frontend_impl.cc +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/devtools/devtools_frontend_impl.h" - -#include "base/strings/utf_string_conversions.h" -#include "content/renderer/render_frame_impl.h" -#include "content/renderer/render_thread_impl.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/web/WebDevToolsFrontend.h" - -namespace content { - -// static -void DevToolsFrontendImpl::CreateMojoService( - RenderFrame* render_frame, - mojom::DevToolsFrontendAssociatedRequest request) { - // Self-destructs on render frame deletion. - new DevToolsFrontendImpl(render_frame, std::move(request)); -} - -DevToolsFrontendImpl::DevToolsFrontendImpl( - RenderFrame* render_frame, - mojom::DevToolsFrontendAssociatedRequest request) - : RenderFrameObserver(render_frame), binding_(this, std::move(request)) {} - -DevToolsFrontendImpl::~DevToolsFrontendImpl() {} - -void DevToolsFrontendImpl::DidClearWindowObject() { - if (!api_script_.empty()) - render_frame()->ExecuteJavaScript(base::UTF8ToUTF16(api_script_)); -} - -void DevToolsFrontendImpl::OnDestruct() { - delete this; -} - -void DevToolsFrontendImpl::SendMessageToEmbedder( - const blink::WebString& message) { - if (host_) - host_->DispatchEmbedderMessage(message.Utf8()); -} - -bool DevToolsFrontendImpl::IsUnderTest() { - return RenderThreadImpl::current()->layout_test_mode(); -} - -void DevToolsFrontendImpl::SetupDevToolsFrontend( - const std::string& api_script, - mojom::DevToolsFrontendHostAssociatedPtrInfo host) { - DCHECK(render_frame()->IsMainFrame()); - api_script_ = api_script; - web_devtools_frontend_.reset( - blink::WebDevToolsFrontend::Create(render_frame()->GetWebFrame(), this)); - host_.Bind(std::move(host)); - host_.set_connection_error_handler(base::BindOnce( - &DevToolsFrontendImpl::OnDestruct, base::Unretained(this))); -} - -void DevToolsFrontendImpl::SetupDevToolsExtensionAPI( - const std::string& extension_api) { - DCHECK(!render_frame()->IsMainFrame()); - api_script_ = extension_api; -} - -} // namespace content
diff --git a/content/renderer/devtools/devtools_frontend_impl.h b/content/renderer/devtools/devtools_frontend_impl.h deleted file mode 100644 index 6bab4f3..0000000 --- a/content/renderer/devtools/devtools_frontend_impl.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_FRONTEND_IMPL_H_ -#define CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_FRONTEND_IMPL_H_ - -#include <stdint.h> - -#include <memory> -#include <string> - -#include "base/macros.h" -#include "content/common/devtools.mojom.h" -#include "content/public/renderer/render_frame_observer.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "third_party/WebKit/public/web/WebDevToolsFrontendClient.h" - -namespace blink { -class WebDevToolsFrontend; -class WebString; -} // namespace blink - -namespace content { - -// Implementation of content.mojom.DevToolsFrontend interface. -class DevToolsFrontendImpl : public RenderFrameObserver, - public blink::WebDevToolsFrontendClient, - public mojom::DevToolsFrontend { - public: - ~DevToolsFrontendImpl() override; - - static void CreateMojoService( - RenderFrame* render_frame, - mojom::DevToolsFrontendAssociatedRequest request); - - private: - DevToolsFrontendImpl(RenderFrame* render_frame, - mojom::DevToolsFrontendAssociatedRequest request); - - // RenderFrameObserver overrides. - void DidClearWindowObject() override; - void OnDestruct() override; - - // WebDevToolsFrontendClient implementation. - void SendMessageToEmbedder(const blink::WebString& message) override; - bool IsUnderTest() override; - - // mojom::DevToolsFrontend implementation. - void SetupDevToolsFrontend( - const std::string& api_script, - mojom::DevToolsFrontendHostAssociatedPtrInfo host) override; - void SetupDevToolsExtensionAPI(const std::string& extension_api) override; - - std::unique_ptr<blink::WebDevToolsFrontend> web_devtools_frontend_; - std::string api_script_; - mojom::DevToolsFrontendHostAssociatedPtr host_; - mojo::AssociatedBinding<mojom::DevToolsFrontend> binding_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsFrontendImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_FRONTEND_IMPL_H_
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index bd485e59..52ee7b4 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -98,7 +98,6 @@ #include "content/renderer/content_security_policy_util.h" #include "content/renderer/context_menu_params_builder.h" #include "content/renderer/devtools/devtools_agent.h" -#include "content/renderer/devtools/devtools_frontend_impl.h" #include "content/renderer/dom_automation_controller.h" #include "content/renderer/effective_connection_type_helper.h" #include "content/renderer/external_popup_menu.h" @@ -7064,9 +7063,6 @@ registry_.AddInterface( base::Bind(&RenderFrameImpl::BindWidget, weak_factory_.GetWeakPtr())); - GetAssociatedInterfaceRegistry()->AddInterface(base::Bind( - &DevToolsFrontendImpl::CreateMojoService, base::Unretained(this))); - if (!frame_->Parent()) { // Only main frame have ImageDownloader service. registry_.AddInterface(base::Bind(&ImageDownloaderImpl::CreateMojoService,
diff --git a/device/geolocation/public/interfaces/geolocation.mojom b/device/geolocation/public/interfaces/geolocation.mojom index 027f53e5..0dda9e3 100644 --- a/device/geolocation/public/interfaces/geolocation.mojom +++ b/device/geolocation/public/interfaces/geolocation.mojom
@@ -10,11 +10,21 @@ // provides updates with low accuracy, but |SetHighAccuracy()| may be called // to change this. interface Geolocation { + // Select between high and low accuracy, if supported by the implementation. + // Ignored if unsupported. SetHighAccuracy(bool high_accuracy); - // Position is reported once it changes or immediately (to report the initial - // position) if this is the first call to QueryNextPosition on this instance. - // Position updates may be throttled by the service. Overlapping calls to - // this method are prohibited and will be treated as a connection error. + // Use this method to get notified of future position updates, by calling + // QueryNextPosition once, and then calling it again when/if it returns. + // + // When first called: + // Returns the latest known Geoposition. + // When subsequently called: + // Issues a request for a single position update, which the implementation + // may fulfill at its discretion (e.g. when the next geoposition change is + // detected). + // + // Overlapping calls to this method are prohibited and will be treated as a + // connection error. Position updates may be throttled by the service. QueryNextPosition() => (Geoposition geoposition); };
diff --git a/docs/testing/json_test_results_format.md b/docs/testing/json_test_results_format.md index a017e3f..5b82614 100644 --- a/docs/testing/json_test_results_format.md +++ b/docs/testing/json_test_results_format.md
@@ -107,7 +107,7 @@ |-------------|-----------|-------------| | `actual` | string | **Required.** An ordered space-separated list of the results the test actually produced. `FAIL PASS` means that a test was run twice, failed the first time, and then passed when it was retried. If a test produces multiple different results, then it was actually flaky during the run. | | `expected` | string | **Required.** An unordered space-separated list of the result types expected for the test, e.g. `FAIL PASS` means that a test is expected to either pass or fail. A test that contains multiple values is expected to be flaky. | -| `artifacts` | dict | **Optional.** A dictionary describing test artifacts generated by the execution of the test. The dictionary maps the name of the artifact (`screenshot`, `crash_log`) to a list of relative locations of the artifact (`screenshot/page.png`, `logs/crash.txt`). There is one entry in the list per test execution. If `artifact_permanent_location` is specified, then this location is relative to that path. Otherwise, it is assumed that this test file is in a known location by whatever is processing this test file, and so the location is relative to a known directory. | +| `artifacts` | dict | **Optional.** A dictionary describing test artifacts generated by the execution of the test. The dictionary maps the name of the artifact (`screenshot`, `crash_log`) to a list of relative locations of the artifact (`screenshot/page.png`, `logs/crash.txt`). Any '/' characters in the file paths are meant to be platform agnostic; tools will replace them with the appropriate per platform path separators. There is one entry in the list per test execution. If `artifact_permanent_location` is specified, then this location is relative to that path. Otherwise, the path is assumed to be relative to the location of the json file which contains this. | | `bugs` | string | **Optional.** A comma-separated list of URLs to bug database entries associated with each test. | | `is_unexpected` | bool | **Optional.** If present and true, the failure was unexpected (a regression). If false (or if the key is not present at all), the failure was expected and will be ignored. | | `time` | float | **Optional.** If present, the time it took in seconds to execute the first invocation of the test. |
diff --git a/extensions/browser/api/feedback_private/feedback_private_api_chromeos_unittest.cc b/extensions/browser/api/feedback_private/feedback_private_api_chromeos_unittest.cc index 0d7ec4c..fe7f2d3 100644 --- a/extensions/browser/api/feedback_private/feedback_private_api_chromeos_unittest.cc +++ b/extensions/browser/api/feedback_private/feedback_private_api_chromeos_unittest.cc
@@ -186,6 +186,31 @@ EXPECT_NE("", RunReadLogSourceFunctionWithError(params)); } +TEST_F(FeedbackPrivateApiUnittest, Anonymize) { + const TimeDelta timeout(TimeDelta::FromMilliseconds(0)); + LogSourceAccessManager::SetRateLimitingTimeoutForTesting(&timeout); + + ReadLogSourceParams params; + params.source = api::feedback_private::LOG_SOURCE_MESSAGES; + params.incremental = true; + + int result_reader_id = 0; + std::string result_string; + // Skip over all the alphabetic results, to test anonymization of the + // subsequent MAC address. + for (int i = 0; i < 26; ++i) { + EXPECT_TRUE( + RunReadLogSourceFunction(params, &result_reader_id, &result_string)); + EXPECT_GT(result_reader_id, 0); + params.reader_id = std::make_unique<int>(result_reader_id); + } + + EXPECT_TRUE( + RunReadLogSourceFunction(params, &result_reader_id, &result_string)); + EXPECT_EQ(*params.reader_id, result_reader_id); + EXPECT_EQ("11:22:33:00:00:01", result_string); +} + TEST_F(FeedbackPrivateApiUnittest, ReadLogSourceMultipleSources) { const TimeDelta timeout(TimeDelta::FromMilliseconds(0)); LogSourceAccessManager::SetRateLimitingTimeoutForTesting(&timeout);
diff --git a/extensions/browser/api/feedback_private/feedback_private_api_unittest_base_chromeos.cc b/extensions/browser/api/feedback_private/feedback_private_api_unittest_base_chromeos.cc index 1b82a15..cdbe136 100644 --- a/extensions/browser/api/feedback_private/feedback_private_api_unittest_base_chromeos.cc +++ b/extensions/browser/api/feedback_private/feedback_private_api_unittest_base_chromeos.cc
@@ -28,6 +28,9 @@ using system_logs::SystemLogsResponse; using system_logs::SystemLogsSource; +// A fake MAC address used to test anonymization. +const char kDummyMacAddress[] = "11:22:33:44:55:66"; + std::unique_ptr<KeyedService> ApiResourceManagerTestFactory( content::BrowserContext* context) { return std::make_unique<ApiResourceManager<LogSourceResource>>(context); @@ -43,15 +46,12 @@ ~TestSingleLogSource() override = default; // Fetch() will return a single different string each time, in the following - // sequence: "a", " bb", " ccc", until 25 spaces followed by 26 z's. Will - // never return an empty result. + // sequence: "a", " bb", " ccc", until 25 spaces followed by 26 z's. After + // that, it returns |kDummyMacAddress| before repeating the entire process. + // It will never return an empty result. void Fetch(const system_logs::SysLogsSourceCallback& callback) override { - int count_modulus = call_count_ % kNumCharsToIterate; - std::string result = - std::string(count_modulus, ' ') + - std::string(count_modulus + 1, kInitialChar + count_modulus); + std::string result = GetNextLogResult(); DCHECK_GT(result.size(), 0U); - ++call_count_; auto result_map = std::make_unique<SystemLogsResponse>(); result_map->emplace("", result); @@ -64,6 +64,18 @@ } private: + std::string GetNextLogResult() { + if (call_count_ == kNumCharsToIterate) { + call_count_ = 0; + return kDummyMacAddress; + } + std::string result = + std::string(call_count_, ' ') + + std::string(call_count_ + 1, kInitialChar + call_count_); + ++call_count_; + return result; + } + // Iterate over the whole lowercase alphabet, starting from 'a'. const int kNumCharsToIterate = 26; const char kInitialChar = 'a';
diff --git a/extensions/browser/api/feedback_private/log_source_access_manager.cc b/extensions/browser/api/feedback_private/log_source_access_manager.cc index 70c29ad..4d555ef2 100644 --- a/extensions/browser/api/feedback_private/log_source_access_manager.cc +++ b/extensions/browser/api/feedback_private/log_source_access_manager.cc
@@ -57,6 +57,7 @@ LogSourceAccessManager::LogSourceAccessManager(content::BrowserContext* context) : context_(context), tick_clock_(std::make_unique<base::DefaultTickClock>()), + anonymizer_(std::make_unique<feedback::AnonymizerTool>()), weak_factory_(this) {} LogSourceAccessManager::~LogSourceAccessManager() {} @@ -121,6 +122,10 @@ result.reader_id = delete_resource ? kInvalidResourceId : resource_id; GetLogLinesFromSystemLogsResponse(*response, &result.log_lines); + + for (std::string& line : result.log_lines) + line = anonymizer_->Anonymize(line); + if (delete_resource) { // This should also remove the entry from |sources_|. ApiResourceManager<LogSourceResource>::Get(context_)->Remove(extension_id,
diff --git a/extensions/browser/api/feedback_private/log_source_access_manager.h b/extensions/browser/api/feedback_private/log_source_access_manager.h index 78a4ca5..343b42f 100644 --- a/extensions/browser/api/feedback_private/log_source_access_manager.h +++ b/extensions/browser/api/feedback_private/log_source_access_manager.h
@@ -16,6 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/time/tick_clock.h" #include "base/time/time.h" +#include "components/feedback/anonymizer_tool.h" #include "components/feedback/system_logs/system_logs_source.h" #include "content/public/browser/browser_context.h" #include "extensions/browser/api/feedback_private/access_rate_limiter.h" @@ -150,6 +151,9 @@ // Can override the default clock for testing. std::unique_ptr<base::TickClock> tick_clock_; + // For removing PII from log strings from log sources. + std::unique_ptr<feedback::AnonymizerTool> anonymizer_; + base::WeakPtrFactory<LogSourceAccessManager> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LogSourceAccessManager);
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index da4defd..9ce2ab0d 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn
@@ -284,8 +284,6 @@ "//extensions/common", "//extensions/common/api", "//gin", - "//mojo/edk/js", - "//mojo/public/js", "//skia", "//third_party/WebKit/public:blink", "//third_party/cld_3/src/src:cld_3", @@ -368,11 +366,7 @@ testonly = true sources = [ "activity_log_converter_strategy_unittest.cc", - "api/mojo_private/mojo_private_unittest.cc", "api_activity_logger_unittest.cc", - "api_test_base.cc", - "api_test_base.h", - "api_test_base_unittest.cc", "bindings/api_binding_hooks_test_delegate.cc", "bindings/api_binding_hooks_test_delegate.h", "bindings/api_binding_js_util_unittest.cc", @@ -428,7 +422,6 @@ "//gin", "//gin:gin_test", "//ipc:test_support", - "//mojo/edk/js", "//testing/gmock", "//testing/gtest", "//third_party/WebKit/public:blink",
diff --git a/extensions/renderer/api/mojo_private/mojo_private_unittest.cc b/extensions/renderer/api/mojo_private/mojo_private_unittest.cc deleted file mode 100644 index 9693bf28..0000000 --- a/extensions/renderer/api/mojo_private/mojo_private_unittest.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "extensions/renderer/api_test_base.h" - -#include "base/macros.h" -#include "extensions/common/extension_builder.h" -#include "extensions/common/value_builder.h" - -// A test launcher for tests for the mojoPrivate API defined in -// extensions/test/data/mojo_private_unittest.js. - -namespace extensions { - -class MojoPrivateApiTest : public ApiTestBase { - public: - MojoPrivateApiTest() = default; - - scoped_refptr<const Extension> CreateExtension() override { - std::unique_ptr<base::DictionaryValue> manifest = - DictionaryBuilder() - .Set("name", "test") - .Set("version", "1.0") - .Set("manifest_version", 2) - .Build(); - // Return an extension whitelisted for the mojoPrivate API. - return ExtensionBuilder() - .SetManifest(std::move(manifest)) - .SetID("pkedcjkdefgpdelpbcmbmeomcjbeemfm") - .Build(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(MojoPrivateApiTest); -}; - -TEST_F(MojoPrivateApiTest, RequireAsync) { - env()->RegisterModule( - "add", "exports.$set('returnValue', function(x, y) { return x + y; });"); - ASSERT_NO_FATAL_FAILURE( - RunTest("mojo_private_unittest.js", "testRequireAsync")); -} - -} // namespace extensions
diff --git a/extensions/renderer/api_test_base.cc b/extensions/renderer/api_test_base.cc deleted file mode 100644 index 0bd6ae36..0000000 --- a/extensions/renderer/api_test_base.cc +++ /dev/null
@@ -1,261 +0,0 @@ -// Copyright 2014 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 "extensions/renderer/api_test_base.h" - -#include <utility> -#include <vector> - -#include "base/feature_list.h" -#include "base/location.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_piece.h" -#include "base/threading/thread_task_runner_handle.h" -#include "extensions/common/extension_features.h" -#include "extensions/common/extension_urls.h" -#include "extensions/renderer/dispatcher.h" -#include "extensions/renderer/process_info_native_handler.h" -#include "gin/converter.h" -#include "gin/dictionary.h" -#include "gin/modules/console.h" -#include "gin/modules/timer.h" -#include "mojo/edk/js/core.h" -#include "mojo/edk/js/handle.h" -#include "mojo/edk/js/support.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/system/core.h" - -namespace extensions { -namespace { - -// Natives for the implementation of the unit test version of chrome.test. Calls -// the provided |quit_closure| when either notifyPass or notifyFail is called. -class TestNatives : public gin::Wrappable<TestNatives> { - public: - static gin::Handle<TestNatives> Create(v8::Isolate* isolate, - const base::Closure& quit_closure) { - return gin::CreateHandle(isolate, new TestNatives(quit_closure)); - } - - gin::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override { - return Wrappable<TestNatives>::GetObjectTemplateBuilder(isolate) - .SetMethod("Log", &TestNatives::Log) - .SetMethod("NotifyPass", &TestNatives::NotifyPass) - .SetMethod("NotifyFail", &TestNatives::NotifyFail); - } - - void Log(const std::string& value) { logs_ += value + "\n"; } - void NotifyPass() { FinishTesting(); } - - void NotifyFail(const std::string& message) { - FinishTesting(); - FAIL() << logs_ << message; - } - - void FinishTesting() { - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_); - } - - static gin::WrapperInfo kWrapperInfo; - - private: - explicit TestNatives(const base::Closure& quit_closure) - : quit_closure_(quit_closure) {} - - const base::Closure quit_closure_; - std::string logs_; -}; - -gin::WrapperInfo TestNatives::kWrapperInfo = {gin::kEmbedderNativeGin}; - -} // namespace - -gin::WrapperInfo TestInterfaceProvider::kWrapperInfo = - {gin::kEmbedderNativeGin}; - -gin::Handle<TestInterfaceProvider> TestInterfaceProvider::Create( - v8::Isolate* isolate) { - return gin::CreateHandle(isolate, new TestInterfaceProvider()); -} - -TestInterfaceProvider::~TestInterfaceProvider() { -} - -gin::ObjectTemplateBuilder TestInterfaceProvider::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return Wrappable<TestInterfaceProvider>::GetObjectTemplateBuilder(isolate) - .SetMethod("getInterface", &TestInterfaceProvider::GetInterface); -} - -mojo::Handle TestInterfaceProvider::GetInterface( - const std::string& interface_name) { - EXPECT_EQ(1u, factories_.count(interface_name)) - << "Unregistered interface " << interface_name << " requested."; - mojo::MessagePipe pipe; - std::map<std::string, - base::Callback<void(mojo::ScopedMessagePipeHandle)> >::iterator it = - factories_.find(interface_name); - if (it != factories_.end()) - it->second.Run(std::move(pipe.handle0)); - return pipe.handle1.release(); -} - -TestInterfaceProvider::TestInterfaceProvider() { -} - -// static -void TestInterfaceProvider::IgnoreHandle(mojo::ScopedMessagePipeHandle handle) { -} - -ApiTestEnvironment::ApiTestEnvironment( - ModuleSystemTestEnvironment* environment) { - env_ = environment; - InitializeEnvironment(); - RegisterModules(); -} - -ApiTestEnvironment::~ApiTestEnvironment() { -} - -void ApiTestEnvironment::RegisterModules() { - v8_schema_registry_.reset(new V8SchemaRegistry); - const std::vector<Dispatcher::JsResourceInfo> resources = - Dispatcher::GetJsResources(); - for (const auto& resource : resources) { - if (base::StringPiece(resource.name) != - "test_environment_specific_bindings") { - env()->RegisterModule(resource.name, resource.id, resource.gzipped); - } - } - Dispatcher::RegisterNativeHandlers(env()->module_system(), - env()->context(), - NULL, - NULL, - v8_schema_registry_.get()); - env()->module_system()->RegisterNativeHandler( - "process", std::unique_ptr<NativeHandler>(new ProcessInfoNativeHandler( - env()->context(), env()->context()->GetExtensionID(), - env()->context()->GetContextTypeDescription(), false, - false, 2, false))); - env()->RegisterTestFile("test_environment_specific_bindings", - "unit_test_environment_specific_bindings.js"); - - env()->OverrideNativeHandler("activityLogger", - "exports.$set('LogAPICall', function() {});"); - env()->OverrideNativeHandler( - "apiDefinitions", - "exports.$set('GetExtensionAPIDefinitionsForTest'," - "function() { return [] });"); - env()->OverrideNativeHandler( - "event_natives", - "exports.$set('AttachEvent', function() {});" - "exports.$set('DetachEvent', function() {});" - "exports.$set('AttachFilteredEvent', function() {});" - "exports.$set('AttachFilteredEvent', function() {});" - "exports.$set('MatchAgainstEventFilter', function() { return [] });"); - - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule(env()->isolate(), gin::Console::kModuleName, - gin::Console::GetModule(env()->isolate())); - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule(env()->isolate(), gin::TimerModule::kName, - gin::TimerModule::GetModule(env()->isolate())); - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule(env()->isolate(), mojo::edk::js::Core::kModuleName, - mojo::edk::js::Core::GetModule(env()->isolate())); - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule(env()->isolate(), mojo::edk::js::Support::kModuleName, - mojo::edk::js::Support::GetModule(env()->isolate())); - gin::Handle<TestInterfaceProvider> interface_provider = - TestInterfaceProvider::Create(env()->isolate()); - interface_provider_ = interface_provider.get(); - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule(env()->isolate(), - "content/public/renderer/frame_interfaces", - interface_provider.ToV8()); -} - -void ApiTestEnvironment::InitializeEnvironment() { - // With native bindings, we use the actual bindings system to set up the - // context, so there's no need to provide these stubs. - if (base::FeatureList::IsEnabled(features::kNativeCrxBindings)) - return; - - gin::Dictionary global(env()->isolate(), - env()->context()->v8_context()->Global()); - gin::Dictionary navigator(gin::Dictionary::CreateEmpty(env()->isolate())); - navigator.Set("appVersion", base::StringPiece("")); - global.Set("navigator", navigator); - gin::Dictionary chrome(gin::Dictionary::CreateEmpty(env()->isolate())); - global.Set("chrome", chrome); - gin::Dictionary runtime(gin::Dictionary::CreateEmpty(env()->isolate())); - chrome.Set("runtime", runtime); -} - -void ApiTestEnvironment::RunTest(const std::string& file_name, - const std::string& test_name) { - env()->RegisterTestFile("testBody", file_name); - base::RunLoop run_loop; - gin::ModuleRegistry::From(env()->context()->v8_context())->AddBuiltinModule( - env()->isolate(), - "testNatives", - TestNatives::Create(env()->isolate(), run_loop.QuitClosure()).ToV8()); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&ApiTestEnvironment::RunTestInner, base::Unretained(this), - test_name, run_loop.QuitClosure())); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ApiTestEnvironment::RunPromisesAgain, - base::Unretained(this))); - run_loop.Run(); -} - -void ApiTestEnvironment::RunTestInner(const std::string& test_name, - const base::Closure& quit_closure) { - v8::HandleScope scope(env()->isolate()); - ModuleSystem::NativesEnabledScope natives_enabled(env()->module_system()); - v8::Local<v8::Value> result; - bool did_run = false; - auto callback = [](bool* did_run, const base::Closure& quit_closure, - const std::string& test_name, - const std::vector<v8::Local<v8::Value>>& result) { - *did_run = true; - if (result.empty() || result[0].IsEmpty() || !result[0]->IsTrue()) { - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure); - FAIL() << "Failed to run test \"" << test_name << "\""; - } - }; - - ASSERT_FALSE( - env()->module_system()->Require("testBody").ToLocalChecked().IsEmpty()); - env()->module_system()->CallModuleMethodSafe( - "testBody", test_name, 0, nullptr, - base::Bind(callback, &did_run, quit_closure, test_name)); - ASSERT_TRUE(did_run); -} - -void ApiTestEnvironment::RunPromisesAgain() { - v8::MicrotasksScope::PerformCheckpoint(env()->isolate()); -} - -ApiTestBase::ApiTestBase() { -} - -ApiTestBase::~ApiTestBase() { -} - -void ApiTestBase::SetUp() { - ModuleSystemTest::SetUp(); - test_env_.reset(new ApiTestEnvironment(env())); -} - -void ApiTestBase::RunTest(const std::string& file_name, - const std::string& test_name) { - ExpectNoAssertionsMade(); - test_env_->RunTest(file_name, test_name); -} - -} // namespace extensions
diff --git a/extensions/renderer/api_test_base.h b/extensions/renderer/api_test_base.h deleted file mode 100644 index 6eb8776..0000000 --- a/extensions/renderer/api_test_base.h +++ /dev/null
@@ -1,123 +0,0 @@ -// Copyright 2014 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 EXTENSIONS_RENDERER_API_TEST_BASE_H_ -#define EXTENSIONS_RENDERER_API_TEST_BASE_H_ - -#include <map> -#include <string> -#include <utility> - -#include "base/run_loop.h" -#include "extensions/renderer/module_system_test.h" -#include "extensions/renderer/v8_schema_registry.h" -#include "gin/handle.h" -#include "gin/modules/module_registry.h" -#include "gin/object_template_builder.h" -#include "gin/wrappable.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/system/core.h" - -namespace extensions { - -class V8SchemaRegistry; - -// An InterfaceProvider that provides access from JS modules to interfaces -// registered by AddInterface() calls. -class TestInterfaceProvider : public gin::Wrappable<TestInterfaceProvider> { - public: - static gin::Handle<TestInterfaceProvider> Create(v8::Isolate* isolate); - ~TestInterfaceProvider() override; - - gin::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override; - - template <typename Interface> - void AddInterface( - const base::Callback<void(mojo::InterfaceRequest<Interface>)> - factory_callback) { - factories_.insert(std::make_pair( - Interface::Name_, - base::Bind(ForwardToInterfaceFactory<Interface>, factory_callback))); - } - - // Ignore requests for Interface. - template <typename Interface> - void IgnoreInterfaceRequests() { - factories_.insert(std::make_pair( - Interface::Name_, base::Bind(&TestInterfaceProvider::IgnoreHandle))); - } - - static gin::WrapperInfo kWrapperInfo; - - private: - TestInterfaceProvider(); - - mojo::Handle GetInterface(const std::string& interface_name); - - template <typename Interface> - static void ForwardToInterfaceFactory( - const base::Callback<void(mojo::InterfaceRequest<Interface>)> - factory_callback, - mojo::ScopedMessagePipeHandle handle) { - factory_callback.Run(mojo::InterfaceRequest<Interface>(std::move(handle))); - } - - static void IgnoreHandle(mojo::ScopedMessagePipeHandle handle); - - std::map<std::string, base::Callback<void(mojo::ScopedMessagePipeHandle)> > - factories_; -}; - -// An environment for unit testing apps/extensions API custom bindings -// implemented on Mojo interfaces. This augments a ModuleSystemTestEnvironment -// with a TestInterfaceProvider and other modules available in a real extensions -// environment. -class ApiTestEnvironment { - public: - explicit ApiTestEnvironment(ModuleSystemTestEnvironment* environment); - ~ApiTestEnvironment(); - void RunTest(const std::string& file_name, const std::string& test_name); - TestInterfaceProvider* interface_provider() { return interface_provider_; } - ModuleSystemTestEnvironment* env() { return env_; } - - private: - void RegisterModules(); - void InitializeEnvironment(); - void RunTestInner(const std::string& test_name, - const base::Closure& quit_closure); - void RunPromisesAgain(); - - ModuleSystemTestEnvironment* env_; - TestInterfaceProvider* interface_provider_; - std::unique_ptr<V8SchemaRegistry> v8_schema_registry_; -}; - -// A base class for unit testing apps/extensions API custom bindings implemented -// on Mojo interfaces. To use: -// 1. Register test Mojo interface implementations on interface_provider(). -// 2. Write JS tests in extensions/test/data/test_file.js. -// 3. Write one C++ test function for each JS test containing -// RunTest("test_file.js", "testFunctionName"). -// See extensions/renderer/api_test_base_unittest.cc and -// extensions/test/data/api_test_base_unittest.js for sample usage. -class ApiTestBase : public ModuleSystemTest { - protected: - ApiTestBase(); - ~ApiTestBase() override; - void SetUp() override; - void RunTest(const std::string& file_name, const std::string& test_name); - - ApiTestEnvironment* api_test_env() { return test_env_.get(); } - TestInterfaceProvider* interface_provider() { - return test_env_->interface_provider(); - } - - private: - std::unique_ptr<ApiTestEnvironment> test_env_; -}; - -} // namespace extensions - -#endif // EXTENSIONS_RENDERER_API_TEST_BASE_H_
diff --git a/extensions/renderer/api_test_base_unittest.cc b/extensions/renderer/api_test_base_unittest.cc deleted file mode 100644 index 149e34e..0000000 --- a/extensions/renderer/api_test_base_unittest.cc +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2014 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 "extensions/renderer/api_test_base.h" - -namespace extensions { - -class ApiTestBaseTest : public ApiTestBase { - public: - void SetUp() override { ApiTestBase::SetUp(); } -}; - -TEST_F(ApiTestBaseTest, TestEnvironment) { - RunTest("api_test_base_unittest.js", "testEnvironment"); -} - -TEST_F(ApiTestBaseTest, TestPromisesRun) { - RunTest("api_test_base_unittest.js", "testPromisesRun"); -} - -TEST_F(ApiTestBaseTest, TestCommonModulesAreAvailable) { - RunTest("api_test_base_unittest.js", "testCommonModulesAreAvailable"); -} - -TEST_F(ApiTestBaseTest, TestMojoModulesAreAvailable) { - RunTest("api_test_base_unittest.js", "testMojoModulesAreAvailable"); -} - -TEST_F(ApiTestBaseTest, TestTestBindings) { - RunTest("api_test_base_unittest.js", "testTestBindings"); -} - -} // namespace extensions
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 4e12af83..0773ddf 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -101,7 +101,6 @@ #include "extensions/renderer/worker_script_context_set.h" #include "extensions/renderer/worker_thread_dispatcher.h" #include "gin/converter.h" -#include "mojo/public/js/constants.h" #include "mojo/public/js/grit/mojo_bindings_resources.h" #include "third_party/WebKit/public/platform/WebRuntimeFeatures.h" #include "third_party/WebKit/public/platform/WebString.h" @@ -685,31 +684,6 @@ {"webViewEvents", IDR_WEB_VIEW_EVENTS_JS}, {"webViewInternal", IDR_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS}, - {mojo::kAssociatedBindingsModuleName, IDR_MOJO_ASSOCIATED_BINDINGS_JS}, - {mojo::kBindingsModuleName, IDR_MOJO_BINDINGS_JS_DEPRECATED}, - {mojo::kBufferModuleName, IDR_MOJO_BUFFER_JS}, - {mojo::kCodecModuleName, IDR_MOJO_CODEC_JS}, - {mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS}, - {mojo::kControlMessageHandlerModuleName, - IDR_MOJO_CONTROL_MESSAGE_HANDLER_JS}, - {mojo::kControlMessageProxyModuleName, IDR_MOJO_CONTROL_MESSAGE_PROXY_JS}, - {mojo::kInterfaceControlMessagesMojom, - IDR_MOJO_INTERFACE_CONTROL_MESSAGES_MOJOM_JS}, - {mojo::kInterfaceEndpointClientModuleName, - IDR_MOJO_INTERFACE_ENDPOINT_CLIENT_JS}, - {mojo::kInterfaceEndpointHandleModuleName, - IDR_MOJO_INTERFACE_ENDPOINT_HANDLE_JS}, - {mojo::kInterfaceTypesModuleName, IDR_MOJO_INTERFACE_TYPES_JS}, - {mojo::kPipeControlMessageHandlerModuleName, - IDR_MOJO_PIPE_CONTROL_MESSAGE_HANDLER_JS}, - {mojo::kPipeControlMessageProxyModuleName, - IDR_MOJO_PIPE_CONTROL_MESSAGE_PROXY_JS}, - {mojo::kPipeControlMessagesMojom, - IDR_MOJO_PIPE_CONTROL_MESSAGES_MOJOM_JS}, - {mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS}, - {mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS}, - {mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS}, - {"async_waiter", IDR_ASYNC_WAITER_JS}, {"keep_alive", IDR_KEEP_ALIVE_JS}, {"mojo_bindings", IDR_MOJO_BINDINGS_JS, true}, {"extensions/common/mojo/keep_alive.mojom", IDR_KEEP_ALIVE_MOJOM_JS},
diff --git a/extensions/renderer/module_system.cc b/extensions/renderer/module_system.cc index c71192a0..5dea4bb 100644 --- a/extensions/renderer/module_system.cc +++ b/extensions/renderer/module_system.cc
@@ -24,7 +24,6 @@ #include "extensions/renderer/source_map.h" #include "extensions/renderer/v8_helpers.h" #include "gin/converter.h" -#include "gin/modules/module_registry.h" #include "third_party/WebKit/public/web/WebContextFeatures.h" #include "third_party/WebKit/public/web/WebFrame.h" @@ -169,17 +168,13 @@ context_(context), source_map_(source_map), natives_enabled_(0), - exception_handler_(new DefaultExceptionHandler(context)), - weak_factory_(this) { + exception_handler_(new DefaultExceptionHandler(context)) { RouteFunction( "require", base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); RouteFunction( "requireNative", base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); - RouteFunction( - "requireAsync", - base::Bind(&ModuleSystem::RequireAsync, base::Unretained(this))); RouteFunction("loadScript", base::Bind(&ModuleSystem::LoadScript, base::Unretained(this))); RouteFunction("privates", @@ -190,12 +185,9 @@ SetPrivate(global, kModulesField, v8::Object::New(isolate)); SetPrivate(global, kModuleSystem, v8::External::New(isolate, this)); - gin::ModuleRegistry::From(context->v8_context())->AddObserver(this); if (context_->GetRenderFrame() && context_->context_type() == Feature::BLESSED_EXTENSION_CONTEXT && ContextNeedsMojoBindings(context_)) { - context_->GetRenderFrame()->EnsureMojoBuiltinsAreAvailable( - context->isolate(), context->v8_context()); blink::WebContextFeatures::EnableMojoJS(context->v8_context(), true); } } @@ -631,36 +623,6 @@ return i->second->NewInstance(); } -void ModuleSystem::RequireAsync( - const v8::FunctionCallbackInfo<v8::Value>& args) { - CHECK_EQ(1, args.Length()); - std::string module_name = *v8::String::Utf8Value(args[0]); - v8::Local<v8::Context> v8_context = context_->v8_context(); - v8::Local<v8::Promise::Resolver> resolver( - v8::Promise::Resolver::New(v8_context).ToLocalChecked()); - args.GetReturnValue().Set(resolver->GetPromise()); - std::unique_ptr<v8::Global<v8::Promise::Resolver>> global_resolver( - new v8::Global<v8::Promise::Resolver>(GetIsolate(), resolver)); - gin::ModuleRegistry* module_registry = - gin::ModuleRegistry::From(v8_context); - if (!module_registry) { - Warn(GetIsolate(), "Extension view no longer exists"); - auto maybe = resolver->Reject( - v8_context, - v8::Exception::Error(ToV8StringUnsafe( - GetIsolate(), - "Extension view no longer exists"))); - CHECK(IsTrue(maybe)); - return; - } - module_registry->LoadModule( - GetIsolate(), module_name, - base::Bind(&ModuleSystem::OnModuleLoaded, weak_factory_.GetWeakPtr(), - base::Passed(&global_resolver))); - if (module_registry->available_modules().count(module_name) == 0) - LoadModule(module_name); -} - void ModuleSystem::LoadScript(const v8::FunctionCallbackInfo<v8::Value>& args) { CHECK_EQ(1, args.Length()); std::string module_name = *v8::String::Utf8Value(args[0]); @@ -687,9 +649,9 @@ // Keep in order with the arguments in RequireForJsInner. v8::Local<v8::String> left = ToV8StringUnsafe( GetIsolate(), - "(function(define, require, requireNative, requireAsync, loadScript, " - "exports, console, privates, apiBridge, bindingUtil, getInternalApi," - "$Array, $Function, $JSON, $Object, $RegExp, $String, $Error) {" + "(function(require, requireNative, loadScript, exports, console, " + "privates, apiBridge, bindingUtil, getInternalApi, $Array, $Function, " + "$JSON, $Object, $RegExp, $String, $Error) {" "'use strict';"); v8::Local<v8::String> right = ToV8StringUnsafe(GetIsolate(), "\n})"); return handle_scope.Escape(v8::Local<v8::String>( @@ -759,9 +721,6 @@ v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(func_as_value); - v8::Local<v8::Object> define_object = v8::Object::New(GetIsolate()); - gin::ModuleRegistry::InstallGlobals(GetIsolate(), define_object); - v8::Local<v8::Object> exports = v8::Object::New(GetIsolate()); v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New( @@ -810,15 +769,11 @@ // These must match the argument order in WrapSource. v8::Local<v8::Value> args[] = { - // AMD. - GetPropertyUnsafe(v8_context, define_object, "define"), // CommonJS. GetPropertyUnsafe(v8_context, natives, "require", v8::NewStringType::kInternalized), GetPropertyUnsafe(v8_context, natives, "requireNative", v8::NewStringType::kInternalized), - GetPropertyUnsafe(v8_context, natives, "requireAsync", - v8::NewStringType::kInternalized), GetPropertyUnsafe(v8_context, natives, "loadScript", v8::NewStringType::kInternalized), exports, @@ -850,39 +805,6 @@ return handle_scope.Escape(exports); } -void ModuleSystem::OnDidAddPendingModule( - const std::string& id, - const std::vector<std::string>& dependencies) { - bool module_system_managed = source_map_->Contains(id); - - gin::ModuleRegistry* registry = - gin::ModuleRegistry::From(context_->v8_context()); - DCHECK(registry); - for (const auto& dependency : dependencies) { - // If a dependency is not available, and either the module or this - // dependency is managed by ModuleSystem, attempt to load it. Other - // gin::ModuleRegistry users (WebUI and users of the mojoPrivate API) are - // responsible for loading their module dependencies when required. - if (registry->available_modules().count(dependency) == 0 && - (module_system_managed || source_map_->Contains(dependency))) { - LoadModule(dependency); - } - } - registry->AttemptToLoadMoreModules(GetIsolate()); -} - -void ModuleSystem::OnModuleLoaded( - std::unique_ptr<v8::Global<v8::Promise::Resolver>> resolver, - v8::Local<v8::Value> value) { - if (!is_valid()) - return; - v8::HandleScope handle_scope(GetIsolate()); - v8::Local<v8::Promise::Resolver> resolver_local( - v8::Local<v8::Promise::Resolver>::New(GetIsolate(), *resolver)); - auto maybe = resolver_local->Resolve(context()->v8_context(), value); - CHECK(IsTrue(maybe)); -} - void ModuleSystem::ClobberExistingNativeHandler(const std::string& name) { NativeHandlerMap::iterator existing_handler = native_handler_map_.find(name); if (existing_handler != native_handler_map_.end()) {
diff --git a/extensions/renderer/module_system.h b/extensions/renderer/module_system.h index e941616..b7844b1 100644 --- a/extensions/renderer/module_system.h +++ b/extensions/renderer/module_system.h
@@ -17,7 +17,6 @@ #include "extensions/renderer/native_handler.h" #include "extensions/renderer/object_backed_native_handler.h" #include "extensions/renderer/script_injection_callback.h" -#include "gin/modules/module_registry_observer.h" #include "v8/include/v8.h" namespace extensions { @@ -41,10 +40,7 @@ // Note that a ModuleSystem must be used only in conjunction with a single // v8::Context. // TODO(koz): Rename this to JavaScriptModuleSystem. -// TODO(yzshen): crbug.com/718047 Remove all gin-related things. Mojo no longer -// relies on gin. -class ModuleSystem : public ObjectBackedNativeHandler, - public gin::ModuleRegistryObserver { +class ModuleSystem : public ObjectBackedNativeHandler { public: class ExceptionHandler { public: @@ -212,10 +208,6 @@ const std::string& native_name); void RequireNative(const v8::FunctionCallbackInfo<v8::Value>& args); - // Return a promise for a requested module. - // |args[0]| - the name of a module. - void RequireAsync(const v8::FunctionCallbackInfo<v8::Value>& args); - // |args[0]| - the name of a module. // This method directly executes the script in the current scope. void LoadScript(const v8::FunctionCallbackInfo<v8::Value>& args); @@ -232,17 +224,6 @@ const std::string& module_name, v8::Local<v8::Value> api_object); - // Invoked when a module is loaded in response to a requireAsync call. - // Resolves |resolver| with |value|. - void OnModuleLoaded( - std::unique_ptr<v8::Global<v8::Promise::Resolver>> resolver, - v8::Local<v8::Value> value); - - // gin::ModuleRegistryObserver overrides. - void OnDidAddPendingModule( - const std::string& id, - const std::vector<std::string>& dependencies) override; - // Marks any existing NativeHandler named |name| as clobbered. // See |clobbered_native_handlers_|. void ClobberExistingNativeHandler(const std::string& name); @@ -287,8 +268,6 @@ // The set of modules that we've attempted to load. std::set<std::string> loaded_modules_; - base::WeakPtrFactory<ModuleSystem> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(ModuleSystem); };
diff --git a/extensions/renderer/module_system_unittest.cc b/extensions/renderer/module_system_unittest.cc index 071be3f9..52f895e 100644 --- a/extensions/renderer/module_system_unittest.cc +++ b/extensions/renderer/module_system_unittest.cc
@@ -10,7 +10,6 @@ #include <utility> #include "extensions/renderer/module_system_test.h" -#include "gin/modules/module_registry.h" namespace extensions { @@ -279,232 +278,6 @@ env()->module_system()->Require("test"); } -TEST_F(ModuleSystemTest, TestRequireAsync) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule("add", - "define('add', [], function() {" - " return { Add: function(x, y) { return x + y; } };" - "});"); - env()->RegisterModule("math", - "define('math', ['add'], function(add) {" - " return { Add: add.Add };" - "});"); - env()->RegisterModule( - "test", - "requireAsync('math').then(function(math) {" - " requireNative('assert').AssertTrue(math.Add(3, 5) == 8);" - "});"); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - -TEST_F(ModuleSystemTest, TestRequireAsyncInParallel) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule("add", - "define('add', [], function() {" - " return { Add: function(x, y) { return x + y; } };" - "});"); - env()->RegisterModule( - "subtract", - "define('subtract', [], function() {" - " return { Subtract: function(x, y) { return x - y; } };" - "});"); - env()->RegisterModule( - "math", - "exports.$set('AddAndSubtract', function(x, y, z) {" - " return Promise.all([requireAsync('add')," - " requireAsync('subtract')" - " ]).then(function(modules) {" - " return modules[1].Subtract(modules[0].Add(x, y), z);" - " });" - "});"); - env()->RegisterModule("test", - "var AddAndSubtract = require('math').AddAndSubtract;" - "AddAndSubtract(3, 5, 2).then(function(result) {" - " requireNative('assert').AssertTrue(result == 6);" - "});"); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - -TEST_F(ModuleSystemTest, TestNestedRequireAsyncs) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule("first", - "define('first', [], function() {" - " return { next: 'second' };" - "});"); - env()->RegisterModule("second", - "define('second', [], function() {" - " return { next: '' };" - "});"); - env()->RegisterModule( - "test", - "requireAsync('first').then(function(module) {" - " return requireAsync(module.next)" - "}).then(function(module) {" - " requireNative('assert').AssertTrue(module.next === '');" - "});"); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - -TEST_F(ModuleSystemTest, TestRequireFromAMDModule) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule( - "add", "exports.$set('Add', function(x, y) { return x + y; });"); - env()->RegisterModule("math", - "define('math', [], function() {" - " var add = require('add');" - " return { Add: add.Add };" - "});"); - env()->RegisterModule( - "test", - "requireAsync('math').then(function(math) {" - " requireNative('assert').AssertTrue(math.Add(3, 5) == 8);" - "});"); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - -TEST_F(ModuleSystemTest, TestRequireAsyncFromAMDModule) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule("add", - "define('add', [], function() {" - " return { Add: function(x, y) { return x + y; } };" - "});"); - env()->RegisterModule("math", - "define('math', [], function() {" - " function Add(x, y) {" - " return requireAsync('add').then(function(add) {" - " return add.Add(x, y);" - " });" - " }" - " return { Add: Add };" - "});"); - env()->RegisterModule("test", - "requireAsync('math').then(function(math) {" - " return math.Add(3, 6);" - "}).then(function(result) {" - " requireNative('assert').AssertTrue(result == 9);" - "});"); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - -TEST_F(ModuleSystemTest, TestRequireAsyncFromAnotherContext) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule( - "test", - "requireAsync('natives').then(function(natives) {" - " natives.requireAsync('ping').then(function(ping) {" - " return ping();" - " }).then(function(result) {" - " requireNative('assert').AssertTrue(result == 'pong');" - " });" - "});"); - std::unique_ptr<ModuleSystemTestEnvironment> other_env = CreateEnvironment(); - other_env->RegisterModule("ping", - "define('ping', ['natives'], function(natives) {" - " return function() {" - " return 'pong';" - " }" - "});"); - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule( - env()->isolate(), "natives", - other_env->module_system()->NewInstance()); - gin::ModuleRegistry::From(other_env->context()->v8_context()) - ->AddBuiltinModule( - env()->isolate(), "natives", - env()->module_system()->NewInstance()); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - -TEST_F(ModuleSystemTest, TestRequireAsyncBetweenContexts) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule("pong", - "define('pong', [], function() {" - " return function() { return 'done'; };" - "});"); - env()->RegisterModule( - "test", - "requireAsync('natives').then(function(natives) {" - " natives.requireAsync('ping').then(function(ping) {" - " return ping();" - " }).then(function(pong) {" - " return pong();" - " }).then(function(result) {" - " requireNative('assert').AssertTrue(result == 'done');" - " });" - "});"); - std::unique_ptr<ModuleSystemTestEnvironment> other_env = CreateEnvironment(); - other_env->RegisterModule("ping", - "define('ping', ['natives'], function(natives) {" - " return function() {" - " return natives.requireAsync('pong');" - " }" - "});"); - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule( - env()->isolate(), "natives", - other_env->module_system()->NewInstance()); - gin::ModuleRegistry::From(other_env->context()->v8_context()) - ->AddBuiltinModule( - env()->isolate(), "natives", - env()->module_system()->NewInstance()); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - -TEST_F(ModuleSystemTest, TestRequireAsyncFromContextWithNoModuleRegistry) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule("test", - "requireAsync('natives').then(function(natives) {" - " var AssertTrue = requireNative('assert').AssertTrue;" - " natives.requireAsync('foo').then(function() {" - " AssertTrue(false);" - " }).catch(function(error) {" - " AssertTrue(error.message == " - " 'Extension view no longer exists');" - " });" - "});"); - std::unique_ptr<ModuleSystemTestEnvironment> other_env = CreateEnvironment(); - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule( - env()->isolate(), "natives", - other_env->module_system()->NewInstance()); - other_env->ShutdownGin(); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - -TEST_F(ModuleSystemTest, TestRequireAsyncFromContextWithNoModuleSystem) { - ModuleSystem::NativesEnabledScope natives_enabled_scope( - env()->module_system()); - env()->RegisterModule("test", - "requireAsync('natives').then(function(natives) {" - " requireNative('assert').AssertTrue(" - " natives.requireAsync('foo') === undefined);" - "});"); - std::unique_ptr<ModuleSystemTestEnvironment> other_env = CreateEnvironment(); - gin::ModuleRegistry::From(env()->context()->v8_context()) - ->AddBuiltinModule( - env()->isolate(), "natives", - other_env->module_system()->NewInstance()); - other_env->ShutdownModuleSystem(); - env()->module_system()->Require("test"); - RunResolvedPromises(); -} - TEST_F(ModuleSystemTest, TestPrivatesIsPrivate) { ModuleSystem::NativesEnabledScope natives_enabled_scope( env()->module_system());
diff --git a/extensions/renderer/resources/async_waiter.js b/extensions/renderer/resources/async_waiter.js deleted file mode 100644 index 6470f64b..0000000 --- a/extensions/renderer/resources/async_waiter.js +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2014 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. - -define('async_waiter', [ - 'mojo/public/js/support', -], function(supportModule) { - /** - * @module async_waiter - */ - - /** - * @callback module:async_waiter.AsyncWaiter.Callback - * @param {number} result The result of waiting. - */ - - /** - * A waiter that waits for a handle to be ready for either reading or writing. - * @param {!MojoHandle} handle The handle to wait on. - * @param {number} signals The signals to wait for handle to be ready for. - * @param {module:async_waiter.AsyncWaiter.Callback} callback The callback to - * call when handle is ready. - * @constructor - * @alias module:async_waiter.AsyncWaiter - */ - function AsyncWaiter(handle, signals, callback) { - /** - * The handle to wait on. - * @type {!MojoHandle} - * @private - */ - this.handle_ = handle; - - /** - * The signals to wait for. - * @type {number} - * @private - */ - this.signals_ = signals; - - /** - * The callback to invoke when - * |[handle_]{@link module:async_waiter.AsyncWaiter#handle_}| is ready. - * @type {module:async_waiter.AsyncWaiter.Callback} - * @private - */ - this.callback_ = callback; - this.id_ = null; - } - - /** - * Start waiting for the handle to be ready. - * @throws Will throw if this is already waiting. - */ - AsyncWaiter.prototype.start = function() { - if (this.id_) - throw new Error('Already started'); - this.id_ = supportModule.asyncWait( - this.handle_, this.signals_, this.onHandleReady_.bind(this)); - }; - - /** - * Stop waiting for the handle to be ready. - */ - AsyncWaiter.prototype.stop = function() { - if (!this.id_) - return; - - supportModule.cancelWait(this.id_); - this.id_ = null; - }; - - /** - * Returns whether this {@link AsyncWaiter} is waiting. - * @return {boolean} Whether this AsyncWaiter is waiting. - */ - AsyncWaiter.prototype.isWaiting = function() { - return !!this.id_; - }; - - /** - * Invoked when |[handle_]{@link module:async_waiter.AsyncWaiter#handle_}| is - * ready. - * @param {number} result The result of the wait. - * @private - */ - AsyncWaiter.prototype.onHandleReady_ = function(result) { - this.id_ = null; - this.callback_(result); - }; - - return {AsyncWaiter: AsyncWaiter}; -});
diff --git a/extensions/renderer/resources/extensions_renderer_resources.grd b/extensions/renderer/resources/extensions_renderer_resources.grd index 01f1a14..e06a844 100644 --- a/extensions/renderer/resources/extensions_renderer_resources.grd +++ b/extensions/renderer/resources/extensions_renderer_resources.grd
@@ -10,7 +10,6 @@ <includes> <!-- Extension libraries. --> <include name="IDR_APP_VIEW_JS" file="guest_view/app_view/app_view.js" type="BINDATA" /> - <include name="IDR_ASYNC_WAITER_JS" file="async_waiter.js" type="BINDATA" /> <include name="IDR_BROWSER_TEST_ENVIRONMENT_SPECIFIC_BINDINGS_JS" file="browser_test_environment_specific_bindings.js" type="BINDATA" /> <include name="IDR_ENTRY_ID_MANAGER" file="entry_id_manager.js" type="BINDATA" /> <include name="IDR_EVENT_BINDINGS_JS" file="event.js" type="BINDATA" /> @@ -85,26 +84,6 @@ <!-- Extension styles. --> <include name="IDR_EXTENSION_FONTS_CSS" file="extension_fonts.css" type="BINDATA"/> - - <!-- Old Mojo JS bindings library. --> - <include name="IDR_MOJO_ASSOCIATED_BINDINGS_JS" file="../../../mojo/public/js/associated_bindings.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_BINDINGS_JS_DEPRECATED" file="../../../mojo/public/js/bindings.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_BUFFER_JS" file="../../../mojo/public/js/buffer.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_CODEC_JS" file="../../../mojo/public/js/codec.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_CONNECTOR_JS" file="../../../mojo/public/js/connector.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_CONTROL_MESSAGE_HANDLER_JS" file="../../../mojo/public/js/lib/control_message_handler.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_CONTROL_MESSAGE_PROXY_JS" file="../../../mojo/public/js/lib/control_message_proxy.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_INTERFACE_CONTROL_MESSAGES_MOJOM_JS" file="${mojom_root}/mojo/public/interfaces/bindings/interface_control_messages.mojom.js" use_base_dir="false" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_PIPE_CONTROL_MESSAGES_MOJOM_JS" file="${mojom_root}/mojo/public/interfaces/bindings/pipe_control_messages.mojom.js" use_base_dir="false" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_INTERFACE_TYPES_JS" file="../../../mojo/public/js/interface_types.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_ROUTER_JS" file="../../../mojo/public/js/router.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_UNICODE_JS" file="../../../mojo/public/js/unicode.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_VALIDATOR_JS" file="../../../mojo/public/js/validator.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_INTERFACE_ENDPOINT_CLIENT_JS" file="../../../mojo/public/js/lib/interface_endpoint_client.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_INTERFACE_ENDPOINT_HANDLE_JS" file="../../../mojo/public/js/lib/interface_endpoint_handle.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_PIPE_CONTROL_MESSAGE_HANDLER_JS" file="../../../mojo/public/js/lib/pipe_control_message_handler.js" flattenhtml="true" type="BINDATA" /> - <include name="IDR_MOJO_PIPE_CONTROL_MESSAGE_PROXY_JS" file="../../../mojo/public/js/lib/pipe_control_message_proxy.js" flattenhtml="true" type="BINDATA" /> - </includes> <structures> <!-- Extension styles. -->
diff --git a/extensions/test/data/api_test_base_unittest.js b/extensions/test/data/api_test_base_unittest.js deleted file mode 100644 index 334b938..0000000 --- a/extensions/test/data/api_test_base_unittest.js +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2014 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. - -var test = requireNative('apiGetter').get('test'); -var unittestBindings = require('test_environment_specific_bindings'); - -unittestBindings.exportTests([ - function testEnvironment() { - test.assertTrue(!!$Array); - test.assertTrue(!!$Function); - test.assertTrue(!!$JSON); - test.assertTrue(!!$Object); - test.assertTrue(!!$RegExp); - test.assertTrue(!!$String); - test.assertTrue(!!privates); - test.assertTrue(!!define); - test.assertTrue(!!require); - test.assertTrue(!!requireNative); - test.assertTrue(!!requireAsync); - test.assertEq(undefined, chrome.runtime.lastError); - // chrome.extension is defined at the //chrome layer, and so won't be - // available. - test.assertEq(undefined, chrome.extension); - test.succeed(); - }, - function testPromisesRun() { - Promise.resolve().then(test.callbackPass()); - }, - function testCommonModulesAreAvailable() { - var binding = bindingUtil || require('binding'); - var sendRequest = - bindingUtil ? bindingUtil.sendRequest : require('sendRequest'); - var lastError = - bindingUtil ? bindingUtil.setLastError : require('lastError'); - test.assertTrue(!!binding); - test.assertTrue(!!sendRequest); - test.assertTrue(!!lastError); - test.succeed(); - }, - function testMojoModulesAreAvailable() { - Promise.all([ - requireAsync('mojo/public/js/bindings'), - requireAsync('mojo/public/js/core'), - requireAsync('content/public/renderer/frame_interfaces'), - ]).then(test.callback(function(modules) { - var bindings = modules[0]; - var core = modules[1]; - var frameInterfaces = modules[2]; - test.assertTrue(!!bindings.Binding); - test.assertTrue(!!core.createMessagePipe); - test.assertTrue(!!frameInterfaces.getInterface); - })); - }, - function testTestBindings() { - var counter = 0; - function increment() { - counter++; - } - test.runWithUserGesture(increment); - test.runWithoutUserGesture(increment); - test.assertEq(2, counter); - test.assertFalse(test.isProcessingUserGesture()); - test.assertTrue(!!test.getApiFeatures()); - test.assertEq(0, test.getApiDefinitions().length); - test.succeed(); - } -], test.runTests, exports);
diff --git a/extensions/test/data/mojo_private_unittest.js b/extensions/test/data/mojo_private_unittest.js deleted file mode 100644 index cfdc9db..0000000 --- a/extensions/test/data/mojo_private_unittest.js +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -'use strict'; - -let getApi = requireNative('apiGetter').get; -let mojoPrivate = getApi('mojoPrivate'); -let test = getApi('test'); -let unittestBindings = require('test_environment_specific_bindings'); - -unittestBindings.exportTests([ - function testRequireAsync() { - mojoPrivate.requireAsync('add').then( - test.callbackPass(function(add) { - test.assertEq('function', typeof add); - })); - }, -], test.runTests, exports);
diff --git a/extensions/test/data/unit_test_environment_specific_bindings.js b/extensions/test/data/unit_test_environment_specific_bindings.js deleted file mode 100644 index e8d03dcc..0000000 --- a/extensions/test/data/unit_test_environment_specific_bindings.js +++ /dev/null
@@ -1,145 +0,0 @@ -// Copyright 2014 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. - -var sendRequestNatives = requireNative('sendRequest'); - -function registerHooks(api) { - var apiFunctions = api.apiFunctions; - - apiFunctions.setHandleRequest('notifyPass', function() { - requireAsync('testNatives').then(function(natives) { - natives.NotifyPass(); - }); - }); - - apiFunctions.setHandleRequest('notifyFail', function(message) { - requireAsync('testNatives').then(function(natives) { - natives.NotifyFail(message); - }); - }); - - apiFunctions.setHandleRequest('log', function() { - requireAsync('testNatives').then(function(natives) { - natives.Log($Array.join(arguments, ' ')); - }); - }); - -} - -function testDone(runNextTest) { - // Use a promise here to allow previous test contexts to be eligible for - // garbage collection. - Promise.resolve().then(function() { - runNextTest(); - }); -} - -function exportTests(tests, runTests, exports) { - $Array.forEach(tests, function(test) { - exports[test.name] = function() { - runTests([test]); - return true; - }; - }); -} - -/** - * A fake implementation of setTimeout and clearTimeout. - * @constructor - */ -function TimeoutManager() { - this.timeouts_ = {}; - this.nextTimeoutId_ = 0; - this.currentTime = 0; - this.autorunEnabled_ = false; -} - -/** - * Installs setTimeout and clearTimeout into the global object. - */ -TimeoutManager.prototype.installGlobals = function() { - var global = sendRequestNatives.GetGlobal({}); - global.setTimeout = this.setTimeout_.bind(this); - global.clearTimeout = this.clearTimeout_.bind(this); -}; - -/** - * Starts auto-running of timeout callbacks. Until |numCallbacksToRun| callbacks - * have run, any timeout callbacks set by calls to setTimeout (including before - * the call to run) will cause the currentTime to be advanced to the time of - * the timeout. - */ -TimeoutManager.prototype.run = function(numCallbacksToRun) { - this.numCallbacksToRun_ = numCallbacksToRun; - Promise.resolve().then(this.autoRun_.bind(this)); -}; - -/** - * Runs timeout callbacks with earliest timeout. - * @private - */ -TimeoutManager.prototype.autoRun_ = function() { - if (this.numCallbacksToRun_ <= 0 || $Object.keys(this.timeouts_).length == 0) - return; - - // Bucket the timeouts by their timeout time. - var timeoutsByTimeout = {}; - var timeoutIds = $Object.keys(this.timeouts_); - for (var i = 0; i < timeoutIds.length; i++) { - var timeout = this.timeouts_[timeoutIds[i]]; - var timeMs = timeout.timeMs; - if (!timeoutsByTimeout[timeMs]) - timeoutsByTimeout[timeMs] = []; - timeoutsByTimeout[timeMs].push(timeout); - } - this.currentTime = - $Function.apply(Math.min, null, $Object.keys((timeoutsByTimeout))); - // Run all timeouts in the earliest timeout bucket. - var timeouts = timeoutsByTimeout[this.currentTime]; - for (var i = 0; i < timeouts.length; i++) { - var currentTimeout = timeouts[i]; - if (!this.timeouts_[currentTimeout.id]) - continue; - this.numCallbacksToRun_--; - delete this.timeouts_[currentTimeout.id]; - try { - currentTimeout.target(); - } catch (e) { - console.log('error calling timeout target ' + e.stack); - } - } - // Continue running any later callbacks. - Promise.resolve().then(this.autoRun_.bind(this)); -}; - -/** - * A fake implementation of setTimeout. This does not support passing callback - * arguments. - * @private - */ -TimeoutManager.prototype.setTimeout_ = function(target, timeoutMs) { - var timeoutId = this.nextTimeoutId_++; - this.timeouts_[timeoutId] = { - id: timeoutId, - target: target, - timeMs: timeoutMs + this.currentTime, - }; - if (this.autorunEnabled_) - Promise.resolve().then(this.autoRun_.bind(this)); - return timeoutId; -}; - -/** - * A fake implementation of clearTimeout. - * @private - */ -TimeoutManager.prototype.clearTimeout_ = function(timeoutId) { - if (this.timeouts_[timeoutId]) - delete this.timeouts_[timeoutId]; -}; - -exports.registerHooks = registerHooks; -exports.testDone = testDone; -exports.exportTests = exportTests; -exports.TimeoutManager = TimeoutManager;
diff --git a/gpu/ipc/client/gpu_in_process_context_tests.cc b/gpu/ipc/client/gpu_in_process_context_tests.cc index dba3e7e..e0c7349b 100644 --- a/gpu/ipc/client/gpu_in_process_context_tests.cc +++ b/gpu/ipc/client/gpu_in_process_context_tests.cc
@@ -36,15 +36,16 @@ attributes.bind_generates_resource = false; auto context = gpu::GLInProcessContext::CreateWithoutInit(); - auto result = context->Initialize(nullptr, /* service */ - nullptr, /* surface */ - true, /* offscreen */ - gpu::kNullSurfaceHandle, /* window */ - nullptr, /* share_context */ - attributes, gpu::SharedMemoryLimits(), - gpu_memory_buffer_manager_.get(), - nullptr, /* image_factory */ - base::ThreadTaskRunnerHandle::Get()); + auto result = context->Initialize( + nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gpu::kNullSurfaceHandle, /* window */ + nullptr, /* share_context */ + attributes, gpu::SharedMemoryLimits(), gpu_memory_buffer_manager_.get(), + nullptr, /* image_factory */ + nullptr /* gpu_channel_manager_delegate */, + base::ThreadTaskRunnerHandle::Get()); DCHECK_EQ(result, gpu::ContextResult::kSuccess); return context; }
diff --git a/gpu/ipc/gl_in_process_context.cc b/gpu/ipc/gl_in_process_context.cc index 0f65c60c..a983202 100644 --- a/gpu/ipc/gl_in_process_context.cc +++ b/gpu/ipc/gl_in_process_context.cc
@@ -63,6 +63,7 @@ const SharedMemoryLimits& mem_limits, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory, + GpuChannelManagerDelegate* gpu_channel_manager_delegate, scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; const gpu::Capabilities& GetCapabilities() const override; const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override; @@ -157,6 +158,7 @@ const SharedMemoryLimits& mem_limits, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory, + GpuChannelManagerDelegate* gpu_channel_manager_delegate, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { // If a surface is provided, we are running in a webview and should not have // a task runner. We must have a task runner in all other cases. @@ -183,7 +185,8 @@ auto result = command_buffer_->Initialize( surface, is_offscreen, window, attribs, share_command_buffer, - gpu_memory_buffer_manager, image_factory, std::move(task_runner)); + gpu_memory_buffer_manager, image_factory, gpu_channel_manager_delegate, + std::move(task_runner)); if (result != gpu::ContextResult::kSuccess) { DLOG(ERROR) << "Failed to initialize InProcessCommmandBuffer"; return result;
diff --git a/gpu/ipc/gl_in_process_context.h b/gpu/ipc/gl_in_process_context.h index a21556e..d160b8da 100644 --- a/gpu/ipc/gl_in_process_context.h +++ b/gpu/ipc/gl_in_process_context.h
@@ -11,8 +11,8 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "base/single_thread_task_runner.h" -#include "gl_in_process_context_export.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/ipc/gl_in_process_context_export.h" #include "gpu/ipc/in_process_command_buffer.h" #include "ui/gfx/native_widget_types.h" #include "ui/gl/gl_surface.h" @@ -36,13 +36,14 @@ static std::unique_ptr<GLInProcessContext> CreateWithoutInit(); // Initialize the GLInProcessContext, if |is_offscreen| is true, renders to an - // offscreen context. |attrib_list| must be NULL or a NONE-terminated list + // offscreen context. |attrib_list| must be null or a NONE-terminated list // of attribute/value pairs. - // If |surface| is not NULL, then it must match |is_offscreen|, + // If |surface| is not null, then it must match |is_offscreen|, // |window| must be gfx::kNullAcceleratedWidget, and the command buffer // service must run on the same thread as this client because GLSurface is - // not thread safe. If |surface| is NULL, then the other parameters are used + // not thread safe. If |surface| is null, then the other parameters are used // to correctly create a surface. + // |gpu_channel_manager| should be non-null when used in the GPU process. virtual gpu::ContextResult Initialize( scoped_refptr<gpu::InProcessCommandBuffer::Service> service, scoped_refptr<gl::GLSurface> surface, @@ -53,6 +54,7 @@ const SharedMemoryLimits& memory_limits, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory, + GpuChannelManagerDelegate* gpu_channel_manager_delegate, scoped_refptr<base::SingleThreadTaskRunner> task_runner) = 0; virtual const gpu::Capabilities& GetCapabilities() const = 0;
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 2f87686..6fd2adb 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc
@@ -47,6 +47,7 @@ #include "gpu/config/gpu_crash_keys.h" #include "gpu/config/gpu_feature_info.h" #include "gpu/ipc/gpu_in_process_thread_service.h" +#include "gpu/ipc/service/gpu_channel_manager_delegate.h" #include "gpu/ipc/service/image_transport_surface.h" #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_context.h" @@ -189,17 +190,6 @@ const scoped_refptr<Service>& service) : command_buffer_id_(CommandBufferId::FromUnsafeValue( g_next_command_buffer_id.GetNext() + 1)), - delayed_work_pending_(false), - image_factory_(nullptr), - snapshot_requested_(false), - gpu_control_client_(nullptr), -#if DCHECK_IS_ON() - context_lost_(false), -#endif - last_put_offset_(-1), - gpu_memory_buffer_manager_(nullptr), - next_fence_sync_release_(1), - flushed_fence_sync_release_(0), flush_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), service_(GetInitialService(service)), @@ -251,9 +241,13 @@ InProcessCommandBuffer* share_group, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory, + GpuChannelManagerDelegate* gpu_channel_manager_delegate, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { DCHECK(!share_group || service_.get() == share_group->service_.get()); + gpu_memory_buffer_manager_ = gpu_memory_buffer_manager; + gpu_channel_manager_delegate_ = gpu_channel_manager_delegate; + if (surface) { // If a surface is provided, we are running in a webview and should not have // a task runner. @@ -285,8 +279,6 @@ &result, &completion)); completion.Wait(); - gpu_memory_buffer_manager_ = gpu_memory_buffer_manager; - if (result == gpu::ContextResult::kSuccess) capabilities_ = capabilities; @@ -1036,7 +1028,15 @@ void InProcessCommandBuffer::DidCreateAcceleratedSurfaceChildWindow( SurfaceHandle parent_window, SurfaceHandle child_window) { - ::SetParent(child_window, parent_window); + // In the browser process call ::SetParent() directly. + if (!gpu_channel_manager_delegate_) { + ::SetParent(child_window, parent_window); + return; + } + + // In the GPU process forward the request back to the browser process. + gpu_channel_manager_delegate_->SendAcceleratedSurfaceCreatedChildWindow( + parent_window, child_window); } #endif
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h index 1d2cd3fab..9067cb6b 100644 --- a/gpu/ipc/in_process_command_buffer.h +++ b/gpu/ipc/in_process_command_buffer.h
@@ -72,6 +72,7 @@ class ShaderTranslatorCache; } +class GpuChannelManagerDelegate; class GpuMemoryBufferManager; class ImageFactory; class TransferBufferManager; @@ -94,6 +95,8 @@ // If |surface| is not null, use it directly; in this case, the command // buffer gpu thread must be the same as the client thread. Otherwise create // a new GLSurface. + // |gpu_channel_manager_delegate| should be non-null when the command buffer + // is used in the GPU process for compositor to gpu thread communication. gpu::ContextResult Initialize( scoped_refptr<gl::GLSurface> surface, bool is_offscreen, @@ -102,6 +105,7 @@ InProcessCommandBuffer* share_group, GpuMemoryBufferManager* gpu_memory_buffer_manager, ImageFactory* image_factory, + GpuChannelManagerDelegate* gpu_channel_manager_delegate, scoped_refptr<base::SingleThreadTaskRunner> task_runner); // CommandBuffer implementation: @@ -339,24 +343,25 @@ scoped_refptr<SyncPointClientState> sync_point_client_state_; base::Closure context_lost_callback_; // Used to throttle PerformDelayedWorkOnGpuThread. - bool delayed_work_pending_; - ImageFactory* image_factory_; + bool delayed_work_pending_ = false; + ImageFactory* image_factory_ = nullptr; + GpuChannelManagerDelegate* gpu_channel_manager_delegate_ = nullptr; base::Closure snapshot_requested_callback_; - bool snapshot_requested_; + bool snapshot_requested_ = false; // Members accessed on the client thread: - GpuControlClient* gpu_control_client_; + GpuControlClient* gpu_control_client_ = nullptr; #if DCHECK_IS_ON() - bool context_lost_; + bool context_lost_ = false; #endif State last_state_; base::Lock last_state_lock_; - int32_t last_put_offset_; + int32_t last_put_offset_ = -1; Capabilities capabilities_; - GpuMemoryBufferManager* gpu_memory_buffer_manager_; - uint64_t next_fence_sync_release_; - uint64_t flushed_fence_sync_release_; + GpuMemoryBufferManager* gpu_memory_buffer_manager_ = nullptr; + uint64_t next_fence_sync_release_ = 1; + uint64_t flushed_fence_sync_release_ = 0; // Accessed on both threads: std::unique_ptr<CommandBufferService> command_buffer_;
diff --git a/headless/test/headless_render_browsertest.cc b/headless/test/headless_render_browsertest.cc index dac8b52..a8759c0 100644 --- a/headless/test/headless_render_browsertest.cc +++ b/headless/test/headless_render_browsertest.cc
@@ -139,6 +139,10 @@ return arg.second == expected; } +MATCHER_P(CookieValue, expected, "") { + return arg->GetValue() == expected; +} + const DOMNode* FindTag(const GetSnapshotResult* snapshot, const char* name) { auto tags = FindTags(snapshot, name); if (tags.empty()) @@ -875,4 +879,112 @@ }; HEADLESS_RENDER_BROWSERTEST(RedirectNewFragment); +class WindowLocationFragments : public HeadlessRenderTest { + private: + GURL GetPageUrl(HeadlessDevToolsClient* client) override { + GetProtocolHandler()->InsertResponse("http://www.example.com/#fragment1", + HttpOk(R"|( + <script> + if (window.location.hash == '#fragment1') { + document.write('<iframe src="iframe#fragment2"></iframe>'); + } + </script>)|")); + GetProtocolHandler()->InsertResponse( + "http://www.example.com/iframe#fragment2", HttpOk(R"|( + <script> + if (window.location.hash == '#fragment2') { + document.location = 'http://www.example.com/pass'; + } + </script>)|")); + GetProtocolHandler()->InsertResponse("http://www.example.com/pass", + HttpOk("<p>Pass</p>")); + return GURL("http://www.example.com/#fragment1"); + } + + void VerifyDom(GetSnapshotResult* dom_snapshot) override { + EXPECT_THAT(GetProtocolHandler()->urls_requested(), + ElementsAre("http://www.example.com/#fragment1", + "http://www.example.com/iframe#fragment2", + "http://www.example.com/pass")); + EXPECT_THAT(NextNode(dom_snapshot, FindTag(dom_snapshot, "P")), + NodeValue("Pass")); + } +}; +HEADLESS_RENDER_BROWSERTEST(WindowLocationFragments); + +class CookieSetFromJs : public HeadlessRenderTest { + private: + GURL GetPageUrl(HeadlessDevToolsClient* client) override { + GetProtocolHandler()->InsertResponse("http://www.example.com/", HttpOk(R"|( +<html><head><script> +document.cookie = 'SessionID=123'; +n = document.cookie.indexOf('SessionID'); +if (n < 0) { + top.location = '/epicfail'; +} +</script></head><body>Pass</body></html>)|")); + return GURL("http://www.example.com/"); + } + + void VerifyDom(GetSnapshotResult* dom_snapshot) override { + EXPECT_THAT(GetProtocolHandler()->urls_requested(), + ElementsAre("http://www.example.com/")); + EXPECT_THAT(NextNode(dom_snapshot, FindTag(dom_snapshot, "BODY")), + NodeValue("Pass")); + } +}; +HEADLESS_RENDER_BROWSERTEST(CookieSetFromJs); + +class CookieSetFromJs_NoCookies : public CookieSetFromJs { + private: + void OverrideWebPreferences(WebPreferences* preferences) override { + HeadlessRenderTest::OverrideWebPreferences(preferences); + preferences->cookie_enabled = false; + } + + void VerifyDom(GetSnapshotResult* dom_snapshot) override { + EXPECT_THAT(GetProtocolHandler()->urls_requested(), + ElementsAre("http://www.example.com/", + "http://www.example.com/epicfail")); + } +}; +HEADLESS_RENDER_BROWSERTEST(CookieSetFromJs_NoCookies); + +class CookieUpdatedFromJs : public HeadlessRenderTest { + private: + GURL GetPageUrl(HeadlessDevToolsClient* client) override { + client->GetNetwork()->SetCookie(network::SetCookieParams::Builder() + .SetUrl("http://www.example.com/") + .SetName("foo") + .SetValue("bar") + .Build()); + GetProtocolHandler()->InsertResponse("http://www.example.com/", HttpOk(R"|( +<html><head><script> +var x = document.cookie; +document.cookie = x + 'baz'; +</script></head><body>Pass</body></html>)|")); + return GURL("http://www.example.com/"); + } + + void OnPageRenderCompleted() override { + devtools_client_->GetNetwork()->GetCookies( + network::GetCookiesParams::Builder() + .SetUrls({"http://www.example.com/"}) + .Build(), + base::Bind(&CookieUpdatedFromJs::OnGetCookies, base::Unretained(this))); + } + + void OnGetCookies(std::unique_ptr<network::GetCookiesResult> result) { + const auto& cookies = *result->GetCookies(); + EXPECT_THAT(cookies, ElementsAre(CookieValue("barbaz"))); + HeadlessRenderTest::OnPageRenderCompleted(); + } + + void VerifyDom(GetSnapshotResult* dom_snapshot) override { + EXPECT_THAT(NextNode(dom_snapshot, FindTag(dom_snapshot, "BODY")), + NodeValue("Pass")); + } +}; +HEADLESS_RENDER_BROWSERTEST(CookieUpdatedFromJs); + } // namespace headless
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index 443d811..b17b573 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -316,11 +316,14 @@ "//ios/chrome/browser/ui/first_run", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/fullscreen:legacy_fullscreen", + "//ios/chrome/browser/ui/fullscreen:new_fullscreen", "//ios/chrome/browser/ui/history", "//ios/chrome/browser/ui/history_popup:coordinator", "//ios/chrome/browser/ui/history_popup/requirements", "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/main:feature_flags", + "//ios/chrome/browser/ui/main_content:main_content_ui", + "//ios/chrome/browser/ui/main_content:main_content_ui_broadcasting_util", "//ios/chrome/browser/ui/ntp", "//ios/chrome/browser/ui/ntp:modal_ntp", "//ios/chrome/browser/ui/ntp:ntp_controller", @@ -346,6 +349,7 @@ "//ios/chrome/browser/ui/tabs:coordinator", "//ios/chrome/browser/ui/tabs/requirements", "//ios/chrome/browser/ui/toolbar:toolbar_ui", + "//ios/chrome/browser/ui/toolbar:toolbar_ui_broadcasting_util", "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature", "//ios/chrome/browser/ui/tools_menu", "//ios/chrome/browser/ui/tools_menu:configuration",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm index fe9ad46..a1de2aa4 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -559,6 +559,10 @@ } } +- (BOOL)isAtTopOfNavigation:(BookmarkTableView*)view { + return (self.navigationController.topViewController == self); +} + #pragma mark - BookmarkFolderViewControllerDelegate - (void)folderPicker:(BookmarkFolderViewController*)folderPicker
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.h b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.h index b8cd267..6e278c5 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.h
@@ -64,6 +64,9 @@ // Tells the delegate to refresh the context bar. - (void)bookmarkTableViewRefreshContextBar:(BookmarkTableView*)view; +// Returns true if this table is at the top of the navigation stack. +- (BOOL)isAtTopOfNavigation:(BookmarkTableView*)view; + @end @interface BookmarkTableView : UIView
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm index f88390d2..05797f1 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_table_view.mm
@@ -42,6 +42,9 @@ // Cell height, in points. CGFloat kCellHeightPt = 56.0; + +// Minimium spacing between keyboard and the titleText when creating new folder. +CGFloat keyboardSpacing = 16.0; } using bookmarks::BookmarkNode; @@ -937,21 +940,32 @@ // Called when the UIKeyboardDidShowNotification is sent - (void)keyboardWasShown:(NSNotification*)aNotification { + if (![self.delegate isAtTopOfNavigation:self]) { + return; + } NSDictionary* info = [aNotification userInfo]; - CGSize kbSize = - [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; + CGFloat keyboardTop = + [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y; + CGFloat tableBottom = + CGRectGetMaxY([self convertRect:self.tableView.frame toView:nil]); + CGFloat shiftY = tableBottom - keyboardTop + keyboardSpacing; - UIEdgeInsets previousContentInsets = self.tableView.contentInset; - // Shift the content inset by the height of the keyboard so we can scoll to - // the bottom of the content that is potentially behind the keyboard. - UIEdgeInsets contentInsets = - UIEdgeInsetsMake(previousContentInsets.top, 0.0, kbSize.height, 0.0); - self.tableView.contentInset = contentInsets; - self.tableView.scrollIndicatorInsets = contentInsets; + if (shiftY >= 0) { + UIEdgeInsets previousContentInsets = self.tableView.contentInset; + // Shift the content inset to prevent the editing content from being hidden + // by the keyboard. + UIEdgeInsets contentInsets = + UIEdgeInsetsMake(previousContentInsets.top, 0.0, shiftY, 0.0); + self.tableView.contentInset = contentInsets; + self.tableView.scrollIndicatorInsets = contentInsets; + } } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { + if (![self.delegate isAtTopOfNavigation:self]) { + return; + } UIEdgeInsets previousContentInsets = self.tableView.contentInset; // Restore the content inset now that the keyboard has been hidden. UIEdgeInsets contentInsets =
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 04f67b39..d12f3f5 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -143,6 +143,8 @@ #import "ios/chrome/browser/ui/external_search/external_search_coordinator.h" #import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h" #import "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #import "ios/chrome/browser/ui/fullscreen/legacy_fullscreen_controller.h" #import "ios/chrome/browser/ui/history_popup/requirements/tab_history_presentation.h" @@ -150,6 +152,10 @@ #import "ios/chrome/browser/ui/key_commands_provider.h" #import "ios/chrome/browser/ui/location_bar_notification_names.h" #import "ios/chrome/browser/ui/main/main_feature_flags.h" +#import "ios/chrome/browser/ui/main_content/main_content_ui.h" +#import "ios/chrome/browser/ui/main_content/main_content_ui_broadcasting_util.h" +#import "ios/chrome/browser/ui/main_content/main_content_ui_state.h" +#import "ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.h" #import "ios/chrome/browser/ui/ntp/modal_ntp.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_controller.h" #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_coordinator.h" @@ -184,6 +190,7 @@ #include "ios/chrome/browser/ui/toolbar/toolbar_model_ios.h" #import "ios/chrome/browser/ui/toolbar/toolbar_snapshot_providing.h" #import "ios/chrome/browser/ui/toolbar/toolbar_ui.h" +#import "ios/chrome/browser/ui/toolbar/toolbar_ui_broadcasting_util.h" #import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h" #import "ios/chrome/browser/ui/tools_menu/public/tools_menu_configuration_provider.h" #import "ios/chrome/browser/ui/tools_menu/public/tools_menu_presentation_provider.h" @@ -393,6 +400,7 @@ InfobarContainerStateDelegate, KeyCommandsPlumbing, NetExportTabHelperDelegate, + MainContentUI, ManageAccountsDelegate, MFMailComposeViewControllerDelegate, NewTabPageControllerObserver, @@ -573,6 +581,12 @@ // The toolbar UI updater for the toolbar managed by |_toolbarCoordinator|. LegacyToolbarUIUpdater* _toolbarUIUpdater; + // The main content UI updater for the content displayed by this BVC. + MainContentUIStateUpdater* _mainContentUIUpdater; + + // The forwarder for web scroll view interation events. + WebScrollViewMainContentUIForwarder* _webMainContentUIForwarder; + // Coordinator for the External Search UI. ExternalSearchCoordinator* _externalSearchCoordinator; @@ -606,6 +620,8 @@ // Whether the controller's view is currently visible. // YES from viewDidAppear to viewWillDisappear. @property(nonatomic, assign) BOOL viewVisible; +// Whether the controller should broadcast its UI. +@property(nonatomic, assign, getter=isBroadcasting) BOOL broadcasting; // Whether the controller is currently dismissing a presented view controller. @property(nonatomic, assign, getter=isDismissingModal) BOOL dismissingModal; // Returns YES if the toolbar has not been scrolled out by fullscreen. @@ -732,9 +748,9 @@ - (UIImageView*)pageFullScreenOpenCloseAnimationView; // Updates the toolbar display based on the current tab. - (void)updateToolbar; -// Starts or stops broadcasting the toolbar UI depending on whether the BVC is -// visible and active. -- (void)updateToolbarBroadcastState; +// Starts or stops broadcasting the toolbar UI and main content UI depending on +// whether the BVC is visible and active. +- (void)updateBroadcastState; // Updates |dialogPresenter|'s |active| property to account for the BVC's // |active|, |visible|, and |inNewTabAnimation| properties. - (void)updateDialogPresenterActiveState; @@ -909,6 +925,7 @@ @synthesize active = _active; @synthesize visible = _visible; @synthesize viewVisible = _viewVisible; +@synthesize broadcasting = _broadcasting; @synthesize dismissingModal = _dismissingModal; @synthesize hideStatusBar = _hideStatusBar; @synthesize activityOverlayCoordinator = _activityOverlayCoordinator; @@ -1044,7 +1061,7 @@ [_model setWebUsageEnabled:active]; [self updateDialogPresenterActiveState]; - [self updateToolbarBroadcastState]; + [self updateBroadcastState]; if (active) { // Make sure the tab (if any; it's possible to get here without a current @@ -1068,7 +1085,7 @@ [_model setPrimary:primary]; if (primary) { [self updateDialogPresenterActiveState]; - [self updateToolbarBroadcastState]; + [self updateBroadcastState]; } else { self.dialogPresenter.active = false; } @@ -1155,7 +1172,42 @@ _viewVisible = viewVisible; self.visible = viewVisible; [self updateDialogPresenterActiveState]; - [self updateToolbarBroadcastState]; + [self updateBroadcastState]; +} + +- (void)setBroadcasting:(BOOL)broadcasting { + if (_broadcasting == broadcasting) + return; + _broadcasting = broadcasting; + if (base::FeatureList::IsEnabled(fullscreen::features::kNewFullscreen)) { + // TODO(crbug.com/790886): Use the Browser's broadcaster once Browsers are + // supported. + ChromeBroadcaster* broadcaster = FullscreenControllerFactory::GetInstance() + ->GetForBrowserState(_browserState) + ->broadcaster(); + if (_broadcasting) { + _toolbarUIUpdater = [[LegacyToolbarUIUpdater alloc] + initWithToolbarUI:[[ToolbarUIState alloc] init] + toolbarOwner:self + webStateList:[_model webStateList]]; + [_toolbarUIUpdater startUpdating]; + StartBroadcastingToolbarUI(_toolbarUIUpdater.toolbarUI, broadcaster); + _mainContentUIUpdater = [[MainContentUIStateUpdater alloc] + initWithState:[[MainContentUIState alloc] init]]; + _webMainContentUIForwarder = [[WebScrollViewMainContentUIForwarder alloc] + initWithUpdater:_mainContentUIUpdater + webStateList:[_model webStateList]]; + StartBroadcastingMainContentUI(self, broadcaster); + } else { + StopBroadcastingToolbarUI(broadcaster); + StopBroadcastingMainContentUI(broadcaster); + [_toolbarUIUpdater stopUpdating]; + _toolbarUIUpdater = nil; + _mainContentUIUpdater = nil; + [_webMainContentUIForwarder disconnect]; + _webMainContentUIForwarder = nil; + } + } } - (BOOL)isToolbarOnScreen { @@ -1167,7 +1219,7 @@ return; _inNewTabAnimation = inNewTabAnimation; [self updateDialogPresenterActiveState]; - [self updateToolbarBroadcastState]; + [self updateBroadcastState]; } - (BOOL)isInNewTabAnimation { @@ -1276,7 +1328,7 @@ [super viewDidAppear:animated]; self.viewVisible = YES; [self updateDialogPresenterActiveState]; - [self updateToolbarBroadcastState]; + [self updateBroadcastState]; // |viewDidAppear| can be called after |browserState| is destroyed. Since // |presentBubblesIfEligible| requires that |self.browserState| is not NULL, @@ -1310,7 +1362,7 @@ - (void)viewWillDisappear:(BOOL)animated { self.viewVisible = NO; [self updateDialogPresenterActiveState]; - [self updateToolbarBroadcastState]; + [self updateBroadcastState]; [[_model currentTab] wasHidden]; [_bookmarkInteractionController dismissSnackbar]; if (IsIPadIdiom() && _infoBarContainer) { @@ -1866,7 +1918,7 @@ [_dispatcher startDispatchingToTarget:_toolbarCoordinator forProtocol:@protocol(OmniboxFocuser)]; [_toolbarCoordinator setTabCount:[_model count]]; - [self updateToolbarBroadcastState]; + [self updateBroadcastState]; if (_voiceSearchController) _voiceSearchController->SetDelegate( [_toolbarCoordinator voiceSearchDelegate]); @@ -2124,22 +2176,9 @@ } } -- (void)updateToolbarBroadcastState { - BOOL shouldBroadcast = +- (void)updateBroadcastState { + self.broadcasting = self.active && self.viewVisible && !self.inNewTabAnimation; - BOOL broadcasting = _toolbarUIUpdater != nil; - if (shouldBroadcast == broadcasting) - return; - if (shouldBroadcast) { - _toolbarUIUpdater = [[LegacyToolbarUIUpdater alloc] - initWithToolbarUI:[[ToolbarUIState alloc] init] - toolbarOwner:self - webStateList:[_model webStateList]]; - [_toolbarUIUpdater startUpdating]; - } else { - [_toolbarUIUpdater stopUpdating]; - _toolbarUIUpdater = nil; - } } - (void)updateDialogPresenterActiveState { @@ -3899,6 +3938,12 @@ [_toolbarCoordinator focusOmnibox]; } +#pragma mark - MainContentUI + +- (MainContentUIState*)mainContentUIState { + return _mainContentUIUpdater.state; +} + #pragma mark - UIResponder - (NSArray*)keyCommands {
diff --git a/ios/chrome/browser/ui/main_content/BUILD.gn b/ios/chrome/browser/ui/main_content/BUILD.gn index 482dbf32..4ac3e6d8 100644 --- a/ios/chrome/browser/ui/main_content/BUILD.gn +++ b/ios/chrome/browser/ui/main_content/BUILD.gn
@@ -24,6 +24,8 @@ "main_content_ui.h", "main_content_ui_state.h", "main_content_ui_state.mm", + "web_scroll_view_main_content_ui_forwarder.h", + "web_scroll_view_main_content_ui_forwarder.mm", ] configs += [ "//build/config/compiler:enable_arc" ] @@ -32,6 +34,8 @@ "//base", "//ios/chrome/browser/ui:ui_util", "//ios/chrome/browser/ui/broadcaster", + "//ios/chrome/browser/web_state_list", + "//ios/web/public", ] }
diff --git a/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.h b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.h new file mode 100644 index 0000000..73d382aa --- /dev/null +++ b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.h
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_MAIN_CONTENT_WEB_SCROLL_VIEW_MAIN_CONTENT_UI_FORWARDER_H_ +#define IOS_CHROME_BROWSER_UI_MAIN_CONTENT_WEB_SCROLL_VIEW_MAIN_CONTENT_UI_FORWARDER_H_ + +#import <Foundation/Foundation.h> + +@class MainContentUIStateUpdater; +class WebStateList; + +// Helper object that forwards a CRWWebViewScrollViewProxy events to a +// MainContentUIStateUpdater. +@interface WebScrollViewMainContentUIForwarder : NSObject + +// Designated initializer for a forwarder that sends the scroll events from +// |webStateList|'s active WebState's scroll view proxy to |updater|. +- (nullable instancetype)initWithUpdater: + (nonnull MainContentUIStateUpdater*)updater + webStateList:(nonnull WebStateList*)webStateList + NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)init NS_UNAVAILABLE; + +// Instructs the forwarder to stop observing the WebStateList and the active +// WebState's scroll view proxy. +- (void)disconnect; + +@end + +#endif // IOS_CHROME_BROWSER_UI_MAIN_CONTENT_WEB_SCROLL_VIEW_MAIN_CONTENT_UI_FORWARDER_H_
diff --git a/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm new file mode 100644 index 0000000..c8d3897e --- /dev/null +++ b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm
@@ -0,0 +1,117 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#import "ios/chrome/browser/ui/main_content/main_content_ui_state.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" +#import "ios/web/public/web_state/ui/crw_web_view_proxy.h" +#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" +#import "ios/web/public/web_state/web_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface WebScrollViewMainContentUIForwarder ()< + CRWWebViewScrollViewProxyObserver, + WebStateListObserving> { + // The observer bridge. + std::unique_ptr<WebStateListObserver> _bridge; +} + +// The updater being driven by this object. +@property(nonatomic, readonly, strong) MainContentUIStateUpdater* updater; +// The WebStateList whose active WebState's scroll state is being forwaded. +@property(nonatomic, readonly) WebStateList* webStateList; +// The scroll view proxy whose scroll events are forwarded to |updater|. +@property(nonatomic, readonly, strong) CRWWebViewScrollViewProxy* proxy; +@end + +@implementation WebScrollViewMainContentUIForwarder +@synthesize updater = _updater; +@synthesize webStateList = _webStateList; +@synthesize proxy = _proxy; + +- (instancetype)initWithUpdater:(MainContentUIStateUpdater*)updater + webStateList:(WebStateList*)webStateList { + if (self = [super init]) { + _updater = updater; + DCHECK(_updater); + _webStateList = webStateList; + DCHECK(_webStateList); + _bridge = base::MakeUnique<WebStateListObserverBridge>(self); + _webStateList->AddObserver(_bridge.get()); + web::WebState* activeWebState = webStateList->GetActiveWebState(); + if (activeWebState) { + _proxy = activeWebState->GetWebViewProxy().scrollViewProxy; + [_proxy addObserver:self]; + } + } + return self; +} + +- (void)dealloc { + [self disconnect]; +} + +#pragma mark Accessors + +- (void)setProxy:(CRWWebViewScrollViewProxy*)proxy { + if (_proxy == proxy) + return; + [_proxy removeObserver:self]; + _proxy = proxy; + [_proxy addObserver:self]; +} + +#pragma mark Public + +- (void)disconnect { + self.webStateList->RemoveObserver(_bridge.get()); + _bridge = nullptr; + self.proxy = nil; +} + +#pragma mark CRWWebViewScrollViewObserver + +- (void)webViewScrollViewDidScroll: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { + [self.updater scrollViewDidScrollToOffset:self.proxy.contentOffset]; +} + +- (void)webViewScrollViewWillBeginDragging: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { + [self.updater + scrollViewWillBeginDraggingWithGesture:self.proxy.panGestureRecognizer]; +} + +- (void)webViewScrollViewWillEndDragging: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy + withVelocity:(CGPoint)velocity + targetContentOffset:(inout CGPoint*)targetContentOffset { + [self.updater + scrollViewDidEndDraggingWithGesture:self.proxy.panGestureRecognizer + residualVelocity:velocity]; +} + +- (void)webViewScrollViewDidEndDecelerating: + (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { + [self.updater scrollViewDidEndDecelerating]; +} + +#pragma mark - WebStateListObserving + +- (void)webStateList:(WebStateList*)webStateList + didChangeActiveWebState:(web::WebState*)newWebState + oldWebState:(web::WebState*)oldWebState + atIndex:(int)atIndex + userAction:(BOOL)userAction { + self.proxy = newWebState->GetWebViewProxy().scrollViewProxy; +} + +@end
diff --git a/media/blink/cdm_result_promise_helper.cc b/media/blink/cdm_result_promise_helper.cc index b65a2247..93dd4da7 100644 --- a/media/blink/cdm_result_promise_helper.cc +++ b/media/blink/cdm_result_promise_helper.cc
@@ -5,7 +5,7 @@ #include "media/blink/cdm_result_promise_helper.h" #include "base/logging.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_functions.h" namespace media { @@ -69,12 +69,7 @@ if (uma_name.empty()) return; - base::LinearHistogram::FactoryGet( - uma_name, - 1, - NUM_RESULT_CODES, - NUM_RESULT_CODES + 1, - base::HistogramBase::kUmaTargetedHistogramFlag)->Add(result); + base::UmaHistogramEnumeration(uma_name, result, NUM_RESULT_CODES); } } // namespace media
diff --git a/media/blink/webencryptedmediaclient_impl.cc b/media/blink/webencryptedmediaclient_impl.cc index c907360..5a0e760 100644 --- a/media/blink/webencryptedmediaclient_impl.cc +++ b/media/blink/webencryptedmediaclient_impl.cc
@@ -8,7 +8,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "media/base/key_systems.h" @@ -72,12 +72,8 @@ private: void Report(KeySystemSupportStatus status) { - // Not using UMA_HISTOGRAM_ENUMERATION directly because UMA_* macros - // require the names to be constant throughout the process' lifetime. - base::LinearHistogram::FactoryGet( - uma_name_, 1, KEY_SYSTEM_SUPPORT_STATUS_COUNT, - KEY_SYSTEM_SUPPORT_STATUS_COUNT + 1, - base::Histogram::kUmaTargetedHistogramFlag)->Add(status); + base::UmaHistogramEnumeration(uma_name_, status, + KEY_SYSTEM_SUPPORT_STATUS_COUNT); } const std::string uma_name_;
diff --git a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java index 90029c48..0063308a 100644 --- a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java +++ b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
@@ -317,46 +317,60 @@ this.fd = mPfd.getFileDescriptor(); } + @Override protected void accept(SocketImpl s) { throw new RuntimeException("accept not implemented"); } + @Override protected int available() { throw new RuntimeException("accept not implemented"); } + @Override protected void bind(InetAddress host, int port) { throw new RuntimeException("accept not implemented"); } + @Override protected void close() { // Detach from |fd| to avoid leak detection false positives without closing |fd|. mPfd.detachFd(); } + @Override protected void connect(InetAddress address, int port) { throw new RuntimeException("connect not implemented"); } + @Override protected void connect(SocketAddress address, int timeout) { throw new RuntimeException("connect not implemented"); } + @Override protected void connect(String host, int port) { throw new RuntimeException("connect not implemented"); } + @Override protected void create(boolean stream) { throw new RuntimeException("create not implemented"); } + @Override protected InputStream getInputStream() { throw new RuntimeException("getInputStream not implemented"); } + @Override protected OutputStream getOutputStream() { throw new RuntimeException("getOutputStream not implemented"); } + @Override protected void listen(int backlog) { throw new RuntimeException("listen not implemented"); } + @Override protected void sendUrgentData(int data) { throw new RuntimeException("sendUrgentData not implemented"); } + @Override public Object getOption(int optID) { throw new RuntimeException("getOption not implemented"); } + @Override public void setOption(int optID, Object value) { throw new RuntimeException("setOption not implemented"); }
diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn index cdb97071..648d52a 100644 --- a/services/device/geolocation/BUILD.gn +++ b/services/device/geolocation/BUILD.gn
@@ -8,6 +8,8 @@ visibility = [ "//services/device:*" ] sources = [ + "public_ip_address_geolocation_provider.cc", + "public_ip_address_geolocation_provider.h", "public_ip_address_geolocator.cc", "public_ip_address_geolocator.h", "public_ip_address_location_notifier.cc", @@ -19,5 +21,6 @@ "//device/geolocation", "//mojo/public/cpp/bindings", "//net", + "//services/device/public/interfaces", ] }
diff --git a/services/device/geolocation/public_ip_address_geolocation_provider.cc b/services/device/geolocation/public_ip_address_geolocation_provider.cc new file mode 100644 index 0000000..4c570ba --- /dev/null +++ b/services/device/geolocation/public_ip_address_geolocation_provider.cc
@@ -0,0 +1,50 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/device/geolocation/public_ip_address_geolocation_provider.h" + +#include "services/device/geolocation/public_ip_address_geolocator.h" + +namespace device { + +PublicIpAddressGeolocationProvider::PublicIpAddressGeolocationProvider() { + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +PublicIpAddressGeolocationProvider::~PublicIpAddressGeolocationProvider() {} + +void PublicIpAddressGeolocationProvider::Initialize( + GeolocationProvider::RequestContextProducer request_context_producer, + const std::string& api_key) { + // Bind sequence_checker_ to the initialization sequence. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + public_ip_address_location_notifier_ = + std::make_unique<PublicIpAddressLocationNotifier>( + request_context_producer, api_key); +} + +void PublicIpAddressGeolocationProvider::Bind( + mojom::PublicIpAddressGeolocationProviderRequest request) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(public_ip_address_location_notifier_); + provider_binding_set_.AddBinding(this, std::move(request)); +} + +void PublicIpAddressGeolocationProvider::CreateGeolocation( + const net::MutablePartialNetworkTrafficAnnotationTag& tag, + mojom::GeolocationRequest request) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(public_ip_address_location_notifier_); + geolocation_binding_set_.AddBinding( + std::make_unique<PublicIpAddressGeolocator>( + static_cast<net::PartialNetworkTrafficAnnotationTag>(tag), + public_ip_address_location_notifier_.get(), + base::Bind( + &mojo::StrongBindingSet<mojom::Geolocation>::ReportBadMessage, + base::Unretained(&geolocation_binding_set_))), + std::move(request)); +} + +} // namespace device
diff --git a/services/device/geolocation/public_ip_address_geolocation_provider.h b/services/device/geolocation/public_ip_address_geolocation_provider.h new file mode 100644 index 0000000..57ee445 --- /dev/null +++ b/services/device/geolocation/public_ip_address_geolocation_provider.h
@@ -0,0 +1,76 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_GEOLOCATION_PROVIDER_H_ +#define SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_GEOLOCATION_PROVIDER_H_ + +#include <string> + +#include "base/macros.h" +#include "device/geolocation/public/interfaces/geolocation.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/strong_binding_set.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/device/geolocation/public_ip_address_geolocator.h" +#include "services/device/geolocation/public_ip_address_location_notifier.h" +#include "services/device/public/interfaces/public_ip_address_geolocation_provider.mojom.h" + +namespace device { + +// Implementation of PublicIpAddressGeolocationProvider Mojo interface that will +// provide mojom::Geolocation implementations that use IP-only geolocation. +// Binds multiple PublicIpAddressGeolocationProvider requests. +// +// Sequencing: +// * Must be used and destroyed on the same sequence. +// * Provides mojom::Geolocation instances that are bound on the same sequence. +// * Requires two-step construction: Construct on any sequence, then invoke +// Initialize() on the sequence on which this object will run. +class PublicIpAddressGeolocationProvider + : public mojom::PublicIpAddressGeolocationProvider { + public: + // After construction, invoke Initialize() (on the appropriate sequence) to + // finish initialization. + PublicIpAddressGeolocationProvider(); + ~PublicIpAddressGeolocationProvider() override; + + // Finishes initialization, using the specified Google |api_key| and a URL + // request context produced by |request_context_producer| for network location + // requests. + // After this call is made, this object must be used only on the sequence on + // which this call was made. + void Initialize( + GeolocationProvider::RequestContextProducer request_context_producer, + const std::string& api_key); + + // Binds a PublicIpAddressGeolocationProvider request to this instance. + void Bind(mojom::PublicIpAddressGeolocationProviderRequest request); + + private: + SEQUENCE_CHECKER(sequence_checker_); + + // mojom::PublicIpAddressGeolocationProvider implementation: + // Provides a Geolocation instance that performs IP-geolocation only. + void CreateGeolocation( + const net::MutablePartialNetworkTrafficAnnotationTag& tag, + mojom::GeolocationRequest request) override; + + // Central PublicIpAddressLocationNotifier for use by all implementations of + // mojom::Geolocation provided by the CreateGeolocation method. + // Note that this must be before the StrongBindingSet<mojom::Geolocation> as + // it must outlive the Geolocation implementations. + std::unique_ptr<PublicIpAddressLocationNotifier> + public_ip_address_location_notifier_; + + mojo::BindingSet<mojom::PublicIpAddressGeolocationProvider> + provider_binding_set_; + + mojo::StrongBindingSet<mojom::Geolocation> geolocation_binding_set_; + + DISALLOW_COPY_AND_ASSIGN(PublicIpAddressGeolocationProvider); +}; + +} // namespace device + +#endif // SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_GEOLOCATION_PROVIDER_H_
diff --git a/services/device/public/interfaces/BUILD.gn b/services/device/public/interfaces/BUILD.gn index 8914b53..bc08e02 100644 --- a/services/device/public/interfaces/BUILD.gn +++ b/services/device/public/interfaces/BUILD.gn
@@ -14,6 +14,7 @@ "nfc.mojom", "nfc_provider.mojom", "power_monitor.mojom", + "public_ip_address_geolocation_provider.mojom", "serial.mojom", "time_zone_monitor.mojom", "vibration_manager.mojom", @@ -22,9 +23,17 @@ "wake_lock_provider.mojom", ] + deps = [ + "//device/geolocation/public/interfaces", + "//services/network/public/interfaces:interfaces", + ] + public_deps = [ ":constants", ] + + overridden_deps_blink = [ "//services/network/public/interfaces:interfaces" ] + component_deps_blink = [ "//third_party/WebKit/Source/platform" ] } mojom("generic_sensor") {
diff --git a/services/device/public/interfaces/public_ip_address_geolocation_provider.mojom b/services/device/public/interfaces/public_ip_address_geolocation_provider.mojom new file mode 100644 index 0000000..214912e --- /dev/null +++ b/services/device/public/interfaces/public_ip_address_geolocation_provider.mojom
@@ -0,0 +1,18 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module device.mojom; + +import "device/geolocation/public/interfaces/geolocation.mojom"; +import "services/network/public/interfaces/mutable_partial_network_traffic_annotation_tag.mojom"; + +// Provides a coarse-grained device.mojom.Geolocation which, subject to +// case-by-case privacy review, may be able to operate without explicit user +// consent. +// +// WARNING: DO NOT USE WITHOUT PRIVACY REVIEW. +interface PublicIpAddressGeolocationProvider { + CreateGeolocation(network.mojom.MutablePartialNetworkTrafficAnnotationTag tag, + Geolocation& request); +};
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index 15e418d..b7e9293 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -486,7 +486,6 @@ # use Mojo APIs instead. -HangingPacRequestProxyScriptBrowserTest.Shutdown -IOThreadBrowserTestWithHangingPacRequest.Shutdown --IOThreadBrowserTestWithPacFileURL.FilePac -ProxySettingsApiTest.ProxyEventsParseError # http://crbug.com/783996
diff --git a/third_party/WebKit/Source/controller/BUILD.gn b/third_party/WebKit/Source/controller/BUILD.gn index 714113d..cd39792d 100644 --- a/third_party/WebKit/Source/controller/BUILD.gn +++ b/third_party/WebKit/Source/controller/BUILD.gn
@@ -37,6 +37,8 @@ "BlinkInitializer.cpp", "BlinkInitializer.h", "ControllerExport.h", + "DevToolsFrontendImpl.cpp", + "DevToolsFrontendImpl.h", "OomInterventionImpl.cpp", "OomInterventionImpl.h", ]
diff --git a/third_party/WebKit/Source/controller/BlinkInitializer.cpp b/third_party/WebKit/Source/controller/BlinkInitializer.cpp index 6bc760c0..9e303da 100644 --- a/third_party/WebKit/Source/controller/BlinkInitializer.cpp +++ b/third_party/WebKit/Source/controller/BlinkInitializer.cpp
@@ -33,6 +33,7 @@ #include "bindings/core/v8/V8Initializer.h" #include "bindings/modules/v8/V8ContextSnapshotExternalReferences.h" #include "build/build_config.h" +#include "controller/DevToolsFrontendImpl.h" #include "controller/OomInterventionImpl.h" #include "core/animation/AnimationClock.h" #include "core/frame/LocalFrame.h" @@ -126,4 +127,20 @@ main_thread->GetSingleThreadTaskRunner()); } +void BlinkInitializer::InitLocalFrame(LocalFrame& frame) const { + frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating( + &DevToolsFrontendImpl::BindMojoRequest, WrapWeakPersistent(&frame))); + ModulesInitializer::InitLocalFrame(frame); +} + +void BlinkInitializer::OnClearWindowObjectInMainWorld( + Document& document, + const Settings& settings) const { + if (DevToolsFrontendImpl* devtools_frontend = + DevToolsFrontendImpl::From(document.GetFrame())) { + devtools_frontend->DidClearWindowObject(); + } + ModulesInitializer::OnClearWindowObjectInMainWorld(document, settings); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/controller/BlinkInitializer.h b/third_party/WebKit/Source/controller/BlinkInitializer.h index cae3ebd..822cfa3 100644 --- a/third_party/WebKit/Source/controller/BlinkInitializer.h +++ b/third_party/WebKit/Source/controller/BlinkInitializer.h
@@ -12,6 +12,9 @@ class BlinkInitializer : public ModulesInitializer { public: void RegisterInterfaces(InterfaceRegistry&) override; + void OnClearWindowObjectInMainWorld(Document&, + const Settings&) const override; + void InitLocalFrame(LocalFrame&) const override; }; } // namespace blink
diff --git a/third_party/WebKit/Source/controller/DevToolsFrontendImpl.cpp b/third_party/WebKit/Source/controller/DevToolsFrontendImpl.cpp new file mode 100644 index 0000000..eb30034 --- /dev/null +++ b/third_party/WebKit/Source/controller/DevToolsFrontendImpl.cpp
@@ -0,0 +1,147 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "controller/DevToolsFrontendImpl.h" + +#include "bindings/core/v8/ScriptController.h" +#include "bindings/core/v8/V8BindingForCore.h" +#include "bindings/core/v8/V8DevToolsHost.h" +#include "core/exported/WebViewImpl.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/WebLocalFrameImpl.h" +#include "core/inspector/DevToolsHost.h" +#include "core/page/Page.h" +#include "platform/LayoutTestSupport.h" + +namespace blink { + +// static +void DevToolsFrontendImpl::BindMojoRequest( + LocalFrame* local_frame, + mojom::blink::DevToolsFrontendAssociatedRequest request) { + if (!local_frame) + return; + local_frame->ProvideSupplement( + SupplementName(), + new DevToolsFrontendImpl(*local_frame, std::move(request))); +} + +// static +DevToolsFrontendImpl* DevToolsFrontendImpl::From(LocalFrame* local_frame) { + if (!local_frame) + return nullptr; + return static_cast<DevToolsFrontendImpl*>( + local_frame->RequireSupplement(SupplementName())); +} + +// static +const char* DevToolsFrontendImpl::SupplementName() { + return "DevToolsFrontendImpl"; +} + +DevToolsFrontendImpl::DevToolsFrontendImpl( + LocalFrame& frame, + mojom::blink::DevToolsFrontendAssociatedRequest request) + : Supplement<LocalFrame>(frame), binding_(this, std::move(request)) {} + +DevToolsFrontendImpl::~DevToolsFrontendImpl() {} + +void DevToolsFrontendImpl::DidClearWindowObject() { + if (host_) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + // Use higher limit for DevTools isolate so that it does not OOM when + // profiling large heaps. + isolate->IncreaseHeapLimitForDebugging(); + ScriptState* script_state = ToScriptStateForMainWorld(GetSupplementable()); + DCHECK(script_state); + ScriptState::Scope scope(script_state); + if (devtools_host_) + devtools_host_->DisconnectClient(); + devtools_host_ = DevToolsHost::Create(this, GetSupplementable()); + v8::Local<v8::Object> global = script_state->GetContext()->Global(); + v8::Local<v8::Value> devtools_host_obj = + ToV8(devtools_host_.Get(), global, script_state->GetIsolate()); + DCHECK(!devtools_host_obj.IsEmpty()); + global->Set(V8AtomicString(isolate, "DevToolsHost"), devtools_host_obj); + } + + if (!api_script_.IsEmpty()) { + GetSupplementable()->GetScriptController().ExecuteScriptInMainWorld( + api_script_); + } +} + +void DevToolsFrontendImpl::SetupDevToolsFrontend( + const String& api_script, + mojom::blink::DevToolsFrontendHostAssociatedPtrInfo host) { + DCHECK(GetSupplementable()->IsMainFrame()); + api_script_ = api_script; + host_.Bind(std::move(host)); + host_.set_connection_error_handler(ConvertToBaseCallback(WTF::Bind( + &DevToolsFrontendImpl::DestroyOnHostGone, WrapWeakPersistent(this)))); + GetSupplementable()->GetPage()->SetDefaultPageScaleLimits(1.f, 1.f); +} + +void DevToolsFrontendImpl::SetupDevToolsExtensionAPI( + const String& extension_api) { + DCHECK(!GetSupplementable()->IsMainFrame()); + api_script_ = extension_api; +} + +void DevToolsFrontendImpl::SendMessageToEmbedder(const String& message) { + if (host_) + host_->DispatchEmbedderMessage(message); +} + +bool DevToolsFrontendImpl::IsUnderTest() { + return LayoutTestSupport::IsRunningLayoutTest(); +} + +void DevToolsFrontendImpl::ShowContextMenu(LocalFrame* target_frame, + float x, + float y, + ContextMenuProvider* menu_provider) { + WebLocalFrameImpl::FromFrame(target_frame) + ->ViewImpl() + ->ShowContextMenuAtPoint(x, y, menu_provider); +} + +void DevToolsFrontendImpl::DestroyOnHostGone() { + if (devtools_host_) + devtools_host_->DisconnectClient(); + GetSupplementable()->RemoveSupplement(SupplementName()); +} + +void DevToolsFrontendImpl::Trace(blink::Visitor* visitor) { + visitor->Trace(devtools_host_); + Supplement<LocalFrame>::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/controller/DevToolsFrontendImpl.h b/third_party/WebKit/Source/controller/DevToolsFrontendImpl.h new file mode 100644 index 0000000..8b68762 --- /dev/null +++ b/third_party/WebKit/Source/controller/DevToolsFrontendImpl.h
@@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DevToolsFrontendImpl_h +#define DevToolsFrontendImpl_h + +#include "base/macros.h" +#include "core/inspector/InspectorFrontendClient.h" +#include "mojo/public/cpp/bindings/associated_binding.h" +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" +#include "platform/wtf/HashMap.h" +#include "platform/wtf/text/WTFString.h" +#include "public/web/devtools_frontend.mojom-blink.h" + +namespace blink { + +class DevToolsHost; +class LocalFrame; + +// This class lives as long as a frame (being a supplement), or until +// it's host (mojom.DevToolsFrontendHost) is destroyed. +class DevToolsFrontendImpl final + : public GarbageCollectedFinalized<DevToolsFrontendImpl>, + public Supplement<LocalFrame>, + public mojom::blink::DevToolsFrontend, + public InspectorFrontendClient { + USING_GARBAGE_COLLECTED_MIXIN(DevToolsFrontendImpl); + + public: + static void BindMojoRequest(LocalFrame*, + mojom::blink::DevToolsFrontendAssociatedRequest); + static DevToolsFrontendImpl* From(LocalFrame*); + + ~DevToolsFrontendImpl() override; + void DidClearWindowObject(); + void Trace(blink::Visitor*); + + private: + DevToolsFrontendImpl(LocalFrame&, + mojom::blink::DevToolsFrontendAssociatedRequest); + static const char* SupplementName(); + void DestroyOnHostGone(); + + // mojom::blink::DevToolsFrontend implementation. + void SetupDevToolsFrontend( + const String& api_script, + mojom::blink::DevToolsFrontendHostAssociatedPtrInfo) override; + void SetupDevToolsExtensionAPI(const String& extension_api) override; + + // InspectorFrontendClient implementation. + void SendMessageToEmbedder(const String&) override; + bool IsUnderTest() override; + void ShowContextMenu(LocalFrame*, + float x, + float y, + ContextMenuProvider*) override; + + Member<DevToolsHost> devtools_host_; + String api_script_; + mojom::blink::DevToolsFrontendHostAssociatedPtr host_; + mojo::AssociatedBinding<mojom::blink::DevToolsFrontend> binding_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsFrontendImpl); +}; + +} // namespace blink + +#endif
diff --git a/third_party/WebKit/Source/core/exported/BUILD.gn b/third_party/WebKit/Source/core/exported/BUILD.gn index d6a6cdf..e8132ed 100644 --- a/third_party/WebKit/Source/core/exported/BUILD.gn +++ b/third_party/WebKit/Source/core/exported/BUILD.gn
@@ -25,8 +25,6 @@ "WebDateTimeSuggestion.cpp", "WebDevToolsAgentImpl.cpp", "WebDevToolsAgentImpl.h", - "WebDevToolsFrontendImpl.cpp", - "WebDevToolsFrontendImpl.h", "WebDocument.cpp", "WebDocumentLoaderImpl.cpp", "WebDocumentLoaderImpl.h",
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp index 3f685c8..aa2f029f 100644 --- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp +++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
@@ -42,7 +42,6 @@ #include "core/events/UIEventWithKeyState.h" #include "core/exported/SharedWorkerRepositoryClientImpl.h" #include "core/exported/WebDevToolsAgentImpl.h" -#include "core/exported/WebDevToolsFrontendImpl.h" #include "core/exported/WebDocumentLoaderImpl.h" #include "core/exported/WebPluginContainerImpl.h" #include "core/exported/WebViewImpl.h" @@ -175,13 +174,6 @@ *settings); } } - // FIXME: when extensions go out of process, this whole concept stops working. - WebDevToolsFrontendImpl* dev_tools_frontend = - web_frame_->Top()->IsWebLocalFrame() - ? ToWebLocalFrameImpl(web_frame_->Top())->DevToolsFrontend() - : nullptr; - if (dev_tools_frontend) - dev_tools_frontend->DidClearWindowObject(web_frame_); } void LocalFrameClientImpl::DocumentElementAvailable() {
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.cpp b/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.cpp deleted file mode 100644 index ebbe3314f..0000000 --- a/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.cpp +++ /dev/null
@@ -1,107 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "core/exported/WebDevToolsFrontendImpl.h" - -#include "bindings/core/v8/ScriptController.h" -#include "bindings/core/v8/V8BindingForCore.h" -#include "bindings/core/v8/V8DevToolsHost.h" -#include "core/exported/WebViewImpl.h" -#include "core/frame/LocalFrame.h" -#include "core/frame/WebLocalFrameImpl.h" -#include "core/inspector/DevToolsHost.h" -#include "core/page/Page.h" -#include "public/platform/WebSecurityOrigin.h" -#include "public/platform/WebString.h" -#include "public/web/WebDevToolsFrontendClient.h" - -namespace blink { - -WebDevToolsFrontend* WebDevToolsFrontend::Create( - WebLocalFrame* frame, - WebDevToolsFrontendClient* client) { - return new WebDevToolsFrontendImpl(ToWebLocalFrameImpl(frame), client); -} - -WebDevToolsFrontendImpl::WebDevToolsFrontendImpl( - WebLocalFrameImpl* web_frame, - WebDevToolsFrontendClient* client) - : web_frame_(web_frame), client_(client) { - web_frame_->SetDevToolsFrontend(this); - web_frame_->GetFrame()->GetPage()->SetDefaultPageScaleLimits(1.f, 1.f); -} - -WebDevToolsFrontendImpl::~WebDevToolsFrontendImpl() { - web_frame_->SetDevToolsFrontend(nullptr); - if (devtools_host_) - devtools_host_->DisconnectClient(); -} - -void WebDevToolsFrontendImpl::DidClearWindowObject(WebLocalFrameImpl* frame) { - if (web_frame_ != frame) - return; - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - // Use higher limit for DevTools isolate so that it does not OOM when - // profiling large heaps. - isolate->IncreaseHeapLimitForDebugging(); - ScriptState* script_state = ToScriptStateForMainWorld(web_frame_->GetFrame()); - DCHECK(script_state); - ScriptState::Scope scope(script_state); - - if (devtools_host_) - devtools_host_->DisconnectClient(); - devtools_host_ = DevToolsHost::Create(this, web_frame_->GetFrame()); - v8::Local<v8::Object> global = script_state->GetContext()->Global(); - v8::Local<v8::Value> devtools_host_obj = - ToV8(devtools_host_.Get(), global, script_state->GetIsolate()); - DCHECK(!devtools_host_obj.IsEmpty()); - global->Set(V8AtomicString(isolate, "DevToolsHost"), devtools_host_obj); -} - -void WebDevToolsFrontendImpl::SendMessageToEmbedder(const String& message) { - if (client_) - client_->SendMessageToEmbedder(message); -} - -bool WebDevToolsFrontendImpl::IsUnderTest() { - return client_ ? client_->IsUnderTest() : false; -} - -void WebDevToolsFrontendImpl::ShowContextMenu( - LocalFrame* target_frame, - float x, - float y, - ContextMenuProvider* menu_provider) { - WebLocalFrameImpl::FromFrame(target_frame) - ->ViewImpl() - ->ShowContextMenuAtPoint(x, y, menu_provider); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.h b/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.h deleted file mode 100644 index 1f229489..0000000 --- a/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.h +++ /dev/null
@@ -1,75 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebDevToolsFrontendImpl_h -#define WebDevToolsFrontendImpl_h - -#include "base/macros.h" -#include "core/CoreExport.h" -#include "core/inspector/InspectorFrontendClient.h" -#include "platform/heap/Handle.h" -#include "platform/wtf/HashMap.h" -#include "platform/wtf/text/WTFString.h" -#include "public/web/WebDevToolsFrontend.h" - -namespace blink { - -class DevToolsHost; -class WebLocalFrameImpl; - -class CORE_EXPORT WebDevToolsFrontendImpl final - : public WebDevToolsFrontend, - public InspectorFrontendClient { - public: - WebDevToolsFrontendImpl(WebLocalFrameImpl*, WebDevToolsFrontendClient*); - ~WebDevToolsFrontendImpl() override; - - void DidClearWindowObject(WebLocalFrameImpl*); - - void SendMessageToEmbedder(const WTF::String&) override; - - bool IsUnderTest() override; - - void ShowContextMenu(LocalFrame*, - float x, - float y, - ContextMenuProvider*) override; - - private: - Persistent<WebLocalFrameImpl> web_frame_; - WebDevToolsFrontendClient* client_; - Persistent<DevToolsHost> devtools_host_; - - DISALLOW_COPY_AND_ASSIGN(WebDevToolsFrontendImpl); -}; - -} // namespace blink - -#endif
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp index 9833489e..b0929025 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -1707,7 +1707,6 @@ autofill_client_(nullptr), input_events_scale_factor_for_emulation_(1), interface_registry_(interface_registry), - web_dev_tools_frontend_(nullptr), input_method_controller_(*this), spell_check_panel_host_client_(nullptr), self_keep_alive_(this) {
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h index 12949d1..ecac5142 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
@@ -60,7 +60,6 @@ struct WebAssociatedURLLoaderOptions; class WebAutofillClient; class WebDevToolsAgentImpl; -class WebDevToolsFrontendImpl; class WebFrameClient; class WebNode; class WebPerformance; @@ -420,14 +419,6 @@ void SetFrameWidget(WebFrameWidgetBase*); - // DevTools front-end bindings. - void SetDevToolsFrontend(WebDevToolsFrontendImpl* frontend) { - web_dev_tools_frontend_ = frontend; - } - WebDevToolsFrontendImpl* DevToolsFrontend() { - return web_dev_tools_frontend_; - } - WebNode ContextMenuNode() const { return context_menu_node_.Get(); } void SetContextMenuNode(Node* node) { context_menu_node_ = node; } void ClearContextMenuNode() { context_menu_node_.Clear(); } @@ -503,8 +494,6 @@ // Borrowed pointers to Mojo objects. blink::InterfaceRegistry* interface_registry_; - WebDevToolsFrontendImpl* web_dev_tools_frontend_; - Member<Node> context_menu_node_; WebInputMethodControllerImpl input_method_controller_;
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp index 840343fc..97c3085 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
@@ -41,10 +41,10 @@ // switch from idle to main thread only happens to a minority of toBlob calls #if !defined(OS_ANDROID) // Png image encoding on 4k by 4k canvas on Mac HDD takes 5.7+ seconds -const double kIdleTaskCompleteTimeoutDelayMs = 6700.0; +const double kIdleTaskCompleteTimeoutDelayMs = 10000.0; #else // Png image encoding on 4k by 4k canvas on Android One takes 9.0+ seconds -const double kIdleTaskCompleteTimeoutDelayMs = 10000.0; +const double kIdleTaskCompleteTimeoutDelayMs = 20000.0; #endif bool IsDeadlineNearOrPassed(double deadline_seconds) { @@ -95,7 +95,7 @@ // end of the list. enum ElapsedTimeHistogramType { kInitiateEncodingDelay, - kIdleEncodeDuration, + kCompleteEncodingDelay, kToBlobDuration, kNumberOfElapsedTimeHistogramTypes }; @@ -115,16 +115,16 @@ ("Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000, 50)); to_blob_jpeg_initiate_encoding_counter.Count(elapsed_time * 1000000.0); } - } else if (type == kIdleEncodeDuration) { + } else if (type == kCompleteEncodingDelay) { if (mime_type == CanvasAsyncBlobCreator::kMimeTypePng) { DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, to_blob_png_idle_encode_counter, - ("Blink.Canvas.ToBlob.IdleEncodeDuration.PNG", 0, 10000000, 50)); + ("Blink.Canvas.ToBlob.CompleteEncodingDelay.PNG", 0, 10000000, 50)); to_blob_png_idle_encode_counter.Count(elapsed_time * 1000000.0); } else if (mime_type == CanvasAsyncBlobCreator::kMimeTypeJpeg) { DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, to_blob_jpeg_idle_encode_counter, - ("Blink.Canvas.ToBlob.IdleEncodeDuration.JPEG", 0, 10000000, 50)); + ("Blink.Canvas.ToBlob.CompleteEncodingDelay.JPEG", 0, 10000000, 50)); to_blob_jpeg_idle_encode_counter.Count(elapsed_time * 1000000.0); } } else if (type == kToBlobDuration) { @@ -184,7 +184,6 @@ context_(context), mime_type_(mime_type), start_time_(start_time), - elapsed_time_(0), callback_(callback), script_promise_resolver_(resolver) { size_t rowBytes = size.Width() * 4; @@ -263,7 +262,7 @@ } void CanvasAsyncBlobCreator::ScheduleInitiateEncoding(double quality) { - schedule_initiate_start_time_ = WTF::MonotonicallyIncreasingTime(); + schedule_idle_task_start_time_ = WTF::MonotonicallyIncreasingTime(); Platform::Current()->CurrentThread()->Scheduler()->PostIdleTask( BLINK_FROM_HERE, WTF::Bind(&CanvasAsyncBlobCreator::InitiateEncoding, WrapPersistent(this), quality)); @@ -276,7 +275,7 @@ } RecordElapsedTimeHistogram( kInitiateEncodingDelay, mime_type_, - WTF::MonotonicallyIncreasingTime() - schedule_initiate_start_time_); + WTF::MonotonicallyIncreasingTime() - schedule_idle_task_start_time_); DCHECK(idle_task_status_ == kIdleTaskNotStarted); idle_task_status_ = kIdleTaskStarted; @@ -286,6 +285,8 @@ return; } + // Re-use this time variable to collect data on complete encoding delay + schedule_idle_task_start_time_ = WTF::MonotonicallyIncreasingTime(); IdleEncodeRows(deadline_seconds); } @@ -294,11 +295,9 @@ return; } - double start_time = WTF::MonotonicallyIncreasingTime(); for (int y = num_rows_completed_; y < src_data_.height(); ++y) { if (IsDeadlineNearOrPassed(deadline_seconds)) { num_rows_completed_ = y; - elapsed_time_ += (WTF::MonotonicallyIncreasingTime() - start_time); Platform::Current()->CurrentThread()->Scheduler()->PostIdleTask( BLINK_FROM_HERE, WTF::Bind(&CanvasAsyncBlobCreator::IdleEncodeRows, WrapPersistent(this))); @@ -314,8 +313,9 @@ num_rows_completed_ = src_data_.height(); idle_task_status_ = kIdleTaskCompleted; - elapsed_time_ += (WTF::MonotonicallyIncreasingTime() - start_time); - RecordElapsedTimeHistogram(kIdleEncodeDuration, mime_type_, elapsed_time_); + double elapsed_time = + WTF::MonotonicallyIncreasingTime() - schedule_idle_task_start_time_; + RecordElapsedTimeHistogram(kCompleteEncodingDelay, mime_type_, elapsed_time); if (IsDeadlineNearOrPassed(deadline_seconds)) { context_->GetTaskRunner(TaskType::kCanvasBlobSerialization) ->PostTask(BLINK_FROM_HERE,
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h index a37271c..6277b9a 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h
@@ -107,9 +107,10 @@ SkPixmap src_data_; const MimeType mime_type_; + + // Chrome metrics use double start_time_; - double schedule_initiate_start_time_; - double elapsed_time_; + double schedule_idle_task_start_time_; ToBlobFunctionType function_type_;
diff --git a/third_party/WebKit/Source/core/inspector/DevToolsHost.cpp b/third_party/WebKit/Source/core/inspector/DevToolsHost.cpp index 08ed4790..d35b0445 100644 --- a/third_party/WebKit/Source/core/inspector/DevToolsHost.cpp +++ b/third_party/WebKit/Source/core/inspector/DevToolsHost.cpp
@@ -115,11 +115,10 @@ frontend_frame_(frontend_frame), menu_provider_(nullptr) {} -DevToolsHost::~DevToolsHost() { - DCHECK(!client_); -} +DevToolsHost::~DevToolsHost() {} void DevToolsHost::Trace(blink::Visitor* visitor) { + visitor->Trace(client_); visitor->Trace(frontend_frame_); visitor->Trace(menu_provider_); ScriptWrappable::Trace(visitor);
diff --git a/third_party/WebKit/Source/core/inspector/DevToolsHost.h b/third_party/WebKit/Source/core/inspector/DevToolsHost.h index 969f46bdb..02e07b6 100644 --- a/third_party/WebKit/Source/core/inspector/DevToolsHost.h +++ b/third_party/WebKit/Source/core/inspector/DevToolsHost.h
@@ -84,7 +84,7 @@ DevToolsHost(InspectorFrontendClient*, LocalFrame* frontend_frame); void EvaluateScript(const String&); - InspectorFrontendClient* client_; + Member<InspectorFrontendClient> client_; Member<LocalFrame> frontend_frame_; Member<FrontendMenuProvider> menu_provider_; };
diff --git a/third_party/WebKit/Source/core/inspector/InspectorFrontendClient.h b/third_party/WebKit/Source/core/inspector/InspectorFrontendClient.h index b6dcdd4..5d3e63e2 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorFrontendClient.h +++ b/third_party/WebKit/Source/core/inspector/InspectorFrontendClient.h
@@ -39,7 +39,7 @@ class ContextMenuProvider; class LocalFrame; -class InspectorFrontendClient { +class InspectorFrontendClient : public GarbageCollectedMixin { public: virtual ~InspectorFrontendClient() {}
diff --git a/third_party/WebKit/Source/modules/ModulesInitializer.h b/third_party/WebKit/Source/modules/ModulesInitializer.h index 7febcca..288db55 100644 --- a/third_party/WebKit/Source/modules/ModulesInitializer.h +++ b/third_party/WebKit/Source/modules/ModulesInitializer.h
@@ -17,6 +17,8 @@ protected: void InitLocalFrame(LocalFrame&) const override; + void OnClearWindowObjectInMainWorld(Document&, + const Settings&) const override; private: void InstallSupplements(LocalFrame&) const override; @@ -29,8 +31,6 @@ InspectorDOMAgent*, InspectedFrames*, Page*) const override; - void OnClearWindowObjectInMainWorld(Document&, - const Settings&) const override; std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer( WebFrameClient*, HTMLMediaElement&,
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 4ed2ad4..837a121 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -223,6 +223,7 @@ visibility = [] # Allow re-assignment of list. visibility = [ "//components/pdf/common:interfaces_blink", + "//services/device/public/interfaces:interfaces_blink", "//third_party/WebKit/*", "//url/mojo:url_mojom_origin_blink", "//url/mojo:url_mojom_gurl_blink",
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.cpp index 727133ef..e5284df 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.cpp
@@ -38,6 +38,19 @@ // Bucket count for metrics. constexpr int32_t kReportBucketCount = 25; +constexpr char kRendererSideResourceScheduler[] = + "RendererSideResourceScheduler"; + +// These values are copied from resource_scheduler.cc, but the meaning is a bit +// different because ResourceScheduler counts the running delayable requests +// while ResourceLoadScheduler counts all the running requests. +constexpr size_t kTightLimitForRendererSideResourceScheduler = 1u; +constexpr size_t kLimitForRendererSideResourceScheduler = 10u; + +constexpr char kTightLimitForRendererSideResourceSchedulerName[] = + "tight_limit"; +constexpr char kLimitForRendererSideResourceSchedulerName[] = "limit"; + // Represents a resource load circumstance, e.g. from main frame vs sub-frames, // or on throttled state vs on not-throttled state. // Used to report histograms. Do not reorder or insert new items. @@ -54,14 +67,15 @@ return static_cast<base::HistogramBase::Sample>(circumstance); } -uint32_t GetFieldTrialUint32Param(const char* name, uint32_t default_param) { +uint32_t GetFieldTrialUint32Param(const char* trial_name, + const char* parameter_name, + uint32_t default_param) { std::map<std::string, std::string> trial_params; - bool result = - base::GetFieldTrialParams(kResourceLoadSchedulerTrial, &trial_params); + bool result = base::GetFieldTrialParams(trial_name, &trial_params); if (!result) return default_param; - const auto& found = trial_params.find(name); + const auto& found = trial_params.find(parameter_name); if (found == trial_params.end()) return default_param; @@ -75,16 +89,17 @@ uint32_t GetOutstandingThrottledLimit(FetchContext* context) { DCHECK(context); - uint32_t main_frame_limit = - GetFieldTrialUint32Param(kOutstandingLimitForBackgroundMainFrameName, - kOutstandingLimitForBackgroundFrameDefault); + uint32_t main_frame_limit = GetFieldTrialUint32Param( + kResourceLoadSchedulerTrial, kOutstandingLimitForBackgroundMainFrameName, + kOutstandingLimitForBackgroundFrameDefault); if (context->IsMainFrame()) return main_frame_limit; // We do not have a fixed default limit for sub-frames, but use the limit for // the main frame so that it works as how previous versions that haven't // consider sub-frames' specific limit work. - return GetFieldTrialUint32Param(kOutstandingLimitForBackgroundSubFrameName, + return GetFieldTrialUint32Param(kResourceLoadSchedulerTrial, + kOutstandingLimitForBackgroundSubFrameName, main_frame_limit); } @@ -331,15 +346,26 @@ traffic_monitor_ = std::make_unique<ResourceLoadScheduler::TrafficMonitor>( context_->IsMainFrame()); - if (!RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled()) + if (!RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled() && + !Platform::Current()->IsRendererSideResourceSchedulerEnabled()) { return; + } auto* scheduler = context->GetFrameScheduler(); if (!scheduler) return; - if (Platform::Current()->IsRendererSideResourceSchedulerEnabled()) + if (Platform::Current()->IsRendererSideResourceSchedulerEnabled()) { policy_ = context->InitialLoadThrottlingPolicy(); + outstanding_limit_ = + GetFieldTrialUint32Param(kRendererSideResourceScheduler, + kLimitForRendererSideResourceSchedulerName, + kLimitForRendererSideResourceScheduler); + tight_outstanding_limit_ = GetFieldTrialUint32Param( + kRendererSideResourceScheduler, + kTightLimitForRendererSideResourceSchedulerName, + kTightLimitForRendererSideResourceScheduler); + } is_enabled_ = true; scheduler->AddThrottlingObserver(WebFrameScheduler::ObserverType::kLoader, @@ -617,6 +643,10 @@ has_enough_running_requets) { break; } + if (IsThrottablePriority(pending_requests_.begin()->priority) && + has_enough_running_requets) { + break; + } ClientId id = pending_requests_.begin()->client_id; pending_requests_.erase(pending_requests_.begin());
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index 4a3d2f3..7a854fd 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -493,8 +493,6 @@ "web/WebDateTimeSuggestion.h", "web/WebDevToolsAgent.h", "web/WebDevToolsAgentClient.h", - "web/WebDevToolsFrontend.h", - "web/WebDevToolsFrontendClient.h", "web/WebDeviceEmulationParams.h", "web/WebDocument.h", "web/WebDocumentLoader.h", @@ -808,6 +806,7 @@ "platform/reporting.mojom", "platform/site_engagement.mojom", "web/console_message.mojom", + "web/devtools_frontend.mojom", "web/selection_menu_behavior.mojom", "web/shared_worker_creation_context_type.mojom", "web/window_features.mojom",
diff --git a/third_party/WebKit/public/platform/InterfaceRegistry.h b/third_party/WebKit/public/platform/InterfaceRegistry.h index 5725979..c041e2c 100644 --- a/third_party/WebKit/public/platform/InterfaceRegistry.h +++ b/third_party/WebKit/public/platform/InterfaceRegistry.h
@@ -69,9 +69,9 @@ factory) { AddAssociatedInterface( Interface::Name_, - ConvertToBaseCallback(WTF::Bind( + WTF::BindRepeating( &InterfaceRegistry::ForwardToAssociatedInterfaceFactory<Interface>, - std::move(factory)))); + std::move(factory))); } private:
diff --git a/third_party/WebKit/public/web/WebDevToolsFrontend.h b/third_party/WebKit/public/web/WebDevToolsFrontend.h deleted file mode 100644 index 77c33dd..0000000 --- a/third_party/WebKit/public/web/WebDevToolsFrontend.h +++ /dev/null
@@ -1,53 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebDevToolsFrontend_h -#define WebDevToolsFrontend_h - -#include "public/platform/WebCommon.h" - -namespace blink { - -class WebDevToolsFrontendClient; -class WebLocalFrame; - -// WebDevToolsFrontend represents DevTools client sitting in the Glue. It -// provides direct and delegate Apis to the host. -class WebDevToolsFrontend { - public: - BLINK_EXPORT static WebDevToolsFrontend* Create(WebLocalFrame*, - WebDevToolsFrontendClient*); - - virtual ~WebDevToolsFrontend() {} -}; - -} // namespace blink - -#endif
diff --git a/third_party/WebKit/public/web/WebDevToolsFrontendClient.h b/third_party/WebKit/public/web/WebDevToolsFrontendClient.h deleted file mode 100644 index 7d6df9feb..0000000 --- a/third_party/WebKit/public/web/WebDevToolsFrontendClient.h +++ /dev/null
@@ -1,52 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebDevToolsFrontendClient_h -#define WebDevToolsFrontendClient_h - -namespace blink { - -class WebString; - -class WebDevToolsFrontendClient { - public: - WebDevToolsFrontendClient() {} - - virtual void SendMessageToEmbedder(const WebString&) {} - - virtual bool IsUnderTest() { return false; } - - protected: - virtual ~WebDevToolsFrontendClient() {} -}; - -} // namespace blink - -#endif
diff --git a/third_party/WebKit/public/web/devtools_frontend.mojom b/third_party/WebKit/public/web/devtools_frontend.mojom new file mode 100644 index 0000000..46f4827 --- /dev/null +++ b/third_party/WebKit/public/web/devtools_frontend.mojom
@@ -0,0 +1,34 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module blink.mojom; + +// Provides extra capabilities required for DevTools frontend to function. +// This includes communication channel from/to inspected target which implements +// remote debugging protocol. Protocol messages go through browser process. +// +// Instances of this interface must be associated with navigation-related +// interface, since we should setup DevToolsFrontend before the navigation +// commits in the frame. +interface DevToolsFrontend { + // Sets up a main frame as a DevTools frontend. This exposes DevToolsHost + // object (see DevToolsHost.idl for details). The |api_script| is executed + // on each navigation in the frame before the DevTools frontend starts + // loading. It makes use of DevToolsHost to expose embedder capabilities to + // DevTools (e.g. connection to the inspected target). + SetupDevToolsFrontend(string api_script, + associated DevToolsFrontendHost host); + + // Sets up a child frame to expose DevTools extension API by executing script + // |extension_api| on each navigation in the frame. This script provides + // required capabilities for DevTools extensions to function, implementing + // chrome.devtools extension API. + SetupDevToolsExtensionAPI(string extension_api); +}; + +// Provides embedder functionality to a frame serving as DevTools frontend. +interface DevToolsFrontendHost { + // Sends a message to DevTools frontend embedder. + DispatchEmbedderMessage(string message); +};
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 4708f28d..ef326f86 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -24482,6 +24482,7 @@ <int value="-1940291343" label="SpeculativeResourcePrefetching:enabled"/> <int value="-1939016096" label="OmniboxUIExperimentHideSuggestionUrlTrivialSubdomains:enabled"/> + <int value="-1939003674" label="NetworkServiceInProcess:disabled"/> <int value="-1938263248" label="enable-extension-info-dialog"/> <int value="-1937077699" label="http-form-warning"/> <int value="-1933425042" label="OfflinePreviews:enabled"/> @@ -25935,6 +25936,7 @@ <int value="2005614493" label="tab-management-experiment-type-dill"/> <int value="2014331873" label="NTPDownloadSuggestions:disabled"/> <int value="2014629801" label="view-passwords:disabled"/> + <int value="2015547864" label="NetworkServiceInProcess:enabled"/> <int value="2020107447" label="AndroidPayIntegrationV1:enabled"/> <int value="2032558514" label="RemoveUsageOfDeprecatedGaiaSigninEndpoint:enabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 49581f64..f44fa8ba 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -6429,13 +6429,17 @@ <summary>Time spent on 2D canvas putImageData API call.</summary> </histogram> -<histogram name="Blink.Canvas.ToBlob.IdleEncodeDuration" units="microseconds"> +<histogram name="Blink.Canvas.ToBlob.CompleteEncodingDelay" + units="microseconds"> <owner>junov@chromium.org</owner> <owner>xlai@chromium.org</owner> <summary> - This metric measures the total time spent on encoding all the rows of an - image (jpeg or png), as part of a canvas.toBlob API call. Encoding occurs - during one or more idle periods on the main thread. + This metric measures the total time spent on completing encoding all the + rows of an image (jpeg or png), as part of a canvas.toBlob API call. + Encoding occurs during one or more idle periods on the main thread and the + waiting time of the next idle period is included in the measurement. If the + code has swtiched to force encoding path, we will not measure the delay in + this metric. This metric is useful in helping us adjust the IdleTaskCompleteTimeoutDelay in canvas.toBlob. When the encoding idle task is delayed for longer than @@ -6449,6 +6453,20 @@ </summary> </histogram> +<histogram name="Blink.Canvas.ToBlob.IdleEncodeDuration" units="microseconds"> + <obsolete> + Replaced with Blink.Canvas.ToBlob.CompleteEncodingDelay in 2017/12. + </obsolete> + <owner>junov@chromium.org</owner> + <owner>xlai@chromium.org</owner> + <summary> + This metric measures the total time spent on encoding all the rows of an + image (jpeg or png), excluding the waiting time of next idle periods. This + is part of a canvas.toBlob API call. Encoding occurs during one or more idle + periods on the main thread. + </summary> +</histogram> + <histogram name="Blink.Canvas.ToBlob.IdleTaskStatus" enum="IdleTaskStatus"> <owner>junov@chromium.org</owner> <owner>xlai@chromium.org</owner> @@ -99406,7 +99424,12 @@ <histogram_suffixes name="BlinkCanvasToBlobIdleEncodAndDelayType" separator="."> <suffix name="JPEG"/> <suffix name="PNG"/> - <affected-histogram name="Blink.Canvas.ToBlob.IdleEncodeDuration"/> + <affected-histogram name="Blink.Canvas.ToBlob.CompleteEncodingDelay"/> + <affected-histogram name="Blink.Canvas.ToBlob.IdleEncodeDuration"> + <obsolete> + Replaced with Blink.Canvas.ToBlob.CompleteEncodingDelay in 2017/12. + </obsolete> + </affected-histogram> <affected-histogram name="Blink.Canvas.ToBlob.InitiateEncodingDelay"/> </histogram_suffixes>
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc index 07ac3ce..dec50b8b 100644 --- a/ui/aura/test/aura_test_helper.cc +++ b/ui/aura/test/aura_test_helper.cc
@@ -31,7 +31,6 @@ #include "ui/base/ime/input_method_factory.h" #include "ui/base/ime/input_method_initializer.h" #include "ui/base/platform_window_defaults.h" -#include "ui/base/ui_base_switches.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" @@ -121,10 +120,6 @@ capture_client_ = std::make_unique<client::DefaultCaptureClient>(); const Env::Mode env_mode = (mode_ == Mode::LOCAL) ? Env::Mode::LOCAL : Env::Mode::MUS; - if (env_mode == Env::Mode::MUS) { - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kMus, switches::kMusHostVizValue); - } if (mode_ == Mode::MUS_CREATE_WINDOW_TREE_CLIENT) InitWindowTreeClient();
diff --git a/ui/base/models/table_model.cc b/ui/base/models/table_model.cc index d98cdb2..144ba862c 100644 --- a/ui/base/models/table_model.cc +++ b/ui/base/models/table_model.cc
@@ -50,28 +50,6 @@ return base::string16(); } -bool TableModel::ShouldIndent(int row) { - return false; -} - -bool TableModel::HasGroups() { - return false; -} - -TableModel::Groups TableModel::GetGroups() { - // If you override HasGroups to return true, you must override this as - // well. - NOTREACHED(); - return std::vector<Group>(); -} - -int TableModel::GetGroupID(int row) { - // If you override HasGroups to return true, you must override this as - // well. - NOTREACHED(); - return 0; -} - int TableModel::CompareValues(int row1, int row2, int column_id) { DCHECK(row1 >= 0 && row1 < RowCount() && row2 >= 0 && row2 < RowCount());
diff --git a/ui/base/models/table_model.h b/ui/base/models/table_model.h index c7172f4..110ae3c 100644 --- a/ui/base/models/table_model.h +++ b/ui/base/models/table_model.h
@@ -22,16 +22,6 @@ // The model driving the TableView. class UI_BASE_EXPORT TableModel { public: - // See HasGroups, get GetGroupID for details as to how this is used. - struct Group { - // The title text for the group. - base::string16 title; - - // Unique id for the group. - int id; - }; - typedef std::vector<Group> Groups; - // Number of rows in the model. virtual int RowCount() = 0; @@ -49,25 +39,6 @@ // column zero. virtual base::string16 GetTooltip(int row); - // If true, this row should be indented. - virtual bool ShouldIndent(int row); - - // Returns true if the TableView has groups. Groups provide a way to visually - // delineate the rows in a table view. When groups are enabled table view - // shows a visual separator for each group, followed by all the rows in - // the group. - // - // On win2k a visual separator is not rendered for the group headers. - virtual bool HasGroups(); - - // Returns the groups. - // This is only used if HasGroups returns true. - virtual Groups GetGroups(); - - // Returns the group id of the specified row. - // This is only used if HasGroups returns true. - virtual int GetGroupID(int row); - // Sets the observer for the model. The TableView should NOT take ownership // of the observer. virtual void SetObserver(TableModelObserver* observer) = 0;
diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc index 12292c6..73ac986 100644 --- a/ui/compositor/test/in_process_context_provider.cc +++ b/ui/compositor/test/in_process_context_provider.cc
@@ -98,7 +98,8 @@ !window_, /* is_offscreen */ window_, (shared_context_ ? shared_context_->context_.get() : nullptr), attribs_, gpu::SharedMemoryLimits(), gpu_memory_buffer_manager_, - image_factory_, base::ThreadTaskRunnerHandle::Get()); + image_factory_, nullptr /* gpu_channel_manager_delegate */, + base::ThreadTaskRunnerHandle::Get()); if (bind_result_ != gpu::ContextResult::kSuccess) return bind_result_;
diff --git a/ui/gfx/win/rendering_window_manager.cc b/ui/gfx/win/rendering_window_manager.cc index a0528ecf..4f2cbfb7 100644 --- a/ui/gfx/win/rendering_window_manager.cc +++ b/ui/gfx/win/rendering_window_manager.cc
@@ -4,7 +4,10 @@ #include "ui/gfx/win/rendering_window_manager.h" +#include "base/callback.h" #include "base/memory/singleton.h" +#include "base/task_scheduler/post_task.h" +#include "base/task_scheduler/task_traits.h" namespace gfx { @@ -16,11 +19,11 @@ void RenderingWindowManager::RegisterParent(HWND parent) { base::AutoLock lock(lock_); - info_[parent] = nullptr; + info_.emplace(parent, EmeddingInfo()); } -bool RenderingWindowManager::RegisterChild(HWND parent, HWND child_window) { - if (!child_window) +bool RenderingWindowManager::RegisterChild(HWND parent, HWND child) { + if (!child) return false; base::AutoLock lock(lock_); @@ -28,10 +31,22 @@ auto it = info_.find(parent); if (it == info_.end()) return false; - if (it->second) + + EmeddingInfo& info = it->second; + if (info.child) return false; - info_[parent] = child_window; + info.child = child; + + // DoSetParentOnChild() was already called for |parent|. Call ::SetParent() + // now but from a worker thread instead of the IO thread. The ::SetParent() + // call could block the IO thread waiting on the UI thread and deadlock. + if (info.call_set_parent) { + base::PostTaskWithTraits( + FROM_HERE, {base::TaskPriority::USER_BLOCKING}, + base::BindOnce(base::IgnoreResult(&::SetParent), child, parent)); + } + return true; } @@ -43,9 +58,17 @@ auto it = info_.find(parent); if (it == info_.end()) return; - if (!it->second) + + EmeddingInfo& info = it->second; + + DCHECK(!info.call_set_parent); + info.call_set_parent = true; + + // Call ::SetParent() once RegisterChild() is called. + if (!info.child) return; - child = it->second; + + child = info.child; } ::SetParent(child, parent); @@ -61,7 +84,7 @@ auto it = info_.find(parent); if (it == info_.end()) return false; - return !!it->second && ::IsWindow(it->second); + return !!it->second.child && ::IsWindow(it->second.child); } RenderingWindowManager::RenderingWindowManager() {}
diff --git a/ui/gfx/win/rendering_window_manager.h b/ui/gfx/win/rendering_window_manager.h index bbb74ac..454e9dd 100644 --- a/ui/gfx/win/rendering_window_manager.h +++ b/ui/gfx/win/rendering_window_manager.h
@@ -7,8 +7,7 @@ #include <windows.h> -#include <map> - +#include "base/containers/flat_map.h" #include "base/synchronization/lock.h" #include "ui/gfx/gfx_export.h" @@ -34,11 +33,19 @@ private: friend struct base::DefaultSingletonTraits<RenderingWindowManager>; + struct EmeddingInfo { + // The child window. + HWND child = nullptr; + + // SetParent() should be called for child window. + bool call_set_parent = false; + }; + RenderingWindowManager(); ~RenderingWindowManager(); base::Lock lock_; - std::map<HWND, HWND> info_; + base::flat_map<HWND, EmeddingInfo> info_; DISALLOW_COPY_AND_ASSIGN(RenderingWindowManager); };
diff --git a/ui/gl/init/create_gr_gl_interface.cc b/ui/gl/init/create_gr_gl_interface.cc index c48be07..e7b1c6e 100644 --- a/ui/gl/init/create_gr_gl_interface.cc +++ b/ui/gl/init/create_gr_gl_interface.cc
@@ -87,6 +87,7 @@ functions->fBindAttribLocation = gl->glBindAttribLocationFn; functions->fBindBuffer = gl->glBindBufferFn; functions->fBindFragDataLocation = gl->glBindFragDataLocationFn; + functions->fBindUniformLocation = gl->glBindUniformLocationCHROMIUMFn; functions->fBeginQuery = gl->glBeginQueryFn; functions->fBindTexture = gl->glBindTextureFn;