diff --git a/BUILD.gn b/BUILD.gn index 92a85782..c3e85d9c 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -947,7 +947,10 @@ } if (is_fuchsia) { - data_deps += [ "//content/shell:content_shell_fuchsia" ] + data_deps += [ + "//content/shell:content_shell_fuchsia", + "//build/fuchsia/layout_test_proxy:layout_test_proxy_runner", + ] } data = [
diff --git a/DEPS b/DEPS index 4664246..61ea18e5 100644 --- a/DEPS +++ b/DEPS
@@ -79,11 +79,11 @@ # 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': 'b1b80f7de4224c5083dfc1475e1988b2ce839a65', + 'skia_revision': '16d0ad06b46841c78cce816406574314fab95c13', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '7199784766ca3b3926eefc39ab7d748e954acc24', + 'v8_revision': 'a998a1a64bdc4eea999ab37457d84b3792760cd8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -103,7 +103,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '27d718ebb2989631d6b4d3425e1fceb4b3bc795b', + 'pdfium_revision': '5ca283f376816522065c0ea35644fcb684f9572f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -135,7 +135,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '3318544c51d46d3165d7fb9929da58bb2049574b', + 'catapult_revision': 'c4b36e2d9b77e6ae89274fa33a982f8efea1b948', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -649,7 +649,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd458ada06171a85af00367251a4ed55db7fe2018', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '4aa8ab5d568d562aa1a28829bedce902429916d8', # commit position 20628 + Var('webrtc_git') + '/src.git' + '@' + '565e3e07d7bad8f877ecd83ad0454272aa9ebb92', # commit position 20628 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java index e95e04c..5336ac6 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java +++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
@@ -236,7 +236,7 @@ @Override public void autofill(final SparseArray<AutofillValue> values) { - if (mNativeAutofillProvider != 0 && mRequest.autofill((values))) { + if (mNativeAutofillProvider != 0 && mRequest != null && mRequest.autofill((values))) { autofill(mNativeAutofillProvider, mRequest.mFormData); } } @@ -366,8 +366,9 @@ @Override protected void reset() { - mAutofillManager.cancel(); - mRequest = null; + // We don't need to reset anything here, it should be safe to cancel + // current autofill session when new one starts in + // startAutofillSession(). } @Override @@ -382,7 +383,7 @@ // possible to know which case we're in, so just catch and // ignore the exception. try { - if (mNativeAutofillProvider != 0) reset(); + if (mNativeAutofillProvider != 0) mRequest = null; mNativeAutofillProvider = nativeAutofillProvider; if (nativeAutofillProvider == 0) mAutofillManager.destroy(); } catch (IllegalStateException e) { @@ -392,7 +393,7 @@ @Override public void setWebContents(WebContents webContents) { if (webContents == mWebContents) return; - if (mWebContents != null) reset(); + if (mWebContents != null) mRequest = null; mWebContents = webContents; }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java index 71a0d8b1..58a5ad0d 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -818,8 +818,8 @@ // Submit form. executeJavaScriptAndWaitForResult("document.getElementById('formid').submit();"); waitForCallbackAndVerifyTypes(cnt, - new Integer[] {AUTOFILL_VALUE_CHANGED, AUTOFILL_VALUE_CHANGED, AUTOFILL_COMMIT, - AUTOFILL_CANCEL}); + new Integer[] { + AUTOFILL_VALUE_CHANGED, AUTOFILL_VALUE_CHANGED, AUTOFILL_COMMIT}); ArrayList<Pair<Integer, AutofillValue>> values = getChangedValues(); assertEquals(2, values.size()); assertEquals("a", values.get(0).second.getTextValue());
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index e45b9a4..660f49e 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1220,6 +1220,11 @@ <message name="IDS_ASH_MESSAGE_CENTER_NO_NOTIFIERS" desc="The message displayed in the message center when there are no notification sources."> Nothing to see just yet </message> + + <!-- Window Control --> + <message name="IDS_ASH_WINDOW_CONTROL_ACCNAME_BACK" desc="The accessible name for the back button on the window frame."> + Back button + </message> </messages> </release> </grit>
diff --git a/ash/frame/caption_buttons/frame_back_button.cc b/ash/frame/caption_buttons/frame_back_button.cc index f72ecd7a..85dae24 100644 --- a/ash/frame/caption_buttons/frame_back_button.cc +++ b/ash/frame/caption_buttons/frame_back_button.cc
@@ -7,8 +7,11 @@ #include "ash/ash_layout_constants.h" #include "ash/frame/caption_buttons/frame_caption_button.h" #include "ash/resources/vector_icons/vector_icons.h" +#include "ash/strings/grit/ash_strings.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" #include "ui/events/event_sink.h" #include "ui/views/widget/widget.h" @@ -18,6 +21,8 @@ : FrameCaptionButton(this, CAPTION_BUTTON_ICON_BACK) { SetImage(CAPTION_BUTTON_ICON_BACK, ANIMATE_NO, kWindowControlBackIcon); SetPreferredSize(GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON)); + SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ASH_WINDOW_CONTROL_ACCNAME_BACK)); } FrameBackButton::~FrameBackButton() = default;
diff --git a/ash/resources/vector_icons/window_control_back.1x.icon b/ash/resources/vector_icons/window_control_back.1x.icon index e77cf8c..54a037c 100644 --- a/ash/resources/vector_icons/window_control_back.1x.icon +++ b/ash/resources/vector_icons/window_control_back.1x.icon
@@ -4,15 +4,16 @@ CANVAS_DIMENSIONS, 12, FLIPS_IN_RTL, -MOVE_TO, 3.9f, 5.25f, -H_LINE_TO, 11.25f, -R_V_LINE_TO, 1.5f, -H_LINE_TO, 3.9f, -R_LINE_TO, 4.6, 3.6f, -LINE_TO, 6.68f, 11.25f, -LINE_TO, 1.5f, 6, -R_LINE_TO, 5.18f, -5.25f, -LINE_TO, 7.5f, 1.65f, -LINE_TO, 3.9f, 5.25f, +MOVE_TO, 4.92f, 5, +H_LINE_TO, 11, +R_V_LINE_TO, 2, +H_LINE_TO, 4.92f, +LINE_TO, 8, 9.75f, +LINE_TO, 6.6f, 11, +LINE_TO, 1, 6, +R_LINE_TO, 0.7f, -0.62f, +LINE_TO, 6.6f, 1, +LINE_TO, 8, 2.25f, +LINE_TO, 4.92f, 5, CLOSE, END
diff --git a/ash/resources/vector_icons/window_control_back.icon b/ash/resources/vector_icons/window_control_back.icon index 3c73e90e..679d4d1 100644 --- a/ash/resources/vector_icons/window_control_back.icon +++ b/ash/resources/vector_icons/window_control_back.icon
@@ -4,14 +4,17 @@ CANVAS_DIMENSIONS, 24, FLIPS_IN_RTL, -MOVE_TO, 6.42f, 13.49f, -R_LINE_TO, 7.24f, 7.49f, -LINE_TO, 12.14f, 22.5f, -LINE_TO, 2.25f, 12.37f, -LINE_TO, 12.14f, 2.25f, -R_LINE_TO, 1.52, 1.5f, -R_LINE_TO, -7.4f, 7.49f, -H_LINE_TO, 21.75, -R_V_LINE_TO, 2.25f, +MOVE_TO, 6.83f, 10, +H_LINE_TO, 23, +R_V_LINE_TO, 3, +H_LINE_TO, 6.83f, +LINE_TO, 15, 20.96f, +LINE_TO, 12.86f, 23, +LINE_TO, 4.93f, 15.25f, +LINE_TO, 1, 11.5f, +R_LINE_TO, 5, -4.77f, +LINE_TO, 12.86f, 0, +LINE_TO, 15, 2.05f, +LINE_TO, 6.83f, 10, CLOSE, END
diff --git a/ash/session/session_controller.cc b/ash/session/session_controller.cc index 2b7db287..101897d 100644 --- a/ash/session/session_controller.cc +++ b/ash/session/session_controller.cc
@@ -116,10 +116,6 @@ !(state_ == SessionState::LOCKED && is_unlocking_); } -bool SessionController::IsUnlocking() const { - return is_unlocking_; -} - bool SessionController::IsInSecondaryLoginScreen() const { return state_ == SessionState::LOGIN_SECONDARY; }
diff --git a/ash/session/session_controller.h b/ash/session/session_controller.h index b604075..551e0d9b 100644 --- a/ash/session/session_controller.h +++ b/ash/session/session_controller.h
@@ -80,9 +80,6 @@ // session. bool IsUserSessionBlocked() const; - // Returns whether session unlocking is in progress. - bool IsUnlocking() const; - // Convenience function that returns true if session state is LOGIN_SECONDARY. bool IsInSecondaryLoginScreen() const;
diff --git a/ash/shell/OWNERS b/ash/shell/OWNERS new file mode 100644 index 0000000..c8dc16e --- /dev/null +++ b/ash/shell/OWNERS
@@ -0,0 +1 @@ +per-file *app_list*=xiyuan@chromium.org
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc index f1fc7622..c54c236c 100644 --- a/ash/shell/app_list.cc +++ b/ash/shell/app_list.cc
@@ -267,6 +267,10 @@ // Nothing needs to be done. } + void ViewShown() override { + // Nothing needs to be done. + } + void Dismiss() override { DCHECK(ShellPort::HasInstance()); Shell::Get()->app_list()->Dismiss();
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index 367ba16c..c3e8c02 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -1368,9 +1368,7 @@ bool is_wallpaper_blurred = false; auto* session_controller = Shell::Get()->session_controller(); - if ((session_controller->IsUserSessionBlocked() || - session_controller->IsUnlocking()) && - IsBlurEnabled()) { + if (session_controller->IsUserSessionBlocked() && IsBlurEnabled()) { component->SetWallpaperBlur(login_constants::kBlurSigma); is_wallpaper_blurred = true; }
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc index 8337500..0ca9522 100644 --- a/base/allocator/partition_allocator/partition_alloc.cc +++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -34,6 +34,9 @@ static_assert(base::kPageMetadataSize * base::kNumPartitionPagesPerSuperPage <= base::kSystemPageSize, "page metadata fits in hole"); +// Limit to prevent callers accidentally overflowing an int size. +static_assert(base::kGenericMaxDirectMapped <= 1UL << 31, + "maximum direct mapped allocation"); // Check that some of our zanier calculations worked out as expected. static_assert(base::kGenericSmallestBucket == 8, "generic smallest bucket"); static_assert(base::kGenericMaxBucketed == 983040, "generic max bucketed");
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h index df8a7fe..6e5143b 100644 --- a/base/allocator/partition_allocator/partition_alloc.h +++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -206,7 +206,7 @@ static const size_t kGenericMinDirectMappedDownsize = kGenericMaxBucketed + 1; // Limit when downsizing a direct mapping using realloc(). -static const size_t kGenericMaxDirectMapped = INT_MAX - kSystemPageSize; +static const size_t kGenericMaxDirectMapped = 1UL << 31; // 2 GiB static const size_t kBitsPerSizeT = sizeof(void*) * CHAR_BIT; // Constants for the memory reclaim logic.
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index 8ccac5b..b84db9b7 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -859,7 +859,7 @@ } // Too large allocation. - requested_size = INT_MAX; + requested_size = kGenericMaxDirectMapped + 1; predicted_size = generic_allocator.root()->ActualSize(requested_size); EXPECT_EQ(requested_size, predicted_size); } @@ -1385,9 +1385,9 @@ EXPECT_DEATH( generic_allocator.root()->Alloc(static_cast<size_t>(-1), type_name), ""); // And the smallest allocation we expect to die. - EXPECT_DEATH(generic_allocator.root()->Alloc(static_cast<size_t>(INT_MAX) + 1, - type_name), - ""); + EXPECT_DEATH( + generic_allocator.root()->Alloc(kGenericMaxDirectMapped + 1, type_name), + ""); } // Check that our immediate double-free detection works.
diff --git a/base/optional.h b/base/optional.h index f6619a5..34e36fa 100644 --- a/base/optional.h +++ b/base/optional.h
@@ -44,6 +44,15 @@ // When T is not trivially destructible we must call its // destructor before deallocating its memory. + // Note that this hides the (implicitly declared) move constructor, which + // would be used for constexpr move constructor in OptionalStorage<T>. + // It is needed iff T is trivially move constructible. However, the current + // is_trivially_{copy,move}_constructible implementation requires + // is_trivially_destructible (which looks a bug, cf: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and + // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not + // necessary for this case at the moment. Please see also the destructor + // comment in "is_trivially_destructible = true" specialization below. ~OptionalStorageBase() { if (!is_null_) value_.~T(); @@ -77,9 +86,18 @@ : is_null_(false), value_(std::forward<Args>(args)...) {} // When T is trivially destructible (i.e. its destructor does nothing) there - // is no need to call it. Explicitly defaulting the destructor means it's not - // user-provided. Those two together make this destructor trivial. - ~OptionalStorageBase() = default; + // is no need to call it. Implicitly defined destructor is trivial, because + // both members (bool and union containing only variants which are trivially + // destructible) are trivially destructible. + // Explicitly-defaulted destructor is also trivial, but do not use it here, + // because it hides the implicit move constructor. It is needed to implement + // constexpr move constructor in OptionalStorage iff T is trivially move + // constructible. Note that, if T is trivially move constructible, the move + // constructor of OptionalStorageBase<T> is also implicitly defined and it is + // trivially move constructor. If T is not trivially move constructible, + // "not declaring move constructor without destructor declaration" here means + // "delete move constructor", which works because any move constructor of + // OptionalStorage will not refer to it in that case. template <class... Args> void Init(Args&&... args) {
diff --git a/base/optional_unittest.cc b/base/optional_unittest.cc index 91e63e7..7cc05ef2 100644 --- a/base/optional_unittest.cc +++ b/base/optional_unittest.cc
@@ -115,6 +115,35 @@ int foo_; }; +class DeletedCopyConstructor { + public: + explicit DeletedCopyConstructor(int foo) : foo_(foo) {} + DeletedCopyConstructor(const DeletedCopyConstructor&) = delete; + DeletedCopyConstructor(DeletedCopyConstructor&&) = default; + + int foo() const { return foo_; } + + private: + int foo_; +}; + +class NonTriviallyDestructibleDeletedCopyConstructor { + public: + explicit NonTriviallyDestructibleDeletedCopyConstructor(int foo) + : foo_(foo) {} + NonTriviallyDestructibleDeletedCopyConstructor( + const NonTriviallyDestructibleDeletedCopyConstructor&) = delete; + NonTriviallyDestructibleDeletedCopyConstructor( + NonTriviallyDestructibleDeletedCopyConstructor&&) = default; + + ~NonTriviallyDestructibleDeletedCopyConstructor() {} + + int foo() const { return foo_; } + + private: + int foo_; +}; + class DeleteNewOperators { public: void* operator new(size_t) = delete; @@ -169,6 +198,15 @@ } { + const Optional<std::string> first("foo"); + Optional<std::string> other(first); + + EXPECT_TRUE(other); + EXPECT_EQ(other.value(), "foo"); + EXPECT_EQ(first, other); + } + + { Optional<TestObject> first(TestObject(3, 0.1)); Optional<TestObject> other(first); @@ -210,33 +248,57 @@ constexpr Optional<float> first(0.1f); constexpr Optional<float> second(std::move(first)); - EXPECT_TRUE(second); + EXPECT_TRUE(second.has_value()); EXPECT_EQ(second.value(), 0.1f); - EXPECT_TRUE(first); + EXPECT_TRUE(first.has_value()); } { Optional<std::string> first("foo"); Optional<std::string> second(std::move(first)); - EXPECT_TRUE(second); + EXPECT_TRUE(second.has_value()); EXPECT_EQ("foo", second.value()); - EXPECT_TRUE(first); + EXPECT_TRUE(first.has_value()); } { Optional<TestObject> first(TestObject(3, 0.1)); Optional<TestObject> second(std::move(first)); - EXPECT_TRUE(!!second); + EXPECT_TRUE(second.has_value()); EXPECT_EQ(TestObject::State::MOVE_CONSTRUCTED, second->state()); EXPECT_TRUE(TestObject(3, 0.1) == second.value()); - EXPECT_TRUE(!!first); + EXPECT_TRUE(first.has_value()); EXPECT_EQ(TestObject::State::MOVED_FROM, first->state()); } + + // Even if copy constructor is deleted, move constructor needs to work. + // Note that it couldn't be constexpr. + { + Optional<DeletedCopyConstructor> first(in_place, 42); + Optional<DeletedCopyConstructor> second(std::move(first)); + + EXPECT_TRUE(second.has_value()); + EXPECT_EQ(42, second->foo()); + + EXPECT_TRUE(first.has_value()); + } + + { + Optional<NonTriviallyDestructibleDeletedCopyConstructor> first(in_place, + 42); + Optional<NonTriviallyDestructibleDeletedCopyConstructor> second( + std::move(first)); + + EXPECT_TRUE(second.has_value()); + EXPECT_EQ(42, second->foo()); + + EXPECT_TRUE(first.has_value()); + } } TEST(OptionalTest, MoveValueConstructor) {
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h index 29ee0ab..779daa7 100644 --- a/base/process/process_metrics.h +++ b/base/process/process_metrics.h
@@ -38,25 +38,8 @@ namespace base { -#if defined(OS_WIN) -// _WINDOWS_ will be defined if Windows.h was included - include Windows.h first -// to get access to the full struct definition. -#if defined(_WINDOWS_) -struct IoCounters : public IO_COUNTERS { -}; -#else +// Full declaration is in process_metrics_iocounters.h. struct IoCounters; -#endif -#elif defined(OS_POSIX) -struct IoCounters { - uint64_t ReadOperationCount; - uint64_t WriteOperationCount; - uint64_t OtherOperationCount; - uint64_t ReadTransferCount; - uint64_t WriteTransferCount; - uint64_t OtherTransferCount; -}; -#endif // Working Set (resident) memory usage broken down by //
diff --git a/base/process/process_metrics_freebsd.cc b/base/process/process_metrics_freebsd.cc index 10d0868d..ebbaaaf 100644 --- a/base/process/process_metrics_freebsd.cc +++ b/base/process/process_metrics_freebsd.cc
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/process/process_metrics_iocounters.h" namespace base {
diff --git a/base/process/process_metrics_iocounters.h b/base/process/process_metrics_iocounters.h new file mode 100644 index 0000000..e12d090 --- /dev/null +++ b/base/process/process_metrics_iocounters.h
@@ -0,0 +1,37 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a separate file so that users of process metrics don't need to +// include windows.h unless they need IoCounters. + +#ifndef BASE_PROCESS_PROCESS_METRICS_IOCOUNTERS_H_ +#define BASE_PROCESS_PROCESS_METRICS_IOCOUNTERS_H_ + +#include <stdint.h> + +#include "base/process/process_metrics.h" +#include "build/build_config.h" + +#if defined(OS_WIN) +#include <windows.h> +#endif + +namespace base { + +#if defined(OS_WIN) +struct IoCounters : public IO_COUNTERS {}; +#elif defined(OS_POSIX) +struct IoCounters { + uint64_t ReadOperationCount; + uint64_t WriteOperationCount; + uint64_t OtherOperationCount; + uint64_t ReadTransferCount; + uint64_t WriteTransferCount; + uint64_t OtherTransferCount; +}; +#endif + +} // namespace base + +#endif // BASE_PROCESS_PROCESS_METRICS_IOCOUNTERS_H_
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc index d8c1e1c1..5997713 100644 --- a/base/process/process_metrics_linux.cc +++ b/base/process/process_metrics_linux.cc
@@ -20,6 +20,7 @@ #include "base/memory/ptr_util.h" #include "base/optional.h" #include "base/process/internal_linux.h" +#include "base/process/process_metrics_iocounters.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h"
diff --git a/base/process/process_metrics_mac.cc b/base/process/process_metrics_mac.cc index 98793ff..276104e 100644 --- a/base/process/process_metrics_mac.cc +++ b/base/process/process_metrics_mac.cc
@@ -19,6 +19,7 @@ #include "base/memory/ptr_util.h" #include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" +#include "base/process/process_metrics_iocounters.h" namespace base {
diff --git a/base/process/process_metrics_openbsd.cc b/base/process/process_metrics_openbsd.cc index c863313..77b43bd1 100644 --- a/base/process/process_metrics_openbsd.cc +++ b/base/process/process_metrics_openbsd.cc
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/process/process_metrics_iocounters.h" namespace base {
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc index 76f09f52..61f0bf4 100644 --- a/base/process/process_metrics_win.cc +++ b/base/process/process_metrics_win.cc
@@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Must be included before process_metrics.h to get full IoCounters definition -#include <windows.h> - #include "base/process/process_metrics.h" +#include <windows.h> // Must be in front of other Windows header files. + #include <psapi.h> #include <stddef.h> #include <stdint.h> @@ -17,12 +16,9 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/process/memory.h" +#include "base/process/process_metrics_iocounters.h" #include "base/sys_info.h" -#if defined(OS_WIN) -#include <windows.h> -#endif - namespace base { namespace {
diff --git a/base/win/win_client_metrics.h b/base/win/win_client_metrics.h new file mode 100644 index 0000000..102148f --- /dev/null +++ b/base/win/win_client_metrics.h
@@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is separate from base/win/win_util.h to avoid pulling windows.h +// into too many translation units. + +#ifndef BASE_WIN_WIN_CLIENT_METRICS_H_ +#define BASE_WIN_WIN_CLIENT_METRICS_H_ + +#include <windows.h> + +// This is the same as NONCLIENTMETRICS except that the +// unused member |iPaddedBorderWidth| has been removed. +struct NONCLIENTMETRICS_XP { + UINT cbSize; + int iBorderWidth; + int iScrollWidth; + int iScrollHeight; + int iCaptionWidth; + int iCaptionHeight; + LOGFONTW lfCaptionFont; + int iSmCaptionWidth; + int iSmCaptionHeight; + LOGFONTW lfSmCaptionFont; + int iMenuWidth; + int iMenuHeight; + LOGFONTW lfMenuFont; + LOGFONTW lfStatusFont; + LOGFONTW lfMessageFont; +}; + +namespace base { +namespace win { + +BASE_EXPORT void GetNonClientMetrics(NONCLIENTMETRICS_XP* metrics); + +} // namespace win +} // namespace base + +#endif // BASE_WIN_WIN_CLIENT_METRICS_H_
diff --git a/base/win/win_util.cc b/base/win/win_util.cc index 0d45d41f..debe6cf8 100644 --- a/base/win/win_util.cc +++ b/base/win/win_util.cc
@@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Must be included before process_metrics.h to get full IoCounters definition -#include <windows.h> - #include "base/win/win_util.h" #include <aclapi.h> @@ -53,6 +50,7 @@ #include "base/win/scoped_handle.h" #include "base/win/scoped_hstring.h" #include "base/win/scoped_propvariant.h" +#include "base/win/win_client_metrics.h" #include "base/win/windows_version.h" namespace base {
diff --git a/base/win/win_util.h b/base/win/win_util.h index 80da69e..9d2f858 100644 --- a/base/win/win_util.h +++ b/base/win/win_util.h
@@ -35,32 +35,6 @@ struct _tagpropertykey; typedef _tagpropertykey PROPERTYKEY; -// _WINDOWS_ will be defined if Windows.h was included - include Windows.h first -// to get access to the full struct definition. -#if defined(_WINDOWS_) -// This is the same as NONCLIENTMETRICS except that the -// unused member |iPaddedBorderWidth| has been removed. -struct NONCLIENTMETRICS_XP { - UINT cbSize; - int iBorderWidth; - int iScrollWidth; - int iScrollHeight; - int iCaptionWidth; - int iCaptionHeight; - LOGFONTW lfCaptionFont; - int iSmCaptionWidth; - int iSmCaptionHeight; - LOGFONTW lfSmCaptionFont; - int iMenuWidth; - int iMenuHeight; - LOGFONTW lfMenuFont; - LOGFONTW lfStatusFont; - LOGFONTW lfMessageFont; -}; -#else -struct NONCLIENTMETRICS_XP; -#endif - namespace base { namespace win { @@ -77,8 +51,6 @@ static_cast<uintptr_t>(static_cast<int32_t>(h))); } -BASE_EXPORT void GetNonClientMetrics(NONCLIENTMETRICS_XP* metrics); - // Returns the string representing the current user sid. BASE_EXPORT bool GetUserSidString(std::wstring* user_sid);
diff --git a/base/win/win_util_unittest.cc b/base/win/win_util_unittest.cc index db6f7ef0..a0dbdd3 100644 --- a/base/win/win_util_unittest.cc +++ b/base/win/win_util_unittest.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <windows.h> +#include "base/win/win_util.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/scoped_native_library.h" -#include "base/win/win_util.h" +#include "base/win/win_client_metrics.h" #include "testing/gtest/include/gtest/gtest.h" namespace base {
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index 6fddf3d0..7f07aad 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -156,10 +156,12 @@ # TODO(pcc): Enable lld on more architectures on Linux. E.g. we probably need # to fix some of crbug.com/742655 to enable it on ARM. # TODO(pcc): Remove !is_msan once crbug.com/772559 is fixed. - use_lld = is_clang && !is_msan && - ((is_win && host_os != "win") || is_fuchsia || - (use_thin_lto && target_os != "chromeos") || - (is_linux && current_cpu == "x64" && target_os != "chromeos")) + use_lld = + is_clang && !is_msan && + ((is_win && host_os != "win") || is_fuchsia || + (use_thin_lto && target_os != "chromeos") || + (is_linux && current_cpu == "x64" && target_os != "chromeos") || + (is_android && current_cpu != "mipsel" && current_cpu != "mips64el")) } declare_args() {
diff --git a/build/fuchsia/layout_test_proxy/BUILD.gn b/build/fuchsia/layout_test_proxy/BUILD.gn new file mode 100644 index 0000000..43ed152 --- /dev/null +++ b/build/fuchsia/layout_test_proxy/BUILD.gn
@@ -0,0 +1,27 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +assert(is_fuchsia) + +import("//testing/test.gni") + +# Binary used to proxy TCP connections from a Fuchsia process. Potentially SSH +# can be used to forward TCP, but this feature is currently broken on Fuchsia, +# see ZX-1555. layout_test_proxy can be removed once that issue with sshd is +# fixed and layout tests are updated to use SSH. +executable("layout_test_proxy") { + testonly = true + sources = [ + "layout_test_proxy.cc", + ] + deps = [ + "//net", + "//net:test_support", + ] +} + +fuchsia_executable_runner("layout_test_proxy_runner") { + testonly = true + exe_target = ":layout_test_proxy" +}
diff --git a/build/fuchsia/layout_test_proxy/DEPS b/build/fuchsia/layout_test_proxy/DEPS new file mode 100644 index 0000000..b2f6f8e --- /dev/null +++ b/build/fuchsia/layout_test_proxy/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+net", +] \ No newline at end of file
diff --git a/build/fuchsia/layout_test_proxy/layout_test_proxy.cc b/build/fuchsia/layout_test_proxy/layout_test_proxy.cc new file mode 100644 index 0000000..1d14df99 --- /dev/null +++ b/build/fuchsia/layout_test_proxy/layout_test_proxy.cc
@@ -0,0 +1,78 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "net/base/ip_endpoint.h" +#include "net/test/tcp_socket_proxy.h" + +const char kPortsSwitch[] = "ports"; +const char kRemoteAddressSwitch[] = "remote-address"; + +int main(int argc, char** argv) { + base::CommandLine::Init(argc, argv); + + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + + if (!command_line->HasSwitch(kPortsSwitch)) { + LOG(ERROR) << "--" << kPortsSwitch << " was not specified."; + return 1; + } + + std::vector<std::string> ports_strings = + base::SplitString(command_line->GetSwitchValueASCII(kPortsSwitch), ",", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (ports_strings.empty()) { + LOG(ERROR) << "At least one port must be specified with --" << kPortsSwitch; + return 1; + } + + std::vector<int> ports; + for (auto& port_string : ports_strings) { + int port; + if (!base::StringToInt(port_string, &port) || port <= 0 || port > 65535) { + LOG(ERROR) << "Invalid value specified for --" << kPortsSwitch << ": " + << port_string; + return 1; + } + ports.push_back(port); + } + + if (!command_line->HasSwitch(kRemoteAddressSwitch)) { + LOG(ERROR) << "--" << kRemoteAddressSwitch << " was not specified."; + return 1; + } + + std::string remote_address_str = + command_line->GetSwitchValueASCII(kRemoteAddressSwitch); + net::IPAddress remote_address; + if (!remote_address.AssignFromIPLiteral(remote_address_str)) { + LOG(ERROR) << "Invalid value specified for --" << kRemoteAddressSwitch + << ": " << remote_address_str; + return 1; + } + + base::MessageLoopForIO message_loop; + + std::vector<std::unique_ptr<net::TcpSocketProxy>> proxies; + + for (int port : ports) { + auto test_server_proxy = + std::make_unique<net::TcpSocketProxy>(message_loop.task_runner()); + if (!test_server_proxy->Initialize(port)) { + LOG(ERROR) << "Can't bind proxy to port " << port; + return 1; + } + LOG(INFO) << "Listening on port " << test_server_proxy->local_port(); + test_server_proxy->Start(net::IPEndPoint(remote_address, port)); + proxies.push_back(std::move(test_server_proxy)); + } + + // Run the message loop indefinitely. + base::RunLoop().Run(); + + return 0; +} \ No newline at end of file
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc index 3beadab..8b68ef0c 100644 --- a/cc/paint/paint_op_reader.cc +++ b/cc/paint/paint_op_reader.cc
@@ -648,8 +648,8 @@ BlurPaintFilter::TileMode tile_mode = SkBlurImageFilter::kClamp_TileMode; sk_sp<PaintFilter> input; - ReadSimple(&sigma_x); - ReadSimple(&sigma_y); + Read(&sigma_x); + Read(&sigma_y); ReadSimple(&tile_mode); Read(&input); if (!valid_) @@ -671,11 +671,11 @@ SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode; sk_sp<PaintFilter> input; - ReadSimple(&dx); - ReadSimple(&dy); - ReadSimple(&sigma_x); - ReadSimple(&sigma_y); - ReadSimple(&color); + Read(&dx); + Read(&dy); + Read(&sigma_x); + Read(&sigma_y); + Read(&color); ReadSimple(&shadow_mode); Read(&input); @@ -695,8 +695,8 @@ SkScalar inset = 0.f; sk_sp<PaintFilter> input; - ReadSimple(&src_rect); - ReadSimple(&inset); + Read(&src_rect); + Read(&inset); Read(&input); if (!valid_) return; @@ -743,7 +743,7 @@ sk_sp<PaintFilter> background; sk_sp<PaintFilter> foreground; - ReadSimple(&blend_mode_int); + Read(&blend_mode_int); Read(&background); Read(&foreground); SkBlendMode blend_mode = SkBlendMode::kClear; @@ -768,11 +768,11 @@ bool enforce_pm_color = false; sk_sp<PaintFilter> background; sk_sp<PaintFilter> foreground; - ReadSimple(&k1); - ReadSimple(&k2); - ReadSimple(&k3); - ReadSimple(&k4); - ReadSimple(&enforce_pm_color); + Read(&k1); + Read(&k2); + Read(&k3); + Read(&k4); + Read(&enforce_pm_color); Read(&background); Read(&foreground); if (!valid_) @@ -804,12 +804,12 @@ } std::vector<SkScalar> kernel(size); for (size_t i = 0; i < size; ++i) - ReadSimple(&kernel[i]); - ReadSimple(&gain); - ReadSimple(&bias); + Read(&kernel[i]); + Read(&gain); + Read(&bias); ReadSimple(&kernel_offset); - ReadSimple(&tile_mode_int); - ReadSimple(&convolve_alpha); + Read(&tile_mode_int); + Read(&convolve_alpha); Read(&input); if (tile_mode_int > SkMatrixConvolutionImageFilter::kMax_TileMode) SetInvalid(); @@ -834,9 +834,9 @@ sk_sp<PaintFilter> displacement; sk_sp<PaintFilter> color; - ReadSimple(&channel_x_int); - ReadSimple(&channel_y_int); - ReadSimple(&scale); + Read(&channel_x_int); + Read(&channel_y_int); + Read(&scale); Read(&displacement); Read(&color); @@ -885,7 +885,7 @@ const base::Optional<PaintFilter::CropRect>& crop_rect) { SkRect record_bounds; sk_sp<PaintRecord> record; - ReadSimple(&record_bounds); + Read(&record_bounds); Read(&record); if (!valid_) return; @@ -918,9 +918,9 @@ int radius_x = 0; int radius_y = 0; sk_sp<PaintFilter> input; - ReadSimple(&morph_type_int); - ReadSimple(&radius_x); - ReadSimple(&radius_y); + Read(&morph_type_int); + Read(&radius_x); + Read(&radius_y); Read(&input); if (morph_type_int > static_cast<uint32_t>(MorphologyPaintFilter::MorphType::kMaxMorphType)) { @@ -942,8 +942,8 @@ SkScalar dy = 0.f; sk_sp<PaintFilter> input; - ReadSimple(&dx); - ReadSimple(&dy); + Read(&dx); + Read(&dy); Read(&input); if (!valid_) return; @@ -958,8 +958,8 @@ SkRect dst = SkRect::MakeEmpty(); sk_sp<PaintFilter> input; - ReadSimple(&src); - ReadSimple(&dst); + Read(&src); + Read(&dst); Read(&input); if (!valid_) return; @@ -976,11 +976,11 @@ SkScalar seed = 0.f; SkISize tile_size = SkISize::MakeEmpty(); - ReadSimple(&turbulence_type_int); - ReadSimple(&base_frequency_x); - ReadSimple(&base_frequency_y); - ReadSimple(&num_octaves); - ReadSimple(&seed); + Read(&turbulence_type_int); + Read(&base_frequency_x); + Read(&base_frequency_y); + Read(&num_octaves); + Read(&seed); ReadSimple(&tile_size); if (turbulence_type_int > static_cast<uint32_t>( @@ -1015,7 +1015,7 @@ SkFilterQuality filter_quality = kNone_SkFilterQuality; sk_sp<PaintFilter> input; - ReadSimple(&matrix); + Read(&matrix); ReadSimple(&filter_quality); Read(&input); if (filter_quality > kLast_SkFilterQuality) @@ -1037,12 +1037,12 @@ SkScalar shininess = 0.f; sk_sp<PaintFilter> input; - ReadSimple(&lighting_type_int); + Read(&lighting_type_int); ReadSimple(&direction); - ReadSimple(&light_color); - ReadSimple(&surface_scale); - ReadSimple(&kconstant); - ReadSimple(&shininess); + Read(&light_color); + Read(&surface_scale); + Read(&kconstant); + Read(&shininess); Read(&input); if (lighting_type_int > static_cast<uint32_t>(PaintFilter::LightingType::kMaxLightingType)) { @@ -1068,12 +1068,12 @@ SkScalar shininess = 0.f; sk_sp<PaintFilter> input; - ReadSimple(&lighting_type_int); + Read(&lighting_type_int); ReadSimple(&location); - ReadSimple(&light_color); - ReadSimple(&surface_scale); - ReadSimple(&kconstant); - ReadSimple(&shininess); + Read(&light_color); + Read(&surface_scale); + Read(&kconstant); + Read(&shininess); Read(&input); if (lighting_type_int > static_cast<uint32_t>(PaintFilter::LightingType::kMaxLightingType)) { @@ -1102,15 +1102,15 @@ SkScalar shininess = 0.f; sk_sp<PaintFilter> input; - ReadSimple(&lighting_type_int); + Read(&lighting_type_int); ReadSimple(&location); ReadSimple(&target); - ReadSimple(&specular_exponent); - ReadSimple(&cutoff_angle); - ReadSimple(&light_color); - ReadSimple(&surface_scale); - ReadSimple(&kconstant); - ReadSimple(&shininess); + Read(&specular_exponent); + Read(&cutoff_angle); + Read(&light_color); + Read(&surface_scale); + Read(&kconstant); + Read(&shininess); Read(&input); if (lighting_type_int >
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc index 19d816d4..41aea6f 100644 --- a/cc/paint/skia_paint_canvas.cc +++ b/cc/paint/skia_paint_canvas.cc
@@ -7,6 +7,7 @@ #include "base/memory/ptr_util.h" #include "cc/paint/display_item_list.h" #include "cc/paint/paint_recorder.h" +#include "cc/paint/scoped_raster_flags.h" #include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkColorSpaceXformCanvas.h" #include "third_party/skia/include/core/SkMetaData.h" @@ -15,7 +16,12 @@ namespace cc { -SkiaPaintCanvas::SkiaPaintCanvas(SkCanvas* canvas) : canvas_(canvas) {} +SkiaPaintCanvas::SkiaPaintCanvas(SkCanvas* canvas, + std::unique_ptr<ImageProvider> image_provider) + : canvas_(canvas), image_provider_(std::move(image_provider)) { + if (image_provider_) + image_provider_->BeginRaster(); +} SkiaPaintCanvas::SkiaPaintCanvas(const SkBitmap& bitmap) : canvas_(new SkCanvas(bitmap)), owned_(canvas_) {} @@ -25,12 +31,18 @@ : canvas_(new SkCanvas(bitmap, props)), owned_(canvas_) {} SkiaPaintCanvas::SkiaPaintCanvas(SkCanvas* canvas, - sk_sp<SkColorSpace> target_color_space) - : canvas_(canvas) { + sk_sp<SkColorSpace> target_color_space, + std::unique_ptr<ImageProvider> image_provider) + : canvas_(canvas), image_provider_(std::move(image_provider)) { WrapCanvasInColorSpaceXformCanvas(target_color_space); + if (image_provider_) + image_provider_->BeginRaster(); } -SkiaPaintCanvas::~SkiaPaintCanvas() = default; +SkiaPaintCanvas::~SkiaPaintCanvas() { + if (image_provider_) + image_provider_->EndRaster(); +} void SkiaPaintCanvas::WrapCanvasInColorSpaceXformCanvas( sk_sp<SkColorSpace> target_color_space) { @@ -60,6 +72,7 @@ int SkiaPaintCanvas::saveLayer(const SkRect* bounds, const PaintFlags* flags) { if (!flags) return canvas_->saveLayer(bounds, nullptr); + SkPaint paint = flags->ToSkPaint(); return canvas_->saveLayer(bounds, &paint); } @@ -154,34 +167,64 @@ SkScalar x1, SkScalar y1, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); + SkiaPaintCanvas::canvas_->drawLine(x0, y0, x1, y1, paint); } void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); + canvas_->drawRect(rect, paint); } void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); + canvas_->drawIRect(rect, paint); } void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); + canvas_->drawOval(oval, paint); } void SkiaPaintCanvas::drawRRect(const SkRRect& rrect, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); + canvas_->drawRRect(rrect, paint); } void SkiaPaintCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); + canvas_->drawDRRect(outer, inner, paint); } @@ -189,12 +232,22 @@ SkScalar rx, SkScalar ry, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); + canvas_->drawRoundRect(rect, rx, ry, paint); } void SkiaPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); + canvas_->drawPath(path, paint); } @@ -202,11 +255,15 @@ SkScalar left, SkScalar top, const PaintFlags* flags) { - SkPaint paint; - if (flags) - paint = flags->ToSkPaint(); - canvas_->drawImage(image.GetSkImage().get(), left, top, - flags ? &paint : nullptr); + ScopedRasterFlags raster_flags(flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + + PlaybackParams params(image_provider_.get(), canvas_->getTotalMatrix()); + DrawImageOp draw_image_op(image, left, top, nullptr); + DrawImageOp::RasterWithFlags(&draw_image_op, raster_flags.flags(), canvas_, + params); } void SkiaPaintCanvas::drawImageRect(const PaintImage& image, @@ -214,12 +271,15 @@ const SkRect& dst, const PaintFlags* flags, SrcRectConstraint constraint) { - SkPaint paint; - if (flags) - paint = flags->ToSkPaint(); - canvas_->drawImageRect(image.GetSkImage().get(), src, dst, - flags ? &paint : nullptr, - static_cast<SkCanvas::SrcRectConstraint>(constraint)); + ScopedRasterFlags raster_flags(flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + + PlaybackParams params(image_provider_.get(), canvas_->getTotalMatrix()); + DrawImageRectOp draw_image_rect_op(image, src, dst, flags, constraint); + DrawImageRectOp::RasterWithFlags(&draw_image_rect_op, raster_flags.flags(), + canvas_, params); } void SkiaPaintCanvas::drawBitmap(const SkBitmap& bitmap, @@ -227,7 +287,11 @@ SkScalar top, const PaintFlags* flags) { if (flags) { - SkPaint paint = flags->ToSkPaint(); + ScopedRasterFlags raster_flags(flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); canvas_->drawBitmap(bitmap, left, top, &paint); } else { canvas_->drawBitmap(bitmap, left, top, nullptr); @@ -238,12 +302,17 @@ SkScalar x, SkScalar y, const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); + ScopedRasterFlags raster_flags(&flags, image_provider_.get(), + canvas_->getTotalMatrix(), 255u); + if (!raster_flags.flags()) + return; + SkPaint paint = raster_flags.flags()->ToSkPaint(); canvas_->drawTextBlob(blob->ToSkTextBlob(), x, y, paint); } void SkiaPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) { - record->Playback(canvas_); + PlaybackParams params(image_provider_.get(), canvas_->getTotalMatrix()); + record->Playback(canvas_, params); } bool SkiaPaintCanvas::isClipEmpty() const {
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h index 51fb194a..aef0321 100644 --- a/cc/paint/skia_paint_canvas.h +++ b/cc/paint/skia_paint_canvas.h
@@ -18,7 +18,7 @@ #include "third_party/skia/include/core/SkCanvas.h" namespace cc { - +class ImageProvider; class PaintFlags; // A PaintCanvas derived class that passes PaintCanvas APIs through to @@ -26,12 +26,16 @@ // and then playing back to an SkCanvas. class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { public: - explicit SkiaPaintCanvas(SkCanvas* canvas); + explicit SkiaPaintCanvas( + SkCanvas* canvas, + std::unique_ptr<ImageProvider> image_provider = nullptr); explicit SkiaPaintCanvas(const SkBitmap& bitmap); explicit SkiaPaintCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props); // If |target_color_space| is non-nullptr, then this will wrap |canvas| in a // SkColorSpaceXformCanvas. - SkiaPaintCanvas(SkCanvas* canvas, sk_sp<SkColorSpace> target_color_space); + SkiaPaintCanvas(SkCanvas* canvas, + sk_sp<SkColorSpace> target_color_space, + std::unique_ptr<ImageProvider> image_provider = nullptr); ~SkiaPaintCanvas() override; SkMetaData& getMetaData() override; @@ -132,6 +136,7 @@ SkCanvas* canvas_; std::unique_ptr<SkCanvas> owned_; std::unique_ptr<SkCanvas> color_space_xform_canvas_; + std::unique_ptr<ImageProvider> image_provider_; DISALLOW_COPY_AND_ASSIGN(SkiaPaintCanvas); };
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc index 6014b80..6dd6e56 100644 --- a/cc/raster/raster_buffer_provider_unittest.cc +++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -272,7 +272,6 @@ void LoseContext(viz::ContextProvider* context_provider) { if (!context_provider) return; - viz::ContextProvider::ScopedContextLock lock(context_provider); context_provider->ContextGL()->LoseContextCHROMIUM( GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); context_provider->ContextGL()->Flush();
diff --git a/cc/resources/display_resource_provider.cc b/cc/resources/display_resource_provider.cc index 696d4a19..4a627df 100644 --- a/cc/resources/display_resource_provider.cc +++ b/cc/resources/display_resource_provider.cc
@@ -15,11 +15,17 @@ namespace cc { +static GLint GetActiveTextureUnit(GLES2Interface* gl) { + GLint active_unit = 0; + gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit); + return active_unit; +} + class ScopedSetActiveTexture { public: ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit) : gl_(gl), unit_(unit) { - DCHECK_EQ(GL_TEXTURE0, DisplayResourceProvider::GetActiveTextureUnit(gl_)); + DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_)); if (unit_ != GL_TEXTURE0) gl_->ActiveTexture(unit_); @@ -489,13 +495,6 @@ return resource->lock_for_read_count > 0 || resource->lost; } -GLint DisplayResourceProvider::GetActiveTextureUnit( - gpu::gles2::GLES2Interface* gl) { - GLint active_unit = 0; - gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit); - return active_unit; -} - DisplayResourceProvider::ScopedReadLockGL::ScopedReadLockGL( DisplayResourceProvider* resource_provider, viz::ResourceId resource_id)
diff --git a/cc/resources/display_resource_provider.h b/cc/resources/display_resource_provider.h index a5071879..7f09f529 100644 --- a/cc/resources/display_resource_provider.h +++ b/cc/resources/display_resource_provider.h
@@ -53,18 +53,9 @@ void WaitSyncToken(viz::ResourceId id); - // Binds the given GL resource to a texture target for sampling using the - // specified filter for both minification and magnification. Returns the - // texture target used. The resource must be locked for reading. - GLenum BindForSampling(viz::ResourceId resource_id, - GLenum unit, - GLenum filter); - // Checks whether a resource is in use. bool InUse(viz::ResourceId id); - static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl); - // The following lock classes are part of the DisplayResourceProvider API and // are needed to read the resource contents. The user must ensure that they // only use GL locks on GL resources, etc, and this is enforced by assertions. @@ -237,6 +228,12 @@ const viz::internal::Resource* LockForRead(viz::ResourceId id); void UnlockForRead(viz::ResourceId id); + // Binds the given GL resource to a texture target for sampling using the + // specified filter for both minification and magnification. Returns the + // texture target used. The resource must be locked for reading. + GLenum BindForSampling(viz::ResourceId resource_id, + GLenum unit, + GLenum filter); bool ReadLockFenceHasPassed(const viz::internal::Resource* resource); #if defined(OS_ANDROID) void DeletePromotionHint(ResourceMap::iterator it, DeleteStyle style);
diff --git a/cc/resources/layer_tree_resource_provider.cc b/cc/resources/layer_tree_resource_provider.cc index 8d5b7a5..5bc08896 100644 --- a/cc/resources/layer_tree_resource_provider.cc +++ b/cc/resources/layer_tree_resource_provider.cc
@@ -73,6 +73,7 @@ use_gpu_memory_buffer_resources( resource_settings.use_gpu_memory_buffer_resources), delegated_sync_points_required(delegated_sync_points_required) { + DCHECK(resource_settings.texture_id_allocation_chunk_size); if (!compositor_context_provider) { // Pick an arbitrary limit here similar to what hardware might. max_texture_size = 16 * 1024; @@ -149,7 +150,6 @@ shared_bitmap_manager_(shared_bitmap_manager), gpu_memory_buffer_manager_(gpu_memory_buffer_manager), next_id_(kLayerTreeInitialResourceId) { - DCHECK(resource_settings.texture_id_allocation_chunk_size); GLES2Interface* gl = ContextGL(); texture_id_allocator_ = std::make_unique<TextureIdAllocator>( gl, resource_settings.texture_id_allocation_chunk_size);
diff --git a/cc/test/fake_resource_provider.h b/cc/test/fake_resource_provider.h index 535f23b3..c1fbc494 100644 --- a/cc/test/fake_resource_provider.h +++ b/cc/test/fake_resource_provider.h
@@ -5,29 +5,13 @@ #ifndef CC_TEST_FAKE_RESOURCE_PROVIDER_H_ #define CC_TEST_FAKE_RESOURCE_PROVIDER_H_ -#include <stddef.h> - -#include "base/memory/ptr_util.h" #include "cc/resources/display_resource_provider.h" #include "cc/resources/layer_tree_resource_provider.h" -#include "cc/resources/resource_provider.h" -#include "ui/gfx/buffer_types.h" namespace cc { -class FakeResourceProvider : public ResourceProvider { +class FakeResourceProvider { public: - static std::unique_ptr<FakeResourceProvider> Create( - viz::ContextProvider* context_provider, - viz::SharedBitmapManager* shared_bitmap_manager, - bool high_bit_for_testing = false) { - viz::ResourceSettings resource_settings; - resource_settings.texture_id_allocation_chunk_size = 1; - resource_settings.high_bit_for_testing = high_bit_for_testing; - return base::WrapUnique(new FakeResourceProvider( - context_provider, shared_bitmap_manager, true, resource_settings)); - } - static std::unique_ptr<LayerTreeResourceProvider> CreateLayerTreeResourceProvider( viz::ContextProvider* context_provider, @@ -50,13 +34,6 @@ return std::make_unique<DisplayResourceProvider>(context_provider, shared_bitmap_manager); } - - private: - FakeResourceProvider(viz::ContextProvider* context_provider, - viz::SharedBitmapManager* shared_bitmap_manager, - bool delegated_sync_points_required, - const viz::ResourceSettings resource_settings) - : ResourceProvider(context_provider) {} }; } // namespace cc
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc index 1e0b59b..a3a2559b 100644 --- a/cc/test/test_context_provider.cc +++ b/cc/test/test_context_provider.cc
@@ -295,6 +295,8 @@ } base::Lock* TestContextProvider::GetLock() { + if (!support_locking_) + return nullptr; return &context_lock_; }
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc index ba2ae8e..8ef3939 100644 --- a/cc/tiles/gpu_image_decode_cache.cc +++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -560,7 +560,10 @@ // Acquire the context_lock so that we can safely retrieve // |max_texture_size_|. { - viz::RasterContextProvider::ScopedRasterContextLock context_lock(context_); + base::Optional<viz::RasterContextProvider::ScopedRasterContextLock> + context_lock; + if (context_->GetLock()) + context_lock.emplace(context_); max_texture_size_ = context_->GrContext()->caps()->maxTextureSize(); } @@ -703,7 +706,7 @@ // We are being called during raster. The context lock must already be // acquired by the caller. - context_->GetLock()->AssertAcquired(); + CheckContextLockAcquiredIfNecessary(); // If we're skipping the image, then the filter quality doesn't matter. if (SkipImage(draw_image)) @@ -775,7 +778,7 @@ // We are being called during raster. The context lock must already be // acquired by the caller. - context_->GetLock()->AssertAcquired(); + CheckContextLockAcquiredIfNecessary(); if (SkipImage(draw_image)) return; @@ -798,10 +801,12 @@ // This is typically called when no tasks are running (between scheduling // tasks). Try to lock and run pending operations if possible, but don't // block on it. - if (context_->GetLock()->Try()) { - RunPendingContextThreadOperations(); + if (context_->GetLock() && !context_->GetLock()->Try()) + return; + + RunPendingContextThreadOperations(); + if (context_->GetLock()) context_->GetLock()->Release(); - } } void GpuImageDecodeCache::SetShouldAggressivelyFreeResources( @@ -810,7 +815,11 @@ "GpuImageDecodeCache::SetShouldAggressivelyFreeResources", "agressive_free_resources", aggressively_free_resources); if (aggressively_free_resources) { - viz::RasterContextProvider::ScopedRasterContextLock context_lock(context_); + base::Optional<viz::RasterContextProvider::ScopedRasterContextLock> + context_lock; + if (context_->GetLock()) + context_lock.emplace(context_); + base::AutoLock lock(lock_); aggressively_freeing_resources_ = aggressively_free_resources; EnsureCapacity(0); @@ -956,7 +965,11 @@ void GpuImageDecodeCache::UploadImage(const DrawImage& draw_image) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "GpuImageDecodeCache::UploadImage"); - viz::RasterContextProvider::ScopedRasterContextLock context_lock(context_); + base::Optional<viz::RasterContextProvider::ScopedRasterContextLock> + context_lock; + if (context_->GetLock()) + context_lock.emplace(context_); + base::AutoLock lock(lock_); ImageData* image_data = GetImageDataForDrawImage(draw_image); DCHECK(image_data); @@ -1339,7 +1352,7 @@ void GpuImageDecodeCache::UploadImageIfNecessary(const DrawImage& draw_image, ImageData* image_data) { - context_->GetLock()->AssertAcquired(); + CheckContextLockAcquiredIfNecessary(); lock_.AssertAcquired(); // We are about to upload a new image and are holding the context lock. @@ -1483,7 +1496,7 @@ // we need to call GlIdFromSkImage, which flushes pending IO on the image, // rather than just using a cached GL ID. void GpuImageDecodeCache::RunPendingContextThreadOperations() { - context_->GetLock()->AssertAcquired(); + CheckContextLockAcquiredIfNecessary(); lock_.AssertAcquired(); for (auto* image : images_pending_complete_lock_) { @@ -1691,4 +1704,10 @@ } } +void GpuImageDecodeCache::CheckContextLockAcquiredIfNecessary() { + if (!context_->GetLock()) + return; + context_->GetLock()->AssertAcquired(); +} + } // namespace cc
diff --git a/cc/tiles/gpu_image_decode_cache.h b/cc/tiles/gpu_image_decode_cache.h index 1c742a4..3dd004f 100644 --- a/cc/tiles/gpu_image_decode_cache.h +++ b/cc/tiles/gpu_image_decode_cache.h
@@ -413,6 +413,8 @@ bool SupportsColorSpaces() const; + void CheckContextLockAcquiredIfNecessary(); + const SkColorType color_type_; const bool use_transfer_cache_ = false; viz::RasterContextProvider* context_;
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc index aa44044..05232f3 100644 --- a/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -212,7 +212,7 @@ : TestContextProvider(std::move(support), std::move(gl), std::move(context), - false) {} + true) {} }; gfx::ColorSpace DefaultColorSpace() { @@ -230,7 +230,11 @@ &discardable_manager_, &transfer_cache_helper_); discardable_manager_.SetGLES2Interface(context_provider_->TestContextGL()); context_provider_->BindToCurrentThread(); - transfer_cache_helper_.SetGrContext(context_provider_->GrContext()); + { + viz::RasterContextProvider::ScopedRasterContextLock context_lock( + context_provider_.get()); + transfer_cache_helper_.SetGrContext(context_provider_->GrContext()); + } use_transfer_cache_ = GetParam().second; color_type_ = GetParam().first; }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 94e20f1d..f0193b2 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -7827,7 +7827,6 @@ viz::ContextProvider* context_provider = host_impl->layer_tree_frame_sink()->context_provider(); ASSERT_TRUE(context_provider); - viz::ContextProvider::ScopedContextLock context_lock(context_provider); GrContext* gr_context = context_provider->GrContext(); ASSERT_TRUE(gr_context);
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 6d8ffbe7..13ce2cd 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -91,6 +91,9 @@ "java/res", "//chrome/android/java/res_chromium", ] + if (enable_vr) { + resource_dirs += [ "//chrome/android/java/res_vr" ] + } deps = [ ":chrome_strings_grd", "//chrome/app:java_strings_grd",
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 800ba16..8b50ec2 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -359,8 +359,35 @@ android:relinquishTaskIdentity="true" android:excludeFromRecents="true" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize"> + <!-- TODO(mthiesse, b/72214458): This is a duplication of the icon metadata below. + Daydream will actually ignore the metadata here, and use the metadata on the + activity-alias. However, play store apk validation fails to find the icons on the + alias, so we need to include them here to pass validation. --> + <meta-data android:name="com.google.android.vr.icon" + android:resource="@drawable/daydream_icon_foreground" /> + <meta-data android:name="com.google.android.vr.icon_background" + android:resource="@drawable/daydream_icon_background" /> {{ self.supports_vr() }} </activity> + <!-- This alias allows us to dynamically toggle whether the Chrome icon shows up in Daydream + home. It starts off disabled and is enabled dynamically via a feature flag when Chrome + is started. --> + <activity-alias android:name="com.google.android.apps.chrome.VrIntentDispatcher" + android:targetActivity="org.chromium.chrome.browser.vr.VrMainActivity" + android:enabled="false" + android:exported="true"> + <!-- These icons are placeholders, and only show up behind a flag that's disabled by + default. --> + <meta-data android:name="com.google.android.vr.icon" + android:resource="@drawable/daydream_icon_foreground" /> + <meta-data android:name="com.google.android.vr.icon_background" + android:resource="@drawable/daydream_icon_background" /> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <!-- Show icon in Daydream app launcher. --> + <category android:name="com.google.intent.category.DAYDREAM" /> + </intent-filter> + </activity-alias> <activity android:name="org.chromium.chrome.browser.vr.CustomTabVrActivity" android:theme="@style/VrSupportTheme" android:screenOrientation="landscape"
diff --git a/chrome/android/java/res/color/flush_footer_button_color.xml b/chrome/android/java/res/color/flush_footer_button_color.xml new file mode 100644 index 0000000..72eba39 --- /dev/null +++ b/chrome/android/java/res/color/flush_footer_button_color.xml
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_focused="true" android:color="@color/google_grey_300" /> + <item android:color="@color/google_grey_100" /> +</selector>
diff --git a/chrome/android/java/res/drawable/flush_footer_button.xml b/chrome/android/java/res/drawable/flush_footer_button.xml index 3d33e5a..8ab36bb 100644 --- a/chrome/android/java/res/drawable/flush_footer_button.xml +++ b/chrome/android/java/res/drawable/flush_footer_button.xml
@@ -5,6 +5,6 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - <solid android:color="@color/google_grey_100" /> + <solid android:color="@color/flush_footer_button_color" /> <stroke android:width="1dp" android:color="@color/google_grey_300"/> </shape> \ No newline at end of file
diff --git a/chrome/android/java/res_vr/drawable-nodpi/daydream_icon_background.png b/chrome/android/java/res_vr/drawable-nodpi/daydream_icon_background.png new file mode 100644 index 0000000..74cd6ed --- /dev/null +++ b/chrome/android/java/res_vr/drawable-nodpi/daydream_icon_background.png Binary files differ
diff --git a/chrome/android/java/res_vr/drawable-nodpi/daydream_icon_foreground.png b/chrome/android/java/res_vr/drawable-nodpi/daydream_icon_foreground.png new file mode 100644 index 0000000..de5b721 --- /dev/null +++ b/chrome/android/java/res_vr/drawable-nodpi/daydream_icon_foreground.png Binary files differ
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 6cad3a64..445bf94 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -249,6 +249,7 @@ public static final String VR_BROWSING = "VrBrowsing"; public static final String VR_BROWSING_FEEDBACK = "VrBrowsingFeedback"; public static final String VR_BROWSING_IN_CUSTOM_TAB = "VrBrowsingInCustomTab"; + public static final String VR_ICON_IN_DAYDREAM_HOME = "VrIconInDaydreamHome"; public static final String VR_LAUNCH_INTENT = "VrLaunchIntents"; public static final String WEB_PAYMENTS = "WebPayments"; public static final String WEB_PAYMENTS_METHOD_SECTION_ORDER_V2 =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/PasswordManagerHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/PasswordManagerHandler.java index ead4749..2860dd3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/PasswordManagerHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/PasswordManagerHandler.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser; +import org.chromium.base.Callback; + /** * Interface for retrieving passwords and password exceptions (websites for which Chrome should not * save password) from native code. @@ -61,4 +63,11 @@ * @param index of exception entry. */ public void removeSavedPasswordException(int index); + + /** + * Trigger serializing the saved passwords in the background. + * + * @param callback is called on completion, with the serialized passwords as argument. + */ + public void serializePasswords(Callback<String> callback); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/PasswordUIView.java b/chrome/android/java/src/org/chromium/chrome/browser/PasswordUIView.java index 2c0172d5..57972ed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/PasswordUIView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/PasswordUIView.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser; +import org.chromium.base.Callback; import org.chromium.base.annotations.CalledByNative; /** @@ -70,6 +71,11 @@ nativeHandleRemoveSavedPasswordException(mNativePasswordUIViewAndroid, index); } + @Override + public void serializePasswords(Callback<String> callback) { + nativeHandleSerializePasswords(mNativePasswordUIViewAndroid, callback); + } + /** * Returns the URL for the website for managing one's passwords without the need to use Chrome * with the user's profile signed in. @@ -111,4 +117,6 @@ private native void nativeDestroy(long nativePasswordUIViewAndroid); + private native void nativeHandleSerializePasswords( + long nativePasswordUIViewAndroid, Callback<String> callback); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java index 0816507..8c0b0e6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java
@@ -23,19 +23,6 @@ private final String mPrimaryActionLabel; private final boolean mInstantAppIsDefault; - @Deprecated - public InstantAppsBannerData(String appName, Bitmap icon, String url, Uri referrer, - Intent intent, String primaryActionLabel, WebContents webContents) { - mAppName = appName; - mAppIcon = icon; - mUrl = url; - mIntent = intent; - mPrimaryActionLabel = primaryActionLabel; - mWebContents = webContents; - mReferrer = referrer; - mInstantAppIsDefault = false; - } - public InstantAppsBannerData(String appName, Bitmap icon, String url, Uri referrer, Intent intent, String primaryActionLabel, WebContents webContents, boolean instantAppIsDefault) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/ReauthenticationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/ReauthenticationManager.java index f9a1859..2658c22 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/ReauthenticationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/ReauthenticationManager.java
@@ -42,6 +42,9 @@ // This allows the tests to be independent of a particular device configuration. private static OverrideState sApiOverride = OverrideState.NOT_OVERRIDDEN; + // Used in tests to avoid displaying the OS reauth dialog. + private static boolean sSkipSystemReauth = false; + /** * Stores the timestamp of last reauthentication of the user. */ @@ -64,6 +67,11 @@ sApiOverride = apiOverride; } + @VisibleForTesting + public static void setSkipSystemReauth(boolean skipSystemReauth) { + sSkipSystemReauth = skipSystemReauth; + } + /** * Checks whether reauthentication is available on the device at all. * @return The result of the check. @@ -93,6 +101,8 @@ */ public static void displayReauthenticationFragment( int descriptionId, int containerViewId, FragmentManager fragmentManager) { + if (sSkipSystemReauth) return; + Fragment passwordReauthentication = new PasswordReauthenticationFragment(); Bundle args = new Bundle(); args.putInt(PasswordReauthenticationFragment.DESCRIPTION_ID, descriptionId);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java index b43b4dd..8811486 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
@@ -21,6 +21,7 @@ import android.view.MenuItem; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.Callback; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.PasswordManagerHandler; @@ -78,6 +79,9 @@ // True if the user triggered the password export flow and this fragment is waiting for the // result of the user's reauthentication. private boolean mExportRequested; + // True if the option to export passwords in the three-dots menu should be disabled due to an + // ongoing export. + private boolean mExportOptionSuspended = false; private Preference mLinkPref; private ChromeSwitchPreference mSavePasswordsSwitch; private ChromeBaseCheckBoxPreference mAutoSignInSwitch; @@ -109,7 +113,7 @@ @Override public void onPrepareOptionsMenu(Menu menu) { - menu.findItem(R.id.export_passwords).setEnabled(!mNoPasswords); + menu.findItem(R.id.export_passwords).setEnabled(!mNoPasswords && !mExportOptionSuspended); super.onPrepareOptionsMenu(menu); } @@ -117,10 +121,33 @@ public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.export_passwords) { + // Disable re-triggering exporting until the current exporting finishes. + mExportOptionSuspended = true; + + // Start fetching the serialized passwords now to use the time the user spends + // reauthenticating and reading the warning message. If the user cancels the export or + // fails the reauthentication, the serialised passwords will simply get ignored when + // they arrive. + PasswordManagerHandlerProvider.getInstance() + .getPasswordManagerHandler() + .serializePasswords(new Callback<String>() { + @Override + public void onResult(String serializedPasswords) { + // TODO(crbug.com/788701): Ensure that the SavePasswordsPreferences is + // not dead before trying to use any of its data members. + // TODO(crbug.com/788701): Ensure that the passwords are stored to a + // file here and its URI in saved-state-bundle in case the reauth + // dialogue causes this activity to be killed. + // TODO(crbug.com/788701): Synchronise with end of the UI flow and pass + // the data. + } + }); if (!ReauthenticationManager.isScreenLockSetUp(getActivity().getApplicationContext())) { Toast.makeText(getActivity().getApplicationContext(), R.string.password_export_set_lock_screen, Toast.LENGTH_LONG) .show(); + // Re-enable exporting, the current one was cancelled by Chrome. + mExportOptionSuspended = false; } else if (ReauthenticationManager.authenticationStillValid()) { exportAfterReauth(); } else { @@ -144,13 +171,16 @@ if (which == AlertDialog.BUTTON_POSITIVE) { exportAfterWarning(); } + // Re-enable exporting, the current one was either finished or dismissed. + mExportOptionSuspended = false; } }); exportWarningDialogFragment.show(getFragmentManager(), null); } private void exportAfterWarning() { - // TODO(crbug.com/788701): Start the export. + // TODO(crbug.com/788701): Synchronise with obtaining serialised passwords and pass them to + // the intent. } /** @@ -279,7 +309,13 @@ super.onResume(); if (mExportRequested) { mExportRequested = false; - if (ReauthenticationManager.authenticationStillValid()) exportAfterReauth(); + // Depending on the authentication result, either carry on with exporting or re-enable + // the export menu for future attempts. + if (ReauthenticationManager.authenticationStillValid()) { + exportAfterReauth(); + } else { + mExportOptionSuspended = false; + } } rebuildPasswordLists(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/subresource_filter/TestSubresourceFilterPublisher.java b/chrome/android/java/src/org/chromium/chrome/browser/subresource_filter/TestSubresourceFilterPublisher.java new file mode 100644 index 0000000..ef5e8ad --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/subresource_filter/TestSubresourceFilterPublisher.java
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.subresource_filter; + +import org.chromium.base.annotations.CalledByNative; + +/** + * Class which aids in publishing test rulesets for SubresourceFilter instrumentation tests. + * All methods and members must be called on the UI thread. + */ +public final class TestSubresourceFilterPublisher { + private boolean mPublished = false; + + public void createAndPublishRulesetDisallowingSuffixForTesting(String suffix) { + nativeCreateAndPublishRulesetDisallowingSuffixForTesting(suffix); + } + + public boolean isPublished() { + return mPublished; + } + + @CalledByNative + private void onRulesetPublished() { + mPublished = true; + } + + private native void nativeCreateAndPublishRulesetDisallowingSuffixForTesting(String suffix); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java index e85d706..5b61d35 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -9,10 +9,12 @@ import android.app.ActivityOptions; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Color; import android.net.Uri; @@ -98,6 +100,9 @@ static final String VR_ENTRY_RESULT_ACTION = "org.chromium.chrome.browser.vr_shell.VrEntryResult"; + private static final String VR_INTENT_DISPATCHER_COMPONENT = + "com.google.android.apps.chrome.VrIntentDispatcher"; + private static final long REENTER_VR_TIMEOUT_MS = 1000; private static final int EXPECT_DON_TIMEOUT_MS = 2000; @@ -112,8 +117,9 @@ private static VrBroadcastReceiver sVrBroadcastReceiver; private static boolean sRegisteredDaydreamHook; private static boolean sAddedBlackOverlayView; - private static boolean sRegisteredVrAssetsComponent = false; - private static boolean sChromeStarted = false; + private static boolean sRegisteredVrAssetsComponent; + private static boolean sChromeStarted; + private static Boolean sIconComponentEnabled; private ChromeActivity mActivity; @@ -345,6 +351,7 @@ int vrSupportLevel = getVrSupportLevel(api, wrapper.createVrCoreVersionChecker(), null); if (!isVrShellEnabled(vrSupportLevel)) return null; + updateDayreamIconComponentState(activity); return api; } @@ -457,6 +464,19 @@ return sInstance; } + private static void updateDayreamIconComponentState(ChromeActivity activity) { + boolean enabled = ChromeFeatureList.isEnabled(ChromeFeatureList.VR_ICON_IN_DAYDREAM_HOME); + + if (sIconComponentEnabled != null && enabled == sIconComponentEnabled) return; + + int componentState = enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED + : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; + ComponentName component = new ComponentName(activity, VR_INTENT_DISPATCHER_COMPONENT); + activity.getPackageManager().setComponentEnabledSetting( + component, componentState, PackageManager.DONT_KILL_APP); + sIconComponentEnabled = enabled; + } + private static boolean activitySupportsPresentation(Activity activity) { return activity instanceof ChromeTabbedActivity || activity instanceof CustomTabActivity || activity instanceof WebappActivity; @@ -960,25 +980,24 @@ * This is called when ChromeTabbedActivity gets a new intent before native is initialized. */ public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) { - if (VrIntentUtils.isVrIntent(intent)) { - // If we get an intent while we're already in VR, we do nothing. This is mostly - // because crbug.com/780673 since on Android O, every intent gets dispatched twice. - if (sInstance != null && sInstance.mInVr) return; - if (DEBUG_LOGS) Log.i(TAG, "maybeHandleVrIntentPreNative: preparing for transition"); - // We add a black overlay view so that we can show black while the VR UI is loading. - // Note that this alone isn't sufficient to prevent 2D UI from showing when - // auto-presenting WebVR. See comment about the custom animation in {@link - // getVrIntentOptions}. - // TODO(crbug.com/775574): This hack doesn't really work to hide the 2D UI on Samsung - // devices since Chrome gets paused and we prematurely remove the overlay. - addBlackOverlayViewForActivity(activity); + if (!VrIntentUtils.isVrIntent(intent)) return; + // If we get an intent while we're already in VR, we do nothing. This is mostly + // because crbug.com/780673 since on Android O, every intent gets dispatched twice. + if (sInstance != null && sInstance.mInVr) return; + if (DEBUG_LOGS) Log.i(TAG, "maybeHandleVrIntentPreNative: preparing for transition"); + // We add a black overlay view so that we can show black while the VR UI is loading. + // Note that this alone isn't sufficient to prevent 2D UI from showing when + // auto-presenting WebVR. See comment about the custom animation in {@link + // getVrIntentOptions}. + // TODO(crbug.com/775574): This hack doesn't really work to hide the 2D UI on Samsung + // devices since Chrome gets paused and we prematurely remove the overlay. + addBlackOverlayViewForActivity(activity); - // Enable VR mode and hide system UI. We do this here so we don't get kicked out of - // VR mode and to prevent seeing a flash of system UI. - getVrClassesWrapper().setVrModeEnabled(activity, true); - activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - activity.getWindow().getDecorView().setSystemUiVisibility(VR_SYSTEM_UI_FLAGS); - } + // Enable VR mode and hide system UI. We do this here so we don't get kicked out of + // VR mode and to prevent seeing a flash of system UI. + getVrClassesWrapper().setVrModeEnabled(activity, true); + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + activity.getWindow().getDecorView().setSystemUiVisibility(VR_SYSTEM_UI_FLAGS); } /** @@ -1229,6 +1248,7 @@ if (!sRegisteredVrAssetsComponent) { registerVrAssetsComponentIfDaydreamUser(isDaydreamCurrentViewer()); } + updateDayreamIconComponentState(mActivity); } }); }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index f85e6634..6fbc269c 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1035,6 +1035,7 @@ "java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java", "java/src/org/chromium/chrome/browser/prerender/ChromePrerenderService.java", "java/src/org/chromium/chrome/browser/prerender/ExternalPrerenderHandler.java", + "java/src/org/chromium/chrome/browser/subresource_filter/TestSubresourceFilterPublisher.java", "java/src/org/chromium/chrome/browser/printing/PrintShareActivity.java", "java/src/org/chromium/chrome/browser/printing/TabPrinter.java", "java/src/org/chromium/chrome/browser/profiles/Profile.java", @@ -1769,6 +1770,7 @@ "javatests/src/org/chromium/chrome/browser/provider/ProviderTestRule.java", "javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java", "javatests/src/org/chromium/chrome/browser/SafeBrowsingTest.java", + "javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java", "javatests/src/org/chromium/chrome/browser/MockSafeBrowsingApiHandler.java", "javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java", "javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java index 31958073..559d3c7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java
@@ -64,7 +64,7 @@ // Wait on the callback to be called. semaphore.acquire(); } catch (InterruptedException e) { - Assert.fail("Failed to acquire semaphore"); + throw new AssertionError("Failed to acquire semaphore", e); } return mShouldLaunchResult; } @@ -73,9 +73,9 @@ try { mLauncher.mLaunchBrowserIfStoppedTask.get(); } catch (InterruptedException e) { - Assert.fail("Launch task was interrupted"); + throw new AssertionError("Launch task was interrupted", e); } catch (ExecutionException e) { - Assert.fail("Launch task had execution exception"); + throw new AssertionError("Launch task had execution exception", e); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java index b29bf7e..8ba17dc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java
@@ -102,7 +102,7 @@ } } } catch (IOException ioe) { - Assert.fail("Failed to read ps output."); + throw new AssertionError("Failed to read ps output.", ioe); } finally { if (reader != null) { try {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java index 8a49a67..a6399b1a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
@@ -139,7 +139,7 @@ try { mockActivity.waitForFileCheck(); } catch (InterruptedException e) { - assert false : "Test thread was interrupted while trying to wait."; + throw new AssertionError("Test thread was interrupted while trying to wait.", e); } ShareHelper.setLastShareComponentName(new ComponentName("", ""), null);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java new file mode 100644 index 0000000..352565d0 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java
@@ -0,0 +1,113 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser; + +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.browser.subresource_filter.TestSubresourceFilterPublisher; +import org.chromium.chrome.test.ChromeActivityTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.components.safe_browsing.SafeBrowsingApiBridge; +import org.chromium.content.browser.test.util.Criteria; +import org.chromium.content.browser.test.util.CriteriaHelper; +import org.chromium.net.test.EmbeddedTestServer; + +/** + * End to end tests of SubresourceFilter ad filtering on Android. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + "enable-features=SubresourceFilter<SB,SubresourceFilterExperimentalUI", + "force-fieldtrials=SB/Enabled", + "force-fieldtrial-params=SB.Enabled:enable_presets/liverun_on_better_ads_violating_sites"}) + +public final class SubresourceFilterTest { + @Rule + public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = + new ChromeActivityTestRule<>(ChromeActivity.class); + private EmbeddedTestServer mTestServer; + + private static final String PAGE_WITH_JPG = + "/chrome/test/data/android/subresource_filter/page-with-img.html"; + private static final String METADATA_FOR_ENFORCEMENT = + "{\"matches\":[{\"threat_type\":\"13\",\"sf_bas\":\"\"}]}"; + private static final String METADATA_FOR_WARNING = + "{\"matches\":[{\"threat_type\":\"13\",\"sf_bas\":\"warn\"}]}"; + + private void createAndPublishRulesetDisallowingSuffix(String suffix) { + TestSubresourceFilterPublisher publisher = new TestSubresourceFilterPublisher(); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () + -> publisher.createAndPublishRulesetDisallowingSuffixForTesting(suffix)); + CriteriaHelper.pollUiThread(new Criteria() { + @Override + public boolean isSatisfied() { + return publisher.isPublished(); + } + }); + } + + @Before + public void setUp() throws Exception { + mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); + + // Create a new temporary instance to ensure the Class is loaded. Otherwise we will get a + // ClassNotFoundException when trying to instantiate during startup. + SafeBrowsingApiBridge.setSafeBrowsingHandlerType( + new MockSafeBrowsingApiHandler().getClass()); + mActivityTestRule.startMainActivityOnBlankPage(); + + // Disallow all jpgs. + createAndPublishRulesetDisallowingSuffix(".jpg"); + } + + @After + public void tearDown() throws Exception { + mTestServer.stopAndDestroyServer(); + MockSafeBrowsingApiHandler.clearMockResponses(); + } + + @Test + @MediumTest + public void resourceNotFiltered() throws Exception { + String url = mTestServer.getURL(PAGE_WITH_JPG); + mActivityTestRule.loadUrl(url); + + String loaded = mActivityTestRule.runJavaScriptCodeInCurrentTab("imgLoaded"); + Assert.assertEquals("true", loaded); + } + + @Test + @MediumTest + public void resourceFiltered() throws Exception { + String url = mTestServer.getURL(PAGE_WITH_JPG); + MockSafeBrowsingApiHandler.addMockResponse(url, METADATA_FOR_ENFORCEMENT); + mActivityTestRule.loadUrl(url); + + String loaded = mActivityTestRule.runJavaScriptCodeInCurrentTab("imgLoaded"); + Assert.assertEquals("false", loaded); + } + + @Test + @MediumTest + public void resourceNotFilteredWithWarning() throws Exception { + String url = mTestServer.getURL(PAGE_WITH_JPG); + MockSafeBrowsingApiHandler.addMockResponse(url, METADATA_FOR_WARNING); + mActivityTestRule.loadUrl(url); + + String loaded = mActivityTestRule.runJavaScriptCodeInCurrentTab("imgLoaded"); + Assert.assertEquals("true", loaded); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java index 34ad7c2..8d50b4a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -1634,7 +1634,7 @@ try { selectCallback.waitForCallback(0); } catch (TimeoutException e) { - Assert.fail("Tab selected event was never received"); + throw new AssertionError("Tab selected event was never received", e); } ThreadUtils.runOnUiThreadBlocking(() -> { TabModelSelector selector = mActivityTestRule.getActivity().getTabModelSelector(); @@ -1984,7 +1984,8 @@ try { pageLoadedCallbacks[i].waitForCallback(0); } catch (TimeoutException e) { - Assert.fail("PAGE_LOAD_FINISHED was not received for tabId=" + tabIds[i]); + throw new AssertionError( + "PAGE_LOAD_FINISHED was not received for tabId=" + tabIds[i], e); } } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java index a73817c..2f191d45 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java
@@ -35,6 +35,7 @@ import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.net.test.EmbeddedTestServer; +import java.util.concurrent.Callable; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -55,13 +56,13 @@ mContext = InstrumentationRegistry.getInstrumentation() .getTargetContext() .getApplicationContext(); - ThreadUtils.runOnUiThreadBlocking(() -> { - try { + ThreadUtils.runOnUiThreadBlocking(new Callable<Void>() { + @Override + public Void call() throws Exception { ChromeBrowserInitializer.getInstance(mContext).handleSynchronousStartup(); - } catch (Exception e) { - Assert.fail(); + mWarmupManager = WarmupManager.getInstance(); + return null; } - mWarmupManager = WarmupManager.getInstance(); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/WebShareTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/WebShareTest.java index e1443a3..4777b5f4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/WebShareTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/WebShareTest.java
@@ -254,7 +254,7 @@ @Override public void onCustomChooserShown(AlertDialog dialog) { // Click on an app (it doesn't matter which, because we will hook the intent). - assert dialog.getListView().getCount() > 0; + Assert.assertTrue(dialog.getListView().getCount() > 0); dialog .getListView() .performItemClick(null, 0, dialog.getListView().getItemIdAtPosition(0));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java index 5d74e6b1..bec581e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
@@ -349,11 +349,7 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - try { - mCustomTabsConnection.lowConfidenceMayLaunchUrl(invalidBundles); - } catch (ClassCastException e) { - Assert.fail(); - } + mCustomTabsConnection.lowConfidenceMayLaunchUrl(invalidBundles); } }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java index c4d2e30..643c0fc4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
@@ -71,7 +71,7 @@ Assert.assertTrue(connection.warmup(0)); startupCallbackHelper.waitForCallback(0); } catch (TimeoutException | InterruptedException e) { - Assert.fail(); + throw new AssertionError("Unexpected exception.", e); } finally { connection.setWarmupCompletedCallbackForTesting(null); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java index d4f609f..2b81a10e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
@@ -199,7 +199,8 @@ mActivityTestRule.getActivity() .getTabModelSelector() .getCurrentTab() - .getWebContents())); + .getWebContents(), + false)); } });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java index c34729d..1137e1c62 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialogTest.java
@@ -47,7 +47,7 @@ ChromeBrowserInitializer.getInstance(InstrumentationRegistry.getTargetContext()) .handleSynchronousStartup(); } catch (ProcessInitException e) { - Assert.fail("Failed to initialize Chrome process"); + throw new AssertionError("Failed to initialize Chrome process.", e); } LocaleManager mockManager = new LocaleManager() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerReferralTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerReferralTest.java index aac4331d..4001c47e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerReferralTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerReferralTest.java
@@ -56,7 +56,7 @@ ChromeBrowserInitializer.getInstance(InstrumentationRegistry.getTargetContext()) .handleSynchronousStartup(); } catch (ProcessInitException e) { - Assert.fail("Failed to load browser"); + throw new AssertionError("Failed to load browser.", e); } } });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerTest.java index be91476..d2bf97c3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerTest.java
@@ -41,7 +41,7 @@ ChromeBrowserInitializer.getInstance(InstrumentationRegistry.getTargetContext()) .handleSynchronousStartup(); } catch (ProcessInitException e) { - Assert.fail("Failed to load browser"); + throw new AssertionError("Failed to load browser.", e); } } });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java index e0102f0..8d056bc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
@@ -30,6 +30,7 @@ import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Feature; @@ -64,12 +65,19 @@ private final PasswordListObserver mObserver; // The faked contents of the password store to be displayed. - private ArrayList<SavedPasswordEntry> mSavedPasswords; + private ArrayList<SavedPasswordEntry> mSavedPasswords = new ArrayList<SavedPasswordEntry>(); + + // This is set to true when serializePasswords is called. + private boolean mSerializePasswordsCalled; public void setSavedPasswords(ArrayList<SavedPasswordEntry> savedPasswords) { mSavedPasswords = savedPasswords; } + public boolean getSerializePasswordsCalled() { + return mSerializePasswordsCalled; + } + /** * Constructor. * @param PasswordListObserver The only observer. @@ -110,6 +118,11 @@ assert false; return; } + + @Override + public void serializePasswords(Callback<String> callback) { + mSerializePasswordsCalled = true; + } } // Used to provide fake lists of stored passwords. Tests which need it can use setPasswordSource @@ -350,6 +363,35 @@ } /** + * Check that tapping the export menu requests the passwords to be serialised in the background. + */ + @Test + @SmallTest + @Feature({"Preferences"}) + @EnableFeatures("PasswordExport") + public void testExportTriggersSerialization() throws Exception { + setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password")); + + ReauthenticationManager.setApiOverride(ReauthenticationManager.OverrideState.AVAILABLE); + ReauthenticationManager.setScreenLockSetUpOverride( + ReauthenticationManager.OverrideState.AVAILABLE); + + final Preferences preferences = + PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(), + SavePasswordsPreferences.class.getName()); + + Espresso.openActionBarOverflowOrOptionsMenu( + InstrumentationRegistry.getInstrumentation().getTargetContext()); + // Before tapping the menu item for export, pretend that the last successful + // reauthentication just happened. This will allow the export flow to continue. + ReauthenticationManager.setLastReauthTimeMillis(System.currentTimeMillis()); + Espresso.onView(withText(R.string.save_password_preferences_export_action_title)) + .perform(click()); + + Assert.assertTrue(mHandler.getSerializePasswordsCalled()); + } + + /** * Check that the export menu item is included and hidden behind the overflow menu. Check that * the menu displays the warning before letting the user export passwords. */ @@ -409,6 +451,77 @@ } /** + * Check that if exporting is cancelled for the absence of the screen lock, the menu item is + * enabled for a retry. + */ + @Test + @SmallTest + @Feature({"Preferences"}) + @EnableFeatures("PasswordExport") + public void testExportMenuItemReenabledNoLock() throws Exception { + setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password")); + + ReauthenticationManager.setApiOverride(ReauthenticationManager.OverrideState.AVAILABLE); + ReauthenticationManager.setScreenLockSetUpOverride( + ReauthenticationManager.OverrideState.UNAVAILABLE); + + final Preferences preferences = + PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(), + SavePasswordsPreferences.class.getName()); + + Espresso.openActionBarOverflowOrOptionsMenu( + InstrumentationRegistry.getInstrumentation().getTargetContext()); + Espresso.onView(withText(R.string.save_password_preferences_export_action_title)) + .perform(click()); + Espresso.openActionBarOverflowOrOptionsMenu( + InstrumentationRegistry.getInstrumentation().getTargetContext()); + // The text matches a text view, but the potentially disabled entity is some wrapper two + // levels up in the view hierarchy, hence the two withParent matchers. + Espresso.onView(allOf(withText(R.string.save_password_preferences_export_action_title), + withParent(withParent(isEnabled())))) + .check(matches(isDisplayed())); + } + + /** + * Check that if exporting is cancelled for the user's failure to reauthenticate, the menu item + * is enabled for a retry. + */ + @Test + @SmallTest + @Feature({"Preferences"}) + @EnableFeatures("PasswordExport") + public void testExportMenuItemReenabledReauthFailure() throws Exception { + setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password")); + + ReauthenticationManager.setApiOverride(ReauthenticationManager.OverrideState.AVAILABLE); + ReauthenticationManager.setSkipSystemReauth(true); + + final Preferences preferences = + PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(), + SavePasswordsPreferences.class.getName()); + + Espresso.openActionBarOverflowOrOptionsMenu( + InstrumentationRegistry.getInstrumentation().getTargetContext()); + Espresso.onView(withText(R.string.save_password_preferences_export_action_title)) + .perform(click()); + // The reauthentication dialog is skipped and the last reauthentication timestamp is not + // reset. This looks like a failed reauthentication to SavePasswordsPreferences' onResume. + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + preferences.getFragmentForTest().onResume(); + } + }); + Espresso.openActionBarOverflowOrOptionsMenu( + InstrumentationRegistry.getInstrumentation().getTargetContext()); + // The text matches a text view, but the potentially disabled entity is some wrapper two + // levels up in the view hierarchy, hence the two withParent matchers. + Espresso.onView(allOf(withText(R.string.save_password_preferences_export_action_title), + withParent(withParent(isEnabled())))) + .check(matches(isDisplayed())); + } + + /** * Check whether the user is asked to set up a screen lock if attempting to view passwords. */ @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java index 103a845da..ec42408 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
@@ -55,4 +55,23 @@ TestAndroidShim profilingProcessHost = new TestAndroidShim(); Assert.assertTrue(profilingProcessHost.runTestForMode("browser", true, true)); } + + // Non-browser processes must be profiled with a command line flag, since + // otherwise, profiling will start after the relevant processes have been + // created, thus that process will be not be profiled. + @Test + @MediumTest + @CommandLineFlags.Add({"memlog=all-renderers", "memlog-stack-mode=pseudo"}) + public void testModeRendererPseudo() throws Exception { + TestAndroidShim profilingProcessHost = new TestAndroidShim(); + Assert.assertTrue(profilingProcessHost.runTestForMode("all-renderers", false, true)); + } + + @Test + @MediumTest + @CommandLineFlags.Add({"memlog=gpu", "memlog-stack-mode=pseudo"}) + public void testModeGpuPseudo() throws Exception { + TestAndroidShim profilingProcessHost = new TestAndroidShim(); + Assert.assertTrue(profilingProcessHost.runTestForMode("gpu", false, true)); + } }
diff --git a/chrome/app/md_extensions_strings.grdp b/chrome/app/md_extensions_strings.grdp index cdda1631..9d9b923 100644 --- a/chrome/app/md_extensions_strings.grdp +++ b/chrome/app/md_extensions_strings.grdp
@@ -75,7 +75,7 @@ <message name="IDS_MD_EXTENSIONS_ITEM_DETAILS" desc="The text on the button to show more details for a given extension."> Details </message> - <message name="IDS_MD_EXTENSIONS_EXTENSION_A11Y_ASSOCIATION" desc="Label used to associate an app or extension with actions for screen readers. This will only be read out lout."> + <message name="IDS_MD_EXTENSIONS_EXTENSION_A11Y_ASSOCIATION" desc="Label used to associate an app or extension with actions a user can take. This label is for screen readers and will only be read out lout. Ex: a button labeled 'Delete' would have the description 'Related to AdBlock'. Without the added description a user on a screen reader would not have context of the extension they want to delete. Note that the action can be 'view details', 'enable', 'delete', 'errors', or something else."> Related to <ph name="NAME_PH">$1<ex>AdBlock</ex></ph> </message> <message name="IDS_MD_EXTENSIONS_APP_ICON" desc="The alt text for the app's icon. Used for accessibility.">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 472d5ea3..1feab06 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2144,6 +2144,7 @@ "android/signin/signin_manager_android.h", "android/signin/signin_promo_util_android.cc", "android/signin/signin_promo_util_android.h", + "android/subresource_filter/test_subresource_filter_publisher.cc", "android/tab_android.cc", "android/tab_android.h", "android/tab_state.cc", @@ -4377,6 +4378,7 @@ "../android/java/src/org/chromium/chrome/browser/snackbar/smartlockautosignin/AutoSigninSnackbarController.java", "../android/java/src/org/chromium/chrome/browser/ssl/CaptivePortalHelper.java", "../android/java/src/org/chromium/chrome/browser/ssl/SecurityStateModel.java", + "../android/java/src/org/chromium/chrome/browser/subresource_filter/TestSubresourceFilterPublisher.java", "../android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java", "../android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java", "../android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 28cf756..63cd246 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2225,6 +2225,9 @@ {"vr-browsing-in-custom-tab", flag_descriptions::kVrBrowsingInCustomTabName, flag_descriptions::kVrBrowsingInCustomTabDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kVrBrowsingInCustomTab)}, + {"vr-icon-in-daydream-home", flag_descriptions::kVrIconInDaydreamHomeName, + flag_descriptions::kVrIconInDaydreamHomeDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kVrIconInDaydreamHome)}, {"vr-launch-intents", flag_descriptions::kVrLaunchIntentsName, flag_descriptions::kVrLaunchIntentsDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kVrLaunchIntents)},
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index a00bd297..e5301f2 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -124,6 +124,7 @@ &kVideoPersistence, &kVrBrowsingFeedback, &kVrBrowsingInCustomTab, + &kVrIconInDaydreamHome, &kVrLaunchIntents, &payments::features::kWebPaymentsMethodSectionOrderV2, &payments::features::kWebPaymentsModifiers, @@ -381,6 +382,9 @@ const base::Feature kVrBrowsingInCustomTab{"VrBrowsingInCustomTab", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kVrIconInDaydreamHome{"VrIconInDaydreamHome", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kVrLaunchIntents{"VrLaunchIntents", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index 17f1fc5..481b30e5 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -85,6 +85,7 @@ extern const base::Feature kVideoPersistence; extern const base::Feature kVrBrowsingFeedback; extern const base::Feature kVrBrowsingInCustomTab; +extern const base::Feature kVrIconInDaydreamHome; extern const base::Feature kVrLaunchIntents; extern const base::Feature kWebPaymentsSingleAppUiSkip; extern const base::Feature kWebVrAutopresentFromIntent;
diff --git a/chrome/browser/android/password_ui_view_android.cc b/chrome/browser/android/password_ui_view_android.cc index 36e8774..52ced7ce 100644 --- a/chrome/browser/android/password_ui_view_android.cc +++ b/chrome/browser/android/password_ui_view_android.cc
@@ -6,16 +6,23 @@ #include <algorithm> +#include "base/android/callback_android.h" #include "base/android/jni_string.h" #include "base/android/jni_weak_ref.h" +#include "base/android/scoped_java_ref.h" +#include "base/bind_helpers.h" #include "base/metrics/field_trial.h" #include "base/strings/string_piece.h" +#include "base/task_scheduler/post_task.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "components/autofill/core/common/password_form.h" #include "components/browser_sync/profile_sync_service.h" +#include "components/password_manager/core/browser/export/password_csv_writer.h" #include "components/password_manager/core/browser/password_manager_constants.h" #include "components/password_manager/core/browser/password_ui_utils.h" +#include "components/password_manager/core/browser/ui/credential_provider_interface.h" +#include "content/public/browser/browser_thread.h" #include "jni/PasswordUIView_jni.h" using base::android::ConvertUTF16ToJavaString; @@ -29,7 +36,20 @@ PasswordUIViewAndroid::~PasswordUIViewAndroid() {} void PasswordUIViewAndroid::Destroy(JNIEnv*, const JavaParamRef<jobject>&) { - delete this; + switch (state_) { + case State::ALIVE: + delete this; + break; + case State::ALIVE_SERIALIZATION_PENDING: + // Postpone the deletion until the pending tasks are completed, so that + // the tasks do not attempt a use after free while reading data from + // |this|. + state_ = State::DELETION_PENDING; + break; + case State::DELETION_PENDING: + NOTREACHED(); + break; + } } Profile* PasswordUIViewAndroid::GetProfile() { @@ -64,6 +84,7 @@ void PasswordUIViewAndroid::UpdatePasswordLists(JNIEnv* env, const JavaParamRef<jobject>&) { + DCHECK_EQ(State::ALIVE, state_); password_manager_presenter_.UpdatePasswordLists(); } @@ -71,6 +92,7 @@ JNIEnv* env, const JavaParamRef<jobject>&, int index) { + DCHECK_EQ(State::ALIVE, state_); const autofill::PasswordForm* form = password_manager_presenter_.GetPassword(index); if (!form) { @@ -91,6 +113,7 @@ JNIEnv* env, const JavaParamRef<jobject>&, int index) { + DCHECK_EQ(State::ALIVE, state_); const autofill::PasswordForm* form = password_manager_presenter_.GetPasswordException(index); if (!form) @@ -103,6 +126,7 @@ JNIEnv* env, const JavaParamRef<jobject>&, int index) { + DCHECK_EQ(State::ALIVE, state_); password_manager_presenter_.RemoveSavedPassword(index); } @@ -110,9 +134,45 @@ JNIEnv* env, const JavaParamRef<jobject>&, int index) { + DCHECK_EQ(State::ALIVE, state_); password_manager_presenter_.RemovePasswordException(index); } +void PasswordUIViewAndroid::HandleSerializePasswords( + JNIEnv* env, + const base::android::JavaParamRef<jobject>&, + const base::android::JavaParamRef<jobject>& callback) { + switch (state_) { + case State::ALIVE: + state_ = State::ALIVE_SERIALIZATION_PENDING; + break; + case State::ALIVE_SERIALIZATION_PENDING: + // The UI should not allow the user to re-request export before finishing + // or cancelling the pending one. + NOTREACHED(); + return; + case State::DELETION_PENDING: + // The Java part should not first request destroying of |this| and then + // ask |this| for serialized passwords. + NOTREACHED(); + return; + } + // The tasks are posted with base::Unretained, because deletion is postponed + // until the reply arrives (look for the occurrences of DELETION_PENDING in + // this file). The background processing is not expected to take very long, + // but still long enough not to block the UI thread. The main concern here is + // not to avoid the background computation if |this| is about to be deleted + // but to simply avoid use after free from the background task runner. + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&PasswordUIViewAndroid::ObtainAndSerializePasswords, + base::Unretained(this)), + base::BindOnce( + &PasswordUIViewAndroid::PostSerializedPasswords, + base::Unretained(this), + base::android::ScopedJavaGlobalRef<jobject>(env, callback))); +} + ScopedJavaLocalRef<jstring> JNI_PasswordUIView_GetAccountDashboardURL( JNIEnv* env, const JavaParamRef<jclass>&) { @@ -126,3 +186,39 @@ PasswordUIViewAndroid* controller = new PasswordUIViewAndroid(env, obj); return reinterpret_cast<intptr_t>(controller); } + +std::string PasswordUIViewAndroid::ObtainAndSerializePasswords() { + // This is run on a backend task runner. Do not access any member variables + // except for |credential_provider_| and |password_manager_presenter_|. + password_manager::CredentialProviderInterface* const provider = + credential_provider_for_testing_ ? credential_provider_for_testing_ + : &password_manager_presenter_; + + return password_manager::PasswordCSVWriter::SerializePasswords( + provider->GetAllPasswords()); +} + +void PasswordUIViewAndroid::PostSerializedPasswords( + const base::android::JavaRef<jobject>& callback, + std::string serialized_passwords) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + switch (state_) { + case State::ALIVE: + NOTREACHED(); + break; + case State::ALIVE_SERIALIZATION_PENDING: { + state_ = State::ALIVE; + if (export_target_for_testing_) { + *export_target_for_testing_ = serialized_passwords; + } else { + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::RunCallbackAndroid( + callback, ConvertUTF8ToJavaString(env, serialized_passwords)); + } + break; + } + case State::DELETION_PENDING: + delete this; + break; + } +}
diff --git a/chrome/browser/android/password_ui_view_android.h b/chrome/browser/android/password_ui_view_android.h index caa4a5f..416c6288 100644 --- a/chrome/browser/android/password_ui_view_android.h +++ b/chrome/browser/android/password_ui_view_android.h
@@ -20,6 +20,10 @@ #include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/browser/password_store_consumer.h" +namespace password_manager { +class CredentialProviderInterface; +} + // PasswordUIView for Android, contains jni hooks that allows Android UI to // display passwords and route UI commands back to native // PasswordManagerPresenter. @@ -58,11 +62,67 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>&, int index); + void HandleSerializePasswords( + JNIEnv* env, + const base::android::JavaParamRef<jobject>&, + const base::android::JavaParamRef<jobject>& callback); // Destroy the native implementation. void Destroy(JNIEnv*, const base::android::JavaParamRef<jobject>&); + void set_export_target_for_testing(std::string* export_target_for_testing) { + export_target_for_testing_ = export_target_for_testing; + } + + void set_credential_provider_for_testing( + password_manager::CredentialProviderInterface* provider) { + credential_provider_for_testing_ = provider; + } + private: + // Possible states in the life of PasswordUIViewAndroid. + // ALIVE: + // * Destroy was not called and no background tasks are pending. + // * All data members can be used on the main task runner. + // ALIVE_SERIALIZATION_PENDING: + // * Destroy was not called, password serialization task on another task + // runner is running. + // * All data members can be used on the main task runner, except for + // |password_manager_presenter_| which can only be used inside + // ObtainAndSerializePasswords, which is being run on a backend task + // runner. + // DELETION_PENDING: + // * Destroy() was called, a background task is pending and |this| should + // be deleted once the tasks complete. + // * This state should not be reached anywhere but in the compeltion call + // of the pending task. + enum class State { ALIVE, ALIVE_SERIALIZATION_PENDING, DELETION_PENDING }; + + // Calls |password_manager_presenter_| to retrieve cached PasswordForm objects + // and then PasswordCSVWriter to serialize them. It returns the serialized + // value. Both steps involve a lot of memory allocation and copying, so this + // method should be executed on a suitable task runner. + std::string ObtainAndSerializePasswords(); + + // Sends |serialized_passwords| to Java via |callback|. + void PostSerializedPasswords(const base::android::JavaRef<jobject>& callback, + std::string serialized_passwords); + + // The |state_| must only be accessed on the main task runner. + State state_ = State::ALIVE; + + // If not null, PostSerializedPasswords will write the serialized passwords to + // |*export_target_for_testing_| instead of passing them to Java. This must + // remain null in production code. + std::string* export_target_for_testing_ = nullptr; + PasswordManagerPresenter password_manager_presenter_; + + // If not null, passwords for exporting will be obtained from + // |*credential_provider_for_testing_|, otherwise from + // |password_manager_presenter_|. This must remain null in production code. + password_manager::CredentialProviderInterface* + credential_provider_for_testing_ = nullptr; + // Java side of UI controller. JavaObjectWeakGlobalRef weak_java_ui_controller_;
diff --git a/chrome/browser/android/password_ui_view_android_unittest.cc b/chrome/browser/android/password_ui_view_android_unittest.cc new file mode 100644 index 0000000..0b9dc95 --- /dev/null +++ b/chrome/browser/android/password_ui_view_android_unittest.cc
@@ -0,0 +1,160 @@ +// 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 "chrome/browser/android/password_ui_view_android.h" + +#include <jni.h> + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/android/jni_android.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/common/password_form.h" +#include "components/password_manager/core/browser/export/password_csv_writer.h" +#include "components/password_manager/core/browser/ui/credential_provider_interface.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" + +namespace android { + +using autofill::PasswordForm; +using base::android::AttachCurrentThread; +using base::android::JavaParamRef; + +namespace { + +// Specific deleter for PasswordUIViewAndroid, which calls +// PasswordUIViewAndroid::Destroy on the object. Use this with a +// std::unique_ptr. +struct PasswordUIViewAndroidDestroyDeleter { + inline void operator()(void* ptr) const { + (static_cast<PasswordUIViewAndroid*>(ptr)->Destroy( + nullptr, JavaParamRef<jobject>(nullptr))); + } +}; + +class FakeCredentialProvider + : public password_manager::CredentialProviderInterface { + public: + FakeCredentialProvider() = default; + ~FakeCredentialProvider() override = default; + + // password_manager::CredentialProviderInterface + std::vector<std::unique_ptr<PasswordForm>> GetAllPasswords() override; + + // Adds a PasswordForm specified by the arguments to the list returned by + // GetAllPasswords. + void AddPasswordEntry(const std::string& origin, + const std::string& username, + const std::string& password); + + private: + std::vector<std::unique_ptr<PasswordForm>> passwords_; + + DISALLOW_COPY_AND_ASSIGN(FakeCredentialProvider); +}; + +std::vector<std::unique_ptr<PasswordForm>> +FakeCredentialProvider::GetAllPasswords() { + std::vector<std::unique_ptr<PasswordForm>> clone; + for (const auto& password : passwords_) { + clone.push_back(std::make_unique<PasswordForm>(*password)); + } + return clone; +} + +void FakeCredentialProvider::AddPasswordEntry(const std::string& origin, + const std::string& username, + const std::string& password) { + auto form = std::make_unique<PasswordForm>(); + form->origin = GURL(origin); + form->signon_realm = origin; + form->username_value = base::UTF8ToUTF16(username); + form->password_value = base::UTF8ToUTF16(password); + passwords_.push_back(std::move(form)); +} + +} // namespace + +class PasswordUIViewAndroidTest : public ::testing::Test { + protected: + PasswordUIViewAndroidTest() + : testing_profile_manager_(TestingBrowserProcess::GetGlobal()), + env_(AttachCurrentThread()) {} + + void SetUp() override { + ASSERT_TRUE(testing_profile_manager_.SetUp()); + testing_profile_ = + testing_profile_manager_.CreateTestingProfile("test profile"); + } + + content::TestBrowserThreadBundle thread_bundle_; + TestingProfileManager testing_profile_manager_; + TestingProfile* testing_profile_; + JNIEnv* env_; +}; + +// Test that the asynchronous processing of password serialization controlled by +// PasswordUIViewAndroid arrives at the same result as synchronous way to +// serialize the passwords. +TEST_F(PasswordUIViewAndroidTest, GetSerializedPasswords) { + FakeCredentialProvider provider; + provider.AddPasswordEntry("https://example.com", "username", "password"); + + // Let the PasswordCSVWriter compute the result instead of hard-coding it, + // because this test focuses on PasswordUIView and not on detecting changes in + // PasswordCSVWriter. + const std::string expected_result = + password_manager::PasswordCSVWriter::SerializePasswords( + provider.GetAllPasswords()); + + std::unique_ptr<PasswordUIViewAndroid, PasswordUIViewAndroidDestroyDeleter> + password_ui_view( + new PasswordUIViewAndroid(env_, JavaParamRef<jobject>(nullptr))); + std::string serialized_passwords; + password_ui_view->set_export_target_for_testing(&serialized_passwords); + password_ui_view->set_credential_provider_for_testing(&provider); + password_ui_view->HandleSerializePasswords( + env_, JavaParamRef<jobject>(nullptr), JavaParamRef<jobject>(nullptr)); + + content::RunAllTasksUntilIdle(); + EXPECT_EQ(expected_result, serialized_passwords); +} + +// Test that destroying the PasswordUIView when tasks are pending does not lead +// to crashes. +TEST_F(PasswordUIViewAndroidTest, GetSerializedPasswords_Cancelled) { + FakeCredentialProvider provider; + provider.AddPasswordEntry("https://example.com", "username", "password"); + + std::unique_ptr<PasswordUIViewAndroid, PasswordUIViewAndroidDestroyDeleter> + password_ui_view( + new PasswordUIViewAndroid(env_, JavaParamRef<jobject>(nullptr))); + std::string serialized_passwords = "this should not get overwritten"; + password_ui_view->set_export_target_for_testing(&serialized_passwords); + password_ui_view->set_credential_provider_for_testing(&provider); + password_ui_view->HandleSerializePasswords( + env_, JavaParamRef<jobject>(nullptr), JavaParamRef<jobject>(nullptr)); + // Register the PasswordUIView for deletion. It should not destruct itself + // before the background tasks are run. The results of the background tasks + // are waited for and then thrown out, so |serialized_passwords| should not be + // overwritten. + password_ui_view.reset(); + // Now run the background tasks (and the subsequent deletion). + content::RunAllTasksUntilIdle(); + EXPECT_EQ("this should not get overwritten", serialized_passwords); +} + +} // namespace android
diff --git a/chrome/browser/android/subresource_filter/test_subresource_filter_publisher.cc b/chrome/browser/android/subresource_filter/test_subresource_filter_publisher.cc new file mode 100644 index 0000000..40a359c --- /dev/null +++ b/chrome/browser/android/subresource_filter/test_subresource_filter_publisher.cc
@@ -0,0 +1,108 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include <jni.h> + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/numerics/safe_conversions.h" +#include "base/threading/thread_restrictions.h" +#include "chrome/browser/browser_process.h" +#include "components/subresource_filter/content/browser/content_ruleset_service.h" +#include "components/subresource_filter/core/browser/ruleset_service.h" +#include "components/url_pattern_index/unindexed_ruleset.h" +#include "content/public/browser/browser_thread.h" +#include "jni/TestSubresourceFilterPublisher_jni.h" +#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h" + +// TODO(csharrison): This whole file is a hack, because Android cannot use +// native files that are test-only. So, this is a duplication and simplification +// of a lot of subresource_filter test harness code. Because it is compiled into +// a normal build of Chrome, I've tried to strip it down as much as possible. +// Once native test files can be used on Android, most all of this can be +// deleted. + +using content::BrowserThread; + +namespace { + +url_pattern_index::proto::UrlRule CreateSuffixRule(const std::string& suffix) { + url_pattern_index::proto::UrlRule rule; + rule.set_semantics(url_pattern_index::proto::RULE_SEMANTICS_BLACKLIST); + rule.set_source_type(url_pattern_index::proto::SOURCE_TYPE_ANY); + rule.set_element_types(url_pattern_index::proto::ELEMENT_TYPE_ALL); + rule.set_url_pattern_type( + url_pattern_index::proto::URL_PATTERN_TYPE_SUBSTRING); + rule.set_anchor_left(url_pattern_index::proto::ANCHOR_TYPE_NONE); + rule.set_anchor_right(url_pattern_index::proto::ANCHOR_TYPE_BOUNDARY); + rule.set_url_pattern(suffix); + return rule; +} + +void OnPublished(std::unique_ptr<base::ScopedTempDir> scoped_temp_dir, + subresource_filter::ContentRulesetService* service, + base::android::ScopedJavaGlobalRef<jobject> publisher) { + base::ScopedAllowBlockingForTesting allow_blocking; + // Ensure the callback does not retain |publisher| by resetting it. + service->SetRulesetPublishedCallbackForTesting(base::RepeatingClosure()); + scoped_temp_dir.reset(); + Java_TestSubresourceFilterPublisher_onRulesetPublished( + base::android::AttachCurrentThread(), publisher); +} + +} // namespace + +void JNI_TestSubresourceFilterPublisher_CreateAndPublishRulesetDisallowingSuffixForTesting( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& publisher_param, + const base::android::JavaParamRef<jstring>& suffix) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + base::android::ScopedJavaGlobalRef<jobject> publisher; + publisher.Reset(env, publisher_param); + + // Create the ruleset contents. + std::string ruleset_contents_str; + google::protobuf::io::StringOutputStream output(&ruleset_contents_str); + url_pattern_index::UnindexedRulesetWriter ruleset_writer(&output); + ruleset_writer.AddUrlRule( + CreateSuffixRule(base::android::ConvertJavaStringToUTF8(env, suffix))); + ruleset_writer.Finish(); + auto* data = reinterpret_cast<const uint8_t*>(ruleset_contents_str.data()); + std::vector<uint8_t> ruleset_contents(data, + data + ruleset_contents_str.size()); + + // Create the ruleset directory and write the ruleset data into a file there. + base::ScopedAllowBlockingForTesting allow_blocking; + auto scoped_temp_dir = std::make_unique<base::ScopedTempDir>(); + CHECK(scoped_temp_dir->CreateUniqueTempDir()); + base::FilePath ruleset_path = scoped_temp_dir->GetPath().AppendASCII("1"); + int ruleset_size_as_int = base::checked_cast<int>(ruleset_contents.size()); + CHECK_EQ( + ruleset_size_as_int, + base::WriteFile(ruleset_path, + reinterpret_cast<const char*>(ruleset_contents.data()), + ruleset_size_as_int)); + + subresource_filter::ContentRulesetService* service = + g_browser_process->subresource_filter_ruleset_service(); + service->SetIsAfterStartupForTesting(); + service->SetRulesetPublishedCallbackForTesting(base::BindRepeating( + &OnPublished, base::Passed(&scoped_temp_dir), service, publisher)); + + subresource_filter::UnindexedRulesetInfo unindexed_ruleset_info; + unindexed_ruleset_info.content_version = "1"; + unindexed_ruleset_info.ruleset_path = ruleset_path; + service->IndexAndStoreAndPublishRulesetIfNeeded(unindexed_ruleset_info); +}
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index bafe286..1a36a86 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -967,7 +967,6 @@ component_updater_ = component_updater::ComponentUpdateServiceFactory( component_updater::MakeChromeComponentUpdaterConfigurator( base::CommandLine::ForCurrentProcess(), - io_thread()->system_url_request_context_getter(), g_browser_process->local_state())); return component_updater_.get();
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index 477a683..06e1787 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -82,6 +82,7 @@ #include "net/cookies/cookie_store.h" #include "net/http/http_transaction_factory.h" #include "net/reporting/reporting_browsing_data_remover.h" +#include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_service.h" #include "net/url_request/network_error_logging_delegate.h" #include "net/url_request/url_request_context.h" @@ -950,6 +951,12 @@ return true; } + const net::ReportingPolicy& GetPolicy() const override { + static net::ReportingPolicy dummy_policy_; + NOTREACHED(); + return dummy_policy_; + } + int remove_calls() const { return remove_calls_; } int last_data_type_mask() const { return last_data_type_mask_; } const base::RepeatingCallback<bool(const GURL&)>& last_origin_filter() const {
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc index 9ae4b31..62e9752 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc +++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -85,15 +85,8 @@ class FakeLoginDisplayHost : public chromeos::LoginDisplayHost { public: - FakeLoginDisplayHost() { - DCHECK(!chromeos::LoginDisplayHost::default_host_); - chromeos::LoginDisplayHost::default_host_ = this; - } - - ~FakeLoginDisplayHost() override { - DCHECK_EQ(chromeos::LoginDisplayHost::default_host_, this); - chromeos::LoginDisplayHost::default_host_ = nullptr; - } + FakeLoginDisplayHost() = default; + ~FakeLoginDisplayHost() override = default; /// chromeos::LoginDisplayHost: chromeos::LoginDisplay* CreateLoginDisplay(
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc index 2442ba4..2109c39 100644 --- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc +++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
@@ -59,10 +59,10 @@ proxy_rules.ParseFromString(proxy_rules_string); const net::ProxyList* proxy_list = nullptr; - if (proxy_rules.type == net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY) { + if (proxy_rules.type == net::ProxyConfig::ProxyRules::Type::PROXY_LIST) { proxy_list = &proxy_rules.single_proxies; } else if (proxy_rules.type == - net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) { + net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME) { proxy_list = proxy_rules.MapUrlSchemeToProxyList(url::kHttpScheme); } if (!proxy_list || proxy_list->IsEmpty())
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc index 0e546ea..cedbee08 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -11,6 +11,7 @@ #include "base/command_line.h" #include "base/location.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" @@ -24,6 +25,7 @@ #include "chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.h" #include "chrome/browser/chromeos/login/ui/mock_login_display.h" #include "chrome/browser/chromeos/login/ui/mock_login_display_host.h" +#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/device_local_account.h" @@ -53,6 +55,7 @@ #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_type.h" @@ -436,9 +439,11 @@ test::UserSessionManagerTestApi session_manager_test_api( UserSessionManager::GetInstance()); session_manager_test_api.InjectStubUserContext(user_context); + // There may be in-session oobe or an initial login screen created from + // --login-manager. EXPECT_CALL(*mock_login_display_host_, StartWizard(OobeScreen::SCREEN_TERMS_OF_SERVICE)) - .Times(0); + .Times(AnyNumber()); EXPECT_CALL(*mock_login_display_, SetUIEnabled(false)).Times(AnyNumber()); EXPECT_CALL(*mock_login_display_, SetUIEnabled(true)).Times(AnyNumber()); }
diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc index e5455325..a42be64f 100644 --- a/chrome/browser/chromeos/login/helper.cc +++ b/chrome/browser/chromeos/login/helper.cc
@@ -169,7 +169,8 @@ const std::string& guid) const { // Connect to the network. NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork( - service_path, success_callback, error_callback, false); + service_path, success_callback, error_callback, + false /* check_error_state */, ConnectCallbackMode::ON_COMPLETED); } content::StoragePartition* GetSigninPartition() {
diff --git a/chrome/browser/chromeos/login/ui/login_display_host.cc b/chrome/browser/chromeos/login/ui/login_display_host.cc index 9e1f86d..daeb633 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host.cc
@@ -28,9 +28,14 @@ // static LoginDisplayHost* LoginDisplayHost::default_host_ = nullptr; -LoginDisplayHost::LoginDisplayHost() : weak_factory_(this) {} +LoginDisplayHost::LoginDisplayHost() : weak_factory_(this) { + DCHECK(default_host() == nullptr); + default_host_ = this; +} -LoginDisplayHost::~LoginDisplayHost() = default; +LoginDisplayHost::~LoginDisplayHost() { + default_host_ = nullptr; +} AppLaunchController* LoginDisplayHost::GetAppLaunchController() { return app_launch_controller_.get();
diff --git a/chrome/browser/chromeos/login/ui/login_display_host.h b/chrome/browser/chromeos/login/ui/login_display_host.h index dbbfbdc..154655d 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host.h +++ b/chrome/browser/chromeos/login/ui/login_display_host.h
@@ -139,9 +139,6 @@ bool IsUserWhitelisted(const AccountId& account_id); protected: - // Default LoginDisplayHost. Child class sets the reference. - static LoginDisplayHost* default_host_; - virtual void OnStartSignInScreen(const LoginScreenContext& context) = 0; virtual void OnStartAppLaunch() = 0; virtual void OnStartArcKiosk() = 0; @@ -162,6 +159,9 @@ std::unique_ptr<ArcKioskController> arc_kiosk_controller_; private: + // Global LoginDisplayHost instance. + static LoginDisplayHost* default_host_; + base::WeakPtrFactory<LoginDisplayHost> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LoginDisplayHost);
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_views.cc b/chrome/browser/chromeos/login/ui/login_display_host_views.cc index 548785d..5c5d238 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_views.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_views.cc
@@ -30,14 +30,9 @@ } // namespace -LoginDisplayHostViews::LoginDisplayHostViews() : weak_factory_(this) { - DCHECK(default_host() == nullptr); - default_host_ = this; -} +LoginDisplayHostViews::LoginDisplayHostViews() : weak_factory_(this) {} LoginDisplayHostViews::~LoginDisplayHostViews() { - DCHECK_EQ(default_host_, this); - default_host_ = nullptr; LoginScreenClient::Get()->SetDelegate(nullptr); ScheduleCompletionCallbacks(std::move(completion_callbacks_)); } @@ -53,7 +48,6 @@ } OobeUI* LoginDisplayHostViews::GetOobeUI() const { - NOTREACHED(); return nullptr; }
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc index eefe88d..deddcb56 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -188,8 +188,11 @@ // Create the LoginDisplayHost. Use the views-based implementation only for // the sign-in screen. chromeos::LoginDisplayHost* display_host = nullptr; - if (ash::switches::IsUsingViewsLogin() && - ShouldShowSigninScreen(first_screen)) { + if (chromeos::LoginDisplayHost::default_host()) { + // Tests may have already allocated an instance for us to use. + display_host = chromeos::LoginDisplayHost::default_host(); + } else if (ash::switches::IsUsingViewsLogin() && + ShouldShowSigninScreen(first_screen)) { display_host = new chromeos::LoginDisplayHostViews(); } else { gfx::Rect screen_bounds(chromeos::CalculateScreenBounds(gfx::Size())); @@ -444,9 +447,6 @@ registrar_.Add(this, chrome::NOTIFICATION_LOGIN_USER_CHANGED, content::NotificationService::AllSources()); - DCHECK(default_host() == nullptr); - default_host_ = this; - keep_alive_.reset( new ScopedKeepAlive(KeepAliveOrigin::LOGIN_DISPLAY_HOST_WEBUI, KeepAliveRestartOption::DISABLED)); @@ -543,7 +543,6 @@ keep_alive_.reset(); - default_host_ = nullptr; // TODO(tengs): This should be refactored. See crbug.com/314934. if (user_manager::UserManager::Get()->IsCurrentUserNew()) { // DriveOptInController will delete itself when finished.
diff --git a/chrome/browser/chromeos/mobile/mobile_activator.cc b/chrome/browser/chromeos/mobile/mobile_activator.cc index 547a657e..cdaccd3 100644 --- a/chrome/browser/chromeos/mobile/mobile_activator.cc +++ b/chrome/browser/chromeos/mobile/mobile_activator.cc
@@ -560,10 +560,9 @@ void MobileActivator::ConnectNetwork(const NetworkState* network) { NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork( - network->path(), - base::Bind(&base::DoNothing), - network_handler::ErrorCallback(), - false /* check_error_state */); + network->path(), base::Bind(&base::DoNothing), + network_handler::ErrorCallback(), false /* check_error_state */, + ConnectCallbackMode::ON_STARTED); } void MobileActivator::ForceReconnect(const NetworkState* network,
diff --git a/chrome/browser/chromeos/preferences_chromeos_browsertest.cc b/chrome/browser/chromeos/preferences_chromeos_browsertest.cc index e9e516eb..be8e8d0 100644 --- a/chrome/browser/chromeos/preferences_chromeos_browsertest.cc +++ b/chrome/browser/chromeos/preferences_chromeos_browsertest.cc
@@ -5,37 +5,23 @@ #include <stddef.h> #include <sys/types.h> -#include <set> -#include <string> - #include "base/command_line.h" -#include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/run_loop.h" -#include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/input_method/input_method_manager_impl.h" #include "chrome/browser/chromeos/login/login_manager_test.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/ui/user_adding_screen.h" -#include "chrome/browser/chromeos/preferences.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" #include "chrome/browser/chromeos/system/fake_input_device_settings.h" -#include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/in_process_browser_test.h" #include "chromeos/chromeos_switches.h" #include "components/feedback/tracing_manager.h" #include "components/prefs/pref_service.h" -#include "components/prefs/pref_store.h" -#include "components/prefs/writeable_pref_store.h" #include "components/user_manager/user_manager.h" -#include "content/public/common/service_manager_connection.h" #include "content/public/test/test_utils.h" -#include "services/service_manager/public/cpp/connector.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ime/chromeos/fake_ime_keyboard.h" #include "ui/events/event_utils.h" @@ -141,61 +127,6 @@ DISALLOW_COPY_AND_ASSIGN(PreferencesTest); }; -class PreferencesServiceBrowserTest : public InProcessBrowserTest { - public: - PreferencesServiceBrowserTest() {} - - protected: - static service_manager::Connector* connector() { - return content::ServiceManagerConnection::GetForProcess()->GetConnector(); - } - - void WaitForPrefChange(PrefStore* store, const std::string& key) { - base::RunLoop run_loop; - TestPrefObserver observer(key, run_loop.QuitClosure()); - store->AddObserver(&observer); - run_loop.Run(); - store->RemoveObserver(&observer); - } - - bool GetIntegerPrefValue(PrefStore* store, - const std::string& key, - int* out_value) { - const base::Value* value = nullptr; - if (!store->GetValue(key, &value)) - return false; - return value->GetAsInteger(out_value); - } - - private: - class TestPrefObserver : public PrefStore::Observer { - public: - TestPrefObserver(const std::string& pref_name, - const base::Closure& callback) - : pref_name_(pref_name), callback_(callback) {} - - ~TestPrefObserver() override {} - - // PrefStore::Observer: - void OnPrefValueChanged(const std::string& key) override { - if (key == pref_name_) - callback_.Run(); - } - - void OnInitializationCompleted(bool success) override { - ASSERT_TRUE(success); - } - - private: - const std::string pref_name_; - const base::Closure callback_; - - DISALLOW_COPY_AND_ASSIGN(TestPrefObserver); - }; - - DISALLOW_COPY_AND_ASSIGN(PreferencesServiceBrowserTest); -}; - IN_PROC_BROWSER_TEST_F(PreferencesTest, PRE_MultiProfiles) { RegisterUser(test_users_[0]); RegisterUser(test_users_[1]);
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator.cc b/chrome/browser/component_updater/chrome_component_updater_configurator.cc index 2a53f42..8c53ba3e 100644 --- a/chrome/browser/component_updater/chrome_component_updater_configurator.cc +++ b/chrome/browser/component_updater/chrome_component_updater_configurator.cc
@@ -40,7 +40,6 @@ class ChromeConfigurator : public update_client::Configurator { public: ChromeConfigurator(const base::CommandLine* cmdline, - net::URLRequestContextGetter* url_request_getter, PrefService* pref_service); // update_client::Configurator overrides. @@ -58,7 +57,7 @@ std::string GetOSLongName() const override; std::string ExtraRequestParams() const override; std::string GetDownloadPreference() const override; - net::URLRequestContextGetter* RequestContext() const override; + scoped_refptr<net::URLRequestContextGetter> RequestContext() const override; std::unique_ptr<service_manager::Connector> CreateServiceManagerConnector() const override; bool EnabledDeltas() const override; @@ -82,12 +81,9 @@ // Allows the component updater to use non-encrypted communication with the // update backend. The security of the update checks is enforced using // a custom message signing protocol and it does not depend on using HTTPS. -ChromeConfigurator::ChromeConfigurator( - const base::CommandLine* cmdline, - net::URLRequestContextGetter* url_request_getter, - PrefService* pref_service) - : configurator_impl_(cmdline, url_request_getter, false), - pref_service_(pref_service) { +ChromeConfigurator::ChromeConfigurator(const base::CommandLine* cmdline, + PrefService* pref_service) + : configurator_impl_(cmdline, false), pref_service_(pref_service) { DCHECK(pref_service_); } @@ -158,8 +154,9 @@ #endif } -net::URLRequestContextGetter* ChromeConfigurator::RequestContext() const { - return configurator_impl_.RequestContext(); +scoped_refptr<net::URLRequestContextGetter> ChromeConfigurator::RequestContext() + const { + return g_browser_process->system_request_context(); } std::unique_ptr<service_manager::Connector> @@ -214,10 +211,8 @@ scoped_refptr<update_client::Configurator> MakeChromeComponentUpdaterConfigurator( const base::CommandLine* cmdline, - net::URLRequestContextGetter* context_getter, PrefService* pref_service) { - return base::MakeRefCounted<ChromeConfigurator>(cmdline, context_getter, - pref_service); + return base::MakeRefCounted<ChromeConfigurator>(cmdline, pref_service); } } // namespace component_updater
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator.h b/chrome/browser/component_updater/chrome_component_updater_configurator.h index 19eaffff..608f1f1 100644 --- a/chrome/browser/component_updater/chrome_component_updater_configurator.h +++ b/chrome/browser/component_updater/chrome_component_updater_configurator.h
@@ -15,10 +15,6 @@ class CommandLine; } -namespace net { -class URLRequestContextGetter; -} - namespace component_updater { // Registers preferences associated with the component updater configurator @@ -31,7 +27,6 @@ scoped_refptr<update_client::Configurator> MakeChromeComponentUpdaterConfigurator( const base::CommandLine* cmdline, - net::URLRequestContextGetter* context_getter, PrefService* pref_service); } // namespace component_updater
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator_unittest.cc b/chrome/browser/component_updater/chrome_component_updater_configurator_unittest.cc index 89ebecf..cbc6a83 100644 --- a/chrome/browser/component_updater/chrome_component_updater_configurator_unittest.cc +++ b/chrome/browser/component_updater/chrome_component_updater_configurator_unittest.cc
@@ -47,8 +47,8 @@ base::CommandLine cmdline(*base::CommandLine::ForCurrentProcess()); cmdline.AppendSwitchASCII(switches::kComponentUpdater, "disable-pings"); - const auto config(MakeChromeComponentUpdaterConfigurator(&cmdline, nullptr, - pref_service())); + const auto config( + MakeChromeComponentUpdaterConfigurator(&cmdline, pref_service())); const std::vector<GURL> pingUrls = config->PingUrl(); EXPECT_TRUE(pingUrls.empty()); @@ -58,8 +58,8 @@ base::CommandLine cmdline(*base::CommandLine::ForCurrentProcess()); cmdline.AppendSwitchASCII(switches::kComponentUpdater, "fast-update"); - const auto config(MakeChromeComponentUpdaterConfigurator(&cmdline, nullptr, - pref_service())); + const auto config( + MakeChromeComponentUpdaterConfigurator(&cmdline, pref_service())); CHECK_EQ(10, config->InitialDelay()); CHECK_EQ(5 * 60 * 60, config->NextCheckDelay()); @@ -77,8 +77,8 @@ val.append(overrideUrl); cmdline.AppendSwitchASCII(switches::kComponentUpdater, val.c_str()); - const auto config(MakeChromeComponentUpdaterConfigurator(&cmdline, nullptr, - pref_service())); + const auto config( + MakeChromeComponentUpdaterConfigurator(&cmdline, pref_service())); const std::vector<GURL> urls = config->UpdateUrl(); @@ -90,16 +90,16 @@ base::CommandLine cmdline(*base::CommandLine::ForCurrentProcess()); cmdline.AppendSwitchASCII(switches::kComponentUpdater, "test-request"); - const auto config(MakeChromeComponentUpdaterConfigurator(&cmdline, nullptr, - pref_service())); + const auto config( + MakeChromeComponentUpdaterConfigurator(&cmdline, pref_service())); EXPECT_FALSE(config->ExtraRequestParams().empty()); } TEST_F(ChromeComponentUpdaterConfiguratorTest, TestUpdaterDefaultUrl) { base::CommandLine cmdline(*base::CommandLine::ForCurrentProcess()); - const auto config(MakeChromeComponentUpdaterConfigurator(&cmdline, nullptr, - pref_service())); + const auto config( + MakeChromeComponentUpdaterConfigurator(&cmdline, pref_service())); const auto urls = config->UpdateUrl(); // Expect the default url to be cryptographically secure. @@ -109,8 +109,8 @@ TEST_F(ChromeComponentUpdaterConfiguratorTest, TestEnabledCupSigning) { base::CommandLine cmdline(*base::CommandLine::ForCurrentProcess()); - const auto config(MakeChromeComponentUpdaterConfigurator(&cmdline, nullptr, - pref_service())); + const auto config( + MakeChromeComponentUpdaterConfigurator(&cmdline, pref_service())); EXPECT_TRUE(config->EnabledCupSigning()); } @@ -118,7 +118,7 @@ TEST_F(ChromeComponentUpdaterConfiguratorTest, TestUseEncryption) { base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); const auto config( - MakeChromeComponentUpdaterConfigurator(cmdline, nullptr, pref_service())); + MakeChromeComponentUpdaterConfigurator(cmdline, pref_service())); const auto urls = config->UpdateUrl(); ASSERT_EQ(2u, urls.size()); @@ -130,7 +130,7 @@ // Use the configurator implementation to test the filtering of // unencrypted URLs. { - const ConfiguratorImpl config(cmdline, nullptr, true); + const ConfiguratorImpl config(cmdline, true); const auto urls = config.UpdateUrl(); ASSERT_EQ(1u, urls.size()); ASSERT_STREQ(kUpdaterDefaultUrlAlt, urls[0].spec().c_str()); @@ -138,7 +138,7 @@ } { - const ConfiguratorImpl config(cmdline, nullptr, false); + const ConfiguratorImpl config(cmdline, false); const auto urls = config.UpdateUrl(); ASSERT_EQ(2u, urls.size()); ASSERT_STREQ(kUpdaterDefaultUrlAlt, urls[0].spec().c_str()); @@ -149,8 +149,8 @@ TEST_F(ChromeComponentUpdaterConfiguratorTest, TestEnabledComponentUpdates) { base::CommandLine cmdline(*base::CommandLine::ForCurrentProcess()); - const auto config(MakeChromeComponentUpdaterConfigurator(&cmdline, nullptr, - pref_service())); + const auto config( + MakeChromeComponentUpdaterConfigurator(&cmdline, pref_service())); // Tests the default is set to |true| and the component updates are enabled. EXPECT_TRUE(config->EnabledComponentUpdates()); @@ -175,8 +175,8 @@ TEST_F(ChromeComponentUpdaterConfiguratorTest, TestProdId) { base::CommandLine cmdline(*base::CommandLine::ForCurrentProcess()); - const auto config(MakeChromeComponentUpdaterConfigurator(&cmdline, nullptr, - pref_service())); + const auto config( + MakeChromeComponentUpdaterConfigurator(&cmdline, pref_service())); EXPECT_STREQ(update_client::UpdateQueryParams::GetProdIdString( update_client::UpdateQueryParams::ProdId::CHROME), config->GetProdId().c_str());
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index 356374b..0771dc9 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -2041,7 +2041,7 @@ // after download of a file while viewing another chrome://. IN_PROC_BROWSER_TEST_F(DownloadTest, ChromeURLAfterDownload) { GURL flags_url(chrome::kChromeUIFlagsURL); - GURL extensions_url(chrome::kChromeUIExtensionsFrameURL); + GURL extensions_url(chrome::kChromeUIExtensionsURL); embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -2057,7 +2057,9 @@ bool webui_responded = false; EXPECT_TRUE(content::ExecuteScriptAndExtractBool( contents, - "window.domAutomationController.send(window.webuiResponded);", + R"(chrome.developerPrivate.getExtensionsInfo(function(info) { + domAutomationController.send(!!info && !chrome.runtime.lastError); + });)", &webui_responded)); EXPECT_TRUE(webui_responded); }
diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc index 63c005e..4ec343e 100644 --- a/chrome/browser/extensions/api/processes/processes_api.cc +++ b/chrome/browser/extensions/api/processes/processes_api.cc
@@ -372,11 +372,12 @@ refresh_types |= GetRefreshTypesFlagOnlyEssentialData(); } + const int64_t on_updated_types = GetRefreshTypesForProcessOptionalData(); if (HasEventListeners(api::processes::OnUpdated::kEventName)) - refresh_types |= GetRefreshTypesForProcessOptionalData(); + refresh_types |= on_updated_types; if (HasEventListeners(api::processes::OnUpdatedWithMemory::kEventName)) - refresh_types |= task_manager::REFRESH_TYPE_MEMORY; + refresh_types |= (on_updated_types | task_manager::REFRESH_TYPE_MEMORY); SetRefreshTypesFlags(refresh_types); }
diff --git a/chrome/browser/extensions/api/processes/processes_apitest.cc b/chrome/browser/extensions/api/processes/processes_apitest.cc index d75a406..42668f26 100644 --- a/chrome/browser/extensions/api/processes/processes_apitest.cc +++ b/chrome/browser/extensions/api/processes/processes_apitest.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/common/extensions/api/processes.h" #include "extensions/common/switches.h" #include "extensions/test/extension_test_message_listener.h" @@ -69,6 +70,48 @@ EXPECT_EQ(0, GetListenersCount()); } +IN_PROC_BROWSER_TEST_F(ProcessesApiTest, OnUpdatedWithMemoryRefreshTypes) { + EXPECT_EQ(0, GetListenersCount()); + + // Load an extension that listen to the onUpdatedWithMemory. + ExtensionTestMessageListener listener("ready", false /* will_reply */); + const extensions::Extension* extension = + LoadExtension(test_data_dir_.AppendASCII("processes") + .AppendASCII("onupdated_with_memory")); + ASSERT_TRUE(extension); + ASSERT_TRUE(listener.WaitUntilSatisfied()); + + // The memory refresh type must be enabled now. + const task_manager::TaskManagerInterface* task_manager = + task_manager::TaskManagerInterface::GetTaskManager(); + EXPECT_EQ(1, GetListenersCount()); + extensions::EventRouter* event_router = + extensions::EventRouter::Get(profile()); + EXPECT_TRUE(event_router->HasEventListener( + extensions::api::processes::OnUpdatedWithMemory::kEventName)); + EXPECT_FALSE(event_router->HasEventListener( + extensions::api::processes::OnUpdated::kEventName)); + EXPECT_TRUE(task_manager->IsResourceRefreshEnabled( + task_manager::REFRESH_TYPE_MEMORY)); + + // Despite the fact that there are no onUpdated listeners, refresh types for + // CPU, Network, SQLite, V8 memory, and webcache stats should be enabled. + constexpr task_manager::RefreshType kOnUpdatedRefreshTypes[] = { + task_manager::REFRESH_TYPE_CPU, + task_manager::REFRESH_TYPE_NETWORK_USAGE, + task_manager::REFRESH_TYPE_SQLITE_MEMORY, + task_manager::REFRESH_TYPE_V8_MEMORY, + task_manager::REFRESH_TYPE_WEBCACHE_STATS, + }; + + for (const auto& type : kOnUpdatedRefreshTypes) + EXPECT_TRUE(task_manager->IsResourceRefreshEnabled(type)); + + // Unload the extensions and make sure the listeners count is updated. + UnloadExtension(extension->id()); + EXPECT_EQ(0, GetListenersCount()); +} + IN_PROC_BROWSER_TEST_F(ProcessesApiTest, CannotTerminateBrowserProcess) { ASSERT_TRUE(RunExtensionTest("processes/terminate-browser-process")) << message_;
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc index 780aafee..4ff753e 100644 --- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc +++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
@@ -378,16 +378,16 @@ rules.ParseFromString(proxy_servers); switch (rules.type) { - case net::ProxyConfig::ProxyRules::TYPE_NO_RULES: + case net::ProxyConfig::ProxyRules::Type::EMPTY: return NULL; - case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY: + case net::ProxyConfig::ProxyRules::Type::PROXY_LIST: if (!rules.single_proxies.IsEmpty()) { extension_proxy_rules->Set( keys::field_name[keys::SCHEME_ALL], CreateProxyServerDict(rules.single_proxies.Get())); } break; - case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME: + case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME: if (!rules.proxies_for_http.IsEmpty()) { extension_proxy_rules->Set( keys::field_name[keys::SCHEME_HTTP],
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc index e802ba00..173a98d 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -1389,7 +1389,7 @@ ScriptExecutor::SINGLE_FRAME, ExtensionApiFrameIdMap::kTopFrameId, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, UserScript::DOCUMENT_IDLE, ScriptExecutor::MAIN_WORLD, ScriptExecutor::DEFAULT_PROCESS, GURL(), - GURL(), user_gesture(), ScriptExecutor::NO_RESULT, + GURL(), user_gesture(), base::nullopt, ScriptExecutor::NO_RESULT, base::Bind(&TabsUpdateFunction::OnExecuteCodeFinished, this)); *is_async = true;
diff --git a/chrome/browser/extensions/execute_script_apitest.cc b/chrome/browser/extensions/execute_script_apitest.cc index ca31131..d249e0e5 100644 --- a/chrome/browser/extensions/execute_script_apitest.cc +++ b/chrome/browser/extensions/execute_script_apitest.cc
@@ -90,6 +90,10 @@ ASSERT_TRUE(RunExtensionTest("executescript/run_at")) << message_; } +IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptCSSOrigin) { + ASSERT_TRUE(RunExtensionTest("executescript/css_origin")) << message_; +} + IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptCallback) { ASSERT_TRUE(RunExtensionTest("executescript/callback")) << message_; }
diff --git a/chrome/browser/extensions/updater/chrome_update_client_config.cc b/chrome/browser/extensions/updater/chrome_update_client_config.cc index c8d6d56b5..3ec4c12 100644 --- a/chrome/browser/extensions/updater/chrome_update_client_config.cc +++ b/chrome/browser/extensions/updater/chrome_update_client_config.cc
@@ -83,9 +83,8 @@ // communication with the update backend. ChromeUpdateClientConfig::ChromeUpdateClientConfig( content::BrowserContext* context) - : impl_(base::CommandLine::ForCurrentProcess(), - content::BrowserContext::GetDefaultStoragePartition(context) - ->GetURLRequestContext(), + : context_(context), + impl_(base::CommandLine::ForCurrentProcess(), /*require_encryption=*/true), pref_service_(ExtensionPrefs::Get(context)->pref_service()), activity_data_service_(std::make_unique<ExtensionActivityDataService>( @@ -152,8 +151,10 @@ return std::string(); } -net::URLRequestContextGetter* ChromeUpdateClientConfig::RequestContext() const { - return impl_.RequestContext(); +scoped_refptr<net::URLRequestContextGetter> +ChromeUpdateClientConfig::RequestContext() const { + return content::BrowserContext::GetDefaultStoragePartition(context_) + ->GetURLRequestContext(); } std::unique_ptr<service_manager::Connector>
diff --git a/chrome/browser/extensions/updater/chrome_update_client_config.h b/chrome/browser/extensions/updater/chrome_update_client_config.h index e27d3393..9ae98af9 100644 --- a/chrome/browser/extensions/updater/chrome_update_client_config.h +++ b/chrome/browser/extensions/updater/chrome_update_client_config.h
@@ -44,7 +44,7 @@ std::string GetOSLongName() const override; std::string ExtraRequestParams() const override; std::string GetDownloadPreference() const override; - net::URLRequestContextGetter* RequestContext() const override; + scoped_refptr<net::URLRequestContextGetter> RequestContext() const override; std::unique_ptr<service_manager::Connector> CreateServiceManagerConnector() const override; bool EnabledDeltas() const override; @@ -61,6 +61,7 @@ ~ChromeUpdateClientConfig() override; private: + content::BrowserContext* context_ = nullptr; component_updater::ConfiguratorImpl impl_; PrefService* pref_service_; std::unique_ptr<update_client::ActivityDataService> activity_data_service_;
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 0444ab0..720fe1b 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2811,6 +2811,10 @@ const char kVrBrowsingInCustomTabDescription[] = "Allow browsing within a VR headset while in a Custom Tab."; +const char kVrIconInDaydreamHomeName[] = "Chrome icon in Daydream Home"; +const char kVrIconInDaydreamHomeDescription[] = + "Adds an icon to Daydream Home that allows launching Chrome in VR."; + const char kVrLaunchIntentsName[] = "VR intents"; const char kVrLaunchIntentsDescription[] = "Allow intents to launch Chrome in VR mode.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index bdcd466f..5d61047 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1731,6 +1731,9 @@ extern const char kVrBrowsingInCustomTabName[]; extern const char kVrBrowsingInCustomTabDescription[]; +extern const char kVrIconInDaydreamHomeName[]; +extern const char kVrIconInDaydreamHomeDescription[]; + extern const char kVrLaunchIntentsName[]; extern const char kVrLaunchIntentsDescription[];
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc index 1f7e765..062c918a 100644 --- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc +++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/mac/bluetooth_utility.h" #include "chrome/browser/shell_integration.h" +#include "chrome/browser/vr/service/vr_device_manager.h" #include "components/flags_ui/pref_service_flags_storage.h" #include "content/public/common/content_switches.h" #include "content/public/common/service_manager_connection.h" @@ -514,6 +515,10 @@ std::move(connector), base::Bind(&OnShellHandlerConnectionError), base::Bind(&OnIsPinnedToTaskbarResult)); } + +void RecordVrStartupHistograms() { + vr::VRDeviceManager::RecordVrStartupHistograms(); +} #endif // defined(OS_WIN) } // namespace @@ -597,11 +602,19 @@ service_manager::Connector* connector = content::ServiceManagerConnection::GetForProcess()->GetConnector(); - base::CreateSequencedTaskRunnerWithTraits(background_task_traits) - ->PostDelayedTask( - FROM_HERE, - base::BindOnce(&RecordIsPinnedToTaskbarHistogram, connector->Clone()), - base::TimeDelta::FromSeconds(45)); + auto background_task_runner = + base::CreateSequencedTaskRunnerWithTraits(background_task_traits); + + background_task_runner->PostDelayedTask( + FROM_HERE, + base::BindOnce(&RecordIsPinnedToTaskbarHistogram, connector->Clone()), + base::TimeDelta::FromSeconds(45)); + + // TODO(billorr): This should eventually be done on all platforms that support + // VR. + background_task_runner->PostDelayedTask( + FROM_HERE, base::BindOnce(&RecordVrStartupHistograms), + base::TimeDelta::FromSeconds(45)); #endif // defined(OS_WIN) display_count_ = display::Screen::GetScreen()->GetNumDisplays();
diff --git a/chrome/browser/net/firefox_proxy_settings.cc b/chrome/browser/net/firefox_proxy_settings.cc index 59f217d2..7847f14 100644 --- a/chrome/browser/net/firefox_proxy_settings.cc +++ b/chrome/browser/net/firefox_proxy_settings.cc
@@ -203,7 +203,7 @@ *config = net::ProxyConfig(); config->proxy_rules().type = - net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; if (!http_proxy().empty()) { config->proxy_rules().proxies_for_http.SetSingleProxyServer(
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index 1e12f15..d28c679 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -350,6 +350,8 @@ EXPECT_FALSE(all_options_notification.icon().IsEmpty()); EXPECT_EQ(kIconWidth, all_options_notification.icon().Width()); EXPECT_EQ(kIconHeight, all_options_notification.icon().Height()); + + // Small images (badges) are only supported on Android. EXPECT_TRUE(all_options_notification.small_image().IsEmpty()); EXPECT_THAT(all_options_notification.vibration_pattern(), @@ -1072,7 +1074,18 @@ EXPECT_TRUE(notification.never_timeout()); EXPECT_DOUBLE_EQ(621046800000., notification.timestamp().ToJsTime()); - // TODO(https://crbug.com/595685): Pass resources via mojo and test them here. +#if !defined(OS_MACOSX) + EXPECT_FALSE(notification.image().IsEmpty()); + EXPECT_EQ(kIconWidth, notification.image().Width()); + EXPECT_EQ(kIconHeight, notification.image().Height()); +#endif + + EXPECT_FALSE(notification.icon().IsEmpty()); + EXPECT_EQ(kIconWidth, notification.icon().Width()); + EXPECT_EQ(kIconHeight, notification.icon().Height()); + + // Small images (badges) are only supported on Android. + EXPECT_TRUE(notification.small_image().IsEmpty()); // Test that notifications with the same tag replace each other and have // identical ids.
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 7908682a..872e0ae 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -4094,8 +4094,7 @@ cus_ = g_browser_process->component_updater(); const auto config = component_updater::MakeChromeComponentUpdaterConfigurator( - base::CommandLine::ForCurrentProcess(), nullptr, - g_browser_process->local_state()); + base::CommandLine::ForCurrentProcess(), g_browser_process->local_state()); const auto urls = config->UpdateUrl(); ASSERT_TRUE(urls.size()); const GURL url = urls.front();
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc index ae9ed60..06bf157b 100644 --- a/chrome/browser/profiles/off_the_record_profile_io_data.cc +++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc
@@ -1,4 +1,3 @@ - // 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. @@ -34,6 +33,9 @@ #include "net/http/http_cache.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties_impl.h" +#include "net/network_error_logging/network_error_logging_service.h" +#include "net/reporting/reporting_policy.h" +#include "net/reporting/reporting_service.h" #include "net/ssl/channel_id_service.h" #include "net/ssl/default_channel_id_store.h" #include "net/url_request/url_request_context.h" @@ -278,6 +280,16 @@ std::move(protocol_handler_interceptor), context->network_delegate(), context->host_resolver()); context->SetJobFactory(std::move(top_job_factory)); + if (context->reporting_service()) { + context->SetReportingService(net::ReportingService::Create( + context->reporting_service()->GetPolicy(), context)); + } + if (context->network_error_logging_delegate()) { + context->SetNetworkErrorLoggingDelegate( + net::NetworkErrorLoggingService::Create()); + context->network_error_logging_delegate()->SetReportingService( + context->reporting_service()); + } return context; }
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc index a9afe2e2..7ce7a49 100644 --- a/chrome/browser/profiles/profile_browsertest.cc +++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -50,7 +50,6 @@ #include "extensions/common/value_builder.h" #include "net/base/net_errors.h" #include "net/dns/mock_host_resolver.h" -#include "net/reporting/reporting_feature.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" @@ -60,6 +59,7 @@ #include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_status.h" +#include "services/network/public/cpp/network_features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -560,6 +560,10 @@ EXPECT_NE(extension_context->reporting_service(), main_context->reporting_service()); } + if (extension_context->network_error_logging_delegate()) { + EXPECT_NE(extension_context->network_error_logging_delegate(), + main_context->network_error_logging_delegate()); + } // Check that the ChannelIDService in the HttpNetworkSession is the same as // the one directly on the URLRequestContext. @@ -583,7 +587,8 @@ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kReporting); + feature_list.InitWithFeatures( + {features::kReporting, features::kNetworkErrorLogging}, {}); MockProfileDelegate delegate; EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, true)); @@ -623,7 +628,8 @@ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kReporting); + feature_list.InitWithFeatures( + {features::kReporting, features::kNetworkErrorLogging}, {}); MockProfileDelegate delegate; EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, true));
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index 558f516..e3a3ff4 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -68,7 +68,7 @@ #include "net/http/http_network_session.h" #include "net/http/http_server_properties.h" #include "net/http/http_server_properties_manager.h" -#include "net/reporting/reporting_feature.h" +#include "net/network_error_logging/network_error_logging_service.h" #include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_service.h" #include "net/ssl/channel_id_service.h" @@ -479,8 +479,6 @@ SetUpJobFactoryDefaultsForBuilder( builder, std::move(request_interceptors), std::move(profile_params->protocol_handler_interceptor)); - - builder->set_reporting_policy(MaybeCreateReportingPolicy()); } void ProfileImplIOData::OnMainRequestContextCreated( @@ -578,7 +576,7 @@ // Build a new HttpNetworkSession that uses the new ChannelIDService. // TODO(mmenke): It's weird to combine state from - // main_request_context_storage() objects and the argumet to this method, + // main_request_context_storage() objects and the argument to this method, // |main_context|. Remove |main_context| as an argument, and just use // main_context() instead. net::HttpNetworkSession* network_session = @@ -615,7 +613,17 @@ context->host_resolver())); context->SetJobFactory(std::move(top_job_factory)); - context->SetReportingService(MaybeCreateReportingService(context)); + if (context->reporting_service()) { + context->SetReportingService(net::ReportingService::Create( + context->reporting_service()->GetPolicy(), context)); + } + + if (context->network_error_logging_delegate()) { + context->SetNetworkErrorLoggingDelegate( + net::NetworkErrorLoggingService::Create()); + context->network_error_logging_delegate()->SetReportingService( + context->reporting_service()); + } return context; } @@ -704,22 +712,3 @@ chrome_browser_net::Predictor* ProfileImplIOData::GetPredictor() { return predictor_.get(); } - -std::unique_ptr<net::ReportingService> -ProfileImplIOData::MaybeCreateReportingService( - net::URLRequestContext* url_request_context) const { - std::unique_ptr<net::ReportingPolicy> reporting_policy( - MaybeCreateReportingPolicy()); - if (!reporting_policy) - return std::unique_ptr<net::ReportingService>(); - - return net::ReportingService::Create(*reporting_policy, url_request_context); -} - -std::unique_ptr<net::ReportingPolicy> -ProfileImplIOData::MaybeCreateReportingPolicy() { - if (!base::FeatureList::IsEnabled(features::kReporting)) - return std::unique_ptr<net::ReportingPolicy>(); - - return base::MakeUnique<net::ReportingPolicy>(); -}
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 47f10c48..85f02a3c 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -105,6 +105,7 @@ #include "net/url_request/data_protocol_handler.h" #include "net/url_request/file_protocol_handler.h" #include "net/url_request/ftp_protocol_handler.h" +#include "net/url_request/network_error_logging_delegate.h" #include "net/url_request/report_sender.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" @@ -628,8 +629,16 @@ set_reporting_service(reporting_service_.get()); } +void ProfileIOData::AppRequestContext::SetNetworkErrorLoggingDelegate( + std::unique_ptr<net::NetworkErrorLoggingDelegate> + network_error_logging_delegate) { + network_error_logging_delegate_ = std::move(network_error_logging_delegate); + set_network_error_logging_delegate(network_error_logging_delegate_.get()); +} + ProfileIOData::AppRequestContext::~AppRequestContext() { - SetReportingService(std::unique_ptr<net::ReportingService>()); + SetNetworkErrorLoggingDelegate(nullptr); + SetReportingService(nullptr); AssertNoURLRequests(); }
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index cdd85d6..934d1db 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h
@@ -81,6 +81,7 @@ class ClientCertStore; class CookieStore; class HttpTransactionFactory; +class NetworkErrorLoggingDelegate; class ReportingService; class ReportSender; class SSLConfigService; @@ -300,6 +301,9 @@ void SetJobFactory(std::unique_ptr<net::URLRequestJobFactory> job_factory); void SetReportingService( std::unique_ptr<net::ReportingService> reporting_service); + void SetNetworkErrorLoggingDelegate( + std::unique_ptr<net::NetworkErrorLoggingDelegate> + network_error_logging_delegate); private: ~AppRequestContext() override; @@ -310,6 +314,8 @@ std::unique_ptr<net::HttpTransactionFactory> http_factory_; std::unique_ptr<net::URLRequestJobFactory> job_factory_; std::unique_ptr<net::ReportingService> reporting_service_; + std::unique_ptr<net::NetworkErrorLoggingDelegate> + network_error_logging_delegate_; }; // Created on the UI thread, read on the IO thread during ProfileIOData lazy
diff --git a/chrome/browser/profiling_host/memlog_browsertest.cc b/chrome/browser/profiling_host/memlog_browsertest.cc index 3cce7eee..623ea3f 100644 --- a/chrome/browser/profiling_host/memlog_browsertest.cc +++ b/chrome/browser/profiling_host/memlog_browsertest.cc
@@ -106,8 +106,9 @@ } } - // There's no way to tell when profiling has started for a renderer, so it - // must be started as soon as chrome has started. + // Non-browser processes must be profiled with a command line flag, since + // otherwise, profiling will start after the relevant processes have been + // created, thus that process will be not be profiled. std::vector<ProfilingProcessHost::Mode> command_line_start_modes; command_line_start_modes.push_back(ProfilingProcessHost::Mode::kAll); command_line_start_modes.push_back(ProfilingProcessHost::Mode::kAllRenderers);
diff --git a/chrome/browser/profiling_host/profiling_test_driver.cc b/chrome/browser/profiling_host/profiling_test_driver.cc index d51e546..730141c 100644 --- a/chrome/browser/profiling_host/profiling_test_driver.cc +++ b/chrome/browser/profiling_host/profiling_test_driver.cc
@@ -18,6 +18,7 @@ #include "build/build_config.h" #include "chrome/common/profiling/memlog_allocator_shim.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/tracing_controller.h" #include "content/public/common/service_manager_connection.h" @@ -43,6 +44,24 @@ constexpr int kPartitionAllocCount = 107; static const char* kPartitionAllocTypeName = "kPartitionAllocTypeName"; +// Whether at least 1 renderer exists, and all renderers are being profiled. +bool RenderersAreBeingProfiled( + const std::vector<base::ProcessId>& profiled_pids) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + size_t renderer_count = 0; + for (auto iter = content::RenderProcessHost::AllHostsIterator(); + !iter.IsAtEnd(); iter.Advance()) { + base::ProcessId pid = base::GetProcId(iter.GetCurrentValue()->GetHandle()); + if (std::find(profiled_pids.begin(), profiled_pids.end(), pid) == + profiled_pids.end()) { + return false; + } + ++renderer_count; + } + + return renderer_count != 0; +} + // On success, populates |pid|. int NumProcessesWithName(base::Value* dump_json, std::string name, int* pid) { int num_processes = 0; @@ -325,7 +344,10 @@ if (running_on_ui_thread_) { if (!CheckOrStartProfiling()) return false; - MakeTestAllocations(); + if (ShouldProfileRenderer()) + WaitForProfilingToStartForAllRenderersUIThread(); + if (ShouldProfileBrowser()) + MakeTestAllocations(); CollectResults(true); } else { content::BrowserThread::PostTask( @@ -336,10 +358,21 @@ wait_for_ui_thread_.Wait(); if (!initialization_success_) return false; - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&ProfilingTestDriver::MakeTestAllocations, - base::Unretained(this))); + if (ShouldProfileRenderer()) { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind( + &ProfilingTestDriver:: + WaitForProfilingToStartForAllRenderersUIThreadAndSignal, + base::Unretained(this))); + wait_for_ui_thread_.Wait(); + } + if (ShouldProfileBrowser()) { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&ProfilingTestDriver::MakeTestAllocations, + base::Unretained(this))); + } content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&ProfilingTestDriver::CollectResults, base::Unretained(this), @@ -580,8 +613,7 @@ base::ProcessId renderer_pid = static_cast<base::ProcessId>(pid); base::Value* heaps_v2 = FindHeapsV2(renderer_pid, dump_json); - if (options_.mode == ProfilingProcessHost::Mode::kAll || - options_.mode == ProfilingProcessHost::Mode::kAllRenderers) { + if (ShouldProfileRenderer()) { if (!heaps_v2) { LOG(ERROR) << "Failed to find heaps v2 for renderer"; return false; @@ -620,8 +652,53 @@ options_.mode == ProfilingProcessHost::Mode::kMinimal; } +bool ProfilingTestDriver::ShouldProfileRenderer() { + return options_.mode == ProfilingProcessHost::Mode::kAll || + options_.mode == ProfilingProcessHost::Mode::kAllRenderers; +} + bool ProfilingTestDriver::HasPseudoFrames() { return options_.stack_mode != profiling::mojom::StackMode::NATIVE; } +void ProfilingTestDriver::WaitForProfilingToStartForAllRenderersUIThread() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + while (true) { + std::vector<base::ProcessId> profiled_pids; + base::RunLoop run_loop; + auto callback = base::BindOnce( + [](std::vector<base::ProcessId>* results, base::OnceClosure finished, + std::vector<base::ProcessId> pids) { + results->swap(pids); + std::move(finished).Run(); + }, + &profiled_pids, run_loop.QuitClosure()); + profiling::ProfilingProcessHost::GetInstance()->GetProfiledPids( + std::move(callback)); + run_loop.Run(); + + if (RenderersAreBeingProfiled(profiled_pids)) + break; + } +} + +void ProfilingTestDriver:: + WaitForProfilingToStartForAllRenderersUIThreadAndSignal() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + profiling::ProfilingProcessHost::GetInstance()->GetProfiledPids( + base::BindOnce(&ProfilingTestDriver:: + WaitForProfilingToStartForAllRenderersUIThreadCallback, + base::Unretained(this))); +} + +void ProfilingTestDriver:: + WaitForProfilingToStartForAllRenderersUIThreadCallback( + std::vector<base::ProcessId> results) { + if (RenderersAreBeingProfiled(results)) { + wait_for_ui_thread_.Signal(); + return; + } + WaitForProfilingToStartForAllRenderersUIThreadAndSignal(); +} + } // namespace profiling
diff --git a/chrome/browser/profiling_host/profiling_test_driver.h b/chrome/browser/profiling_host/profiling_test_driver.h index 88478e6..7a082e2a 100644 --- a/chrome/browser/profiling_host/profiling_test_driver.h +++ b/chrome/browser/profiling_host/profiling_test_driver.h
@@ -92,8 +92,17 @@ bool ValidateRendererAllocations(base::Value* dump_json); bool ShouldProfileBrowser(); + bool ShouldProfileRenderer(); bool HasPseudoFrames(); + void WaitForProfilingToStartForAllRenderersUIThread(); + + // Android does not support nested RunLoops. Instead, it signals + // |wait_for_ui_thread_| when finished. + void WaitForProfilingToStartForAllRenderersUIThreadAndSignal(); + void WaitForProfilingToStartForAllRenderersUIThreadCallback( + std::vector<base::ProcessId> results); + Options options_; // Allocations made by this class. Intentionally leaked, since deallocating
diff --git a/chrome/browser/resources/extensions/extensions.js b/chrome/browser/resources/extensions/extensions.js index 663f8382b..4f9d1b2 100644 --- a/chrome/browser/resources/extensions/extensions.js +++ b/chrome/browser/resources/extensions/extensions.js
@@ -19,10 +19,6 @@ // <include src="chromeos/kiosk_apps.js"> // </if> -// Used for observing function of the backend datasource for this page by -// tests. -var webuiResponded = false; - cr.define('extensions', function() { var ExtensionList = extensions.ExtensionList; @@ -185,7 +181,6 @@ // don't need to display the interstitial spinner. if (!this.hasLoaded_) this.setLoading_(true); - webuiResponded = true; /** @const */ var supervised = profileInfo.isSupervised;
diff --git a/chrome/browser/resources/feedback/js/feedback.js b/chrome/browser/resources/feedback/js/feedback.js index a4a3768..909a5e5 100644 --- a/chrome/browser/resources/feedback/js/feedback.js +++ b/chrome/browser/resources/feedback/js/feedback.js
@@ -321,7 +321,8 @@ } $('description-text').textContent = feedbackInfo.description; - $('description-text').placeholder = feedbackInfo.descriptionPlaceholder; + if (feedbackInfo.descriptionPlaceholder) + $('description-text').placeholder = feedbackInfo.descriptionPlaceholder; if (feedbackInfo.pageUrl) $('page-url-text').value = feedbackInfo.pageUrl;
diff --git a/chrome/browser/resources/identity_internals.html b/chrome/browser/resources/identity_internals.html index fcfcc43..3be4478 100644 --- a/chrome/browser/resources/identity_internals.html +++ b/chrome/browser/resources/identity_internals.html
@@ -1,8 +1,8 @@ <!doctype html> -<html i18n-values="dir:textdirection;lang:language"> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> - <title i18n-content="tokenCacheHeader"></title> + <title>$i18n{tokenCacheHeader}</title> <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> <link rel="stylesheet" href="identity_internals.css"> <script src="chrome://resources/js/cr.js"></script> @@ -13,7 +13,7 @@ <script src="identity_internals.js"></script> </head> <body> - <h2 class="header" i18n-content="tokenCacheHeader"></h2> + <h2 class="header">$i18n{tokenCacheHeader}</h2> <div id="token-list"></div> <script src="chrome://resources/js/i18n_template.js"></script> </body>
diff --git a/chrome/browser/resources/md_downloads/compiled_resources2.gyp b/chrome/browser/resources/md_downloads/compiled_resources2.gyp index b9e2ca90..4adfce2 100644 --- a/chrome/browser/resources/md_downloads/compiled_resources2.gyp +++ b/chrome/browser/resources/md_downloads/compiled_resources2.gyp
@@ -75,7 +75,6 @@ '<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu', '<(DEPTH)/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp:cr_toolbar', '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-announcer/compiled_resources2.gyp:iron-a11y-announcer-extracted', - '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-menu/compiled_resources2.gyp:paper-menu-extracted', 'browser_proxy', 'search_service', ],
diff --git a/chrome/browser/resources/md_extensions/compiled_resources2.gyp b/chrome/browser/resources/md_extensions/compiled_resources2.gyp index 7485079..3cf31dd 100644 --- a/chrome/browser/resources/md_extensions/compiled_resources2.gyp +++ b/chrome/browser/resources/md_extensions/compiled_resources2.gyp
@@ -50,7 +50,6 @@ { 'target_name': 'error_page', 'dependencies': [ - '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-menu/compiled_resources2.gyp:paper-menu-extracted', '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_outline_manager',
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html index ba7ede3..e3afc52 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -270,7 +270,9 @@ </template> </div> </iron-collapse> + </template> + <template is="dom-if" if="[[hasProxySection_(networkProperties)]]"> <!-- Proxy toggle --> <div class="settings-box" actionable on-tap="toggleProxyExpanded_"> <div class="start">$i18n{networkSectionProxy}</div>
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js index 7f96c57..2b08e72 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -1067,6 +1067,20 @@ * @return {boolean} * @private */ + hasProxySection_: function(networkProperties) { + if (networkProperties.Type == CrOnc.Type.TETHER) { + // Proxy settings apply to the underlying WiFi network, not the Tether + // network. + return false; + } + return this.isRememberedOrConnected_(networkProperties); + }, + + /** + * @param {!CrOnc.NetworkProperties} networkProperties + * @return {boolean} + * @private + */ showCellularChooseNetwork_: function(networkProperties) { return networkProperties.Type == CrOnc.Type.CELLULAR && !!this.get('Cellular.SupportNetworkScan', this.networkProperties);
diff --git a/chrome/browser/resources/settings/people_page/change_picture.js b/chrome/browser/resources/settings/people_page/change_picture.js index 48eaa44..eeca3287 100644 --- a/chrome/browser/resources/settings/people_page/change_picture.js +++ b/chrome/browser/resources/settings/people_page/change_picture.js
@@ -81,6 +81,9 @@ /** @private {?CrPictureListElement} */ pictureList_: null, + /** @private {boolean} */ + oldImagePending_: false, + /** @override */ ready: function() { this.browserProxy_ = settings.ChangePictureBrowserProxyImpl.getInstance(); @@ -144,6 +147,7 @@ * @private */ receiveOldImage_: function(imageInfo) { + this.oldImagePending_ = false; this.pictureList_.setOldImageUrl(imageInfo.url, imageInfo.index); }, @@ -216,6 +220,7 @@ * @private */ onPhotoTaken_: function(event) { + this.oldImagePending_ = true; this.browserProxy_.photoTaken(event.detail.photoDataUrl); this.pictureList_.setOldImageUrl(event.detail.photoDataUrl); this.pictureList_.setFocus(); @@ -235,6 +240,9 @@ /** @private */ onDiscardImage_: function() { + // Prevent image from being discarded if old image is pending. + if (this.oldImagePending_) + return; this.pictureList_.setOldImageUrl(CrPicture.kDefaultImageUrl); // Revert to profile image as we don't know what last used default image is. this.browserProxy_.selectProfileImage();
diff --git a/chrome/browser/resources/settings/people_page/change_picture_browser_proxy.js b/chrome/browser/resources/settings/people_page/change_picture_browser_proxy.js index 7295e66f..3cd333e 100644 --- a/chrome/browser/resources/settings/people_page/change_picture_browser_proxy.js +++ b/chrome/browser/resources/settings/people_page/change_picture_browser_proxy.js
@@ -51,8 +51,9 @@ selectProfileImage() {} /** - * Provides the taken photo as a data URL to the C++. No response is - * expected. + * Provides the taken photo as a data URL to the C++ and sets the user + * image to the 'old' image. As a response, the C++ sends the + * 'old-image-changed' WebUIListener event. * @param {string} photoDataUrl */ photoTaken(photoDataUrl) {}
diff --git a/chrome/browser/resources/signin/signin_error/signin_error.html b/chrome/browser/resources/signin/signin_error/signin_error.html index a3d578d..2e050a8 100644 --- a/chrome/browser/resources/signin/signin_error/signin_error.html +++ b/chrome/browser/resources/signin/signin_error/signin_error.html
@@ -1,5 +1,5 @@ <!doctype html> -<html i18n-values="dir:textdirection;lang:language"> +<html i18n-values="dir:textdirection;lang:language" dir="$i18n{textdirection}"> <head> <meta charset="utf-8"> <link rel="import" href="chrome://resources/html/polymer.html"> @@ -26,6 +26,41 @@ -webkit-margin-start: 8px; } + #normal-error-message p:empty, + #normal-error-message a:empty { + display: none; + } + + #profile-blocking-error-message { + margin-top: 30px; + } + + #profile-blocking-error-message p { + -webkit-padding-start: 35px; + background-position: 0 3px; + background-repeat: no-repeat; + background-size: 20px; + line-height: 18px; + } + + html[dir=rtl] #profile-blocking-error-message p { + background-position: right 3px; + } + + #profile-blocking-error-message p:empty { + display: none; + } + + #profile-blocking-error-message p:nth-child(1) { + background-image: + url(../../../../../ui/webui/resources/images/business.svg); + } + + #profile-blocking-error-message p:nth-child(2) { + background-image: + url(../../../../../ui/webui/resources/images/info.svg); + } + <if expr="is_macosx or is_linux"> #closeButton { -webkit-margin-end: 8px; @@ -37,10 +72,15 @@ <body> <div class="container"> <div class="top-title-bar">$i18n{signinErrorTitle}</div> - <div class="details"> + <div id="normal-error-message" class="details"> <p>$i18nRaw{signinErrorMessage}</p> <a id="learnMoreLink" href="#">$i18nRaw{signinErrorLearnMore}</a> </div> + <div id="profile-blocking-error-message" class="details"> + <p>$i18n{profileBlockedMessage}</p> + <p>$i18n{profileBlockedAddPersonSuggestion}</p> + <p>$i18n{profileBlockedRemoveProfileSuggestion}</p> + </div> <div class="action-container"> <paper-button class="primary-action" id="switchButton"> $i18n{signinErrorSwitchLabel}
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc index 53d02404..a267119 100644 --- a/chrome/browser/safe_browsing/safe_browsing_database.cc +++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -18,7 +18,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" #include "base/process/process_handle.h" -#include "base/process/process_metrics.h" +#include "base/process/process_metrics_iocounters.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h"
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc index dbb67ed..47c881d 100644 --- a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc +++ b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
@@ -9,6 +9,7 @@ #include <utility> #include "base/json/json_writer.h" +#include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/extensions/component_loader.h" @@ -32,6 +33,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" #include "net/base/network_change_notifier.h" +#include "ui/base/l10n/l10n_util.h" using extensions::EventRouter; using extensions::Extension; @@ -65,6 +67,16 @@ constants::kErrorMissingPauseOrResume); } +const std::vector<extensions::TtsVoice>* GetVoicesInternal( + content::BrowserContext* context, + const extensions::Extension* extension) { + Profile* profile = Profile::FromBrowserContext(context); + const std::vector<extensions::TtsVoice>* voices = + TtsEngineExtensionObserver::GetInstance(profile)->GetRuntimeVoices( + extension->id()); + return voices ? voices : extensions::TtsVoices::GetTtsVoices(extension); +} + } // namespace TtsExtensionEngine* TtsExtensionEngine::GetInstance() { @@ -94,7 +106,7 @@ } const std::vector<extensions::TtsVoice>* tts_voices = - extensions::TtsVoice::GetTtsVoices(extension); + GetVoicesInternal(profile, extension); if (!tts_voices) continue; @@ -260,6 +272,69 @@ } ExtensionFunction::ResponseAction +ExtensionTtsEngineUpdateVoicesFunction::Run() { + base::ListValue* voices_data = nullptr; + EXTENSION_FUNCTION_VALIDATE(args_->GetList(0, &voices_data)); + auto tts_voices = std::make_unique<extensions::TtsVoices>(); + const char* error = nullptr; + for (size_t i = 0; i < voices_data->GetSize(); i++) { + extensions::TtsVoice voice; + base::DictionaryValue* voice_data = nullptr; + voices_data->GetDictionary(i, &voice_data); + + // Note partial validation of these attributes occurs based on tts engine's + // json schema (e.g. for data type matching). The missing checks follow + // similar checks in manifest parsing. + if (voice_data->HasKey(constants::kVoiceNameKey)) + voice_data->GetString(constants::kVoiceNameKey, &voice.voice_name); + if (voice_data->HasKey(constants::kLangKey)) { + voice_data->GetString(constants::kLangKey, &voice.lang); + if (!l10n_util::IsValidLocaleSyntax(voice.lang)) { + error = constants::kErrorInvalidLang; + continue; + } + } + if (voice_data->HasKey(constants::kGenderKey)) + voice_data->GetString(constants::kGenderKey, &voice.gender); + if (voice_data->HasKey(constants::kRemoteKey)) + voice_data->GetBoolean(constants::kRemoteKey, &voice.remote); + if (voice_data->HasKey(constants::kExtensionIdKey)) { + // Allow this for clients who might have used |chrome.tts.getVoices| to + // update existing voices. However, trying to update the voice of another + // extension should trigger an error. + std::string extension_id; + voice_data->GetString(constants::kExtensionIdKey, &extension_id); + if (extension()->id() != extension_id) { + error = constants::kErrorExtensionIdMismatch; + continue; + } + } + base::ListValue* event_types = nullptr; + if (voice_data->HasKey(constants::kEventTypesKey)) + voice_data->GetList(constants::kEventTypesKey, &event_types); + + if (event_types) { + for (size_t j = 0; j < event_types->GetSize(); j++) { + std::string event_type; + event_types->GetString(j, &event_type); + voice.event_types.insert(event_type); + } + } + + tts_voices->voices.push_back(voice); + } + + Profile* profile = Profile::FromBrowserContext(browser_context()); + TtsEngineExtensionObserver::GetInstance(profile)->SetRuntimeVoices( + std::move(tts_voices), extension()->id()); + + if (error) + return RespondNow(Error(error)); + + return RespondNow(NoArguments()); +} + +ExtensionFunction::ResponseAction ExtensionTtsEngineSendTtsEventFunction::Run() { int utterance_id = 0; EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &utterance_id)); @@ -279,8 +354,9 @@ // Make sure the extension has included this event type in its manifest. bool event_type_allowed = false; + Profile* profile = Profile::FromBrowserContext(browser_context()); const std::vector<extensions::TtsVoice>* tts_voices = - extensions::TtsVoice::GetTtsVoices(extension()); + GetVoicesInternal(profile, extension()); if (!tts_voices) return RespondNow(Error(constants::kErrorUndeclaredEventType));
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api.h b/chrome/browser/speech/extension_api/tts_engine_extension_api.h index eac6054f..5e60d5c 100644 --- a/chrome/browser/speech/extension_api/tts_engine_extension_api.h +++ b/chrome/browser/speech/extension_api/tts_engine_extension_api.h
@@ -39,6 +39,17 @@ bool LoadBuiltInTtsExtension( content::BrowserContext* browser_context) override; }; + +// Function that allows tts engines to update its list of supported voices at +// runtime. +class ExtensionTtsEngineUpdateVoicesFunction + : public UIThreadExtensionFunction { + private: + ~ExtensionTtsEngineUpdateVoicesFunction() override {} + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("ttsEngine.updateVoices", TTSENGINE_UPDATEVOICES) +}; + // Hidden/internal extension function used to allow TTS engine extensions // to send events back to the client that's calling tts.speak(). class ExtensionTtsEngineSendTtsEventFunction
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_observer.cc b/chrome/browser/speech/extension_api/tts_engine_extension_observer.cc index 22d5a474..2f2a027 100644 --- a/chrome/browser/speech/extension_api/tts_engine_extension_observer.cc +++ b/chrome/browser/speech/extension_api/tts_engine_extension_observer.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h" #include "chrome/browser/speech/tts_controller.h" +#include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/core/keyed_service.h" @@ -88,6 +89,22 @@ return previously_loaded; } +const std::vector<extensions::TtsVoice>* +TtsEngineExtensionObserver::GetRuntimeVoices(const std::string extension_id) { + auto it = extension_id_to_runtime_voices_.find(extension_id); + if (it == extension_id_to_runtime_voices_.end()) + return nullptr; + + return &it->second->voices; +} + +void TtsEngineExtensionObserver::SetRuntimeVoices( + std::unique_ptr<extensions::TtsVoices> tts_voices, + const std::string extension_id) { + extension_id_to_runtime_voices_[extension_id] = std::move(tts_voices); + TtsController::GetInstance()->VoicesChanged(); +} + void TtsEngineExtensionObserver::Shutdown() { extensions::EventRouter::Get(profile_)->UnregisterObserver(this); } @@ -120,9 +137,9 @@ content::BrowserContext* browser_context, const extensions::Extension* extension, extensions::UnloadedExtensionReason reason) { - if (engine_extension_ids_.find(extension->id()) != - engine_extension_ids_.end()) { - engine_extension_ids_.erase(extension->id()); + size_t erase_count = 0; + erase_count += engine_extension_ids_.erase(extension->id()); + erase_count += extension_id_to_runtime_voices_.erase(extension->id()); + if (erase_count >= 0) TtsController::GetInstance()->VoicesChanged(); - } }
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_observer.h b/chrome/browser/speech/extension_api/tts_engine_extension_observer.h index 5e1f79c..6473803 100644 --- a/chrome/browser/speech/extension_api/tts_engine_extension_observer.h +++ b/chrome/browser/speech/extension_api/tts_engine_extension_observer.h
@@ -14,6 +14,11 @@ class Profile; +namespace extensions { +struct TtsVoice; +struct TtsVoices; +}; // namespace extensions + // Profile-keyed class that observes the extension registry to determine load of // extension-based tts engines. class TtsEngineExtensionObserver @@ -27,6 +32,15 @@ // as loaded immediately if |update| is set to true. bool SawExtensionLoad(const std::string& extension_id, bool update); + // Gets voices for |extension_id| updated through TtsEngine.updateVoices. + const std::vector<extensions::TtsVoice>* GetRuntimeVoices( + const std::string extension_id); + + // Called to update the voices list for the given extension. This overrides + // voices declared in the extension manifest. + void SetRuntimeVoices(std::unique_ptr<extensions::TtsVoices> tts_voices, + const std::string extension_id); + // Implementation of KeyedService. void Shutdown() override; @@ -52,6 +66,9 @@ std::set<std::string> engine_extension_ids_; + std::map<std::string, std::unique_ptr<extensions::TtsVoices>> + extension_id_to_runtime_voices_; + friend class TtsEngineExtensionObserverFactory; DISALLOW_COPY_AND_ASSIGN(TtsEngineExtensionObserver);
diff --git a/chrome/browser/speech/extension_api/tts_extension_api.cc b/chrome/browser/speech/extension_api/tts_extension_api.cc index 4ea4334a..c46bdcf 100644 --- a/chrome/browser/speech/extension_api/tts_extension_api.cc +++ b/chrome/browser/speech/extension_api/tts_extension_api.cc
@@ -351,6 +351,7 @@ TtsAPI::TtsAPI(content::BrowserContext* context) { ExtensionFunctionRegistry* registry = ExtensionFunctionRegistry::GetInstance(); + registry->RegisterFunction<ExtensionTtsEngineUpdateVoicesFunction>(); registry->RegisterFunction<ExtensionTtsEngineSendTtsEventFunction>(); registry->RegisterFunction<TtsGetVoicesFunction>(); registry->RegisterFunction<TtsIsSpeakingFunction>();
diff --git a/chrome/browser/speech/extension_api/tts_extension_api_constants.cc b/chrome/browser/speech/extension_api/tts_extension_api_constants.cc index f1853dc..43bc556 100644 --- a/chrome/browser/speech/extension_api/tts_extension_api_constants.cc +++ b/chrome/browser/speech/extension_api/tts_extension_api_constants.cc
@@ -39,6 +39,7 @@ const char kEventTypeStart[] = "start"; const char kEventTypeWord[] = "word"; +const char kErrorExtensionIdMismatch[] = "Extension id mismatch."; const char kErrorInvalidGender[] = "Invalid gender."; const char kErrorInvalidLang[] = "Invalid lang."; const char kErrorInvalidPitch[] = "Invalid pitch.";
diff --git a/chrome/browser/speech/extension_api/tts_extension_api_constants.h b/chrome/browser/speech/extension_api/tts_extension_api_constants.h index bec1749..32075d9 100644 --- a/chrome/browser/speech/extension_api/tts_extension_api_constants.h +++ b/chrome/browser/speech/extension_api/tts_extension_api_constants.h
@@ -44,6 +44,7 @@ extern const char kEventTypeStart[]; extern const char kEventTypeWord[]; +extern const char kErrorExtensionIdMismatch[]; extern const char kErrorInvalidGender[]; extern const char kErrorInvalidLang[]; extern const char kErrorInvalidPitch[];
diff --git a/chrome/browser/speech/extension_api/tts_extension_apitest.cc b/chrome/browser/speech/extension_api/tts_extension_apitest.cc index 9911653e..3951d02e 100644 --- a/chrome/browser/speech/extension_api/tts_extension_apitest.cc +++ b/chrome/browser/speech/extension_api/tts_extension_apitest.cc
@@ -465,4 +465,8 @@ ASSERT_TRUE(RunExtensionTest("tts_engine/engine_api")) << message_; } +IN_PROC_BROWSER_TEST_F(TtsApiTest, UpdateVoicesApi) { + ASSERT_TRUE(RunExtensionTest("tts_engine/update_voices_api")) << message_; +} + } // namespace extensions
diff --git a/chrome/browser/ui/app_list/app_list_model_updater.h b/chrome/browser/ui/app_list/app_list_model_updater.h index ce504f32..5fdd64a8 100644 --- a/chrome/browser/ui/app_list/app_list_model_updater.h +++ b/chrome/browser/ui/app_list/app_list_model_updater.h
@@ -81,6 +81,7 @@ virtual bool FindItemIndexForTest(const std::string& id, size_t* index) = 0; virtual app_list::AppListViewState StateFullscreen() = 0; virtual std::map<std::string, size_t> GetIdToAppListIndexMap() = 0; + virtual size_t BadgedItemCount() = 0; // For SearchModel: virtual bool TabletMode() = 0; virtual bool SearchEngineIsGoogle() = 0;
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index 8e1375cfc..1b4b36e 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -14,6 +14,7 @@ #include "ash/app_list/model/search/search_model.h" #include "ash/public/interfaces/constants.mojom.h" #include "base/command_line.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "build/build_config.h" @@ -240,6 +241,12 @@ } } +void AppListViewDelegate::ViewShown() { + base::RecordAction(base::UserMetricsAction("Launcher_Show")); + base::UmaHistogramSparse("Apps.AppListBadgedAppsCount", + model_updater_->BadgedItemCount()); +} + void AppListViewDelegate::Dismiss() { controller_->DismissView(); }
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h index c1c04e7..72f4871 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.h +++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -68,6 +68,7 @@ int action_index, int event_flags) override; void ViewInitialized() override; + void ViewShown() override; void Dismiss() override; void ViewClosing() override; views::View* CreateStartPageWebView(const gfx::Size& size) override;
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc index ae66198..ea2febf 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -201,6 +201,10 @@ return id_to_app_list_index; } +size_t ChromeAppListModelUpdater::BadgedItemCount() { + return model_->top_level_item_list()->BadgedItemCount(); +} + app_list::AppListFolderItem* ChromeAppListModelUpdater::ResolveOemFolderPosition( const std::string& oem_folder_id,
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h index d555f9db..e9483b09 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
@@ -77,6 +77,7 @@ app_list::AppListViewState StateFullscreen() override; bool SearchEngineIsGoogle() override; std::map<std::string, size_t> GetIdToAppListIndexMap() override; + size_t BadgedItemCount() override; ui::MenuModel* GetContextMenuModel(const std::string& id); // Methods for AppListSyncableService:
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc index c8ad781..6f07a49 100644 --- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc +++ b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
@@ -104,6 +104,10 @@ return id_to_app_list_index; } +size_t FakeAppListModelUpdater::BadgedItemCount() { + return 0u; +} + bool FakeAppListModelUpdater::SearchEngineIsGoogle() { return search_engine_is_google_; }
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h index fbfdb36..67ea082 100644 --- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h +++ b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h
@@ -45,6 +45,7 @@ bool FindItemIndexForTest(const std::string& id, size_t* index) override; app_list::AppListViewState StateFullscreen() override; std::map<std::string, size_t> GetIdToAppListIndexMap() override; + size_t BadgedItemCount() override; // For SearchModel: bool TabletMode() override; bool SearchEngineIsGoogle() override;
diff --git a/chrome/browser/ui/ash/auto_connect_notifier_unittest.cc b/chrome/browser/ui/ash/auto_connect_notifier_unittest.cc index c7a228e8..e5ab553 100644 --- a/chrome/browser/ui/ash/auto_connect_notifier_unittest.cc +++ b/chrome/browser/ui/ash/auto_connect_notifier_unittest.cc
@@ -61,7 +61,8 @@ const std::string& service_path, const base::Closure& success_callback, const chromeos::network_handler::ErrorCallback& error_callback, - bool check_error_state) override {} + bool check_error_state, + chromeos::ConnectCallbackMode mode) override {} bool HasConnectingNetwork(const std::string& service_path) override { return false;
diff --git a/chrome/browser/ui/webui/signin/login_ui_service.cc b/chrome/browser/ui/webui/signin/login_ui_service.cc index 9cc14d3..1e21d92 100644 --- a/chrome/browser/ui/webui/signin/login_ui_service.cc +++ b/chrome/browser/ui/webui/signin/login_ui_service.cc
@@ -71,6 +71,7 @@ // ChromeOS doesn't have the avatar bubble so it never calls this function. NOTREACHED(); #else + is_displaying_profile_blocking_error_message_ = false; last_login_result_ = error_message; last_login_error_email_ = email; if (!error_message.empty()) { @@ -88,6 +89,16 @@ #endif } +void LoginUIService::SetProfileBlockingErrorMessage() { + last_login_result_ = base::string16(); + last_login_error_email_ = base::string16(); + is_displaying_profile_blocking_error_message_ = true; +} + +bool LoginUIService::IsDisplayingProfileBlockedErrorMessage() const { + return is_displaying_profile_blocking_error_message_; +} + const base::string16& LoginUIService::GetLastLoginResult() const { return last_login_result_; }
diff --git a/chrome/browser/ui/webui/signin/login_ui_service.h b/chrome/browser/ui/webui/signin/login_ui_service.h index c3cc5ee..1458430 100644 --- a/chrome/browser/ui/webui/signin/login_ui_service.h +++ b/chrome/browser/ui/webui/signin/login_ui_service.h
@@ -86,6 +86,13 @@ const base::string16& error_message, const base::string16& email); + // Set the profile blocking modal error dialog message. + virtual void SetProfileBlockingErrorMessage(); + + // Gets whether the Modal Signin Error dialog should display profile blocking + // error message. + bool IsDisplayingProfileBlockedErrorMessage() const; + // Gets the last login result set through |DisplayLoginResult|. const base::string16& GetLastLoginResult() const; @@ -105,6 +112,7 @@ base::string16 last_login_result_; base::string16 last_login_error_email_; + bool is_displaying_profile_blocking_error_message_ = false; DISALLOW_COPY_AND_ASSIGN(LoginUIService); };
diff --git a/chrome/browser/ui/webui/signin/login_ui_service_unittest.cc b/chrome/browser/ui/webui/signin/login_ui_service_unittest.cc index ffe14f05..d77bb0d9 100644 --- a/chrome/browser/ui/webui/signin/login_ui_service_unittest.cc +++ b/chrome/browser/ui/webui/signin/login_ui_service_unittest.cc
@@ -47,3 +47,13 @@ service.LoginUIClosed(&other_ui); EXPECT_EQ(nullptr, service.current_login_ui()); } + +TEST(LoginUIServiceTest, SetProfileBlockingErrorMessage) { + LoginUIService service(nullptr); + + service.SetProfileBlockingErrorMessage(); + + EXPECT_EQ(base::string16(), service.GetLastLoginResult()); + EXPECT_EQ(base::string16(), service.GetLastLoginErrorEmail()); + EXPECT_TRUE(service.IsDisplayingProfileBlockedErrorMessage()); +}
diff --git a/chrome/browser/ui/webui/signin/signin_error_ui.cc b/chrome/browser/ui/webui/signin/signin_error_ui.cc index abb8a71..e127aefb 100644 --- a/chrome/browser/ui/webui/signin/signin_error_ui.cc +++ b/chrome/browser/ui/webui/signin/signin_error_ui.cc
@@ -72,7 +72,12 @@ const base::string16 last_login_result( login_ui_service->GetLastLoginResult()); const base::string16 email = login_ui_service->GetLastLoginErrorEmail(); - if (email.empty()) { + const bool is_profile_blocked = + login_ui_service->IsDisplayingProfileBlockedErrorMessage(); + if (is_profile_blocked) { + source->AddLocalizedString("signinErrorTitle", + IDS_OLD_PROFILES_DISABLED_TITLE); + } else if (email.empty()) { source->AddLocalizedString("signinErrorTitle", IDS_SIGNIN_ERROR_TITLE); } else { source->AddString( @@ -80,12 +85,24 @@ l10n_util::GetStringFUTF16(IDS_SIGNIN_ERROR_EMAIL_TITLE, email)); } + source->AddString("signinErrorMessage", base::string16()); + source->AddString("profileBlockedMessage", base::string16()); + source->AddString("profileBlockedAddPersonSuggestion", base::string16()); + source->AddString("profileBlockedRemoveProfileSuggestion", base::string16()); + // Tweak the dialog UI depending on whether the signin error is // username-in-use error and the error UI is shown with a browser window. base::string16 existing_name; - if (!is_system_profile && - last_login_result.compare( - l10n_util::GetStringUTF16(IDS_SYNC_USER_NAME_IN_USE_ERROR)) == 0) { + if (is_profile_blocked) { + source->AddLocalizedString("profileBlockedMessage", + IDS_OLD_PROFILES_DISABLED_MESSAGE); + source->AddLocalizedString("profileBlockedAddPersonSuggestion", + IDS_OLD_PROFILES_DISABLED_ADD_PERSON_SUGGESTION); + source->AddLocalizedString("profileBlockedRemoveProfileSuggestion", + IDS_OLD_PROFILES_DISABLED_REMOVED_OLD_PROFILE); + } else if (!is_system_profile && + last_login_result.compare(l10n_util::GetStringUTF16( + IDS_SYNC_USER_NAME_IN_USE_ERROR)) == 0) { ProfileManager* profile_manager = g_browser_process->profile_manager(); if (profile_manager) { std::vector<ProfileAttributesEntry*> entries =
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc index 5f1241d..dff00446 100644 --- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc +++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -492,8 +492,11 @@ // in with an email address matched RestrictSigninToPattern policy already. RecordAuthenticatedLaunchUserEvent( AuthenticatedLaunchUserEvent::USED_PROFILE_BLOCKED_WARNING); - DisplayErrorMessage( - l10n_util::GetStringUTF16(IDS_USER_NOT_ALLOWED_BY_POLICY), web_ui()); + LoginUIServiceFactory::GetForProfile( + Profile::FromWebUI(web_ui())->GetOriginalProfile()) + ->SetProfileBlockingErrorMessage(); + UserManagerProfileDialog::ShowDialogAndDisplayErrorMessage( + web_ui()->GetWebContents()->GetBrowserContext()); } else { // Fresh sign in via user manager without existing email address. RecordAuthenticatedLaunchUserEvent(
diff --git a/chrome/browser/ui/webui/signin/user_manager_ui_browsertest.cc b/chrome/browser/ui/webui/signin/user_manager_ui_browsertest.cc index a37de58..282ee579 100644 --- a/chrome/browser/ui/webui/signin/user_manager_ui_browsertest.cc +++ b/chrome/browser/ui/webui/signin/user_manager_ui_browsertest.cc
@@ -39,6 +39,7 @@ void(Browser* browser, const base::string16& error_message, const base::string16& email)); + MOCK_METHOD0(SetProfileBlockingErrorMessage, void(void)); }; std::unique_ptr<KeyedService> CreateLoginUIService( @@ -165,7 +166,6 @@ EXPECT_CALL(*service, DisplayLoginResult(_, _, _)); LaunchAuthenticatedUser(""); - histogram_tester_.ExpectUniqueSample( kAuthenticatedLaunchUserEventMetricsName, AuthenticatedLaunchUserEvent::SUPERVISED_PROFILE_BLOCKED_WARNING, 1); @@ -180,7 +180,7 @@ MockLoginUIService* service = static_cast<MockLoginUIService*>( LoginUIServiceFactory::GetInstance()->SetTestingFactoryAndUse( profile_, CreateLoginUIService)); - EXPECT_CALL(*service, DisplayLoginResult(_, _, _)); + EXPECT_CALL(*service, SetProfileBlockingErrorMessage()); LaunchAuthenticatedUser("");
diff --git a/chrome/browser/vr/service/vr_device_manager.cc b/chrome/browser/vr/service/vr_device_manager.cc index c23b74b..5380228 100644 --- a/chrome/browser/vr/service/vr_device_manager.cc +++ b/chrome/browser/vr/service/vr_device_manager.cc
@@ -158,6 +158,12 @@ } } +void VRDeviceManager::RecordVrStartupHistograms() { +#if BUILDFLAG(ENABLE_OPENVR) + device::OpenVRDeviceProvider::RecordRuntimeAvailability(); +#endif +} + device::VRDevice* VRDeviceManager::GetDevice(unsigned int index) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/chrome/browser/vr/service/vr_device_manager.h b/chrome/browser/vr/service/vr_device_manager.h index a4aca391..45cea72 100644 --- a/chrome/browser/vr/service/vr_device_manager.h +++ b/chrome/browser/vr/service/vr_device_manager.h
@@ -36,6 +36,7 @@ // Returns the VRDeviceManager singleton. static VRDeviceManager* GetInstance(); static bool HasInstance(); + static void RecordVrStartupHistograms(); // Adds a listener for device manager events. VRDeviceManager does not own // this object.
diff --git a/chrome/common/extensions/api/speech/tts_engine_manifest_handler.cc b/chrome/common/extensions/api/speech/tts_engine_manifest_handler.cc index 7ee2968..d813324d 100644 --- a/chrome/common/extensions/api/speech/tts_engine_manifest_handler.cc +++ b/chrome/common/extensions/api/speech/tts_engine_manifest_handler.cc
@@ -21,16 +21,6 @@ namespace keys = manifest_keys; namespace errors = manifest_errors; -namespace { - -struct TtsVoices : public Extension::ManifestData { - TtsVoices() {} - ~TtsVoices() override {} - - std::vector<extensions::TtsVoice> voices; -}; - -} // namespace TtsVoice::TtsVoice() : remote(false) {} @@ -38,40 +28,15 @@ TtsVoice::~TtsVoice() {} -// static -const std::vector<TtsVoice>* TtsVoice::GetTtsVoices( - const Extension* extension) { - TtsVoices* info = static_cast<TtsVoices*>( - extension->GetManifestData(keys::kTtsVoices)); - return info ? &info->voices : NULL; -} +TtsVoices::TtsVoices() {} +TtsVoices::~TtsVoices() {} -TtsEngineManifestHandler::TtsEngineManifestHandler() { -} - -TtsEngineManifestHandler::~TtsEngineManifestHandler() { -} - -bool TtsEngineManifestHandler::Parse(Extension* extension, - base::string16* error) { - std::unique_ptr<TtsVoices> info(new TtsVoices); - const base::DictionaryValue* tts_dict = NULL; - if (!extension->manifest()->GetDictionary(keys::kTtsEngine, &tts_dict)) { - *error = base::ASCIIToUTF16(errors::kInvalidTts); - return false; - } - - if (!tts_dict->HasKey(keys::kTtsVoices)) - return true; - - const base::ListValue* tts_voices = NULL; - if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) { - *error = base::ASCIIToUTF16(errors::kInvalidTtsVoices); - return false; - } - +// static +bool TtsVoices::Parse(const base::ListValue* tts_voices, + TtsVoices* out_voices, + base::string16* error) { for (size_t i = 0; i < tts_voices->GetSize(); i++) { - const base::DictionaryValue* one_tts_voice = NULL; + const base::DictionaryValue* one_tts_voice = nullptr; if (!tts_voices->GetDictionary(i, &one_tts_voice)) { *error = base::ASCIIToUTF16(errors::kInvalidTtsVoices); return false; @@ -141,9 +106,43 @@ voice_data.event_types.insert(event_type); } } - - info->voices.push_back(voice_data); + out_voices->voices.push_back(voice_data); } + return true; +} + +// static +const std::vector<TtsVoice>* TtsVoices::GetTtsVoices( + const Extension* extension) { + TtsVoices* info = + static_cast<TtsVoices*>(extension->GetManifestData(keys::kTtsVoices)); + return info ? &info->voices : nullptr; +} + +TtsEngineManifestHandler::TtsEngineManifestHandler() {} + +TtsEngineManifestHandler::~TtsEngineManifestHandler() {} + +bool TtsEngineManifestHandler::Parse(Extension* extension, + base::string16* error) { + auto info = std::make_unique<TtsVoices>(); + const base::DictionaryValue* tts_dict = nullptr; + if (!extension->manifest()->GetDictionary(keys::kTtsEngine, &tts_dict)) { + *error = base::ASCIIToUTF16(errors::kInvalidTts); + return false; + } + + if (!tts_dict->HasKey(keys::kTtsVoices)) + return true; + + const base::ListValue* tts_voices = nullptr; + if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) { + *error = base::ASCIIToUTF16(errors::kInvalidTtsVoices); + return false; + } + + if (!TtsVoices::Parse(tts_voices, info.get(), error)) + return false; extension->SetManifestData(keys::kTtsVoices, std::move(info)); return true;
diff --git a/chrome/common/extensions/api/speech/tts_engine_manifest_handler.h b/chrome/common/extensions/api/speech/tts_engine_manifest_handler.h index 20b1b95..2cc26462 100644 --- a/chrome/common/extensions/api/speech/tts_engine_manifest_handler.h +++ b/chrome/common/extensions/api/speech/tts_engine_manifest_handler.h
@@ -25,6 +25,16 @@ std::string gender; bool remote; std::set<std::string> event_types; +}; + +struct TtsVoices : public Extension::ManifestData { + TtsVoices(); + ~TtsVoices() override; + static bool Parse(const base::ListValue* tts_voices, + TtsVoices* out_voices, + base::string16* error); + + std::vector<extensions::TtsVoice> voices; static const std::vector<TtsVoice>* GetTtsVoices(const Extension* extension); };
diff --git a/chrome/common/extensions/api/tts.json b/chrome/common/extensions/api/tts.json index 0b03c83..2bdd26ef0 100644 --- a/chrome/common/extensions/api/tts.json +++ b/chrome/common/extensions/api/tts.json
@@ -82,7 +82,7 @@ }, "eventTypes": { "type": "array", - "items": {"type": "string"}, + "items": {"$ref": "EventType"}, "optional": true, "description": "All of the callback event types that this voice is capable of sending." }
diff --git a/chrome/common/extensions/api/tts_engine.json b/chrome/common/extensions/api/tts_engine.json index ed5b64f..34a0e870 100644 --- a/chrome/common/extensions/api/tts_engine.json +++ b/chrome/common/extensions/api/tts_engine.json
@@ -15,6 +15,19 @@ ], "functions": [ { + "name": "updateVoices", + "type": "function", + "description": "Called by an engine to update its list of voices. This list overrides any voices declared in this extension's manifest.", + "parameters": [ + { + "type": "array", + "name": "voices", + "items": { "$ref": "tts.TtsVoice" }, + "description": "Array of $(ref:tts.TtsVoice) objects representing the available voices for speech synthesis." + } + ] + }, + { "name": "sendTtsEvent", "nodoc": true, "type": "function",
diff --git a/chrome/common/extensions/docs/templates/intros/ttsEngine.html b/chrome/common/extensions/docs/templates/intros/ttsEngine.html index 2320f3e..4d20510 100644 --- a/chrome/common/extensions/docs/templates/intros/ttsEngine.html +++ b/chrome/common/extensions/docs/templates/intros/ttsEngine.html
@@ -46,6 +46,9 @@ <p>An extension can specify any number of voices.</p> +<p>Once loaded, an extension can replace the list of declared voices + by calling <code>chrome.ttsEngine.updateVoices</code></p> + <p>The <code>voice_name</code> parameter is required. The name should be descriptive enough that it identifies the name of the voice and the engine used. In the unlikely event that two extensions register voices
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 0223d3f..71f8393 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2167,6 +2167,7 @@ "../browser/android/ntp/content_suggestions_notifier_unittest.cc", "../browser/android/oom_intervention/near_oom_monitor_unittest.cc", "../browser/android/oom_intervention/oom_intervention_decider_unittest.cc", + "../browser/android/password_ui_view_android_unittest.cc", "../browser/android/physical_web/eddystone_encoder_bridge_unittest.cc", "../browser/android/physical_web/physical_web_data_source_android_unittest.cc", "../browser/android/preferences/pref_service_bridge_unittest.cc",
diff --git a/chrome/test/data/android/subresource_filter/page-with-img.html b/chrome/test/data/android/subresource_filter/page-with-img.html new file mode 100644 index 0000000..00bfe565 --- /dev/null +++ b/chrome/test/data/android/subresource_filter/page-with-img.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> +<img id="image" src="../capybara.jpg"/> +<script> +imgLoaded = false; +var img = document.getElementById("image"); +img.onload = () => { imgLoaded = true; } +</script>
diff --git a/chrome/test/data/extensions/api_test/executescript/css_origin/b.js b/chrome/test/data/extensions/api_test/executescript/css_origin/b.js new file mode 100644 index 0000000..653fedc --- /dev/null +++ b/chrome/test/data/extensions/api_test/executescript/css_origin/b.js
@@ -0,0 +1,13 @@ +// 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. + +chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { + var element = document.getElementById(message.id); + var style = getComputedStyle(element); + var response = { + color: style.getPropertyValue('color'), + backgroundColor: style.getPropertyValue('background-color') + }; + sendResponse(response); +});
diff --git a/chrome/test/data/extensions/api_test/executescript/css_origin/manifest.json b/chrome/test/data/extensions/api_test/executescript/css_origin/manifest.json new file mode 100644 index 0000000..bfbdf151 --- /dev/null +++ b/chrome/test/data/extensions/api_test/executescript/css_origin/manifest.json
@@ -0,0 +1,16 @@ +{ + "version": "1.0.0.0", + "manifest_version": 2, + "name": "css_origin test", + "description": "Test the css_origin property of insertCSS", + "background": { + "scripts": ["test.js"] + }, + "permissions": ["tabs", "http://b.com/"], + "content_scripts": [ + { + "matches": ["http://*/*"], + "js": ["b.js"] + } + ] +}
diff --git a/chrome/test/data/extensions/api_test/executescript/css_origin/test.html b/chrome/test/data/extensions/api_test/executescript/css_origin/test.html new file mode 100644 index 0000000..a806a79 --- /dev/null +++ b/chrome/test/data/extensions/api_test/executescript/css_origin/test.html
@@ -0,0 +1,16 @@ +<html> + <style> + #author, #user, #none { + color: red; + } + </style> + <div id="author" style="background-color: black !important"> + Hello. + </div> + <div id="user" style="background-color: black !important"> + Hello. + </div> + <div id="none" style="background-color: black !important"> + Hello. + </div> +</html>
diff --git a/chrome/test/data/extensions/api_test/executescript/css_origin/test.js b/chrome/test/data/extensions/api_test/executescript/css_origin/test.js new file mode 100644 index 0000000..78047330 --- /dev/null +++ b/chrome/test/data/extensions/api_test/executescript/css_origin/test.js
@@ -0,0 +1,92 @@ +// 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. + +chrome.test.getConfig(function(config) { + var testUrl = 'http://b.com:' + config.testServer.port + + '/extensions/api_test/executescript/css_origin/test.html'; + chrome.tabs.onUpdated.addListener(function listener(tabId, changeInfo, tab) { + if (changeInfo.status != 'complete') + return; + chrome.tabs.onUpdated.removeListener(listener); + chrome.test.runTests([ + // Until we have tabs.removeCSS we just have to target a different + // element on the page for each test. + function authorOriginShouldSucceed() { + var injectDetails = {}; + injectDetails.code = '#author {' + + ' color: blue !important;' + + ' background-color: white !important;' + + '}'; + injectDetails.cssOrigin = 'author'; + chrome.tabs.insertCSS(tabId, injectDetails, + chrome.test.callbackPass(function() { + chrome.tabs.sendMessage(tabId, { id: 'author' }, + chrome.test.callbackPass(function(response) { + chrome.test.assertEq('rgb(0, 0, 255)', response.color); + // !important rules in author style sheets do not override inline + // !important rules. + chrome.test.assertEq('rgb(0, 0, 0)', response.backgroundColor); + })); + })); + }, + function userOriginShouldSucceed() { + var injectDetails = {}; + injectDetails.code = '#user {' + + ' color: blue !important;' + + ' background-color: white !important;' + + '}'; + injectDetails.cssOrigin = 'user'; + chrome.tabs.insertCSS(tabId, injectDetails, + chrome.test.callbackPass(function() { + chrome.tabs.sendMessage(tabId, { id: 'user' }, + chrome.test.callbackPass(function(response) { + chrome.test.assertEq('rgb(0, 0, 255)', response.color); + // !important rules in user style sheets do override inline + // !important rules. + chrome.test.assertEq('rgb(255, 255, 255)', + response.backgroundColor); + })); + })); + }, + function noneOriginShouldSucceed() { + // When no CSS origin is specified, it should default to author origin. + var injectDetails = {}; + injectDetails.code = '#none {' + + ' color: blue !important;' + + ' background-color: white !important;' + + '}'; + chrome.tabs.insertCSS(tabId, injectDetails, + chrome.test.callbackPass(function() { + chrome.tabs.sendMessage(tabId, { id: 'none' }, + chrome.test.callbackPass(function(response) { + chrome.test.assertEq('rgb(0, 0, 255)', response.color); + // !important rules in author style sheets do not override inline + // !important rules. + chrome.test.assertEq('rgb(0, 0, 0)', response.backgroundColor); + })); + })); + }, + function unknownOriginShouldFail() { + var injectDetails = {}; + injectDetails.code = '#unknown { color: black !important }'; + injectDetails.cssOrigin = 'unknown'; + try { + chrome.tabs.insertCSS(tabId, injectDetails); + chrome.test.fail('Unknown CSS origin should throw an error'); + } catch (e) { + chrome.test.succeed(); + } + }, + function originInExecuteScriptShouldFail() { + var injectDetails = {}; + injectDetails.code = '(function(){})();'; + injectDetails.cssOrigin = 'author'; + chrome.tabs.executeScript(tabId, injectDetails, + chrome.test.callbackFail( + 'CSS origin should be specified only for CSS code.')); + } + ]); + }); + chrome.tabs.create({ url: testUrl }); +});
diff --git a/chrome/test/data/extensions/api_test/tts_engine/update_voices_api/manifest.json b/chrome/test/data/extensions/api_test/tts_engine/update_voices_api/manifest.json new file mode 100644 index 0000000..1a02e8d --- /dev/null +++ b/chrome/test/data/extensions/api_test/tts_engine/update_voices_api/manifest.json
@@ -0,0 +1,20 @@ +{ + "name": "chrome.ttsEngine", + "version": "0.1", + "manifest_version": 2, + "description": "browser test for chrome.ttsEngine.updateVoices API", + "background": { + "scripts": ["test.js"] + }, + "tts_engine": { + "voices": [ + { + "voice_name": "Zach", + "lang": "en-US", + "event_types": [ "end", "error" ] + } + ] + }, + "permissions": ["tts", "ttsEngine"], + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDfX9dHNh948bt00YhZBm3P6E5QLaOt+v8kXVtibQfiPtOD2FTScB/f0wX/EQWVO7BkaSOsRkTPcPIgocyMPYr2FLgqGLFlYT9nQpKJZUFNF5oJ5rG6Nv7ppf4zEB3j6da1IBRTz2yOZ+6O1TMZxol/V62/QcqrJeggsHTEPGLdr9Ua4b1Ka0xKJnJngZljsbw93FI1o+P9dAh5BS6wTPiZI/vmJVjvMTkSTnaZ3n9Go2t7A0XLcSxLcVyuLAd2mAvSN0mIviOukdM66wr7llif71nKuUt+4qvlr/r9HfwzN6pA4jkwhtS1UD+3CmB+wsHwsnohNcuu4FIQ6rgq/7QIDAQAB" +}
diff --git a/chrome/test/data/extensions/api_test/tts_engine/update_voices_api/test.js b/chrome/test/data/extensions/api_test/tts_engine/update_voices_api/test.js new file mode 100644 index 0000000..ff697d9 --- /dev/null +++ b/chrome/test/data/extensions/api_test/tts_engine/update_voices_api/test.js
@@ -0,0 +1,85 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var testVoiceData = [ + { + eventTypes: ['start'], + extensionId: 'pkplfbidichfdicaijlchgnapepdginl', + gender: 'male', + lang: 'zh-TW', + remote: false, + voiceName: 'David' + }, + { + eventTypes: ['end', 'interrupted', 'cancelled'], + extensionId: 'pkplfbidichfdicaijlchgnapepdginl', + gender: 'female', + lang: 'en-GB', + remote: false, + voiceName: 'Laura' + } +]; + +function setup() { + var speakListener = function(utterance, options, sendTtsEvent) {}; + var stopListener = function() {}; + chrome.ttsEngine.onSpeak.addListener(speakListener); + chrome.ttsEngine.onStop.addListener(stopListener); +} + +chrome.test.runTests([ + function testGetVoices() { + setup(); + chrome.tts.getVoices(function(voices) { + chrome.test.assertEq(1, voices.length); + chrome.test.assertEq({ + eventTypes: [ 'end', 'interrupted', 'cancelled', 'error'], + extensionId: 'pkplfbidichfdicaijlchgnapepdginl', + lang: 'en-US', + remote: false, + voiceName: 'Zach' + }, voices[0]); + chrome.ttsEngine.updateVoices(testVoiceData); + chrome.tts.getVoices(function(runtimeVoices) { + chrome.test.assertEq(testVoiceData.length, runtimeVoices.length); + for (var i = 0; i < runtimeVoices.length; i++) { + chrome.test.assertEq(testVoiceData[i], runtimeVoices[i]); + chrome.test.assertEq(runtimeVoices[i], testVoiceData[i]); + } + chrome.test.assertNoLastError(); + chrome.test.succeed(); + }); + }); + }, + function testExtensionIdMismatch() { + setup(); + chrome.ttsEngine.updateVoices([{ + eventTypes: [ 'end', 'interrupted', 'cancelled', 'error'], + extensionId: 'interloper', + lang: 'en-US', + remote: false, + voiceName: 'Zach' + }]); + + chrome.tts.getVoices(function(voices) { + chrome.test.assertEq(0, voices.length); + chrome.test.succeed(); + }); + }, + function testInvalidLang() { + setup(); + chrome.ttsEngine.updateVoices([{ + eventTypes: [ 'end', 'interrupted', 'cancelled', 'error'], + extensionId: 'pkplfbidichfdicaijlchgnapepdginl', + lang: 'bad lang syntax', + remote: false, + voiceName: 'Zach' + }]); + + chrome.tts.getVoices(function(voices) { + chrome.test.assertEq(0, voices.length); + chrome.test.succeed(); + }); + } +]);
diff --git a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js index 4fb324b..850c1b2c 100644 --- a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js +++ b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
@@ -38,6 +38,7 @@ '../../../../../ui/webui/resources/js/promise_resolver.js', '../../../../../ui/webui/resources/js/webui_resource_test.js', '../fake_chrome_event.js', + '../settings/test_util.js', '../test_browser_proxy.js', 'test_service.js', ]); @@ -130,6 +131,12 @@ this.runMochaTest(extension_toolbar_tests.TestNames.ClickHandlers); }); +GEN('#if defined(OS_CHROMEOS)'); +TEST_F('CrExtensionsToolbarTest', 'KioskMode', function() { + this.runMochaTest(extension_toolbar_tests.TestNames.KioskMode); +}); +GEN('#endif'); + //////////////////////////////////////////////////////////////////////////////// // Extension Item Tests @@ -316,6 +323,7 @@ /** @override */ get extraLibraries() { return super.extraLibraries.concat([ + 'test_kiosk_browser_proxy.js', 'extension_manager_unit_test.js', ]); } @@ -354,6 +362,12 @@ this.runMochaTest(extension_manager_tests.TestNames.EnableAndDisable); }); +GEN('#if defined(OS_CHROMEOS)'); +TEST_F('CrExtensionsManagerUnitTest', 'KioskMode', function() { + this.runMochaTest(extension_manager_tests.TestNames.KioskMode); +}); +GEN('#endif'); + var CrExtensionsManagerTestWithMultipleExtensionTypesInstalled = class extends CrExtensionsBrowserTest { @@ -687,7 +701,6 @@ /** @override */ get extraLibraries() { return super.extraLibraries.concat([ - '../settings/test_util.js', 'toggle_row_test.js', ]); } @@ -696,3 +709,33 @@ TEST_F('CrExtensionsToggleRowTest', 'ToggleRowTest', function() { mocha.run(); }); + +//////////////////////////////////////////////////////////////////////////////// +// kiosk mode tests. + +GEN('#if defined(OS_CHROMEOS)'); + +var CrExtensionsKioskModeTest = class extends CrExtensionsBrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://extensions/kiosk_dialog.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + 'test_kiosk_browser_proxy.js', + 'extension_kiosk_mode_test.js', + ]); + } + /** @override */ + get suiteName() { + return extension_kiosk_mode_tests.suiteName; + } +}; + +TEST_F('CrExtensionsKioskModeTest', 'AddButton', function() { + this.runMochaTest(extension_kiosk_mode_tests.TestNames.AddButton); +}); + +GEN('#endif');
diff --git a/chrome/test/data/webui/extensions/extension_kiosk_mode_test.js b/chrome/test/data/webui/extensions/extension_kiosk_mode_test.js new file mode 100644 index 0000000..4e9ad5b --- /dev/null +++ b/chrome/test/data/webui/extensions/extension_kiosk_mode_test.js
@@ -0,0 +1,50 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** @fileoverview Suite of tests for extension-kiosk-dialog. */ +cr.define('extension_kiosk_mode_tests', function() { + /** @enum {string} */ + let TestNames = { + AddButton: 'AddButton', + }; + + let suiteName = 'kioskModeTests'; + + suite(suiteName, function() { + let browserProxy = null; + let dialog = null; + + setup(function() { + PolymerTest.clearBody(); + + browserProxy = new TestKioskBrowserProxy(); + extensions.KioskBrowserProxyImpl.instance_ = browserProxy; + + dialog = document.createElement('extensions-kiosk-dialog'); + document.body.appendChild(dialog); + + Polymer.dom.flush(); + }); + + test(assert(TestNames.AddButton), function() { + const addButton = dialog.$['add-button']; + expectTrue(!!addButton); + expectTrue(addButton.disabled); + + const addInput = dialog.$['add-input']; + addInput.value = 'blah'; + expectFalse(addButton.disabled); + + MockInteractions.tap(addButton); + return browserProxy.whenCalled('addKioskApp').then(appId => { + expectEquals(appId, 'blah'); + }); + }); + }); + + return { + suiteName: suiteName, + TestNames: TestNames, + }; +});
diff --git a/chrome/test/data/webui/extensions/extension_manager_unit_test.js b/chrome/test/data/webui/extensions/extension_manager_unit_test.js index e8ada89..9a0664b 100644 --- a/chrome/test/data/webui/extensions/extension_manager_unit_test.js +++ b/chrome/test/data/webui/extensions/extension_manager_unit_test.js
@@ -15,6 +15,7 @@ Uninstall: 'uninstall', UninstallFromDetails: 'uninstall while in details view', UpdateItemData: 'update item data', + KioskMode: 'kiosk mode', }; var suiteName = 'ExtensionManagerUnitTest'; @@ -26,7 +27,15 @@ /** @type {TestService} */ let service; + /** @type {extensions.KioskBrowserProxy} */ + let browserProxy; + setup(function() { + if (cr.isChromeOS) { + browserProxy = new TestKioskBrowserProxy(); + extensions.KioskBrowserProxyImpl.instance_ = browserProxy; + } + PolymerTest.clearBody(); service = new extensions.TestService(); @@ -281,6 +290,20 @@ }); expectEquals(ExtensionState.ENABLED, manager.extensions_[0].state); }); + + if (cr.isChromeOS) { + test(assert(TestNames.KioskMode), function() { + expectFalse(!!manager.$$('extensions-kiosk-dialog')); + + return browserProxy.whenCalled('initializeKioskAppSettings') + .then(() => { + expectTrue(manager.$$('extensions-toolbar').kioskEnabled); + manager.$$('extensions-toolbar').fire('kiosk-tap'); + Polymer.dom.flush(); + expectTrue(!!manager.$$('extensions-kiosk-dialog')); + }); + }); + } }); return {
diff --git a/chrome/test/data/webui/extensions/extension_toolbar_test.js b/chrome/test/data/webui/extensions/extension_toolbar_test.js index 7520865e..5793642 100644 --- a/chrome/test/data/webui/extensions/extension_toolbar_test.js +++ b/chrome/test/data/webui/extensions/extension_toolbar_test.js
@@ -9,6 +9,7 @@ Layout: 'layout', ClickHandlers: 'click handlers', DevModeToggle: 'dev mode toggle', + KioskMode: 'kiosk mode button' }; var suiteName = 'ExtensionToolbarTest'; @@ -91,12 +92,24 @@ MockInteractions.tap(toolbar.$$('#update-now')); return mockDelegate.whenCalled('updateAllExtensions'); }).then(function() { - var listener = new extension_test_util.ListenerMock(); - listener.addListener(toolbar, 'pack-tap'); + const whenTapped = test_util.eventToPromise('pack-tap', toolbar); MockInteractions.tap(toolbar.$$('#pack-extensions')); - listener.verify(); + return whenTapped; }); }); + + if (cr.isChromeOS) { + test(assert(TestNames.KioskMode), function() { + const button = toolbar.$$('#kiosk-extensions'); + expectTrue(button.hidden); + toolbar.kioskEnabled = true; + expectFalse(button.hidden); + + const whenTapped = test_util.eventToPromise('kiosk-tap', toolbar); + MockInteractions.tap(button); + return whenTapped; + }); + } }); return {
diff --git a/chrome/test/data/webui/extensions/test_kiosk_browser_proxy.js b/chrome/test/data/webui/extensions/test_kiosk_browser_proxy.js new file mode 100644 index 0000000..5b5ac96 --- /dev/null +++ b/chrome/test/data/webui/extensions/test_kiosk_browser_proxy.js
@@ -0,0 +1,62 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** @implements {extensions.KioskBrowserProxy} */ +class TestKioskBrowserProxy extends TestBrowserProxy { + constructor() { + super([ + 'initializeKioskAppSettings', + 'getKioskAppSettings', + 'addKioskApp', + 'disableKioskAutoLaunch', + 'enableKioskAutoLaunch', + 'removeKioskApp', + 'setDisableBailoutShortcut', + ]); + } + + /** @override */ + initializeKioskAppSettings() { + this.methodCalled('initializeKioskAppSettings'); + return Promise.resolve({ + kioskEnabled: true, + autoLaunchEnabled: false + }); + } + + /** @override */ + getKioskAppSettings() { + this.methodCalled('getKioskAppSettings'); + return Promise.resolve({ + apps: [], + disableBailout: false, + hasAutoLaunchApp: false + }); + } + + /** @override */ + addKioskApp(appId) { + this.methodCalled('addKioskApp', appId); + } + + /** @override */ + disableKioskAutoLaunch(appId) { + this.methodCalled('disableKioskAutoLaunch', appId); + } + + /** @override */ + enableKioskAutoLaunch(appId) { + this.methodCalled('enableKioskAutoLaunch', appId); + } + + /** @override */ + removeKioskApp(appId) { + this.methodCalled('removeKioskApp', appId); + } + + /** @override */ + setDisableBailoutShortcut(disableBailout) { + this.methodCalled('setDisableBailoutShortcut', disableBailout); + } +} \ No newline at end of file
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index 02e865ac..d18977f 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -250,13 +250,12 @@ if (target_os == "linux" && !is_cast_desktop_build) { # DesktopCaptureDeviceTest.*: No capture device on Eureka # Disable PepperGamepadHostTest.WaitForReply (pepper not supported on Eureka) - # Disable GpuDataManagerImplPrivateTest.SetGLStrings and - # RenderWidgetHostTest.Background because we disable the blacklist to enable WebGL (b/16142554) + # Disable RenderWidgetHostTest.Background because we disable the + # blacklist to enable WebGL (b/16142554) gtest_excludes += [ "DOMStorageDatabaseTest.TestCanOpenAndReadWebCoreDatabase", "DesktopCaptureDeviceTest.Capture", "GamepadProviderTest.PollingAccess", - "GpuDataManagerImplPrivateTest.SetGLStrings", "PepperGamepadHostTest.WaitForReply", "RenderWidgetHostTest.Background", ]
diff --git a/chromecast/app/BUILD.gn b/chromecast/app/BUILD.gn index b8399665..172e3f7 100644 --- a/chromecast/app/BUILD.gn +++ b/chromecast/app/BUILD.gn
@@ -19,6 +19,7 @@ "//chromecast/base", "//chromecast/browser", "//chromecast/common", + "//chromecast/gpu", "//chromecast/renderer", "//chromecast/utility", "//components/crash/core/common:crash_key",
diff --git a/chromecast/app/DEPS b/chromecast/app/DEPS index 9ca074e..706cc6d 100644 --- a/chromecast/app/DEPS +++ b/chromecast/app/DEPS
@@ -2,6 +2,7 @@ "+chromecast/browser", "+chromecast/common", "+chromecast/crash", + "+chromecast/gpu", "+chromecast/renderer", "+chromecast/utility", "+components/crash",
diff --git a/chromecast/app/cast_main_delegate.cc b/chromecast/app/cast_main_delegate.cc index 7ae8008..9a052ee 100644 --- a/chromecast/app/cast_main_delegate.cc +++ b/chromecast/app/cast_main_delegate.cc
@@ -18,11 +18,12 @@ #include "base/path_service.h" #include "base/posix/global_descriptors.h" #include "build/build_config.h" -#include "chromecast/chromecast_features.h" #include "chromecast/base/cast_paths.h" #include "chromecast/browser/cast_content_browser_client.h" +#include "chromecast/chromecast_features.h" #include "chromecast/common/cast_resource_delegate.h" #include "chromecast/common/global_descriptors.h" +#include "chromecast/gpu/cast_content_gpu_client.h" #include "chromecast/renderer/cast_content_renderer_client.h" #include "chromecast/utility/cast_content_utility_client.h" #include "components/crash/content/app/crash_reporter_client.h" @@ -234,6 +235,11 @@ return browser_client_.get(); } +content::ContentGpuClient* CastMainDelegate::CreateContentGpuClient() { + gpu_client_ = CastContentGpuClient::Create(); + return gpu_client_.get(); +} + content::ContentRendererClient* CastMainDelegate::CreateContentRendererClient() { renderer_client_ = CastContentRendererClient::Create();
diff --git a/chromecast/app/cast_main_delegate.h b/chromecast/app/cast_main_delegate.h index 0101796..319ba6b 100644 --- a/chromecast/app/cast_main_delegate.h +++ b/chromecast/app/cast_main_delegate.h
@@ -23,6 +23,7 @@ namespace shell { class CastContentBrowserClient; +class CastContentGpuClient; class CastContentRendererClient; class CastContentUtilityClient; @@ -41,6 +42,7 @@ void ZygoteForked() override; #endif // defined(OS_LINUX) content::ContentBrowserClient* CreateContentBrowserClient() override; + content::ContentGpuClient* CreateContentGpuClient() override; content::ContentRendererClient* CreateContentRendererClient() override; content::ContentUtilityClient* CreateContentUtilityClient() override; @@ -48,6 +50,7 @@ void InitializeResourceBundle(); std::unique_ptr<CastContentBrowserClient> browser_client_; + std::unique_ptr<CastContentGpuClient> gpu_client_; std::unique_ptr<CastContentRendererClient> renderer_client_; std::unique_ptr<CastContentUtilityClient> utility_client_; std::unique_ptr<CastResourceDelegate> resource_delegate_;
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc index 01d95e2..a5d1aa2 100644 --- a/chromecast/browser/cast_browser_main_parts.cc +++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -26,7 +26,6 @@ #include "chromecast/base/cast_constants.h" #include "chromecast/base/cast_features.h" #include "chromecast/base/cast_paths.h" -#include "chromecast/base/cast_sys_info_util.h" #include "chromecast/base/chromecast_switches.h" #include "chromecast/base/metrics/cast_metrics_helper.h" #include "chromecast/base/metrics/grouped_histogram.h" @@ -52,13 +51,11 @@ #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" #include "chromecast/net/connectivity_checker.h" #include "chromecast/public/cast_media_shlib.h" -#include "chromecast/public/cast_sys_info.h" #include "chromecast/service/cast_service.h" #include "components/prefs/pref_registry_simple.h" #include "components/proxy_config/pref_proxy_config_tracker_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" -#include "content/public/browser/gpu_data_manager.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/content_switches.h" #include "gpu/command_buffer/service/gpu_switches.h" @@ -240,10 +237,9 @@ #endif #endif #endif // defined(OS_LINUX) - // Needed so that our call to GpuDataManager::SetGLStrings doesn't race - // against GPU process creation (which is otherwise triggered from - // BrowserThreadsStarted). The GPU process will be created as soon as a - // renderer needs it, which always happens after main loop starts. + // It's better to start GPU process on demand. For example, for TV platforms + // cast starts in background and can't render until TV switches to cast + // input. {switches::kDisableGpuEarlyInit, ""}, // Enable navigator.connection API. // TODO(derekjchow): Remove this switch when enabled by default. @@ -420,14 +416,6 @@ CHECK(PathService::Get(DIR_CAST_HOME, &home_dir)); if (!base::CreateDirectory(home_dir)) return 1; - - // Set GL strings so GPU config code can make correct feature blacklisting/ - // whitelisting decisions. - // Note: SetGLStrings can be called before GpuDataManager::Initialize. - std::unique_ptr<CastSysInfo> sys_info = CreateSysInfo(); - content::GpuDataManager::GetInstance()->SetGLStrings( - sys_info->GetGlVendor(), sys_info->GetGlRenderer(), - sys_info->GetGlVersion()); #endif scoped_refptr<PrefRegistrySimple> pref_registry(new PrefRegistrySimple());
diff --git a/chromecast/gpu/BUILD.gn b/chromecast/gpu/BUILD.gn new file mode 100644 index 0000000..215cd0f5 --- /dev/null +++ b/chromecast/gpu/BUILD.gn
@@ -0,0 +1,21 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//chromecast/chromecast.gni") + +cast_source_set("gpu") { + sources = [ + "cast_content_gpu_client.cc", + "cast_content_gpu_client.h", + ] + + deps = [ + "//base", + "//chromecast/base", + "//chromecast/base:cast_sys_info", + "//chromecast/public", + "//content/public/gpu", + "//gpu/config", + ] +}
diff --git a/chromecast/gpu/DEPS b/chromecast/gpu/DEPS new file mode 100644 index 0000000..63915af --- /dev/null +++ b/chromecast/gpu/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + "+chromecast/base", + "+chromecast/public", + "+content/public/gpu", + "+gpu/config", +]
diff --git a/chromecast/gpu/cast_content_gpu_client.cc b/chromecast/gpu/cast_content_gpu_client.cc new file mode 100644 index 0000000..3f41f710 --- /dev/null +++ b/chromecast/gpu/cast_content_gpu_client.cc
@@ -0,0 +1,44 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/gpu/cast_content_gpu_client.h" + +#include "base/memory/ptr_util.h" +#include "build/build_config.h" +#include "chromecast/base/cast_sys_info_util.h" +#include "chromecast/public/cast_sys_info.h" +#include "gpu/config/gpu_info.h" +#include "gpu/config/gpu_info_collector.h" + +namespace chromecast { + +namespace shell { + +// static +std::unique_ptr<CastContentGpuClient> CastContentGpuClient::Create() { + return base::WrapUnique(new CastContentGpuClient()); +} + +CastContentGpuClient::CastContentGpuClient() = default; + +CastContentGpuClient::~CastContentGpuClient() = default; + +const gpu::GPUInfo* CastContentGpuClient::GetGPUInfo() { +#if defined(OS_ANDROID) + return nullptr; +#else + if (!gpu_info_) { + gpu_info_ = base::MakeUnique<gpu::GPUInfo>(); + std::unique_ptr<CastSysInfo> sys_info = CreateSysInfo(); + gpu_info_->gl_vendor = sys_info->GetGlVendor(); + gpu_info_->gl_renderer = sys_info->GetGlRenderer(); + gpu_info_->gl_version = sys_info->GetGlVersion(); + gpu::CollectDriverInfoGL(gpu_info_.get()); + } + return gpu_info_.get(); +#endif // OS_ANDROID +} + +} // namespace shell +} // namespace chromecast
diff --git a/chromecast/gpu/cast_content_gpu_client.h b/chromecast/gpu/cast_content_gpu_client.h new file mode 100644 index 0000000..297986a3 --- /dev/null +++ b/chromecast/gpu/cast_content_gpu_client.h
@@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_GPU_CAST_CONTENT_GPU_CLIENT_H_ +#define CHROMECAST_GPU_CAST_CONTENT_GPU_CLIENT_H_ + +#include <memory> + +#include "base/macros.h" +#include "content/public/gpu/content_gpu_client.h" + +namespace gpu { +struct GPUInfo; +} + +namespace chromecast { + +namespace shell { + +class CastContentGpuClient : public content::ContentGpuClient { + public: + ~CastContentGpuClient() override; + + static std::unique_ptr<CastContentGpuClient> Create(); + + // ContentGpuClient: + const gpu::GPUInfo* GetGPUInfo() override; + + protected: + CastContentGpuClient(); + + private: + std::unique_ptr<gpu::GPUInfo> gpu_info_; + + DISALLOW_COPY_AND_ASSIGN(CastContentGpuClient); +}; + +} // namespace shell +} // namespace chromecast + +#endif // CHROMECAST_GPU_CAST_CONTENT_GPU_CLIENT_H_
diff --git a/chromeos/components/tether/connect_tethering_operation.cc b/chromeos/components/tether/connect_tethering_operation.cc index e62d1a0..b8c7990 100644 --- a/chromeos/components/tether/connect_tethering_operation.cc +++ b/chromeos/components/tether/connect_tethering_operation.cc
@@ -15,10 +15,19 @@ namespace tether { -// This value is quite large because first time -// setup can take a long time. +// When setup is not required, allow a 30-second timeout. If a host device is on +// a slow data connection, enabling the tether hotspot may take a significant +// amount of time because most phones must send a "provisioning" request to +// the mobile provider to ask the provider whether tethering is allowed. // static -uint32_t ConnectTetheringOperation::kSetupRequiredResponseTimeoutSeconds = 90; +const uint32_t + ConnectTetheringOperation::kSetupNotRequiredResponseTimeoutSeconds = 30; + +// When setup is required, the timeout is extended another 90 seconds because +// setup requires that the user interact with a notification on the Tether host. +// static +const uint32_t ConnectTetheringOperation::kSetupRequiredResponseTimeoutSeconds = + 120; // static ConnectTetheringOperation::Factory* @@ -120,6 +129,9 @@ tether_host_response_recorder_->RecordSuccessfulConnectTetheringResponse( remote_device); + // Save the response values here, but do not notify observers until + // OnOperationFinished(). Notifying observers at this point can cause this + // object to be deleted, resulting in a crash. ssid_to_return_ = response->ssid(); password_to_return_ = response->password(); } else { @@ -148,19 +160,15 @@ } void ConnectTetheringOperation::OnOperationFinished() { - // Notify observers of the results of this operation in OnOperationFinished() - // instead of in OnMessageReceived() because observers may delete this - // ConnectTetheringOperation instance. If this happens, the UnregisterDevice() - // call in OnMessageReceived() will cause a crash. - - if (!ssid_to_return_.empty()) { - NotifyObserversOfSuccessfulResponse(ssid_to_return_, password_to_return_); - } else { - // At this point, either the operation finished with a failed response or - // no connection succeeded at all. In these cases, notify observers of a - // failure. + // If |ssid_to_return_| has not been set, either the operation finished with a + // failed response or no connection succeeded at all. In these cases, notify + // observers of a failure. + if (ssid_to_return_.empty()) { NotifyObserversOfConnectionFailure(error_code_to_return_); + return; } + + NotifyObserversOfSuccessfulResponse(ssid_to_return_, password_to_return_); } MessageType ConnectTetheringOperation::GetMessageTypeForConnection() { @@ -195,9 +203,10 @@ } uint32_t ConnectTetheringOperation::GetTimeoutSeconds() { - return (setup_required_) + return setup_required_ ? ConnectTetheringOperation::kSetupRequiredResponseTimeoutSeconds - : MessageTransferOperation::GetTimeoutSeconds(); + : ConnectTetheringOperation:: + kSetupNotRequiredResponseTimeoutSeconds; } void ConnectTetheringOperation::SetClockForTest(
diff --git a/chromeos/components/tether/connect_tethering_operation.h b/chromeos/components/tether/connect_tethering_operation.h index ea651d2..e152950 100644 --- a/chromeos/components/tether/connect_tethering_operation.h +++ b/chromeos/components/tether/connect_tethering_operation.h
@@ -93,9 +93,10 @@ void SetClockForTest(std::unique_ptr<base::Clock> clock_for_test); - // The amount of time this operation will wait for if first time setup is - // required on the host device. - static uint32_t kSetupRequiredResponseTimeoutSeconds; + // The amount of time this operation will wait for a response. The timeout + // values are different depending on whether setup is needed on the host. + static const uint32_t kSetupNotRequiredResponseTimeoutSeconds; + static const uint32_t kSetupRequiredResponseTimeoutSeconds; cryptauth::RemoteDevice remote_device_; TetherHostResponseRecorder* tether_host_response_recorder_;
diff --git a/chromeos/components/tether/connect_tethering_operation_unittest.cc b/chromeos/components/tether/connect_tethering_operation_unittest.cc index ffd71ca..f2ee5679 100644 --- a/chromeos/components/tether/connect_tethering_operation_unittest.cc +++ b/chromeos/components/tether/connect_tethering_operation_unittest.cc
@@ -200,7 +200,8 @@ uint32_t expected_response_timeout_seconds = setup_required ? ConnectTetheringOperation::kSetupRequiredResponseTimeoutSeconds - : MessageTransferOperation::kDefaultTimeoutSeconds; + : ConnectTetheringOperation:: + kSetupNotRequiredResponseTimeoutSeconds; EXPECT_EQ(expected_response_timeout_seconds, operation_->GetTimeoutSeconds());
diff --git a/chromeos/components/tether/network_connection_handler_tether_delegate_unittest.cc b/chromeos/components/tether/network_connection_handler_tether_delegate_unittest.cc index faefe13..96309c5 100644 --- a/chromeos/components/tether/network_connection_handler_tether_delegate_unittest.cc +++ b/chromeos/components/tether/network_connection_handler_tether_delegate_unittest.cc
@@ -69,7 +69,8 @@ void ConnectToNetwork(const std::string& service_path, const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback, - bool check_error_state) override {} + bool check_error_state, + ConnectCallbackMode mode) override {} void DisconnectNetwork( const std::string& service_path,
diff --git a/chromeos/components/tether/wifi_hotspot_disconnector_impl_unittest.cc b/chromeos/components/tether/wifi_hotspot_disconnector_impl_unittest.cc index f9b46c8..b112196 100644 --- a/chromeos/components/tether/wifi_hotspot_disconnector_impl_unittest.cc +++ b/chromeos/components/tether/wifi_hotspot_disconnector_impl_unittest.cc
@@ -73,7 +73,8 @@ void ConnectToNetwork(const std::string& service_path, const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback, - bool check_error_state) override {} + bool check_error_state, + ConnectCallbackMode mode) override {} bool HasConnectingNetwork(const std::string& service_path) override { return false; }
diff --git a/chromeos/dbus/services/component_updater_service_provider.cc b/chromeos/dbus/services/component_updater_service_provider.cc index db455c3..d626d4f 100644 --- a/chromeos/dbus/services/component_updater_service_provider.cc +++ b/chromeos/dbus/services/component_updater_service_provider.cc
@@ -61,7 +61,10 @@ // |mount| is an optional parameter, and by default is true. bool mount = true; if (reader.PopString(&component_name)) { - reader.PopBool(&mount); + // dbus::MessageReader::PopBool sets its out-param to false on failure. + // Resets |mount| to its default value on failure. + if (!reader.PopBool(&mount)) + mount = true; delegate_->LoadComponent( component_name, mount, base::Bind(&ComponentUpdaterServiceProvider::OnLoadComponent,
diff --git a/chromeos/network/auto_connect_handler_unittest.cc b/chromeos/network/auto_connect_handler_unittest.cc index 9e82629c..0c635e17 100644 --- a/chromeos/network/auto_connect_handler_unittest.cc +++ b/chromeos/network/auto_connect_handler_unittest.cc
@@ -95,7 +95,8 @@ void ConnectToNetwork(const std::string& service_path, const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback, - bool check_error_state) override {} + bool check_error_state, + ConnectCallbackMode mode) override {} bool HasConnectingNetwork(const std::string& service_path) override { return false;
diff --git a/chromeos/network/network_connect.cc b/chromeos/network/network_connect.cc index 0ca26f5a..13abf33c 100644 --- a/chromeos/network/network_connect.cc +++ b/chromeos/network/network_connect.cc
@@ -254,7 +254,7 @@ weak_factory_.GetWeakPtr(), network_id), base::Bind(&NetworkConnectImpl::OnConnectFailed, weak_factory_.GetWeakPtr(), network_id), - check_error_state); + check_error_state, ConnectCallbackMode::ON_COMPLETED); } void NetworkConnectImpl::OnActivateFailed(
diff --git a/chromeos/network/network_connection_handler.h b/chromeos/network/network_connection_handler.h index 625964a..f6fd03d 100644 --- a/chromeos/network/network_connection_handler.h +++ b/chromeos/network/network_connection_handler.h
@@ -37,6 +37,8 @@ // available State information, and NetworkConfigurationHandler for any // configuration calls. +enum class ConnectCallbackMode { ON_STARTED, ON_COMPLETED }; + class CHROMEOS_EXPORT NetworkConnectionHandler { public: // Constants for |error_name| from |error_callback| for Connect. @@ -86,7 +88,7 @@ // Certificate load timed out. static const char kErrorCertLoadTimeout[]; - // Trying to configure an unmanged network but policy prohibits that + // Trying to configure an unmanaged network but policy prohibits that static const char kErrorUnmanagedNetwork[]; // Network activation failed. @@ -131,18 +133,25 @@ void SetTetherDelegate(TetherDelegate* tether_delegate); // ConnectToNetwork() will start an asynchronous connection attempt. - // On success, |success_callback| will be called. - // On failure, |error_callback| will be called with |error_name| one of the - // constants defined above. + // |success_callback| will be called if the connection request succeeds + // or if a request is sent if |mode| is ON_STARTED (see below). + // |error_callback| will be called with |error_name| set to one of the + // constants defined above if the connection request fails. // |error_message| will contain an additional error string for debugging. // If |check_error_state| is true, the current state of the network is - // checked for errors, otherwise current state is ignored (e.g. for recently - // configured networks or repeat attempts). + // checked for errors, otherwise current state is ignored (e.g. for recently + // configured networks or repeat attempts). + // If |mode| is ON_STARTED, |success_callback| will be invoked when the + // connect request is successfully made and not when the connection + // completes. Note: This also prevents |error_callback| from being called + // if the connection request is successfully sent but the network does not + // connect. virtual void ConnectToNetwork( const std::string& service_path, const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback, - bool check_error_state) = 0; + bool check_error_state, + ConnectCallbackMode mode) = 0; // DisconnectNetwork() will send a Disconnect request to Shill. // On success, |success_callback| will be called.
diff --git a/chromeos/network/network_connection_handler_impl.cc b/chromeos/network/network_connection_handler_impl.cc index 080078c..73336cbc 100644 --- a/chromeos/network/network_connection_handler_impl.cc +++ b/chromeos/network/network_connection_handler_impl.cc
@@ -95,11 +95,13 @@ } // namespace NetworkConnectionHandlerImpl::ConnectRequest::ConnectRequest( + ConnectCallbackMode mode, const std::string& service_path, const std::string& profile_path, const base::Closure& success, const network_handler::ErrorCallback& error) - : service_path(service_path), + : mode(mode), + service_path(service_path), profile_path(profile_path), connect_state(CONNECT_REQUESTED), success_callback(success), @@ -181,7 +183,8 @@ const std::string& service_path, const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback, - bool check_error_state) { + bool check_error_state, + ConnectCallbackMode mode) { NET_LOG_USER("ConnectToNetwork", service_path); for (auto& observer : observers_) observer.ConnectToNetworkRequested(service_path); @@ -248,20 +251,26 @@ if (!network || network->profile_path().empty()) profile_path = GetDefaultUserProfilePath(network); - // All synchronous checks passed, add |service_path| to connecting list. - pending_requests_.emplace( - service_path, ConnectRequest(service_path, profile_path, success_callback, - error_callback)); + bool call_connect = false; // Connect immediately to 'connectable' networks. // TODO(stevenjb): Shill needs to properly set Connectable for VPN. if (network && network->connectable() && network->type() != shill::kTypeVPN) { if (IsNetworkProhibitedByPolicy(network->type(), network->guid(), network->profile_path())) { - ErrorCallbackForPendingRequest(service_path, kErrorUnmanagedNetwork); + InvokeConnectErrorCallback(service_path, error_callback, + kErrorUnmanagedNetwork); return; } + call_connect = true; + } + // All synchronous checks passed, add |service_path| to connecting list. + pending_requests_.emplace(service_path, + ConnectRequest(mode, service_path, profile_path, + success_callback, error_callback)); + + if (call_connect) { CallShillConnect(service_path); return; } @@ -565,9 +574,9 @@ } NET_LOG_EVENT("Connect Request Queued", service_path); - queued_connect_.reset(new ConnectRequest(service_path, request->profile_path, - request->success_callback, - request->error_callback)); + queued_connect_.reset( + new ConnectRequest(request->mode, service_path, request->profile_path, + request->success_callback, request->error_callback)); pending_requests_.erase(service_path); // Post a delayed task to check to see if certificates have loaded. If they @@ -607,7 +616,7 @@ NET_LOG_EVENT("Connecting to Queued Network", service_path); ConnectToNetwork(service_path, success_callback, error_callback, - false /* check_error_state */); + false /* check_error_state */, queued_connect_->mode); } void NetworkConnectionHandlerImpl::CallShillConnect( @@ -626,6 +635,7 @@ const std::string& service_path, const std::string& error_name, std::unique_ptr<base::DictionaryValue> error_data) { + NET_LOG(ERROR) << "Connect configuration failure: " << error_name; ConnectRequest* request = GetPendingRequest(service_path); if (!request) { NET_LOG_ERROR("HandleConfigurationFailure called with no pending request.", @@ -646,6 +656,14 @@ service_path); return; } + if (request->mode == ConnectCallbackMode::ON_STARTED) { + if (!request->success_callback.is_null()) + request->success_callback.Run(); + // Request started; do not invoke success or error callbacks on + // completion. + request->success_callback = base::Closure(); + request->error_callback = network_handler::ErrorCallback(); + } request->connect_state = ConnectRequest::CONNECT_STARTED; NET_LOG_EVENT("Connect Request Acknowledged", service_path); // Do not call success_callback here, wait for one of the following
diff --git a/chromeos/network/network_connection_handler_impl.h b/chromeos/network/network_connection_handler_impl.h index 4a18fbf..a348b82c 100644 --- a/chromeos/network/network_connection_handler_impl.h +++ b/chromeos/network/network_connection_handler_impl.h
@@ -29,7 +29,8 @@ void ConnectToNetwork(const std::string& service_path, const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback, - bool check_error_state) override; + bool check_error_state, + ConnectCallbackMode mode) override; void DisconnectNetwork( const std::string& service_path, const base::Closure& success_callback, @@ -56,7 +57,8 @@ private: struct ConnectRequest { - ConnectRequest(const std::string& service_path, + ConnectRequest(ConnectCallbackMode mode, + const std::string& service_path, const std::string& profile_path, const base::Closure& success, const network_handler::ErrorCallback& error); @@ -69,6 +71,7 @@ CONNECT_CONNECTING = 2 }; + ConnectCallbackMode mode; std::string service_path; std::string profile_path; ConnectState connect_state;
diff --git a/chromeos/network/network_connection_handler_impl_unittest.cc b/chromeos/network/network_connection_handler_impl_unittest.cc index 23953fa..be14b28e 100644 --- a/chromeos/network/network_connection_handler_impl_unittest.cc +++ b/chromeos/network/network_connection_handler_impl_unittest.cc
@@ -206,14 +206,13 @@ protected: void Connect(const std::string& service_path) { - const bool check_error_state = true; network_connection_handler_->ConnectToNetwork( service_path, base::Bind(&NetworkConnectionHandlerImplTest::SuccessCallback, base::Unretained(this)), base::Bind(&NetworkConnectionHandlerImplTest::ErrorCallback, base::Unretained(this)), - check_error_state); + true /* check_error_state */, ConnectCallbackMode::ON_COMPLETED); scoped_task_environment_.RunUntilIdle(); }
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc index d06da11..939dbaa 100644 --- a/chromeos/network/onc/onc_utils.cc +++ b/chromeos/network/onc/onc_utils.cc
@@ -906,10 +906,10 @@ const std::string& onc_scheme, base::DictionaryValue* dict) { const net::ProxyList* proxy_list = nullptr; - if (proxy_rules.type == net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY) { + if (proxy_rules.type == net::ProxyConfig::ProxyRules::Type::PROXY_LIST) { proxy_list = &proxy_rules.single_proxies; } else if (proxy_rules.type == - net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) { + net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME) { proxy_list = proxy_rules.MapUrlSchemeToProxyList(scheme); } if (!proxy_list || proxy_list->IsEmpty())
diff --git a/chromeos/network/proxy/proxy_config_service_impl.cc b/chromeos/network/proxy/proxy_config_service_impl.cc index 619231bc..082ba1b 100644 --- a/chromeos/network/proxy/proxy_config_service_impl.cc +++ b/chromeos/network/proxy/proxy_config_service_impl.cc
@@ -92,7 +92,7 @@ const net::ProxyConfig& config) { VLOG(1) << "Got prefs change: " << ProxyPrefs::ConfigStateToDebugString(config_state) - << ", mode=" << config.proxy_rules().type; + << ", mode=" << static_cast<int>(config.proxy_rules().type); DetermineEffectiveConfigFromDefaultNetwork(); } @@ -264,7 +264,7 @@ effective_config_state = ProxyPrefs::CONFIG_OTHER_PRECEDE; // If config is manual, add rule to bypass local host. if (effective_config.proxy_rules().type != - net::ProxyConfig::ProxyRules::TYPE_NO_RULES) { + net::ProxyConfig::ProxyRules::Type::EMPTY) { effective_config.proxy_rules().bypass_rules.AddRuleToBypassLocal(); } PrefProxyConfigTrackerImpl::OnProxyConfigChanged(effective_config_state,
diff --git a/chromeos/network/proxy/ui_proxy_config.cc b/chromeos/network/proxy/ui_proxy_config.cc index 8111f47..ddd4a1a 100644 --- a/chromeos/network/proxy/ui_proxy_config.cc +++ b/chromeos/network/proxy/ui_proxy_config.cc
@@ -57,7 +57,7 @@ *this = UIProxyConfig(); // Reset to default. const net::ProxyConfig::ProxyRules& rules = net_config.proxy_rules(); switch (rules.type) { - case net::ProxyConfig::ProxyRules::TYPE_NO_RULES: + case net::ProxyConfig::ProxyRules::Type::EMPTY: if (!net_config.HasAutomaticSettings()) { mode = UIProxyConfig::MODE_DIRECT; } else if (net_config.auto_detect()) { @@ -69,14 +69,14 @@ return false; } return true; - case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY: + case net::ProxyConfig::ProxyRules::Type::PROXY_LIST: if (rules.single_proxies.IsEmpty()) return false; mode = MODE_SINGLE_PROXY; single_proxy.server = rules.single_proxies.Get(); bypass_rules = rules.bypass_rules; return true; - case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME: + case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME: // Make sure we have valid server for at least one of the protocols. if (rules.proxies_for_http.IsEmpty() && rules.proxies_for_https.IsEmpty() &&
diff --git a/components/arc/net/arc_net_host_impl.cc b/components/arc/net/arc_net_host_impl.cc index 3848665a..c7aa02c 100644 --- a/components/arc/net/arc_net_host_impl.cc +++ b/components/arc/net/arc_net_host_impl.cc
@@ -638,7 +638,8 @@ base::AdaptCallbackForRepeating(std::move(callback)); GetNetworkConnectionHandler()->ConnectToNetwork( path, base::Bind(&StartConnectSuccessCallback, repeating_callback), - base::Bind(&StartConnectFailureCallback, repeating_callback), false); + base::Bind(&StartConnectFailureCallback, repeating_callback), + false /* check_error_state */, chromeos::ConnectCallbackMode::ON_STARTED); } void ArcNetHostImpl::StartDisconnect(const std::string& guid, @@ -806,7 +807,8 @@ GetNetworkConnectionHandler()->ConnectToNetwork( service_path, base::Bind(&ArcVpnSuccessCallback), - base::Bind(&ArcVpnErrorCallback), false /* check_error_state */); + base::Bind(&ArcVpnErrorCallback), false /* check_error_state */, + chromeos::ConnectCallbackMode::ON_COMPLETED); } std::unique_ptr<base::Value> ArcNetHostImpl::TranslateStringListToValue(
diff --git a/components/autofill/core/browser/autofill_scanner.h b/components/autofill/core/browser/autofill_scanner.h index 88b84e6f..0babe38a 100644 --- a/components/autofill/core/browser/autofill_scanner.h +++ b/components/autofill/core/browser/autofill_scanner.h
@@ -45,6 +45,9 @@ // |RewindTo()|. size_t SaveCursor(); + // This is only for logging purposes. + size_t CursorIndex() { return static_cast<size_t>(cursor_ - begin_); }; + private: void Init(const std::vector<AutofillField*>& fields);
diff --git a/components/autofill/core/browser/credit_card_field.cc b/components/autofill/core/browser/credit_card_field.cc index 3343e58..a0c484b 100644 --- a/components/autofill/core/browser/credit_card_field.cc +++ b/components/autofill/core/browser/credit_card_field.cc
@@ -88,6 +88,7 @@ // Using 'new' to access private constructor. auto credit_card_field = base::WrapUnique(new CreditCardField()); size_t saved_cursor = scanner->SaveCursor(); + int nb_unknown_fields = 0; // Credit card fields can appear in many different orders. // We loop until no more credit card related fields are found, see |break| at @@ -134,6 +135,7 @@ if (!credit_card_field->type_ && LikelyCardTypeSelectField(scanner)) { credit_card_field->type_ = scanner->Cursor(); scanner->Advance(); + nb_unknown_fields = 0; continue; } @@ -176,6 +178,7 @@ credit_card_field->verification_ = nullptr; } } else { + nb_unknown_fields = 0; continue; } } @@ -204,11 +207,14 @@ current_number_field->set_credit_card_number_offset(start_index); credit_card_field->numbers_.push_back(current_number_field); + nb_unknown_fields = 0; continue; } - if (credit_card_field->ParseExpirationDate(scanner)) + if (credit_card_field->ParseExpirationDate(scanner)) { + nb_unknown_fields = 0; continue; + } if (credit_card_field->expiration_month_ && !credit_card_field->expiration_year_ && @@ -218,6 +224,24 @@ return nullptr; } + nb_unknown_fields++; + + // Since cc#/verification and expiration are inter-dependent for the final + // detection decision, we allow for 4 UNKONWN fields in between. + // We can't allow for a lot of unknown fields, because the name on address + // sections may sometimes be mistakenly detected as cardholder name. + if ((credit_card_field->verification_ || + !credit_card_field->numbers_.empty() || + credit_card_field->HasExpiration()) && + (!credit_card_field->verification_ || + credit_card_field->numbers_.empty() || + !credit_card_field->HasExpiration()) && + nb_unknown_fields < 4) { + scanner->Advance(); + fields--; // We continue searching in the same credit card section, but + // no more field is identified. + continue; + } break; }
diff --git a/components/autofill/core/browser/form_field.h b/components/autofill/core/browser/form_field.h index 3ec73b4c..c721f4b 100644 --- a/components/autofill/core/browser/form_field.h +++ b/components/autofill/core/browser/form_field.h
@@ -74,9 +74,9 @@ // Parses the stream of fields in |scanner| with regular expression |pattern| // as specified in the |match_type| bit field (see |MatchType|). If |match| - // is non-NULL and the pattern matches, the matched field is returned. - // A |true| result is returned in the case of a successful match, false - // otherwise. + // is non-NULL and the pattern matches, |match| will be set to the matched + // field, and the scanner would advance by one step. A |true| result is + // returned in the case of a successful match, false otherwise. static bool ParseFieldSpecifics(AutofillScanner* scanner, const base::string16& pattern, int match_type,
diff --git a/components/component_updater/configurator_impl.cc b/components/component_updater/configurator_impl.cc index 07a0dcf..144d250 100644 --- a/components/component_updater/configurator_impl.cc +++ b/components/component_updater/configurator_impl.cc
@@ -81,12 +81,9 @@ } // namespace -ConfiguratorImpl::ConfiguratorImpl( - const base::CommandLine* cmdline, - net::URLRequestContextGetter* url_request_getter, - bool require_encryption) - : url_request_getter_(url_request_getter), - fast_update_(false), +ConfiguratorImpl::ConfiguratorImpl(const base::CommandLine* cmdline, + bool require_encryption) + : fast_update_(false), pings_enabled_(false), deltas_enabled_(false), background_downloads_enabled_(false), @@ -177,10 +174,6 @@ return std::string(); } -net::URLRequestContextGetter* ConfiguratorImpl::RequestContext() const { - return url_request_getter_; -} - bool ConfiguratorImpl::EnabledDeltas() const { return deltas_enabled_; }
diff --git a/components/component_updater/configurator_impl.h b/components/component_updater/configurator_impl.h index afc3d2d..bbe01352 100644 --- a/components/component_updater/configurator_impl.h +++ b/components/component_updater/configurator_impl.h
@@ -18,10 +18,6 @@ class Version; } -namespace net { -class URLRequestContextGetter; -} - namespace component_updater { // Helper class for the implementations of update_client::Configurator. @@ -29,7 +25,6 @@ class ConfiguratorImpl { public: ConfiguratorImpl(const base::CommandLine* cmdline, - net::URLRequestContextGetter* url_request_getter, bool require_encryption); ~ConfiguratorImpl(); @@ -71,9 +66,6 @@ // download urls are returned. std::string GetDownloadPreference() const; - // The source of contexts for all the url requests. - net::URLRequestContextGetter* RequestContext() const; - // True means that this client can handle delta updates. bool EnabledDeltas() const; @@ -91,7 +83,6 @@ std::vector<uint8_t> GetRunActionKeyHash() const; private: - net::URLRequestContextGetter* url_request_getter_; std::string extra_info_; GURL url_source_override_; bool fast_update_;
diff --git a/components/component_updater/configurator_impl_unittest.cc b/components/component_updater/configurator_impl_unittest.cc index 39b5f2f..35a41be 100644 --- a/components/component_updater/configurator_impl_unittest.cc +++ b/components/component_updater/configurator_impl_unittest.cc
@@ -32,8 +32,8 @@ TEST_F(ComponentUpdaterConfiguratorImplTest, FastUpdate) { // Test the default timing values when no command line argument is present. base::CommandLine cmdline(base::CommandLine::NO_PROGRAM); - std::unique_ptr<ConfiguratorImpl> config( - new ConfiguratorImpl(&cmdline, nullptr, false)); + std::unique_ptr<ConfiguratorImpl> config = + std::make_unique<ConfiguratorImpl>(&cmdline, false); CHECK_EQ(6 * kDelayOneMinute, config->InitialDelay()); CHECK_EQ(5 * kDelayOneHour, config->NextCheckDelay()); CHECK_EQ(30 * kDelayOneMinute, config->OnDemandDelay()); @@ -41,7 +41,7 @@ // Test the fast-update timings. cmdline.AppendSwitchASCII("--component-updater", "fast-update"); - config.reset(new ConfiguratorImpl(&cmdline, nullptr, false)); + config = std::make_unique<ConfiguratorImpl>(&cmdline, false); CHECK_EQ(10, config->InitialDelay()); CHECK_EQ(5 * kDelayOneHour, config->NextCheckDelay()); CHECK_EQ(2, config->OnDemandDelay());
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index 0a6ebfb..7dc920ad8 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -29,9 +29,14 @@ #include "net/nqe/network_quality_estimator_params.h" #include "net/quic/chromium/quic_utils_chromium.h" #include "net/quic/core/quic_packets.h" +#include "net/reporting/reporting_policy.h" #include "net/socket/ssl_client_socket.h" #include "net/url_request/url_request_context_builder.h" +#if BUILDFLAG(ENABLE_REPORTING) +#include "net/reporting/reporting_policy.h" +#endif // BUILDFLAG(ENABLE_REPORTING) + namespace cronet { namespace { @@ -105,6 +110,11 @@ // NetworkQualityEstimator (NQE) experiment dictionary name. const char kNetworkQualityEstimatorFieldTrialName[] = "NetworkQualityEstimator"; +// Network Error Logging experiment dictionary name. +const char kNetworkErrorLoggingFieldTrialName[] = "NetworkErrorLogging"; +// Name of boolean to enable Reporting API. +const char kNetworkErrorLoggingEnable[] = "enable"; + // Disable IPv6 when on WiFi. This is a workaround for a known issue on certain // Android phones, and should not be necessary when not on one of those devices. // See https://crbug.com/696569 for details. @@ -209,6 +219,7 @@ bool stale_dns_enable = false; bool host_resolver_rules_enable = false; bool disable_ipv6_on_wifi = false; + bool nel_enable = false; effective_experimental_options = dict->CreateDeepCopy(); StaleHostResolver::StaleOptions stale_dns_options; @@ -412,6 +423,15 @@ } host_resolver_rules_enable = host_resolver_rules_args->GetString( kHostResolverRules, &host_resolver_rules_string); + } else if (it.key() == kNetworkErrorLoggingFieldTrialName) { + const base::DictionaryValue* nel_args = nullptr; + if (!it.value().GetAsDictionary(&nel_args)) { + LOG(ERROR) << "\"" << it.key() << "\" config params \"" << it.value() + << "\" is not a dictionary value"; + effective_experimental_options->Remove(it.key(), nullptr); + continue; + } + nel_args->GetBoolean(kNetworkErrorLoggingEnable, &nel_enable); } else if (it.key() == kDisableIPv6OnWifi) { if (!it.value().GetAsBoolean(&disable_ipv6_on_wifi)) { LOG(ERROR) << "\"" << it.key() << "\" config params \"" << it.value() @@ -483,6 +503,23 @@ } context_builder->set_host_resolver(std::move(host_resolver)); } + +#if BUILDFLAG(ENABLE_REPORTING) + if (nel_enable) { + auto policy = std::make_unique<net::ReportingPolicy>(); + + // Apps (like Cronet embedders) are generally allowed to run in the + // background, even across network changes, so use more relaxed privacy + // settings than when Reporting is running in the browser. + policy->persist_reports_across_restarts = true; + policy->persist_clients_across_restarts = true; + policy->clear_reports_on_network_changes = false; + policy->clear_clients_on_network_changes = false; + + context_builder->set_reporting_policy(std::move(policy)); + context_builder->set_network_error_logging_enabled(true); + } +#endif // BUILDFLAG(ENABLE_REPORTING) } void URLRequestContextConfig::ConfigureURLRequestContextBuilder(
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc index 20f938c..39666e862 100644 --- a/components/cronet/url_request_context_config_unittest.cc +++ b/components/cronet/url_request_context_config_unittest.cc
@@ -52,6 +52,7 @@ "\"race_cert_verification\":true," "\"connection_options\":\"TIME,TBBR,REJ\"}," "\"AsyncDNS\":{\"enable\":true}," + "\"NetworkErrorLogging\":{\"enable\":true}," "\"UnknownOption\":{\"foo\":true}," "\"HostResolverRules\":{\"host_resolver_rules\":" "\"MAP * 127.0.0.1\"}," @@ -106,6 +107,13 @@ EXPECT_TRUE(context->host_resolver()->GetDnsConfigAsValue()); #endif // defined(ENABLE_BUILT_IN_DNS) +#if BUILDFLAG(ENABLE_REPORTING) + // Check Reporting and Network Error Logging are enabled (can be disabled at + // build time). + EXPECT_TRUE(context->reporting_service()); + EXPECT_TRUE(context->network_error_logging_delegate()); +#endif // BUILDFLAG(ENABLE_REPORTING) + // Check IPv6 is disabled when on wifi. EXPECT_TRUE(context->host_resolver()->GetNoIPv6OnWifi());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc index 24dacd2..5e2dfd4 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -306,8 +306,8 @@ const net::ProxyConfig::ProxyRules& proxy_rules, bool is_https, base::TimeDelta* min_retry_delay) const { - // Data reduction proxy config is TYPE_PROXY_PER_SCHEME. - if (proxy_rules.type != net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) + // Data reduction proxy config is Type::PROXY_LIST_PER_SCHEME. + if (proxy_rules.type != net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME) return false; if (is_https) @@ -363,8 +363,8 @@ bool DataReductionProxyConfig::ContainsDataReductionProxy( const net::ProxyConfig::ProxyRules& proxy_rules) const { DCHECK(thread_checker_.CalledOnValidThread()); - // Data Reduction Proxy configurations are always TYPE_PROXY_PER_SCHEME. - if (proxy_rules.type != net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME) + // Data Reduction Proxy configurations are always Type::PROXY_LIST_PER_SCHEME. + if (proxy_rules.type != net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME) return false; const net::ProxyList* http_proxy_list =
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc index 474ea79..105d17d 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc
@@ -53,7 +53,7 @@ net::ProxyConfig config; DCHECK(!config.is_valid() && config.proxy_rules().proxies_for_http.IsEmpty()); config.proxy_rules().type = - net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; for (const auto& http_proxy : proxies_for_http) { // If the config is being generated for fetching the probe URL, then the
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc index aff0df53..836f478f 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
@@ -75,7 +75,7 @@ const net::ProxyConfig::ProxyRules& rules = config_->GetProxyConfig().proxy_rules(); ASSERT_EQ(expected_rules_type, rules.type); - if (net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME == + if (net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME == expected_rules_type) { ASSERT_EQ(expected_http_proxies, rules.proxies_for_http.ToPacString()); ASSERT_EQ(std::string(), rules.proxies_for_https.ToPacString()); @@ -95,7 +95,7 @@ ->CreateProxyConfig(probe_url_config, *manager_.get(), http_proxies) .proxy_rules(); ASSERT_EQ(expected_rules_type, rules.type); - if (net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME == + if (net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME == expected_rules_type) { ASSERT_EQ(expected_http_proxies, rules.proxies_for_http.ToPacString()); ASSERT_EQ(std::string(), rules.proxies_for_https.ToPacString()); @@ -114,7 +114,7 @@ config_->Enable(*manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT", std::string()); } @@ -123,7 +123,7 @@ config_->Enable(*manager_, BuildProxyList("quic://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "QUIC www.foo.com:443;PROXY www.bar.com:80;DIRECT", std::string()); } @@ -133,7 +133,7 @@ config_->Enable(*manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT", "<local>;*.goo.com;"); } @@ -143,7 +143,7 @@ config_->Enable(*manager_, BuildProxyList("quic://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "QUIC www.foo.com:443;PROXY www.bar.com:80;DIRECT", "<local>;*.goo.com;"); } @@ -152,7 +152,7 @@ config_->Enable(*manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, std::string(), ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "HTTPS www.foo.com:443;DIRECT", std::string()); } @@ -161,7 +161,7 @@ config_->Enable(*manager_, BuildProxyList("quic://www.foo.com:443", ProxyServer::CORE, std::string(), ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "QUIC www.foo.com:443;DIRECT", std::string()); } @@ -170,7 +170,7 @@ config_->Enable(*manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "PROXY www.bar.com:80;DIRECT", std::string()); } @@ -179,7 +179,7 @@ config_->Enable(*manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT", std::string()); } @@ -191,7 +191,7 @@ *manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::UNSPECIFIED_TYPE, "http://www.bar.com:80", ProxyServer::UNSPECIFIED_TYPE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT", std::string()); } @@ -201,7 +201,7 @@ config_->Enable(*manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "HTTPS www.foo.com:443;DIRECT", std::string()); } @@ -210,7 +210,7 @@ config_->Enable(*manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT", std::string()); } @@ -221,7 +221,7 @@ config_->Enable(*manager_, BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, "", + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "", std::string()); } @@ -230,7 +230,7 @@ config_->Enable(*manager_, BuildProxyList("quic://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "PROXY www.bar.com:80;DIRECT", std::string()); } @@ -239,7 +239,7 @@ BuildProxyList("https://www.foo.com:443", ProxyServer::CORE, "http://www.bar.com:80", ProxyServer::CORE)); config_->Disable(); - CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_NO_RULES, std::string(), + CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::EMPTY, std::string(), std::string()); } @@ -263,11 +263,11 @@ "http://www.bar.com:80", ProxyServer::CORE); config_->Enable(*manager_, http_proxies); CheckProbeProxyConfig(http_proxies, true /* probe_url_config */, - net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT", std::string()); CheckProbeProxyConfig(http_proxies, false /* probe_url_config */, - net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, "", + net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "", std::string()); }
diff --git a/components/download/internal/blob_task_proxy.cc b/components/download/internal/blob_task_proxy.cc index 1348f13..b641414 100644 --- a/components/download/internal/blob_task_proxy.cc +++ b/components/download/internal/blob_task_proxy.cc
@@ -59,9 +59,10 @@ // Build blob data. std::string blob_uuid = base::GenerateGUID(); - storage::BlobDataBuilder builder(blob_uuid); - builder.AppendData(*data.get()); - blob_data_handle_ = blob_storage_context_->AddFinishedBlob(builder); + auto builder = std::make_unique<storage::BlobDataBuilder>(blob_uuid); + builder->AppendData(*data.get()); + blob_data_handle_ = + blob_storage_context_->AddFinishedBlob(std::move(builder)); // Wait for blob data construction complete. auto cb = base::BindRepeating(&BlobTaskProxy::BlobSavedOnIO,
diff --git a/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc b/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc index b0fd3b5..3dbaba5 100644 --- a/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc +++ b/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc
@@ -126,7 +126,7 @@ EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, proxy_config_service_->GetLatestProxyConfig(&actual_config)); EXPECT_FALSE(actual_config.auto_detect()); - EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, + EXPECT_EQ(net::ProxyConfig::ProxyRules::Type::PROXY_LIST, actual_config.proxy_rules().type); EXPECT_EQ(actual_config.proxy_rules().single_proxies.Get(), net::ProxyServer::FromURI("http://example.com:3128",
diff --git a/components/subresource_filter/content/browser/content_ruleset_service.cc b/components/subresource_filter/content/browser/content_ruleset_service.cc index f9d1c334..90c4fe1 100644 --- a/components/subresource_filter/content/browser/content_ruleset_service.cc +++ b/components/subresource_filter/content/browser/content_ruleset_service.cc
@@ -105,6 +105,11 @@ unindexed_ruleset_info); } +void ContentRulesetService::SetIsAfterStartupForTesting() { + DCHECK(ruleset_service_); + ruleset_service_->set_is_after_startup_for_testing(); +} + void ContentRulesetService::Observe( int type, const content::NotificationSource& source,
diff --git a/components/subresource_filter/content/browser/content_ruleset_service.h b/components/subresource_filter/content/browser/content_ruleset_service.h index 97c049e14..e3cc43f1 100644 --- a/components/subresource_filter/content/browser/content_ruleset_service.h +++ b/components/subresource_filter/content/browser/content_ruleset_service.h
@@ -77,6 +77,8 @@ return ruleset_dealer_.get(); } + void SetIsAfterStartupForTesting(); + private: // content::NotificationObserver: void Observe(int type,
diff --git a/components/subresource_filter/core/browser/ruleset_service.h b/components/subresource_filter/core/browser/ruleset_service.h index ef84c0ca..51e12321 100644 --- a/components/subresource_filter/core/browser/ruleset_service.h +++ b/components/subresource_filter/core/browser/ruleset_service.h
@@ -187,6 +187,8 @@ virtual void IndexAndStoreAndPublishRulesetIfNeeded( const UnindexedRulesetInfo& unindexed_ruleset_info); + void set_is_after_startup_for_testing() { is_after_startup_ = true; } + private: friend class SubresourceFilteringRulesetServiceTest; FRIEND_TEST_ALL_PREFIXES(SubresourceFilteringRulesetServiceTest,
diff --git a/components/test/data/autofill/heuristics/output/135_bug_471831.out b/components/test/data/autofill/heuristics/output/135_bug_471831.out index 41513e4..dda54f7 100644 --- a/components/test/data/autofill/heuristics/output/135_bug_471831.out +++ b/components/test/data/autofill/heuristics/output/135_bug_471831.out
@@ -3,5 +3,5 @@ CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR | cc-exp | MM / YY | | credit-card-cc UNKNOWN_TYPE | cc-exp-year | CardBitcoin | Year | email_1-default UNKNOWN_TYPE | cc-exp-month | CardBitcoin | Month | email_1-default -UNKNOWN_TYPE | cc-csc | CVC | | email_1-default +CREDIT_CARD_VERIFICATION_CODE | cc-csc | CVC | | credit-card-cc PHONE_HOME_WHOLE_NUMBER | phone | (555) 123-1234 | | email_1-default
diff --git a/components/test/data/autofill/heuristics/output/141_checkout_cc_keurig.com.out b/components/test/data/autofill/heuristics/output/141_checkout_cc_keurig.com.out index ebe0ca1..feea886 100644 --- a/components/test/data/autofill/heuristics/output/141_checkout_cc_keurig.com.out +++ b/components/test/data/autofill/heuristics/output/141_checkout_cc_keurig.com.out
@@ -3,8 +3,8 @@ CREDIT_CARD_NUMBER | card_accountNumber | Card Number* | | credit-card-cc CREDIT_CARD_TYPE | card_cardType | Card Type | | credit-card-cc UNKNOWN_TYPE | | Please select a card type | | card_firstNameOnCard_1-default -UNKNOWN_TYPE | card_expirationMonth | Expiration Date* | | card_firstNameOnCard_1-default +CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR | card_expirationMonth | Expiration Date* | | credit-card-cc UNKNOWN_TYPE | | Month | | card_firstNameOnCard_1-default -CREDIT_CARD_EXP_MONTH | card_expirationYear | Expiration Date* | | credit-card-cc -CREDIT_CARD_EXP_4_DIGIT_YEAR | | Year | | credit-card-cc +UNKNOWN_TYPE | card_expirationYear | Expiration Date* | | card_firstNameOnCard_1-default +UNKNOWN_TYPE | | Year | | card_firstNameOnCard_1-default CREDIT_CARD_VERIFICATION_CODE | card_cvNumber | Security Code* | | credit-card-cc
diff --git a/components/update_client/configurator.h b/components/update_client/configurator.h index fd29c79c..2d08795 100644 --- a/components/update_client/configurator.h +++ b/components/update_client/configurator.h
@@ -10,6 +10,7 @@ #include <vector> #include "base/memory/ref_counted.h" +#include "net/url_request/url_request_context_getter.h" class GURL; class PrefService; @@ -18,10 +19,6 @@ class Version; } -namespace net { -class URLRequestContextGetter; -} - namespace service_manager { class Connector; } @@ -96,7 +93,8 @@ virtual std::string GetDownloadPreference() const = 0; // The source of contexts for all the url requests. - virtual net::URLRequestContextGetter* RequestContext() const = 0; + virtual scoped_refptr<net::URLRequestContextGetter> RequestContext() + const = 0; // Returns a new connector to the service manager. That connector is not bound // to any thread yet.
diff --git a/components/update_client/crx_downloader.cc b/components/update_client/crx_downloader.cc index 02d898c3..806b90f 100644 --- a/components/update_client/crx_downloader.cc +++ b/components/update_client/crx_downloader.cc
@@ -22,6 +22,7 @@ #include "components/update_client/update_client_errors.h" #include "components/update_client/url_fetcher_downloader.h" #include "components/update_client/utils.h" +#include "net/url_request/url_request_context_getter.h" namespace update_client { @@ -41,7 +42,7 @@ // which uses the BITS service. std::unique_ptr<CrxDownloader> CrxDownloader::Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { std::unique_ptr<CrxDownloader> url_fetcher_downloader = std::make_unique<UrlFetcherDownloader>(nullptr, context_getter);
diff --git a/components/update_client/crx_downloader.h b/components/update_client/crx_downloader.h index 544a915..eab6741 100644 --- a/components/update_client/crx_downloader.h +++ b/components/update_client/crx_downloader.h
@@ -86,8 +86,9 @@ // bytes is not guaranteed to monotonically increment over time. using ProgressCallback = base::Callback<void(const Result& result)>; - using Factory = - std::unique_ptr<CrxDownloader> (*)(bool, net::URLRequestContextGetter*); + using Factory = std::unique_ptr<CrxDownloader> (*)( + bool, + scoped_refptr<net::URLRequestContextGetter>); // Factory method to create an instance of this class and build the // chain of responsibility. |is_background_download| specifies that a @@ -96,7 +97,7 @@ // code such as file IO operations. static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter); + scoped_refptr<net::URLRequestContextGetter> context_getter); virtual ~CrxDownloader(); void set_progress_callback(const ProgressCallback& progress_callback);
diff --git a/components/update_client/test_configurator.cc b/components/update_client/test_configurator.cc index 2543c15..2fde1dd5 100644 --- a/components/update_client/test_configurator.cc +++ b/components/update_client/test_configurator.cc
@@ -109,8 +109,9 @@ return download_preference_; } -net::URLRequestContextGetter* TestConfigurator::RequestContext() const { - return context_.get(); +scoped_refptr<net::URLRequestContextGetter> TestConfigurator::RequestContext() + const { + return context_; } std::unique_ptr<service_manager::Connector>
diff --git a/components/update_client/test_configurator.h b/components/update_client/test_configurator.h index f911b5b..9d12aa6 100644 --- a/components/update_client/test_configurator.h +++ b/components/update_client/test_configurator.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <memory> #include <string> #include <utility> #include <vector> @@ -43,7 +44,7 @@ 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4, 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40}; // component 1 public key (base64 encoded): -const std::string jebg_public_key = +const char jebg_public_key[] = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68bW8i/RzSaeXOcNLuBw0SP9+1bdo5ysLqH" "qfLqZs6XyJWEyL0U6f1axPR6LwViku21kgdc6PI524eb8Cr+a/iXGgZ8SdvZTcfQ/g/ukwlblF" "mtqYfDoVpz03U8rDQ9b6DxeJBF4r48TNlFORggrAiNR26qbf1i178Au12AzWtwIDAQAB"; @@ -85,7 +86,7 @@ std::string GetOSLongName() const override; std::string ExtraRequestParams() const override; std::string GetDownloadPreference() const override; - net::URLRequestContextGetter* RequestContext() const override; + scoped_refptr<net::URLRequestContextGetter> RequestContext() const override; std::unique_ptr<service_manager::Connector> CreateServiceManagerConnector() const override; bool EnabledDeltas() const override;
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc index 3c23319..f0a6278 100644 --- a/components/update_client/update_client_unittest.cc +++ b/components/update_client/update_client_unittest.cc
@@ -268,7 +268,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -427,7 +427,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -659,7 +659,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -924,7 +924,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -1206,7 +1206,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -1474,7 +1474,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -1720,7 +1720,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -1935,7 +1935,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -2078,7 +2078,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -2238,7 +2238,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -2323,7 +2323,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -2372,7 +2372,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return nullptr; } @@ -2497,7 +2497,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -2734,7 +2734,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -2898,7 +2898,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -3019,7 +3019,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); } @@ -3161,7 +3161,7 @@ public: static std::unique_ptr<CrxDownloader> Create( bool is_background_download, - net::URLRequestContextGetter* context_getter) { + scoped_refptr<net::URLRequestContextGetter> context_getter) { return std::make_unique<FakeCrxDownloader>(); }
diff --git a/components/update_client/url_fetcher_downloader.cc b/components/update_client/url_fetcher_downloader.cc index 77dd764..2d0d4d1 100644 --- a/components/update_client/url_fetcher_downloader.cc +++ b/components/update_client/url_fetcher_downloader.cc
@@ -20,6 +20,7 @@ #include "net/base/load_flags.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher.h" +#include "net/url_request/url_request_context_getter.h" #include "url/gurl.h" namespace { @@ -54,7 +55,7 @@ UrlFetcherDownloader::UrlFetcherDownloader( std::unique_ptr<CrxDownloader> successor, - net::URLRequestContextGetter* context_getter) + scoped_refptr<net::URLRequestContextGetter> context_getter) : CrxDownloader(std::move(successor)), delegate_(std::make_unique<URLFetcherDelegate>(this)), context_getter_(context_getter) {} @@ -137,7 +138,7 @@ url_fetcher_ = net::URLFetcher::Create(0, url, net::URLFetcher::GET, delegate_.get(), traffic_annotation); - url_fetcher_->SetRequestContext(context_getter_); + url_fetcher_->SetRequestContext(context_getter_.get()); url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DISABLE_CACHE);
diff --git a/components/update_client/url_fetcher_downloader.h b/components/update_client/url_fetcher_downloader.h index 2241adc8..442cbf2 100644 --- a/components/update_client/url_fetcher_downloader.h +++ b/components/update_client/url_fetcher_downloader.h
@@ -27,8 +27,9 @@ // Implements a CRX downloader in top of the URLFetcher. class UrlFetcherDownloader : public CrxDownloader { public: - UrlFetcherDownloader(std::unique_ptr<CrxDownloader> successor, - net::URLRequestContextGetter* context_getter); + UrlFetcherDownloader( + std::unique_ptr<CrxDownloader> successor, + scoped_refptr<net::URLRequestContextGetter> context_getter); ~UrlFetcherDownloader() override; private: @@ -65,7 +66,7 @@ std::unique_ptr<URLFetcherDelegate> delegate_; std::unique_ptr<net::URLFetcher> url_fetcher_; - net::URLRequestContextGetter* context_getter_ = nullptr; + scoped_refptr<net::URLRequestContextGetter> context_getter_; // Contains a temporary download directory for the downloaded file. base::FilePath download_dir_;
diff --git a/components/update_client/utils.cc b/components/update_client/utils.cc index c200deff..4e7b8c6e 100644 --- a/components/update_client/utils.cc +++ b/components/update_client/utils.cc
@@ -42,7 +42,7 @@ const GURL& url, const std::string& protocol_request, net::URLFetcherDelegate* url_fetcher_delegate, - net::URLRequestContextGetter* url_request_context_getter) { + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) { net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("component_updater_utils", R"( semantics { @@ -79,7 +79,7 @@ data_use_measurement::DataUseUserData::AttachToFetcher( url_fetcher.get(), data_use_measurement::DataUseUserData::UPDATE_CLIENT); url_fetcher->SetUploadData("application/xml", protocol_request); - url_fetcher->SetRequestContext(url_request_context_getter); + url_fetcher->SetRequestContext(url_request_context_getter.get()); url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DISABLE_CACHE);
diff --git a/components/update_client/utils.h b/components/update_client/utils.h index 30f6edd..8feb7dd 100644 --- a/components/update_client/utils.h +++ b/components/update_client/utils.h
@@ -11,6 +11,7 @@ #include <vector> #include "base/callback_forward.h" +#include "base/memory/ref_counted.h" #include "components/update_client/update_client.h" class GURL; @@ -43,7 +44,7 @@ const GURL& url, const std::string& protocol_request, net::URLFetcherDelegate* url_fetcher_delegate, - net::URLRequestContextGetter* url_request_context_getter); + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter); // Returns true if the url request of |fetcher| was succesful. bool FetchSuccess(const net::URLFetcher& fetcher);
diff --git a/components/viz/common/gpu/raster_context_provider.h b/components/viz/common/gpu/raster_context_provider.h index e46927c..01487b2 100644 --- a/components/viz/common/gpu/raster_context_provider.h +++ b/components/viz/common/gpu/raster_context_provider.h
@@ -74,6 +74,8 @@ // Returns the lock that should be held if using this context from multiple // threads. This can be called on any thread. + // Returns null if the context does not support locking and must be used from + // the same thread. // NOTE: Helper method for ScopedContextLock. Use that instead of calling this // directly. virtual base::Lock* GetLock() = 0;
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc index 65df0a2..fead1e77 100644 --- a/components/viz/service/display/software_renderer.cc +++ b/components/viz/service/display/software_renderer.cc
@@ -31,7 +31,7 @@ #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkShader.h" -#include "third_party/skia/include/effects/SkLayerRasterizer.h" +#include "third_party/skia/include/effects/SkShaderMaskFilter.h" #include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/skia_util.h" @@ -497,15 +497,9 @@ SkMatrix mask_mat; mask_mat.setRectToRect(mask_rect, dest_rect, SkMatrix::kFill_ScaleToFit); - SkPaint mask_paint; - mask_paint.setShader( + current_paint_.setMaskFilter(SkShaderMaskFilter::Make( SkShader::MakeBitmapShader(*mask, SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode, &mask_mat)); - - SkLayerRasterizer::Builder builder; - builder.addLayer(mask_paint); - - current_paint_.setRasterizer(builder.detach()); + SkShader::kClamp_TileMode, &mask_mat))); } // If we have a background filter shader, render its results first. @@ -514,7 +508,7 @@ if (background_filter_shader) { SkPaint paint; paint.setShader(std::move(background_filter_shader)); - paint.setRasterizer(current_paint_.refRasterizer()); + paint.setMaskFilter(current_paint_.refMaskFilter()); current_canvas_->drawRect(dest_visible_rect, paint); } current_paint_.setShader(std::move(shader));
diff --git a/content/app/strings/content_strings.grd b/content/app/strings/content_strings.grd index dba7a20..c946d09 100644 --- a/content/app/strings/content_strings.grd +++ b/content/app/strings/content_strings.grd
@@ -812,6 +812,9 @@ <message name="IDS_MEDIA_OVERFLOW_MENU_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a picture in picture button."> Picture in Picture </message> + <message name="IDS_MEDIA_PICTURE_IN_PICTURE_INTERSTITIAL_TEXT" desc="Text message shown to user when in picture in picture mode. When a video is in picture in picture mode, an interstitial with this text appears where the video player is positioned. The video continues to play back in another window that gives the experience that the video is 'popped out'."> + Now in picture in picture mode + </message> <message name="IDS_MEDIA_REMOTING_CAST_TEXT" desc="Text message shown to the user when casting a video to a known remote device."> Now casting to <ph name="DEVICE_FRIENDLY_NAME">$1<ex>Living Room TV</ex></ph> </message>
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc index 1745011e..01fb9b4 100644 --- a/content/browser/background_fetch/background_fetch_data_manager.cc +++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -366,14 +366,15 @@ DCHECK(!request->GetFilePath().empty()); DCHECK(blob_storage_context_); - storage::BlobDataBuilder blob_builder(base::GenerateGUID()); - blob_builder.AppendFile(request->GetFilePath(), 0 /* offset */, - request->GetFileSize(), - base::Time() /* expected_modification_time */); + auto blob_builder = + std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID()); + blob_builder->AppendFile(request->GetFilePath(), 0 /* offset */, + request->GetFileSize(), + base::Time() /* expected_modification_time */); auto blob_data_handle = GetBlobStorageContext(blob_storage_context_.get()) - ->AddFinishedBlob(&blob_builder); + ->AddFinishedBlob(std::move(blob_builder)); // TODO(peter): Appropriately handle !blob_data_handle if (blob_data_handle) {
diff --git a/content/browser/blob_storage/blob_url_unittest.cc b/content/browser/blob_storage/blob_url_unittest.cc index f0ae816..6f8c76a 100644 --- a/content/browser/blob_storage/blob_url_unittest.cc +++ b/content/browser/blob_storage/blob_url_unittest.cc
@@ -153,6 +153,7 @@ BlobURLRequestJobTest() : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), blob_data_(new BlobDataBuilder("uuid")), + blob_uuid_(blob_data_->uuid()), response_error_code_(net::OK), expected_status_code_(0) {} @@ -272,7 +273,7 @@ if (GetParam()) { GetHandleFromBuilder(); // To add to StorageContext. const_cast<storage::BlobStorageRegistry&>(blob_context_.registry()) - .CreateUrlMapping(url, blob_data_->uuid()); + .CreateUrlMapping(url, blob_uuid_); network::ResourceRequest request; request.url = url; request.method = method; @@ -358,7 +359,7 @@ storage::BlobDataHandle* GetHandleFromBuilder() { if (!blob_handle_) { - blob_handle_ = blob_context_.AddFinishedBlob(blob_data_.get()); + blob_handle_ = blob_context_.AddFinishedBlob(std::move(blob_data_)); } return blob_handle_.get(); } @@ -403,6 +404,7 @@ storage::BlobStorageContext blob_context_; std::unique_ptr<storage::BlobDataHandle> blob_handle_; std::unique_ptr<BlobDataBuilder> blob_data_; + std::string blob_uuid_; std::unique_ptr<BlobDataSnapshot> blob_data_snapshot_; net::URLRequestJobFactoryImpl url_request_job_factory_; net::URLRequestContext url_request_context_;
diff --git a/content/browser/blob_storage/chrome_blob_storage_context.cc b/content/browser/blob_storage/chrome_blob_storage_context.cc index 0478c2f..b4df994 100644 --- a/content/browser/blob_storage/chrome_blob_storage_context.cc +++ b/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -148,12 +148,12 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); std::string uuid(base::GenerateGUID()); - storage::BlobDataBuilder blob_data_builder(uuid); - blob_data_builder.set_content_type(content_type); - blob_data_builder.AppendData(data, length); + auto blob_data_builder = std::make_unique<storage::BlobDataBuilder>(uuid); + blob_data_builder->set_content_type(content_type); + blob_data_builder->AppendData(data, length); std::unique_ptr<storage::BlobDataHandle> blob_data_handle = - context_->AddFinishedBlob(&blob_data_builder); + context_->AddFinishedBlob(std::move(blob_data_builder)); if (!blob_data_handle) return std::unique_ptr<BlobHandle>(); @@ -170,11 +170,11 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); std::string uuid(base::GenerateGUID()); - storage::BlobDataBuilder blob_data_builder(uuid); - blob_data_builder.AppendFile(path, offset, size, expected_modification_time); + auto blob_data_builder = std::make_unique<storage::BlobDataBuilder>(uuid); + blob_data_builder->AppendFile(path, offset, size, expected_modification_time); std::unique_ptr<storage::BlobDataHandle> blob_data_handle = - context_->AddFinishedBlob(&blob_data_builder); + context_->AddFinishedBlob(std::move(blob_data_builder)); if (!blob_data_handle) return std::unique_ptr<BlobHandle>();
diff --git a/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc b/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc index 4eaf403f..e6fe660 100644 --- a/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc +++ b/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
@@ -129,11 +129,10 @@ } void InitBlob() { - std::unique_ptr<storage::BlobDataBuilder> blob_data( - new storage::BlobDataBuilder("blob-id:myblob")); + auto blob_data = + std::make_unique<storage::BlobDataBuilder>("blob-id:myblob"); blob_data->AppendData(data_); - - blob_handle_ = blob_storage_context_->AddFinishedBlob(blob_data.get()); + blob_handle_ = blob_storage_context_->AddFinishedBlob(std::move(blob_data)); } void InitCache() {
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index a85f7b62..5b09c8f 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -1865,13 +1865,14 @@ // Create a blob with the response body data. response->blob_size = entry->GetDataSize(INDEX_RESPONSE_BODY); response->blob_uuid = base::GenerateGUID(); - storage::BlobDataBuilder blob_data(response->blob_uuid); + auto blob_data = + std::make_unique<storage::BlobDataBuilder>(response->blob_uuid); disk_cache::Entry* temp_entry = entry.get(); - blob_data.AppendDiskCacheEntryWithSideData( + blob_data->AppendDiskCacheEntryWithSideData( new CacheStorageCacheDataHandle(CreateCacheHandle(), std::move(entry)), temp_entry, INDEX_RESPONSE_BODY, INDEX_SIDE_DATA); - auto result = blob_storage_context_->AddFinishedBlob(&blob_data); + auto result = blob_storage_context_->AddFinishedBlob(std::move(blob_data)); blink::mojom::BlobPtr blob_ptr; storage::BlobImpl::Create(std::make_unique<storage::BlobDataHandle>(*result),
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc index daef918..84db5127 100644 --- a/content/browser/cache_storage/cache_storage_cache_unittest.cc +++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -484,7 +484,7 @@ std::unique_ptr<storage::BlobDataBuilder> builder = std::make_unique<storage::BlobDataBuilder>(uuid); builder->AppendData(data); - return blob_storage_context_->AddFinishedBlob(builder.get()); + return blob_storage_context_->AddFinishedBlob(std::move(builder)); } void CopySideDataToResponse(storage::BlobDataHandle* side_data_blob_handle,
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc index 2f0bef7..513ff3ce 100644 --- a/content/browser/cache_storage/cache_storage_manager_unittest.cc +++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -412,7 +412,7 @@ blob_data->AppendData(request.url.spec()); std::unique_ptr<storage::BlobDataHandle> blob_data_handle = - blob_storage_context_->AddFinishedBlob(blob_data.get()); + blob_storage_context_->AddFinishedBlob(std::move(blob_data)); scoped_refptr<storage::BlobHandle> blob_handle; blink::mojom::BlobPtr blob;
diff --git a/content/browser/child_process_launcher_helper_mac.cc b/content/browser/child_process_launcher_helper_mac.cc index ee448dbe..fe69395 100644 --- a/content/browser/child_process_launcher_helper_mac.cc +++ b/content/browser/child_process_launcher_helper_mac.cc
@@ -80,7 +80,6 @@ case service_manager::SANDBOX_TYPE_NACL_LOADER: case service_manager::SANDBOX_TYPE_PDF_COMPOSITOR: case service_manager::SANDBOX_TYPE_PROFILING: - case service_manager::SANDBOX_TYPE_GPU: v2_process = true; break; default:
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index 3e22c67..71ccf4a5 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -300,23 +300,29 @@ return Response::FallThrough(); } -Response PageHandler::Reload(Maybe<bool> bypassCache, - Maybe<std::string> script_to_evaluate_on_load) { +void PageHandler::Reload(Maybe<bool> bypassCache, + Maybe<std::string> script_to_evaluate_on_load, + std::unique_ptr<ReloadCallback> callback) { WebContentsImpl* web_contents = GetWebContents(); - if (!web_contents) - return Response::InternalError(); + if (!web_contents) { + callback->sendFailure(Response::InternalError()); + return; + } if (web_contents->IsCrashed() || web_contents->GetURL().scheme() == url::kDataScheme || (web_contents->GetController().GetVisibleEntry() && - web_contents->GetController().GetVisibleEntry()->IsViewSourceMode())) { + web_contents->GetController().GetVisibleEntry()->IsViewSourceMode()) || + !script_to_evaluate_on_load.isJust()) { + if (reload_callback_) + reload_callback_->sendSuccess(); + reload_callback_ = std::move(callback); web_contents->GetController().Reload(bypassCache.fromMaybe(false) ? ReloadType::BYPASSING_CACHE : ReloadType::NORMAL, - false); - return Response::OK(); + true); } else { // Handle reload in renderer except for crashed and view source mode. - return Response::FallThrough(); + callback->fallThrough(); } } @@ -382,9 +388,16 @@ } void PageHandler::NavigationReset(NavigationRequest* navigation_request) { + WebContentsImpl* web_contents = GetWebContents(); + if (reload_callback_) { + if (!web_contents) + reload_callback_->sendFailure(Response::InternalError()); + else + reload_callback_->sendSuccess(); + reload_callback_.reset(); + } if (!navigate_callback_) return; - WebContentsImpl* web_contents = GetWebContents(); if (!web_contents) { navigate_callback_->sendFailure(Response::InternalError()); return;
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h index 3ffdea9f..7337c7f 100644 --- a/content/browser/devtools/protocol/page_handler.h +++ b/content/browser/devtools/protocol/page_handler.h
@@ -85,8 +85,9 @@ Response Disable() override; Response Crash() override; - Response Reload(Maybe<bool> bypassCache, - Maybe<std::string> script_to_evaluate_on_load) override; + void Reload(Maybe<bool> bypassCache, + Maybe<std::string> script_to_evaluate_on_load, + std::unique_ptr<ReloadCallback>) override; void Navigate(const std::string& url, Maybe<std::string> referrer, Maybe<std::string> transition_type, @@ -195,6 +196,7 @@ JavaScriptDialogCallback pending_dialog_; scoped_refptr<DevToolsDownloadManagerDelegate> download_manager_delegate_; std::unique_ptr<NavigateCallback> navigate_callback_; + std::unique_ptr<ReloadCallback> reload_callback_; base::WeakPtrFactory<PageHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(PageHandler);
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index ada8d21..86a7f81 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -50,7 +50,7 @@ "startScreencast", "stopScreencast", "screencastFrameAck", "handleJavaScriptDialog", "setColorPickerEnabled", "requestAppBanner", "printToPDF", "bringToFront", "setDownloadBehavior", "getAppManifest", "crash"], "include_events": ["colorPicked", "interstitialShown", "interstitialHidden", "javascriptDialogOpening", "javascriptDialogClosed", "screencastVisibilityChanged", "screencastFrame"], - "async": ["captureScreenshot", "printToPDF", "navigate", "getAppManifest"] + "async": ["captureScreenshot", "printToPDF", "reload", "navigate", "getAppManifest"] }, { "domain": "Runtime",
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc index 2ca8d1219..fb97ac4 100644 --- a/content/browser/gpu/gpu_data_manager_impl.cc +++ b/content/browser/gpu/gpu_data_manager_impl.cc
@@ -84,13 +84,6 @@ private_->UnblockDomainFrom3DAPIs(url); } -void GpuDataManagerImpl::SetGLStrings(const std::string& gl_vendor, - const std::string& gl_renderer, - const std::string& gl_version) { - base::AutoLock auto_lock(lock_); - private_->SetGLStrings(gl_vendor, gl_renderer, gl_version); -} - void GpuDataManagerImpl::DisableHardwareAcceleration() { base::AutoLock auto_lock(lock_); private_->DisableHardwareAcceleration();
diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h index 54e4e79..5bd7175 100644 --- a/content/browser/gpu/gpu_data_manager_impl.h +++ b/content/browser/gpu/gpu_data_manager_impl.h
@@ -81,9 +81,6 @@ void AddObserver(GpuDataManagerObserver* observer) override; void RemoveObserver(GpuDataManagerObserver* observer) override; void UnblockDomainFrom3DAPIs(const GURL& url) override; - void SetGLStrings(const std::string& gl_vendor, - const std::string& gl_renderer, - const std::string& gl_version) override; void DisableHardwareAcceleration() override; bool HardwareAccelerationEnabled() const override; void GetDisabledExtensions(std::string* disabled_extensions) const override;
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc index f5f51f69..06cacc1 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -453,38 +453,6 @@ timestamps_of_gpu_resets_.clear(); } -void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor, - const std::string& gl_renderer, - const std::string& gl_version) { - if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty()) - return; - - if (!is_initialized_) { - post_init_tasks_.push_back( - base::Bind(&GpuDataManagerImplPrivate::SetGLStrings, - base::Unretained(this), gl_vendor, gl_renderer, gl_version)); - return; - } - - // If GPUInfo already got GL strings, do nothing. This is for the rare - // situation where GPU process collected GL strings before this call. - if (!gpu_info_.gl_vendor.empty() || - !gpu_info_.gl_renderer.empty() || - !gpu_info_.gl_version.empty()) - return; - - gpu::GPUInfo gpu_info = gpu_info_; - - gpu_info.gl_vendor = gl_vendor; - gpu_info.gl_renderer = gl_renderer; - gpu_info.gl_version = gl_version; - - gpu::IdentifyActiveGPU(&gpu_info); - gpu::CollectDriverInfoGL(&gpu_info); - - UpdateGpuInfo(gpu_info); -} - void GpuDataManagerImplPrivate::Initialize() { TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize"); if (finalized_) {
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.h b/content/browser/gpu/gpu_data_manager_impl_private.h index b1d1f19..32908d0 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.h +++ b/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -53,9 +53,6 @@ void AddObserver(GpuDataManagerObserver* observer); void RemoveObserver(GpuDataManagerObserver* observer); void UnblockDomainFrom3DAPIs(const GURL& url); - void SetGLStrings(const std::string& gl_vendor, - const std::string& gl_renderer, - const std::string& gl_version); void DisableHardwareAcceleration(); bool HardwareAccelerationEnabled() const; void DisableSwiftShader();
diff --git a/content/browser/gpu/gpu_data_manager_testing.json b/content/browser/gpu/gpu_data_manager_testing.json index 0d363ba..f5d871c 100644 --- a/content/browser/gpu/gpu_data_manager_testing.json +++ b/content/browser/gpu/gpu_data_manager_testing.json
@@ -47,56 +47,13 @@ }, { "id": 6, - "description": "GpuDataManagerImplPrivateTest.SetGLStrings", - "vendor_id": "0x8086", - "exceptions": [ - { - "device_id": ["0x0042"], - "driver_version": { - "op": ">=", - "value": "8.0.2" - } - } - ], - "features": [ - "accelerated_webgl" - ] - }, - { - "id": 7, - "description": "GpuDataManagerImplPrivateTest.SetGLStringsNoEffects", - "vendor_id": "0x8086", - "exceptions": [ - { - "device_id": ["0x0042"], - "driver_version": { - "op": ">=", - "value": "8.0.2" - } - } - ], - "features": [ - "accelerated_webgl" - ] - }, - { - "id" : 8, - "description": "GpuDataManagerImplPrivateTest.SetGLStringsDefered", - "vendor_id" : "0x8086", - "device_id" : ["0x0042"], - "driver_vendor" : "Mesa", - "driver_version" : {"op" : ">=", "value" : "8.0.0"}, - "features" : ["accelerated_webgl"] - }, - { - "id": 9, - "description": "GpuDataManagerImplPrivateTest.BlacklistAllFeatures", + "description": "GpuDataManagerImplPrivateTest.BlacklistAllFeatures", "features": [ "all" ] }, { - "id": 10, + "id": 7, "description": "GpuDataManagerImplPrivateTest.UpdateActiveGpu", "vendor_id": "0x8086", "multi_gpu_category": "active",
diff --git a/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h b/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h index a1b299a..41bda61 100644 --- a/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h +++ b/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h
@@ -46,55 +46,7 @@ nullptr, ".*GeForce.*", nullptr, nullptr, }; -const int kFeatureListForEntry6[1] = { - GPU_FEATURE_TYPE_ACCELERATED_WEBGL, -}; - -const uint32_t kDeviceIDsForEntry6Exception0[1] = { - 0x0042, -}; - -const GpuControlList::DriverInfo kDriverInfoForEntry6Exception0 = { - nullptr, // driver_vendor - {GpuControlList::kGE, GpuControlList::kVersionStyleNumerical, "8.0.2", - nullptr}, // driver_version - {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, - nullptr}, // driver_date -}; - -const int kFeatureListForEntry7[1] = { - GPU_FEATURE_TYPE_ACCELERATED_WEBGL, -}; - -const uint32_t kDeviceIDsForEntry7Exception0[1] = { - 0x0042, -}; - -const GpuControlList::DriverInfo kDriverInfoForEntry7Exception0 = { - nullptr, // driver_vendor - {GpuControlList::kGE, GpuControlList::kVersionStyleNumerical, "8.0.2", - nullptr}, // driver_version - {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, - nullptr}, // driver_date -}; - -const int kFeatureListForEntry8[1] = { - GPU_FEATURE_TYPE_ACCELERATED_WEBGL, -}; - -const uint32_t kDeviceIDsForEntry8[1] = { - 0x0042, -}; - -const GpuControlList::DriverInfo kDriverInfoForEntry8 = { - "Mesa", // driver_vendor - {GpuControlList::kGE, GpuControlList::kVersionStyleNumerical, "8.0.0", - nullptr}, // driver_version - {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, - nullptr}, // driver_date -}; - -const int kFeatureListForEntry9[9] = { +const int kFeatureListForEntry6[9] = { GPU_FEATURE_TYPE_FLASH_STAGE3D, GPU_FEATURE_TYPE_GPU_COMPOSITING, GPU_FEATURE_TYPE_GPU_RASTERIZATION, @@ -106,7 +58,7 @@ GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE, }; -const int kFeatureListForEntry10[1] = { +const int kFeatureListForEntry7[1] = { GPU_FEATURE_TYPE_ACCELERATED_WEBGL, };
diff --git a/content/browser/gpu/gpu_data_manager_testing_autogen.cc b/content/browser/gpu/gpu_data_manager_testing_autogen.cc index 05c1e100..6d36db8c 100644 --- a/content/browser/gpu/gpu_data_manager_testing_autogen.cc +++ b/content/browser/gpu/gpu_data_manager_testing_autogen.cc
@@ -148,7 +148,7 @@ }, { 6, // id - "GpuDataManagerImplPrivateTest.SetGLStrings", + "GpuDataManagerImplPrivateTest.BlacklistAllFeatures", arraysize(kFeatureListForEntry6), // features size kFeatureListForEntry6, // features 0, // DisabledExtensions size @@ -159,84 +159,6 @@ GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // os_version - 0x8086, // vendor_id - 0, // DeviceIDs size - nullptr, // DeviceIDs - GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category - GpuControlList::kMultiGpuStyleNone, // multi_gpu_style - nullptr, // driver info - nullptr, // GL strings - nullptr, // machine model info - nullptr, // more conditions - }, - arraysize(kExceptionsForEntry6), // exceptions count - kExceptionsForEntry6, // exceptions - }, - { - 7, // id - "GpuDataManagerImplPrivateTest.SetGLStringsNoEffects", - arraysize(kFeatureListForEntry7), // features size - kFeatureListForEntry7, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // CrBugs size - nullptr, // CrBugs - { - GpuControlList::kOsAny, // os_type - {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, - nullptr, nullptr}, // os_version - 0x8086, // vendor_id - 0, // DeviceIDs size - nullptr, // DeviceIDs - GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category - GpuControlList::kMultiGpuStyleNone, // multi_gpu_style - nullptr, // driver info - nullptr, // GL strings - nullptr, // machine model info - nullptr, // more conditions - }, - arraysize(kExceptionsForEntry7), // exceptions count - kExceptionsForEntry7, // exceptions - }, - { - 8, // id - "GpuDataManagerImplPrivateTest.SetGLStringsDefered", - arraysize(kFeatureListForEntry8), // features size - kFeatureListForEntry8, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // CrBugs size - nullptr, // CrBugs - { - GpuControlList::kOsAny, // os_type - {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, - nullptr, nullptr}, // os_version - 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry8), // DeviceIDs size - kDeviceIDsForEntry8, // DeviceIDs - GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category - GpuControlList::kMultiGpuStyleNone, // multi_gpu_style - &kDriverInfoForEntry8, // driver info - nullptr, // GL strings - nullptr, // machine model info - nullptr, // more conditions - }, - 0, // exceptions count - nullptr, // exceptions - }, - { - 9, // id - "GpuDataManagerImplPrivateTest.BlacklistAllFeatures", - arraysize(kFeatureListForEntry9), // features size - kFeatureListForEntry9, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // CrBugs size - nullptr, // CrBugs - { - GpuControlList::kOsAny, // os_type - {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, - nullptr, nullptr}, // os_version 0x00, // vendor_id 0, // DeviceIDs size nullptr, // DeviceIDs @@ -251,14 +173,14 @@ nullptr, // exceptions }, { - 10, // id + 7, // id "GpuDataManagerImplPrivateTest.UpdateActiveGpu", - arraysize(kFeatureListForEntry10), // features size - kFeatureListForEntry10, // features - 0, // DisabledExtensions size - nullptr, // DisabledExtensions - 0, // CrBugs size - nullptr, // CrBugs + arraysize(kFeatureListForEntry7), // features size + kFeatureListForEntry7, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // CrBugs size + nullptr, // CrBugs { GpuControlList::kOsAny, // os_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, @@ -277,5 +199,5 @@ nullptr, // exceptions }, }; -const size_t kGpuDataManagerTestingEntryCount = 10; +const size_t kGpuDataManagerTestingEntryCount = 7; } // namespace gpu
diff --git a/content/browser/gpu/gpu_data_manager_testing_entry_enums_autogen.h b/content/browser/gpu/gpu_data_manager_testing_entry_enums_autogen.h index ad06de9d..6ea0120 100644 --- a/content/browser/gpu/gpu_data_manager_testing_entry_enums_autogen.h +++ b/content/browser/gpu/gpu_data_manager_testing_entry_enums_autogen.h
@@ -18,11 +18,8 @@ kGpuDataManagerImplPrivateTest_GpuSideBlacklistingWebGL_0 = 2, kGpuDataManagerImplPrivateTest_GpuSideBlacklistingWebGL_1 = 3, kGpuDataManagerImplPrivateTest_GpuSideException = 4, - kGpuDataManagerImplPrivateTest_SetGLStrings = 5, - kGpuDataManagerImplPrivateTest_SetGLStringsNoEffects = 6, - kGpuDataManagerImplPrivateTest_SetGLStringsDefered = 7, - kGpuDataManagerImplPrivateTest_BlacklistAllFeatures = 8, - kGpuDataManagerImplPrivateTest_UpdateActiveGpu = 9, + kGpuDataManagerImplPrivateTest_BlacklistAllFeatures = 5, + kGpuDataManagerImplPrivateTest_UpdateActiveGpu = 6, }; } // namespace gpu
diff --git a/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h b/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h index a550427..12a2a5491 100644 --- a/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h +++ b/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h
@@ -29,40 +29,6 @@ }, }; -const GpuControlList::Conditions kExceptionsForEntry6[1] = { - { - GpuControlList::kOsAny, // os_type - {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, - nullptr, nullptr}, // os_version - 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry6Exception0), // DeviceIDs size - kDeviceIDsForEntry6Exception0, // DeviceIDs - GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category - GpuControlList::kMultiGpuStyleNone, // multi_gpu_style - &kDriverInfoForEntry6Exception0, // driver info - nullptr, // GL strings - nullptr, // machine model info - nullptr, // more conditions - }, -}; - -const GpuControlList::Conditions kExceptionsForEntry7[1] = { - { - GpuControlList::kOsAny, // os_type - {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, - nullptr, nullptr}, // os_version - 0x8086, // vendor_id - arraysize(kDeviceIDsForEntry7Exception0), // DeviceIDs size - kDeviceIDsForEntry7Exception0, // DeviceIDs - GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category - GpuControlList::kMultiGpuStyleNone, // multi_gpu_style - &kDriverInfoForEntry7Exception0, // driver info - nullptr, // GL strings - nullptr, // machine model info - nullptr, // more conditions - }, -}; - } // namespace gpu #endif // CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_TESTING_EXCEPTIONS_AUTOGEN_H_
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc index 7dc346e..75195a2 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -169,11 +169,11 @@ std::unique_ptr<storage::BlobDataHandle> blob_data_handle; if (uuid.empty()) { uuid = base::GenerateGUID(); - storage::BlobDataBuilder blob_data_builder(uuid); - blob_data_builder.set_content_type(base::UTF16ToUTF8(blob_info.type())); - blob_data_builder.AppendFile(blob_info.file_path(), 0, blob_info.size(), - blob_info.last_modified()); - blob_data_handle = context->AddFinishedBlob(&blob_data_builder); + auto blob_data_builder = std::make_unique<storage::BlobDataBuilder>(uuid); + blob_data_builder->set_content_type(base::UTF16ToUTF8(blob_info.type())); + blob_data_builder->AppendFile(blob_info.file_path(), 0, blob_info.size(), + blob_info.last_modified()); + blob_data_handle = context->AddFinishedBlob(std::move(blob_data_builder)); } else { auto iter = blob_data_handle_map_.find(uuid); if (iter != blob_data_handle_map_.end()) {
diff --git a/content/browser/loader/upload_data_stream_builder_unittest.cc b/content/browser/loader/upload_data_stream_builder_unittest.cc index 9468d3a..8231784c 100644 --- a/content/browser/loader/upload_data_stream_builder_unittest.cc +++ b/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -53,9 +53,10 @@ const int64_t kIdentifier = 12345; BlobStorageContext context; - BlobDataBuilder builder(kBlob); - builder.AppendData(kBlobData); - std::unique_ptr<BlobDataHandle> handle = context.AddFinishedBlob(&builder); + auto builder = std::make_unique<BlobDataBuilder>(kBlob); + builder->AppendData(kBlobData); + std::unique_ptr<BlobDataHandle> handle = + context.AddFinishedBlob(std::move(builder)); request_body->AppendBytes(kData, arraysize(kData) - 1); request_body->AppendFileRange(base::FilePath(kFilePath), kFileOffset, @@ -118,7 +119,7 @@ new BlobDataBuilder(blob_id)); blob_data_builder->AppendFile(test_blob_path, 0, kZeroLength, blob_time); std::unique_ptr<BlobDataHandle> handle = - blob_storage_context.AddFinishedBlob(blob_data_builder.get()); + blob_storage_context.AddFinishedBlob(std::move(blob_data_builder)); scoped_refptr<network::ResourceRequestBody> request_body( new network::ResourceRequestBody()); @@ -176,10 +177,10 @@ const int64_t kIdentifier = 12345; BlobStorageContext blob_storage_context; - BlobDataBuilder builder(kBlob); - builder.AppendData(kBlobData); + auto builder = std::make_unique<BlobDataBuilder>(kBlob); + builder->AppendData(kBlobData); std::unique_ptr<BlobDataHandle> handle = - blob_storage_context.AddFinishedBlob(&builder); + blob_storage_context.AddFinishedBlob(std::move(builder)); request_body->AppendBlob(kBlob); request_body->set_identifier(kIdentifier);
diff --git a/content/browser/notifications/blink_notification_service_impl.cc b/content/browser/notifications/blink_notification_service_impl.cc index a84707c..e2ecad15 100644 --- a/content/browser/notifications/blink_notification_service_impl.cc +++ b/content/browser/notifications/blink_notification_service_impl.cc
@@ -75,7 +75,8 @@ } void BlinkNotificationServiceImpl::DisplayNonPersistentNotification( - const PlatformNotificationData& platform_notification_data) { + const PlatformNotificationData& platform_notification_data, + const NotificationResources& notification_resources) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!Service()) return; @@ -91,14 +92,13 @@ origin_.GetURL(), platform_notification_data.tag, request_id, render_process_id_); - // TODO(crbug.com/595685): Pass the actual notification resources here. // Using base::Unretained is safe because Service() returns a singleton. BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::BindOnce(&PlatformNotificationService::DisplayNotification, base::Unretained(Service()), browser_context_, notification_id, origin_.GetURL(), - platform_notification_data, NotificationResources())); + platform_notification_data, notification_resources)); } } // namespace content
diff --git a/content/browser/notifications/blink_notification_service_impl.h b/content/browser/notifications/blink_notification_service_impl.h index 599012e..bcc912e 100644 --- a/content/browser/notifications/blink_notification_service_impl.h +++ b/content/browser/notifications/blink_notification_service_impl.h
@@ -35,7 +35,8 @@ // blink::mojom::NotificationService implementation. void GetPermissionStatus(GetPermissionStatusCallback callback) override; void DisplayNonPersistentNotification( - const PlatformNotificationData& platform_notification_data) override; + const PlatformNotificationData& platform_notification_data, + const NotificationResources& notification_resources) override; private: // Called when an error is detected on binding_.
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc index 9fb51430..776b59cb 100644 --- a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc +++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -119,6 +119,11 @@ static_cast<MediaDeviceType>(i), this); } } + + for (auto& subscription_id : subscription_ids_) { + media_stream_manager_->media_devices_manager()->UnsubscribeDeviceChange( + subscription_id); + } } void MediaDevicesDispatcherHost::EnumerateDevices( @@ -226,6 +231,31 @@ } } +void MediaDevicesDispatcherHost::AddMediaDevicesListener( + bool subscribe_audio_input, + bool subscribe_video_input, + bool subscribe_audio_output, + blink::mojom::MediaDevicesListenerPtr listener) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (!subscribe_audio_input && !subscribe_video_input && + !subscribe_audio_output) { + bad_message::ReceivedBadMessage( + render_process_id_, bad_message::MDDH_INVALID_DEVICE_TYPE_REQUEST); + return; + } + + MediaDevicesManager::BoolDeviceTypes devices_to_subscribe; + devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = subscribe_audio_input; + devices_to_subscribe[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = subscribe_video_input; + devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = subscribe_audio_output; + + uint32_t subscription_id = media_stream_manager_->media_devices_manager() + ->SubscribeDeviceChangeNotifications( + devices_to_subscribe, std::move(listener)); + subscription_ids_.push_back(subscription_id); +} + void MediaDevicesDispatcherHost::OnDevicesChanged( MediaDeviceType type, const MediaDeviceInfoArray& device_infos) {
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.h b/content/browser/renderer_host/media/media_devices_dispatcher_host.h index 6db42f5..b85891b 100644 --- a/content/browser/renderer_host/media/media_devices_dispatcher_host.h +++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.h
@@ -57,6 +57,11 @@ uint32_t subscription_id) override; void UnsubscribeDeviceChangeNotifications(MediaDeviceType type, uint32_t subscription_id) override; + void AddMediaDevicesListener( + bool subscribe_audio_input, + bool subscribe_video_input, + bool subscribe_audio_output, + blink::mojom::MediaDevicesListenerPtr listener) override; // MediaDeviceChangeSubscriber implementation. void OnDevicesChanged(MediaDeviceType type, @@ -142,6 +147,8 @@ MediaStreamManager* media_stream_manager_; std::vector<uint32_t> device_change_subscriptions_[NUM_MEDIA_DEVICE_TYPES]; + // TODO(c.padhi): Remove this field once device change migration to blink is + // complete, see https://crbug.com/793297. // This field can only be accessed on the UI thread. blink::mojom::MediaDevicesListenerPtr device_change_listener_; @@ -153,6 +160,8 @@ std::vector<blink::mojom::AudioInputDeviceCapabilities> current_audio_input_capabilities_; + std::vector<uint32_t> subscription_ids_; + base::WeakPtrFactory<MediaDevicesDispatcherHost> weak_factory_; DISALLOW_COPY_AND_ASSIGN(MediaDevicesDispatcherHost);
diff --git a/content/browser/renderer_host/media/media_devices_manager.cc b/content/browser/renderer_host/media/media_devices_manager.cc index 38c697d..57ee40f0 100644 --- a/content/browser/renderer_host/media/media_devices_manager.cc +++ b/content/browser/renderer_host/media/media_devices_manager.cc
@@ -146,6 +146,20 @@ base::ThreadChecker thread_checker_; }; +MediaDevicesManager::SubscriptionRequest::SubscriptionRequest( + const BoolDeviceTypes& subscribe_types, + blink::mojom::MediaDevicesListenerPtr listener) + : subscribe_types(subscribe_types), listener(std::move(listener)) {} + +MediaDevicesManager::SubscriptionRequest::SubscriptionRequest( + SubscriptionRequest&&) = default; + +MediaDevicesManager::SubscriptionRequest::~SubscriptionRequest() = default; + +MediaDevicesManager::SubscriptionRequest& +MediaDevicesManager::SubscriptionRequest::operator=(SubscriptionRequest&&) = + default; + MediaDevicesManager::MediaDevicesManager( media::AudioSystem* audio_system, const scoped_refptr<VideoCaptureManager>& video_capture_manager, @@ -230,6 +244,28 @@ device_change_subscribers_[type].erase(it); } +uint32_t MediaDevicesManager::SubscribeDeviceChangeNotifications( + const BoolDeviceTypes& subscribe_types, + blink::mojom::MediaDevicesListenerPtr listener) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + uint32_t subscription_id = ++current_subscription_id_; + blink::mojom::MediaDevicesListenerPtr media_devices_listener = + std::move(listener); + media_devices_listener.set_connection_error_handler( + base::BindOnce(&MediaDevicesManager::UnsubscribeDeviceChange, + weak_factory_.GetWeakPtr(), subscription_id)); + subscriptions_.emplace( + subscription_id, + SubscriptionRequest(subscribe_types, std::move(media_devices_listener))); + + return subscription_id; +} + +void MediaDevicesManager::UnsubscribeDeviceChange(uint32_t subscription_id) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + subscriptions_.erase(subscription_id); +} + void MediaDevicesManager::SetCachePolicy(MediaDeviceType type, CachePolicy policy) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -588,8 +624,16 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(IsValidMediaDeviceType(type)); - for (auto* subscriber : device_change_subscribers_[type]) { + for (auto* subscriber : device_change_subscribers_[type]) subscriber->OnDevicesChanged(type, snapshot); + + // TODO(c.padhi): Check permission for |type| and translate |snapshot|, + // see https://crbug.com/793297. + for (auto& subscription : subscriptions_) { + if (subscription.second.subscribe_types[type]) { + subscription.second.listener->OnDevicesChanged(type, subscription.first, + MediaDeviceInfoArray()); + } } }
diff --git a/content/browser/renderer_host/media/media_devices_manager.h b/content/browser/renderer_host/media/media_devices_manager.h index 1e74a41..bcf3055d 100644 --- a/content/browser/renderer_host/media/media_devices_manager.h +++ b/content/browser/renderer_host/media/media_devices_manager.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/callback.h" +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/system_monitor/system_monitor.h" @@ -17,6 +18,7 @@ #include "content/common/media/media_devices.h" #include "media/audio/audio_device_description.h" #include "media/capture/video/video_capture_device_descriptor.h" +#include "third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h" namespace media { class AudioSystem; @@ -108,6 +110,11 @@ MediaDeviceType type, MediaDeviceChangeSubscriber* subscriber); + uint32_t SubscribeDeviceChangeNotifications( + const BoolDeviceTypes& subscribe_types, + blink::mojom::MediaDevicesListenerPtr listener); + void UnsubscribeDeviceChange(uint32_t subscription_id); + // Tries to start device monitoring. If successful, enables caching of // enumeration results for the device types supported by the monitor. void StartMonitoring(); @@ -238,6 +245,21 @@ std::vector<MediaDeviceChangeSubscriber*> device_change_subscribers_[NUM_MEDIA_DEVICE_TYPES]; + struct SubscriptionRequest { + SubscriptionRequest(const BoolDeviceTypes& subscribe_types, + blink::mojom::MediaDevicesListenerPtr listener); + SubscriptionRequest(SubscriptionRequest&&); + ~SubscriptionRequest(); + + SubscriptionRequest& operator=(SubscriptionRequest&&); + + BoolDeviceTypes subscribe_types; + blink::mojom::MediaDevicesListenerPtr listener; + }; + + uint32_t current_subscription_id_ = 0u; + base::flat_map<uint32_t, SubscriptionRequest> subscriptions_; + // Callback used to obtain the current device ID salt and security origin. MediaDeviceSaltAndOriginCallback salt_and_origin_callback_;
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc index d437d3c..2021291 100644 --- a/content/browser/renderer_host/media/video_capture_host.cc +++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -18,57 +18,54 @@ namespace content { -// Helper class that does all the work of notifying RenderProcessHost instance -// about active video capture stream changes. It should be called and destroyed -// on UI thread. -class VideoCaptureHost::RenderProcessHostDelegate { +VideoCaptureHost::RenderProcessHostDelegate::~RenderProcessHostDelegate() = + default; + +// Looks up a RenderProcessHost on demand based on a given |render_process_id| +// and invokes OnMediaStreamAdded() and OnMediaStreamRemoved(). It should be +// called and destroyed on UI thread. +class VideoCaptureHost::RenderProcessHostDelegateImpl + : public VideoCaptureHost::RenderProcessHostDelegate { public: - explicit RenderProcessHostDelegate(int render_process_id) + explicit RenderProcessHostDelegateImpl(uint32_t render_process_id) : render_process_id_(render_process_id) {} - ~RenderProcessHostDelegate() { DCHECK_CURRENTLY_ON(BrowserThread::UI); } + ~RenderProcessHostDelegateImpl() override { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + } // Helper functions that are used for notifying Browser-side RenderProcessHost // if renderer is currently consuming video capture. This information is then // used to determine if the renderer process should be backgrounded or not. - void NotifyStreamAdded() { + void NotifyStreamAdded() override { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ++number_of_active_streams_; RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_); if (host) host->OnMediaStreamAdded(); } - void NotifyStreamRemoved() { + void NotifyStreamRemoved() override { DCHECK_CURRENTLY_ON(BrowserThread::UI); - // DoError() from camera side failure can be followed by Stop() from JS - // side, so we should check before going to negative. - // TODO(emircan): Investigate all edge cases and add more browsertests. - // https://crbug.com/754765 - if (number_of_active_streams_ == 0) - return; - --number_of_active_streams_; RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_); if (host) host->OnMediaStreamRemoved(); } - void NotifyAllStreamsRemoved() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - for (uint32_t i = 0; i < number_of_active_streams_; ++i) - NotifyStreamRemoved(); - } - private: - const int render_process_id_; - uint32_t number_of_active_streams_ = 0; - DISALLOW_COPY_AND_ASSIGN(RenderProcessHostDelegate); + const uint32_t render_process_id_; + DISALLOW_COPY_AND_ASSIGN(RenderProcessHostDelegateImpl); }; -VideoCaptureHost::VideoCaptureHost(int render_process_id, +VideoCaptureHost::VideoCaptureHost(uint32_t render_process_id, MediaStreamManager* media_stream_manager) - : render_process_host_delegate_( - new RenderProcessHostDelegate(render_process_id)), + : VideoCaptureHost( + std::make_unique<RenderProcessHostDelegateImpl>(render_process_id), + media_stream_manager) {} + +VideoCaptureHost::VideoCaptureHost( + std::unique_ptr<RenderProcessHostDelegate> delegate, + MediaStreamManager* media_stream_manager) + : render_process_host_delegate_(std::move(delegate)), media_stream_manager_(media_stream_manager), weak_factory_(this) { DVLOG(1) << __func__; @@ -76,7 +73,7 @@ } // static -void VideoCaptureHost::Create(int render_process_id, +void VideoCaptureHost::Create(uint32_t render_process_id, MediaStreamManager* media_stream_manager, mojom::VideoCaptureHostRequest request) { DVLOG(1) << __func__; @@ -87,6 +84,7 @@ } VideoCaptureHost::~VideoCaptureHost() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); for (auto it = controllers_.begin(); it != controllers_.end(); ) { const base::WeakPtr<VideoCaptureController>& controller = it->second; if (controller) { @@ -102,12 +100,7 @@ } } - // base::Unretained() usage is safe because |render_process_host_delegate_| is - // destroyed on UI thread. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&RenderProcessHostDelegate::NotifyAllStreamsRemoved, - base::Unretained(render_process_host_delegate_.get()))); + NotifyAllStreamsRemoved(); BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, render_process_host_delegate_.release()); } @@ -178,12 +171,7 @@ if (base::ContainsKey(device_id_to_observer_map_, controller_id)) { device_id_to_observer_map_[controller_id]->OnStateChanged( mojom::VideoCaptureState::STARTED); - // base::Unretained() usage is safe because |render_process_host_delegate_| - // is destroyed on UI thread. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&RenderProcessHostDelegate::NotifyStreamAdded, - base::Unretained(render_process_host_delegate_.get()))); + NotifyStreamAdded(); } } @@ -205,12 +193,7 @@ if (controllers_.find(controller_id) != controllers_.end()) { device_id_to_observer_map_[device_id]->OnStateChanged( mojom::VideoCaptureState::STARTED); - // base::Unretained() usage is safe because |render_process_host_delegate_| - // is destroyed on UI thread. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&RenderProcessHostDelegate::NotifyStreamAdded, - base::Unretained(render_process_host_delegate_.get()))); + NotifyStreamAdded(); return; } @@ -234,12 +217,7 @@ device_id_to_observer_map_.erase(controller_id); DeleteVideoCaptureController(controller_id, false); - // base::Unretained() usage is safe because |render_process_host_delegate_| is - // destroyed on UI thread. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&RenderProcessHostDelegate::NotifyStreamRemoved, - base::Unretained(render_process_host_delegate_.get()))); + NotifyStreamRemoved(); } void VideoCaptureHost::Pause(int32_t device_id) { @@ -350,12 +328,7 @@ } DeleteVideoCaptureController(controller_id, true); - // base::Unretained() usage is safe because |render_process_host_delegate_| is - // destroyed on UI thread. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&RenderProcessHostDelegate::NotifyStreamRemoved, - base::Unretained(render_process_host_delegate_.get()))); + NotifyStreamRemoved(); } void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id) { @@ -370,12 +343,7 @@ } DeleteVideoCaptureController(controller_id, false); - // base::Unretained() usage is safe because |render_process_host_delegate_| is - // destroyed on UI thread. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&RenderProcessHostDelegate::NotifyStreamRemoved, - base::Unretained(render_process_host_delegate_.get()))); + NotifyStreamRemoved(); } void VideoCaptureHost::OnControllerAdded( @@ -422,4 +390,38 @@ controller.get(), controller_id, this, on_error); } +void VideoCaptureHost::NotifyStreamAdded() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + ++number_of_active_streams_; + // base::Unretained() usage is safe because |render_process_host_delegate_| + // is destroyed on UI thread. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&RenderProcessHostDelegate::NotifyStreamAdded, + base::Unretained(render_process_host_delegate_.get()))); +} + +void VideoCaptureHost::NotifyStreamRemoved() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + // DoError() from camera side failure can be followed by Stop() from JS + // side, so we should check before going to negative. + // TODO(emircan): Investigate all edge cases and add more browsertests. + // https://crbug.com/754765 + if (number_of_active_streams_ == 0) + return; + --number_of_active_streams_; + // base::Unretained() usage is safe because |render_process_host_delegate_| is + // destroyed on UI thread. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&RenderProcessHostDelegate::NotifyStreamRemoved, + base::Unretained(render_process_host_delegate_.get()))); +} + +void VideoCaptureHost::NotifyAllStreamsRemoved() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + while (number_of_active_streams_ > 0) + NotifyStreamRemoved(); +} + } // namespace content
diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h index d9ad77c..8539fdb 100644 --- a/content/browser/renderer_host/media/video_capture_host.h +++ b/content/browser/renderer_host/media/video_capture_host.h
@@ -28,17 +28,29 @@ : public VideoCaptureControllerEventHandler, public mojom::VideoCaptureHost { public: - VideoCaptureHost(int render_process_id, + VideoCaptureHost(uint32_t render_process_id, MediaStreamManager* media_stream_manager); + class RenderProcessHostDelegate; + VideoCaptureHost(std::unique_ptr<RenderProcessHostDelegate> delegate, + MediaStreamManager* media_stream_manager); + ~VideoCaptureHost() override; - static void Create(int render_process_id, + static void Create(uint32_t render_process_id, MediaStreamManager* media_stream_manager, mojom::VideoCaptureHostRequest request); - ~VideoCaptureHost() override; + // Interface for notifying RenderProcessHost instance about active video + // capture stream changes. + class CONTENT_EXPORT RenderProcessHostDelegate { + public: + virtual ~RenderProcessHostDelegate(); + virtual void NotifyStreamAdded() = 0; + virtual void NotifyStreamRemoved() = 0; + }; private: friend class VideoCaptureTest; + FRIEND_TEST_ALL_PREFIXES(VideoCaptureTest, IncrementMatchesDecrementCalls); // VideoCaptureControllerEventHandler implementation. void OnError(VideoCaptureControllerID id) override; @@ -92,8 +104,13 @@ void DeleteVideoCaptureController(VideoCaptureControllerID controller_id, bool on_error); - class RenderProcessHostDelegate; + void NotifyStreamAdded(); + void NotifyStreamRemoved(); + void NotifyAllStreamsRemoved(); + + class RenderProcessHostDelegateImpl; std::unique_ptr<RenderProcessHostDelegate> render_process_host_delegate_; + uint32_t number_of_active_streams_ = 0; MediaStreamManager* const media_stream_manager_;
diff --git a/content/browser/renderer_host/media/video_capture_unittest.cc b/content/browser/renderer_host/media/video_capture_unittest.cc index 287e133..f4628ae2 100644 --- a/content/browser/renderer_host/media/video_capture_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -75,6 +75,13 @@ task_runner->PostTask(FROM_HERE, quit_closure); } +class MockRenderProcessHostDelegate + : public VideoCaptureHost::RenderProcessHostDelegate { + public: + MOCK_METHOD0(NotifyStreamAdded, void()); + MOCK_METHOD0(NotifyStreamRemoved, void()); +}; + // This is an integration test of VideoCaptureHost in conjunction with // MediaStreamManager, VideoCaptureManager, VideoCaptureController, and // VideoCaptureDevice. @@ -351,4 +358,26 @@ base::RunLoop().RunUntilIdle(); } +// Tests if RenderProcessHostDelegate methods are called as often as as +// expected. +TEST_F(VideoCaptureTest, IncrementMatchesDecrementCalls) { + std::unique_ptr<MockRenderProcessHostDelegate> mock_delegate = + std::make_unique<MockRenderProcessHostDelegate>(); + MockRenderProcessHostDelegate* const mock_delegate_ptr = mock_delegate.get(); + std::unique_ptr<VideoCaptureHost> host = + std::make_unique<VideoCaptureHost>(std::move(mock_delegate), nullptr); + + const int kNumNotifyCalls = 3; + EXPECT_CALL(*mock_delegate_ptr, NotifyStreamAdded()).Times(kNumNotifyCalls); + EXPECT_CALL(*mock_delegate_ptr, NotifyStreamRemoved()).Times(kNumNotifyCalls); + + EXPECT_EQ(0u, host->number_of_active_streams_); + for (int i = 0; i < kNumNotifyCalls; ++i) + host->NotifyStreamAdded(); + EXPECT_EQ(kNumNotifyCalls, static_cast<int>(host->number_of_active_streams_)); + host->NotifyStreamRemoved(); + host->NotifyAllStreamsRemoved(); + EXPECT_EQ(0u, host->number_of_active_streams_); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 9ab72e7..38934a8 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -94,6 +94,7 @@ #include "url/url_constants.h" #if defined(OS_WIN) +#include "base/win/win_client_metrics.h" #include "ui/display/win/screen_win.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/platform_font_win.h"
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc index caae0f4..3bd3324b 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -343,7 +343,8 @@ RenderWidgetHostViewBase* root_view, RenderWidgetHostViewBase* target, const blink::WebMouseEvent& mouse_event, - const ui::LatencyInfo& latency) { + const ui::LatencyInfo& latency, + const base::Optional<gfx::PointF>& target_location) { // TODO(wjmaclean): Should we be sending a no-consumer ack to the root_view // if there is no target? if (!target) @@ -354,19 +355,23 @@ else if (mouse_event.GetType() == blink::WebInputEvent::kMouseDown) mouse_capture_target_.target = target; + DCHECK(target_location.has_value()); + blink::WebMouseEvent event = mouse_event; + event.SetPositionInWidget(target_location->x(), target_location->y()); + // SendMouseEnterOrLeaveEvents is called with the original event // coordinates, which are transformed independently for each view that will // receive an event. Also, since the view under the mouse has changed, // notify the CursorManager that it might need to change the cursor. - if ((mouse_event.GetType() == blink::WebInputEvent::kMouseLeave || - mouse_event.GetType() == blink::WebInputEvent::kMouseMove) && + if ((event.GetType() == blink::WebInputEvent::kMouseLeave || + event.GetType() == blink::WebInputEvent::kMouseMove) && target != last_mouse_move_target_) { - SendMouseEnterOrLeaveEvents(mouse_event, target, root_view); + SendMouseEnterOrLeaveEvents(event, target, root_view); if (root_view->GetCursorManager()) root_view->GetCursorManager()->UpdateViewUnderCursor(target); } - target->ProcessMouseEvent(mouse_event, latency); + target->ProcessMouseEvent(event, latency); } void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent( @@ -1238,8 +1243,8 @@ const base::Optional<gfx::PointF>& target_location) { if (blink::WebInputEvent::IsMouseEventType(event.GetType())) { DispatchMouseEvent(root_view, target, - static_cast<const blink::WebMouseEvent&>(event), - latency); + static_cast<const blink::WebMouseEvent&>(event), latency, + target_location); return; } if (event.GetType() == blink::WebInputEvent::kMouseWheel) {
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h index f69037a3..8550698 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.h +++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -194,11 +194,12 @@ RenderWidgetHostViewBase* root_view, const blink::WebGestureEvent& gesture_event); - // |mouse_event| is in the coord-space of |target|. + // |mouse_event| is in the coord-space of |root_view|. void DispatchMouseEvent(RenderWidgetHostViewBase* root_view, RenderWidgetHostViewBase* target, const blink::WebMouseEvent& mouse_event, - const ui::LatencyInfo& latency); + const ui::LatencyInfo& latency, + const base::Optional<gfx::PointF>& target_location); // |mouse_wheel_event| is in the coord-space of |root_view|. void DispatchMouseWheelEvent( RenderWidgetHostViewBase* root_view,
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc index 5bde7d58..197370f 100644 --- a/content/browser/renderer_host/render_widget_targeter.cc +++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -50,8 +50,8 @@ metric_name_(metric_name), tracing_category_(tracing_category) { TRACE_EVENT_ASYNC_BEGIN0( - tracing_category_, metric_name_, - TRACE_ID_WITH_SCOPE(metric_name_, TRACE_ID_LOCAL(id_))); + tracing_category_.c_str(), metric_name_.c_str(), + TRACE_ID_WITH_SCOPE(metric_name_.c_str(), TRACE_ID_LOCAL(id_))); } ~TracingUmaTracker() = default; TracingUmaTracker(TracingUmaTracker&& tracker) = default; @@ -59,16 +59,17 @@ void Stop() { TRACE_EVENT_ASYNC_END0( - tracing_category_, metric_name_, - TRACE_ID_WITH_SCOPE(metric_name_, TRACE_ID_LOCAL(id_))); - UmaHistogramTimes(metric_name_, base::TimeTicks::Now() - start_time_); + tracing_category_.c_str(), metric_name_.c_str(), + TRACE_ID_WITH_SCOPE(metric_name_.c_str(), TRACE_ID_LOCAL(id_))); + UmaHistogramTimes(metric_name_.c_str(), + base::TimeTicks::Now() - start_time_); } private: const int id_; const base::TimeTicks start_time_; - const char* metric_name_; - const char* tracing_category_; + std::string metric_name_; + std::string tracing_category_; static int next_id_; @@ -113,6 +114,15 @@ RenderWidgetHostViewBase* root_view, const blink::WebInputEvent& event, const ui::LatencyInfo& latency) { + DCHECK(blink::WebInputEvent::IsMouseEventType(event.GetType()) || + event.GetType() == blink::WebInputEvent::kMouseWheel || + blink::WebInputEvent::IsTouchEventType(event.GetType()) || + (blink::WebInputEvent::IsGestureEventType(event.GetType()) && + (static_cast<const blink::WebGestureEvent&>(event).source_device == + blink::WebGestureDevice::kWebGestureDeviceTouchscreen || + static_cast<const blink::WebGestureEvent&>(event).source_device == + blink::WebGestureDevice::kWebGestureDeviceTouchpad))); + if (request_in_flight_) { if (!requests_.empty()) { auto& request = requests_.back(); @@ -170,14 +180,6 @@ target->GetRenderWidgetHostImpl()->input_target_client(); TracingUmaTracker tracker("Event.AsyncTargeting.ResponseTime", "input,latency"); - if (blink::WebInputEvent::IsMouseEventType(event.GetType()) || - event.GetType() == blink::WebInputEvent::kMouseWheel || - event.GetType() == blink::WebInputEvent::kTouchStart || - (blink::WebInputEvent::IsGestureEventType(event.GetType()) && - (static_cast<const blink::WebGestureEvent&>(event).source_device == - blink::WebGestureDevice::kWebGestureDeviceTouchscreen || - static_cast<const blink::WebGestureEvent&>(event).source_device == - blink::WebGestureDevice::kWebGestureDeviceTouchpad))) { async_hit_test_timeout_.reset(new OneShotTimeoutMonitor( base::BindOnce( &RenderWidgetTargeter::AsyncHitTestTimedOut, @@ -194,9 +196,6 @@ weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(), target->GetWeakPtr(), ui::WebInputEventTraits::Clone(event), latency, ++last_request_id_, target_location, std::move(tracker))); - return; - } - NOTREACHED(); } void RenderWidgetTargeter::FlushEventQueue() { @@ -259,31 +258,8 @@ const base::Optional<gfx::PointF>& target_location) { if (!root_view) return; - // TODO: Unify position conversion for all event types. - if (blink::WebInputEvent::IsMouseEventType(event.GetType())) { - blink::WebMouseEvent mouse_event = - static_cast<const blink::WebMouseEvent&>(event); - if (target_location.has_value()) { - mouse_event.SetPositionInWidget(target_location->x(), - target_location->y()); - } - if (mouse_event.GetType() != blink::WebInputEvent::kUndefined) - delegate_->DispatchEventToTarget(root_view, target, mouse_event, latency, - target_location); - } else if (event.GetType() == blink::WebInputEvent::kMouseWheel || - blink::WebInputEvent::IsTouchEventType(event.GetType()) || - blink::WebInputEvent::IsGestureEventType(event.GetType())) { - DCHECK(!blink::WebInputEvent::IsGestureEventType(event.GetType()) || - (static_cast<const blink::WebGestureEvent&>(event).source_device == - blink::WebGestureDevice::kWebGestureDeviceTouchscreen || - static_cast<const blink::WebGestureEvent&>(event).source_device == - blink::WebGestureDevice::kWebGestureDeviceTouchpad)); - delegate_->DispatchEventToTarget(root_view, target, event, latency, - target_location); - } else { - NOTREACHED(); - return; - } + delegate_->DispatchEventToTarget(root_view, target, event, latency, + target_location); FlushEventQueue(); }
diff --git a/content/browser/service_manager/service_manager_context_browsertest.cc b/content/browser/service_manager/service_manager_context_browsertest.cc index 29e6be2..b049756d 100644 --- a/content/browser/service_manager/service_manager_context_browsertest.cc +++ b/content/browser/service_manager/service_manager_context_browsertest.cc
@@ -112,8 +112,13 @@ loop.Run(); } -// Verifies that if an important service quits then the browser exits. -TEST(ServiceManagerContextTest, TerminateOnServiceQuit) { +// Flaky timeout on Linux and Chrome OS ASAN: http://crbug.com/803814 +#if defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER) +#define MAYBE_TerminateOnServiceQuit DISABLED_TerminateOnServiceQuit +#else +#define MAYBE_TerminateOnServiceQuit TerminateOnServiceQuit +#endif +TEST(ServiceManagerContextTest, MAYBE_TerminateOnServiceQuit) { // Run the above test and collect the test output. base::CommandLine new_test = base::CommandLine(base::CommandLine::ForCurrentProcess()->GetProgram());
diff --git a/content/browser/service_worker/service_worker_url_loader_job_unittest.cc b/content/browser/service_worker/service_worker_url_loader_job_unittest.cc index 13ea86ca..bbd489c 100644 --- a/content/browser/service_worker/service_worker_url_loader_job_unittest.cc +++ b/content/browser/service_worker/service_worker_url_loader_job_unittest.cc
@@ -670,7 +670,7 @@ auto blob_data = std::make_unique<storage::BlobDataBuilder>("blob-id:myblob"); blob_data->AppendData(kResponseBody); std::unique_ptr<storage::BlobDataHandle> blob_handle = - blob_context_.AddFinishedBlob(blob_data.get()); + blob_context_.AddFinishedBlob(std::move(blob_data)); blink::mojom::BlobPtr blob_ptr; blink::mojom::BlobRequest request = mojo::MakeRequest(&blob_ptr); storage::BlobImpl::Create(std::move(blob_handle), std::move(request));
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc index 4064b7b3..6dcaa56 100644 --- a/content/browser/service_worker/service_worker_url_request_job.cc +++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -603,14 +603,16 @@ void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid, uint64_t* blob_size) { DCHECK(HasRequestBody()); - storage::BlobDataBuilder blob_builder(base::GenerateGUID()); + auto blob_builder = + std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID()); for (const network::DataElement& element : (*body_->elements())) { - blob_builder.AppendIPCDataElement(element, nullptr); // TODO + blob_builder->AppendIPCDataElement(element, nullptr, + blob_storage_context_->registry()); } + *blob_uuid = blob_builder->uuid(); request_body_blob_data_handle_ = - blob_storage_context_->AddFinishedBlob(&blob_builder); - *blob_uuid = blob_builder.uuid(); + blob_storage_context_->AddFinishedBlob(std::move(blob_builder)); *blob_size = request_body_blob_data_handle_->size(); blink::mojom::BlobPtr blob_ptr;
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc index 6173266..c9c5dbf 100644 --- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc +++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -841,7 +841,7 @@ expected_response += kTestData; } std::unique_ptr<storage::BlobDataHandle> blob_handle = - blob_storage_context->context()->AddFinishedBlob(blob_data.get()); + blob_storage_context->context()->AddFinishedBlob(std::move(blob_data)); SetUpWithHelper(std::make_unique<BlobResponder>(blob_handle->uuid(), expected_response.size()));
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index 6b76af54..025d0cfb 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -224,6 +224,8 @@ return IDS_MEDIA_OVERFLOW_MENU_DOWNLOAD; case WebLocalizedString::kOverflowMenuPictureInPicture: return IDS_MEDIA_OVERFLOW_MENU_PICTURE_IN_PICTURE; + case WebLocalizedString::kPictureInPictureInterstitialText: + return IDS_MEDIA_PICTURE_IN_PICTURE_INTERSTITIAL_TEXT; case WebLocalizedString::kPlaceholderForDayOfMonthField: return IDS_FORM_PLACEHOLDER_FOR_DAY_OF_MONTH_FIELD; case WebLocalizedString::kPlaceholderForMonthField:
diff --git a/content/common/notifications/notification_struct_traits.cc b/content/common/notifications/notification_struct_traits.cc index 354e683e..4f794ae 100644 --- a/content/common/notifications/notification_struct_traits.cc +++ b/content/common/notifications/notification_struct_traits.cc
@@ -171,4 +171,13 @@ ValidateData(platform_notification_data->data); } +// static +bool StructTraits<blink::mojom::NotificationResourcesDataView, + content::NotificationResources>:: + Read(blink::mojom::NotificationResourcesDataView in, + content::NotificationResources* out) { + return in.ReadImage(&out->image) && in.ReadIcon(&out->notification_icon) && + in.ReadBadge(&out->badge) && in.ReadActionIcons(&out->action_icons); +} + } // namespace mojo
diff --git a/content/common/notifications/notification_struct_traits.h b/content/common/notifications/notification_struct_traits.h index 99de47df..f828c7f0 100644 --- a/content/common/notifications/notification_struct_traits.h +++ b/content/common/notifications/notification_struct_traits.h
@@ -12,6 +12,7 @@ #include "mojo/common/common_custom_types_struct_traits.h" #include "mojo/common/string16_struct_traits.h" #include "mojo/public/cpp/bindings/struct_traits.h" +#include "skia/public/interfaces/bitmap_skbitmap_struct_traits.h" #include "third_party/WebKit/public/platform/modules/notifications/notification.mojom.h" #include "url/gurl.h" #include "url/mojo/url_gurl_struct_traits.h" @@ -151,6 +152,32 @@ content::PlatformNotificationData* platform_notification_data); }; +template <> +struct CONTENT_EXPORT StructTraits<blink::mojom::NotificationResourcesDataView, + content::NotificationResources> { + static const SkBitmap& image( + const content::NotificationResources& resources) { + return resources.image; + } + + static const SkBitmap& icon(const content::NotificationResources& resources) { + return resources.notification_icon; + } + + static const SkBitmap& badge( + const content::NotificationResources& resources) { + return resources.badge; + } + + static const std::vector<SkBitmap>& action_icons( + const content::NotificationResources& resources) { + return resources.action_icons; + } + + static bool Read(blink::mojom::NotificationResourcesDataView in, + content::NotificationResources* out); +}; + } // namespace mojo #endif // CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_STRUCT_TRAITS_H_
diff --git a/content/common/notifications/notification_struct_traits_unittest.cc b/content/common/notifications/notification_struct_traits_unittest.cc index 1fc9135..6dda4f1 100644 --- a/content/common/notifications/notification_struct_traits_unittest.cc +++ b/content/common/notifications/notification_struct_traits_unittest.cc
@@ -12,10 +12,29 @@ #include "mojo/public/cpp/test_support/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/modules/notifications/notification.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "url/gurl.h" namespace content { +namespace { + +SkBitmap CreateBitmap(int width, int height, SkColor color) { + SkBitmap bitmap; + bitmap.allocN32Pixels(width, height); + bitmap.eraseColor(color); + return bitmap; +} + +// Returns true if |lhs| and |rhs| have the same width and height and the +// pixel at position (0, 0) is the same color in both. +bool ImagesShareDimensionsAndColor(const SkBitmap& lhs, const SkBitmap& rhs) { + return lhs.width() == rhs.width() && lhs.height() == rhs.height() && + lhs.getColor(0, 0) == rhs.getColor(0, 0); +} + +} // namespace + TEST(NotificationStructTraitsTest, NotificationDataRoundtrip) { PlatformNotificationData notification_data; notification_data.title = base::ASCIIToUTF16("Title of my notification"); @@ -187,4 +206,45 @@ mojo::test::SerializeAndDeserialize<blink::mojom::NotificationData>( ¬ification_data, &platform_notification_data)); } + +TEST(NotificationStructTraitsTest, NotificationResourcesRoundtrip) { + NotificationResources resources; + + resources.image = CreateBitmap(200, 100, SK_ColorMAGENTA); + resources.notification_icon = CreateBitmap(100, 50, SK_ColorGREEN); + resources.badge = CreateBitmap(20, 10, SK_ColorBLUE); + + resources.action_icons.resize(2); + resources.action_icons[0] = CreateBitmap(10, 10, SK_ColorLTGRAY); + resources.action_icons[1] = CreateBitmap(11, 11, SK_ColorDKGRAY); + + NotificationResources roundtrip_resources; + + ASSERT_TRUE( + mojo::test::SerializeAndDeserialize<blink::mojom::NotificationResources>( + &resources, &roundtrip_resources)); + + ASSERT_FALSE(roundtrip_resources.image.empty()); + EXPECT_TRUE(ImagesShareDimensionsAndColor(resources.image, + roundtrip_resources.image)); + + ASSERT_FALSE(roundtrip_resources.notification_icon.empty()); + EXPECT_TRUE(ImagesShareDimensionsAndColor( + resources.notification_icon, roundtrip_resources.notification_icon)); + + ASSERT_FALSE(roundtrip_resources.badge.empty()); + EXPECT_TRUE(ImagesShareDimensionsAndColor(resources.badge, + roundtrip_resources.badge)); + + ASSERT_EQ(resources.action_icons.size(), + roundtrip_resources.action_icons.size()); + + for (size_t i = 0; i < roundtrip_resources.action_icons.size(); ++i) { + SCOPED_TRACE(base::StringPrintf("Action icon index: %zd", i)); + ASSERT_FALSE(roundtrip_resources.action_icons[i].empty()); + EXPECT_TRUE(ImagesShareDimensionsAndColor( + resources.action_icons[i], roundtrip_resources.action_icons[i])); + } +} + } // namespace content
diff --git a/content/common/notifications/notification_types.typemap b/content/common/notifications/notification_types.typemap index fd211e73..5ab8b9f 100644 --- a/content/common/notifications/notification_types.typemap +++ b/content/common/notifications/notification_types.typemap
@@ -3,7 +3,10 @@ # found in the LICENSE file. mojom = "//third_party/WebKit/public/platform/modules/notifications/notification.mojom" -public_headers = [ "//content/public/common/platform_notification_data.h" ] +public_headers = [ + "//content/public/common/notification_resources.h", + "//content/public/common/platform_notification_data.h", +] traits_headers = [ "//content/common/notifications/notification_struct_traits.h" ] deps = [ @@ -13,4 +16,5 @@ type_mappings = [ "blink.mojom.NotificationData=content::PlatformNotificationData", "blink.mojom.NotificationDirection=content::PlatformNotificationData::Direction", + "blink.mojom.NotificationResources=content::NotificationResources", ]
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc index a03f236d..61a1b08 100644 --- a/content/gpu/gpu_child_thread.cc +++ b/content/gpu/gpu_child_thread.cc
@@ -33,6 +33,7 @@ #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/connector.h" #include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h" +#include "skia/ext/event_tracer_impl.h" #if defined(USE_OZONE) #include "ui/ozone/public/ozone_platform.h" @@ -210,6 +211,8 @@ GetServiceManagerConnection()->AddConnectionFilter(std::move(filter)); StartServiceManagerConnection(); + + InitSkiaEventTracer(); } void GpuChildThread::CreateVizMainService(
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc index 018c4ce1..c989841e6 100644 --- a/content/gpu/gpu_main.cc +++ b/content/gpu/gpu_main.cc
@@ -30,6 +30,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" #include "content/public/common/result_codes.h" +#include "content/public/gpu/content_gpu_client.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/config/gpu_driver_bug_list.h" #include "gpu/config/gpu_info_collector.h" @@ -87,7 +88,6 @@ #if defined(OS_MACOSX) #include "base/message_loop/message_pump_mac.h" -#include "sandbox/mac/seatbelt.h" #include "services/service_manager/sandbox/mac/sandbox_mac.h" #endif @@ -99,14 +99,6 @@ #include "media/gpu/vaapi/vaapi_wrapper.h" #endif -#if defined(OS_MACOSX) -extern "C" { -void _LSSetApplicationLaunchServicesServerConnectionStatus( - uint64_t flags, - bool (^connection_allowed)(CFDictionaryRef)); -}; -#endif // defined(OS_MACOSX) - namespace content { namespace { @@ -177,7 +169,7 @@ #elif defined(OS_WIN) return StartSandboxWindows(sandbox_info_); #elif defined(OS_MACOSX) - return sandbox::Seatbelt::IsSandboxed(); + return service_manager::SandboxMac::IsCurrentlyActive(); #else return false; #endif @@ -274,9 +266,6 @@ // https://crbug.com/312462#c51 and https://crbug.com/783298 std::unique_ptr<base::MessagePump> pump(new base::MessagePumpNSRunLoop()); main_message_loop.reset(new base::MessageLoop(std::move(pump))); - - // Tell LaunchServices to continue without a connection to the daemon. - _LSSetApplicationLaunchServicesServerConnectionStatus(0, nullptr); #else main_message_loop.reset( new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT)); @@ -298,6 +287,7 @@ gpu_init->set_sandbox_helper(&sandbox_helper); + auto* client = GetContentClient()->gpu(); // Gpu initialization may fail for various reasons, in which case we will need // to tear down this process. However, we can not do so safely until the IPC // channel is set up, because the detection of early return of a child process @@ -307,7 +297,9 @@ // defer tearing down the GPU process until receiving the initialization // message from the browser (through mojom::VizMain::CreateGpuService()). const bool init_success = gpu_init->InitializeAndStartSandbox( - const_cast<base::CommandLine*>(&command_line), gpu_preferences); + const_cast<base::CommandLine*>(&command_line), gpu_preferences, + client ? client->GetGPUInfo() : nullptr, + client ? client->GetGpuFeatureInfo() : nullptr); const bool dead_on_arrival = !init_success; logging::SetLogMessageHandler(nullptr);
diff --git a/content/network/network_context.cc b/content/network/network_context.cc index ddd2766..4c65f2a 100644 --- a/content/network/network_context.cc +++ b/content/network/network_context.cc
@@ -43,11 +43,13 @@ #include "net/http/http_server_properties_manager.h" #include "net/http/http_transaction_factory.h" #include "net/proxy/proxy_config.h" +#include "net/reporting/reporting_policy.h" #include "net/ssl/channel_id_service.h" #include "net/ssl/default_channel_id_store.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" #include "services/network/proxy_config_service_mojo.h" +#include "services/network/public/cpp/network_features.h" #include "services/network/public/cpp/network_switches.h" namespace content { @@ -379,6 +381,16 @@ DCHECK(!network_context_params->enable_ftp_url_support); #endif +#if BUILDFLAG(ENABLE_REPORTING) + if (base::FeatureList::IsEnabled(features::kReporting)) + builder->set_reporting_policy(std::make_unique<net::ReportingPolicy>()); + else + builder->set_reporting_policy(nullptr); + + builder->set_network_error_logging_enabled( + base::FeatureList::IsEnabled(features::kNetworkErrorLogging)); +#endif // BUILDFLAG(ENABLE_REPORTING) + net::HttpNetworkSession::Params session_params; bool is_quic_force_disabled = false; if (quic_disabled)
diff --git a/content/network/network_context_unittest.cc b/content/network/network_context_unittest.cc index 23b203cb..62bebf3 100644 --- a/content/network/network_context_unittest.cc +++ b/content/network/network_context_unittest.cc
@@ -17,6 +17,7 @@ #include "base/run_loop.h" #include "base/strings/string_split.h" #include "base/test/mock_entropy_provider.h" +#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -43,6 +44,7 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" #include "net/url_request/url_request_job_factory.h" +#include "services/network/public/cpp/network_features.h" #include "services/network/public/interfaces/network_service.mojom.h" #include "services/network/public/interfaces/proxy_config.mojom.h" #include "testing/gtest/include/gtest/gtest.h" @@ -260,6 +262,46 @@ } #endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) +#if BUILDFLAG(ENABLE_REPORTING) +TEST_F(NetworkContextTest, DisableReporting) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndDisableFeature(features::kReporting); + + std::unique_ptr<NetworkContext> network_context = + CreateContextWithParams(CreateContextParams()); + EXPECT_FALSE(network_context->url_request_context()->reporting_service()); +} + +TEST_F(NetworkContextTest, EnableReporting) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndEnableFeature(features::kReporting); + + std::unique_ptr<NetworkContext> network_context = + CreateContextWithParams(CreateContextParams()); + EXPECT_TRUE(network_context->url_request_context()->reporting_service()); +} + +TEST_F(NetworkContextTest, DisableNetworkErrorLogging) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndDisableFeature(features::kNetworkErrorLogging); + + std::unique_ptr<NetworkContext> network_context = + CreateContextWithParams(CreateContextParams()); + EXPECT_FALSE( + network_context->url_request_context()->network_error_logging_delegate()); +} + +TEST_F(NetworkContextTest, EnableNetworkErrorLogging) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndEnableFeature(features::kNetworkErrorLogging); + + std::unique_ptr<NetworkContext> network_context = + CreateContextWithParams(CreateContextParams()); + EXPECT_TRUE( + network_context->url_request_context()->network_error_logging_delegate()); +} +#endif // BUILDFLAG(ENABLE_REPORTING) + TEST_F(NetworkContextTest, Http09Disabled) { network::mojom::NetworkContextParamsPtr context_params = CreateContextParams();
diff --git a/content/public/browser/gpu_data_manager.h b/content/public/browser/gpu_data_manager.h index 5d6601b5f..3ab8430 100644 --- a/content/public/browser/gpu_data_manager.h +++ b/content/public/browser/gpu_data_manager.h
@@ -68,12 +68,6 @@ // to access them again. virtual void UnblockDomainFrom3DAPIs(const GURL& url) = 0; - // Set GL strings. This triggers a re-calculation of GPU blacklist - // decision. - virtual void SetGLStrings(const std::string& gl_vendor, - const std::string& gl_renderer, - const std::string& gl_version) = 0; - virtual void DisableHardwareAcceleration() = 0; // Whether a GPU is in use (as opposed to a software renderer).
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 2792ade..ac4fc25 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -122,7 +122,7 @@ // same-origin to the top frame, or if a user gesture is being processed. const base::Feature kFramebustingNeedsSameOriginOrUserGesture{ "FramebustingNeedsSameOriginOrUserGesture", - base::FEATURE_ENABLED_BY_DEFAULT}; + base::FEATURE_DISABLED_BY_DEFAULT}; // Enables extended Gamepad API features like motion tracking and haptics. const base::Feature kGamepadExtensions{"GamepadExtensions",
diff --git a/content/renderer/media/media_devices_event_dispatcher_unittest.cc b/content/renderer/media/media_devices_event_dispatcher_unittest.cc index e3dbe6b..eb34cd27 100644 --- a/content/renderer/media/media_devices_event_dispatcher_unittest.cc +++ b/content/renderer/media/media_devices_event_dispatcher_unittest.cc
@@ -69,6 +69,14 @@ NOTREACHED(); } + void AddMediaDevicesListener( + bool subscribe_audio_input, + bool subscribe_video_input, + bool subscribe_audio_output, + blink::mojom::MediaDevicesListenerPtr listener) override { + NOTREACHED(); + } + blink::mojom::MediaDevicesDispatcherHostPtr CreateInterfacePtrAndBind() { blink::mojom::MediaDevicesDispatcherHostPtr ptr; binding_.Bind(mojo::MakeRequest(&ptr));
diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc index 7a573dd..227c156 100644 --- a/content/renderer/media/user_media_client_impl.cc +++ b/content/renderer/media/user_media_client_impl.cc
@@ -259,37 +259,6 @@ } } -void UserMediaClientImpl::SetMediaDeviceChangeObserver( - const blink::WebMediaDeviceChangeObserver& observer) { - media_device_change_observer_ = observer; - - // Do nothing if setting a valid observer while already subscribed or setting - // no observer while unsubscribed. - if (media_device_change_observer_.IsNull() == - device_change_subscription_ids_.empty()) - return; - - base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher = - MediaDevicesEventDispatcher::GetForRenderFrame(render_frame()); - if (media_device_change_observer_.IsNull()) { - event_dispatcher->UnsubscribeDeviceChangeNotifications( - device_change_subscription_ids_); - device_change_subscription_ids_.clear(); - } else { - DCHECK(device_change_subscription_ids_.empty()); - device_change_subscription_ids_ = - event_dispatcher->SubscribeDeviceChangeNotifications(base::Bind( - &UserMediaClientImpl::DevicesChanged, weak_factory_.GetWeakPtr())); - } -} - -void UserMediaClientImpl::DevicesChanged( - MediaDeviceType type, - const MediaDeviceInfoArray& device_infos) { - if (!media_device_change_observer_.IsNull()) - media_device_change_observer_.DidChangeMediaDevices(); -} - void UserMediaClientImpl::DeleteAllUserMediaRequests() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); user_media_processor_->StopAllProcessing();
diff --git a/content/renderer/media/user_media_client_impl.h b/content/renderer/media/user_media_client_impl.h index 2520cb6..3acbe9d 100644 --- a/content/renderer/media/user_media_client_impl.h +++ b/content/renderer/media/user_media_client_impl.h
@@ -7,7 +7,6 @@ #include <list> #include <memory> -#include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -16,12 +15,9 @@ #include "content/common/content_export.h" #include "content/common/media/media_devices.h" #include "content/public/renderer/render_frame_observer.h" -#include "content/renderer/media/media_devices_event_dispatcher.h" #include "content/renderer/media/user_media_processor.h" -#include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h" #include "third_party/WebKit/public/web/WebApplyConstraintsRequest.h" -#include "third_party/WebKit/public/web/WebMediaDeviceChangeObserver.h" #include "third_party/WebKit/public/web/WebUserMediaClient.h" #include "third_party/WebKit/public/web/WebUserMediaRequest.h" @@ -57,8 +53,6 @@ void RequestUserMedia(const blink::WebUserMediaRequest& web_request) override; void CancelUserMediaRequest( const blink::WebUserMediaRequest& web_request) override; - void SetMediaDeviceChangeObserver( - const blink::WebMediaDeviceChangeObserver& observer) override; void ApplyConstraints( const blink::WebApplyConstraintsRequest& web_request) override; void StopTrack(const blink::WebMediaStreamTrack& web_track) override; @@ -111,11 +105,6 @@ // RenderFrameObserver implementation. void OnDestruct() override; - // Callback invoked by MediaDevicesEventDispatcher when a device-change - // notification arrives. - void DevicesChanged(MediaDeviceType device_type, - const MediaDeviceInfoArray& device_infos); - const blink::mojom::MediaDevicesDispatcherHostPtr& GetMediaDevicesDispatcher(); @@ -133,11 +122,6 @@ bool is_processing_request_ = false; std::list<Request> pending_request_infos_; - MediaDevicesEventDispatcher::SubscriptionIdList - device_change_subscription_ids_; - - blink::WebMediaDeviceChangeObserver media_device_change_observer_; - SEQUENCE_CHECKER(sequence_checker_); // Note: This member must be the last to ensure all outstanding weak pointers
diff --git a/content/renderer/media/user_media_client_impl_unittest.cc b/content/renderer/media/user_media_client_impl_unittest.cc index a1c3f1c..b1a6c3ac 100644 --- a/content/renderer/media/user_media_client_impl_unittest.cc +++ b/content/renderer/media/user_media_client_impl_unittest.cc
@@ -242,6 +242,14 @@ MOCK_METHOD2(UnsubscribeDeviceChangeNotifications, void(MediaDeviceType type, uint32_t subscription_id)); + void AddMediaDevicesListener( + bool subscribe_audio_input, + bool subscribe_video_input, + bool subscribe_audio_output, + blink::mojom::MediaDevicesListenerPtr listener) override { + NOTREACHED(); + } + void GetAllVideoInputDeviceFormats( const std::string&, GetAllVideoInputDeviceFormatsCallback callback) override { @@ -437,8 +445,7 @@ public: UserMediaClientImplTest() : binding_user_media_processor_(&media_devices_dispatcher_), - binding_user_media_client_(&media_devices_dispatcher_), - binding_event_dispatcher_(&media_devices_dispatcher_) {} + binding_user_media_client_(&media_devices_dispatcher_) {} void SetUp() override { // Create our test object. @@ -464,18 +471,9 @@ mojo::MakeRequest(&user_media_client_host_proxy)); user_media_client_impl_->SetMediaDevicesDispatcherForTesting( std::move(user_media_client_host_proxy)); - - base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher = - MediaDevicesEventDispatcher::GetForRenderFrame(nullptr); - blink::mojom::MediaDevicesDispatcherHostPtr event_dispatcher_host_proxy; - binding_event_dispatcher_.Bind( - mojo::MakeRequest(&event_dispatcher_host_proxy)); - event_dispatcher->SetMediaDevicesDispatcherForTesting( - std::move(event_dispatcher_host_proxy)); } void TearDown() override { - MediaDevicesEventDispatcher::GetForRenderFrame(nullptr)->OnDestruct(); user_media_client_impl_.reset(); blink::WebHeap::CollectAllGarbageForTesting(); } @@ -621,8 +619,6 @@ binding_user_media_processor_; mojo::Binding<blink::mojom::MediaDevicesDispatcherHost> binding_user_media_client_; - mojo::Binding<blink::mojom::MediaDevicesDispatcherHost> - binding_event_dispatcher_; UserMediaProcessorUnderTest* user_media_processor_ = nullptr; // Owned by |user_media_client_impl_| @@ -1103,41 +1099,6 @@ EXPECT_EQ(kGeometry, properties.goog_array_geometry); } -TEST_F(UserMediaClientImplTest, ObserveMediaDeviceChanges) { - EXPECT_CALL(media_devices_dispatcher_, SubscribeDeviceChangeNotifications( - MEDIA_DEVICE_TYPE_AUDIO_INPUT, _)); - EXPECT_CALL(media_devices_dispatcher_, SubscribeDeviceChangeNotifications( - MEDIA_DEVICE_TYPE_VIDEO_INPUT, _)); - EXPECT_CALL( - media_devices_dispatcher_, - SubscribeDeviceChangeNotifications(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, _)); - user_media_client_impl_->SetMediaDeviceChangeObserver( - blink::WebMediaDeviceChangeObserver(true)); - base::RunLoop().RunUntilIdle(); - - base::WeakPtr<MediaDevicesEventDispatcher> event_dispatcher = - MediaDevicesEventDispatcher::GetForRenderFrame(nullptr); - event_dispatcher->DispatchDevicesChangedEvent(MEDIA_DEVICE_TYPE_AUDIO_INPUT, - MediaDeviceInfoArray()); - event_dispatcher->DispatchDevicesChangedEvent(MEDIA_DEVICE_TYPE_VIDEO_INPUT, - MediaDeviceInfoArray()); - event_dispatcher->DispatchDevicesChangedEvent(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, - MediaDeviceInfoArray()); - base::RunLoop().RunUntilIdle(); - - EXPECT_CALL(media_devices_dispatcher_, UnsubscribeDeviceChangeNotifications( - MEDIA_DEVICE_TYPE_AUDIO_INPUT, _)); - EXPECT_CALL(media_devices_dispatcher_, UnsubscribeDeviceChangeNotifications( - MEDIA_DEVICE_TYPE_VIDEO_INPUT, _)); - EXPECT_CALL( - media_devices_dispatcher_, - UnsubscribeDeviceChangeNotifications(MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, _)); - - user_media_client_impl_->SetMediaDeviceChangeObserver( - blink::WebMediaDeviceChangeObserver()); - base::RunLoop().RunUntilIdle(); -} - TEST_F(UserMediaClientImplTest, CreateWithMandatoryInvalidAudioDeviceId) { blink::WebMediaConstraints audio_constraints = CreateDeviceConstraints(kInvalidDeviceId);
diff --git a/content/renderer/media/webmediaplayer_ms.cc b/content/renderer/media/webmediaplayer_ms.cc index b528aa5..6cbca23 100644 --- a/content/renderer/media/webmediaplayer_ms.cc +++ b/content/renderer/media/webmediaplayer_ms.cc
@@ -502,6 +502,8 @@ delegate_->DidPlayerMutedStatusChange(delegate_id_, volume == 0.0); } +void WebMediaPlayerMS::PictureInPicture() {} + void WebMediaPlayerMS::SetSinkId( const blink::WebString& sink_id, const blink::WebSecurityOrigin& security_origin,
diff --git a/content/renderer/media/webmediaplayer_ms.h b/content/renderer/media/webmediaplayer_ms.h index ef57237..32eb788 100644 --- a/content/renderer/media/webmediaplayer_ms.h +++ b/content/renderer/media/webmediaplayer_ms.h
@@ -97,6 +97,7 @@ void Seek(double seconds) override; void SetRate(double rate) override; void SetVolume(double volume) override; + void PictureInPicture() override; void SetSinkId(const blink::WebString& sink_id, const blink::WebSecurityOrigin& security_origin, blink::WebSetSinkIdCallbacks* web_callback) override;
diff --git a/content/renderer/media/webmediaplayer_ms_unittest.cc b/content/renderer/media/webmediaplayer_ms_unittest.cc index b547abc..0fcb0b78 100644 --- a/content/renderer/media/webmediaplayer_ms_unittest.cc +++ b/content/renderer/media/webmediaplayer_ms_unittest.cc
@@ -527,6 +527,8 @@ const blink::WebString& remote_device_friendly_name) override {} void MediaRemotingStopped( blink::WebLocalizedString::Name error_msg) override {} + void PictureInPictureStarted() override {} + void PictureInPictureStopped() override {} // Implementation of cc::VideoFrameProvider::Client void StopUsingProvider() override;
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc index 4e28d7c..d7b5ed83 100644 --- a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc +++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
@@ -39,6 +39,7 @@ void Seek(double seconds) override {} void SetRate(double) override {} void SetVolume(double) override {} + void PictureInPicture() override {} blink::WebTimeRanges Buffered() const override { return blink::WebTimeRanges(); }
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 1475c85..0df9eb3 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1519,7 +1519,7 @@ bool support_locking = false; bool support_gles2_interface = true; - bool support_raster_interface = false; + bool support_raster_interface = true; bool support_oop_rasterization = false; shared_main_thread_contexts_ = CreateOffscreenContext( std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 5615937..172f5c45 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -1133,6 +1133,7 @@ web_attributes.support_stencil || web_attributes.support_antialias; attributes.sample_buffers = 0; attributes.bind_generates_resource = false; + attributes.enable_raster_interface = web_attributes.enable_raster_interface; // Prefer discrete GPU for WebGL. attributes.gpu_preference = gl::PreferDiscreteGpu;
diff --git a/content/renderer/webgraphicscontext3d_provider_impl.cc b/content/renderer/webgraphicscontext3d_provider_impl.cc index c4b8dc0..7d5be74 100644 --- a/content/renderer/webgraphicscontext3d_provider_impl.cc +++ b/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -4,6 +4,7 @@ #include "content/renderer/webgraphicscontext3d_provider_impl.h" +#include "cc/tiles/gpu_image_decode_cache.h" #include "components/viz/common/gl_helper.h" #include "gpu/command_buffer/client/context_support.h" #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" @@ -83,4 +84,23 @@ context_lost_callback_.Run(); } +cc::ImageDecodeCache* WebGraphicsContext3DProviderImpl::ImageDecodeCache() { + if (image_decode_cache_) + return image_decode_cache_.get(); + + // The max working set bytes is used to cap the maximum memory for images that + // can be pre-decoded and locked before rasterization. Since users of this + // context don't pre-decode images, this limit is not relevant. + static const size_t kMaxWorkingSetBytes = 0u; + + // TransferCache is used only with OOP raster. + const bool use_transfer_cache = false; + + DCHECK(provider_->RasterInterface()); + image_decode_cache_ = std::make_unique<cc::GpuImageDecodeCache>( + provider_.get(), use_transfer_cache, kN32_SkColorType, + kMaxWorkingSetBytes); + return image_decode_cache_.get(); +} + } // namespace content
diff --git a/content/renderer/webgraphicscontext3d_provider_impl.h b/content/renderer/webgraphicscontext3d_provider_impl.h index 75cbe07..3799885 100644 --- a/content/renderer/webgraphicscontext3d_provider_impl.h +++ b/content/renderer/webgraphicscontext3d_provider_impl.h
@@ -11,6 +11,10 @@ #include "content/common/content_export.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h" +namespace cc { +class ImageDecodeCache; +} // namespace cc + namespace gpu { namespace gles2 { class GLES2Interface; @@ -49,6 +53,7 @@ void SetErrorMessageCallback( base::RepeatingCallback<void(const char*, int32_t)>) override; void SignalQuery(uint32_t, base::OnceClosure) override; + cc::ImageDecodeCache* ImageDecodeCache() override; ui::ContextProviderCommandBuffer* context_provider() const { return provider_.get(); @@ -62,6 +67,7 @@ std::unique_ptr<viz::GLHelper> gl_helper_; const bool software_rendering_; base::RepeatingClosure context_lost_callback_; + std::unique_ptr<cc::ImageDecodeCache> image_decode_cache_; DISALLOW_COPY_AND_ASSIGN(WebGraphicsContext3DProviderImpl); };
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc index 5d6b814..60cb2243 100644 --- a/content/shell/browser/shell_url_request_context_getter.cc +++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -34,13 +34,13 @@ #include "net/http/http_network_session.h" #include "net/proxy/proxy_config_service.h" #include "net/proxy/proxy_service.h" -#include "net/reporting/reporting_feature.h" #include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_service.h" #include "net/ssl/channel_id_service.h" #include "net/ssl/default_channel_id_store.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" +#include "services/network/public/cpp/network_features.h" #include "services/network/public/cpp/network_switches.h" #include "url/url_constants.h"
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py index e609a23c..d692db3 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py
@@ -49,11 +49,8 @@ class WebGLConformanceExpectationsTest(unittest.TestCase): def testGlslConstructVecMatIndexExpectationOnWin(self): - # TODO(kbr): re-enable after Catapult rolls forward. crbug.com/801578 - if True: - return unittest.skip('Skipping due to crbug.com/801578') possible_browser = fakes.FakePossibleBrowser() - browser = possible_browser.Create(None) + browser = possible_browser.Create() browser.platform = FakeWindowsPlatform() browser.returned_system_info = fakes.FakeSystemInfo( gpu_dict=fake_win_amd_gpu_info.FAKE_GPU_INFO)
diff --git a/device/gamepad/BUILD.gn b/device/gamepad/BUILD.gn index f1e9fcde..157e762 100644 --- a/device/gamepad/BUILD.gn +++ b/device/gamepad/BUILD.gn
@@ -64,6 +64,8 @@ "hid_dll_functions_win.h", "raw_input_data_fetcher_win.cc", "raw_input_data_fetcher_win.h", + "raw_input_gamepad_device_win.cc", + "raw_input_gamepad_device_win.h", "udev_gamepad_linux.cc", "udev_gamepad_linux.h", "xbox_controller_mac.h",
diff --git a/device/gamepad/gamepad_provider.cc b/device/gamepad/gamepad_provider.cc index e2a273d..974237f3 100644 --- a/device/gamepad/gamepad_provider.cc +++ b/device/gamepad/gamepad_provider.cc
@@ -44,7 +44,7 @@ devices_changed_(true), ever_had_user_gesture_(false), sanitize_(true), - gamepad_shared_buffer_(new GamepadSharedBuffer()), + gamepad_shared_buffer_(std::make_unique<GamepadSharedBuffer>()), connection_change_client_(connection_change_client) { Initialize(std::unique_ptr<GamepadDataFetcher>()); } @@ -57,7 +57,7 @@ devices_changed_(true), ever_had_user_gesture_(false), sanitize_(true), - gamepad_shared_buffer_(new GamepadSharedBuffer()), + gamepad_shared_buffer_(std::make_unique<GamepadSharedBuffer>()), connection_change_client_(connection_change_client) { Initialize(std::move(fetcher)); }
diff --git a/device/gamepad/gamepad_shared_buffer.cc b/device/gamepad/gamepad_shared_buffer.cc index ca82bea..7d686ac 100644 --- a/device/gamepad/gamepad_shared_buffer.cc +++ b/device/gamepad/gamepad_shared_buffer.cc
@@ -7,8 +7,10 @@ namespace device { GamepadSharedBuffer::GamepadSharedBuffer() { - size_t data_size = sizeof(GamepadHardwareBuffer); - bool res = shared_memory_.CreateAndMapAnonymous(data_size); + base::SharedMemoryCreateOptions options; + options.size = sizeof(GamepadHardwareBuffer); + options.share_read_only = true; + bool res = shared_memory_.Create(options) && shared_memory_.Map(options.size); CHECK(res); void* mem = shared_memory_.memory();
diff --git a/device/gamepad/raw_input_data_fetcher_win.cc b/device/gamepad/raw_input_data_fetcher_win.cc index 9926ca6e..5ba9fdc3 100644 --- a/device/gamepad/raw_input_data_fetcher_win.cc +++ b/device/gamepad/raw_input_data_fetcher_win.cc
@@ -9,45 +9,21 @@ #include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" +#include "device/gamepad/gamepad_standard_mappings.h" namespace device { namespace { -float NormalizeAxis(long value, long min, long max) { - return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; -} - -unsigned long GetBitmask(unsigned short bits) { - return (1 << bits) - 1; -} - -// From the HID Usage Tables specification. -USHORT DeviceUsages[] = { - 0x04, // Joysticks - 0x05, // Gamepads - 0x08, // Multi Axis +const uint16_t DeviceUsages[] = { + RawInputGamepadDeviceWin::kGenericDesktopJoystick, + RawInputGamepadDeviceWin::kGenericDesktopGamePad, + RawInputGamepadDeviceWin::kGenericDesktopMultiAxisController, }; -const uint32_t kAxisMinimumUsageNumber = 0x30; -const uint32_t kGameControlsUsagePage = 0x05; -const uint32_t kButtonUsagePage = 0x09; - -const uint32_t kVendorOculus = 0x2833; -const uint32_t kVendorBlue = 0xb58e; - } // namespace -RawGamepadInfo::RawGamepadInfo() {} - -RawGamepadInfo::~RawGamepadInfo() {} - -RawInputDataFetcher::RawInputDataFetcher() - : rawinput_available_(false), - filter_xinput_(true), - events_monitored_(false), - last_source_id_(0), - last_enumeration_id_(0) {} +RawInputDataFetcher::RawInputDataFetcher() = default; RawInputDataFetcher::~RawInputDataFetcher() { StopMonitor(); @@ -101,8 +77,8 @@ // Register to receive raw HID input. std::unique_ptr<RAWINPUTDEVICE[]> devices( GetRawInputDevices(RIDEV_INPUTSINK)); - if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), - sizeof(RAWINPUTDEVICE))) { + if (!::RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), + sizeof(RAWINPUTDEVICE))) { PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK"; window_.reset(); return; @@ -119,8 +95,8 @@ DCHECK(window_); std::unique_ptr<RAWINPUTDEVICE[]> devices(GetRawInputDevices(RIDEV_REMOVE)); - if (!RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), - sizeof(RAWINPUTDEVICE))) { + if (!::RegisterRawInputDevices(devices.get(), arraysize(DeviceUsages), + sizeof(RAWINPUTDEVICE))) { PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE"; } @@ -129,11 +105,9 @@ } void RawInputDataFetcher::ClearControllers() { - while (!controllers_.empty()) { - RawGamepadInfo* gamepad_info = controllers_.begin()->second; - controllers_.erase(gamepad_info->handle); - delete gamepad_info; - } + for (const auto& entry : controllers_) + entry.second->Shutdown(); + controllers_.clear(); } void RawInputDataFetcher::GetGamepadData(bool devices_changed_hint) { @@ -143,33 +117,20 @@ if (devices_changed_hint) EnumerateDevices(); - for (const auto& controller : controllers_) { - RawGamepadInfo* gamepad = controller.second; - PadState* state = GetPadState(gamepad->source_id); + for (const auto& entry : controllers_) { + const RawInputGamepadDeviceWin* device = entry.second.get(); + PadState* state = GetPadState(device->GetSourceId()); if (!state) continue; - Gamepad& pad = state->data; - - pad.timestamp = gamepad->report_id; - pad.buttons_length = gamepad->buttons_length; - pad.axes_length = gamepad->axes_length; - - for (unsigned int i = 0; i < pad.buttons_length; i++) { - pad.buttons[i].pressed = gamepad->buttons[i]; - pad.buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0; - } - - for (unsigned int i = 0; i < pad.axes_length; i++) - pad.axes[i] = gamepad->axes[i].value; + device->ReadPadState(&state->data); } } void RawInputDataFetcher::EnumerateDevices() { - last_enumeration_id_++; - UINT count = 0; - UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)); + UINT result = + ::GetRawInputDeviceList(nullptr, &count, sizeof(RAWINPUTDEVICELIST)); if (result == static_cast<UINT>(-1)) { PLOG(ERROR) << "GetRawInputDeviceList() failed"; return; @@ -178,49 +139,75 @@ std::unique_ptr<RAWINPUTDEVICELIST[]> device_list( new RAWINPUTDEVICELIST[count]); - result = GetRawInputDeviceList(device_list.get(), &count, - sizeof(RAWINPUTDEVICELIST)); + result = ::GetRawInputDeviceList(device_list.get(), &count, + sizeof(RAWINPUTDEVICELIST)); if (result == static_cast<UINT>(-1)) { PLOG(ERROR) << "GetRawInputDeviceList() failed"; return; } DCHECK_EQ(count, result); + std::unordered_set<HANDLE> enumerated_device_handles; for (UINT i = 0; i < count; ++i) { if (device_list[i].dwType == RIM_TYPEHID) { HANDLE device_handle = device_list[i].hDevice; - ControllerMap::iterator controller = controllers_.find(device_handle); + auto controller_it = controllers_.find(device_handle); - RawGamepadInfo* gamepad; - if (controller != controllers_.end()) { - gamepad = controller->second; + RawInputGamepadDeviceWin* device; + if (controller_it != controllers_.end()) { + device = controller_it->second.get(); } else { - gamepad = ParseGamepadInfo(device_handle); - if (!gamepad) + int source_id = ++last_source_id_; + auto new_device = std::make_unique<RawInputGamepadDeviceWin>( + device_handle, source_id, hid_functions_.get()); + if (!new_device->IsValid()) { + new_device->Shutdown(); continue; + } - PadState* state = GetPadState(gamepad->source_id); - if (!state) + // The presence of "IG_" in the device name indicates that this is an + // XInput Gamepad. Skip enumerating these devices and let the XInput + // path handle it. + // http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx + const std::wstring device_name = new_device->GetDeviceName(); + if (filter_xinput_ && device_name.find(L"IG_") != std::wstring::npos) { + new_device->Shutdown(); + continue; + } + + PadState* state = GetPadState(source_id); + if (!state) { + new_device->Shutdown(); continue; // No slot available for this gamepad. + } - controllers_[device_handle] = gamepad; + auto emplace_result = + controllers_.emplace(device_handle, std::move(new_device)); + device = emplace_result.first->second.get(); Gamepad& pad = state->data; pad.connected = true; - std::string vendor = base::StringPrintf("%04x", gamepad->vendor_id); - std::string product = base::StringPrintf("%04x", gamepad->product_id); - std::string version = - base::StringPrintf("%04x", gamepad->version_number); + pad.vibration_actuator.type = GamepadHapticActuatorType::kDualRumble; + pad.vibration_actuator.not_null = false; + + const int vendor_int = device->GetVendorId(); + const int product_int = device->GetProductId(); + const int version_number = device->GetVersionNumber(); + const std::wstring product_string = device->GetProductString(); + + const std::string vendor = base::StringPrintf("%04x", vendor_int); + const std::string product = base::StringPrintf("%04x", product_int); + const std::string version = base::StringPrintf("%04x", version_number); state->mapper = GetGamepadStandardMappingFunction(vendor, product, version); state->axis_mask = 0; state->button_mask = 0; swprintf(pad.id, Gamepad::kIdLengthCap, - L"%ls (%lsVendor: %04x Product: %04x)", gamepad->id, - state->mapper ? L"STANDARD GAMEPAD " : L"", gamepad->vendor_id, - gamepad->product_id); + L"%ls (%lsVendor: %04x Product: %04x)", product_string.c_str(), + state->mapper ? L"STANDARD GAMEPAD " : L"", vendor_int, + product_int); if (state->mapper) swprintf(pad.mapping, Gamepad::kMappingLengthCap, L"standard"); @@ -228,294 +215,37 @@ pad.mapping[0] = 0; } - gamepad->enumeration_id = last_enumeration_id_; + enumerated_device_handles.insert(device_handle); } } // Clear out old controllers that weren't part of this enumeration pass. auto controller_it = controllers_.begin(); while (controller_it != controllers_.end()) { - RawGamepadInfo* gamepad = controller_it->second; - if (gamepad->enumeration_id != last_enumeration_id_) { + if (enumerated_device_handles.find(controller_it->first) == + enumerated_device_handles.end()) { + controller_it->second->Shutdown(); controller_it = controllers_.erase(controller_it); - delete gamepad; } else { ++controller_it; } } } -RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { - DCHECK(hid_functions_); - DCHECK(hid_functions_->IsValid()); - UINT size = 0; - - // Query basic device info. - UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, NULL, &size); - if (result == static_cast<UINT>(-1)) { - PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; - return NULL; +RawInputGamepadDeviceWin* RawInputDataFetcher::DeviceFromSourceId( + int source_id) { + for (const auto& entry : controllers_) { + if (entry.second->GetSourceId() == source_id) + return entry.second.get(); } - DCHECK_EQ(0u, result); - - std::unique_ptr<uint8_t[]> di_buffer(new uint8_t[size]); - RID_DEVICE_INFO* device_info = - reinterpret_cast<RID_DEVICE_INFO*>(di_buffer.get()); - result = - GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, di_buffer.get(), &size); - if (result == static_cast<UINT>(-1)) { - PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; - return NULL; - } - DCHECK_EQ(size, result); - - // Make sure this device is of a type that we want to observe. - bool valid_type = false; - for (USHORT device_usage : DeviceUsages) { - if (device_info->hid.usUsage == device_usage) { - valid_type = true; - break; - } - } - - // This is terrible, but the Oculus Rift and some Blue Yeti microphones seem - // to think they are gamepads. Filter out any such devices. Oculus Touch is - // handled elsewhere. - if (device_info->hid.dwVendorId == kVendorOculus || - device_info->hid.dwVendorId == kVendorBlue) { - valid_type = false; - } - - if (!valid_type) - return NULL; - - std::unique_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo); - gamepad_info->source_id = ++last_source_id_; - gamepad_info->handle = hDevice; - gamepad_info->report_id = 0; - gamepad_info->vendor_id = device_info->hid.dwVendorId; - gamepad_info->product_id = device_info->hid.dwProductId; - gamepad_info->version_number = device_info->hid.dwVersionNumber; - gamepad_info->buttons_length = 0; - ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); - gamepad_info->axes_length = 0; - ZeroMemory(gamepad_info->axes, sizeof(gamepad_info->axes)); - - // Query device identifier - result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, NULL, &size); - if (result == static_cast<UINT>(-1)) { - PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; - return NULL; - } - DCHECK_EQ(0u, result); - - std::unique_ptr<wchar_t[]> name_buffer(new wchar_t[size]); - result = - GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, name_buffer.get(), &size); - if (result == static_cast<UINT>(-1)) { - PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; - return NULL; - } - DCHECK_EQ(size, result); - - // The presence of "IG_" in the device name indicates that this is an XInput - // Gamepad. Skip enumerating these devices and let the XInput path handle it. - // http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014.aspx - if (filter_xinput_ && wcsstr(name_buffer.get(), L"IG_")) - return NULL; - - // Get a friendly device name - BOOLEAN got_product_string = FALSE; - HANDLE hid_handle = CreateFile( - name_buffer.get(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); - if (hid_handle) { - got_product_string = hid_functions_->HidDGetProductString()( - hid_handle, gamepad_info->id, sizeof(gamepad_info->id)); - CloseHandle(hid_handle); - } - - if (!got_product_string) - swprintf(gamepad_info->id, Gamepad::kIdLengthCap, L"Unknown Gamepad"); - - // Query device capabilities. - result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA, NULL, &size); - if (result == static_cast<UINT>(-1)) { - PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; - return NULL; - } - DCHECK_EQ(0u, result); - - gamepad_info->ppd_buffer.reset(new uint8_t[size]); - gamepad_info->preparsed_data = - reinterpret_cast<PHIDP_PREPARSED_DATA>(gamepad_info->ppd_buffer.get()); - result = GetRawInputDeviceInfo(hDevice, RIDI_PREPARSEDDATA, - gamepad_info->ppd_buffer.get(), &size); - if (result == static_cast<UINT>(-1)) { - PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; - return NULL; - } - DCHECK_EQ(size, result); - - HIDP_CAPS caps; - NTSTATUS status = - hid_functions_->HidPGetCaps()(gamepad_info->preparsed_data, &caps); - DCHECK_EQ(HIDP_STATUS_SUCCESS, status); - - // Query button information. - USHORT count = caps.NumberInputButtonCaps; - if (count > 0) { - std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps( - new HIDP_BUTTON_CAPS[count]); - status = hid_functions_->HidPGetButtonCaps()( - HidP_Input, button_caps.get(), &count, gamepad_info->preparsed_data); - DCHECK_EQ(HIDP_STATUS_SUCCESS, status); - - for (uint32_t i = 0; i < count; ++i) { - if (button_caps[i].Range.UsageMin <= Gamepad::kButtonsLengthCap && - button_caps[i].UsagePage == kButtonUsagePage) { - uint32_t max_index = - std::min(Gamepad::kButtonsLengthCap, - static_cast<size_t>(button_caps[i].Range.UsageMax)); - gamepad_info->buttons_length = - std::max(gamepad_info->buttons_length, max_index); - } - } - } - - // Query axis information. - count = caps.NumberInputValueCaps; - std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[count]); - status = hid_functions_->HidPGetValueCaps()( - HidP_Input, axes_caps.get(), &count, gamepad_info->preparsed_data); - - bool mapped_all_axes = true; - - for (UINT i = 0; i < count; i++) { - uint32_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; - if (axis_index < Gamepad::kAxesLengthCap) { - gamepad_info->axes[axis_index].caps = axes_caps[i]; - gamepad_info->axes[axis_index].value = 0; - gamepad_info->axes[axis_index].active = true; - gamepad_info->axes[axis_index].bitmask = GetBitmask(axes_caps[i].BitSize); - gamepad_info->axes_length = - std::max(gamepad_info->axes_length, axis_index + 1); - } else { - mapped_all_axes = false; - } - } - - if (!mapped_all_axes) { - // For axes who's usage puts them outside the standard axesLengthCap range. - uint32_t next_index = 0; - for (UINT i = 0; i < count; i++) { - uint32_t usage = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; - if (usage >= Gamepad::kAxesLengthCap && - axes_caps[i].UsagePage <= kGameControlsUsagePage) { - for (; next_index < Gamepad::kAxesLengthCap; ++next_index) { - if (!gamepad_info->axes[next_index].active) - break; - } - if (next_index < Gamepad::kAxesLengthCap) { - gamepad_info->axes[next_index].caps = axes_caps[i]; - gamepad_info->axes[next_index].value = 0; - gamepad_info->axes[next_index].active = true; - gamepad_info->axes[next_index].bitmask = - GetBitmask(axes_caps[i].BitSize); - gamepad_info->axes_length = - std::max(gamepad_info->axes_length, next_index + 1); - } - } - - if (next_index >= Gamepad::kAxesLengthCap) - break; - } - } - - // Sometimes devices show up with no buttons or axes. Don't return these. - if (gamepad_info->buttons_length == 0 && gamepad_info->axes_length == 0) - return nullptr; - - return gamepad_info.release(); -} - -void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, - RawGamepadInfo* gamepad_info) { - DCHECK(hid_functions_); - DCHECK(hid_functions_->IsValid()); - NTSTATUS status; - - gamepad_info->report_id++; - - // Query button state. - if (gamepad_info->buttons_length) { - // Clear the button state - ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); - ULONG buttons_length = 0; - - hid_functions_->HidPGetUsagesEx()( - HidP_Input, 0, NULL, &buttons_length, gamepad_info->preparsed_data, - reinterpret_cast<PCHAR>(input->data.hid.bRawData), - input->data.hid.dwSizeHid); - - std::unique_ptr<USAGE_AND_PAGE[]> usages( - new USAGE_AND_PAGE[buttons_length]); - status = hid_functions_->HidPGetUsagesEx()( - HidP_Input, 0, usages.get(), &buttons_length, - gamepad_info->preparsed_data, - reinterpret_cast<PCHAR>(input->data.hid.bRawData), - input->data.hid.dwSizeHid); - - if (status == HIDP_STATUS_SUCCESS) { - // Set each reported button to true. - for (uint32_t j = 0; j < buttons_length; j++) { - int32_t button_index = usages[j].Usage - 1; - if (usages[j].UsagePage == kButtonUsagePage && button_index >= 0 && - button_index < static_cast<int>(Gamepad::kButtonsLengthCap)) { - gamepad_info->buttons[button_index] = true; - } - } - } - } - - // Query axis state. - ULONG axis_value = 0; - LONG scaled_axis_value = 0; - for (uint32_t i = 0; i < gamepad_info->axes_length; i++) { - RawGamepadAxis* axis = &gamepad_info->axes[i]; - - // If the min is < 0 we have to query the scaled value, otherwise we need - // the normal unscaled value. - if (axis->caps.LogicalMin < 0) { - status = hid_functions_->HidPGetScaledUsageValue()( - HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin, - &scaled_axis_value, gamepad_info->preparsed_data, - reinterpret_cast<PCHAR>(input->data.hid.bRawData), - input->data.hid.dwSizeHid); - if (status == HIDP_STATUS_SUCCESS) { - axis->value = NormalizeAxis(scaled_axis_value, axis->caps.PhysicalMin, - axis->caps.PhysicalMax); - } - } else { - status = hid_functions_->HidPGetUsageValue()( - HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin, - &axis_value, gamepad_info->preparsed_data, - reinterpret_cast<PCHAR>(input->data.hid.bRawData), - input->data.hid.dwSizeHid); - if (status == HIDP_STATUS_SUCCESS) { - axis->value = NormalizeAxis(axis_value & axis->bitmask, - axis->caps.LogicalMin & axis->bitmask, - axis->caps.LogicalMax & axis->bitmask); - } - } - } + return nullptr; } LRESULT RawInputDataFetcher::OnInput(HRAWINPUT input_handle) { // Get the size of the input record. UINT size = 0; - UINT result = GetRawInputData(input_handle, RID_INPUT, NULL, &size, - sizeof(RAWINPUTHEADER)); + UINT result = ::GetRawInputData(input_handle, RID_INPUT, nullptr, &size, + sizeof(RAWINPUTHEADER)); if (result == static_cast<UINT>(-1)) { PLOG(ERROR) << "GetRawInputData() failed"; return 0; @@ -525,8 +255,8 @@ // Retrieve the input record. std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]); RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get()); - result = GetRawInputData(input_handle, RID_INPUT, buffer.get(), &size, - sizeof(RAWINPUTHEADER)); + result = ::GetRawInputData(input_handle, RID_INPUT, buffer.get(), &size, + sizeof(RAWINPUTHEADER)); if (result == static_cast<UINT>(-1)) { PLOG(ERROR) << "GetRawInputData() failed"; return 0; @@ -535,12 +265,12 @@ // Notify the observer about events generated locally. if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) { - ControllerMap::iterator it = controllers_.find(input->header.hDevice); + auto it = controllers_.find(input->header.hDevice); if (it != controllers_.end()) - UpdateGamepad(input, it->second); + it->second->UpdateGamepad(input); } - return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); + return ::DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); } bool RawInputDataFetcher::HandleMessage(UINT message,
diff --git a/device/gamepad/raw_input_data_fetcher_win.h b/device/gamepad/raw_input_data_fetcher_win.h index 06b827a..e37ee41 100644 --- a/device/gamepad/raw_input_data_fetcher_win.h +++ b/device/gamepad/raw_input_data_fetcher_win.h
@@ -14,57 +14,22 @@ #include <map> #include <memory> -#include <vector> #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/scoped_native_library.h" #include "base/win/message_window.h" -#include "build/build_config.h" #include "device/gamepad/gamepad_data_fetcher.h" -#include "device/gamepad/gamepad_standard_mappings.h" #include "device/gamepad/hid_dll_functions_win.h" #include "device/gamepad/public/cpp/gamepad.h" +#include "device/gamepad/raw_input_gamepad_device_win.h" namespace device { -struct RawGamepadAxis { - HIDP_VALUE_CAPS caps; - float value; - bool active; - unsigned long bitmask; -}; - -struct RawGamepadInfo { - RawGamepadInfo(); - ~RawGamepadInfo(); - - int source_id; - int enumeration_id; - HANDLE handle; - std::unique_ptr<uint8_t[]> ppd_buffer; - PHIDP_PREPARSED_DATA preparsed_data; - - uint32_t report_id; - uint32_t vendor_id; - uint32_t product_id; - uint32_t version_number; - - wchar_t id[Gamepad::kIdLengthCap]; - - uint32_t buttons_length; - bool buttons[Gamepad::kButtonsLengthCap]; - - uint32_t axes_length; - RawGamepadAxis axes[Gamepad::kAxesLengthCap]; -}; - class RawInputDataFetcher : public GamepadDataFetcher, public base::SupportsWeakPtr<RawInputDataFetcher> { public: - typedef GamepadDataFetcherFactoryImpl<RawInputDataFetcher, - GAMEPAD_SOURCE_WIN_RAW> - Factory; + using Factory = GamepadDataFetcherFactoryImpl<RawInputDataFetcher, + GAMEPAD_SOURCE_WIN_RAW>; explicit RawInputDataFetcher(); ~RawInputDataFetcher() override; @@ -80,8 +45,7 @@ void StartMonitor(); void StopMonitor(); void EnumerateDevices(); - RawGamepadInfo* ParseGamepadInfo(HANDLE hDevice); - void UpdateGamepad(RAWINPUT* input, RawGamepadInfo* gamepad_info); + RawInputGamepadDeviceWin* DeviceFromSourceId(int source_id); // Handles WM_INPUT messages. LRESULT OnInput(HRAWINPUT input_handle); // Handles messages received by |window_|. @@ -92,19 +56,31 @@ RAWINPUTDEVICE* GetRawInputDevices(DWORD flags); void ClearControllers(); + // The window to receive RawInput events. std::unique_ptr<base::win::MessageWindow> window_; - bool rawinput_available_; - bool filter_xinput_; - bool events_monitored_; - int last_source_id_; - int last_enumeration_id_; - typedef std::map<HANDLE, RawGamepadInfo*> ControllerMap; - ControllerMap controllers_; + // True if DLL loading succeeded and methods for enumerating and polling + // RawInput devices are available. + bool rawinput_available_ = false; + + // When true, XInput devices will not be enumerated by this data fetcher. + // This should be enabled when the platform data fetcher is active to avoid + // enumerating XInput gamepads twice. + bool filter_xinput_ = true; + + // True if we are registered to receive RawInput events. + bool events_monitored_ = false; + + // The last ID assigned to an enumerated device. + int last_source_id_ = 0; // HID functions loaded from hid.dll. std::unique_ptr<HidDllFunctionsWin> hid_functions_; + // Connected devices, keyed by device handle. + std::unordered_map<HANDLE, std::unique_ptr<RawInputGamepadDeviceWin>> + controllers_; + DISALLOW_COPY_AND_ASSIGN(RawInputDataFetcher); };
diff --git a/device/gamepad/raw_input_gamepad_device_win.cc b/device/gamepad/raw_input_gamepad_device_win.cc new file mode 100644 index 0000000..4f73ddf --- /dev/null +++ b/device/gamepad/raw_input_gamepad_device_win.cc
@@ -0,0 +1,345 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "raw_input_gamepad_device_win.h" + +namespace device { + +namespace { + +float NormalizeAxis(long value, long min, long max) { + return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; +} + +unsigned long GetBitmask(unsigned short bits) { + return (1 << bits) - 1; +} + +const uint32_t kAxisMinimumUsageNumber = 0x30; +const uint32_t kGameControlsUsagePage = 0x05; +const uint32_t kButtonUsagePage = 0x09; + +// Blacklisted vendor IDs. +const uint32_t kVendorOculus = 0x2833; +const uint32_t kVendorBlue = 0xb58e; + +} // namespace + +RawInputGamepadDeviceWin::RawInputGamepadDeviceWin( + HANDLE device_handle, + int source_id, + HidDllFunctionsWin* hid_functions) + : handle_(device_handle), + source_id_(source_id), + hid_functions_(hid_functions) { + ::ZeroMemory(buttons_, sizeof(buttons_)); + ::ZeroMemory(axes_, sizeof(axes_)); + + if (hid_functions_->IsValid()) + is_valid_ = QueryDeviceInfo(); +} + +RawInputGamepadDeviceWin::~RawInputGamepadDeviceWin() = default; + +// static +bool RawInputGamepadDeviceWin::IsGamepadUsageId(uint16_t usage) { + return usage == kGenericDesktopJoystick || usage == kGenericDesktopGamePad || + usage == kGenericDesktopMultiAxisController; +} + +void RawInputGamepadDeviceWin::UpdateGamepad(RAWINPUT* input) { + DCHECK(hid_functions_->IsValid()); + NTSTATUS status; + + report_id_++; + + // Query button state. + if (buttons_length_ > 0) { + // Clear the button state + ::ZeroMemory(buttons_, sizeof(buttons_)); + ULONG buttons_length = 0; + + hid_functions_->HidPGetUsagesEx()( + HidP_Input, 0, nullptr, &buttons_length, preparsed_data_, + reinterpret_cast<PCHAR>(input->data.hid.bRawData), + input->data.hid.dwSizeHid); + + std::unique_ptr<USAGE_AND_PAGE[]> usages( + new USAGE_AND_PAGE[buttons_length]); + status = hid_functions_->HidPGetUsagesEx()( + HidP_Input, 0, usages.get(), &buttons_length, preparsed_data_, + reinterpret_cast<PCHAR>(input->data.hid.bRawData), + input->data.hid.dwSizeHid); + + if (status == HIDP_STATUS_SUCCESS) { + // Set each reported button to true. + for (uint32_t j = 0; j < buttons_length; j++) { + int32_t button_index = usages[j].Usage - 1; + if (usages[j].UsagePage == kButtonUsagePage && button_index >= 0 && + button_index < static_cast<int>(Gamepad::kButtonsLengthCap)) { + buttons_[button_index] = true; + } + } + } + } + + // Query axis state. + ULONG axis_value = 0; + LONG scaled_axis_value = 0; + for (uint32_t i = 0; i < axes_length_; i++) { + RawGamepadAxis* axis = &axes_[i]; + + // If the min is < 0 we have to query the scaled value, otherwise we need + // the normal unscaled value. + if (axis->caps.LogicalMin < 0) { + status = hid_functions_->HidPGetScaledUsageValue()( + HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin, + &scaled_axis_value, preparsed_data_, + reinterpret_cast<PCHAR>(input->data.hid.bRawData), + input->data.hid.dwSizeHid); + if (status == HIDP_STATUS_SUCCESS) { + axis->value = NormalizeAxis(scaled_axis_value, axis->caps.PhysicalMin, + axis->caps.PhysicalMax); + } + } else { + status = hid_functions_->HidPGetUsageValue()( + HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin, + &axis_value, preparsed_data_, + reinterpret_cast<PCHAR>(input->data.hid.bRawData), + input->data.hid.dwSizeHid); + if (status == HIDP_STATUS_SUCCESS) { + axis->value = NormalizeAxis(axis_value & axis->bitmask, + axis->caps.LogicalMin & axis->bitmask, + axis->caps.LogicalMax & axis->bitmask); + } + } + } +} + +void RawInputGamepadDeviceWin::ReadPadState(Gamepad* pad) const { + DCHECK(pad); + + pad->timestamp = report_id_; + pad->buttons_length = buttons_length_; + pad->axes_length = axes_length_; + + for (unsigned int i = 0; i < buttons_length_; i++) { + pad->buttons[i].pressed = buttons_[i]; + pad->buttons[i].value = buttons_[i] ? 1.0 : 0.0; + } + + for (unsigned int i = 0; i < axes_length_; i++) + pad->axes[i] = axes_[i].value; +} + +bool RawInputGamepadDeviceWin::QueryDeviceInfo() { + // Fetch HID properties (RID_DEVICE_INFO_HID) for this device. This includes + // |vendor_id_|, |product_id_|, |version_number_|, and |usage_|. + if (!QueryHidInfo()) + return false; + + // Make sure this device is of a type that we want to observe. + if (!IsGamepadUsageId(usage_)) + return false; + + // This is terrible, but the Oculus Rift and some Blue Yeti microphones seem + // to think they are gamepads. Filter out any such devices. Oculus Touch is + // handled elsewhere. + if (vendor_id_ == kVendorOculus || vendor_id_ == kVendorBlue) + return false; + + // Fetch the device's |name_| (RIDI_DEVICENAME). + if (!QueryDeviceName()) + return false; + + // Fetch the human-friendly |product_string_|, if available. + if (!QueryProductString()) + product_string_ = L"Unknown Gamepad"; + + // Fetch information about the buttons and axes on this device. This sets + // |buttons_length_| and |axes_length_| to their correct values and populates + // |axes_| with capabilities info. + if (!QueryDeviceCapabilities()) + return false; + + // Gamepads must have at least one button or axis. + if (buttons_length_ == 0 && axes_length_ == 0) + return false; + + return true; +} + +bool RawInputGamepadDeviceWin::QueryHidInfo() { + UINT size = 0; + + UINT result = + ::GetRawInputDeviceInfo(handle_, RIDI_DEVICEINFO, nullptr, &size); + if (result == static_cast<UINT>(-1)) { + PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; + return false; + } + DCHECK_EQ(0u, result); + + std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]); + result = + ::GetRawInputDeviceInfo(handle_, RIDI_DEVICEINFO, buffer.get(), &size); + if (result == static_cast<UINT>(-1)) { + PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; + return false; + } + DCHECK_EQ(size, result); + RID_DEVICE_INFO* device_info = + reinterpret_cast<RID_DEVICE_INFO*>(buffer.get()); + + DCHECK_EQ(device_info->dwType, static_cast<DWORD>(RIM_TYPEHID)); + vendor_id_ = device_info->hid.dwVendorId; + product_id_ = device_info->hid.dwProductId; + version_number_ = device_info->hid.dwVersionNumber; + usage_ = device_info->hid.usUsage; + + return true; +} + +bool RawInputGamepadDeviceWin::QueryDeviceName() { + UINT size = 0; + + UINT result = + ::GetRawInputDeviceInfo(handle_, RIDI_DEVICENAME, nullptr, &size); + if (result == static_cast<UINT>(-1)) { + PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; + return false; + } + DCHECK_EQ(0u, result); + + std::unique_ptr<wchar_t[]> buffer(new wchar_t[size]); + result = + ::GetRawInputDeviceInfo(handle_, RIDI_DEVICENAME, buffer.get(), &size); + if (result == static_cast<UINT>(-1)) { + PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; + return false; + } + DCHECK_EQ(size, result); + + name_ = buffer.get(); + + return true; +} + +bool RawInputGamepadDeviceWin::QueryProductString() { + DCHECK(hid_functions_); + DCHECK(hid_functions_->IsValid()); + base::win::ScopedHandle hid_handle(::CreateFile( + name_.c_str(), GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL)); + if (!hid_handle.IsValid()) + return false; + product_string_.resize(Gamepad::kIdLengthCap); + return hid_functions_->HidDGetProductString()( + hid_handle.Get(), &product_string_.front(), Gamepad::kIdLengthCap); +} + +bool RawInputGamepadDeviceWin::QueryDeviceCapabilities() { + DCHECK(hid_functions_); + DCHECK(hid_functions_->IsValid()); + UINT size = 0; + + UINT result = + ::GetRawInputDeviceInfo(handle_, RIDI_PREPARSEDDATA, nullptr, &size); + if (result == static_cast<UINT>(-1)) { + PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; + return false; + } + DCHECK_EQ(0u, result); + + ppd_buffer_.reset(new uint8_t[size]); + preparsed_data_ = reinterpret_cast<PHIDP_PREPARSED_DATA>(ppd_buffer_.get()); + result = ::GetRawInputDeviceInfo(handle_, RIDI_PREPARSEDDATA, + ppd_buffer_.get(), &size); + if (result == static_cast<UINT>(-1)) { + PLOG(ERROR) << "GetRawInputDeviceInfo() failed"; + return false; + } + DCHECK_EQ(size, result); + + HIDP_CAPS caps; + NTSTATUS status = hid_functions_->HidPGetCaps()(preparsed_data_, &caps); + DCHECK_EQ(HIDP_STATUS_SUCCESS, status); + + QueryButtonCapabilities(caps.NumberInputButtonCaps); + QueryAxisCapabilities(caps.NumberInputValueCaps); + + return true; +} + +void RawInputGamepadDeviceWin::QueryButtonCapabilities(uint16_t button_count) { + DCHECK(hid_functions_); + DCHECK(hid_functions_->IsValid()); + if (button_count > 0) { + std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps( + new HIDP_BUTTON_CAPS[button_count]); + NTSTATUS status = hid_functions_->HidPGetButtonCaps()( + HidP_Input, button_caps.get(), &button_count, preparsed_data_); + DCHECK_EQ(HIDP_STATUS_SUCCESS, status); + + for (size_t i = 0; i < button_count; ++i) { + if (button_caps[i].Range.UsageMin <= Gamepad::kButtonsLengthCap && + button_caps[i].UsagePage == kButtonUsagePage) { + size_t max_index = + std::min(Gamepad::kButtonsLengthCap, + static_cast<size_t>(button_caps[i].Range.UsageMax)); + buttons_length_ = std::max(buttons_length_, max_index); + } + } + } +} + +void RawInputGamepadDeviceWin::QueryAxisCapabilities(uint16_t axis_count) { + DCHECK(hid_functions_); + DCHECK(hid_functions_->IsValid()); + std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[axis_count]); + hid_functions_->HidPGetValueCaps()(HidP_Input, axes_caps.get(), &axis_count, + preparsed_data_); + + bool mapped_all_axes = true; + + for (size_t i = 0; i < axis_count; i++) { + size_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; + if (axis_index < Gamepad::kAxesLengthCap) { + axes_[axis_index].caps = axes_caps[i]; + axes_[axis_index].value = 0; + axes_[axis_index].active = true; + axes_[axis_index].bitmask = GetBitmask(axes_caps[i].BitSize); + axes_length_ = std::max(axes_length_, axis_index + 1); + } else { + mapped_all_axes = false; + } + } + + if (!mapped_all_axes) { + // For axes whose usage puts them outside the standard axesLengthCap range. + size_t next_index = 0; + for (size_t i = 0; i < axis_count; i++) { + size_t usage = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber; + if (usage >= Gamepad::kAxesLengthCap && + axes_caps[i].UsagePage <= kGameControlsUsagePage) { + for (; next_index < Gamepad::kAxesLengthCap; ++next_index) { + if (!axes_[next_index].active) + break; + } + if (next_index < Gamepad::kAxesLengthCap) { + axes_[next_index].caps = axes_caps[i]; + axes_[next_index].value = 0; + axes_[next_index].active = true; + axes_[next_index].bitmask = GetBitmask(axes_caps[i].BitSize); + axes_length_ = std::max(axes_length_, next_index + 1); + } + } + + if (next_index >= Gamepad::kAxesLengthCap) + break; + } + } +} + +} // namespace device
diff --git a/device/gamepad/raw_input_gamepad_device_win.h b/device/gamepad/raw_input_gamepad_device_win.h new file mode 100644 index 0000000..45c1d3a --- /dev/null +++ b/device/gamepad/raw_input_gamepad_device_win.h
@@ -0,0 +1,122 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_GAMEPAD_RAW_INPUT_GAMEPAD_DEVICE_WIN_ +#define DEVICE_GAMEPAD_RAW_INPUT_GAMEPAD_DEVICE_WIN_ + +#include <Unknwn.h> +#include <WinDef.h> +#include <hidsdi.h> +#include <stdint.h> +#include <stdlib.h> +#include <windows.h> + +#include <memory> + +#include "device/gamepad/abstract_haptic_gamepad.h" +#include "device/gamepad/hid_dll_functions_win.h" +#include "device/gamepad/public/cpp/gamepad.h" + +namespace device { + +class RawInputGamepadDeviceWin : public AbstractHapticGamepad { + public: + // Relevant usage IDs within the Generic Desktop usage page. RawInput gamepads + // must have one of these usage IDs. + static const uint16_t kGenericDesktopJoystick = 0x04; + static const uint16_t kGenericDesktopGamePad = 0x05; + static const uint16_t kGenericDesktopMultiAxisController = 0x08; + + RawInputGamepadDeviceWin(HANDLE device_handle, + int source_id, + HidDllFunctionsWin* hid_functions); + ~RawInputGamepadDeviceWin() override; + + static bool IsGamepadUsageId(uint16_t usage); + + int GetSourceId() const { return source_id_; } + int GetVendorId() const { return vendor_id_; } + int GetVersionNumber() const { return version_number_; } + int GetProductId() const { return product_id_; } + std::wstring GetDeviceName() const { return name_; } + std::wstring GetProductString() const { return product_string_; } + + // Return true if this device is a gamepad. + bool IsValid() const { return is_valid_; } + + // Updates the current gamepad state with data from a RAWINPUT event. + void UpdateGamepad(RAWINPUT* input); + + // Read the current gamepad state into |pad|. + void ReadPadState(Gamepad* pad) const; + + // Set the vibration magnitude for the strong and weak vibration actuators. + void SetVibration(double strong_magnitude, double weak_magnitude) override {} + + private: + // Axis state and capabilities for a single RawInput axis. + struct RawGamepadAxis { + HIDP_VALUE_CAPS caps; + float value; + bool active; + unsigned long bitmask; + }; + + // Fetch information about this device. Returns true if the device appears to + // be a valid gamepad. + bool QueryDeviceInfo(); + + // Fetch HID properties (RID_DEVICE_INFO_HID). Returns false on failure. + bool QueryHidInfo(); + + // Fetch the device name (RIDI_DEVICENAME). Returns false on failure. + bool QueryDeviceName(); + + // Fetch the product string. Returns false if none is available. + bool QueryProductString(); + + // These methods fetch information about the capabilities of buttons and axes + // on the device. + bool QueryDeviceCapabilities(); + void QueryButtonCapabilities(uint16_t button_count); + void QueryAxisCapabilities(uint16_t axis_count); + + // True if the device described by this object is a valid RawInput gamepad. + bool is_valid_ = false; + + // The device handle. + HANDLE handle_ = nullptr; + + // The index assigned to this gamepad by the data fetcher. + int source_id_ = 0; + + // Functions loaded from hid.dll. Not owned. + HidDllFunctionsWin* hid_functions_ = nullptr; + + // The report ID incremented each time an input message is received for this + // device. It is included in the pad info in place of a timestamp. + uint32_t report_id_ = 0; + + uint32_t vendor_id_ = 0; + uint32_t product_id_ = 0; + uint32_t version_number_ = 0; + uint16_t usage_ = 0; + std::wstring name_; + std::wstring product_string_; + + size_t buttons_length_ = 0; + bool buttons_[Gamepad::kButtonsLengthCap]; + + size_t axes_length_ = 0; + RawGamepadAxis axes_[Gamepad::kAxesLengthCap]; + + // Buffer used for querying device capabilities. |ppd_buffer_| owns the + // memory pointed to by |preparsed_data_|. + std::unique_ptr<uint8_t[]> ppd_buffer_; + PHIDP_PREPARSED_DATA preparsed_data_ = nullptr; +}; + +} // namespace device + +#endif // DEVICE_GAMEPAD_RAW_INPUT_GAMEPAD_DEVICE_WIN_
diff --git a/device/vr/openvr/openvr_device_provider.cc b/device/vr/openvr/openvr_device_provider.cc index 7175900..b2ae187 100644 --- a/device/vr/openvr/openvr_device_provider.cc +++ b/device/vr/openvr/openvr_device_provider.cc
@@ -4,6 +4,7 @@ #include "device/vr/openvr/openvr_device_provider.h" +#include "base/metrics/histogram_macros.h" #include "device/gamepad/gamepad_data_fetcher_manager.h" #include "device/vr/openvr/openvr_device.h" #include "device/vr/openvr/openvr_gamepad_data_fetcher.h" @@ -11,6 +12,14 @@ namespace device { +void OpenVRDeviceProvider::RecordRuntimeAvailability() { + XrRuntimeAvailable runtime = XrRuntimeAvailable::NONE; + if (vr::VR_IsRuntimeInstalled()) + runtime = XrRuntimeAvailable::OPENVR; + UMA_HISTOGRAM_ENUMERATION("XR.RuntimeAvailable", runtime, + XrRuntimeAvailable::COUNT); +} + OpenVRDeviceProvider::OpenVRDeviceProvider() = default; OpenVRDeviceProvider::~OpenVRDeviceProvider() {
diff --git a/device/vr/openvr/openvr_device_provider.h b/device/vr/openvr/openvr_device_provider.h index 8483d1a..3d2ee82 100644 --- a/device/vr/openvr/openvr_device_provider.h +++ b/device/vr/openvr/openvr_device_provider.h
@@ -27,6 +27,8 @@ bool Initialized() override; + static void RecordRuntimeAvailability(); + private: void CreateDevice();
diff --git a/device/vr/vr_device.h b/device/vr/vr_device.h index 2f8e732..fc4a0ba 100644 --- a/device/vr/vr_device.h +++ b/device/vr/vr_device.h
@@ -12,7 +12,8 @@ namespace device { -// Must match VRViewerType in enums.xml. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class VrViewerType { GVR_UNKNOWN = 0, GVR_CARDBOARD = 1, @@ -25,6 +26,14 @@ VIEWER_TYPE_COUNT, }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class XrRuntimeAvailable { + NONE = 0, + OPENVR = 1, + COUNT, +}; + const unsigned int VR_DEVICE_LAST_ID = 0xFFFFFFFF; // Represents one of the platform's VR devices. Owned by the respective
diff --git a/extensions/browser/api/execute_code_function.cc b/extensions/browser/api/execute_code_function.cc index ab9d4b5..099079901 100644 --- a/extensions/browser/api/execute_code_function.cc +++ b/extensions/browser/api/execute_code_function.cc
@@ -31,6 +31,8 @@ const char kBadFileEncodingError[] = "Could not load file '*' for content script. It isn't UTF-8 encoded."; const char kLoadFileError[] = "Failed to load file: \"*\". "; +const char kCSSOriginForNonCSSError[] = + "CSS origin should be specified only for CSS code."; } @@ -147,12 +149,18 @@ } CHECK_NE(UserScript::UNDEFINED, run_at); + base::Optional<CSSOrigin> css_origin; + if (details_->css_origin == api::extension_types::CSS_ORIGIN_USER) + css_origin = CSS_ORIGIN_USER; + else if (details_->css_origin == api::extension_types::CSS_ORIGIN_AUTHOR) + css_origin = CSS_ORIGIN_AUTHOR; + executor->ExecuteScript( host_id_, script_type, code_string, frame_scope, frame_id, match_about_blank, run_at, ScriptExecutor::ISOLATED_WORLD, IsWebView() ? ScriptExecutor::WEB_VIEW_PROCESS : ScriptExecutor::DEFAULT_PROCESS, - GetWebViewSrc(), file_url_, user_gesture(), + GetWebViewSrc(), file_url_, user_gesture(), css_origin, has_callback() ? ScriptExecutor::JSON_SERIALIZED_RESULT : ScriptExecutor::NO_RESULT, base::Bind(&ExecuteCodeFunction::OnExecuteCodeFinished, this)); @@ -180,6 +188,11 @@ error_ = kMoreThanOneValuesError; return false; } + if (details_->css_origin != api::extension_types::CSS_ORIGIN_NONE && + !ShouldInsertCSS()) { + error_ = kCSSOriginForNonCSSError; + return false; + } if (!CanExecuteScriptOnPage()) return false;
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc index f28c62a5..6dacb64 100644 --- a/extensions/browser/api/networking_private/networking_private_chromeos.cc +++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -550,7 +550,7 @@ NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork( service_path, success_callback, base::Bind(&NetworkHandlerFailureCallback, failure_callback), - check_error_state); + check_error_state, chromeos::ConnectCallbackMode::ON_STARTED); } void NetworkingPrivateChromeOS::StartDisconnect(
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index c34e4480..e5446c805 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1272,6 +1272,7 @@ CRYPTOTOKENPRIVATE_ISAPPIDHASHINENTERPRISECONTEXT, CRYPTOTOKENPRIVATE_CANAPPIDGETATTESTATION, SYSTEM_DISPLAY_SETMIRRORMODE, + TTSENGINE_UPDATEVOICES, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/browser/script_executor.cc b/extensions/browser/script_executor.cc index 9adc646..c3cfa38 100644 --- a/extensions/browser/script_executor.cc +++ b/extensions/browser/script_executor.cc
@@ -242,6 +242,7 @@ const GURL& webview_src, const GURL& file_url, bool user_gesture, + base::Optional<CSSOrigin> css_origin, ScriptExecutor::ResultType result_type, const ExecuteScriptCallback& callback) { if (host_id.type() == HostID::EXTENSIONS) { @@ -268,6 +269,7 @@ params.file_url = file_url; params.wants_result = (result_type == JSON_SERIALIZED_RESULT); params.user_gesture = user_gesture; + params.css_origin = css_origin; // Handler handles IPCs and deletes itself on completion. new Handler(script_observers_, web_contents_, params, frame_scope, frame_id,
diff --git a/extensions/browser/script_executor.h b/extensions/browser/script_executor.h index 25e6c54..46cb9bb95 100644 --- a/extensions/browser/script_executor.h +++ b/extensions/browser/script_executor.h
@@ -7,6 +7,8 @@ #include "base/callback_forward.h" #include "base/observer_list.h" +#include "base/optional.h" +#include "extensions/common/constants.h" #include "extensions/common/user_script.h" class GURL; @@ -101,6 +103,7 @@ const GURL& webview_src, const GURL& file_url, bool user_gesture, + base::Optional<CSSOrigin> css_origin, ResultType result_type, const ExecuteScriptCallback& callback);
diff --git a/extensions/common/api/extension_types.json b/extensions/common/api/extension_types.json index 9f27590..e2ea16dc 100644 --- a/extensions/common/api/extension_types.json +++ b/extensions/common/api/extension_types.json
@@ -39,6 +39,12 @@ "description": "The soonest that the JavaScript or CSS will be injected into the tab." }, { + "id": "CSSOrigin", + "type": "string", + "enum": ["author", "user"], + "description": "The <a href=\"https://www.w3.org/TR/css3-cascade/#cascading-origins\">origin</a> of injected CSS." + }, + { "id": "InjectDetails", "type": "object", "description": "Details of the script or CSS to inject. Either the code or the file property must be set, but both may not be set at the same time.", @@ -61,6 +67,11 @@ "$ref": "RunAt", "optional": true, "description": "The soonest that the JavaScript or CSS will be injected into the tab. Defaults to \"document_idle\"." + }, + "cssOrigin": { + "$ref": "CSSOrigin", + "optional": true, + "description": "The <a href=\"https://www.w3.org/TR/css3-cascade/#cascading-origins\">origin</a> of the CSS to inject. This may only be specified for CSS, not JavaScript. Defaults to <code>\"author\"</code>." } } }
diff --git a/extensions/common/api/networking_onc.idl b/extensions/common/api/networking_onc.idl index 0db827fa..a130a1a 100644 --- a/extensions/common/api/networking_onc.idl +++ b/extensions/common/api/networking_onc.idl
@@ -997,7 +997,9 @@ // |networkGuid|: The GUID of the network to connect to. // |callback|: Called when the connect request has been sent. Note: the // connection may not have completed. Observe $(ref:onNetworksChanged) - // to be notified when a network state changes. + // to be notified when a network state changes. If the connect request + // immediately failed (e.g. the network is unconfigured), + // $(ref:runtime.lastError) will be set with a failure reason. static void startConnect(DOMString networkGuid, optional VoidCallback callback);
diff --git a/extensions/common/api/networking_private.idl b/extensions/common/api/networking_private.idl index cb25d0cd..4daf58df 100644 --- a/extensions/common/api/networking_private.idl +++ b/extensions/common/api/networking_private.idl
@@ -425,7 +425,7 @@ DOMString? Password; long? Port; DOMString? Proto; - DOMString? PushPeerInfo; + boolean? PushPeerInfo; DOMString? RemoteCertEKU; DOMString[]? RemoteCertKU; DOMString? RemoteCertTLS; @@ -466,7 +466,7 @@ ManagedDOMString? Password; ManagedLong? Port; ManagedDOMString? Proto; - ManagedDOMString? PushPeerInfo; + ManagedBoolean? PushPeerInfo; ManagedDOMString? RemoteCertEKU; ManagedDOMStringList? RemoteCertKU; ManagedDOMString? RemoteCertTLS; @@ -904,7 +904,7 @@ callback GetGlobalPolicyCallback = void(GlobalPolicy result); callback GetCertificateListsCallback = void(CertificateLists result); - // These functions all report failures via chrome.runtime.lastError. + // These functions all report failures via $(ref:runtime.lastError). interface Functions { // Gets all the properties of the network with id networkGuid. Includes all // properties of the network (read-only and read/write values). @@ -1012,7 +1012,9 @@ // |networkGuid|: The GUID of the network to connect to. // |callback|: Called when the connect request has been sent. Note: the // connection may not have completed. Observe $(ref:onNetworksChanged) - // to be notified when a network state changes. + // to be notified when a network state changes. If the connect request + // immediately failed (e.g. the network is unconfigured), + // $(ref:runtime.lastError) will be set with a failure reason. static void startConnect(DOMString networkGuid, optional VoidCallback callback); @@ -1120,7 +1122,7 @@ // the operation will fail. This will not lock the SIM; that is handled // automatically by the device. NOTE: If the SIM is locked, it must first be // unlocked with unlockCellularSim() before this can be called (otherwise it - // will fail and chrome.runtime.lastError will be set to Error.SimLocked). + // will fail and $(ref:runtime.lastError) will be set to Error.SimLocked). // |networkGuid|: The GUID of the cellular network to set the SIM state of. // If empty, the default cellular device will be used. // |simState|: The SIM state to set.
diff --git a/extensions/common/constants.h b/extensions/common/constants.h index b96eb342..a55a018 100644 --- a/extensions/common/constants.h +++ b/extensions/common/constants.h
@@ -185,6 +185,10 @@ NUM_LAUNCH_CONTAINERS }; +// The origin of injected CSS. +enum CSSOrigin { CSS_ORIGIN_AUTHOR, CSS_ORIGIN_USER }; +static const CSSOrigin CSS_ORIGIN_LAST = CSS_ORIGIN_USER; + } // namespace extensions namespace extension_misc {
diff --git a/extensions/common/extension_messages.h b/extensions/common/extension_messages.h index f21c902..790420a 100644 --- a/extensions/common/extension_messages.h +++ b/extensions/common/extension_messages.h
@@ -18,6 +18,7 @@ #include "content/public/common/socket_permission_request.h" #include "extensions/common/api/messaging/message.h" #include "extensions/common/api/messaging/port_id.h" +#include "extensions/common/constants.h" #include "extensions/common/common_param_traits.h" #include "extensions/common/draggable_region.h" #include "extensions/common/event_filtering_info.h" @@ -38,6 +39,8 @@ #define IPC_MESSAGE_START ExtensionMsgStart +IPC_ENUM_TRAITS_MAX_VALUE(extensions::CSSOrigin, extensions::CSS_ORIGIN_LAST) + IPC_ENUM_TRAITS_MAX_VALUE(extensions::ViewType, extensions::VIEW_TYPE_LAST) IPC_ENUM_TRAITS_MAX_VALUE(content::SocketPermissionRequest::OperationType, content::SocketPermissionRequest::OPERATION_TYPE_LAST) @@ -179,6 +182,9 @@ // Whether the code to be executed should be associated with a user gesture. IPC_STRUCT_MEMBER(bool, user_gesture) + + // The origin of the CSS. + IPC_STRUCT_MEMBER(base::Optional<extensions::CSSOrigin>, css_origin) IPC_STRUCT_END() // Struct containing information about the sender of connect() calls that
diff --git a/extensions/renderer/programmatic_script_injector.cc b/extensions/renderer/programmatic_script_injector.cc index 0e0b0de..7b55c0d 100644 --- a/extensions/renderer/programmatic_script_injector.cc +++ b/extensions/renderer/programmatic_script_injector.cc
@@ -47,6 +47,10 @@ return params_->user_gesture; } +base::Optional<CSSOrigin> ProgrammaticScriptInjector::GetCssOrigin() const { + return params_->css_origin; +} + bool ProgrammaticScriptInjector::ExpectsResults() const { return params_->wants_result; }
diff --git a/extensions/renderer/programmatic_script_injector.h b/extensions/renderer/programmatic_script_injector.h index d48e6e9..ef61b20 100644 --- a/extensions/renderer/programmatic_script_injector.h +++ b/extensions/renderer/programmatic_script_injector.h
@@ -32,6 +32,7 @@ UserScript::InjectionType script_type() const override; bool ShouldExecuteInMainWorld() const override; bool IsUserGesture() const override; + base::Optional<CSSOrigin> GetCssOrigin() const override; bool ExpectsResults() const override; bool ShouldInjectJs( UserScript::RunLocation run_location,
diff --git a/extensions/renderer/script_injection.cc b/extensions/renderer/script_injection.cc index fa7beb14..5699905 100644 --- a/extensions/renderer/script_injection.cc +++ b/extensions/renderer/script_injection.cc
@@ -402,8 +402,14 @@ std::vector<blink::WebString> css_sources = injector_->GetCssSources( run_location_, injected_stylesheets, num_injected_stylesheets); blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame(); + // Default CSS origin is "author", but can be overridden to "user" by scripts. + base::Optional<CSSOrigin> css_origin = injector_->GetCssOrigin(); + blink::WebDocument::CSSOrigin blink_css_origin = + css_origin && *css_origin == CSS_ORIGIN_USER + ? blink::WebDocument::kUserOrigin + : blink::WebDocument::kAuthorOrigin; for (const blink::WebString& css : css_sources) - web_frame->GetDocument().InsertStyleSheet(css); + web_frame->GetDocument().InsertStyleSheet(css, blink_css_origin); } } // namespace extensions
diff --git a/extensions/renderer/script_injector.h b/extensions/renderer/script_injector.h index cc03624..46470fd 100644 --- a/extensions/renderer/script_injector.h +++ b/extensions/renderer/script_injector.h
@@ -9,6 +9,7 @@ #include <vector> #include "extensions/common/permissions/permissions_data.h" +#include "extensions/common/constants.h" #include "extensions/common/user_script.h" #include "third_party/WebKit/public/web/WebScriptSource.h" @@ -44,6 +45,9 @@ // Returns true if the script is running inside a user gesture. virtual bool IsUserGesture() const = 0; + // Returns the CSS origin of this injection. + virtual base::Optional<CSSOrigin> GetCssOrigin() const = 0; + // Returns true if the script expects results. virtual bool ExpectsResults() const = 0;
diff --git a/extensions/renderer/user_script_injector.cc b/extensions/renderer/user_script_injector.cc index 9be67bcf..972d47a 100644 --- a/extensions/renderer/user_script_injector.cc +++ b/extensions/renderer/user_script_injector.cc
@@ -145,6 +145,10 @@ return false; } +base::Optional<CSSOrigin> UserScriptInjector::GetCssOrigin() const { + return base::nullopt; +} + bool UserScriptInjector::ShouldInjectJs( UserScript::RunLocation run_location, const std::set<std::string>& executing_scripts) const {
diff --git a/extensions/renderer/user_script_injector.h b/extensions/renderer/user_script_injector.h index c380b81..c543608a 100644 --- a/extensions/renderer/user_script_injector.h +++ b/extensions/renderer/user_script_injector.h
@@ -40,6 +40,7 @@ UserScript::InjectionType script_type() const override; bool ShouldExecuteInMainWorld() const override; bool IsUserGesture() const override; + base::Optional<CSSOrigin> GetCssOrigin() const override; bool ExpectsResults() const override; bool ShouldInjectJs( UserScript::RunLocation run_location,
diff --git a/extensions/shell/browser/shell_network_controller_chromeos.cc b/extensions/shell/browser/shell_network_controller_chromeos.cc index bde9c32..0a44912 100644 --- a/extensions/shell/browser/shell_network_controller_chromeos.cc +++ b/extensions/shell/browser/shell_network_controller_chromeos.cc
@@ -199,7 +199,8 @@ weak_ptr_factory_.GetWeakPtr()), base::Bind(&ShellNetworkController::HandleConnectionError, weak_ptr_factory_.GetWeakPtr()), - false /* check_error_state */); + false /* check_error_state */, + chromeos::ConnectCallbackMode::ON_COMPLETED); } void ShellNetworkController::HandleConnectionSuccess() {
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 2296182..4d7c2d0 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc
@@ -1110,6 +1110,9 @@ // In the browser process call ::SetParent() directly. if (!gpu_channel_manager_delegate_) { ::SetParent(child_window, parent_window); + // Move D3D window behind Chrome's window to avoid losing some messages. + ::SetWindowPos(child_window, HWND_BOTTOM, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE); return; }
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc index eb559bc..320be451 100644 --- a/gpu/ipc/service/gpu_init.cc +++ b/gpu/ipc/service/gpu_init.cc
@@ -104,11 +104,16 @@ gpu::StopForceDiscreteGPU(); } -bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, - const GpuPreferences& gpu_preferences) { +bool GpuInit::InitializeAndStartSandbox( + base::CommandLine* command_line, + const GpuPreferences& gpu_preferences, + const GPUInfo* gpu_info, + const GpuFeatureInfo* gpu_feature_info) { gpu_preferences_ = gpu_preferences; #if !defined(OS_ANDROID) - if (!PopGPUInfoCache(&gpu_info_)) { + if (gpu_info) { + gpu_info_ = *gpu_info; + } else if (!PopGPUInfoCache(&gpu_info_)) { // Get vendor_id, device_id, driver_version from browser process through // commandline switches. // TODO(zmo): Collect basic GPU info (without a context) here instead of @@ -125,7 +130,9 @@ gpu_info_.driver_vendor == "NVIDIA" && !CanAccessNvidiaDeviceFile()) return false; #endif - if (!PopGpuFeatureInfoCache(&gpu_feature_info_)) { + if (gpu_feature_info) { + gpu_feature_info_ = *gpu_feature_info; + } else if (!PopGpuFeatureInfoCache(&gpu_feature_info_)) { // Compute blacklist and driver bug workaround decisions based on basic GPU // info. gpu_feature_info_ = gpu::ComputeGpuFeatureInfo( @@ -319,15 +326,20 @@ ui::OzonePlatform::GetInstance()->AfterSandboxEntry(); #endif - if (gpu_info && gpu_feature_info) { + if (gpu_info) { gpu_info_ = *gpu_info; - gpu_feature_info_ = *gpu_feature_info; } else { #if !defined(OS_ANDROID) if (!PopGPUInfoCache(&gpu_info_)) { // TODO(zmo): Collect basic GPU info here instead. gpu::GetGpuInfoFromCommandLine(*command_line, &gpu_info_); } +#endif + } + if (gpu_feature_info) { + gpu_feature_info_ = *gpu_feature_info; + } else { +#if !defined(OS_ANDROID) if (!PopGpuFeatureInfoCache(&gpu_feature_info_)) { gpu_feature_info_ = gpu::ComputeGpuFeatureInfo( gpu_info_, gpu_preferences.ignore_gpu_blacklist,
diff --git a/gpu/ipc/service/gpu_init.h b/gpu/ipc/service/gpu_init.h index 9fd6b89..ee94bed 100644 --- a/gpu/ipc/service/gpu_init.h +++ b/gpu/ipc/service/gpu_init.h
@@ -41,8 +41,13 @@ // TODO(zmo): Get rid of |command_line| in the following two functions. // Pass all bits through GpuPreferences. + // Mostly we collect GPUInfo and compute GpuFeatureInfo inside this function, + // but on certain platforms (Chromecast, MacOSX) they might be computed + // somewhere else. bool InitializeAndStartSandbox(base::CommandLine* command_line, - const GpuPreferences& gpu_preferences); + const GpuPreferences& gpu_preferences, + const GPUInfo* gpu_info, + const GpuFeatureInfo* gpu_feature_info); void InitializeInProcess(base::CommandLine* command_line, const GpuPreferences& gpu_preferences, const GPUInfo* gpu_info = nullptr,
diff --git a/gpu/ipc/service/image_transport_surface_fuchsia.cc b/gpu/ipc/service/image_transport_surface_fuchsia.cc index 8818adf..f2feaed 100644 --- a/gpu/ipc/service/image_transport_surface_fuchsia.cc +++ b/gpu/ipc/service/image_transport_surface_fuchsia.cc
@@ -6,8 +6,8 @@ #include "base/logging.h" #include "ui/gl/gl_surface.h" -#include "ui/gl/gl_surface_osmesa.h" #include "ui/gl/gl_surface_stub.h" +#include "ui/gl/init/gl_factory.h" namespace gpu { @@ -16,14 +16,12 @@ base::WeakPtr<ImageTransportSurfaceDelegate> delegate, SurfaceHandle surface_handle, gl::GLSurfaceFormat format) { - if (gl::GetGLImplementation() == gl::kGLImplementationOSMesaGL) { - return gl::InitializeGLSurfaceWithFormat( - new gl::GLSurfaceOSMesa(format, gfx::Size(1, 1)), format); + if (gl::GetGLImplementation() == gl::kGLImplementationMockGL || + gl::GetGLImplementation() == gl::kGLImplementationStubGL) { + return new gl::GLSurfaceStub; } - DCHECK(gl::GetGLImplementation() == gl::kGLImplementationMockGL || - gl::GetGLImplementation() == gl::kGLImplementationStubGL); - return new gl::GLSurfaceStub; + return gl::init::CreateViewGLSurface(surface_handle); } } // namespace gpu
diff --git a/ios/chrome/browser/application_context_impl.cc b/ios/chrome/browser/application_context_impl.cc index 04b70cc..4bffab1 100644 --- a/ios/chrome/browser/application_context_impl.cc +++ b/ios/chrome/browser/application_context_impl.cc
@@ -276,8 +276,7 @@ // be registered and Start() needs to be called. component_updater_ = component_updater::ComponentUpdateServiceFactory( component_updater::MakeIOSComponentUpdaterConfigurator( - base::CommandLine::ForCurrentProcess(), - GetSystemURLRequestContext())); + base::CommandLine::ForCurrentProcess())); } return component_updater_.get(); }
diff --git a/ios/chrome/browser/component_updater/ios_component_updater_configurator.cc b/ios/chrome/browser/component_updater/ios_component_updater_configurator.cc index f88bfa0..c0233af 100644 --- a/ios/chrome/browser/component_updater/ios_component_updater_configurator.cc +++ b/ios/chrome/browser/component_updater/ios_component_updater_configurator.cc
@@ -25,8 +25,7 @@ class IOSConfigurator : public update_client::Configurator { public: - IOSConfigurator(const base::CommandLine* cmdline, - net::URLRequestContextGetter* url_request_getter); + explicit IOSConfigurator(const base::CommandLine* cmdline); // update_client::Configurator overrides. int InitialDelay() const override; @@ -43,7 +42,7 @@ std::string GetOSLongName() const override; std::string ExtraRequestParams() const override; std::string GetDownloadPreference() const override; - net::URLRequestContextGetter* RequestContext() const override; + scoped_refptr<net::URLRequestContextGetter> RequestContext() const override; std::unique_ptr<service_manager::Connector> CreateServiceManagerConnector() const override; bool EnabledDeltas() const override; @@ -66,10 +65,8 @@ // Allows the component updater to use non-encrypted communication with the // update backend. The security of the update checks is enforced using // a custom message signing protocol and it does not depend on using HTTPS. -IOSConfigurator::IOSConfigurator( - const base::CommandLine* cmdline, - net::URLRequestContextGetter* url_request_getter) - : configurator_impl_(cmdline, url_request_getter, false) {} +IOSConfigurator::IOSConfigurator(const base::CommandLine* cmdline) + : configurator_impl_(cmdline, false) {} int IOSConfigurator::InitialDelay() const { return configurator_impl_.InitialDelay(); @@ -130,8 +127,9 @@ return configurator_impl_.GetDownloadPreference(); } -net::URLRequestContextGetter* IOSConfigurator::RequestContext() const { - return configurator_impl_.RequestContext(); +scoped_refptr<net::URLRequestContextGetter> IOSConfigurator::RequestContext() + const { + return GetApplicationContext()->GetSystemURLRequestContext(); } std::unique_ptr<service_manager::Connector> @@ -175,9 +173,8 @@ } // namespace scoped_refptr<update_client::Configurator> MakeIOSComponentUpdaterConfigurator( - const base::CommandLine* cmdline, - net::URLRequestContextGetter* context_getter) { - return base::MakeRefCounted<IOSConfigurator>(cmdline, context_getter); + const base::CommandLine* cmdline) { + return base::MakeRefCounted<IOSConfigurator>(cmdline); } } // namespace component_updater
diff --git a/ios/chrome/browser/component_updater/ios_component_updater_configurator.h b/ios/chrome/browser/component_updater/ios_component_updater_configurator.h index 037c287a..e1c80440 100644 --- a/ios/chrome/browser/component_updater/ios_component_updater_configurator.h +++ b/ios/chrome/browser/component_updater/ios_component_updater_configurator.h
@@ -12,15 +12,10 @@ class CommandLine; } -namespace net { -class URLRequestContextGetter; -} - namespace component_updater { scoped_refptr<update_client::Configurator> MakeIOSComponentUpdaterConfigurator( - const base::CommandLine* cmdline, - net::URLRequestContextGetter* context_getter); + const base::CommandLine* cmdline); } // namespace component_updater
diff --git a/ios/web/navigation/history_state_operations_inttest.mm b/ios/web/navigation/history_state_operations_inttest.mm index 9f7ccc0..8d51284 100644 --- a/ios/web/navigation/history_state_operations_inttest.mm +++ b/ios/web/navigation/history_state_operations_inttest.mm
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/compiler_specific.h" #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" @@ -70,15 +71,15 @@ // Load the history state test page. state_operations_url_ = web::test::HttpServer::MakeUrl(kHistoryStateOperationsTestUrl); - LoadUrl(state_operations_url()); + ASSERT_TRUE(LoadUrl(state_operations_url())); } // The URL of the window.location test page. const GURL& state_operations_url() { return state_operations_url_; } // Reloads the page and waits for the load to finish. - void Reload() { - ExecuteBlockAndWaitForLoad(GetLastCommittedItem()->GetURL(), ^{ + bool Reload() WARN_UNUSED_RESULT { + return ExecuteBlockAndWaitForLoad(GetLastCommittedItem()->GetURL(), ^{ // TODO(crbug.com/677364): Use NavigationManager::Reload() once it no // longer requires a web delegate. web_state()->ExecuteJavaScript(ASCIIToUTF16("window.location.reload()")); @@ -243,11 +244,11 @@ // NavigationItem can be used later to verify that the title is replaced // rather than pushed. GURL about_blank("about:blank"); - LoadUrl(about_blank); + ASSERT_TRUE(LoadUrl(about_blank)); web::NavigationItem* about_blank_item = GetLastCommittedItem(); - ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ + EXPECT_TRUE(ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ navigation_manager()->GoBack(); - }); + })); EXPECT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); // Set up the state parameters and tap the replace state button. std::string empty_state; @@ -273,11 +274,11 @@ // NavigationItem can be used later to verify that the state is replaced // rather than pushed. GURL about_blank("about:blank"); - LoadUrl(about_blank); + ASSERT_TRUE(LoadUrl(about_blank)); web::NavigationItem* about_blank_item = GetLastCommittedItem(); - ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ + EXPECT_TRUE(ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ navigation_manager()->GoBack(); - }); + })); ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); // Set up the state parameters and tap the replace state button. std::string new_state("STATE OBJECT"); @@ -326,7 +327,7 @@ SetStateParams(new_state, empty_title, empty_url); ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); // Reload the page and check that the state object is present. - Reload(); + EXPECT_TRUE(Reload()); ASSERT_TRUE(IsOnLoadTextVisible()); BOOL completed = testing::WaitUntilConditionOrTimeout( testing::kWaitForJSCompletionTimeout, ^{ @@ -342,10 +343,10 @@ // NavigationItem can be used later to verify that the state is replaced // rather than pushed. GURL about_blank("about:blank"); - LoadUrl(about_blank); - ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ + ASSERT_TRUE(LoadUrl(about_blank)); + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ navigation_manager()->GoBack(); - }); + })); ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); // Set up the state parameters and tap the replace state button. std::string new_state("STATE OBJECT"); @@ -354,12 +355,12 @@ SetStateParams(new_state, empty_title, empty_url); ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); // Go forward and back, then check that the state object is present. - ExecuteBlockAndWaitForLoad(about_blank, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(about_blank, ^{ navigation_manager()->GoForward(); - }); - ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ + })); + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ navigation_manager()->GoBack(); - }); + })); ASSERT_TRUE(IsOnLoadTextVisible()); BOOL completed = testing::WaitUntilConditionOrTimeout( testing::kWaitForJSCompletionTimeout, ^{ @@ -375,11 +376,11 @@ // NavigationItem can be used later to verify that the state is replaced // rather than pushed. GURL about_blank("about:blank"); - LoadUrl(about_blank); + ASSERT_TRUE(LoadUrl(about_blank)); web::NavigationItem* about_blank_item = GetLastCommittedItem(); - ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ navigation_manager()->GoBack(); - }); + })); ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); web::NavigationItem* non_pushed_item = GetLastCommittedItem(); // Set up the state parameters and tap the replace state button. @@ -450,7 +451,7 @@ GURL url = web::test::HttpServer::MakeUrl( "http://ios/testing/data/http_server_files/" "onload_replacestate_reload.html"); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); GURL new_url = web::test::HttpServer::MakeUrl( "http://ios/testing/data/http_server_files/pony.html"); BOOL completed =
diff --git a/ios/web/navigation/window_location_inttest.mm b/ios/web/navigation/window_location_inttest.mm index 981c42e15..f71e8c7 100644 --- a/ios/web/navigation/window_location_inttest.mm +++ b/ios/web/navigation/window_location_inttest.mm
@@ -69,7 +69,7 @@ // Load the window.location test page. window_location_url_ = web::test::HttpServer::MakeUrl(kWindowLocationTestURL); - LoadUrl(window_location_url()); + ASSERT_TRUE(LoadUrl(window_location_url())); } // The URL of the window.location test page. @@ -120,23 +120,23 @@ TEST_F(WindowLocationTest, MAYBE_Assign) { // Navigate to about:blank so there is a forward entry to prune. GURL about_blank("about:blank"); - LoadUrl(about_blank); + ASSERT_TRUE(LoadUrl(about_blank)); web::NavigationItem* about_blank_item = navigation_manager()->GetLastCommittedItem(); // Navigate back to the window.location test page. - ExecuteBlockAndWaitForLoad(window_location_url(), ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(window_location_url(), ^{ navigation_manager()->GoBack(); - }); + })); // Set the window.location test URL and tap the window.location.assign() // button. GURL sample_url = web::test::HttpServer::MakeUrl(kSampleFileBasedURL); SetWindowLocationUrl(sample_url); - ExecuteBlockAndWaitForLoad(sample_url, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(sample_url, ^{ ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kWindowLocationAssignID)); - }); + })); // Verify that |sample_url| was loaded and that |about_blank_item| was pruned. EXPECT_EQ(sample_url, navigation_manager()->GetLastCommittedItem()->GetURL()); @@ -164,23 +164,23 @@ TEST_F(WindowLocationTest, DISABLED_Replace) { // Navigate to about:blank so there is a forward entry. GURL about_blank("about:blank"); - LoadUrl(about_blank); + ASSERT_TRUE(LoadUrl(about_blank)); web::NavigationItem* about_blank_item = navigation_manager()->GetLastCommittedItem(); // Navigate back to the window.location test page. - ExecuteBlockAndWaitForLoad(window_location_url(), ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(window_location_url(), ^{ navigation_manager()->GoBack(); - }); + })); // Set the window.location test URL and tap the window.location.replace() // button. GURL sample_url = web::test::HttpServer::MakeUrl(kSampleFileBasedURL); SetWindowLocationUrl(sample_url); - ExecuteBlockAndWaitForLoad(sample_url, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(sample_url, ^{ ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kWindowLocationReplaceID)); - }); + })); // Verify that |sample_url| was loaded and that |about_blank_item| was pruned. web::NavigationItem* current_item = @@ -214,10 +214,10 @@ // TODO(crbug.com/721465): Enable this test on device. TEST_F(WindowLocationTest, MAYBE_WindowLocationReload) { // Tap the window.location.reload() button. - ExecuteBlockAndWaitForLoad(window_location_url(), ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(window_location_url(), ^{ ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kWindowLocationReloadID)); - }); + })); // Verify that |kOnLoadText| is displayed and that no additional // NavigationItems are added. @@ -236,23 +236,23 @@ TEST_F(WindowLocationTest, MAYBE_WindowLocationSetToDOMString) { // Navigate to about:blank so there is a forward entry to prune. GURL about_blank("about:blank"); - LoadUrl(about_blank); + ASSERT_TRUE(LoadUrl(about_blank)); web::NavigationItem* about_blank_item = navigation_manager()->GetLastCommittedItem(); // Navigate back to the window.location test page. - ExecuteBlockAndWaitForLoad(window_location_url(), ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(window_location_url(), ^{ navigation_manager()->GoBack(); - }); + })); // Set the window.location test URL and tap the window.location.assign() // button. GURL sample_url = web::test::HttpServer::MakeUrl(kSampleFileBasedURL); SetWindowLocationUrl(sample_url); - ExecuteBlockAndWaitForLoad(sample_url, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(sample_url, ^{ ASSERT_TRUE(web::test::TapWebViewElementWithId( web_state(), kWindowLocationSetToDOMStringID)); - }); + })); // Verify that |sample_url| was loaded and that |about_blank_item| was pruned. EXPECT_EQ(sample_url, navigation_manager()->GetLastCommittedItem()->GetURL());
diff --git a/ios/web/test/BUILD.gn b/ios/web/test/BUILD.gn index c5363e7..ae9bd25 100644 --- a/ios/web/test/BUILD.gn +++ b/ios/web/test/BUILD.gn
@@ -56,7 +56,8 @@ ":test_constants", "//base", "//base/test:test_support", - "//ios/web:web", + "//ios/testing:ios_test_support", + "//ios/web", "//ios/web/navigation:core", "//ios/web/public/test/fakes", "//ios/web/public/test/http_server",
diff --git a/ios/web/test/web_int_test.h b/ios/web/test/web_int_test.h index 65f8451..c85bf668 100644 --- a/ios/web/test/web_int_test.h +++ b/ios/web/test/web_int_test.h
@@ -7,6 +7,7 @@ #import <WebKit/WebKit.h> +#include "base/compiler_specific.h" #import "base/ios/block_types.h" #include "base/macros.h" #import "ios/web/public/navigation_manager.h" @@ -45,13 +46,15 @@ // Executes |block| and waits until |url| is successfully loaded in // |web_state_|. - void ExecuteBlockAndWaitForLoad(const GURL& url, ProceduralBlock block); + bool ExecuteBlockAndWaitForLoad(const GURL& url, + ProceduralBlock block) WARN_UNUSED_RESULT; // Navigates |web_state_| to |url| and waits for the page to be loaded. - void LoadUrl(const GURL& url); + bool LoadUrl(const GURL& url) WARN_UNUSED_RESULT; // Navigates |web_state_| using |params| and waits for the page to be loaded. - void LoadWithParams(const NavigationManager::WebLoadParams& params); + bool LoadWithParams(const NavigationManager::WebLoadParams& params) + WARN_UNUSED_RESULT; // Synchronously removes data from |data_store|. // |websiteDataTypes| is from the constants defined in
diff --git a/ios/web/test/web_int_test.mm b/ios/web/test/web_int_test.mm index 93feb74b..50e599a 100644 --- a/ios/web/test/web_int_test.mm +++ b/ios/web/test/web_int_test.mm
@@ -8,6 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/scoped_observer.h" #import "base/test/ios/wait_util.h" +#import "ios/testing/wait_util.h" #import "ios/web/public/test/http_server/http_server.h" #import "ios/web/public/test/js_test_util.h" #include "ios/web/public/web_state/web_state_observer.h" @@ -17,6 +18,8 @@ #error "This file requires ARC support." #endif +using testing::WaitUntilConditionOrTimeout; + namespace web { #pragma mark - IntTestWebStateObserver @@ -91,7 +94,7 @@ return web::ExecuteJavaScript(web_state()->GetJSInjectionReceiver(), script); } -void WebIntTest::ExecuteBlockAndWaitForLoad(const GURL& url, +bool WebIntTest::ExecuteBlockAndWaitForLoad(const GURL& url, ProceduralBlock block) { DCHECK(block); @@ -104,21 +107,21 @@ // Need to use a pointer to |observer| as the block wants to capture it by // value (even if marked with __block) which would not work. IntTestWebStateObserver* observer_ptr = &observer; - base::test::ios::WaitUntilCondition(^bool { + return WaitUntilConditionOrTimeout(testing::kWaitForPageLoadTimeout, ^{ return observer_ptr->IsExpectedPageLoaded(); }); } -void WebIntTest::LoadUrl(const GURL& url) { +bool WebIntTest::LoadUrl(const GURL& url) { web::NavigationManager::WebLoadParams params(url); params.transition_type = ui::PageTransition::PAGE_TRANSITION_TYPED; - LoadWithParams(params); + return LoadWithParams(params); } -void WebIntTest::LoadWithParams( +bool WebIntTest::LoadWithParams( const NavigationManager::WebLoadParams& params) { NavigationManager::WebLoadParams block_params(params); - ExecuteBlockAndWaitForLoad(params.url, ^{ + return ExecuteBlockAndWaitForLoad(params.url, ^{ navigation_manager()->LoadURLWithParams(block_params); }); }
diff --git a/ios/web/web_state/navigation_and_load_callbacks_inttest.mm b/ios/web/web_state/navigation_and_load_callbacks_inttest.mm index 3fcefeb..0780cde 100644 --- a/ios/web/web_state/navigation_and_load_callbacks_inttest.mm +++ b/ios/web/web_state/navigation_and_load_callbacks_inttest.mm
@@ -420,7 +420,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); } // Tests that if web usage is already enabled, enabling it again would not cause @@ -448,7 +448,7 @@ EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); web_state()->SetWebUsageEnabled(true); web_state()->SetWebUsageEnabled(true); } @@ -494,7 +494,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); // Reload web page. NavigationContext* context = nullptr; @@ -515,10 +515,10 @@ // the delegate will allow form resubmission. Remove this workaround (clearing // the delegate, once |check_for_repost| is supported). web_state()->SetDelegate(nullptr); - ExecuteBlockAndWaitForLoad(url, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(url, ^{ navigation_manager()->Reload(ReloadType::NORMAL, false /*check_for_repost*/); - }); + })); } // Tests user-initiated hash change. @@ -541,7 +541,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); // Perform same-document navigation. const GURL hash_url = HttpServer::MakeUrl("http://chromium.test#1"); @@ -561,7 +561,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(hash_url); + ASSERT_TRUE(LoadUrl(hash_url)); // Perform same-document navigation by going back. // No ShouldAllowRequest callback for same-document back-forward navigations. @@ -581,9 +581,9 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - ExecuteBlockAndWaitForLoad(url, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(url, ^{ navigation_manager()->GoBack(); - }); + })); } // Tests renderer-initiated hash change. @@ -606,7 +606,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); // Perform same-page navigation using JavaScript. const GURL hash_url = HttpServer::MakeUrl("http://chromium.test#1"); @@ -649,7 +649,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); // Perform push state using JavaScript. const GURL push_url = HttpServer::MakeUrl("http://chromium.test/test.html"); @@ -699,7 +699,7 @@ EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); [provider_ setController:content_ forURL:url]; - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); } // Tests native content reload navigation. @@ -714,7 +714,7 @@ EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); [provider_ setController:content_ forURL:url]; - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); // Reload native content. NavigationContext* context = nullptr; @@ -761,7 +761,7 @@ web::NavigationManager::WebLoadParams params(url); params.post_data = [@"foo" dataUsingEncoding:NSUTF8StringEncoding]; params.extra_headers = @{@"Content-Type" : @"text/html"}; - LoadWithParams(params); + ASSERT_TRUE(LoadWithParams(params)); ASSERT_TRUE(WaitForWebViewContainingText(web_state(), kTestPageText)); } @@ -786,7 +786,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); ASSERT_TRUE(WaitForWebViewContainingText(web_state(), kTestPageText)); // Submit the form using JavaScript. @@ -829,7 +829,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); ASSERT_TRUE(WaitForWebViewContainingText(web_state(), kTestPageText)); // Submit the form using JavaScript. @@ -865,10 +865,10 @@ // the delegate will allow form resubmission. Remove this workaround (clearing // the delegate, once |check_for_repost| is supported). web_state()->SetDelegate(nullptr); - ExecuteBlockAndWaitForLoad(action, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(action, ^{ navigation_manager()->Reload(ReloadType::NORMAL, false /*check_for_repost*/); - }); + })); } // Tests going forward to a page rendered from post response. @@ -892,7 +892,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); ASSERT_TRUE(WaitForWebViewContainingText(web_state(), kTestPageText)); // Submit the form using JavaScript. @@ -929,9 +929,9 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - ExecuteBlockAndWaitForLoad(url, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(url, ^{ navigation_manager()->GoBack(); - }); + })); // Go forward. NavigationContext* context = nullptr; @@ -956,9 +956,9 @@ // the delegate will allow form resubmission. Remove this workaround (clearing // the delegate, once |check_for_repost| is supported). web_state()->SetDelegate(nullptr); - ExecuteBlockAndWaitForLoad(action, ^{ + ASSERT_TRUE(ExecuteBlockAndWaitForLoad(action, ^{ navigation_manager()->GoForward(); - }); + })); } // Tests server redirect navigation. @@ -989,7 +989,7 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); EXPECT_CALL(observer_, PageLoaded(web_state(), PageLoadCompletionStatus::SUCCESS)); - LoadUrl(url); + ASSERT_TRUE(LoadUrl(url)); } } // namespace web
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 464cadb..f8c003a 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -4729,11 +4729,10 @@ - (void)SSLStatusUpdater:(CRWSSLStatusUpdater*)SSLStatusUpdater didChangeSSLStatusForNavigationItem:(web::NavigationItem*)navigationItem { - web::NavigationItem* lastCommittedNavigationItem = - _webStateImpl->GetNavigationManager()->GetLastCommittedItem(); - if (navigationItem == lastCommittedNavigationItem) { + web::NavigationItem* visibleItem = + _webStateImpl->GetNavigationManager()->GetVisibleItem(); + if (navigationItem == visibleItem) _webStateImpl->DidChangeVisibleSecurityState(); - } } #pragma mark -
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 8b681abb..4884ef5 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -800,6 +800,11 @@ UpdatePlayState(); } +void WebMediaPlayerImpl::PictureInPicture() { + if (client_) + client_->PictureInPictureStarted(); +} + void WebMediaPlayerImpl::SetSinkId( const blink::WebString& sink_id, const blink::WebSecurityOrigin& security_origin,
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index a89c9fb..6a28050 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -132,6 +132,7 @@ void Seek(double seconds) override; void SetRate(double rate) override; void SetVolume(double volume) override; + void PictureInPicture() override; void SetSinkId(const blink::WebString& sink_id, const blink::WebSecurityOrigin& security_origin, blink::WebSetSinkIdCallbacks* web_callback) override;
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc index 57e43be3..6a9eaf9e 100644 --- a/media/blink/webmediaplayer_impl_unittest.cc +++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -128,6 +128,8 @@ MOCK_METHOD1(ActivateViewportIntersectionMonitoring, void(bool)); MOCK_METHOD1(MediaRemotingStarted, void(const blink::WebString&)); MOCK_METHOD1(MediaRemotingStopped, void(blink::WebLocalizedString::Name)); + MOCK_METHOD0(PictureInPictureStarted, void()); + MOCK_METHOD0(PictureInPictureStopped, void()); void set_is_autoplaying_muted(bool value) { is_autoplaying_muted_ = value; }
diff --git a/net/BUILD.gn b/net/BUILD.gn index 7676ff4c..f856881 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1817,8 +1817,6 @@ "reporting/reporting_delivery_agent.h", "reporting/reporting_endpoint_manager.cc", "reporting/reporting_endpoint_manager.h", - "reporting/reporting_feature.cc", - "reporting/reporting_feature.h", "reporting/reporting_garbage_collector.cc", "reporting/reporting_garbage_collector.h", "reporting/reporting_header_parser.cc", @@ -2629,6 +2627,8 @@ "test/net_test_suite.h", "test/scoped_disable_exit_on_dfatal.cc", "test/scoped_disable_exit_on_dfatal.h", + "test/tcp_socket_proxy.cc", + "test/tcp_socket_proxy.h", "test/test_certificate_data.h", "test/test_data_directory.cc", "test/test_data_directory.h", @@ -2687,26 +2687,24 @@ "test/spawned_test_server/base_test_server.h", "test/spawned_test_server/spawned_test_server.h", ] + } - if (use_remote_test_server) { - sources += [ - "test/spawned_test_server/remote_test_server.cc", - "test/spawned_test_server/remote_test_server.h", - "test/spawned_test_server/remote_test_server_config.cc", - "test/spawned_test_server/remote_test_server_config.h", - "test/spawned_test_server/remote_test_server_proxy.cc", - "test/spawned_test_server/remote_test_server_proxy.h", - "test/spawned_test_server/remote_test_server_spawner_request.cc", - "test/spawned_test_server/remote_test_server_spawner_request.h", - ] - } else { - sources += [ - "test/spawned_test_server/local_test_server.cc", - "test/spawned_test_server/local_test_server.h", - "test/spawned_test_server/local_test_server_posix.cc", - "test/spawned_test_server/local_test_server_win.cc", - ] - } + if (use_remote_test_server) { + sources += [ + "test/spawned_test_server/remote_test_server.cc", + "test/spawned_test_server/remote_test_server.h", + "test/spawned_test_server/remote_test_server_config.cc", + "test/spawned_test_server/remote_test_server_config.h", + "test/spawned_test_server/remote_test_server_spawner_request.cc", + "test/spawned_test_server/remote_test_server_spawner_request.h", + ] + } else if (!is_ios) { + sources += [ + "test/spawned_test_server/local_test_server.cc", + "test/spawned_test_server/local_test_server.h", + "test/spawned_test_server/local_test_server_posix.cc", + "test/spawned_test_server/local_test_server_win.cc", + ] } if (enable_python_utils) { @@ -5265,6 +5263,7 @@ "test/embedded_test_server/http_request_unittest.cc", "test/embedded_test_server/http_response_unittest.cc", "test/run_all_unittests.cc", + "test/tcp_socket_proxy_unittest.cc", "third_party/nist-pkits/pkits_testcases-inl.h", "tools/content_decoder_tool/content_decoder_tool.cc", "tools/content_decoder_tool/content_decoder_tool.h", @@ -5436,11 +5435,6 @@ ] } - if (use_remote_test_server) { - sources += - [ "test/spawned_test_server/remote_test_server_proxy_unittests.cc" ] - } - if (enable_python_utils) { sources += [ "test/python_utils_unittest.cc" ] }
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc index 7ea853b..74529e4 100644 --- a/net/http/bidirectional_stream_unittest.cc +++ b/net/http/bidirectional_stream_unittest.cc
@@ -28,6 +28,7 @@ #include "net/log/net_log_source_type.h" #include "net/log/test_net_log.h" #include "net/log/test_net_log_util.h" +#include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" #include "net/spdy/chromium/spdy_session.h" #include "net/spdy/chromium/spdy_test_util_common.h" @@ -391,7 +392,10 @@ BidirectionalStreamTest() : default_url_(kDefaultUrl), host_port_pair_(HostPortPair::FromURL(default_url_)), - key_(host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED), + key_(host_port_pair_, + ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, + SocketTag()), ssl_data_(SSLSocketDataProvider(ASYNC, OK)) { ssl_data_.next_proto = kProtoHTTP2; ssl_data_.ssl_info.cert =
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index a2f6033..dd24ae5c 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -81,6 +81,7 @@ #include "net/socket/connection_attempts.h" #include "net/socket/mock_client_socket_pool_manager.h" #include "net/socket/next_proto.h" +#include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" #include "net/socket/ssl_client_socket.h" #include "net/spdy/chromium/spdy_session.h" @@ -5067,8 +5068,8 @@ // Race a session to the proxy, which completes first. session_deps_.host_resolver->set_ondemand_mode(false); - SpdySessionKey key( - HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session = CreateSpdySession(session.get(), key, log.bound()); @@ -12106,7 +12107,7 @@ // Set up an initial SpdySession in the pool to reuse. HostPortPair host_port_pair("www.example.org", 443); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session = CreateSpdySession(session.get(), key, NetLogWithSource()); @@ -13756,7 +13757,7 @@ // Set up an initial SpdySession in the pool to reuse. HostPortPair host_port_pair("www.example.org", 443); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session = CreateSpdySession(session.get(), key, NetLogWithSource()); @@ -15371,8 +15372,8 @@ session_deps_.socket_factory->AddSocketDataProvider(&http_data); HostPortPair host_port_pair_a("www.a.com", 443); - SpdySessionKey spdy_session_key_a( - host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + SpdySessionKey spdy_session_key_a(host_port_pair_a, ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); EXPECT_FALSE( HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); @@ -15403,8 +15404,8 @@ HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); HostPortPair host_port_pair_b("www.b.com", 443); - SpdySessionKey spdy_session_key_b( - host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + SpdySessionKey spdy_session_key_b(host_port_pair_b, ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); EXPECT_FALSE( HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); HttpRequestInfo request2; @@ -15432,8 +15433,8 @@ HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); HostPortPair host_port_pair_a1("www.a.com", 80); - SpdySessionKey spdy_session_key_a1( - host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + SpdySessionKey spdy_session_key_a1(host_port_pair_a1, ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); EXPECT_FALSE( HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1)); HttpRequestInfo request3;
diff --git a/net/http/http_proxy_client_socket_wrapper.cc b/net/http/http_proxy_client_socket_wrapper.cc index 4d76995..e61f2ad5 100644 --- a/net/http/http_proxy_client_socket_wrapper.cc +++ b/net/http/http_proxy_client_socket_wrapper.cc
@@ -470,7 +470,8 @@ SpdySessionKey key(ssl_params_->GetDirectConnectionParams() ->destination() .host_port_pair(), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + ProxyServer::Direct(), PRIVACY_MODE_DISABLED, + initial_socket_tag_); if (spdy_session_pool_->FindAvailableSession( key, /* enable_ip_based_pooling = */ true, net_log_)) { using_spdy_ = true; @@ -583,7 +584,7 @@ DCHECK(ssl_params_); SpdySessionKey key( ssl_params_->GetDirectConnectionParams()->destination().host_port_pair(), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + ProxyServer::Direct(), PRIVACY_MODE_DISABLED, initial_socket_tag_); base::WeakPtr<SpdySession> spdy_session = spdy_session_pool_->FindAvailableSession( key, /* enable_ip_based_pooling = */ true, net_log_);
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index 0a5801a0..d7f9acc 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc
@@ -210,7 +210,8 @@ : GetSpdySessionKey(spdy_session_direct_, proxy_info_.proxy_server(), origin_url_, - request_info_.privacy_mode)), + request_info_.privacy_mode, + request_info_.socket_tag)), stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), init_connection_already_resumed_(false), ptr_factory_(this) { @@ -404,16 +405,17 @@ bool spdy_session_direct, const ProxyServer& proxy_server, const GURL& origin_url, - PrivacyMode privacy_mode) { + PrivacyMode privacy_mode, + const SocketTag& socket_tag) { // In the case that we're using an HTTPS proxy for an HTTP url, // we look for a SPDY session *to* the proxy, instead of to the // origin server. if (!spdy_session_direct) { return SpdySessionKey(proxy_server.host_port_pair(), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, socket_tag); } return SpdySessionKey(HostPortPair::FromURL(origin_url), proxy_server, - privacy_mode); + privacy_mode, socket_tag); } bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const {
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h index aa8769964..cef6090 100644 --- a/net/http/http_stream_factory_impl_job.h +++ b/net/http/http_stream_factory_impl_job.h
@@ -366,7 +366,8 @@ static SpdySessionKey GetSpdySessionKey(bool spdy_session_direct, const ProxyServer& proxy_server, const GURL& origin_url, - PrivacyMode privacy_mode); + PrivacyMode privacy_mode, + const SocketTag& socket_tag); // Returns true if the current request can use an existing spdy session. bool CanUseExistingSpdySession() const;
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc index b7ff549..ec8f0d87 100644 --- a/net/http/http_stream_factory_impl_unittest.cc +++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -16,6 +16,7 @@ #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/test/histogram_tester.h" +#include "build/build_config.h" #include "net/base/port_util.h" #include "net/base/privacy_mode.h" #include "net/base/test_completion_callback.h" @@ -604,7 +605,7 @@ // Put a SpdySession in the pool. HostPortPair host_port_pair("www.google.com", 443); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); ignore_result(CreateFakeSpdySession(session->spdy_session_pool(), key)); CapturePreconnectsTransportSocketPool* transport_conn_pool = @@ -1373,7 +1374,7 @@ // Set an existing SpdySession in the pool. HostPortPair host_port_pair("www.google.com", 443); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - PRIVACY_MODE_ENABLED); + PRIVACY_MODE_ENABLED, SocketTag()); HttpRequestInfo request_info; request_info.method = "GET"; @@ -1422,6 +1423,19 @@ return session_list->GetSize(); } +#if defined(OS_ANDROID) +// Return count of sockets handed out by a given socket pool. +int GetHandedOutSocketCount(ClientSocketPool* pool) { + int count = 0; + std::unique_ptr<base::DictionaryValue> dict( + pool->GetInfoAsValue("", "", false)); + EXPECT_TRUE(dict != nullptr); + if (!dict->GetInteger("handed_out_socket_count", &count)) + return -1; + return count; +} +#endif + } // namespace TEST_F(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) { @@ -2603,6 +2617,138 @@ HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); } +#if defined(OS_ANDROID) +// Verify HttpStreamFactoryImplJob passes socket tag along properly and that +// SpdySessions have unique socket tags (e.g. one sessions should not be shared +// amongst streams with different socket tags). +TEST_F(HttpStreamFactoryTest, Tag) { + SpdySessionDependencies session_deps; + MockTaggingClientSocketFactory* socket_factory = + new MockTaggingClientSocketFactory(); + session_deps.socket_factory.reset(socket_factory); + + // Prepare for two HTTPS connects. + MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING); + SequencedSocketData socket_data(&mock_read, 1, nullptr, 0); + socket_data.set_connect_data(MockConnect(ASYNC, OK)); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); + MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING); + SequencedSocketData socket_data2(&mock_read2, 1, nullptr, 0); + socket_data2.set_connect_data(MockConnect(ASYNC, OK)); + session_deps.socket_factory->AddSocketDataProvider(&socket_data2); + SSLSocketDataProvider ssl_socket_data(ASYNC, OK); + ssl_socket_data.next_proto = kProtoHTTP2; + session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); + SSLSocketDataProvider ssl_socket_data2(ASYNC, OK); + ssl_socket_data2.next_proto = kProtoHTTP2; + session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2); + + HostPortPair host_port_pair("example.org", 443); + std::unique_ptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); + + // Prepare two different tags and corresponding HttpRequestInfos. + SocketTag tag1(SocketTag::UNSET_UID, 0x12345678); + HttpRequestInfo request_info1; + request_info1.method = "GET"; + request_info1.url = GURL("https://example.org"); + request_info1.load_flags = 0; + request_info1.socket_tag = tag1; + SocketTag tag2(getuid(), 0x87654321); + HttpRequestInfo request_info2 = request_info1; + request_info2.socket_tag = tag2; + + // Verify one stream with one tag results in one session, group and socket. + SSLConfig ssl_config; + StreamRequestWaiter waiter1; + std::unique_ptr<HttpStreamRequest> request1( + session->http_stream_factory()->RequestStream( + request_info1, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter1, + /* enable_ip_based_pooling = */ true, + /* enable_alternative_services = */ true, NetLogWithSource())); + waiter1.WaitForStream(); + EXPECT_TRUE(waiter1.stream_done()); + EXPECT_TRUE(nullptr == waiter1.websocket_stream()); + ASSERT_TRUE(nullptr != waiter1.stream()); + + EXPECT_EQ(1, GetSpdySessionCount(session.get())); + EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetTransportSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSSLSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetTransportSocketPool( + HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); + EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( + HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); + EXPECT_EQ(1, GetHandedOutSocketCount(session->GetTransportSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(1, GetHandedOutSocketCount(session->GetSSLSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + // Verify socket tagged appropriately. + EXPECT_TRUE(tag1 == socket_factory->GetLastProducedSocket()->tag()); + EXPECT_TRUE( + socket_factory->GetLastProducedSocket()->tagged_before_connected()); + + // Verify one more stream with a different tag results in one more session and + // socket. + StreamRequestWaiter waiter2; + std::unique_ptr<HttpStreamRequest> request2( + session->http_stream_factory()->RequestStream( + request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter2, + /* enable_ip_based_pooling = */ true, + /* enable_alternative_services = */ true, NetLogWithSource())); + waiter2.WaitForStream(); + EXPECT_TRUE(waiter2.stream_done()); + EXPECT_TRUE(nullptr == waiter2.websocket_stream()); + ASSERT_TRUE(nullptr != waiter2.stream()); + + EXPECT_EQ(2, GetSpdySessionCount(session.get())); + EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetTransportSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSSLSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetTransportSocketPool( + HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); + EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( + HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); + EXPECT_EQ(2, GetHandedOutSocketCount(session->GetTransportSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(2, GetHandedOutSocketCount(session->GetSSLSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + // Verify socket tagged appropriately. + EXPECT_TRUE(tag2 == socket_factory->GetLastProducedSocket()->tag()); + EXPECT_TRUE( + socket_factory->GetLastProducedSocket()->tagged_before_connected()); + + // Verify one more stream reusing a tag does not create new sessions, groups + // or sockets. + StreamRequestWaiter waiter3; + std::unique_ptr<HttpStreamRequest> request3( + session->http_stream_factory()->RequestStream( + request_info2, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter3, + /* enable_ip_based_pooling = */ true, + /* enable_alternative_services = */ true, NetLogWithSource())); + waiter3.WaitForStream(); + EXPECT_TRUE(waiter3.stream_done()); + EXPECT_TRUE(nullptr == waiter3.websocket_stream()); + ASSERT_TRUE(nullptr != waiter3.stream()); + + EXPECT_EQ(2, GetSpdySessionCount(session.get())); + EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetTransportSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSSLSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetTransportSocketPool( + HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); + EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( + HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); + EXPECT_EQ(2, GetHandedOutSocketCount(session->GetTransportSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); + EXPECT_EQ(2, GetHandedOutSocketCount(session->GetSSLSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL))); +} +#endif + } // namespace } // namespace net
diff --git a/net/network_error_logging/network_error_logging_end_to_end_test.cc b/net/network_error_logging/network_error_logging_end_to_end_test.cc index 3da56ed6a..ffcbc4c 100644 --- a/net/network_error_logging/network_error_logging_end_to_end_test.cc +++ b/net/network_error_logging/network_error_logging_end_to_end_test.cc
@@ -5,14 +5,12 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" -#include "base/test/scoped_feature_list.h" #include "base/test/values_test_util.h" #include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" #include "net/base/net_errors.h" #include "net/network_error_logging/network_error_logging_service.h" -#include "net/reporting/reporting_feature.h" #include "net/reporting/reporting_policy.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" @@ -57,9 +55,6 @@ : test_server_(test_server::EmbeddedTestServer::TYPE_HTTPS), upload_should_hang_(false), upload_received_(false) { - scoped_feature_list_.InitWithFeatures( - {features::kReporting, features::kNetworkErrorLogging}, {}); - // Make report delivery happen instantly. auto policy = std::make_unique<ReportingPolicy>(); policy->delivery_interval = base::TimeDelta::FromSeconds(0); @@ -145,7 +140,6 @@ return std::move(response); } - base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<URLRequestContext> url_request_context_; test_server::EmbeddedTestServer test_server_;
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc index e9d6f7b..ebded2f 100644 --- a/net/network_error_logging/network_error_logging_service.cc +++ b/net/network_error_logging/network_error_logging_service.cc
@@ -8,7 +8,6 @@ #include <string> #include <utility> -#include "base/feature_list.h" #include "base/json/json_reader.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -24,13 +23,6 @@ #include "url/gurl.h" #include "url/origin.h" -namespace features { - -const base::Feature kNetworkErrorLogging{"NetworkErrorLogging", - base::FEATURE_DISABLED_BY_DEFAULT}; - -} // namespace features - namespace net { namespace { @@ -127,9 +119,6 @@ // static std::unique_ptr<NetworkErrorLoggingService> NetworkErrorLoggingService::Create() { - if (!base::FeatureList::IsEnabled(features::kNetworkErrorLogging)) - return std::unique_ptr<NetworkErrorLoggingService>(); - // Would be MakeUnique, but the constructor is private so MakeUnique can't see // it. return base::WrapUnique(new NetworkErrorLoggingService());
diff --git a/net/network_error_logging/network_error_logging_service_unittest.cc b/net/network_error_logging/network_error_logging_service_unittest.cc index e04a2f2..56fe21fe 100644 --- a/net/network_error_logging/network_error_logging_service_unittest.cc +++ b/net/network_error_logging/network_error_logging_service_unittest.cc
@@ -10,13 +10,13 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/test/scoped_feature_list.h" #include "base/test/values_test_util.h" #include "base/time/time.h" #include "base/values.h" #include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/network_error_logging/network_error_logging_service.h" +#include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_service.h" #include "net/socket/next_proto.h" #include "testing/gtest/include/gtest/gtest.h" @@ -85,8 +85,14 @@ return true; } + const ReportingPolicy& GetPolicy() const override { + NOTREACHED(); + return dummy_policy_; + } + private: std::vector<Report> reports_; + ReportingPolicy dummy_policy_; DISALLOW_COPY_AND_ASSIGN(TestReportingService); }; @@ -94,7 +100,6 @@ class NetworkErrorLoggingServiceTest : public ::testing::Test { protected: NetworkErrorLoggingServiceTest() { - scoped_feature_list_.InitAndEnableFeature(features::kNetworkErrorLogging); service_ = NetworkErrorLoggingService::Create(); CreateReportingService(); } @@ -158,22 +163,12 @@ const GURL kReferrer_ = GURL("https://referrer.com/"); private: - base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<NetworkErrorLoggingService> service_; std::unique_ptr<TestReportingService> reporting_service_; }; -TEST_F(NetworkErrorLoggingServiceTest, FeatureDisabled) { - // N.B. This test does not actually use the test fixture. - - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature(features::kNetworkErrorLogging); - - auto service = NetworkErrorLoggingService::Create(); - EXPECT_FALSE(service); -} - -TEST_F(NetworkErrorLoggingServiceTest, FeatureEnabled) { +TEST_F(NetworkErrorLoggingServiceTest, CreateService) { + // Service is created by default in the test fixture.. EXPECT_TRUE(service()); }
diff --git a/net/proxy/proxy_config.cc b/net/proxy/proxy_config.cc index 1f4ae8b1..ec4e490 100644 --- a/net/proxy/proxy_config.cc +++ b/net/proxy/proxy_config.cc
@@ -40,7 +40,7 @@ ProxyConfig::ProxyRules::ProxyRules() : reverse_bypass(false), - type(TYPE_NO_RULES) { + type(Type::EMPTY) { } ProxyConfig::ProxyRules::ProxyRules(const ProxyRules& other) = default; @@ -62,11 +62,11 @@ } switch (type) { - case ProxyRules::TYPE_SINGLE_PROXY: { + case ProxyRules::Type::PROXY_LIST: { result->UseProxyList(single_proxies); return; } - case ProxyRules::TYPE_PROXY_PER_SCHEME: { + case ProxyRules::Type::PROXY_LIST_PER_SCHEME: { const ProxyList* entry = MapUrlSchemeToProxyList(url.scheme()); if (entry) { result->UseProxyList(*entry); @@ -87,7 +87,7 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) { // Reset. - type = TYPE_NO_RULES; + type = Type::EMPTY; single_proxies = ProxyList(); proxies_for_http = ProxyList(); proxies_for_https = ProxyList(); @@ -106,12 +106,12 @@ // this is a regular proxy server configuration, i.e. proxies // are not configured per protocol. if (!proxy_server_for_scheme.GetNext()) { - if (type == TYPE_PROXY_PER_SCHEME) + if (type == Type::PROXY_LIST_PER_SCHEME) continue; // Unexpected. AddProxyURIListToProxyList(url_scheme, &single_proxies, ProxyServer::SCHEME_HTTP); - type = TYPE_SINGLE_PROXY; + type = Type::PROXY_LIST; return; } @@ -119,7 +119,7 @@ base::TrimWhitespaceASCII(url_scheme, base::TRIM_ALL, &url_scheme); // Add it to the per-scheme mappings (if supported scheme). - type = TYPE_PROXY_PER_SCHEME; + type = Type::PROXY_LIST_PER_SCHEME; ProxyList* entry = MapUrlSchemeToProxyListNoFallback(url_scheme); ProxyServer::Scheme default_scheme = ProxyServer::SCHEME_HTTP; @@ -169,7 +169,7 @@ ProxyList* ProxyConfig::ProxyRules::MapUrlSchemeToProxyListNoFallback( const std::string& scheme) { - DCHECK_EQ(TYPE_PROXY_PER_SCHEME, type); + DCHECK_EQ(Type::PROXY_LIST_PER_SCHEME, type); if (scheme == "http") return &proxies_for_http; if (scheme == "https") @@ -232,13 +232,13 @@ } // Output the manual settings. - if (proxy_rules_.type != ProxyRules::TYPE_NO_RULES) { + if (proxy_rules_.type != ProxyRules::Type::EMPTY) { switch (proxy_rules_.type) { - case ProxyRules::TYPE_SINGLE_PROXY: + case ProxyRules::Type::PROXY_LIST: AddProxyListToValue("single_proxy", proxy_rules_.single_proxies, dict.get()); break; - case ProxyRules::TYPE_PROXY_PER_SCHEME: { + case ProxyRules::Type::PROXY_LIST_PER_SCHEME: { std::unique_ptr<base::DictionaryValue> dict2( new base::DictionaryValue()); AddProxyListToValue("http", proxy_rules_.proxies_for_http, dict2.get());
diff --git a/net/proxy/proxy_config.h b/net/proxy/proxy_config.h index 8f88dc1..01b2814d 100644 --- a/net/proxy/proxy_config.h +++ b/net/proxy/proxy_config.h
@@ -37,24 +37,21 @@ class NET_EXPORT ProxyConfig { public: // ProxyRules describes the "manual" proxy settings. - // TODO(eroman): Turn this into a class. - // TODO(crbug.com/546383): Update the enum names; "TYPE_SINGLE_PROXY" really - // means the same set of proxies are used for all requests. struct NET_EXPORT ProxyRules { - enum Type { - TYPE_NO_RULES, - TYPE_SINGLE_PROXY, - TYPE_PROXY_PER_SCHEME, + enum class Type { + EMPTY, + PROXY_LIST, + PROXY_LIST_PER_SCHEME, }; - // Note that the default of TYPE_NO_RULES results in direct connections + // Note that the default of Type::EMPTY results in direct connections // being made when using this ProxyConfig. ProxyRules(); ProxyRules(const ProxyRules& other); ~ProxyRules(); bool empty() const { - return type == TYPE_NO_RULES; + return type == Type::EMPTY; } // Sets |result| with the proxies to use for |url| based on the current @@ -111,7 +108,7 @@ // Returns one of {&proxies_for_http, &proxies_for_https, &proxies_for_ftp, // &fallback_proxies}, or NULL if there is no proxy to use. - // Should only call this if the type is TYPE_PROXY_PER_SCHEME. + // Should only call this if the type is Type::PROXY_LIST_PER_SCHEME. const ProxyList* MapUrlSchemeToProxyList( const std::string& url_scheme) const; @@ -126,10 +123,10 @@ Type type; - // Set if |type| is TYPE_SINGLE_PROXY. + // Set if |type| is Type::PROXY_LIST. ProxyList single_proxies; - // Set if |type| is TYPE_PROXY_PER_SCHEME. + // Set if |type| is Type::PROXY_LIST_PER_SCHEME. ProxyList proxies_for_http; ProxyList proxies_for_https; ProxyList proxies_for_ftp; @@ -141,7 +138,7 @@ private: // Returns one of {&proxies_for_http, &proxies_for_https, &proxies_for_ftp} // or NULL if it is a scheme that we don't have a mapping for. Should only - // call this if the type is TYPE_PROXY_PER_SCHEME. Intentionally returns + // call this if the type is Type::PROXY_LIST_PER_SCHEME. Intentionally returns // NULL for "ws" and "wss" as those are handled specially by // GetProxyListForWebSocketScheme(). ProxyList* MapUrlSchemeToProxyListNoFallback(const std::string& scheme);
diff --git a/net/proxy/proxy_config_service_android.cc b/net/proxy/proxy_config_service_android.cc index 40ed97ea..4fe8153 100644 --- a/net/proxy/proxy_config_service_android.cc +++ b/net/proxy/proxy_config_service_android.cc
@@ -126,7 +126,7 @@ // connections via proxy. This default is identical on other platforms. // On the opposite, Java spec suggests to use HTTPS port (443) by default (the // default value of https.proxyPort). - rules->type = ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + rules->type = ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; rules->proxies_for_http.SetSingleProxyServer( LookupProxy("http", get_property, ProxyServer::SCHEME_HTTP)); rules->proxies_for_https.SetSingleProxyServer(
diff --git a/net/proxy/proxy_config_service_common_unittest.cc b/net/proxy/proxy_config_service_common_unittest.cc index 3835bb1..035ecd1 100644 --- a/net/proxy/proxy_config_service_common_unittest.cc +++ b/net/proxy/proxy_config_service_common_unittest.cc
@@ -98,8 +98,8 @@ bool failed = false; if (rules.type != type) { - failure_details << "Type mismatch. Expected: " - << type << " but was: " << rules.type; + failure_details << "Type mismatch. Expected: " << static_cast<int>(type) + << " but was: " << static_cast<int>(rules.type); failed = true; } @@ -133,14 +133,14 @@ // static ProxyRulesExpectation ProxyRulesExpectation::Empty() { - return ProxyRulesExpectation(ProxyConfig::ProxyRules::TYPE_NO_RULES, + return ProxyRulesExpectation(ProxyConfig::ProxyRules::Type::EMPTY, "", "", "", "", "", "", false); } // static ProxyRulesExpectation ProxyRulesExpectation::EmptyWithBypass( const char* flattened_bypass_rules) { - return ProxyRulesExpectation(ProxyConfig::ProxyRules::TYPE_NO_RULES, + return ProxyRulesExpectation(ProxyConfig::ProxyRules::Type::EMPTY, "", "", "", "", "", flattened_bypass_rules, false); } @@ -149,7 +149,7 @@ ProxyRulesExpectation ProxyRulesExpectation::Single( const char* single_proxy, const char* flattened_bypass_rules) { - return ProxyRulesExpectation(ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, + return ProxyRulesExpectation(ProxyConfig::ProxyRules::Type::PROXY_LIST, single_proxy, "", "", "", "", flattened_bypass_rules, false); } @@ -160,7 +160,7 @@ const char* proxy_https, const char* proxy_ftp, const char* flattened_bypass_rules) { - return ProxyRulesExpectation(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + return ProxyRulesExpectation(ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "", proxy_http, proxy_https, proxy_ftp, "", flattened_bypass_rules, false); } @@ -172,7 +172,7 @@ const char* proxy_ftp, const char* socks_proxy, const char* flattened_bypass_rules) { - return ProxyRulesExpectation(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + return ProxyRulesExpectation(ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "", proxy_http, proxy_https, proxy_ftp, socks_proxy, flattened_bypass_rules, false); } @@ -183,7 +183,7 @@ const char* proxy_https, const char* proxy_ftp, const char* flattened_bypass_rules) { - return ProxyRulesExpectation(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + return ProxyRulesExpectation(ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, "", proxy_http, proxy_https, proxy_ftp, "", flattened_bypass_rules, true); }
diff --git a/net/proxy/proxy_config_service_ios.cc b/net/proxy/proxy_config_service_ios.cc index 84a5adce..ef29a03 100644 --- a/net/proxy/proxy_config_service_ios.cc +++ b/net/proxy/proxy_config_service_ios.cc
@@ -77,7 +77,7 @@ kCFNetworkProxiesHTTPPort); if (proxy_server.is_valid()) { config->proxy_rules().type = - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; config->proxy_rules().proxies_for_http.SetSingleProxyServer(proxy_server); // Desktop Safari applies the HTTP proxy to http:// URLs only, but // Mobile Safari applies the HTTP proxy to https:// URLs as well.
diff --git a/net/proxy/proxy_config_service_linux.cc b/net/proxy/proxy_config_service_linux.cc index bd7bce5..6e6b5e0 100644 --- a/net/proxy/proxy_config_service_linux.cc +++ b/net/proxy/proxy_config_service_linux.cc
@@ -134,7 +134,7 @@ // "all_proxy" is a shortcut to avoid defining {http,https,ftp}_proxy. ProxyServer proxy_server; if (GetProxyFromEnvVar("all_proxy", &proxy_server)) { - config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config->proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST; config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_server); } else { bool have_http = GetProxyFromEnvVar("http_proxy", &proxy_server); @@ -155,7 +155,7 @@ if (have_http || have_https || have_ftp) { // mustn't change type unless some rules are actually set. config->proxy_rules().type = - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; } } if (config->proxy_rules().empty()) { @@ -168,7 +168,7 @@ && env_version == "4") scheme = ProxyServer::SCHEME_SOCKS4; if (GetProxyFromEnvVarForScheme("SOCKS_SERVER", scheme, &proxy_server)) { - config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config->proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST; config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_server); } } @@ -1087,18 +1087,18 @@ if (same_proxy) { if (proxy_for_http.is_valid()) { // Use the http proxy for all schemes. - config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config->proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST; config->proxy_rules().single_proxies.SetSingleProxyServer(proxy_for_http); } } else if (num_proxies_specified > 0) { if (socks_proxy.is_valid() && num_proxies_specified == 1) { // If the only proxy specified was for SOCKS, use it for all schemes. - config->proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config->proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST; config->proxy_rules().single_proxies.SetSingleProxyServer(socks_proxy); } else { // Otherwise use the indicated proxies per-scheme. config->proxy_rules().type = - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; config->proxy_rules().proxies_for_http. SetSingleProxyServer(proxy_for_http); config->proxy_rules().proxies_for_https.
diff --git a/net/proxy/proxy_config_service_mac.cc b/net/proxy/proxy_config_service_mac.cc index 055912f6..4d98fdf1 100644 --- a/net/proxy/proxy_config_service_mac.cc +++ b/net/proxy/proxy_config_service_mac.cc
@@ -77,7 +77,7 @@ kSCPropNetProxiesFTPPort); if (proxy_server.is_valid()) { config->proxy_rules().type = - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; config->proxy_rules().proxies_for_ftp.SetSingleProxyServer(proxy_server); } } @@ -91,7 +91,7 @@ kSCPropNetProxiesHTTPPort); if (proxy_server.is_valid()) { config->proxy_rules().type = - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; config->proxy_rules().proxies_for_http.SetSingleProxyServer(proxy_server); } } @@ -105,7 +105,7 @@ kSCPropNetProxiesHTTPSPort); if (proxy_server.is_valid()) { config->proxy_rules().type = - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; config->proxy_rules().proxies_for_https. SetSingleProxyServer(proxy_server); } @@ -120,7 +120,7 @@ kSCPropNetProxiesSOCKSPort); if (proxy_server.is_valid()) { config->proxy_rules().type = - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; config->proxy_rules().fallback_proxies.SetSingleProxyServer(proxy_server); } }
diff --git a/net/proxy/proxy_config_unittest.cc b/net/proxy/proxy_config_unittest.cc index 1554419..a028613 100644 --- a/net/proxy/proxy_config_unittest.cc +++ b/net/proxy/proxy_config_unittest.cc
@@ -50,14 +50,14 @@ // Test |ProxyConfig::proxy_rules|. - config2.proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config2.proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST; config2.proxy_rules().single_proxies.SetSingleProxyServer( ProxyServer::FromURI("myproxy:80", ProxyServer::SCHEME_HTTP)); EXPECT_FALSE(config1.Equals(config2)); EXPECT_FALSE(config2.Equals(config1)); - config1.proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + config1.proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST; config1.proxy_rules().single_proxies.SetSingleProxyServer( ProxyServer::FromURI("myproxy:100", ProxyServer::SCHEME_HTTP)); @@ -111,7 +111,7 @@ { "myproxy:80", - ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, + ProxyConfig::ProxyRules::Type::PROXY_LIST, "PROXY myproxy:80", NULL, NULL, @@ -123,7 +123,7 @@ { "myproxy:80,https://myotherproxy", - ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, + ProxyConfig::ProxyRules::Type::PROXY_LIST, "PROXY myproxy:80;HTTPS myotherproxy:443", NULL, NULL, @@ -135,7 +135,7 @@ { "http=myproxy:80", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, "PROXY myproxy:80", NULL, @@ -147,7 +147,7 @@ { "ftp=ftp-proxy ; https=socks4://foopy", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, NULL, "SOCKS foopy:1080", @@ -157,11 +157,11 @@ // Give a scheme-specific proxy as well as a non-scheme specific. // The first entry "foopy" takes precedance marking this list as - // TYPE_SINGLE_PROXY. + // Type::PROXY_LIST. { "foopy ; ftp=ftp-proxy", - ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, + ProxyConfig::ProxyRules::Type::PROXY_LIST, "PROXY foopy:80", NULL, NULL, @@ -171,11 +171,11 @@ // Give a scheme-specific proxy as well as a non-scheme specific. // The first entry "ftp=ftp-proxy" takes precedance marking this list as - // TYPE_PROXY_PER_SCHEME. + // Type::PROXY_LIST_PER_SCHEME. { "ftp=ftp-proxy ; foopy", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, NULL, NULL, @@ -187,7 +187,7 @@ { "ftp=ftp1,ftp2,ftp3", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, NULL, NULL, @@ -199,7 +199,7 @@ { "http=http1,http2; http=http3", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, "PROXY http1:80;PROXY http2:80;PROXY http3:80", NULL, @@ -211,7 +211,7 @@ { "ftp=ftp1,ftp2,ftp3 ; http=http1,http2; ", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, "PROXY http1:80;PROXY http2:80", NULL, @@ -223,7 +223,7 @@ { "http=https://secure_proxy; ftp=socks4://socks_proxy; https=socks://foo", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, "HTTPS secure_proxy:443", "SOCKS5 foo:1080", @@ -235,7 +235,7 @@ { "socks=foopy", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, NULL, NULL, @@ -247,7 +247,7 @@ { "http=httpproxy ; https=httpsproxy ; ftp=ftpproxy ; socks=foopy ", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, "PROXY httpproxy:80", "PROXY httpsproxy:80", @@ -260,7 +260,7 @@ { "http=httpproxy ; https=httpsproxy ; socks=socks5://foopy ", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, "PROXY httpproxy:80", "PROXY httpsproxy:80", @@ -272,7 +272,7 @@ { "crazy=foopy ; foo=bar ; https=myhttpsproxy", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, NULL, "PROXY myhttpsproxy:80", @@ -284,7 +284,7 @@ { "http=direct://,myhttpproxy; https=direct://", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, "DIRECT;PROXY myhttpproxy:80", "DIRECT", @@ -296,7 +296,7 @@ { "http=myhttpproxy,direct://", - ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, NULL, "PROXY myhttpproxy:80;DIRECT", NULL,
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index ce48b20..c5c60f58 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc
@@ -1858,7 +1858,7 @@ ProxyConfig config; config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080"); config.set_auto_detect(false); - EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, + EXPECT_EQ(ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME, config.proxy_rules().type); {
diff --git a/net/quic/chromium/quic_connectivity_probing_manager.cc b/net/quic/chromium/quic_connectivity_probing_manager.cc index e720367c..deb6cfd 100644 --- a/net/quic/chromium/quic_connectivity_probing_manager.cc +++ b/net/quic/chromium/quic_connectivity_probing_manager.cc
@@ -4,6 +4,7 @@ #include "net/quic/chromium/quic_connectivity_probing_manager.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "net/log/net_log.h" @@ -46,6 +47,7 @@ : delegate_(delegate), network_(NetworkChangeNotifier::kInvalidNetworkHandle), retry_count_(0), + probe_start_time_(base::TimeTicks()), task_runner_(task_runner), weak_factory_(this) { retransmit_timer_.SetTaskRunner(task_runner_); @@ -94,6 +96,7 @@ writer_.reset(); reader_.reset(); retry_count_ = 0; + probe_start_time_ = base::TimeTicks(); initial_timeout_ = base::TimeDelta(); retransmit_timer_.Stop(); } @@ -121,6 +124,7 @@ socket_ = std::move(socket); writer_ = std::move(writer); net_log_ = net_log; + probe_start_time_ = base::TimeTicks::Now(); // |this| will listen to all socket write events for the probing // packet writer. @@ -165,7 +169,12 @@ base::Bind(&NetLogQuicConnectivityProbingResponseCallback, network_, &local_address, &peer_address_)); - // TODO(zhongyi): add metrics collection. + UMA_HISTOGRAM_COUNTS_100("Net.QuicSession.ProbingRetryCountUntilSuccess", + retry_count_); + + UMA_HISTOGRAM_TIMES("Net.QuicSession.ProbingTimeInMillisecondsUntilSuccess", + base::TimeTicks::Now() - probe_start_time_); + // Notify the delegate that the probe succeeds and reset everything. delegate_->OnProbeNetworkSucceeded(network_, self_address, std::move(socket_), std::move(writer_), std::move(reader_));
diff --git a/net/quic/chromium/quic_connectivity_probing_manager.h b/net/quic/chromium/quic_connectivity_probing_manager.h index 407e951..2d45b02 100644 --- a/net/quic/chromium/quic_connectivity_probing_manager.h +++ b/net/quic/chromium/quic_connectivity_probing_manager.h
@@ -117,6 +117,7 @@ std::unique_ptr<QuicChromiumPacketReader> reader_; int64_t retry_count_; + base::TimeTicks probe_start_time_; base::TimeDelta initial_timeout_; base::OneShotTimer retransmit_timer_;
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc index 5cc6b57..ee1d6067 100644 --- a/net/quic/chromium/quic_network_transaction_unittest.cc +++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -1998,11 +1998,9 @@ quic_data.AddWrite(client_maker_.MakeDataPacket( 10, kHeadersStreamId, true, false, settings_offset, settings_data)); - if (FLAGS_quic_reloadable_flag_quic_explicit_close_after_tlp) { - quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket( - 11, true, QuicTime::Delta::Infinite(), 0, 1, 1, - QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity.")); - } + quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket( + 11, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_NETWORK_IDLE_TIMEOUT, + "No recent network activity.")); quic_data.AddRead(ASYNC, ERR_IO_PENDING); quic_data.AddRead(ASYNC, OK); @@ -2361,11 +2359,9 @@ quic_data.AddWrite(client_maker_.MakeDataPacket( 10, kHeadersStreamId, true, false, settings_offset, settings_data)); - if (FLAGS_quic_reloadable_flag_quic_explicit_close_after_tlp) { - quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket( - 11, true, QuicTime::Delta::Infinite(), 0, 1, 1, - QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity.")); - } + quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket( + 11, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_NETWORK_IDLE_TIMEOUT, + "No recent network activity.")); quic_data.AddRead(ASYNC, ERR_IO_PENDING); quic_data.AddRead(ASYNC, OK); @@ -2484,11 +2480,9 @@ quic_data.AddWrite(client_maker_.MakeDataPacket( 10, kHeadersStreamId, true, false, settings_offset, settings_data)); - if (FLAGS_quic_reloadable_flag_quic_explicit_close_after_tlp) { - quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket( - 11, true, QuicTime::Delta::Infinite(), 0, 1, 1, - QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity.")); - } + quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket( + 11, true, QuicTime::Delta::Infinite(), 0, 1, 1, QUIC_NETWORK_IDLE_TIMEOUT, + "No recent network activity.")); quic_data.AddRead(ASYNC, ERR_IO_PENDING); quic_data.AddRead(ASYNC, OK); @@ -2618,11 +2612,9 @@ quic_data.AddWrite(client_maker_.MakeDataPacket( 11, kHeadersStreamId, false, false, settings_offset, settings_data)); - if (FLAGS_quic_reloadable_flag_quic_explicit_close_after_tlp) { - quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket( - 12, false, QuicTime::Delta::FromMilliseconds(4200), 1, 1, 1, - QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity.")); - } + quic_data.AddWrite(client_maker_.MakeAckAndConnectionClosePacket( + 12, false, QuicTime::Delta::FromMilliseconds(4200), 1, 1, 1, + QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity.")); quic_data.AddRead(ASYNC, ERR_IO_PENDING); quic_data.AddRead(ASYNC, OK);
diff --git a/net/quic/core/congestion_control/rtt_stats.cc b/net/quic/core/congestion_control/rtt_stats.cc index 1fd7a2c..ce824d3 100644 --- a/net/quic/core/congestion_control/rtt_stats.cc +++ b/net/quic/core/congestion_control/rtt_stats.cc
@@ -6,6 +6,8 @@ #include <cstdlib> // std::abs +#include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { @@ -27,7 +29,8 @@ smoothed_rtt_(QuicTime::Delta::Zero()), previous_srtt_(QuicTime::Delta::Zero()), mean_deviation_(QuicTime::Delta::Zero()), - initial_rtt_us_(kInitialRttMs * kNumMicrosPerMilli) {} + initial_rtt_us_(kInitialRttMs * kNumMicrosPerMilli), + max_ack_delay_(QuicTime::Delta::Zero()) {} void RttStats::ExpireSmoothedMetrics() { mean_deviation_ = std::max( @@ -56,14 +59,22 @@ min_rtt_ = send_delta; } - // Correct for ack_delay if information received from the peer results in a - // positive RTT sample. Otherwise, we use the send_delta as a reasonable - // measure for smoothed_rtt. QuicTime::Delta rtt_sample(send_delta); previous_srtt_ = smoothed_rtt_; + // Correct for ack_delay if information received from the peer results in a + // an RTT sample at least as large as min_rtt. Otherwise, only use the + // send_delta. if (rtt_sample > ack_delay) { - rtt_sample = rtt_sample - ack_delay; + if (GetQuicReloadableFlag(quic_min_rtt_ack_delay)) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_min_rtt_ack_delay); + if (rtt_sample - min_rtt_ >= ack_delay) { + max_ack_delay_ = std::max(max_ack_delay_, ack_delay); + rtt_sample = rtt_sample - ack_delay; + } + } else { + rtt_sample = rtt_sample - ack_delay; + } } latest_rtt_ = rtt_sample; // First time call. @@ -87,6 +98,7 @@ smoothed_rtt_ = QuicTime::Delta::Zero(); mean_deviation_ = QuicTime::Delta::Zero(); initial_rtt_us_ = kInitialRttMs * kNumMicrosPerMilli; + max_ack_delay_ = QuicTime::Delta::Zero(); } } // namespace net
diff --git a/net/quic/core/congestion_control/rtt_stats.h b/net/quic/core/congestion_control/rtt_stats.h index 5b54cf9e..28d2230 100644 --- a/net/quic/core/congestion_control/rtt_stats.h +++ b/net/quic/core/congestion_control/rtt_stats.h
@@ -68,6 +68,8 @@ QuicTime::Delta mean_deviation() const { return mean_deviation_; } + QuicTime::Delta max_ack_delay() const { return max_ack_delay_; } + private: friend class test::RttStatsPeer; @@ -80,6 +82,9 @@ // larger than the standard deviation, for a normally distributed signal. QuicTime::Delta mean_deviation_; int64_t initial_rtt_us_; + // The maximum ack delay observed over the connection after excluding ack + // delays that were too large to be included in an RTT measurement. + QuicTime::Delta max_ack_delay_; DISALLOW_COPY_AND_ASSIGN(RttStats); };
diff --git a/net/quic/core/congestion_control/rtt_stats_test.cc b/net/quic/core/congestion_control/rtt_stats_test.cc index 905b714..9ae7537 100644 --- a/net/quic/core/congestion_control/rtt_stats_test.cc +++ b/net/quic/core/congestion_control/rtt_stats_test.cc
@@ -11,9 +11,9 @@ #include "net/quic/test_tools/rtt_stats_peer.h" using logging::LOG_WARNING; +using testing::_; using testing::HasSubstr; using testing::Message; -using testing::_; namespace net { namespace test { @@ -30,6 +30,7 @@ } TEST_F(RttStatsTest, SmoothedRtt) { + SetQuicReloadableFlag(quic_min_rtt_ack_delay, false); // Verify that ack_delay is corrected for in Smoothed RTT. rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300), QuicTime::Delta::FromMilliseconds(100), @@ -50,6 +51,36 @@ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt()); } +TEST_F(RttStatsTest, SmoothedRttMaxAckDelay) { + SetQuicReloadableFlag(quic_min_rtt_ack_delay, true); + // Verify that ack_delay is ignored in the first measurement. + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300), + QuicTime::Delta::FromMilliseconds(100), + QuicTime::Zero()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt()); + EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.max_ack_delay()); + // Verify that a plausible ack delay increases the max ack delay. + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(400), + QuicTime::Delta::FromMilliseconds(100), + QuicTime::Zero()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), rtt_stats_.max_ack_delay()); + // Verify that Smoothed RTT includes max ack delay if it's reasonable. + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(350), + QuicTime::Delta::FromMilliseconds(50), QuicTime::Zero()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt()); + // Verify that large erroneous ack_delay does not change Smoothed RTT. + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200), + QuicTime::Delta::FromMilliseconds(300), + QuicTime::Zero()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMicroseconds(287500), + rtt_stats_.smoothed_rtt()); +} + // Ensure that the potential rounding artifacts in EWMA calculation do not cause // the SRTT to drift too far from the exact value. TEST_F(RttStatsTest, SmoothedRttStability) { @@ -66,9 +97,8 @@ TEST_F(RttStatsTest, PreviousSmoothedRtt) { // Verify that ack_delay is corrected for in Smoothed RTT. - rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300), - QuicTime::Delta::FromMilliseconds(100), - QuicTime::Zero()); + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200), + QuicTime::Delta::FromMilliseconds(0), QuicTime::Zero()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt()); EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.previous_srtt()); @@ -164,18 +194,30 @@ } TEST_F(RttStatsTest, ResetAfterConnectionMigrations) { + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200), + QuicTime::Delta::FromMilliseconds(0), QuicTime::Zero()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.min_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(0), rtt_stats_.max_ack_delay()); + rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300), QuicTime::Delta::FromMilliseconds(100), QuicTime::Zero()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt()); - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.min_rtt()); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.min_rtt()); + if (GetQuicReloadableFlag(quic_min_rtt_ack_delay)) { + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), + rtt_stats_.max_ack_delay()); + } // Reset rtt stats on connection migrations. rtt_stats_.OnConnectionMigration(); EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.latest_rtt()); EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.smoothed_rtt()); EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.min_rtt()); + EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.max_ack_delay()); } } // namespace test
diff --git a/net/quic/core/crypto/crypto_framer.cc b/net/quic/core/crypto/crypto_framer.cc index 7d7d2c0..4ceb94f 100644 --- a/net/quic/core/crypto/crypto_framer.cc +++ b/net/quic/core/crypto/crypto_framer.cc
@@ -92,6 +92,31 @@ return buffer_.length(); } +bool CryptoFramer::HasTag(QuicTag tag) const { + if (state_ != STATE_READING_VALUES) { + return false; + } + for (const auto& it : tags_and_lengths_) { + if (it.first == tag) { + return true; + } + } + return false; +} + +void CryptoFramer::ForceHandshake() { + QuicDataReader reader(buffer_.data(), buffer_.length(), HOST_BYTE_ORDER); + for (const std::pair<QuicTag, size_t>& item : tags_and_lengths_) { + QuicStringPiece value; + if (reader.BytesRemaining() < item.second) { + break; + } + reader.ReadStringPiece(&value, item.second); + message_.SetStringPiece(item.first, value); + } + visitor_->OnHandshakeMessage(message_); +} + // static QuicData* CryptoFramer::ConstructHandshakeMessage( const CryptoHandshakeMessage& message,
diff --git a/net/quic/core/crypto/crypto_framer.h b/net/quic/core/crypto/crypto_framer.h index 9ff7036..3023ccb 100644 --- a/net/quic/core/crypto/crypto_framer.h +++ b/net/quic/core/crypto/crypto_framer.h
@@ -67,6 +67,15 @@ // parsed. size_t InputBytesRemaining() const override; + // Checks if the specified tag has been seen. Returns |true| if it + // has, and |false| if it has not or a CHLO has not been seen. + bool HasTag(QuicTag tag) const; + + // Even if the CHLO has not been fully received, force processing of + // the handshake message. This is dangerous and should not be used + // except as a mechanism of last resort. + void ForceHandshake(); + // Returns a new QuicData owned by the caller that contains a serialized // |message|, or nullptr if there was an error. static QuicData* ConstructHandshakeMessage(
diff --git a/net/quic/core/frames/quic_frame.h b/net/quic/core/frames/quic_frame.h index b02ceaef..affa1d6 100644 --- a/net/quic/core/frames/quic_frame.h +++ b/net/quic/core/frames/quic_frame.h
@@ -11,7 +11,6 @@ #include "net/quic/core/frames/quic_ack_frame.h" #include "net/quic/core/frames/quic_blocked_frame.h" #include "net/quic/core/frames/quic_connection_close_frame.h" -#include "net/quic/core/frames/quic_frame.h" #include "net/quic/core/frames/quic_goaway_frame.h" #include "net/quic/core/frames/quic_mtu_discovery_frame.h" #include "net/quic/core/frames/quic_padding_frame.h"
diff --git a/net/quic/core/quic_config.cc b/net/quic/core/quic_config.cc index 593fb64..49b7e34 100644 --- a/net/quic/core/quic_config.cc +++ b/net/quic/core/quic_config.cc
@@ -653,6 +653,14 @@ max_streams_per_connection_.negotiated(); } +void QuicConfig::SetCreateSessionTagIndicators(QuicTagVector tags) { + create_session_tag_indicators_ = std::move(tags); +} + +const QuicTagVector& QuicConfig::create_session_tag_indicators() const { + return create_session_tag_indicators_; +} + void QuicConfig::SetDefaults() { idle_network_timeout_seconds_.set(kMaximumIdleTimeoutSecs, kDefaultIdleTimeoutSecs);
diff --git a/net/quic/core/quic_config.h b/net/quic/core/quic_config.h index e367b4ba..f630b265 100644 --- a/net/quic/core/quic_config.h +++ b/net/quic/core/quic_config.h
@@ -401,6 +401,10 @@ bool negotiated() const; + void SetCreateSessionTagIndicators(QuicTagVector tags); + + const QuicTagVector& create_session_tag_indicators() const; + // ToHandshakeMessage serialises the settings in this object as a series of // tags /value pairs and adds them to |out|. void ToHandshakeMessage(CryptoHandshakeMessage* out) const; @@ -464,6 +468,11 @@ // Stateless reset token used in IETF public reset packet. QuicFixedUint128 stateless_reset_token_; + + // List of QuicTags whose presence immediately causes the session to + // be created. This allows for CHLOs that are larger than a single + // packet to be processed. + QuicTagVector create_session_tag_indicators_; }; } // namespace net
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc index 027c90d..d29aa42 100644 --- a/net/quic/core/quic_connection.cc +++ b/net/quic/core/quic_connection.cc
@@ -269,8 +269,6 @@ packets_between_mtu_probes_(kPacketsBetweenMtuProbesBase), next_mtu_probe_at_(kPacketsBetweenMtuProbesBase), largest_received_packet_size_(0), - goaway_sent_(false), - goaway_received_(false), write_error_occurred_(false), no_stop_waiting_frames_(false), consecutive_num_packets_with_no_retransmittable_frames_(0), @@ -956,7 +954,6 @@ << " and error: " << QuicErrorCodeToString(frame.error_code) << " and reason: " << frame.reason_phrase; - goaway_received_ = true; visitor_->OnGoAway(frame); visitor_->PostProcessAfterData(); should_last_packet_instigate_acks_ = true; @@ -1411,8 +1408,7 @@ if (self_address_.port() != last_packet_destination_address_.port() || self_address_.host().Normalized() != last_packet_destination_address_.host().Normalized()) { - if (!GetQuicReloadableFlag(quic_allow_address_change_for_udp_proxy) || - !visitor_->AllowSelfAddressChange()) { + if (!visitor_->AllowSelfAddressChange()) { CloseConnection( QUIC_ERROR_MIGRATING_ADDRESS, "Self address migration is not supported at the server.", @@ -2168,11 +2164,6 @@ void QuicConnection::SendGoAway(QuicErrorCode error, QuicStreamId last_good_stream_id, const string& reason) { - if (goaway_sent_) { - return; - } - goaway_sent_ = true; - QUIC_DLOG(INFO) << ENDPOINT << "Going away with error " << QuicErrorCodeToString(error) << " (" << error << ")"; @@ -2252,11 +2243,9 @@ if (idle_duration >= idle_network_timeout_) { const string error_details = "No recent network activity."; QUIC_DVLOG(1) << ENDPOINT << error_details; - if (GetQuicReloadableFlag(quic_explicit_close_after_tlp) && - (sent_packet_manager_.GetConsecutiveTlpCount() > 0 || + if ((sent_packet_manager_.GetConsecutiveTlpCount() > 0 || sent_packet_manager_.GetConsecutiveRtoCount() > 0 || visitor_->HasOpenDynamicStreams())) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_explicit_close_after_tlp); CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, error_details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); } else { @@ -2520,12 +2509,13 @@ QUIC_DLOG(INFO) << ENDPOINT << "Sending connectivity probing packet for " << "connection_id = " << connection_id_; - std::unique_ptr<QuicEncryptedPacket> probing_packet( + OwningSerializedPacketPointer probing_packet( packet_generator_.SerializeConnectivityProbingPacket()); + DCHECK_EQ(IsRetransmittable(*probing_packet), NO_RETRANSMITTABLE_DATA); WriteResult result = probing_writer->WritePacket( - probing_packet->data(), probing_packet->length(), self_address().host(), - peer_address, per_packet_options_); + probing_packet->encrypted_buffer, probing_packet->encrypted_length, + self_address().host(), peer_address, per_packet_options_); if (result.status == WRITE_STATUS_ERROR) { QUIC_DLOG(INFO) << "Write probing packet not finished with error = " @@ -2533,6 +2523,20 @@ return false; } + // Call OnPacketSent regardless of the write result. This treats a blocked + // write the same as a packet loss. + sent_packet_manager_.OnPacketSent( + probing_packet.get(), probing_packet->original_packet_number, + clock_->Now(), probing_packet->transmission_type, + NO_RETRANSMITTABLE_DATA); + + if (result.status == WRITE_STATUS_BLOCKED) { + visitor_->OnWriteBlocked(); + if (probing_writer->IsWriteBlockedDataBuffered()) { + QUIC_BUG << "Write probing packet blocked"; + } + } + return true; }
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h index bdb90a9..3fdf5379 100644 --- a/net/quic/core/quic_connection.h +++ b/net/quic/core/quic_connection.h
@@ -382,7 +382,7 @@ const std::string& details, ConnectionCloseBehavior connection_close_behavior); - // Sends a GOAWAY frame. Does nothing if a GOAWAY frame has already been sent. + // Sends a GOAWAY frame. virtual void SendGoAway(QuicErrorCode error, QuicStreamId last_good_stream_id, const std::string& reason); @@ -520,10 +520,6 @@ bool connected() const { return connected_; } - bool goaway_sent() const { return goaway_sent_; } - - bool goaway_received() const { return goaway_received_; } - // Must only be called on client connections. const ParsedQuicVersionVector& server_supported_versions() const { DCHECK_EQ(Perspective::IS_CLIENT, perspective_); @@ -1136,12 +1132,6 @@ // The size of the largest packet received from peer. QuicByteCount largest_received_packet_size_; - // Whether a GoAway has been sent. - bool goaway_sent_; - - // Whether a GoAway has been received. - bool goaway_received_; - // Indicates whether a write error is encountered currently. This is used to // avoid infinite write errors. bool write_error_occurred_;
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc index adf70273..b35237e 100644 --- a/net/quic/core/quic_connection_test.cc +++ b/net/quic/core/quic_connection_test.cc
@@ -1170,9 +1170,7 @@ QuicIpAddress host; host.FromString("1.1.1.1"); QuicSocketAddress self_address(host, 123); - if (GetQuicReloadableFlag(quic_allow_address_change_for_udp_proxy)) { - EXPECT_CALL(visitor_, AllowSelfAddressChange()).WillOnce(Return(false)); - } + EXPECT_CALL(visitor_, AllowSelfAddressChange()).WillOnce(Return(false)); EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_ERROR_MIGRATING_ADDRESS, _, _)); ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), self_address, kPeerAddress); @@ -1280,11 +1278,13 @@ // Process a padded PING packet with no peer address change on server side // will be ignored. - std::unique_ptr<QuicEncryptedPacket> probing_packet( + OwningSerializedPacketPointer probing_packet( QuicPacketCreatorPeer::SerializeConnectivityProbingPacket( &peer_creator_)); - std::unique_ptr<QuicReceivedPacket> received( - ConstructReceivedPacket(*probing_packet, clock_.Now())); + std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket( + QuicEncryptedPacket(probing_packet->encrypted_buffer, + probing_packet->encrypted_length), + clock_.Now())); ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received); EXPECT_EQ(kPeerAddress, connection_.peer_address()); @@ -1319,11 +1319,13 @@ const QuicSocketAddress kNewPeerAddress = QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456); - std::unique_ptr<QuicEncryptedPacket> probing_packet( + OwningSerializedPacketPointer probing_packet( QuicPacketCreatorPeer::SerializeConnectivityProbingPacket( &peer_creator_)); - std::unique_ptr<QuicReceivedPacket> received( - ConstructReceivedPacket(*probing_packet, clock_.Now())); + std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket( + QuicEncryptedPacket(probing_packet->encrypted_buffer, + probing_packet->encrypted_length), + clock_.Now())); ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received); if (GetQuicReloadableFlag(quic_server_reply_to_connectivity_probing)) { @@ -1367,11 +1369,13 @@ const QuicSocketAddress kNewPeerAddress = QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456); - std::unique_ptr<QuicEncryptedPacket> probing_packet( + OwningSerializedPacketPointer probing_packet( QuicPacketCreatorPeer::SerializeConnectivityProbingPacket( &peer_creator_)); - std::unique_ptr<QuicReceivedPacket> received( - ConstructReceivedPacket(*probing_packet, clock_.Now())); + std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket( + QuicEncryptedPacket(probing_packet->encrypted_buffer, + probing_packet->encrypted_length), + clock_.Now())); ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received); if (GetQuicReloadableFlag(quic_server_reply_to_connectivity_probing)) { EXPECT_EQ(kPeerAddress, connection_.peer_address()); @@ -1412,11 +1416,13 @@ EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0); EXPECT_CALL(visitor_, OnConnectivityProbeReceived(_, _)).Times(1); - std::unique_ptr<QuicEncryptedPacket> probing_packet( + OwningSerializedPacketPointer probing_packet( QuicPacketCreatorPeer::SerializeConnectivityProbingPacket( &peer_creator_)); - std::unique_ptr<QuicReceivedPacket> received( - ConstructReceivedPacket(*probing_packet, clock_.Now())); + std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket( + QuicEncryptedPacket(probing_packet->encrypted_buffer, + probing_packet->encrypted_length), + clock_.Now())); ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received); EXPECT_EQ(kPeerAddress, connection_.peer_address()); @@ -1447,11 +1453,13 @@ const QuicSocketAddress kNewSelfAddress = QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456); - std::unique_ptr<QuicEncryptedPacket> probing_packet( + OwningSerializedPacketPointer probing_packet( QuicPacketCreatorPeer::SerializeConnectivityProbingPacket( &peer_creator_)); - std::unique_ptr<QuicReceivedPacket> received( - ConstructReceivedPacket(*probing_packet, clock_.Now())); + std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket( + QuicEncryptedPacket(probing_packet->encrypted_buffer, + probing_packet->encrypted_length), + clock_.Now())); ProcessReceivedPacket(kNewSelfAddress, kPeerAddress, *received); EXPECT_EQ(kPeerAddress, connection_.peer_address()); @@ -3773,7 +3781,6 @@ } TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) { - SetQuicReloadableFlag(quic_explicit_close_after_tlp, true); // Same test as above, but complete a handshake which enables silent close, // but sending TLPs causes the connection close to be sent. EXPECT_TRUE(connection_.connected()); @@ -3828,7 +3835,6 @@ } TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) { - SetQuicReloadableFlag(quic_explicit_close_after_tlp, true); // Same test as above, but complete a handshake which enables silent close, // but having open streams causes the connection close to be sent. EXPECT_TRUE(connection_.connected()); @@ -5287,15 +5293,6 @@ EXPECT_TRUE(ack_alarm->IsSet()); } -TEST_P(QuicConnectionTest, DoNotSendGoAwayTwice) { - EXPECT_FALSE(connection_.goaway_sent()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.SendGoAway(QUIC_PEER_GOING_AWAY, kHeadersStreamId, "Going Away."); - EXPECT_TRUE(connection_.goaway_sent()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0); - connection_.SendGoAway(QUIC_PEER_GOING_AWAY, kHeadersStreamId, "Going Away."); -} - TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) { // Enable pacing. EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
diff --git a/net/quic/core/quic_data_reader.cc b/net/quic/core/quic_data_reader.cc index bb3953a..04190ed 100644 --- a/net/quic/core/quic_data_reader.cc +++ b/net/quic/core/quic_data_reader.cc
@@ -198,4 +198,70 @@ return data_[pos_]; } +// Read an IETF/QUIC formatted 62-bit Variable Length Integer. +// +// Performance notes +// +// Measurements and experiments showed that unrolling the four cases +// like this and dereferencing next_ as we do (*(next_+n) --- and then +// doing a single pos_+=x at the end) gains about 10% over making a +// loop and dereferencing next_ such as *(next_++) +// +// Using a register for pos_ was not helpful. +// +// Branches are ordered to increase the likelihood of the first being +// taken. +// +// Low-level optimization is useful here because this function will be +// called frequently, leading to outsize benefits. +bool QuicDataReader::ReadVarInt62(uint64_t* result) { + size_t remaining = BytesRemaining(); + const char* next = data_ + pos_; + if (remaining != 0) { + switch (*next & 0xc0) { + case 0xc0: + // Leading 0b11...... is 8 byte encoding + if (remaining >= 8) { + *result = (static_cast<uint64_t>((*(next)) & 0x3f) << 56) + + (static_cast<uint64_t>(*(next + 1)) << 48) + + (static_cast<uint64_t>(*(next + 2)) << 40) + + (static_cast<uint64_t>(*(next + 3)) << 32) + + (static_cast<uint64_t>(*(next + 4)) << 24) + + (static_cast<uint64_t>(*(next + 5)) << 16) + + (static_cast<uint64_t>(*(next + 6)) << 8) + + (static_cast<uint64_t>(*(next + 7)) << 0); + pos_ += 8; + return true; + } + return false; + + case 0x80: + // Leading 0b10...... is 4 byte encoding + if (remaining >= 4) { + *result = (((*(next)) & 0x3f) << 24) + (((*(next + 1)) << 16)) + + (((*(next + 2)) << 8)) + (((*(next + 3)) << 0)); + pos_ += 4; + return true; + } + return false; + + case 0x40: + // Leading 0b01...... is 2 byte encoding + if (remaining >= 2) { + *result = (((*(next)) & 0x3f) << 8) + (*(next + 1)); + pos_ += 2; + return true; + } + return false; + + case 0x00: + // Leading 0b00...... is 1 byte encoding + *result = (*next) & 0x3f; + pos_++; + return true; + } + } + return false; +} + } // namespace net
diff --git a/net/quic/core/quic_data_reader.h b/net/quic/core/quic_data_reader.h index b96c7b9..caa8fd66 100644 --- a/net/quic/core/quic_data_reader.h +++ b/net/quic/core/quic_data_reader.h
@@ -126,6 +126,15 @@ void set_endianness(Endianness endianness) { endianness_ = endianness; } + // Read an IETF-encoded Variable Length Integer and place the result + // in |*result|. + // Returns true if it works, false if not. The only error is that + // there is not enough in the buffer to read the number. + // If there is an error, |*result| is not altered. + // Numbers are encoded per the rules in draft-ietf-quic-transport-08.txt + // and that the integers in the range 0 ... (2^62)-1. + bool ReadVarInt62(uint64_t* result); + private: // Returns true if the underlying buffer has enough room to read the given // amount of bytes.
diff --git a/net/quic/core/quic_data_writer.cc b/net/quic/core/quic_data_writer.cc index 290d335..276a7df 100644 --- a/net/quic/core/quic_data_writer.cc +++ b/net/quic/core/quic_data_writer.cc
@@ -189,4 +189,86 @@ return WriteBytes(&tag, sizeof(tag)); } +// Converts a uint64_t into an IETF/Quic formatted Variable Length +// Integer. IETF Variable Length Integers have 62 significant bits, so +// the value to write must be in the range of 0..(2^62)-1. +// +// Performance notes +// +// Measurements and experiments showed that unrolling the four cases +// like this and dereferencing next_ as we do (*(next_+n)) gains about +// 10% over making a loop and dereferencing it as *(next_++) +// +// Using a register for next didn't help. +// +// Branches are ordered to increase the likelihood of the first being +// taken. +// +// Low-level optimization is useful here because this function will be +// called frequently, leading to outsize benefits. +bool QuicDataWriter::WriteVarInt62(uint64_t value) { + size_t remaining = capacity_ - length_; + char* next = buffer_ + length_; + if ((value & UINT64_C(0xc000000000000000)) == 0) { + // We know the high 2 bits are 0 so |value| is legal. + // We can do the encoding. + if ((value & UINT64_C(0x3fffffffc0000000)) != 0) { + // Someplace in the high-4 bytes is a 1-bit. Do an 8-byte + // encoding. + if (remaining >= 8) { + *(next + 0) = ((value >> 56) & 0x3f) + 0xc0; + *(next + 1) = (value >> 48) & 0xff; + *(next + 2) = (value >> 40) & 0xff; + *(next + 3) = (value >> 32) & 0xff; + *(next + 4) = (value >> 24) & 0xff; + *(next + 5) = (value >> 16) & 0xff; + *(next + 6) = (value >> 8) & 0xff; + *(next + 7) = value & 0xff; + length_ += 8; + return true; + } + return false; + } + // The high-order-4 bytes are all 0, check for a 1, 2, or 4-byte + // encoding + if ((value & UINT64_C(0x000000003fffc000)) != 0) { + // The encoding will not fit into 2 bytes, Do a 4-byte + // encoding. + if (remaining >= 4) { + *(next + 0) = ((value >> 24) & 0x3f) + 0x80; + *(next + 1) = (value >> 16) & 0xff; + *(next + 2) = (value >> 8) & 0xff; + *(next + 3) = value & 0xff; + length_ += 4; + return true; + } + return false; + } + // The high-order bits are all 0. Check to see if the number + // can be encoded as one or two bytes. One byte encoding has + // only 6 significant bits (bits 0xffffffff ffffffc0 are all 0). + // Two byte encoding has more than 6, but 14 or less significant + // bits (bits 0xffffffff ffffc000 are 0 and 0x00000000 00003fc0 + // are not 0) + if ((value & UINT64_C(0x0000000000003fc0)) != 0) { + // Do 2-byte encoding + if (remaining >= 2) { + *(next + 0) = ((value >> 8) & 0x3f) + 0x40; + *(next + 1) = (value)&0xff; + length_ += 2; + return true; + } + return false; + } + if (remaining >= 1) { + // Do 1-byte encoding + *next = (value & 0x3f); + length_ += 1; + return true; + } + return false; + } + // Can not encode, high 2 bits not 0 + return false; +} } // namespace net
diff --git a/net/quic/core/quic_data_writer.h b/net/quic/core/quic_data_writer.h index 1097a65..9d4627d 100644 --- a/net/quic/core/quic_data_writer.h +++ b/net/quic/core/quic_data_writer.h
@@ -47,6 +47,14 @@ bool WriteUInt32(uint32_t value); bool WriteUInt64(uint64_t value); + // Write an unsigned-integer value per the IETF QUIC/Variable Length + // Integer encoding rules (see draft-ietf-quic-transport-08.txt). + // IETF Variable Length Integers have 62 significant bits, so the + // value to write must be in the range of 0...(2^62)-1. Returns + // false if the value is out of range or if there is no room in the + // buffer. + bool WriteVarInt62(uint64_t value); + // Writes |value| to the position |offset| from the start of the data. // |offset| must be less than the current length of the writer. bool WriteUInt8AtOffset(uint8_t value, size_t offset);
diff --git a/net/quic/core/quic_data_writer_test.cc b/net/quic/core/quic_data_writer_test.cc index bc59ba40..3ba2a0a6 100644 --- a/net/quic/core/quic_data_writer_test.cc +++ b/net/quic/core/quic_data_writer_test.cc
@@ -584,6 +584,307 @@ } } +// Encodes and then decodes a specified value in a specified buffer, +// etc, etc. Ensures that the operation is correct. Reports errors via +// EXPECT_ macros. +void EncodeDecodeValue(uint64_t value_in, + char* buffer, + size_t size_of_buffer, + Endianness endianness) { + // This is the biggest value we can encode, ensure that + // it will fit. Other tests look at error cases. + EXPECT_LE(value_in, UINT64_C(0x3fffffffffffffff)); + + // Init the buffer to all 0, just for cleanliness. Makes for better + // output if, in debugging, we need to dump out the buffer. + memset(buffer, 0, size_of_buffer); + // make a writer. Note that for IETF encoding + // we do not care about endianness... + QuicDataWriter writer(size_of_buffer, buffer, endianness); + + EXPECT_TRUE(writer.WriteVarInt62(value_in)); + // Look at the value we encoded. Determine how much should have been + // used based on the value, and then check the state of the writer + // to see that it matches. + size_t expected_length = 0; + if (value_in <= 0x3f) { + expected_length = 1; + } else if (value_in <= 0x3fff) { + expected_length = 2; + } else if (value_in <= 0x3fffffff) { + expected_length = 4; + } else { + expected_length = 8; + } + EXPECT_EQ(writer.length(), expected_length); + + // set up a reader, just the length we've used, no more, no less. + QuicDataReader reader(buffer, expected_length, endianness); + uint64_t value_out; + + EXPECT_TRUE(reader.ReadVarInt62(&value_out)); + EXPECT_EQ(value_in, value_out); + // We only write one value so there had better be nothing left to read + EXPECT_TRUE(reader.IsDoneReading()); +} + +// Test that 8-byte-encoded Variable Length Integers are properly laid +// out in the buffer. +TEST_P(QuicDataWriterTest, DISABLED_VarInt8Layout) { + char buffer[1024]; + + // Check that the layout of bytes in the buffer is correct. Bytes + // are always encoded big endian... + memset(buffer, 0, sizeof(buffer)); + QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer), + GetParam().endianness); + EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142f3e4d5c6b7a8))); + EXPECT_EQ(*(writer.data() + 0), (0x31 + 0xc0)); // 0xc0 for encoding + EXPECT_EQ(*(writer.data() + 1), 0x42); + EXPECT_EQ(*(writer.data() + 2), 0xf3); + EXPECT_EQ(*(writer.data() + 3), 0xe4); + EXPECT_EQ(*(writer.data() + 4), 0xd5); + EXPECT_EQ(*(writer.data() + 5), 0xc6); + EXPECT_EQ(*(writer.data() + 6), 0xb7); + EXPECT_EQ(*(writer.data() + 7), 0xa8); +} + +// Test that 4-byte-encoded Variable Length Integers are properly laid +// out in the buffer. +TEST_P(QuicDataWriterTest, DISABLED_VarInt4Layout) { + char buffer[1024]; + + // Check that the layout of bytes in the buffer is correct. Bytes + // are always encoded big endian... + memset(buffer, 0, sizeof(buffer)); + QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer), + GetParam().endianness); + EXPECT_TRUE(writer.WriteVarInt62(0x3243f4e5)); + EXPECT_EQ(*(writer.data() + 0), (0x32 + 0x80)); // 0x80 for encoding + EXPECT_EQ(*(writer.data() + 1), 0x43); + EXPECT_EQ(*(writer.data() + 2), 0xf4); + EXPECT_EQ(*(writer.data() + 3), 0xe5); +} + +// Test that 2-byte-encoded Variable Length Integers are properly laid +// out in the buffer. +TEST_P(QuicDataWriterTest, DISABLED_VarInt2Layout) { + char buffer[1024]; + + // Check that the layout of bytes in the buffer is correct. Bytes + // are always encoded big endian... + memset(buffer, 0, sizeof(buffer)); + QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer), + GetParam().endianness); + EXPECT_TRUE(writer.WriteVarInt62(0x3647)); + EXPECT_EQ(*(writer.data() + 0), (0x36 + 0x40)); // 0x40 for encoding + EXPECT_EQ(*(writer.data() + 1), 0x47); +} + +// Test that 1-byte-encoded Variable Length Integers are properly laid +// out in the buffer. +TEST_P(QuicDataWriterTest, DISABLED_VarInt1Layout) { + char buffer[1024]; + + // Check that the layout of bytes in the buffer + // is correct. Bytes are always encoded big endian... + memset(buffer, 0, sizeof(buffer)); + QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer), + GetParam().endianness); + EXPECT_TRUE(writer.WriteVarInt62(0x3f)); + EXPECT_EQ(*(writer.data() + 0), 0x3f); +} + +// This test runs a very large range of numbers, doing IETF Variable +// Length Integer encoding and decoding operations. For each number +// encoded/decoded we test that +// - decode(encode(number))==number +// - that the reader and writer state is correct after +// decoding/encoding +// Systems are fast so rather than test for specific interesting +// numbers, we simply do exhaustive testing for the low range (1, 2, +// and 4-byte encoding). +TEST_P(QuicDataWriterTest, DISABLED_VarIntRangeSmall) { + char buffer[1024]; + + // Test a range of values. These tests do basic checks that the + // decoded value is the same as the encoded one, that the buffer + // states are correct after encoding and decoding, and so on. They + // do not check that the bit-layout in the buffer is correct. + for (uint64_t test_val = 0; test_val <= 0x0ffffff0; test_val++) { + EncodeDecodeValue(test_val, static_cast<char*>(buffer), sizeof(buffer), + GetParam().endianness); + } +} +// Test in the vicinity of moving from 4-byte to 8-byte +// encoding. Tests some exhaustive ranges as well as some targeted +// values. +TEST_P(QuicDataWriterTest, DISABLED_VarIntRangeMedium) { + char buffer[1024]; + + // Test a range of values. These tests do basic checks that the + // decoded value is the same as the encoded one, that the buffer + // states are correct after encoding and decoding, and so on. They + // do not check that the bit-layout in the buffer is correct. + for (uint64_t test_val = 0; test_val <= 0x1ffffff00; test_val += 0xff) { + EncodeDecodeValue(test_val, static_cast<char*>(buffer), sizeof(buffer), + GetParam().endianness); + } + // Specifically test around the 4/8 byte transition. + for (uint64_t test_val = 0x3fffffff - 1000; test_val <= 0x3fffffff + 1000; + test_val++) { + EncodeDecodeValue(test_val, static_cast<char*>(buffer), sizeof(buffer), + GetParam().endianness); + } +} + +TEST_P(QuicDataWriterTest, DISABLED_VarIntRangeLarge) { + char buffer[1024]; + + // Test a range of values. These tests do basic checks that the + // decoded value is the same as the encoded one, that the buffer + // states are correct after encoding and decoding, and so on. They + // do not check that the bit-layout in the buffer is correct. + // + // Run up to the maximum value, using exponentially increasing + // increments. + for (uint64_t test_val = 0x0fffffff; test_val <= UINT64_C(0x3fffffffffffffff); + test_val += (test_val >> 21)) { + EncodeDecodeValue(test_val, static_cast<char*>(buffer), sizeof(buffer), + GetParam().endianness); + } + + // Finally, do the last range incrementing by 1 + for (uint64_t test_val = UINT64_C(0x3fffffffffff0000); + test_val <= UINT64_C(0x3fffffffffffffff); test_val++) { + EncodeDecodeValue(test_val, static_cast<char*>(buffer), sizeof(buffer), + GetParam().endianness); + } +} + +// Following tests all try to fill the buffer with multiple values, +// go one value more than the buffer can accommodate, then read +// the successfully encoded values, and try to read the unsuccessfully +// encoded value. The following is the number of values to encode. +const int kMultiVarCount = 1000; + +// Test writing & reading multiple 8-byte-encoded varints +TEST_P(QuicDataWriterTest, DISABLED_MultiVarInt8) { + uint64_t test_val; + char buffer[8 * kMultiVarCount]; + memset(buffer, 0, sizeof(buffer)); + QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer), + GetParam().endianness); + // Put N values into the buffer. Adding i to the value ensures that + // each value is different so we can detect if we overwrite values, + // or read the same value over and over. + for (int i = 0; i < kMultiVarCount; i++) { + EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142f3e4d5c6b7a8) + i)); + } + EXPECT_EQ(writer.length(), 8u * kMultiVarCount); + + // N+1st should fail, the buffer is full. + EXPECT_FALSE(writer.WriteVarInt62(UINT64_C(0x3142f3e4d5c6b7a8))); + + // Now we should be able to read out the N values that were + // successfully encoded. + QuicDataReader reader(buffer, sizeof(buffer), GetParam().endianness); + for (int i = 0; i < kMultiVarCount; i++) { + EXPECT_TRUE(reader.ReadVarInt62(&test_val)); + EXPECT_EQ(test_val, (UINT64_C(0x3142f3e4d5c6b7a8) + i)); + } + // And the N+1st should fail. + EXPECT_FALSE(reader.ReadVarInt62(&test_val)); +} + +// Test writing & reading multiple 4-byte-encoded varints +TEST_P(QuicDataWriterTest, DISABLED_MultiVarInt4) { + uint64_t test_val; + char buffer[4 * kMultiVarCount]; + memset(buffer, 0, sizeof(buffer)); + QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer), + GetParam().endianness); + // Put N values into the buffer. Adding i to the value ensures that + // each value is different so we can detect if we overwrite values, + // or read the same value over and over. + for (int i = 0; i < kMultiVarCount; i++) { + EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142f3e4) + i)); + } + EXPECT_EQ(writer.length(), 4u * kMultiVarCount); + + // N+1st should fail, the buffer is full. + EXPECT_FALSE(writer.WriteVarInt62(UINT64_C(0x3142f3e4))); + + // Now we should be able to read out the N values that were + // successfully encoded. + QuicDataReader reader(buffer, sizeof(buffer), GetParam().endianness); + for (int i = 0; i < kMultiVarCount; i++) { + EXPECT_TRUE(reader.ReadVarInt62(&test_val)); + EXPECT_EQ(test_val, (UINT64_C(0x3142f3e4) + i)); + } + // And the N+1st should fail. + EXPECT_FALSE(reader.ReadVarInt62(&test_val)); +} + +// Test writing & reading multiple 2-byte-encoded varints +TEST_P(QuicDataWriterTest, DISABLED_MultiVarInt2) { + uint64_t test_val; + char buffer[2 * kMultiVarCount]; + memset(buffer, 0, sizeof(buffer)); + QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer), + GetParam().endianness); + // Put N values into the buffer. Adding i to the value ensures that + // each value is different so we can detect if we overwrite values, + // or read the same value over and over. + for (int i = 0; i < kMultiVarCount; i++) { + EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142) + i)); + } + EXPECT_EQ(writer.length(), 2u * kMultiVarCount); + + // N+1st should fail, the buffer is full. + EXPECT_FALSE(writer.WriteVarInt62(UINT64_C(0x3142))); + + // Now we should be able to read out the N values that were + // successfully encoded. + QuicDataReader reader(buffer, sizeof(buffer), GetParam().endianness); + for (int i = 0; i < kMultiVarCount; i++) { + EXPECT_TRUE(reader.ReadVarInt62(&test_val)); + EXPECT_EQ(test_val, (UINT64_C(0x3142) + i)); + } + // And the N+1st should fail. + EXPECT_FALSE(reader.ReadVarInt62(&test_val)); +} + +// Test writing & reading multiple 1-byte-encoded varints +TEST_P(QuicDataWriterTest, DISABLED_MultiVarInt1) { + uint64_t test_val; + char buffer[1 * kMultiVarCount]; + memset(buffer, 0, sizeof(buffer)); + QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer), + GetParam().endianness); + // Put N values into the buffer. Adding i to the value ensures that + // each value is different so we can detect if we overwrite values, + // or read the same value over and over. &0xf ensures we do not + // overflow the max value for single-byte encoding. + for (int i = 0; i < kMultiVarCount; i++) { + EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x30) + (i & 0xf))); + } + EXPECT_EQ(writer.length(), 1u * kMultiVarCount); + + // N+1st should fail, the buffer is full. + EXPECT_FALSE(writer.WriteVarInt62(UINT64_C(0x31))); + + // Now we should be able to read out the N values that were + // successfully encoded. + QuicDataReader reader(buffer, sizeof(buffer), GetParam().endianness); + for (int i = 0; i < kMultiVarCount; i++) { + EXPECT_TRUE(reader.ReadVarInt62(&test_val)); + EXPECT_EQ(test_val, (UINT64_C(0x30) + (i & 0xf))); + } + // And the N+1st should fail. + EXPECT_FALSE(reader.ReadVarInt62(&test_val)); +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index c5f8d924..3e2a489 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -109,15 +109,6 @@ // If true, enable QUIC v43. QUIC_FLAG(bool, FLAGS_quic_enable_version_43, false) -// If true, allows one address change when UDP proxying. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_allow_address_change_for_udp_proxy, - true) - -// Explicitly send a connection close if the TLP count is greater than 0 when -// idle timeout occurs. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_explicit_close_after_tlp, true) - // Enables 3 new connection options to make PROBE_RTT more aggressive QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_less_probe_rtt, false) @@ -131,7 +122,7 @@ // If true, allow stream data and control frames to be acked multiple times. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_multiple_acks_for_data2, - false) + true) // If true, calculate stream sequencer buffer block count in a way that // guaranteed to be 2048. @@ -168,3 +159,17 @@ // If true, QuicStreamSendBuffer keeps track of the slice which next write // should get data from if writing new data. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_write_index, false) + +// If true, when WINDOW_UPDATE is received, add stream to session's write +// blocked list and let session unblock it later. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_streams_unblocked_by_session, + false) + +// If true, inspects CHLO packets for indicator tags to allow early session +// creation. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_inspect_chlo_tags, false) + +// When true, ignore the specified ack delay if it causes the RTT sample to be +// less than min_rtt. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_min_rtt_ack_delay, false)
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc index 6df508b7..5a847d6 100644 --- a/net/quic/core/quic_framer.cc +++ b/net/quic/core/quic_framer.cc
@@ -299,7 +299,7 @@ } bool QuicFramer::IsSupportedVersion(const ParsedQuicVersion version) const { - for (ParsedQuicVersion supported_version : supported_versions_) { + for (const ParsedQuicVersion& supported_version : supported_versions_) { if (version == supported_version) { return true; } @@ -564,7 +564,7 @@ return nullptr; } - for (ParsedQuicVersion version : versions) { + for (const ParsedQuicVersion& version : versions) { // TODO(rch): Use WriteUInt32() once QUIC_VERSION_38 and earlier // are removed. if (!writer.WriteTag(
diff --git a/net/quic/core/quic_packet_creator.cc b/net/quic/core/quic_packet_creator.cc index bc52f7d..a0de1cb 100644 --- a/net/quic/core/quic_packet_creator.cc +++ b/net/quic/core/quic_packet_creator.cc
@@ -473,7 +473,7 @@ return encrypted; } -std::unique_ptr<QuicEncryptedPacket> +OwningSerializedPacketPointer QuicPacketCreator::SerializeConnectivityProbingPacket() { QuicPacketHeader header; // FillPacketHeader increments packet_number_. @@ -490,8 +490,14 @@ kMaxPacketSize, buffer.get()); DCHECK(encrypted_length); - return QuicMakeUnique<QuicEncryptedPacket>(buffer.release(), encrypted_length, - /*owns_buffer = */ true); + OwningSerializedPacketPointer serialize_packet(new SerializedPacket( + header.packet_number, header.packet_number_length, buffer.release(), + encrypted_length, /*has_ack=*/false, /*has_stop_waiting=*/false)); + + serialize_packet->encryption_level = packet_.encryption_level; + serialize_packet->transmission_type = NOT_RETRANSMISSION; + + return serialize_packet; } // TODO(jri): Make this a public method of framer?
diff --git a/net/quic/core/quic_packet_creator.h b/net/quic/core/quic_packet_creator.h index c73cbd8e..466d8944 100644 --- a/net/quic/core/quic_packet_creator.h +++ b/net/quic/core/quic_packet_creator.h
@@ -157,7 +157,7 @@ const ParsedQuicVersionVector& supported_versions); // Creates a connectivity probing packet. - std::unique_ptr<QuicEncryptedPacket> SerializeConnectivityProbingPacket(); + OwningSerializedPacketPointer SerializeConnectivityProbingPacket(); // Returns a dummy packet that is valid but contains no useful information. static SerializedPacket NoPacket();
diff --git a/net/quic/core/quic_packet_creator_test.cc b/net/quic/core/quic_packet_creator_test.cc index e8a6d6a..f7d1100 100644 --- a/net/quic/core/quic_packet_creator_test.cc +++ b/net/quic/core/quic_packet_creator_test.cc
@@ -26,12 +26,12 @@ #include "net/quic/test_tools/simple_data_producer.h" using std::string; +using testing::_; using testing::DoAll; using testing::InSequence; using testing::Return; using testing::SaveArg; using testing::StrictMock; -using testing::_; namespace net { namespace test { @@ -680,7 +680,7 @@ creator_.set_encryption_level(level); - std::unique_ptr<QuicEncryptedPacket> encrypted( + OwningSerializedPacketPointer encrypted( creator_.SerializeConnectivityProbingPacket()); { InSequence s; @@ -694,7 +694,8 @@ EXPECT_CALL(framer_visitor_, OnPacketComplete()); } // QuicFramerPeer::SetPerspective(&client_framer_, Perspective::IS_SERVER); - server_framer_.ProcessPacket(*encrypted); + server_framer_.ProcessPacket(QuicEncryptedPacket( + encrypted->encrypted_buffer, encrypted->encrypted_length)); } }
diff --git a/net/quic/core/quic_packet_generator.cc b/net/quic/core/quic_packet_generator.cc index 2274d32..4b41ee8 100644 --- a/net/quic/core/quic_packet_generator.cc +++ b/net/quic/core/quic_packet_generator.cc
@@ -313,7 +313,7 @@ return packet_creator_.SerializeVersionNegotiationPacket(supported_versions); } -std::unique_ptr<QuicEncryptedPacket> +OwningSerializedPacketPointer QuicPacketGenerator::SerializeConnectivityProbingPacket() { return packet_creator_.SerializeConnectivityProbingPacket(); }
diff --git a/net/quic/core/quic_packet_generator.h b/net/quic/core/quic_packet_generator.h index d3f1473a..2982b97 100644 --- a/net/quic/core/quic_packet_generator.h +++ b/net/quic/core/quic_packet_generator.h
@@ -140,7 +140,7 @@ const ParsedQuicVersionVector& supported_versions); // Creates a connectivity probing packet. - std::unique_ptr<QuicEncryptedPacket> SerializeConnectivityProbingPacket(); + OwningSerializedPacketPointer SerializeConnectivityProbingPacket(); // Re-serializes frames with the original packet's packet number length. // Used for retransmitting packets to ensure they aren't too long.
diff --git a/net/quic/core/quic_packet_generator_test.cc b/net/quic/core/quic_packet_generator_test.cc index e24df72..56d15f6 100644 --- a/net/quic/core/quic_packet_generator_test.cc +++ b/net/quic/core/quic_packet_generator_test.cc
@@ -27,10 +27,10 @@ #include "net/quic/test_tools/simple_quic_framer.h" using std::string; +using testing::_; using testing::InSequence; using testing::Return; using testing::StrictMock; -using testing::_; namespace net { namespace test { @@ -110,10 +110,7 @@ QuicRandom* random_generator, DelegateInterface* delegate, SimpleDataProducer* producer) - : QuicPacketGenerator(connection_id, - framer, - random_generator, - delegate), + : QuicPacketGenerator(connection_id, framer, random_generator, delegate), producer_(producer) {} QuicConsumedData ConsumeDataFastPath(QuicStreamId id, @@ -938,10 +935,11 @@ TEST_F(QuicPacketGeneratorTest, GenerateConnectivityProbingPacket) { delegate_.SetCanWriteAnything(); - std::unique_ptr<QuicEncryptedPacket> probing_packet( + OwningSerializedPacketPointer probing_packet( generator_.SerializeConnectivityProbingPacket()); - ASSERT_TRUE(simple_framer_.ProcessPacket(*probing_packet)); + ASSERT_TRUE(simple_framer_.ProcessPacket(QuicEncryptedPacket( + probing_packet->encrypted_buffer, probing_packet->encrypted_length))); EXPECT_EQ(2u, simple_framer_.num_frames()); EXPECT_EQ(1u, simple_framer_.ping_frames().size());
diff --git a/net/quic/core/quic_packets.h b/net/quic/core/quic_packets.h index 3ee5a6bd..78db9f19 100644 --- a/net/quic/core/quic_packets.h +++ b/net/quic/core/quic_packets.h
@@ -247,6 +247,21 @@ // |packet.encrypted_buffer|. QUIC_EXPORT_PRIVATE char* CopyBuffer(const SerializedPacket& packet); +struct QUIC_EXPORT_PRIVATE SerializedPacketDeleter { + void operator()(SerializedPacket* packet) { + if (packet->encrypted_buffer != nullptr) { + delete[] packet->encrypted_buffer; + } + delete packet; + } +}; + +// On destruction, OwningSerializedPacketPointer deletes a packet's (on-heap) +// encrypted_buffer before deleting the (also on-heap) packet itself. +// TODO(wub): Maybe delete retransmittable_frames too? +typedef std::unique_ptr<SerializedPacket, SerializedPacketDeleter> + OwningSerializedPacketPointer; + } // namespace net #endif // NET_QUIC_CORE_QUIC_PACKETS_H_
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc index 26411993..cff5dfbf 100644 --- a/net/quic/core/quic_sent_packet_manager.cc +++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -70,7 +70,6 @@ loss_algorithm_(&general_loss_algorithm_), general_loss_algorithm_(loss_type), n_connection_simulation_(false), - least_packet_awaited_by_peer_(1), first_rto_transmission_(0), consecutive_rto_count_(0), consecutive_tlp_count_(0), @@ -206,7 +205,6 @@ QuicTime ack_receive_time) { DCHECK_LE(LargestAcked(ack_frame), unacked_packets_.largest_sent_packet()); QuicByteCount prior_in_flight = unacked_packets_.bytes_in_flight(); - UpdatePacketInformationReceivedByPeer(ack_frame); bool rtt_updated = MaybeUpdateRTT(ack_frame, ack_receive_time); DCHECK_GE(LargestAcked(ack_frame), unacked_packets_.largest_observed()); unacked_packets_.IncreaseLargestObserved(LargestAcked(ack_frame)); @@ -254,15 +252,6 @@ } } -void QuicSentPacketManager::UpdatePacketInformationReceivedByPeer( - const QuicAckFrame& ack_frame) { - if (ack_frame.packets.Empty()) { - least_packet_awaited_by_peer_ = LargestAcked(ack_frame) + 1; - } else { - least_packet_awaited_by_peer_ = ack_frame.packets.Min(); - } -} - void QuicSentPacketManager::MaybeInvokeCongestionEvent( bool rtt_updated, QuicByteCount prior_in_flight, @@ -329,7 +318,7 @@ QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked(); for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it, ++packet_number) { - if (!it->retransmittable_frames.empty() && + if (unacked_packets_.HasRetransmittableFrames(*it) && (retransmission_type == ALL_UNACKED_RETRANSMISSION || it->encryption_level == ENCRYPTION_INITIAL)) { MarkForRetransmission(packet_number, retransmission_type); @@ -341,7 +330,7 @@ QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked(); for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it, ++packet_number) { - if (!it->retransmittable_frames.empty() && + if (unacked_packets_.HasRetransmittableFrames(*it) && it->encryption_level == ENCRYPTION_NONE) { // Once you're forward secure, no unencrypted packets will be sent, crypto // or otherwise. Unencrypted packets are neutered and abandoned, to ensure @@ -359,7 +348,7 @@ TransmissionType transmission_type) { const QuicTransmissionInfo& transmission_info = unacked_packets_.GetTransmissionInfo(packet_number); - QUIC_BUG_IF(transmission_info.retransmittable_frames.empty()); + QUIC_BUG_IF(!unacked_packets_.HasRetransmittableFrames(transmission_info)); // Both TLP and the new RTO leave the packets in flight and let the loss // detection decide if packets are lost. if (transmission_type != TLP_RETRANSMISSION && @@ -428,7 +417,7 @@ DCHECK(unacked_packets_.IsUnacked(packet_number)) << packet_number; const QuicTransmissionInfo& transmission_info = unacked_packets_.GetTransmissionInfo(packet_number); - DCHECK(!transmission_info.retransmittable_frames.empty()); + DCHECK(unacked_packets_.HasRetransmittableFrames(transmission_info)); return QuicPendingRetransmission(packet_number, transmission_type, transmission_info); @@ -577,7 +566,7 @@ for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it, ++packet_number) { // Only retransmit frames which are in flight, and therefore have been sent. - if (!it->in_flight || it->retransmittable_frames.empty() || + if (!it->in_flight || !unacked_packets_.HasRetransmittableFrames(*it) || !it->has_crypto_handshake) { continue; } @@ -600,7 +589,7 @@ for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it, ++packet_number) { // Only retransmit frames which are in flight, and therefore have been sent. - if (!it->in_flight || it->retransmittable_frames.empty()) { + if (!it->in_flight || !unacked_packets_.HasRetransmittableFrames(*it)) { continue; } MarkForRetransmission(packet_number, type); @@ -618,7 +607,7 @@ QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked(); for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it, ++packet_number) { - if (!it->retransmittable_frames.empty() && + if (unacked_packets_.HasRetransmittableFrames(*it) && pending_timer_transmission_count_ < kMaxRetransmissionsOnTimeout) { MarkForRetransmission(packet_number, RTO_RETRANSMISSION); ++pending_timer_transmission_count_; @@ -626,7 +615,7 @@ // Abandon non-retransmittable data that's in flight to ensure it doesn't // fill up the congestion window. const bool has_retransmissions = it->retransmission != 0; - if (it->retransmittable_frames.empty() && it->in_flight && + if (!unacked_packets_.HasRetransmittableFrames(*it) && it->in_flight && !has_retransmissions) { // Log only for non-retransmittable data. // Retransmittable data is marked as lost during loss detection, and will
diff --git a/net/quic/core/quic_sent_packet_manager.h b/net/quic/core/quic_sent_packet_manager.h index b0c974c..a608ba1a 100644 --- a/net/quic/core/quic_sent_packet_manager.h +++ b/net/quic/core/quic_sent_packet_manager.h
@@ -258,9 +258,6 @@ typedef QuicLinkedHashMap<QuicPacketNumber, TransmissionType> PendingRetransmissionMap; - // Updates the least_packet_awaited_by_peer. - void UpdatePacketInformationReceivedByPeer(const QuicAckFrame& ack_frame); - // Process the incoming ack looking for newly ack'd data packets. void HandleAckForSentPackets(const QuicAckFrame& ack_frame); @@ -367,9 +364,6 @@ GeneralLossAlgorithm general_loss_algorithm_; bool n_connection_simulation_; - // Least packet number which the peer is still waiting for. - QuicPacketNumber least_packet_awaited_by_peer_; - // Tracks the first RTO packet. If any packet before that packet gets acked, // it indicates the RTO was spurious and should be reversed(F-RTO). QuicPacketNumber first_rto_transmission_;
diff --git a/net/quic/core/quic_sent_packet_manager_test.cc b/net/quic/core/quic_sent_packet_manager_test.cc index 8b70717..ad554c70 100644 --- a/net/quic/core/quic_sent_packet_manager_test.cc +++ b/net/quic/core/quic_sent_packet_manager_test.cc
@@ -533,13 +533,12 @@ TEST_F(QuicSentPacketManagerTest, Rtt) { QuicPacketNumber packet_number = 1; - QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(15); + QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(20); SendDataPacket(packet_number); - clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20)); + clock_.AdvanceTime(expected_rtt); ExpectAck(packet_number); QuicAckFrame ack_frame = InitAckFrame(packet_number); - ack_frame.ack_delay_time = QuicTime::Delta::FromMilliseconds(5); manager_.OnIncomingAck(ack_frame, clock_.Now()); EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt()); }
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc index b53709c0..4fe9d40 100644 --- a/net/quic/core/quic_session.cc +++ b/net/quic/core/quic_session.cc
@@ -54,9 +54,13 @@ perspective() == Perspective::IS_SERVER, nullptr), currently_writing_stream_id_(0), + goaway_sent_(false), + goaway_received_(false), can_use_slices_(GetQuicReloadableFlag(quic_use_mem_slices)), allow_multiple_acks_for_data_( - GetQuicReloadableFlag(quic_allow_multiple_acks_for_data2)) { + GetQuicReloadableFlag(quic_allow_multiple_acks_for_data2)), + session_unblocks_stream_( + GetQuicReloadableFlag(quic_streams_unblocked_by_session)) { if (allow_multiple_acks_for_data_) { QUIC_FLAG_COUNT(quic_reloadable_flag_quic_allow_multiple_acks_for_data2); } @@ -146,7 +150,9 @@ stream->OnStreamReset(frame); } -void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) {} +void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) { + goaway_received_ = true; +} void QuicSession::OnConnectionClosed(QuicErrorCode error, const string& error_details, @@ -400,9 +406,10 @@ } void QuicSession::SendGoAway(QuicErrorCode error_code, const string& reason) { - if (goaway_sent()) { + if (goaway_sent_) { return; } + goaway_sent_ = true; connection_->SendGoAway(error_code, largest_peer_created_stream_id_, reason); } @@ -832,14 +839,6 @@ max_open_outgoing_streams_ = max_open_outgoing_streams; } -bool QuicSession::goaway_sent() const { - return connection_->goaway_sent(); -} - -bool QuicSession::goaway_received() const { - return connection_->goaway_received(); -} - bool QuicSession::IsClosedStream(QuicStreamId id) { DCHECK_NE(0u, id); if (IsOpenStream(id)) {
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h index 35981f0..abd3a1ab 100644 --- a/net/quic/core/quic_session.h +++ b/net/quic/core/quic_session.h
@@ -240,9 +240,9 @@ // connection, or in a write-blocked stream. bool HasDataToWrite() const; - bool goaway_sent() const; + bool goaway_sent() const { return goaway_sent_; } - bool goaway_received() const; + bool goaway_received() const { return goaway_received_; } QuicErrorCode error() const { return error_; } @@ -287,6 +287,8 @@ return allow_multiple_acks_for_data_; } + bool session_unblocks_stream() const { return session_unblocks_stream_; } + protected: using StaticStreamMap = QuicSmallMap<QuicStreamId, QuicStream*, 2>; @@ -502,6 +504,12 @@ // call stack of OnCanWrite. QuicStreamId currently_writing_stream_id_; + // Whether a GoAway has been sent. + bool goaway_sent_; + + // Whether a GoAway has been received. + bool goaway_received_; + // QUIC stream can take ownership of application data provided in reference // counted memory to avoid data copy. const bool can_use_slices_; @@ -514,6 +522,9 @@ // List of streams with pending retransmissions. QuicLinkedHashMap<QuicStreamId, bool> streams_with_pending_retransmission_; + // Latched value of quic_reloadable_flag_quic_streams_unblocked_by_session. + const bool session_unblocks_stream_; + DISALLOW_COPY_AND_ASSIGN(QuicSession); };
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc index 734e2a827..8a76566 100644 --- a/net/quic/core/quic_session_test.cc +++ b/net/quic/core/quic_session_test.cc
@@ -822,6 +822,15 @@ EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId)); } +TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) { + EXPECT_CALL(*connection_, + SendGoAway(QUIC_PEER_GOING_AWAY, kHeadersStreamId, "Going Away.")) + .Times(1); + session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away."); + EXPECT_TRUE(session_.goaway_sent()); + session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away."); +} + TEST_P(QuicSessionTestServer, InvalidGoAway) { QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY, session_.next_outgoing_stream_id(), "");
diff --git a/net/quic/core/quic_stream.cc b/net/quic/core/quic_stream.cc index 53fae61..8d1771a 100644 --- a/net/quic/core/quic_stream.cc +++ b/net/quic/core/quic_stream.cc
@@ -508,12 +508,20 @@ void QuicStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) { if (flow_controller_.UpdateSendWindowOffset(frame.byte_offset)) { - // Writing can be done again! - // TODO(rjshade): This does not respect priorities (e.g. multiple - // outstanding POSTs are unblocked on arrival of - // SHLO with initial window). - // As long as the connection is not flow control blocked, write on! - OnCanWrite(); + if (session_->session_unblocks_stream()) { + if (HasBufferedData()) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_streams_unblocked_by_session); + // Let session unblock this stream. + session_->MarkConnectionLevelWriteBlocked(id_); + } + } else { + // Writing can be done again! + // TODO(rjshade): This does not respect priorities (e.g. multiple + // outstanding POSTs are unblocked on arrival of + // SHLO with initial window). + // As long as the connection is not flow control blocked, write on! + OnCanWrite(); + } } }
diff --git a/net/quic/core/quic_stream_test.cc b/net/quic/core/quic_stream_test.cc index ef3667af..73bac878 100644 --- a/net/quic/core/quic_stream_test.cc +++ b/net/quic/core/quic_stream_test.cc
@@ -1165,6 +1165,32 @@ stream_->OnCanWrite(); } +TEST_F(QuicStreamTest, MarkConnectionLevelWriteBlockedOnWindowUpdateFrame) { + // Set a small initial control window size. + set_initial_flow_control_window_bytes(100); + Initialize(kShouldProcessData); + + EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); + EXPECT_CALL(*connection_, SendBlocked(stream_->id())); + string data(1024, '.'); + stream_->WriteOrBufferData(data, false, nullptr); + EXPECT_FALSE(HasWriteBlockedStreams()); + + QuicWindowUpdateFrame window_update(kInvalidControlFrameId, stream_->id(), + 1234); + + stream_->OnWindowUpdateFrame(window_update); + if (session_->session_unblocks_stream()) { + // Verify stream is marked connection level write blocked. + EXPECT_TRUE(HasWriteBlockedStreams()); + EXPECT_TRUE(stream_->HasBufferedData()); + } else { + EXPECT_FALSE(HasWriteBlockedStreams()); + EXPECT_FALSE(stream_->HasBufferedData()); + } +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/core/quic_types.h b/net/quic/core/quic_types.h index 618c7754..7537e5a7 100644 --- a/net/quic/core/quic_types.h +++ b/net/quic/core/quic_types.h
@@ -112,7 +112,7 @@ SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK }; -enum QuicFrameType { +enum QuicFrameType : int8_t { // Regular frame types. The values set here cannot change without the // introduction of a new QUIC version. PADDING_FRAME = 0,
diff --git a/net/quic/core/quic_unacked_packet_map.cc b/net/quic/core/quic_unacked_packet_map.cc index 18be0ba3..a8ded035 100644 --- a/net/quic/core/quic_unacked_packet_map.cc +++ b/net/quic/core/quic_unacked_packet_map.cc
@@ -136,8 +136,13 @@ QuicPacketNumber packet_number) const { DCHECK_GE(packet_number, least_unacked_); DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); - return !unacked_packets_[packet_number - least_unacked_] - .retransmittable_frames.empty(); + return HasRetransmittableFrames( + unacked_packets_[packet_number - least_unacked_]); +} + +bool QuicUnackedPacketMap::HasRetransmittableFrames( + const QuicTransmissionInfo& info) const { + return !info.retransmittable_frames.empty(); } void QuicUnackedPacketMap::RemoveRetransmittability( @@ -149,7 +154,7 @@ } if (info->has_crypto_handshake) { - DCHECK(!info->retransmittable_frames.empty()); + DCHECK(HasRetransmittableFrames(*info)); DCHECK_LT(0u, pending_crypto_packet_count_); --pending_crypto_packet_count_; info->has_crypto_handshake = false; @@ -190,7 +195,7 @@ const QuicTransmissionInfo& info) const { // Packet may have retransmittable frames, or the data may have been // retransmitted with a new packet number. - return !info.retransmittable_frames.empty() || + return HasRetransmittableFrames(info) || // Allow for an extra 1 RTT before stopping to track old packets. info.retransmission > largest_observed_; } @@ -312,7 +317,7 @@ bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const { for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); it != unacked_packets_.rend(); ++it) { - if (it->in_flight && !it->retransmittable_frames.empty()) { + if (it->in_flight && HasRetransmittableFrames(*it)) { return true; } }
diff --git a/net/quic/core/quic_unacked_packet_map.h b/net/quic/core/quic_unacked_packet_map.h index 6e2eb8a..98dc178 100644 --- a/net/quic/core/quic_unacked_packet_map.h +++ b/net/quic/core/quic_unacked_packet_map.h
@@ -55,13 +55,16 @@ // No longer retransmit data for |stream_id|. void CancelRetransmissionsForStream(QuicStreamId stream_id); - // Returns true if the unacked packet |packet_number| has retransmittable - // frames. This will return false if the packet has been acked, if a - // previous transmission of this packet was ACK'd, or if this packet has been - // retransmitted as with different packet number, or if the packet never - // had any retransmittable packets in the first place. + // Returns true if |packet_number| has retransmittable frames. This will + // return false if all frames of this packet are either non-retransmittable or + // have been acked. bool HasRetransmittableFrames(QuicPacketNumber packet_number) const; + // Returns true if |info| has retransmittable frames. This will return false + // if all frames of this packet are either non-retransmittable or have been + // acked. + bool HasRetransmittableFrames(const QuicTransmissionInfo& info) const; + // Returns true if there are any unacked packets. bool HasUnackedPackets() const;
diff --git a/net/quic/core/quic_unacked_packet_map_test.cc b/net/quic/core/quic_unacked_packet_map_test.cc index cf81a97..c1c9c9f9 100644 --- a/net/quic/core/quic_unacked_packet_map_test.cc +++ b/net/quic/core/quic_unacked_packet_map_test.cc
@@ -96,7 +96,7 @@ size_t num_retransmittable_packets = 0; for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it) { - if (!it->retransmittable_frames.empty()) { + if (unacked_packets_.HasRetransmittableFrames(*it)) { ++num_retransmittable_packets; } }
diff --git a/net/quic/test_tools/quic_packet_creator_peer.cc b/net/quic/test_tools/quic_packet_creator_peer.cc index 138460da..b502a9b 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.cc +++ b/net/quic/test_tools/quic_packet_creator_peer.cc
@@ -77,7 +77,7 @@ } // static -std::unique_ptr<QuicEncryptedPacket> +OwningSerializedPacketPointer QuicPacketCreatorPeer::SerializeConnectivityProbingPacket( QuicPacketCreator* creator) { return creator->SerializeConnectivityProbingPacket();
diff --git a/net/quic/test_tools/quic_packet_creator_peer.h b/net/quic/test_tools/quic_packet_creator_peer.h index e65a24d8..1e9e7b3 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.h +++ b/net/quic/test_tools/quic_packet_creator_peer.h
@@ -39,8 +39,8 @@ const QuicFrames& frames, char* buffer, size_t buffer_len); - static std::unique_ptr<QuicEncryptedPacket> - SerializeConnectivityProbingPacket(QuicPacketCreator* creator); + static OwningSerializedPacketPointer SerializeConnectivityProbingPacket( + QuicPacketCreator* creator); static EncryptionLevel GetEncryptionLevel(QuicPacketCreator* creator); static QuicFramer* framer(QuicPacketCreator* creator);
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/net/quic/test_tools/quic_sent_packet_manager_peer.cc index c706543..7af24e0 100644 --- a/net/quic/test_tools/quic_sent_packet_manager_peer.cc +++ b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -119,7 +119,7 @@ for (QuicUnackedPacketMap::const_iterator it = sent_packet_manager->unacked_packets_.begin(); it != sent_packet_manager->unacked_packets_.end(); ++it) { - if (!it->retransmittable_frames.empty()) { + if (sent_packet_manager->unacked_packets_.HasRetransmittableFrames(*it)) { ++num_unacked_packets; } }
diff --git a/net/reporting/reporting_feature.cc b/net/reporting/reporting_feature.cc deleted file mode 100644 index 9f4e28e..0000000 --- a/net/reporting/reporting_feature.cc +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/reporting/reporting_feature.h" - -namespace features { - -const base::Feature kReporting{"Reporting", base::FEATURE_DISABLED_BY_DEFAULT}; - -} // namespace features
diff --git a/net/reporting/reporting_feature.h b/net/reporting/reporting_feature.h deleted file mode 100644 index 4bd3d39..0000000 --- a/net/reporting/reporting_feature.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_REPORTING_REPORTING_FEATURE_H_ -#define NET_REPORTING_REPORTING_FEATURE_H_ - -#include "base/feature_list.h" -#include "net/base/net_export.h" - -namespace features { - -extern const base::Feature NET_EXPORT kReporting; - -} // namespace features - -#endif // NET_REPORTING_REPORTING_FEATURE_H_
diff --git a/net/reporting/reporting_service.cc b/net/reporting/reporting_service.cc index 59976e23..46fbba8e 100644 --- a/net/reporting/reporting_service.cc +++ b/net/reporting/reporting_service.cc
@@ -62,6 +62,10 @@ return context_->uploader()->RequestIsUpload(request); } + const ReportingPolicy& GetPolicy() const override { + return context_->policy(); + } + private: std::unique_ptr<ReportingContext> context_;
diff --git a/net/reporting/reporting_service.h b/net/reporting/reporting_service.h index aa7dc40e..37958702 100644 --- a/net/reporting/reporting_service.h +++ b/net/reporting/reporting_service.h
@@ -70,6 +70,8 @@ // about report uploads. virtual bool RequestIsUpload(const URLRequest& request) = 0; + virtual const ReportingPolicy& GetPolicy() const = 0; + protected: ReportingService() {}
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index c9fe4605..00a86d27 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -845,7 +845,7 @@ // Setup a SpdySessionKey test_hosts[i].key = SpdySessionKey( HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); } MockRead reads[] = { @@ -905,7 +905,7 @@ // Setup a SpdySessionKey test_hosts[i].key = SpdySessionKey( HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); } MockRead reads[] = {
diff --git a/net/spdy/chromium/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/chromium/bidirectional_stream_spdy_impl_unittest.cc index a92c304..5247745 100644 --- a/net/spdy/chromium/bidirectional_stream_spdy_impl_unittest.cc +++ b/net/spdy/chromium/bidirectional_stream_spdy_impl_unittest.cc
@@ -16,6 +16,7 @@ #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/log/test_net_log.h" +#include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" #include "net/spdy/chromium/spdy_session.h" #include "net/spdy/chromium/spdy_test_util_common.h" @@ -233,7 +234,10 @@ BidirectionalStreamSpdyImplTest() : default_url_(kDefaultUrl), host_port_pair_(HostPortPair::FromURL(default_url_)), - key_(host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED), + key_(host_port_pair_, + ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, + SocketTag()), ssl_data_(SSLSocketDataProvider(ASYNC, OK)) { ssl_data_.next_proto = kProtoHTTP2; ssl_data_.ssl_info.cert =
diff --git a/net/spdy/chromium/http2_push_promise_index_test.cc b/net/spdy/chromium/http2_push_promise_index_test.cc index 6777cb50..39d9d83 100644 --- a/net/spdy/chromium/http2_push_promise_index_test.cc +++ b/net/spdy/chromium/http2_push_promise_index_test.cc
@@ -6,6 +6,7 @@ #include "net/base/host_port_pair.h" #include "net/base/privacy_mode.h" +#include "net/socket/socket_tag.h" #include "net/test/gtest_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -58,10 +59,12 @@ url2_("https://mail.example.com"), key1_(HostPortPair::FromURL(url1_), ProxyServer::Direct(), - PRIVACY_MODE_ENABLED), + PRIVACY_MODE_ENABLED, + SocketTag()), key2_(HostPortPair::FromURL(url2_), ProxyServer::Direct(), - PRIVACY_MODE_ENABLED) {} + PRIVACY_MODE_ENABLED, + SocketTag()) {} const GURL url1_; const GURL url2_;
diff --git a/net/spdy/chromium/spdy_http_stream_unittest.cc b/net/spdy/chromium/spdy_http_stream_unittest.cc index 83f92b95..e9b0d0a 100644 --- a/net/spdy/chromium/spdy_http_stream_unittest.cc +++ b/net/spdy/chromium/spdy_http_stream_unittest.cc
@@ -22,6 +22,7 @@ #include "net/http/http_response_info.h" #include "net/log/net_log_with_source.h" #include "net/log/test_net_log.h" +#include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" #include "net/spdy/chromium/spdy_http_utils.h" #include "net/spdy/chromium/spdy_test_util_common.h" @@ -125,7 +126,10 @@ SpdyHttpStreamTest() : url_(kDefaultUrl), host_port_pair_(HostPortPair::FromURL(url_)), - key_(host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED), + key_(host_port_pair_, + ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, + SocketTag()), ssl_(SYNCHRONOUS, OK) { session_deps_.net_log = &net_log_; }
diff --git a/net/spdy/chromium/spdy_network_transaction_unittest.cc b/net/spdy/chromium/spdy_network_transaction_unittest.cc index 0da92cf..160830d4 100644 --- a/net/spdy/chromium/spdy_network_transaction_unittest.cc +++ b/net/spdy/chromium/spdy_network_transaction_unittest.cc
@@ -37,6 +37,7 @@ #include "net/proxy/proxy_server.h" #include "net/socket/client_socket_pool_base.h" #include "net/socket/next_proto.h" +#include "net/socket/socket_tag.h" #include "net/spdy/chromium/buffered_spdy_framer.h" #include "net/spdy/chromium/spdy_http_stream.h" #include "net/spdy/chromium/spdy_http_utils.h" @@ -387,7 +388,8 @@ // session. Once we have the session, we verify that the streams are // all closed and not leaked at this point. SpdySessionKey key(HostPortPair::FromURL(request_.url), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + ProxyServer::Direct(), PRIVACY_MODE_DISABLED, + SocketTag()); HttpNetworkSession* session = helper.session(); base::WeakPtr<SpdySession> spdy_session = session->spdy_session_pool()->FindAvailableSession( @@ -3213,7 +3215,7 @@ SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); SpdySessionKey key(host_port_pair_, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session = spdy_session_pool->FindAvailableSession( key, /* enable_ip_based_pooling = */ true, log_); @@ -3325,7 +3327,7 @@ SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); SpdySessionKey key1(HostPortPair::FromURL(GURL(kUrl1)), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session1 = spdy_session_pool->FindAvailableSession( key1, /* enable_ip_based_pooling = */ true, log_); @@ -3335,7 +3337,7 @@ // a client-initiated request would not pool to this connection, // because the IP address does not match. SpdySessionKey key2(HostPortPair::FromURL(GURL(kUrl2)), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); EXPECT_FALSE(spdy_session_pool->FindAvailableSession( key2, /* enable_ip_based_pooling = */ true, log_)); @@ -4354,7 +4356,7 @@ // GOAWAY frame has not yet been received, SpdySession should be available. SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); SpdySessionKey key(host_port_pair_, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session = spdy_session_pool->FindAvailableSession( key, /* enable_ip_based_pooling = */ true, log_); @@ -4712,12 +4714,12 @@ // Check that the SpdySession is still in the SpdySessionPool. SpdySessionKey session_pool_key_direct(host_port_pair_, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct)); SpdySessionKey session_pool_key_proxy( host_port_pair_, ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy)); // New SpdyTestUtil instance for the session that will be used for the @@ -5327,7 +5329,7 @@ SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); SpdySessionKey key(host_port_pair_, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session = spdy_session_pool->FindAvailableSession( key, /* enable_ip_based_pooling = */ true, log_); @@ -5467,7 +5469,7 @@ SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); HostPortPair host_port_pair0("mail.example.org", 443); SpdySessionKey key0(host_port_pair0, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session0 = spdy_session_pool->FindAvailableSession( key0, /* enable_ip_based_pooling = */ true, log_); @@ -5476,7 +5478,7 @@ HostPortPair host_port_pair1("docs.example.org", 443); SpdySessionKey key1(host_port_pair1, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> spdy_session1 = spdy_session_pool->FindAvailableSession( key1, /* enable_ip_based_pooling = */ true, log_); @@ -6969,7 +6971,7 @@ // Get a SpdySession. SpdySessionKey key(HostPortPair::FromURL(request_.url), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); HttpNetworkSession* session = helper.session(); base::WeakPtr<SpdySession> spdy_session = session->spdy_session_pool()->FindAvailableSession(
diff --git a/net/spdy/chromium/spdy_proxy_client_socket_unittest.cc b/net/spdy/chromium/spdy_proxy_client_socket_unittest.cc index e8eccf49..be9525be 100644 --- a/net/spdy/chromium/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/chromium/spdy_proxy_client_socket_unittest.cc
@@ -23,6 +23,7 @@ #include "net/log/test_net_log_entry.h" #include "net/log/test_net_log_util.h" #include "net/socket/client_socket_factory.h" +#include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" #include "net/socket/tcp_client_socket.h" #include "net/spdy/chromium/buffered_spdy_framer.h" @@ -159,7 +160,8 @@ proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_), endpoint_spdy_session_key_(endpoint_host_port_pair_, proxy_, - PRIVACY_MODE_DISABLED) { + PRIVACY_MODE_DISABLED, + SocketTag()) { session_deps_.net_log = net_log_.bound().net_log(); }
diff --git a/net/spdy/chromium/spdy_session_fuzzer.cc b/net/spdy/chromium/spdy_session_fuzzer.cc index a1ac99d..6583a9c3 100644 --- a/net/spdy/chromium/spdy_session_fuzzer.cc +++ b/net/spdy/chromium/spdy_session_fuzzer.cc
@@ -14,6 +14,7 @@ #include "net/log/test_net_log.h" #include "net/socket/client_socket_handle.h" #include "net/socket/fuzzed_socket_factory.h" +#include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" #include "net/socket/ssl_client_socket.h" #include "net/spdy/chromium/spdy_test_util_common.h" @@ -117,7 +118,8 @@ net::ProxyServer direct_connect(net::ProxyServer::Direct()); net::SpdySessionKey session_key(net::HostPortPair("127.0.0.1", 80), - direct_connect, net::PRIVACY_MODE_DISABLED); + direct_connect, net::PRIVACY_MODE_DISABLED, + net::SocketTag()); base::WeakPtr<net::SpdySession> spdy_session(net::CreateSpdySession( http_session.get(), session_key, bound_test_net_log.bound()));
diff --git a/net/spdy/chromium/spdy_session_key.cc b/net/spdy/chromium/spdy_session_key.cc index be206e5..4331c388 100644 --- a/net/spdy/chromium/spdy_session_key.cc +++ b/net/spdy/chromium/spdy_session_key.cc
@@ -16,9 +16,11 @@ SpdySessionKey::SpdySessionKey(const HostPortPair& host_port_pair, const ProxyServer& proxy_server, - PrivacyMode privacy_mode) + PrivacyMode privacy_mode, + const SocketTag& socket_tag) : host_port_proxy_pair_(host_port_pair, proxy_server), - privacy_mode_(privacy_mode) { + privacy_mode_(privacy_mode), + socket_tag_(socket_tag) { DVLOG(1) << "SpdySessionKey(host=" << host_port_pair.ToString() << ", proxy=" << proxy_server.ToURI() << ", privacy=" << privacy_mode; @@ -30,15 +32,17 @@ bool SpdySessionKey::operator<(const SpdySessionKey& other) const { return std::tie(privacy_mode_, host_port_proxy_pair_.first, - host_port_proxy_pair_.second) < + host_port_proxy_pair_.second, socket_tag_) < std::tie(other.privacy_mode_, other.host_port_proxy_pair_.first, - other.host_port_proxy_pair_.second); + other.host_port_proxy_pair_.second, other.socket_tag_); } bool SpdySessionKey::operator==(const SpdySessionKey& other) const { return privacy_mode_ == other.privacy_mode_ && - host_port_proxy_pair_.first.Equals(other.host_port_proxy_pair_.first) && - host_port_proxy_pair_.second == other.host_port_proxy_pair_.second; + host_port_proxy_pair_.first.Equals( + other.host_port_proxy_pair_.first) && + host_port_proxy_pair_.second == other.host_port_proxy_pair_.second && + socket_tag_ == other.socket_tag_; } size_t SpdySessionKey::EstimateMemoryUsage() const {
diff --git a/net/spdy/chromium/spdy_session_key.h b/net/spdy/chromium/spdy_session_key.h index ef5ac19..cf338b8 100644 --- a/net/spdy/chromium/spdy_session_key.h +++ b/net/spdy/chromium/spdy_session_key.h
@@ -8,6 +8,7 @@ #include "net/base/net_export.h" #include "net/base/privacy_mode.h" #include "net/proxy/proxy_server.h" +#include "net/socket/socket_tag.h" namespace net { @@ -17,7 +18,8 @@ SpdySessionKey(); SpdySessionKey(const HostPortPair& host_port_pair, const ProxyServer& proxy_server, - PrivacyMode privacy_mode); + PrivacyMode privacy_mode, + const SocketTag& socket_tag); SpdySessionKey(const SpdySessionKey& other); @@ -45,6 +47,8 @@ return privacy_mode_; } + const SocketTag& socket_tag() const { return socket_tag_; } + // Returns the estimate of dynamically allocated memory in bytes. size_t EstimateMemoryUsage() const; @@ -52,6 +56,7 @@ HostPortProxyPair host_port_proxy_pair_; // If enabled, then session cannot be tracked by the server. PrivacyMode privacy_mode_ = PRIVACY_MODE_DISABLED; + SocketTag socket_tag_; }; } // namespace net
diff --git a/net/spdy/chromium/spdy_session_pool.cc b/net/spdy/chromium/spdy_session_pool.cc index 312e581a..d4a4594 100644 --- a/net/spdy/chromium/spdy_session_pool.cc +++ b/net/spdy/chromium/spdy_session_pool.cc
@@ -193,9 +193,10 @@ const SpdySessionKey& alias_key = alias_it->second; // We can reuse this session only if the proxy and privacy - // settings match. + // settings and socket tag match. if (!(alias_key.proxy_server() == key.proxy_server()) || - !(alias_key.privacy_mode() == key.privacy_mode())) + !(alias_key.privacy_mode() == key.privacy_mode()) || + !(alias_key.socket_tag() == key.socket_tag())) continue; AvailableSessionMap::iterator available_session_it =
diff --git a/net/spdy/chromium/spdy_session_pool_unittest.cc b/net/spdy/chromium/spdy_session_pool_unittest.cc index 74169d9..6445fdc 100644 --- a/net/spdy/chromium/spdy_session_pool_unittest.cc +++ b/net/spdy/chromium/spdy_session_pool_unittest.cc
@@ -20,6 +20,7 @@ #include "net/log/test_net_log.h" #include "net/log/test_net_log_entry.h" #include "net/socket/client_socket_handle.h" +#include "net/socket/socket_tag.h" #include "net/socket/transport_client_socket_pool.h" #include "net/spdy/chromium/spdy_session.h" #include "net/spdy/chromium/spdy_stream_test_util.h" @@ -118,9 +119,8 @@ HostPortPair test_host_port_pair(kTestHost, kTestPort); SpdySessionKey test_key = - SpdySessionKey( - test_host_port_pair, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + SpdySessionKey(test_host_port_pair, ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); MockConnect connect_data(SYNCHRONOUS, OK); MockRead reads[] = { @@ -181,7 +181,7 @@ const SpdyString kTestHost1("www.example.org"); HostPortPair test_host_port_pair1(kTestHost1, 80); SpdySessionKey key1(test_host_port_pair1, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> session1 = CreateSpdySession(http_session_.get(), key1, NetLogWithSource()); GURL url1(kTestHost1); @@ -196,7 +196,7 @@ const SpdyString kTestHost2("mail.example.org"); HostPortPair test_host_port_pair2(kTestHost2, 80); SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> session2 = CreateSpdySession(http_session_.get(), key2, NetLogWithSource()); GURL url2(kTestHost2); @@ -211,7 +211,7 @@ const SpdyString kTestHost3("mail.example.com"); HostPortPair test_host_port_pair3(kTestHost3, 80); SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> session3 = CreateSpdySession(http_session_.get(), key3, NetLogWithSource()); GURL url3(kTestHost3); @@ -290,9 +290,8 @@ HostPortPair test_host_port_pair(kTestHost, kTestPort); SpdySessionKey test_key = - SpdySessionKey( - test_host_port_pair, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + SpdySessionKey(test_host_port_pair, ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); MockConnect connect_data(SYNCHRONOUS, OK); MockRead reads[] = { @@ -372,7 +371,7 @@ // Setup a SpdySessionKey. test_hosts[i].key = SpdySessionKey( HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); } MockConnect connect_data(SYNCHRONOUS, OK); @@ -410,9 +409,10 @@ EXPECT_FALSE(session1); // Verify that the second host, through a proxy, won't share the IP. - SpdySessionKey proxy_key(test_hosts[1].key.host_port_pair(), + SpdySessionKey proxy_key( + test_hosts[1].key.host_port_pair(), ProxyServer::FromPacString("HTTP http://proxy.foo.com/"), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); EXPECT_FALSE(HasSpdySession(spdy_session_pool_, proxy_key)); // Overlap between 2 and 3 does is not transitive to 1. @@ -555,9 +555,9 @@ info, DEFAULT_PRIORITY, &test_hosts[i].addresses, CompletionCallback(), &test_hosts[i].request, NetLogWithSource()); - test_hosts[i].key = - SpdySessionKey(HostPortPair(test_hosts[i].name, kTestPort), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + test_hosts[i].key = SpdySessionKey( + HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); } MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; @@ -634,9 +634,9 @@ info, DEFAULT_PRIORITY, &test_hosts[i].addresses, CompletionCallback(), &test_hosts[i].request, NetLogWithSource()); - test_hosts[i].key = - SpdySessionKey(HostPortPair(test_hosts[i].name, kTestPort), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + test_hosts[i].key = SpdySessionKey( + HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); } MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; @@ -714,8 +714,8 @@ // Set up session A: Going away, but with an active stream. const SpdyString kTestHostA("www.example.org"); HostPortPair test_host_port_pairA(kTestHostA, 80); - SpdySessionKey keyA( - test_host_port_pairA, ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + SpdySessionKey keyA(test_host_port_pairA, ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> sessionA = CreateSpdySession(http_session_.get(), keyA, NetLogWithSource()); @@ -745,8 +745,8 @@ const SpdyString kTestHostB("mail.example.org"); HostPortPair test_host_port_pairB(kTestHostB, 80); - SpdySessionKey keyB( - test_host_port_pairB, ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + SpdySessionKey keyB(test_host_port_pairB, ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> sessionB = CreateSpdySession(http_session_.get(), keyB, NetLogWithSource()); EXPECT_TRUE(sessionB->IsAvailable()); @@ -767,8 +767,8 @@ const SpdyString kTestHostC("mail.example.com"); HostPortPair test_host_port_pairC(kTestHostC, 80); - SpdySessionKey keyC( - test_host_port_pairC, ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + SpdySessionKey keyC(test_host_port_pairC, ProxyServer::Direct(), + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> sessionC = CreateSpdySession(http_session_.get(), keyC, NetLogWithSource()); @@ -826,7 +826,7 @@ const GURL url(kDefaultUrl); SpdySessionKey key(HostPortPair::FromURL(url), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> session = CreateSpdySession(http_session_.get(), key, NetLogWithSource()); @@ -881,7 +881,7 @@ const GURL url(kDefaultUrl); SpdySessionKey key(HostPortPair::FromURL(url), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); base::WeakPtr<SpdySession> session = CreateSpdySession(http_session_.get(), key, NetLogWithSource()); @@ -928,7 +928,7 @@ TEST_P(SpdySessionMemoryDumpTest, DumpMemoryStats) { SpdySessionKey key(HostPortPair("www.example.org", 443), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + ProxyServer::Direct(), PRIVACY_MODE_DISABLED, SocketTag()); MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
diff --git a/net/spdy/chromium/spdy_session_unittest.cc b/net/spdy/chromium/spdy_session_unittest.cc index 60e54bc8..c7e2d47 100644 --- a/net/spdy/chromium/spdy_session_unittest.cc +++ b/net/spdy/chromium/spdy_session_unittest.cc
@@ -133,7 +133,8 @@ test_server_(test_url_), key_(HostPortPair::FromURL(test_url_), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED), + PRIVACY_MODE_DISABLED, + SocketTag()), ssl_(SYNCHRONOUS, OK) {} ~SpdySessionTest() override { @@ -3508,14 +3509,16 @@ // Create an idle SPDY session. SpdySessionKey key1(HostPortPair("www.example.org", 80), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + ProxyServer::Direct(), PRIVACY_MODE_DISABLED, + SocketTag()); base::WeakPtr<SpdySession> session1 = ::net::CreateSpdySession(http_session_.get(), key1, NetLogWithSource()); EXPECT_FALSE(pool->IsStalled()); // Set up an alias for the idle SPDY session, increasing its ref count to 2. SpdySessionKey key2(HostPortPair("mail.example.org", 80), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + ProxyServer::Direct(), PRIVACY_MODE_DISABLED, + SocketTag()); HostResolver::RequestInfo info(key2.host_port_pair()); AddressList addresses; std::unique_ptr<HostResolver::Request> request; @@ -3649,9 +3652,9 @@ HostPortPair host_port_pair("www.example.org", 443); SpdySessionKey key_privacy_enabled(host_port_pair, ProxyServer::Direct(), - PRIVACY_MODE_ENABLED); + PRIVACY_MODE_ENABLED, SocketTag()); SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled));
diff --git a/net/spdy/chromium/spdy_stream_unittest.cc b/net/spdy/chromium/spdy_stream_unittest.cc index 12e40c02..214c54a5 100644 --- a/net/spdy/chromium/spdy_stream_unittest.cc +++ b/net/spdy/chromium/spdy_stream_unittest.cc
@@ -22,6 +22,7 @@ #include "net/log/test_net_log.h" #include "net/log/test_net_log_entry.h" #include "net/log/test_net_log_util.h" +#include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" #include "net/spdy/chromium/buffered_spdy_framer.h" #include "net/spdy/chromium/http2_push_promise_index.h" @@ -76,7 +77,7 @@ base::WeakPtr<SpdySession> CreateDefaultSpdySession() { SpdySessionKey key(HostPortPair::FromURL(url_), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); return CreateSpdySession(session_.get(), key, NetLogWithSource()); } @@ -356,7 +357,7 @@ data.RunUntilPaused(); const SpdySessionKey key(HostPortPair::FromURL(url_), ProxyServer::Direct(), - PRIVACY_MODE_DISABLED); + PRIVACY_MODE_DISABLED, SocketTag()); const GURL pushed_url(kPushUrl); HttpRequestInfo push_request; push_request.url = pushed_url;
diff --git a/net/test/spawned_test_server/remote_test_server.cc b/net/test/spawned_test_server/remote_test_server.cc index 8cfe03b2..23025c4 100644 --- a/net/test/spawned_test_server/remote_test_server.cc +++ b/net/test/spawned_test_server/remote_test_server.cc
@@ -23,8 +23,8 @@ #include "net/base/host_port_pair.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" -#include "net/test/spawned_test_server/remote_test_server_proxy.h" #include "net/test/spawned_test_server/remote_test_server_spawner_request.h" +#include "net/test/tcp_socket_proxy.h" #include "url/gurl.h" namespace net { @@ -96,8 +96,9 @@ SSLOptions::CERT_AUTO_AIA_INTERMEDIATE || !ssl_options().GetOCSPArgument().empty()); if (config_.address() != IPAddress::IPv4Localhost() && ocsp_server_enabled) { - ocsp_proxy_ = - std::make_unique<RemoteTestServerProxy>(io_thread_.task_runner()); + ocsp_proxy_ = std::make_unique<TcpSocketProxy>(io_thread_.task_runner()); + bool initialized = !ocsp_proxy_->Initialize(); + CHECK(initialized); arguments_dict.SetKey("ocsp-proxy-port-number", base::Value(ocsp_proxy_->local_port())); } @@ -135,7 +136,9 @@ // forward connections to the server. if (config_.address() != IPAddress::IPv4Localhost()) { test_server_proxy_ = - std::make_unique<RemoteTestServerProxy>(io_thread_.task_runner()); + std::make_unique<TcpSocketProxy>(io_thread_.task_runner()); + bool initialized = !test_server_proxy_->Initialize(); + CHECK(initialized); test_server_proxy_->Start(IPEndPoint(config_.address(), remote_port_)); if (ocsp_proxy_) {
diff --git a/net/test/spawned_test_server/remote_test_server.h b/net/test/spawned_test_server/remote_test_server.h index 8a7e430d..4fb3396 100644 --- a/net/test/spawned_test_server/remote_test_server.h +++ b/net/test/spawned_test_server/remote_test_server.h
@@ -15,7 +15,7 @@ namespace net { class RemoteTestServerSpawnerRequest; -class RemoteTestServerProxy; +class TcpSocketProxy; // The RemoteTestServer runs an external Python-based test server in another // machine that is different from the machine that executes the tests. It is @@ -92,8 +92,8 @@ // Server port. Non-zero when the server is running. int remote_port_ = 0; - std::unique_ptr<RemoteTestServerProxy> test_server_proxy_; - std::unique_ptr<RemoteTestServerProxy> ocsp_proxy_; + std::unique_ptr<TcpSocketProxy> test_server_proxy_; + std::unique_ptr<TcpSocketProxy> ocsp_proxy_; DISALLOW_COPY_AND_ASSIGN(RemoteTestServer); };
diff --git a/net/test/spawned_test_server/remote_test_server_proxy.h b/net/test/spawned_test_server/remote_test_server_proxy.h deleted file mode 100644 index 366e254..0000000 --- a/net/test/spawned_test_server/remote_test_server_proxy.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TEST_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_PROXY_H_ -#define NET_TEST_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_PROXY_H_ - -#include <stdint.h> - -#include <memory> - -#include "base/memory/ref_counted.h" -#include "base/threading/thread_checker.h" - -namespace base { -class SingleThreadTaskRunner; -} // namespace base - -namespace net { - -class IPEndPoint; - -// RemoteTestServerProxy proxies TCP connection from localhost to a remote IP -// address. -class RemoteTestServerProxy { - public: - explicit RemoteTestServerProxy( - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); - ~RemoteTestServerProxy(); - - uint16_t local_port() const { return local_port_; } - - // Starts the proxy for the specified |remote_address|. Must be called before - // any incoming connection on local_port() are initiated. - void Start(const IPEndPoint& remote_address); - - private: - class Core; - - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; - - // Core implements the proxy functionality. It runs on |io_task_runner_|. - std::unique_ptr<Core> core_; - - uint16_t local_port_; - - THREAD_CHECKER(thread_checker_); - - DISALLOW_COPY_AND_ASSIGN(RemoteTestServerProxy); -}; - -} // namespace net - -#endif // NET_TEST_SPAWNED_TEST_SERVER_REMOTE_TEST_SERVER_PROXY_H_
diff --git a/net/test/spawned_test_server/remote_test_server_proxy.cc b/net/test/tcp_socket_proxy.cc similarity index 71% rename from net/test/spawned_test_server/remote_test_server_proxy.cc rename to net/test/tcp_socket_proxy.cc index 86278709a..8b7d99c 100644 --- a/net/test/spawned_test_server/remote_test_server_proxy.cc +++ b/net/test/tcp_socket_proxy.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/test/spawned_test_server/remote_test_server_proxy.h" +#include "net/test/tcp_socket_proxy.h" #include <memory> #include <vector> @@ -112,13 +112,13 @@ explicit ConnectionProxy(std::unique_ptr<StreamSocket> local_socket); ~ConnectionProxy(); - void Start(const IPEndPoint& remote_address, + void Start(const IPEndPoint& remote_endpoint, base::OnceClosure on_done_callback); private: void Close(); - void HandleConnectResult(const IPEndPoint& remote_address, int result); + void HandleConnectResult(const IPEndPoint& remote_endpoint, int result); base::OnceClosure on_done_callback_; @@ -142,28 +142,28 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } -void ConnectionProxy::Start(const IPEndPoint& remote_address, +void ConnectionProxy::Start(const IPEndPoint& remote_endpoint, base::OnceClosure on_done_callback) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); on_done_callback_ = std::move(on_done_callback); remote_socket_ = std::make_unique<TCPClientSocket>( - AddressList(remote_address), nullptr, nullptr, NetLogSource()); + AddressList(remote_endpoint), nullptr, nullptr, NetLogSource()); int result = remote_socket_->Connect( base::Bind(&ConnectionProxy::HandleConnectResult, base::Unretained(this), - remote_address)); + remote_endpoint)); if (result != ERR_IO_PENDING) - HandleConnectResult(remote_address, result); + HandleConnectResult(remote_endpoint, result); } -void ConnectionProxy::HandleConnectResult(const IPEndPoint& remote_address, +void ConnectionProxy::HandleConnectResult(const IPEndPoint& remote_endpoint, int result) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!incoming_pump_); DCHECK(!outgoing_pump_); if (result < 0) { - LOG(ERROR) << "Connection to " << remote_address.ToString() + LOG(ERROR) << "Connection to " << remote_endpoint.ToString() << " failed: " << ErrorToString(result); Close(); return; @@ -194,20 +194,14 @@ } // namespace -// RemoteTestServerProxy implementation that runs on a background IO thread. -class RemoteTestServerProxy::Core { +// TcpSocketProxy implementation that runs on a background IO thread. +class TcpSocketProxy::Core { public: Core(); ~Core(); - // Creates local socket for accepting incoming connections and binds it to a - // port. local_port() comes valid after this call is complete. - void Initialize(base::WaitableEvent* initialized_event); - - // Starts accepting incoming connections and redirecting them to - // remote_address. Must be called only after Initialize(). - void Start(const IPEndPoint& remote_address); - + void Initialize(int local_port, base::WaitableEvent* initialized_event); + void Start(const IPEndPoint& remote_endpoint); uint16_t local_port() const { return local_port_; } private: @@ -216,11 +210,11 @@ void HandleAcceptResult(int result); void OnConnectionClosed(ConnectionProxy* connection); - IPEndPoint remote_address_; + IPEndPoint remote_endpoint_; std::unique_ptr<TCPServerSocket> socket_; - uint16_t local_port_; + uint16_t local_port_ = 0; std::vector<std::unique_ptr<ConnectionProxy>> connections_; std::unique_ptr<StreamSocket> accepted_socket_; @@ -228,35 +222,46 @@ DISALLOW_COPY_AND_ASSIGN(Core); }; -RemoteTestServerProxy::Core::Core() {} +TcpSocketProxy::Core::Core() {} -void RemoteTestServerProxy::Core::Initialize( - base::WaitableEvent* initialized_event) { - CHECK(!socket_); +void TcpSocketProxy::Core::Initialize(int local_port, + base::WaitableEvent* initialized_event) { + DCHECK(!socket_); + + local_port_ = 0; socket_ = std::make_unique<TCPServerSocket>(nullptr, net::NetLogSource()); - int result = socket_->Listen(IPEndPoint(IPAddress::IPv4Localhost(), 0), 5); - CHECK_EQ(result, OK); + int result = + socket_->Listen(IPEndPoint(IPAddress::IPv4Localhost(), local_port), 5); + if (result != OK) { + LOG(ERROR) << "TcpServerSocket::Listen() returned " + << ErrorToString(result); + } else { + // Get local port number. + IPEndPoint address; + result = socket_->GetLocalAddress(&address); + if (result != OK) { + LOG(ERROR) << "TcpServerSocket::GetLocalAddress() returned " + << ErrorToString(result); + } else { + local_port_ = address.port(); + } + } - // Get local port number. - IPEndPoint address; - result = socket_->GetLocalAddress(&address); - CHECK_EQ(result, OK); - local_port_ = address.port(); - - initialized_event->Signal(); + if (initialized_event) + initialized_event->Signal(); } -void RemoteTestServerProxy::Core::Start(const IPEndPoint& remote_address) { - CHECK(socket_); +void TcpSocketProxy::Core::Start(const IPEndPoint& remote_endpoint) { + DCHECK(socket_); - remote_address_ = remote_address; + remote_endpoint_ = remote_endpoint; DoAcceptLoop(); } -RemoteTestServerProxy::Core::~Core() {} +TcpSocketProxy::Core::~Core() {} -void RemoteTestServerProxy::Core::DoAcceptLoop() { +void TcpSocketProxy::Core::DoAcceptLoop() { int result = OK; while (result == OK) { result = socket_->Accept( @@ -267,13 +272,13 @@ } } -void RemoteTestServerProxy::Core::OnAcceptResult(int result) { +void TcpSocketProxy::Core::OnAcceptResult(int result) { HandleAcceptResult(result); if (result == OK) DoAcceptLoop(); } -void RemoteTestServerProxy::Core::HandleAcceptResult(int result) { +void TcpSocketProxy::Core::HandleAcceptResult(int result) { DCHECK_NE(result, ERR_IO_PENDING); if (result < 0) { @@ -290,13 +295,12 @@ // Start() may invoke the callback so it needs to be called after the // connection is pushed to connections_. connection_proxy_ptr->Start( - remote_address_, + remote_endpoint_, base::BindOnce(&Core::OnConnectionClosed, base::Unretained(this), connection_proxy_ptr)); } -void RemoteTestServerProxy::Core::OnConnectionClosed( - ConnectionProxy* connection) { +void TcpSocketProxy::Core::OnConnectionClosed(ConnectionProxy* connection) { for (auto it = connections_.begin(); it != connections_.end(); ++it) { if (it->get() == connection) { connections_.erase(it); @@ -306,30 +310,40 @@ NOTREACHED(); } -RemoteTestServerProxy::RemoteTestServerProxy( +TcpSocketProxy::TcpSocketProxy( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) - : io_task_runner_(io_task_runner), core_(std::make_unique<Core>()) { - base::WaitableEvent intialized_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - io_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&Core::Initialize, base::Unretained(core_.get()), - &intialized_event)); - intialized_event.Wait(); + : io_task_runner_(io_task_runner), core_(std::make_unique<Core>()) {} + +bool TcpSocketProxy::Initialize(int local_port) { + DCHECK(!local_port_); + + if (io_task_runner_->BelongsToCurrentThread()) { + core_->Initialize(local_port, nullptr); + } else { + base::WaitableEvent initialized_event( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + io_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&Core::Initialize, base::Unretained(core_.get()), + local_port, &initialized_event)); + initialized_event.Wait(); + } local_port_ = core_->local_port(); + + return local_port_ != 0; } -RemoteTestServerProxy::~RemoteTestServerProxy() { +TcpSocketProxy::~TcpSocketProxy() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - io_task_runner_->DeleteSoon(FROM_HERE, core_.release()); + io_task_runner_->DeleteSoon(FROM_HERE, std::move(core_)); } -void RemoteTestServerProxy::Start(const IPEndPoint& remote_address) { +void TcpSocketProxy::Start(const IPEndPoint& remote_endpoint) { io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&Core::Start, base::Unretained(core_.get()), - remote_address)); + remote_endpoint)); } } // namespace net
diff --git a/net/test/tcp_socket_proxy.h b/net/test/tcp_socket_proxy.h new file mode 100644 index 0000000..d0933f25 --- /dev/null +++ b/net/test/tcp_socket_proxy.h
@@ -0,0 +1,62 @@ +// 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 NET_TEST_TCP_SOCKET_PROXY_H_ +#define NET_TEST_TCP_SOCKET_PROXY_H_ + +#include <stdint.h> + +#include <memory> + +#include "base/memory/ref_counted.h" +#include "base/threading/thread_checker.h" + +namespace base { +class SingleThreadTaskRunner; +} // namespace base + +namespace net { + +class IPEndPoint; + +// TcpSocketProxy proxies TCP connection from localhost to a remote IP address. +class TcpSocketProxy { + public: + explicit TcpSocketProxy( + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); + ~TcpSocketProxy(); + + // Initializes local socket for the proxy. If |local_port| is not 0 then the + // proxy will listen on that port. Otherwise the socket will be bound to an + // available port and local_port() should be used to get the port number. + // Returns false if initialization fails. + bool Initialize(int local_port = 0); + + // Local port number for the proxy or 0 if the proxy is not initialized. + uint16_t local_port() const { return local_port_; } + + // Starts the proxy for the specified |remote_endpoint|. Must be called after + // a successful Initialize() call and before any incoming connection on + // local_port() are initiated. Port number in |remote_endpoint| may be + // different from local_port(). + void Start(const IPEndPoint& remote_endpoint); + + private: + class Core; + + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + + // Core implements the proxy functionality. It runs on |io_task_runner_|. + std::unique_ptr<Core> core_; + + uint16_t local_port_ = 0; + + THREAD_CHECKER(thread_checker_); + + DISALLOW_COPY_AND_ASSIGN(TcpSocketProxy); +}; + +} // namespace net + +#endif // NET_TEST_TCP_SOCKET_PROXY_H_
diff --git a/net/test/spawned_test_server/remote_test_server_proxy_unittests.cc b/net/test/tcp_socket_proxy_unittest.cc similarity index 84% rename from net/test/spawned_test_server/remote_test_server_proxy_unittests.cc rename to net/test/tcp_socket_proxy_unittest.cc index 7b3b6b5..08cb90d 100644 --- a/net/test/spawned_test_server/remote_test_server_proxy_unittests.cc +++ b/net/test/tcp_socket_proxy_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/test/spawned_test_server/remote_test_server_proxy.h" +#include "net/test/tcp_socket_proxy.h" #include "base/message_loop/message_loop.h" #include "base/threading/thread.h" @@ -18,9 +18,9 @@ namespace net { -class RemoteTestServerProxyTest : public testing::Test { +class TcpSocketProxyTest : public testing::Test { public: - RemoteTestServerProxyTest() : io_thread_("RemoteTestServer IO Thread") { + TcpSocketProxyTest() : io_thread_("TcpSocketProxyTest IO Thread") { EXPECT_TRUE(io_thread_.StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); @@ -35,7 +35,9 @@ result = listen_socket_->GetLocalAddress(&address); EXPECT_THAT(result, IsOk()); - proxy_ = std::make_unique<RemoteTestServerProxy>(io_thread_.task_runner()); + proxy_ = std::make_unique<TcpSocketProxy>(io_thread_.task_runner()); + EXPECT_TRUE(proxy_->Initialize()); + proxy_address_ = IPEndPoint(IPAddress::IPv4Localhost(), proxy_->local_port()); proxy_->Start(address); @@ -94,15 +96,15 @@ protected: base::Thread io_thread_; - // Server socket that simulates testserver that RemoteTestServerProxy normally + // Server socket that simulates testserver that TcpSocketProxy normally // would connect to. std::unique_ptr<TCPServerSocket> listen_socket_; - std::unique_ptr<RemoteTestServerProxy> proxy_; + std::unique_ptr<TcpSocketProxy> proxy_; IPEndPoint proxy_address_; }; -TEST_F(RemoteTestServerProxyTest, SendAndReceive) { +TEST_F(TcpSocketProxyTest, SendAndReceive) { std::unique_ptr<StreamSocket> client_socket; std::unique_ptr<StreamSocket> server_socket; MakeConnection(&client_socket, &server_socket); @@ -110,7 +112,7 @@ SendAndReceiveData(server_socket.get(), client_socket.get()); } -TEST_F(RemoteTestServerProxyTest, TwoConnections) { +TEST_F(TcpSocketProxyTest, TwoConnections) { std::unique_ptr<StreamSocket> client_socket1; std::unique_ptr<StreamSocket> server_socket1; MakeConnection(&client_socket1, &server_socket1); @@ -127,7 +129,7 @@ // Close socket on the server side and verify that it's closed on the client // side. -TEST_F(RemoteTestServerProxyTest, DisconnectServer) { +TEST_F(TcpSocketProxyTest, DisconnectServer) { std::unique_ptr<StreamSocket> client_socket; std::unique_ptr<StreamSocket> server_socket; MakeConnection(&client_socket, &server_socket); @@ -137,7 +139,7 @@ // Close socket on the client side and verify that it's closed on the server // side. -TEST_F(RemoteTestServerProxyTest, DisconnectClient) { +TEST_F(TcpSocketProxyTest, DisconnectClient) { std::unique_ptr<StreamSocket> client_socket; std::unique_ptr<StreamSocket> server_socket; MakeConnection(&client_socket, &server_socket); @@ -145,4 +147,11 @@ ExpectClosed(server_socket.get()); } +// Initialize() must fail if the port is in use. +TEST_F(TcpSocketProxyTest, PortInUse) { + // Try initializing second proxy on the same port. + auto proxy2 = std::make_unique<TcpSocketProxy>(io_thread_.task_runner()); + EXPECT_FALSE(proxy2->Initialize(proxy_->local_port())); +} + } // namespace net
diff --git a/net/tools/quic/chlo_extractor.cc b/net/tools/quic/chlo_extractor.cc index 4d71aa7..d0ac16f 100644 --- a/net/tools/quic/chlo_extractor.cc +++ b/net/tools/quic/chlo_extractor.cc
@@ -20,7 +20,9 @@ class ChloFramerVisitor : public QuicFramerVisitorInterface, public CryptoFramerVisitorInterface { public: - ChloFramerVisitor(QuicFramer* framer, ChloExtractor::Delegate* delegate); + ChloFramerVisitor(QuicFramer* framer, + const QuicTagVector& create_session_tag_indicators, + ChloExtractor::Delegate* delegate); ~ChloFramerVisitor() override = default; @@ -52,19 +54,26 @@ void OnHandshakeMessage(const CryptoHandshakeMessage& message) override; bool found_chlo() { return found_chlo_; } + bool chlo_contains_tags() { return chlo_contains_tags_; } private: QuicFramer* framer_; + const QuicTagVector& create_session_tag_indicators_; ChloExtractor::Delegate* delegate_; bool found_chlo_; + bool chlo_contains_tags_; QuicConnectionId connection_id_; }; -ChloFramerVisitor::ChloFramerVisitor(QuicFramer* framer, - ChloExtractor::Delegate* delegate) +ChloFramerVisitor::ChloFramerVisitor( + QuicFramer* framer, + const QuicTagVector& create_session_tag_indicators, + ChloExtractor::Delegate* delegate) : framer_(framer), + create_session_tag_indicators_(create_session_tag_indicators), delegate_(delegate), found_chlo_(false), + chlo_contains_tags_(false), connection_id_(0) {} bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) { @@ -96,7 +105,25 @@ if (!crypto_framer.ProcessInput(data, Perspective::IS_SERVER)) { return false; } + if (FLAGS_quic_reloadable_flag_quic_inspect_chlo_tags) { + // Interrogate the crypto framer and see if there are any + // intersecting tags between what we saw in the maybe-CHLO and the + // indicator set. + for (const QuicTag tag : create_session_tag_indicators_) { + if (crypto_framer.HasTag(tag)) { + chlo_contains_tags_ = true; + } + } + if (chlo_contains_tags_ && delegate_) { + // Unfortunately, because this is a partial CHLO, + // OnHandshakeMessage was never called, so the ALPN was never + // extracted. Fake it up a bit and send it to the delegate so that + // the correct dispatch can happen. + crypto_framer.ForceHandshake(); + } + } } + return true; } @@ -153,14 +180,15 @@ // static bool ChloExtractor::Extract(const QuicEncryptedPacket& packet, const ParsedQuicVersionVector& versions, + const QuicTagVector& create_session_tag_indicators, Delegate* delegate) { QuicFramer framer(versions, QuicTime::Zero(), Perspective::IS_SERVER); - ChloFramerVisitor visitor(&framer, delegate); + ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate); framer.set_visitor(&visitor); if (!framer.ProcessPacket(packet)) { return false; } - return visitor.found_chlo(); + return visitor.found_chlo() || visitor.chlo_contains_tags(); } } // namespace net
diff --git a/net/tools/quic/chlo_extractor.h b/net/tools/quic/chlo_extractor.h index b56df49..dd0fe90 100644 --- a/net/tools/quic/chlo_extractor.h +++ b/net/tools/quic/chlo_extractor.h
@@ -24,11 +24,15 @@ const CryptoHandshakeMessage& chlo) = 0; }; - // Extracts a CHLO message from |packet| and invokes the OnChlo method - // of |delegate|. Return true if a CHLO message was found, and false - // otherwise. + // Extracts a CHLO message from |packet| and invokes the OnChlo + // method of |delegate|. Return true if a CHLO message was found, + // and false otherwise. If non-empty, + // |create_session_tag_indicators| contains a list of QUIC tags that + // if found will result in the session being created early, to + // enable support for multi-packet CHLOs. static bool Extract(const QuicEncryptedPacket& packet, const ParsedQuicVersionVector& versions, + const QuicTagVector& create_session_tag_indicators, Delegate* delegate); ChloExtractor(const ChloExtractor&) = delete;
diff --git a/net/tools/quic/chlo_extractor_test.cc b/net/tools/quic/chlo_extractor_test.cc index 1692887..b12e6ed 100644 --- a/net/tools/quic/chlo_extractor_test.cc +++ b/net/tools/quic/chlo_extractor_test.cc
@@ -90,7 +90,7 @@ header_.version = version; MakePacket( new QuicStreamFrame(kCryptoStreamId, false, 0, client_hello_str)); - EXPECT_TRUE(ChloExtractor::Extract(*packet_, versions, &delegate_)) + EXPECT_TRUE(ChloExtractor::Extract(*packet_, versions, {}, &delegate_)) << ParsedQuicVersionToString(version); EXPECT_EQ(version.transport_version, delegate_.transport_version()); EXPECT_EQ(header_.connection_id, delegate_.connection_id()); @@ -110,7 +110,7 @@ MakePacket( new QuicStreamFrame(kCryptoStreamId + 1, false, 0, client_hello_str)); EXPECT_FALSE( - ChloExtractor::Extract(*packet_, AllSupportedVersions(), &delegate_)); + ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_)); } TEST_F(ChloExtractorTest, DoesNotFindValidChloOnWrongOffset) { @@ -122,13 +122,13 @@ .as_string()); MakePacket(new QuicStreamFrame(kCryptoStreamId, false, 1, client_hello_str)); EXPECT_FALSE( - ChloExtractor::Extract(*packet_, AllSupportedVersions(), &delegate_)); + ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_)); } TEST_F(ChloExtractorTest, DoesNotFindInvalidChlo) { MakePacket(new QuicStreamFrame(kCryptoStreamId, false, 0, "foo")); EXPECT_FALSE( - ChloExtractor::Extract(*packet_, AllSupportedVersions(), &delegate_)); + ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_)); } } // namespace
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 053e63f6..d6863c5 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -143,7 +143,7 @@ // with future versions of QUIC, so don't remove it. ParsedQuicVersionVector version_buckets[1]; - for (const ParsedQuicVersion version : all_supported_versions) { + for (const ParsedQuicVersion& version : all_supported_versions) { // Versions: 35+ // QUIC_VERSION_35 allows endpoints to independently set stream limit. version_buckets[0].push_back(version); @@ -570,6 +570,23 @@ *client_->client()->client_session(), n); } + void WaitForDelayedAcks() { + // kWaitDuration is a period of time that is long enough for all delayed + // acks to be sent and received on the other end. + const QuicTime::Delta kWaitDuration = + 4 * QuicTime::Delta::FromMilliseconds(kMaxDelayedAckTimeMs); + + const QuicClock* clock = + client_->client()->client_session()->connection()->clock(); + + QuicTime wait_until = clock->ApproximateNow() + kWaitDuration; + while (clock->ApproximateNow() < wait_until) { + QUIC_LOG_EVERY_N_SEC(INFO, 0.01) << "Waiting for delayed acks..."; + // This waits for up to 50 ms. + client_->client()->WaitForEvents(); + } + } + bool initialized_; QuicSocketAddress server_address_; string server_hostname_; @@ -1853,24 +1870,24 @@ // called exactly once on destruction. class TestAckListener : public QuicAckListenerInterface { public: - explicit TestAckListener(int num_packets) : num_notifications_(num_packets) {} + explicit TestAckListener(int bytes_to_ack) : bytes_to_ack_(bytes_to_ack) {} - void OnPacketAcked(int /*acked_bytes*/, + void OnPacketAcked(int acked_bytes, QuicTime::Delta /*delta_largest_observed*/) override { - ASSERT_LT(0, num_notifications_); - num_notifications_--; + ASSERT_LE(acked_bytes, bytes_to_ack_); + bytes_to_ack_ -= acked_bytes; } void OnPacketRetransmitted(int /*retransmitted_bytes*/) override {} - bool has_been_notified() const { return num_notifications_ == 0; } + bool has_been_notified() const { return bytes_to_ack_ == 0; } protected: // Object is ref counted. - ~TestAckListener() override { EXPECT_EQ(0, num_notifications_); } + ~TestAckListener() override { EXPECT_EQ(0, bytes_to_ack_); } private: - int num_notifications_; + int bytes_to_ack_; }; class TestResponseListener : public QuicSpdyClientBase::ResponseListener { @@ -1910,15 +1927,15 @@ client_->SendMessage(headers, "", /*fin=*/false); - // The TestAckListener will cause a failure if not notified. - QuicReferenceCountedPointer<TestAckListener> ack_listener( - new TestAckListener(2)); - // Test the AckNotifier's ability to track multiple packets by making the // request body exceed the size of a single packet. string request_string = "a request body bigger than one packet" + string(kMaxPacketSize, '.'); + // The TestAckListener will cause a failure if not notified. + QuicReferenceCountedPointer<TestAckListener> ack_listener( + new TestAckListener(request_string.length())); + // Send the request, and register the delegate for ACKs. client_->SendData(request_string, true, ack_listener); client_->WaitForResponse(); @@ -2981,6 +2998,27 @@ client->SendCustomSynchronousRequest(headers, body); } +// Regression test for b/71711996. This test sends a connectivity probing packet +// as its last sent packet, and makes sure the server's ACK of that packet does +// not cause the client to fail. +TEST_P(EndToEndTest, LastPacketSentIsConnectivityProbing) { + ASSERT_TRUE(Initialize()); + + EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); + EXPECT_EQ("200", client_->response_headers()->find(":status")->second); + + // Wait for the client's ACK (of the response) to be received by the server. + WaitForDelayedAcks(); + + // We are sending a connectivity probing packet from an unchanged client + // address, so the server will not respond to us with a connectivity probing + // packet, however the server should send an ack-only packet to us. + client_->SendConnectivityProbing(); + + // Wait for the server's last ACK to be received by the client. + WaitForDelayedAcks(); +} + class EndToEndBufferedPacketsTest : public EndToEndTest { public: void CreateClientWithWriter() override {
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index a5214d5..0eb953fa 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc
@@ -208,7 +208,8 @@ : helper_(helper), self_address_(self_address), rejector_(rejector), - can_accept_(false) {} + can_accept_(false), + error_details_("CHLO not processed") {} // ChloExtractor::Delegate implementation. void OnChlo(QuicTransportVersion version, @@ -907,6 +908,7 @@ ChloAlpnExtractor alpn_extractor; if (FLAGS_quic_allow_chlo_buffering && !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), + config_.create_session_tag_indicators(), &alpn_extractor)) { // Buffer non-CHLO packets. ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id); @@ -925,6 +927,7 @@ ChloValidator validator(session_helper_.get(), current_server_address_, rejector.get()); if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), + config_.create_session_tag_indicators(), &validator)) { ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id); return;
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc index ae7b377..cb565a13 100644 --- a/net/tools/quic/quic_dispatcher_test.cc +++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -262,7 +262,7 @@ std::unique_ptr<QuicReceivedPacket> received_packet( ConstructReceivedPacket(*packet, helper_.GetClock()->Now())); - if (ChloExtractor::Extract(*packet, versions, nullptr)) { + if (ChloExtractor::Extract(*packet, versions, {}, nullptr)) { // Add CHLO packet to the beginning to be verified first, because it is // also processed first by new session. data_connection_map_[connection_id].push_front(
diff --git a/net/tools/quic/quic_server_bin.cc b/net/tools/quic/quic_server_bin.cc index 3d18dedd4..2bb71ba 100644 --- a/net/tools/quic/quic_server_bin.cc +++ b/net/tools/quic/quic_server_bin.cc
@@ -95,7 +95,7 @@ return 1; } - while (1) { + while (true) { server.WaitForEvents(); } }
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index 73d3be6..0ceca2d3 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -461,6 +461,12 @@ return SendCustomSynchronousRequest(headers, ""); } +void QuicTestClient::SendConnectivityProbing() { + QuicConnection* connection = client()->client_session()->connection(); + connection->SendConnectivityProbingPacket(connection->writer(), + connection->peer_address()); +} + void QuicTestClient::SetLatestCreatedStream(QuicSpdyClientStream* stream) { latest_created_stream_ = stream; if (latest_created_stream_ != nullptr) {
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h index 3302b52..6d7bfe2 100644 --- a/net/tools/quic/test_tools/quic_test_client.h +++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -127,6 +127,7 @@ // Sends a GET request for |uri|, waits for the response, and returns the // response body. std::string SendSynchronousRequest(const std::string& uri); + void SendConnectivityProbing(); void Connect(); void ResetConnection(); void Disconnect();
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 01afe00..a0a04b6 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -144,6 +144,7 @@ #endif #if BUILDFLAG(ENABLE_REPORTING) +#include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_service.h" #include "net/url_request/network_error_logging_delegate.h" #endif // BUILDFLAG(ENABLE_REPORTING) @@ -7048,6 +7049,12 @@ return true; } + const ReportingPolicy& GetPolicy() const override { + static ReportingPolicy dummy_policy_; + NOTIMPLEMENTED(); + return dummy_policy_; + } + private: std::vector<Header> headers_; };
diff --git a/sandbox/win/src/restricted_token_unittest.cc b/sandbox/win/src/restricted_token_unittest.cc index fad38cc..6c674d5 100644 --- a/sandbox/win/src/restricted_token_unittest.cc +++ b/sandbox/win/src/restricted_token_unittest.cc
@@ -128,6 +128,39 @@ EXPECT_TRUE(::EqualSid(capabilities->Groups[index].Sid, security_capabilities->Capabilities[index].Sid)); } + + DWORD length_needed = 0; + ::GetKernelObjectSecurity(token.Get(), DACL_SECURITY_INFORMATION, nullptr, 0, + &length_needed); + ASSERT_EQ(::GetLastError(), DWORD{ERROR_INSUFFICIENT_BUFFER}); + + std::vector<char> security_desc_buffer(length_needed); + SECURITY_DESCRIPTOR* security_desc = + reinterpret_cast<SECURITY_DESCRIPTOR*>(security_desc_buffer.data()); + + ASSERT_TRUE(::GetKernelObjectSecurity(token.Get(), DACL_SECURITY_INFORMATION, + security_desc, length_needed, + &length_needed)); + + ATL::CSecurityDesc token_sd(*security_desc); + ATL::CSid check_sid( + static_cast<SID*>(security_capabilities->AppContainerSid)); + bool package_sid_found = false; + + ATL::CDacl dacl; + ASSERT_TRUE(token_sd.GetDacl(&dacl)); + unsigned int ace_count = dacl.GetAceCount(); + for (unsigned int i = 0; i < ace_count; ++i) { + ATL::CSid sid; + ACCESS_MASK mask = 0; + BYTE type = 0; + dacl.GetAclEntry(i, &sid, &mask, &type); + if (sid == check_sid && mask == TOKEN_ALL_ACCESS && + type == ACCESS_ALLOWED_ACE_TYPE) { + package_sid_found = true; + } + } + ASSERT_TRUE(package_sid_found); } // Checks if a sid is in the restricting list of the restricted token.
diff --git a/sandbox/win/src/restricted_token_utils.cc b/sandbox/win/src/restricted_token_utils.cc index 104ae07..2653090 100644 --- a/sandbox/win/src/restricted_token_utils.cc +++ b/sandbox/win/src/restricted_token_utils.cc
@@ -23,6 +23,34 @@ namespace sandbox { +namespace { + +DWORD GetObjectSecurityDescriptor(HANDLE handle, + SECURITY_INFORMATION security_info, + std::vector<char>* security_desc_buffer, + PSECURITY_DESCRIPTOR* security_desc) { + DWORD last_error = 0; + DWORD length_needed = 0; + + ::GetKernelObjectSecurity(handle, security_info, nullptr, 0, &length_needed); + last_error = ::GetLastError(); + if (last_error != ERROR_INSUFFICIENT_BUFFER) + return last_error; + + security_desc_buffer->resize(length_needed); + *security_desc = + reinterpret_cast<PSECURITY_DESCRIPTOR>(security_desc_buffer->data()); + + if (!::GetKernelObjectSecurity(handle, security_info, *security_desc, + length_needed, &length_needed)) { + return ::GetLastError(); + } + + return ERROR_SUCCESS; +} + +} // namespace + DWORD CreateRestrictedToken(TokenLevel security_level, IntegrityLevel integrity_level, TokenType token_type, @@ -243,31 +271,21 @@ } DWORD HardenTokenIntegrityLevelPolicy(HANDLE token) { - DWORD last_error = 0; - DWORD length_needed = 0; - - ::GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, nullptr, 0, - &length_needed); - - last_error = ::GetLastError(); - if (last_error != ERROR_INSUFFICIENT_BUFFER) + std::vector<char> security_desc_buffer; + PSECURITY_DESCRIPTOR security_desc = nullptr; + DWORD last_error = GetObjectSecurityDescriptor( + token, LABEL_SECURITY_INFORMATION, &security_desc_buffer, &security_desc); + if (last_error != ERROR_SUCCESS) return last_error; - std::vector<char> security_desc_buffer(length_needed); - PSECURITY_DESCRIPTOR security_desc = - reinterpret_cast<PSECURITY_DESCRIPTOR>(&security_desc_buffer[0]); - - if (!::GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, - security_desc, length_needed, &length_needed)) - return ::GetLastError(); - PACL sacl = nullptr; BOOL sacl_present = false; BOOL sacl_defaulted = false; if (!::GetSecurityDescriptorSacl(security_desc, &sacl_present, &sacl, - &sacl_defaulted)) + &sacl_defaulted)) { return ::GetLastError(); + } for (DWORD ace_index = 0; ace_index < sacl->AceCount; ++ace_index) { PSYSTEM_MANDATORY_LABEL_ACE ace; @@ -343,7 +361,7 @@ // Default from NtCreateLowBoxToken is a Primary token. if (token_type == PRIMARY) { - token->Set(token_lowbox_handle.Take()); + *token = std::move(token_lowbox_handle); return ERROR_SUCCESS; } @@ -354,7 +372,23 @@ return ::GetLastError(); } - token->Set(dup_handle); + // Copy security descriptor from primary token as the new object will have + // the DACL from the current token's default DACL. + base::win::ScopedHandle token_for_sd(dup_handle); + std::vector<char> security_desc_buffer; + PSECURITY_DESCRIPTOR security_desc = nullptr; + DWORD last_error = GetObjectSecurityDescriptor( + token_lowbox_handle.Get(), DACL_SECURITY_INFORMATION, + &security_desc_buffer, &security_desc); + if (last_error != ERROR_SUCCESS) + return last_error; + + if (!::SetKernelObjectSecurity(token_for_sd.Get(), DACL_SECURITY_INFORMATION, + security_desc)) { + return ::GetLastError(); + } + + *token = std::move(token_for_sd); return ERROR_SUCCESS; }
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn index 3399f7f6..7ccd21c 100644 --- a/services/network/public/cpp/BUILD.gn +++ b/services/network/public/cpp/BUILD.gn
@@ -14,6 +14,8 @@ "mutable_partial_network_traffic_annotation_tag_struct_traits.h", "net_adapters.cc", "net_adapters.h", + "network_features.cc", + "network_features.h", "network_switches.cc", "network_switches.h", "proxy_resolving_client_socket.cc",
diff --git a/services/network/public/cpp/data_element.cc b/services/network/public/cpp/data_element.cc index cdec1cf..f8dd18fe 100644 --- a/services/network/public/cpp/data_element.cc +++ b/services/network/public/cpp/data_element.cc
@@ -13,6 +13,8 @@ namespace network { +const uint64_t DataElement::kUnknownSize; + DataElement::DataElement() : type_(TYPE_UNKNOWN), bytes_(NULL),
diff --git a/services/network/public/cpp/network_features.cc b/services/network/public/cpp/network_features.cc new file mode 100644 index 0000000..ad31b70 --- /dev/null +++ b/services/network/public/cpp/network_features.cc
@@ -0,0 +1,13 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/public/cpp/network_features.h" + +namespace features { + +const base::Feature kReporting{"Reporting", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kNetworkErrorLogging{"NetworkErrorLogging", + base::FEATURE_DISABLED_BY_DEFAULT}; + +} // namespace features
diff --git a/services/network/public/cpp/network_features.h b/services/network/public/cpp/network_features.h new file mode 100644 index 0000000..9c818f1 --- /dev/null +++ b/services/network/public/cpp/network_features.h
@@ -0,0 +1,17 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_NETWORK_PUBLIC_CPP_NETWORK_FEATURES_ +#define SERVICES_NETWORK_PUBLIC_CPP_NETWORK_FEATURES_ + +#include "base/feature_list.h" + +namespace features { + +extern const base::Feature kReporting; +extern const base::Feature kNetworkErrorLogging; + +} // namespace features + +#endif // SERVICES_NETWORK_PUBLIC_CPP_NETWORK_FEATURES_
diff --git a/services/network/public/cpp/proxy_config_traits.cc b/services/network/public/cpp/proxy_config_traits.cc index ad58ca5b..1ab515e 100644 --- a/services/network/public/cpp/proxy_config_traits.cc +++ b/services/network/public/cpp/proxy_config_traits.cc
@@ -63,14 +63,14 @@ EnumTraits<network::mojom::ProxyRulesType, net::ProxyConfig::ProxyRules::Type>:: ToMojom(net::ProxyConfig::ProxyRules::Type net_proxy_rules_type) { switch (net_proxy_rules_type) { - case net::ProxyConfig::ProxyRules::TYPE_NO_RULES: - return network::mojom::ProxyRulesType::TYPE_NO_RULES; - case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY: - return network::mojom::ProxyRulesType::TYPE_SINGLE_PROXY; - case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME: - return network::mojom::ProxyRulesType::TYPE_PROXY_PER_SCHEME; + case net::ProxyConfig::ProxyRules::Type::EMPTY: + return network::mojom::ProxyRulesType::EMPTY; + case net::ProxyConfig::ProxyRules::Type::PROXY_LIST: + return network::mojom::ProxyRulesType::PROXY_LIST; + case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME: + return network::mojom::ProxyRulesType::PROXY_LIST_PER_SCHEME; } - return network::mojom::ProxyRulesType::TYPE_NO_RULES; + return network::mojom::ProxyRulesType::EMPTY; } bool EnumTraits<network::mojom::ProxyRulesType, @@ -78,14 +78,14 @@ FromMojom(network::mojom::ProxyRulesType mojo_proxy_rules_type, net::ProxyConfig::ProxyRules::Type* out) { switch (mojo_proxy_rules_type) { - case network::mojom::ProxyRulesType::TYPE_NO_RULES: - *out = net::ProxyConfig::ProxyRules::TYPE_NO_RULES; + case network::mojom::ProxyRulesType::EMPTY: + *out = net::ProxyConfig::ProxyRules::Type::EMPTY; return true; - case network::mojom::ProxyRulesType::TYPE_SINGLE_PROXY: - *out = net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + case network::mojom::ProxyRulesType::PROXY_LIST: + *out = net::ProxyConfig::ProxyRules::Type::PROXY_LIST; return true; - case network::mojom::ProxyRulesType::TYPE_PROXY_PER_SCHEME: - *out = net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + case network::mojom::ProxyRulesType::PROXY_LIST_PER_SCHEME: + *out = net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME; return true; } return false;
diff --git a/services/network/public/interfaces/proxy_config.mojom b/services/network/public/interfaces/proxy_config.mojom index 9cc58ff..17c0628 100644 --- a/services/network/public/interfaces/proxy_config.mojom +++ b/services/network/public/interfaces/proxy_config.mojom
@@ -19,9 +19,9 @@ // This corresponds to net::ProxyConfig::ProxyRules::Type. enum ProxyRulesType { - TYPE_NO_RULES, - TYPE_SINGLE_PROXY, - TYPE_PROXY_PER_SCHEME, + EMPTY, + PROXY_LIST, + PROXY_LIST_PER_SCHEME, }; // These fields mirror those of net::ProxyConfig::ProxyRules.
diff --git a/services/service_manager/sandbox/mac/gpu_v2.sb b/services/service_manager/sandbox/mac/gpu_v2.sb index 7b66e6c..593b49d 100644 --- a/services/service_manager/sandbox/mac/gpu_v2.sb +++ b/services/service_manager/sandbox/mac/gpu_v2.sb
@@ -7,7 +7,6 @@ ; Allow communication between the GPU process and the UI server. (allow mach-lookup (global-name "com.apple.cvmsServ") - (global-name "com.apple.system.notification_center") (global-name "com.apple.tsm.uiserver") (global-name "com.apple.windowserver.active")) @@ -24,9 +23,6 @@ (iokit-user-client-class "IOSurfaceSendRight")) (iokit-user-client-class "RootDomainUserClient") -(allow ipc-posix-shm-read-data - (ipc-posix-name "apple.shm.notification_center")) - ; https://crbug.com/515280 (if (>= os-version 1011) (allow file-read* (subpath "/System/Library/Extensions")))
diff --git a/services/ui/public/cpp/gpu/context_provider_command_buffer.cc b/services/ui/public/cpp/gpu/context_provider_command_buffer.cc index b3f82d1..6cbc49ae 100644 --- a/services/ui/public/cpp/gpu/context_provider_command_buffer.cc +++ b/services/ui/public/cpp/gpu/context_provider_command_buffer.cc
@@ -462,7 +462,8 @@ } base::Lock* ContextProviderCommandBuffer::GetLock() { - DCHECK(support_locking_); + if (!support_locking_) + return nullptr; return &context_lock_; }
diff --git a/services/ui/ws/window_finder.cc b/services/ui/ws/window_finder.cc index b8efd8d..1f99e99 100644 --- a/services/ui/ws/window_finder.cc +++ b/services/ui/ws/window_finder.cc
@@ -6,7 +6,6 @@ #include "base/containers/adapters.h" #include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_delegate.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/point_f.h" @@ -87,6 +86,7 @@ bool FindDeepestVisibleWindowForLocationImpl( ServerWindow* window, + bool is_root_window, EventSource event_source, const gfx::Point& location_in_root, const gfx::Point& location_in_window, @@ -95,7 +95,11 @@ // The non-client area takes precedence over descendants, as otherwise the // user would likely not be able to hit the non-client area as it's common // for descendants to go into the non-client area. - if (IsLocationInNonclientArea(window, location_in_window)) { + // + // Display roots aren't allowed to have non-client areas. This is important + // as roots may have a transform, which causes problem in comparing sizes. + if (!is_root_window && + IsLocationInNonclientArea(window, location_in_window)) { deepest_window->window = window; deepest_window->in_non_client_area = true; return true; @@ -133,9 +137,10 @@ continue; } + const bool child_is_root = false; if (FindDeepestVisibleWindowForLocationImpl( - child, event_source, location_in_root, location_in_child, - child_transform, deepest_window)) { + child, child_is_root, event_source, location_in_root, + location_in_child, child_transform, deepest_window)) { return true; } } @@ -164,9 +169,10 @@ DeepestWindow result; // Allow the root to have a transform, which mirrors what happens with // WindowManagerDisplayRoot. - FindDeepestVisibleWindowForLocationImpl(root_window, event_source, location, - initial_location, root_transform, - &result); + const bool is_root_window = true; + FindDeepestVisibleWindowForLocationImpl( + root_window, is_root_window, event_source, location, initial_location, + root_transform, &result); return result; }
diff --git a/services/ui/ws/window_finder_unittest.cc b/services/ui/ws/window_finder_unittest.cc index 8e87df9..fadedfe 100644 --- a/services/ui/ws/window_finder_unittest.cc +++ b/services/ui/ws/window_finder_unittest.cc
@@ -273,5 +273,47 @@ .window); } +// Creates the following window hierarchy: +// root +// |- c1 (has .5x transform, and is used as the root in +// FindDeepestVisibleWindowForLocation). +// |- c2 +// |- c3 +// With various assertions around hit testing. +TEST_F(WindowFinderTest, + FindDeepestVisibleWindowWithTransformOnParentMagnified) { + TestServerWindowDelegate window_delegate(viz_host_proxy()); + ServerWindow root(&window_delegate, WindowId(1, 2)); + root.set_event_targeting_policy( + mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); + root.SetVisible(true); + root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); + window_delegate.set_root_window(&root); + ServerWindow c1(&window_delegate, WindowId(1, 3)); + root.Add(&c1); + c1.SetVisible(true); + c1.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); + gfx::Transform transform; + transform.Scale(SkFloatToMScalar(.5f), SkFloatToMScalar(.5f)); + c1.SetTransform(transform); + + ServerWindow c2(&window_delegate, WindowId(1, 4)); + c1.Add(&c2); + c2.SetVisible(true); + c2.SetBounds(gfx::Rect(0, 0, 200, 200), base::nullopt); + + ServerWindow c3(&window_delegate, WindowId(1, 5)); + c2.Add(&c3); + c3.SetVisible(true); + c3.SetBounds(gfx::Rect(0, 190, 200, 10), base::nullopt); + + EXPECT_EQ(&c2, FindDeepestVisibleWindowForLocation(&c1, EventSource::MOUSE, + gfx::Point(55, 55)) + .window); + EXPECT_EQ(&c3, FindDeepestVisibleWindowForLocation(&c1, EventSource::MOUSE, + gfx::Point(0, 99)) + .window); +} + } // namespace ws } // namespace ui
diff --git a/services/ui/ws/window_manager_state_unittest.cc b/services/ui/ws/window_manager_state_unittest.cc index bc84563..4e12a05 100644 --- a/services/ui/ws/window_manager_state_unittest.cc +++ b/services/ui/ws/window_manager_state_unittest.cc
@@ -775,6 +775,13 @@ window_server->user_id_tracker()->SetActiveUserId(kUserId1); const int64_t first_display_id = screen_manager.AddDisplay(); const int64_t second_display_id = screen_manager.AddDisplay(); + Display* first_display = + window_server->display_manager()->GetDisplayById(first_display_id); + // As there are no child windows make sure the root is a valid target. + first_display->GetWindowManagerDisplayRootForUser(kUserId1) + ->GetClientVisibleRoot() + ->set_event_targeting_policy( + mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); Display* second_display = window_server->display_manager()->GetDisplayById(second_display_id); ASSERT_TRUE(second_display);
diff --git a/storage/browser/blob/blob_data_builder.cc b/storage/browser/blob/blob_data_builder.cc index 668166a..ce2459e9 100644 --- a/storage/browser/blob/blob_data_builder.cc +++ b/storage/browser/blob/blob_data_builder.cc
@@ -11,12 +11,16 @@ #include <utility> #include "base/files/file.h" +#include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/time/time.h" #include "net/disk_cache/disk_cache.h" +#include "storage/browser/blob/blob_entry.h" +#include "storage/browser/blob/blob_storage_registry.h" +#include "storage/browser/blob/shareable_blob_data_item.h" using base::FilePath; @@ -128,14 +132,12 @@ } BlobDataBuilder::BlobDataBuilder(const std::string& uuid) : uuid_(uuid) {} - -BlobDataBuilder::BlobDataBuilder(BlobDataBuilder&&) = default; -BlobDataBuilder& BlobDataBuilder::operator=(BlobDataBuilder&&) = default; BlobDataBuilder::~BlobDataBuilder() = default; void BlobDataBuilder::AppendIPCDataElement( const network::DataElement& ipc_data, - const scoped_refptr<FileSystemContext>& file_system_context) { + const scoped_refptr<FileSystemContext>& file_system_context, + const BlobStorageRegistry& blob_registry) { uint64_t length = ipc_data.length(); switch (ipc_data.type()) { case network::DataElement::TYPE_BYTES: @@ -153,9 +155,10 @@ file_system_context); break; case network::DataElement::TYPE_BLOB: - // This is a temporary item that will be deconstructed later in - // BlobStorageContext. - AppendBlob(ipc_data.blob_uuid(), ipc_data.offset(), ipc_data.length()); + // This will be deconstructed immediately into the items the blob is made + // up of. + AppendBlob(ipc_data.blob_uuid(), ipc_data.offset(), ipc_data.length(), + blob_registry); break; case network::DataElement::TYPE_RAW_FILE: case network::DataElement::TYPE_BYTES_DESCRIPTION: @@ -173,15 +176,40 @@ return; std::unique_ptr<network::DataElement> element(new network::DataElement()); element->SetToBytes(data, length); - items_.push_back(new BlobDataItem(std::move(element))); + scoped_refptr<BlobDataItem> item = new BlobDataItem(std::move(element)); + + auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>( + std::move(item), ShareableBlobDataItem::QUOTA_NEEDED); + // Even though we already prepopulate this data, we treat it as needing + // transport anyway since we do need to allocate memory quota. + pending_transport_items_.push_back(shareable_item); + items_.push_back(std::move(shareable_item)); + + total_size_ += length; + total_memory_size_ += length; + transport_quota_needed_ += length; + found_memory_transport_ = true; + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.Bytes", length / 1024); } BlobDataBuilder::FutureData BlobDataBuilder::AppendFutureData(size_t length) { CHECK_NE(length, 0u); std::unique_ptr<network::DataElement> element(new network::DataElement()); element->SetToBytesDescription(length); - items_.push_back(new BlobDataItem(std::move(element))); - return FutureData(items_.back()); + scoped_refptr<BlobDataItem> item = new BlobDataItem(std::move(element)); + + auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>( + item, ShareableBlobDataItem::QUOTA_NEEDED); + pending_transport_items_.push_back(shareable_item); + items_.push_back(std::move(shareable_item)); + + total_size_ += length; + total_memory_size_ += length; + transport_quota_needed_ += length; + found_memory_transport_ = true; + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.Bytes", length / 1024); + + return FutureData(std::move(item)); } BlobDataBuilder::FutureFile BlobDataBuilder::AppendFutureFile( @@ -189,11 +217,24 @@ uint64_t length, uint64_t file_id) { CHECK_NE(length, 0ull); + DCHECK_NE(length, network::DataElement::kUnknownSize); std::unique_ptr<network::DataElement> element(new network::DataElement()); element->SetToFilePathRange(GetFutureFileItemPath(file_id), offset, length, base::Time()); - items_.push_back(new BlobDataItem(std::move(element))); - return FutureFile(items_.back()); + scoped_refptr<BlobDataItem> item = new BlobDataItem(std::move(element)); + + auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>( + item, ShareableBlobDataItem::QUOTA_NEEDED); + pending_transport_items_.push_back(shareable_item); + items_.push_back(std::move(shareable_item)); + + total_size_ += length; + transport_quota_needed_ += length; + found_file_transport_ = true; + UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.File.Unknown", false); + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.File", length / 1024); + + return FutureFile(std::move(item)); } void BlobDataBuilder::AppendFile(const FilePath& file_path, @@ -204,23 +245,205 @@ element->SetToFilePathRange(file_path, offset, length, expected_modification_time); DCHECK(!IsFutureFileItem(*element)) << file_path.value(); - items_.push_back(new BlobDataItem(std::move(element), - ShareableFileReference::Get(file_path))); + scoped_refptr<BlobDataItem> item = new BlobDataItem( + std::move(element), ShareableFileReference::Get(file_path)); + + auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>( + std::move(item), ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA); + items_.push_back(std::move(shareable_item)); + + total_size_ += length; + bool unknown_size = length == network::DataElement::kUnknownSize; + UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.File.Unknown", unknown_size); + if (!unknown_size) + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.File", length / 1024); } void BlobDataBuilder::AppendBlob(const std::string& uuid, uint64_t offset, - uint64_t length) { + uint64_t length, + const BlobStorageRegistry& blob_registry) { DCHECK_GT(length, 0ul); std::unique_ptr<network::DataElement> element(new network::DataElement()); element->SetToBlobRange(uuid, offset, length); - items_.push_back(new BlobDataItem(std::move(element))); + + const BlobEntry* ref_entry = blob_registry.GetEntry(uuid); + + // Self-references or non-existing blob references are invalid. + if (!ref_entry || uuid == uuid_) { + has_blob_errors_ = true; + return; + } + + dependent_blob_uuids_.insert(uuid); + + if (BlobStatusIsError(ref_entry->status())) { + has_blob_errors_ = true; + return; + } + + // We can't reference a blob with unknown size. + if (ref_entry->total_size() == network::DataElement::kUnknownSize) { + has_blob_errors_ = true; + return; + } + + if (length == network::DataElement::kUnknownSize) + length = ref_entry->total_size() - offset; + + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.Blob", length / 1024); + + total_size_ += length; + + // If we're referencing the whole blob, then we don't need to slice. + if (offset == 0 && length == ref_entry->total_size()) { + for (const auto& shareable_item : ref_entry->items()) { + if (shareable_item->item()->type() == network::DataElement::TYPE_BYTES || + shareable_item->item()->type() == + network::DataElement::TYPE_BYTES_DESCRIPTION) { + total_memory_size_ += shareable_item->item()->length(); + } + items_.push_back(shareable_item); + } + return; + } + + // Validate our reference has good offset & length. + uint64_t end_byte; + if (!base::CheckAdd(offset, length).AssignIfValid(&end_byte) || + end_byte > ref_entry->total_size()) { + has_blob_errors_ = true; + return; + } + + SliceBlob(ref_entry, offset, length); } -void BlobDataBuilder::AppendBlob(const std::string& uuid) { - std::unique_ptr<network::DataElement> element(new network::DataElement()); - element->SetToBlob(uuid); - items_.push_back(new BlobDataItem(std::move(element))); +void BlobDataBuilder::SliceBlob(const BlobEntry* source, + uint64_t slice_offset, + uint64_t slice_size) { + const auto& source_items = source->items(); + const auto& offsets = source->offsets(); + DCHECK_LE(slice_offset + slice_size, source->total_size()); + size_t item_index = + std::upper_bound(offsets.begin(), offsets.end(), slice_offset) - + offsets.begin(); + uint64_t item_offset = + item_index == 0 ? slice_offset : slice_offset - offsets[item_index - 1]; + size_t num_items = source_items.size(); + + // Read starting from 'first_item_index' and 'item_offset'. + for (uint64_t total_sliced = 0; + item_index < num_items && total_sliced < slice_size; item_index++) { + const scoped_refptr<BlobDataItem>& source_item = + source_items[item_index]->item(); + uint64_t source_length = source_item->length(); + network::DataElement::Type type = source_item->type(); + DCHECK_NE(source_length, std::numeric_limits<uint64_t>::max()); + DCHECK_NE(source_length, 0ull); + + uint64_t read_size = + std::min(source_length - item_offset, slice_size - total_sliced); + total_sliced += read_size; + + bool reusing_blob_item = (read_size == source_length); + UMA_HISTOGRAM_BOOLEAN("Storage.Blob.ReusedItem", reusing_blob_item); + if (reusing_blob_item) { + // We can share the entire item. + items_.push_back(source_items[item_index]); + if (type == network::DataElement::TYPE_BYTES || + type == network::DataElement::TYPE_BYTES_DESCRIPTION) { + total_memory_size_ += source_length; + } + continue; + } + + bool need_copy = false; + scoped_refptr<BlobDataItem> data_item; + ShareableBlobDataItem::State state = + ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA; + switch (type) { + case network::DataElement::TYPE_BYTES_DESCRIPTION: + case network::DataElement::TYPE_BYTES: { + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.Bytes", + read_size / 1024); + need_copy = true; + copy_quota_needed_ += read_size; + total_memory_size_ += read_size; + // Since we don't have quota yet for memory, we create temporary items + // for this data. When our blob is finished constructing, all dependent + // blobs are done, and we have enough memory quota, we'll copy the data + // over. + std::unique_ptr<network::DataElement> element( + new network::DataElement()); + element->SetToBytesDescription(base::checked_cast<size_t>(read_size)); + data_item = new BlobDataItem(std::move(element)); + state = ShareableBlobDataItem::QUOTA_NEEDED; + break; + } + case network::DataElement::TYPE_FILE: { + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.File", + read_size / 1024); + std::unique_ptr<network::DataElement> element( + new network::DataElement()); + element->SetToFilePathRange( + source_item->path(), source_item->offset() + item_offset, read_size, + source_item->expected_modification_time()); + data_item = + new BlobDataItem(std::move(element), source_item->data_handle_); + + if (BlobDataBuilder::IsFutureFileItem(source_item->data_element())) { + // The source file isn't a real file yet (path is fake), so store the + // items we need to copy from later. + need_copy = true; + } + break; + } + case network::DataElement::TYPE_FILE_FILESYSTEM: { + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.FileSystem", + read_size / 1024); + std::unique_ptr<network::DataElement> element( + new network::DataElement()); + element->SetToFileSystemUrlRange( + source_item->filesystem_url(), source_item->offset() + item_offset, + read_size, source_item->expected_modification_time()); + data_item = new BlobDataItem(std::move(element), + source_item->file_system_context()); + break; + } + case network::DataElement::TYPE_DISK_CACHE_ENTRY: { + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.CacheEntry", + read_size / 1024); + std::unique_ptr<network::DataElement> element( + new network::DataElement()); + element->SetToDiskCacheEntryRange(source_item->offset() + item_offset, + read_size); + data_item = + new BlobDataItem(std::move(element), source_item->data_handle_, + source_item->disk_cache_entry(), + source_item->disk_cache_stream_index(), + source_item->disk_cache_side_stream_index()); + break; + } + case network::DataElement::TYPE_RAW_FILE: + case network::DataElement::TYPE_BLOB: + case network::DataElement::TYPE_DATA_PIPE: + case network::DataElement::TYPE_UNKNOWN: + CHECK(false) << "Illegal blob item type: " << type; + } + + items_.push_back(new ShareableBlobDataItem(std::move(data_item), state)); + if (need_copy) { + copies_.push_back( + ItemCopyEntry(source_items[item_index], item_offset, items_.back())); + } + item_offset = 0; + } +} + +void BlobDataBuilder::AppendBlob(const std::string& uuid, + const BlobStorageRegistry& blob_registry) { + AppendBlob(uuid, 0, network::DataElement::kUnknownSize, blob_registry); } void BlobDataBuilder::AppendFileSystemFile( @@ -233,20 +456,28 @@ std::unique_ptr<network::DataElement> element(new network::DataElement()); element->SetToFileSystemUrlRange(url, offset, length, expected_modification_time); - items_.push_back( - new BlobDataItem(std::move(element), std::move(file_system_context))); + scoped_refptr<BlobDataItem> item = + new BlobDataItem(std::move(element), std::move(file_system_context)); + + auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>( + std::move(item), ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA); + items_.push_back(std::move(shareable_item)); + + total_size_ += length; + bool unknown_size = length == network::DataElement::kUnknownSize; + UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.FileSystem.Unknown", + unknown_size); + if (!unknown_size) + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.FileSystem", length / 1024); } void BlobDataBuilder::AppendDiskCacheEntry( const scoped_refptr<DataHandle>& data_handle, disk_cache::Entry* disk_cache_entry, int disk_cache_stream_index) { - std::unique_ptr<network::DataElement> element(new network::DataElement()); - element->SetToDiskCacheEntryRange( - 0U, disk_cache_entry->GetDataSize(disk_cache_stream_index)); - items_.push_back(new BlobDataItem(std::move(element), data_handle, - disk_cache_entry, disk_cache_stream_index, - kInvalidDiskCacheSideStreamIndex)); + AppendDiskCacheEntryWithSideData(data_handle, disk_cache_entry, + disk_cache_stream_index, + kInvalidDiskCacheSideStreamIndex); } void BlobDataBuilder::AppendDiskCacheEntryWithSideData( @@ -257,16 +488,25 @@ std::unique_ptr<network::DataElement> element(new network::DataElement()); element->SetToDiskCacheEntryRange( 0U, disk_cache_entry->GetDataSize(disk_cache_stream_index)); - items_.push_back(new BlobDataItem(std::move(element), data_handle, - disk_cache_entry, disk_cache_stream_index, - disk_cache_side_stream_index)); + scoped_refptr<BlobDataItem> item = + new BlobDataItem(std::move(element), data_handle, disk_cache_entry, + disk_cache_stream_index, disk_cache_side_stream_index); + + total_size_ += item->length(); + UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.CacheEntry", + item->length() / 1024); + + auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>( + std::move(item), ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA); + items_.push_back(std::move(shareable_item)); } -void BlobDataBuilder::Clear() { - items_.clear(); - content_disposition_.clear(); - content_type_.clear(); - uuid_.clear(); +std::unique_ptr<BlobDataSnapshot> BlobDataBuilder::CreateSnapshot() const { + std::vector<scoped_refptr<BlobDataItem>> items; + for (const auto& item : items_) + items.push_back(item->item()); + return base::WrapUnique(new BlobDataSnapshot( + uuid_, content_type_, content_disposition_, std::move(items))); } void PrintTo(const BlobDataBuilder& x, std::ostream* os) { @@ -275,7 +515,7 @@ << ", content_type: " << x.content_type_ << ", content_disposition: " << x.content_disposition_ << ", items: ["; for (const auto& item : x.items_) { - PrintTo(*item, os); + PrintTo(*item->item(), os); *os << ", "; } *os << "]}";
diff --git a/storage/browser/blob/blob_data_builder.h b/storage/browser/blob/blob_data_builder.h index 60e2bf1..e16db19 100644 --- a/storage/browser/blob/blob_data_builder.h +++ b/storage/browser/blob/blob_data_builder.h
@@ -14,8 +14,11 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/numerics/checked_math.h" #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_data_snapshot.h" +#include "storage/browser/blob/blob_entry.h" +#include "storage/browser/blob/shareable_blob_data_item.h" #include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/storage_browser_export.h" @@ -25,8 +28,9 @@ } namespace storage { +class BlobSliceTest; class BlobStorageContext; -class ShareableFileReference; +class BlobStorageRegistry; // This class is used to build blobs. It also facilitates the operation of // 'pending' data, where the user knows the size and existence of a file or @@ -36,6 +40,8 @@ class STORAGE_EXPORT BlobDataBuilder { public: using DataHandle = BlobDataItem::DataHandle; + using ItemCopyEntry = BlobEntry::ItemCopyEntry; + // Visible for testing. static base::FilePath GetFutureFileItemPath(uint64_t file_id); @@ -45,8 +51,6 @@ static uint64_t GetFutureFileID(const network::DataElement& element); explicit BlobDataBuilder(const std::string& uuid); - BlobDataBuilder(BlobDataBuilder&&); - BlobDataBuilder& operator=(BlobDataBuilder&&); ~BlobDataBuilder(); const std::string& uuid() const { return uuid_; } @@ -57,9 +61,11 @@ // given to this method. // |file_system_context| needs to be set if data element is of type // FILE_FILESYSTEM. + // |blob_registry| is needed for data elements of type BLOB. void AppendIPCDataElement( const network::DataElement& ipc_data, - const scoped_refptr<FileSystemContext>& file_system_context); + const scoped_refptr<FileSystemContext>& file_system_context, + const BlobStorageRegistry& blob_registry); // Copies the given data into the blob. void AppendData(const std::string& data) { @@ -145,9 +151,12 @@ uint64_t length, const base::Time& expected_modification_time); - void AppendBlob(const std::string& uuid, uint64_t offset, uint64_t length); - - void AppendBlob(const std::string& uuid); + void AppendBlob(const std::string& uuid, + uint64_t offset, + uint64_t length, + const BlobStorageRegistry& blob_registry); + void AppendBlob(const std::string& uuid, + const BlobStorageRegistry& blob_registry); void AppendFileSystemFile( const GURL& url, @@ -175,56 +184,97 @@ content_disposition_ = content_disposition; } - void Clear(); + std::unique_ptr<BlobDataSnapshot> CreateSnapshot() const; + + const std::vector<scoped_refptr<ShareableBlobDataItem>>& items() const { + return items_; + } + + std::vector<scoped_refptr<ShareableBlobDataItem>> ReleaseItems() { + return std::move(items_); + } + + const std::vector<scoped_refptr<ShareableBlobDataItem>>& + pending_transport_items() const { + return pending_transport_items_; + } + + std::vector<scoped_refptr<ShareableBlobDataItem>> + ReleasePendingTransportItems() { + return std::move(pending_transport_items_); + } + + const std::vector<ItemCopyEntry>& copies() const { return copies_; } + + std::vector<ItemCopyEntry> ReleaseCopies() { return std::move(copies_); } + + const std::set<std::string>& dependent_blobs() const { + return dependent_blob_uuids_; + } + + bool IsValid() const { + return !(found_memory_transport_ && found_file_transport_) && + !has_blob_errors_ && total_size_.IsValid() && + transport_quota_needed_.IsValid() && copy_quota_needed_.IsValid(); + } + + bool found_memory_transport() const { return found_memory_transport_; } + + bool found_file_transport() const { return found_file_transport_; } + + uint64_t total_size() const { + return IsValid() ? total_size_.ValueOrDie() : 0u; + } + + uint64_t total_memory_size() const { + return IsValid() ? total_memory_size_.ValueOrDie() : 0u; + } + + uint64_t transport_quota_needed() const { + return IsValid() ? transport_quota_needed_.ValueOrDie() : 0u; + } + + uint64_t copy_quota_needed() const { + return IsValid() ? copy_quota_needed_.ValueOrDie() : 0u; + } private: - friend class BlobMemoryControllerTest; friend class BlobStorageContext; - friend bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b); - friend bool operator==(const BlobDataSnapshot& a, const BlobDataBuilder& b); friend STORAGE_EXPORT void PrintTo(const BlobDataBuilder& x, ::std::ostream* os); - FRIEND_TEST_ALL_PREFIXES(BlobDataBuilderTest, TestFutureFiles); - FRIEND_TEST_ALL_PREFIXES(BlobStorageContextTest, BuildBlobFuzzy); + friend class BlobSliceTest; + + void SliceBlob(const BlobEntry* entry, + uint64_t slice_offset, + uint64_t slice_size); std::string uuid_; std::string content_type_; std::string content_disposition_; - std::vector<scoped_refptr<BlobDataItem>> items_; + + base::CheckedNumeric<uint64_t> total_size_; + base::CheckedNumeric<uint64_t> total_memory_size_; + base::CheckedNumeric<uint64_t> transport_quota_needed_; + base::CheckedNumeric<uint64_t> copy_quota_needed_; + bool has_blob_errors_ = false; + bool found_memory_transport_ = false; + bool found_file_transport_ = false; + + std::vector<scoped_refptr<ShareableBlobDataItem>> items_; + std::vector<scoped_refptr<ShareableBlobDataItem>> pending_transport_items_; + std::set<std::string> dependent_blob_uuids_; + std::vector<ItemCopyEntry> copies_; DISALLOW_COPY_AND_ASSIGN(BlobDataBuilder); }; #if defined(UNIT_TEST) -inline bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b) { - if (a.content_type_ != b.content_type_) - return false; - if (a.content_disposition_ != b.content_disposition_) - return false; - if (a.items_.size() != b.items_.size()) - return false; - for (size_t i = 0; i < a.items_.size(); ++i) { - if (*(a.items_[i]) != *(b.items_[i])) - return false; - } - return true; +inline bool operator==(const BlobDataSnapshot& a, const BlobDataBuilder& b) { + return a == *b.CreateSnapshot(); } -inline bool operator==(const BlobDataSnapshot& a, const BlobDataBuilder& b) { - if (a.content_type() != b.content_type_) { - return false; - } - if (a.content_disposition() != b.content_disposition_) { - return false; - } - if (a.items().size() != b.items_.size()) { - return false; - } - for (size_t i = 0; i < a.items().size(); ++i) { - if (*(a.items()[i]) != *(b.items_[i])) - return false; - } - return true; +inline bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b) { + return *a.CreateSnapshot() == b; } inline bool operator==(const BlobDataBuilder& a, const BlobDataSnapshot& b) {
diff --git a/storage/browser/blob/blob_data_builder_unittest.cc b/storage/browser/blob/blob_data_builder_unittest.cc index c74a7257..80ae39c 100644 --- a/storage/browser/blob/blob_data_builder_unittest.cc +++ b/storage/browser/blob/blob_data_builder_unittest.cc
@@ -22,10 +22,10 @@ BlobDataBuilder builder(kId); builder.AppendFutureFile(0, 10, 0); - EXPECT_TRUE( - BlobDataBuilder::IsFutureFileItem(builder.items_[0]->data_element())); + EXPECT_TRUE(BlobDataBuilder::IsFutureFileItem( + builder.items()[0]->item()->data_element())); EXPECT_EQ(0ull, BlobDataBuilder::GetFutureFileID( - builder.items_[0]->data_element())); + builder.items()[0]->item()->data_element())); } } // namespace storage
diff --git a/storage/browser/blob/blob_data_snapshot.h b/storage/browser/blob/blob_data_snapshot.h index 481629a..3db666e 100644 --- a/storage/browser/blob/blob_data_snapshot.h +++ b/storage/browser/blob/blob_data_snapshot.h
@@ -62,5 +62,26 @@ std::vector<scoped_refptr<BlobDataItem>> items_; }; +#if defined(UNIT_TEST) + +inline bool operator==(const BlobDataSnapshot& a, const BlobDataSnapshot& b) { + if (a.content_type() != b.content_type()) { + return false; + } + if (a.content_disposition() != b.content_disposition()) { + return false; + } + if (a.items().size() != b.items().size()) { + return false; + } + for (size_t i = 0; i < a.items().size(); ++i) { + if (*(a.items()[i]) != *(b.items()[i])) + return false; + } + return true; +} + +#endif // defined(UNIT_TEST) + } // namespace storage #endif // STORAGE_BROWSER_BLOB_BLOB_DATA_SNAPSHOT_H_
diff --git a/storage/browser/blob/blob_entry.cc b/storage/browser/blob/blob_entry.cc index a396e11..ab36fd7 100644 --- a/storage/browser/blob/blob_entry.cc +++ b/storage/browser/blob/blob_entry.cc
@@ -65,6 +65,24 @@ items_.push_back(std::move(item)); } +void BlobEntry::SetSharedBlobItems( + std::vector<scoped_refptr<ShareableBlobDataItem>> items) { + DCHECK(items_.empty()); + DCHECK(offsets_.empty()); + DCHECK_EQ(size_, 0u); + + items_ = std::move(items); + offsets_.reserve(items_.size()); + for (const auto& item : items_) { + size_ += item->item()->length(); + offsets_.emplace_back(size_); + } + // The loop above pushed one too many offset onto offsets_, so remove the + // last one. + if (!offsets_.empty()) + offsets_.pop_back(); +} + const std::vector<scoped_refptr<ShareableBlobDataItem>>& BlobEntry::items() const { return items_;
diff --git a/storage/browser/blob/blob_entry.h b/storage/browser/blob/blob_entry.h index 310f676a..8fd89e1 100644 --- a/storage/browser/blob/blob_entry.h +++ b/storage/browser/blob/blob_entry.h
@@ -101,6 +101,8 @@ // Appends the given shared blob data item to this object. void AppendSharedBlobItem(scoped_refptr<ShareableBlobDataItem> item); + void SetSharedBlobItems( + std::vector<scoped_refptr<ShareableBlobDataItem>> items); // Returns if we're a pending blob that can finish building. bool CanFinishBuilding() const {
diff --git a/storage/browser/blob/blob_flattener_unittest.cc b/storage/browser/blob/blob_flattener_unittest.cc index b2dd5ef..53f01af 100644 --- a/storage/browser/blob/blob_flattener_unittest.cc +++ b/storage/browser/blob/blob_flattener_unittest.cc
@@ -29,8 +29,6 @@ using base::TestSimpleTaskRunner; using FileCreationInfo = BlobMemoryController::FileCreationInfo; -const char kType[] = "type"; -const char kDisposition[] = ""; const size_t kTestBlobStorageIPCThresholdBytes = 20; const size_t kTestBlobStorageMaxSharedMemoryBytes = 50; @@ -50,10 +48,11 @@ } // namespace +// Historically BlobFlattener was a separate class. All that functionality +// was merged into BlobDataBuilder though, so now this test just tests that +// subset of the BlobDataBuilder functionality. class BlobFlattenerTest : public testing::Test { protected: - using BlobFlattener = BlobStorageContext::BlobFlattener; - BlobFlattenerTest() : fake_file_path_(base::FilePath(FILE_PATH_LITERAL("kFakePath"))) {} ~BlobFlattenerTest() override = default; @@ -97,17 +96,17 @@ }; std::unique_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) { - BlobDataBuilder builder(id); - builder.AppendData("1", 1); - builder.set_content_type("text/plain"); - return context_->AddFinishedBlob(builder); + auto builder = std::make_unique<BlobDataBuilder>(id); + builder->AppendData("1", 1); + builder->set_content_type("text/plain"); + return context_->AddFinishedBlob(std::move(builder)); } - BlobStorageRegistry* registry() { return context_->mutable_registry(); } + const BlobStorageRegistry& registry() { return context_->registry(); } const ShareableBlobDataItem& GetItemInBlob(const std::string& uuid, size_t index) { - BlobEntry* entry = registry()->GetEntry(uuid); + const BlobEntry* entry = registry().GetEntry(uuid); EXPECT_TRUE(entry); return *entry->items()[index]; } @@ -121,7 +120,7 @@ limits.effective_max_disk_space = kTestBlobStorageMaxDiskSpace; limits.min_page_file_size = kTestBlobStorageMinFileSizeBytes; limits.max_file_size = kTestBlobStorageMaxFileSizeBytes; - context_->mutable_memory_controller()->set_limits_for_testing(limits); + context_->set_limits_for_testing(limits); } base::FilePath fake_file_path_; @@ -138,18 +137,15 @@ BlobDataBuilder builder(kBlobUUID); builder.AppendData("hi", 2u); builder.AppendFile(fake_file_path_, 0u, 10u, base::Time::Max()); - BlobEntry output(kType, kDisposition); - BlobFlattener flattener(builder, &output, registry()); - EXPECT_EQ(BlobStatus::PENDING_QUOTA, flattener.status); - EXPECT_EQ(0u, flattener.dependent_blobs.size()); - EXPECT_EQ(0u, flattener.copies.size()); - EXPECT_EQ(12u, flattener.total_size); - EXPECT_EQ(2u, flattener.transport_quota_needed); + EXPECT_EQ(0u, builder.dependent_blobs().size()); + EXPECT_EQ(0u, builder.copies().size()); + EXPECT_EQ(12u, builder.total_size()); + EXPECT_EQ(2u, builder.transport_quota_needed()); - ASSERT_EQ(2u, output.items().size()); - EXPECT_EQ(*CreateDataItem("hi", 2u), *output.items()[0]->item()); - EXPECT_EQ(*CreateFileItem(0, 10u), *output.items()[1]->item()); + ASSERT_EQ(2u, builder.items().size()); + EXPECT_EQ(*CreateDataItem("hi", 2u), *builder.items()[0]->item()); + EXPECT_EQ(*CreateFileItem(0, 10u), *builder.items()[1]->item()); } TEST_F(BlobFlattenerTest, ErrorCases) { @@ -159,29 +155,23 @@ // Invalid blob reference. { BlobDataBuilder builder(kBlobUUID); - builder.AppendBlob("doesnotexist"); - BlobEntry output(kType, kDisposition); - BlobFlattener flattener(builder, &output, registry()); - EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, flattener.status); + builder.AppendBlob("doesnotexist", registry()); + EXPECT_FALSE(builder.IsValid()); } // Circular reference. { BlobDataBuilder builder(kBlobUUID); - builder.AppendBlob(kBlobUUID); - BlobEntry output(kType, kDisposition); - BlobFlattener flattener(builder, &output, registry()); - EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, flattener.status); + builder.AppendBlob(kBlobUUID, registry()); + EXPECT_FALSE(builder.IsValid()); } // Bad slice. { std::unique_ptr<BlobDataHandle> handle = SetupBasicBlob(kBlob2UUID); BlobDataBuilder builder(kBlobUUID); - builder.AppendBlob(kBlob2UUID, 1, 2); - BlobEntry output(kType, kDisposition); - BlobFlattener flattener(builder, &output, registry()); - EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, flattener.status); + builder.AppendBlob(kBlob2UUID, 1, 2, registry()); + EXPECT_FALSE(builder.IsValid()); } } @@ -204,72 +194,69 @@ std::unique_ptr<BlobDataHandle> data_blob; { - BlobDataBuilder builder(kDataBlob); - builder.AppendData("12345", 5); - builder.set_content_type("text/plain"); - data_blob = context_->AddFinishedBlob(builder); + auto builder = std::make_unique<BlobDataBuilder>(kDataBlob); + builder->AppendData("12345", 5); + builder->set_content_type("text/plain"); + data_blob = context_->AddFinishedBlob(std::move(builder)); } std::unique_ptr<BlobDataHandle> file_blob; { - BlobDataBuilder builder(kFileBlob); - builder.AppendFile(fake_file_path_, 1u, 10u, base::Time::Max()); - file_blob = context_->AddFinishedBlob(builder); + auto builder = std::make_unique<BlobDataBuilder>(kFileBlob); + builder->AppendFile(fake_file_path_, 1u, 10u, base::Time::Max()); + file_blob = context_->AddFinishedBlob(std::move(builder)); } BlobStatus file_status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; std::vector<FileCreationInfo> file_handles; std::unique_ptr<BlobDataHandle> future_file_blob; { - BlobDataBuilder builder(kPendingFileBlob); - builder.AppendFutureFile(0u, 2u, 0); - builder.AppendFutureFile(2u, 5u, 0); + auto builder = std::make_unique<BlobDataBuilder>(kPendingFileBlob); + builder->AppendFutureFile(0u, 2u, 0); + builder->AppendFutureFile(2u, 5u, 0); future_file_blob = context_->BuildBlob( - builder, + std::move(builder), base::Bind(&SaveBlobStatusAndFiles, &file_status, &file_handles)); } BlobDataBuilder builder(kBlobUUID); builder.AppendData("hi", 2u); - builder.AppendBlob(kDataBlob, 1u, 2u); + builder.AppendBlob(kDataBlob, 1u, 2u, registry()); builder.AppendFile(fake_file_path_, 3u, 5u, base::Time::Max()); - builder.AppendBlob(kDataBlob); - builder.AppendBlob(kFileBlob, 1u, 3u); + builder.AppendBlob(kDataBlob, registry()); + builder.AppendBlob(kFileBlob, 1u, 3u, registry()); builder.AppendFutureData(12u); - builder.AppendBlob(kPendingFileBlob, 1u, 3u); + builder.AppendBlob(kPendingFileBlob, 1u, 3u, registry()); - BlobEntry output(kType, kDisposition); - BlobFlattener flattener(builder, &output, registry()); - EXPECT_EQ(BlobStatus::PENDING_QUOTA, flattener.status); + ASSERT_TRUE(builder.IsValid()); + EXPECT_EQ(3u, builder.dependent_blobs().size()); + EXPECT_EQ(32u, builder.total_size()); + EXPECT_EQ(14u, builder.transport_quota_needed()); + EXPECT_EQ(2u, builder.copy_quota_needed()); - EXPECT_EQ(3u, flattener.dependent_blobs.size()); - EXPECT_EQ(32u, flattener.total_size); - EXPECT_EQ(14u, flattener.transport_quota_needed); - EXPECT_EQ(2u, flattener.copy_quota_needed); - - ASSERT_EQ(8u, output.items().size()); - EXPECT_EQ(*CreateDataItem("hi", 2u), *output.items()[0]->item()); - EXPECT_EQ(*CreateDataDescriptionItem(2u), *output.items()[1]->item()); - EXPECT_EQ(*CreateFileItem(3u, 5u), *output.items()[2]->item()); - EXPECT_EQ(GetItemInBlob(kDataBlob, 0), *output.items()[3]); - EXPECT_EQ(*CreateFileItem(2u, 3u), *output.items()[4]->item()); - EXPECT_EQ(*CreateDataDescriptionItem(12u), *output.items()[5]->item()); - EXPECT_EQ(*CreateFutureFileItem(1u, 1u), *output.items()[6]->item()); - EXPECT_EQ(*CreateFutureFileItem(2u, 2u), *output.items()[7]->item()); + ASSERT_EQ(8u, builder.items().size()); + EXPECT_EQ(*CreateDataItem("hi", 2u), *builder.items()[0]->item()); + EXPECT_EQ(*CreateDataDescriptionItem(2u), *builder.items()[1]->item()); + EXPECT_EQ(*CreateFileItem(3u, 5u), *builder.items()[2]->item()); + EXPECT_EQ(GetItemInBlob(kDataBlob, 0), *builder.items()[3]); + EXPECT_EQ(*CreateFileItem(2u, 3u), *builder.items()[4]->item()); + EXPECT_EQ(*CreateDataDescriptionItem(12u), *builder.items()[5]->item()); + EXPECT_EQ(*CreateFutureFileItem(1u, 1u), *builder.items()[6]->item()); + EXPECT_EQ(*CreateFutureFileItem(2u, 2u), *builder.items()[7]->item()); // We're copying items at index 1, 6, and 7. - ASSERT_EQ(3u, flattener.copies.size()); - EXPECT_EQ(*flattener.copies[0].dest_item, *output.items()[1]); - EXPECT_EQ(GetItemInBlob(kDataBlob, 0), *flattener.copies[0].source_item); - EXPECT_EQ(1u, flattener.copies[0].source_item_offset); - EXPECT_EQ(*flattener.copies[1].dest_item, *output.items()[6]); + ASSERT_EQ(3u, builder.copies().size()); + EXPECT_EQ(*builder.copies()[0].dest_item, *builder.items()[1]); + EXPECT_EQ(GetItemInBlob(kDataBlob, 0), *builder.copies()[0].source_item); + EXPECT_EQ(1u, builder.copies()[0].source_item_offset); + EXPECT_EQ(*builder.copies()[1].dest_item, *builder.items()[6]); EXPECT_EQ(GetItemInBlob(kPendingFileBlob, 0), - *flattener.copies[1].source_item); - EXPECT_EQ(1u, flattener.copies[1].source_item_offset); - EXPECT_EQ(*flattener.copies[2].dest_item, *output.items()[7]); + *builder.copies()[1].source_item); + EXPECT_EQ(1u, builder.copies()[1].source_item_offset); + EXPECT_EQ(*builder.copies()[2].dest_item, *builder.items()[7]); EXPECT_EQ(GetItemInBlob(kPendingFileBlob, 1), - *flattener.copies[2].source_item); - EXPECT_EQ(0u, flattener.copies[2].source_item_offset); + *builder.copies()[2].source_item); + EXPECT_EQ(0u, builder.copies()[2].source_item_offset); // Clean up temp files. EXPECT_TRUE(file_runner_->HasPendingTask());
diff --git a/storage/browser/blob/blob_impl_unittest.cc b/storage/browser/blob/blob_impl_unittest.cc index d05fe82b..070758d 100644 --- a/storage/browser/blob/blob_impl_unittest.cc +++ b/storage/browser/blob/blob_impl_unittest.cc
@@ -68,10 +68,10 @@ std::unique_ptr<BlobDataHandle> CreateBlobFromString( const std::string& uuid, const std::string& contents) { - BlobDataBuilder builder(uuid); - builder.set_content_type("text/plain"); - builder.AppendData(contents); - return context_->AddFinishedBlob(builder); + auto builder = std::make_unique<BlobDataBuilder>(uuid); + builder->set_content_type("text/plain"); + builder->AppendData(contents); + return context_->AddFinishedBlob(std::move(builder)); } std::string UUIDFromBlob(blink::mojom::Blob* blob) {
diff --git a/storage/browser/blob/blob_memory_controller_unittest.cc b/storage/browser/blob/blob_memory_controller_unittest.cc index 0c3e047..b4b6971 100644 --- a/storage/browser/blob/blob_memory_controller_unittest.cc +++ b/storage/browser/blob/blob_memory_controller_unittest.cc
@@ -77,9 +77,9 @@ std::vector<scoped_refptr<ShareableBlobDataItem>> CreateSharedDataItems( const BlobDataBuilder& builder) { std::vector<scoped_refptr<ShareableBlobDataItem>> result; - for (size_t i = 0; i < builder.items_.size(); ++i) { + for (const auto& item : builder.items()) { result.push_back(base::MakeRefCounted<ShareableBlobDataItem>( - builder.items_[i], ShareableBlobDataItem::QUOTA_NEEDED)); + item->item(), ShareableBlobDataItem::QUOTA_NEEDED)); } return result; } @@ -432,12 +432,13 @@ std::memset(kData, 'e', kBlobSize); // Add item that is the file quota. - BlobDataBuilder builder(kId); + auto builder = std::make_unique<BlobDataBuilder>(kId); BlobDataBuilder::FutureFile future_file = - builder.AppendFutureFile(0, kBlobSize, 0); + builder->AppendFutureFile(0, kBlobSize, 0); std::vector<scoped_refptr<ShareableBlobDataItem>> items = - CreateSharedDataItems(builder); + CreateSharedDataItems(*builder); + builder.reset(); file_quota_result_ = false; base::WeakPtr<QuotaAllocationTask> task = @@ -468,7 +469,6 @@ EXPECT_FALSE( BlobDataBuilder::IsFutureFileItem(items[0]->item()->data_element())); - builder.Clear(); items.clear(); // Run cleanup tasks from the ShareableFileReferences. base::RunLoop().RunUntilIdle();
diff --git a/storage/browser/blob/blob_reader_unittest.cc b/storage/browser/blob/blob_reader_unittest.cc index e3e5cd00..77d446ab 100644 --- a/storage/browser/blob/blob_reader_unittest.cc +++ b/storage/browser/blob/blob_reader_unittest.cc
@@ -353,8 +353,9 @@ } protected: - void InitializeReader(BlobDataBuilder* builder) { - blob_handle_ = builder ? context_.AddFinishedBlob(builder) : nullptr; + void InitializeReader(std::unique_ptr<BlobDataBuilder> builder) { + blob_handle_ = + builder ? context_.AddFinishedBlob(std::move(builder)) : nullptr; provider_ = new MockFileStreamReaderProvider(); reader_.reset(new BlobReader(blob_handle_.get())); reader_->SetFileStreamProviderForTesting(base::WrapUnique(provider_)); @@ -425,11 +426,11 @@ }; TEST_F(BlobReaderTest, BasicMemory) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData("Hello!!!"); const size_t kDataSize = 8ul; - b.AppendData(kData); - this->InitializeReader(&b); + b->AppendData(kData); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_FALSE(IsReaderTotalSizeCalculated()); @@ -452,12 +453,12 @@ } TEST_F(BlobReaderTest, BasicFile) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt"); const std::string kData = "FileData!!!"; const base::Time kTime = base::Time::Now(); - b.AppendFile(kPath, 0, kData.size(), kTime); - this->InitializeReader(&b); + b->AppendFile(kPath, 0, kData.size(), kTime); + this->InitializeReader(std::move(b)); // Non-async reader. ExpectLocalFileCall(kPath, kTime, 0, new FakeFileStreamReader(kData)); @@ -483,12 +484,12 @@ } TEST_F(BlobReaderTest, BasicFileSystem) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const GURL kURL("file://test_file/here.txt"); const std::string kData = "FileData!!!"; const base::Time kTime = base::Time::Now(); - b.AppendFileSystemFile(kURL, 0, kData.size(), kTime, nullptr); - this->InitializeReader(&b); + b->AppendFileSystemFile(kURL, 0, kData.size(), kTime, nullptr); + this->InitializeReader(std::move(b)); // Non-async reader. ExpectFileSystemCall(kURL, 0, kData.size(), kTime, new FakeFileStreamReader(kData)); @@ -518,14 +519,14 @@ std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); ASSERT_TRUE(cache); - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData = "Test Blob Data"; scoped_refptr<BlobDataBuilder::DataHandle> data_handle = new EmptyDataHandle(); disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache.get(), "test entry", kData); - b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex); - this->InitializeReader(&b); + b->AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_FALSE(IsReaderTotalSizeCalculated()); @@ -552,17 +553,17 @@ std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); ASSERT_TRUE(cache); - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData = "Test Blob Data"; const std::string kSideData = "Test side data"; scoped_refptr<BlobDataBuilder::DataHandle> data_handle = new EmptyDataHandle(); disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntryWithSideData( cache.get(), "test entry", kData, kSideData); - b.AppendDiskCacheEntryWithSideData(data_handle, entry.get(), - kTestDiskCacheStreamIndex, - kTestDiskCacheSideStreamIndex); - this->InitializeReader(&b); + b->AppendDiskCacheEntryWithSideData(data_handle, entry.get(), + kTestDiskCacheStreamIndex, + kTestDiskCacheSideStreamIndex); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_FALSE(IsReaderTotalSizeCalculated()); @@ -583,12 +584,12 @@ } TEST_F(BlobReaderTest, BufferLargerThanMemory) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData("Hello!!!"); const size_t kDataSize = 8ul; const size_t kBufferSize = 10ul; - b.AppendData(kData); - this->InitializeReader(&b); + b->AppendData(kData); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_FALSE(IsReaderTotalSizeCalculated()); @@ -610,13 +611,13 @@ } TEST_F(BlobReaderTest, MemoryRange) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData("Hello!!!"); const size_t kDataSize = 8ul; const size_t kSeekOffset = 2ul; const uint64_t kReadLength = 4ull; - b.AppendData(kData); - this->InitializeReader(&b); + b->AppendData(kData); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_FALSE(IsReaderTotalSizeCalculated()); @@ -639,11 +640,11 @@ } TEST_F(BlobReaderTest, BufferSmallerThanMemory) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData("Hello!!!"); const size_t kBufferSize = 4ul; - b.AppendData(kData); - this->InitializeReader(&b); + b->AppendData(kData); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_FALSE(IsReaderTotalSizeCalculated()); @@ -674,7 +675,7 @@ } TEST_F(BlobReaderTest, SegmentedBufferAndMemory) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const size_t kNumItems = 10; const size_t kItemSize = 6; const size_t kBufferSize = 10; @@ -685,9 +686,9 @@ for (size_t j = 0; j < kItemSize; j++) { buf[j] = current_value++; } - b.AppendData(buf, kItemSize); + b->AppendData(buf, kItemSize); } - this->InitializeReader(&b); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_FALSE(IsReaderTotalSizeCalculated()); @@ -715,12 +716,12 @@ } TEST_F(BlobReaderTest, FileAsync) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt"); const std::string kData = "FileData!!!"; const base::Time kTime = base::Time::Now(); - b.AppendFile(kPath, 0, kData.size(), kTime); - this->InitializeReader(&b); + b->AppendFile(kPath, 0, kData.size(), kTime); + this->InitializeReader(std::move(b)); std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData)); reader->SetAsyncRunner(base::ThreadTaskRunnerHandle::Get().get()); @@ -751,12 +752,12 @@ } TEST_F(BlobReaderTest, FileSystemAsync) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const GURL kURL("file://test_file/here.txt"); const std::string kData = "FileData!!!"; const base::Time kTime = base::Time::Now(); - b.AppendFileSystemFile(kURL, 0, kData.size(), kTime, nullptr); - this->InitializeReader(&b); + b->AppendFileSystemFile(kURL, 0, kData.size(), kTime, nullptr); + this->InitializeReader(std::move(b)); std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData)); reader->SetAsyncRunner(base::ThreadTaskRunnerHandle::Get().get()); @@ -790,15 +791,15 @@ std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); ASSERT_TRUE(cache); - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData = "Test Blob Data"; scoped_refptr<BlobDataBuilder::DataHandle> data_handle = new EmptyDataHandle(); std::unique_ptr<DelayedReadEntry> delayed_read_entry(new DelayedReadEntry( CreateDiskCacheEntry(cache.get(), "test entry", kData))); - b.AppendDiskCacheEntry(data_handle, delayed_read_entry.get(), - kTestDiskCacheStreamIndex); - this->InitializeReader(&b); + b->AppendDiskCacheEntry(data_handle, delayed_read_entry.get(), + kTestDiskCacheStreamIndex); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_FALSE(IsReaderTotalSizeCalculated()); @@ -822,7 +823,7 @@ } TEST_F(BlobReaderTest, FileRange) { - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt"); // We check the offset in the ExpectLocalFileCall mock. const std::string kRangeData = "leD"; @@ -830,8 +831,8 @@ const uint64_t kOffset = 2; const uint64_t kReadLength = 3; const base::Time kTime = base::Time::Now(); - b.AppendFile(kPath, 0, kData.size(), kTime); - this->InitializeReader(&b); + b->AppendFile(kPath, 0, kData.size(), kTime); + this->InitializeReader(std::move(b)); std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData)); reader->SetAsyncRunner(base::ThreadTaskRunnerHandle::Get().get()); @@ -867,7 +868,7 @@ std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); ASSERT_TRUE(cache); - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData = "Test Blob Data"; const uint64_t kOffset = 2; const uint64_t kReadLength = 3; @@ -875,8 +876,8 @@ new EmptyDataHandle(); disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache.get(), "test entry", kData); - b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex); - this->InitializeReader(&b); + b->AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_EQ(BlobReader::Status::DONE, @@ -902,7 +903,7 @@ // * Unknown file sizes (item length of uint64_t::max) for every other item. // * Offsets for every 3rd file item. // * Non-async reader for every 4th file item. - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const FilePath kPathBase = FilePath::FromUTF8Unsafe("/fake/file.txt"); const base::Time kTime = base::Time::Now(); const size_t kNumItems = 10; @@ -917,9 +918,9 @@ FilePath::FromUTF8Unsafe(base::StringPrintf("%d", current_value))); uint64_t offset = i % 3 == 0 ? 1 : 0; uint64_t size = kItemSize; - b.AppendFile(path, offset, size, kTime); + b->AppendFile(path, offset, size, kTime); } - this->InitializeReader(&b); + this->InitializeReader(std::move(b)); // Set expectations. current_value = 0; @@ -975,7 +976,7 @@ std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); ASSERT_TRUE(cache); - BlobDataBuilder b("uuid"); + auto b = std::make_unique<BlobDataBuilder>("uuid"); const std::string kData1("Hello "); const std::string kData2("there. "); const std::string kData3("This "); @@ -988,14 +989,14 @@ disk_cache::ScopedEntryPtr entry3 = CreateDiskCacheEntry(cache.get(), "test entry", kData3); - b.AppendFile(kData1Path, 0, kData1.size(), kTime); - b.AppendData(kData2); - b.AppendDiskCacheEntry( + b->AppendFile(kData1Path, 0, kData1.size(), kTime); + b->AppendData(kData2); + b->AppendDiskCacheEntry( scoped_refptr<BlobDataBuilder::DataHandle>(new EmptyDataHandle()), entry3.get(), kTestDiskCacheStreamIndex); - b.AppendData(kData4); + b->AppendData(kData4); - this->InitializeReader(&b); + this->InitializeReader(std::move(b)); std::unique_ptr<FakeFileStreamReader> reader( new FakeFileStreamReader(kData1)); @@ -1047,9 +1048,9 @@ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error()); // Case: Not calling CalculateSize before SetReadRange. - BlobDataBuilder builder1("uuid1"); - builder1.AppendData(kData); - InitializeReader(&builder1); + auto builder1 = std::make_unique<BlobDataBuilder>("uuid1"); + builder1->AppendData(kData); + InitializeReader(std::move(builder1)); EXPECT_EQ(BlobReader::Status::NET_ERROR, reader_->SetReadRange(0, 10)); EXPECT_EQ(net::ERR_FAILED, reader_->net_error()); EXPECT_EQ(BlobReader::Status::NET_ERROR, @@ -1057,9 +1058,9 @@ base::Bind(&SetValue<int>, &async_bytes_read))); // Case: Not calling CalculateSize before Read. - BlobDataBuilder builder2("uuid2"); - builder2.AppendData(kData); - InitializeReader(&builder2); + auto builder2 = std::make_unique<BlobDataBuilder>("uuid2"); + builder2->AppendData(kData); + InitializeReader(std::move(builder2)); EXPECT_EQ(BlobReader::Status::NET_ERROR, reader_->Read(buffer.get(), 10, &bytes_read, base::Bind(&SetValue<int>, &async_bytes_read))); @@ -1072,9 +1073,9 @@ const base::Time kTime = base::Time::Now(); // Case: Error on length query. - BlobDataBuilder builder1("uuid1"); - builder1.AppendFile(kPath, 0, kData.size(), kTime); - this->InitializeReader(&builder1); + auto builder1 = std::make_unique<BlobDataBuilder>("uuid1"); + builder1->AppendFile(kPath, 0, kData.size(), kTime); + this->InitializeReader(std::move(builder1)); FakeFileStreamReader* reader = new FakeFileStreamReader(kData); reader->SetReturnError(net::ERR_FILE_NOT_FOUND); ExpectLocalFileCall(kPath, kTime, 0, reader); @@ -1084,9 +1085,9 @@ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error()); // Case: Error on read. - BlobDataBuilder builder2("uuid2"); - builder2.AppendFile(kPath, 0, kData.size(), kTime); - this->InitializeReader(&builder2); + auto builder2 = std::make_unique<BlobDataBuilder>("uuid2"); + builder2->AppendFile(kPath, 0, kData.size(), kTime); + this->InitializeReader(std::move(builder2)); reader = new FakeFileStreamReader(kData); ExpectLocalFileCall(kPath, kTime, 0, reader); EXPECT_EQ(BlobReader::Status::DONE, @@ -1109,9 +1110,9 @@ const base::Time kTime = base::Time::Now(); // Case: Error on length query. - BlobDataBuilder builder1("uuid1"); - builder1.AppendFile(kPath, 0, kData.size(), kTime); - this->InitializeReader(&builder1); + auto builder1 = std::make_unique<BlobDataBuilder>("uuid1"); + builder1->AppendFile(kPath, 0, kData.size(), kTime); + this->InitializeReader(std::move(builder1)); FakeFileStreamReader* reader = new FakeFileStreamReader(kData); reader->SetAsyncRunner(base::ThreadTaskRunnerHandle::Get().get()); reader->SetReturnError(net::ERR_FILE_NOT_FOUND); @@ -1125,9 +1126,9 @@ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error()); // Case: Error on read. - BlobDataBuilder builder2("uuid2"); - builder2.AppendFile(kPath, 0, kData.size(), kTime); - this->InitializeReader(&builder2); + auto builder2 = std::make_unique<BlobDataBuilder>("uuid2"); + builder2->AppendFile(kPath, 0, kData.size(), kTime); + this->InitializeReader(std::move(builder2)); reader = new FakeFileStreamReader(kData); ExpectLocalFileCall(kPath, kTime, 0, reader); EXPECT_EQ(BlobReader::Status::DONE, @@ -1153,9 +1154,9 @@ const uint64_t kReadLength = 4ull; // Case: offset too high. - BlobDataBuilder b("uuid1"); - b.AppendData(kData); - this->InitializeReader(&b); + auto b = std::make_unique<BlobDataBuilder>("uuid1"); + b->AppendData(kData); + this->InitializeReader(std::move(b)); int size_result = -1; EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result))); @@ -1165,9 +1166,9 @@ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error()); // Case: length too long. - BlobDataBuilder b2("uuid2"); - b2.AppendData(kData); - this->InitializeReader(&b2); + auto b2 = std::make_unique<BlobDataBuilder>("uuid2"); + b2->AppendData(kData); + this->InitializeReader(std::move(b2)); size_result = -1; EXPECT_EQ(BlobReader::Status::DONE, reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result))); @@ -1183,12 +1184,13 @@ const size_t kDataSize = 8ul; std::vector<FileCreationInfo> files; - BlobDataBuilder b(kUuid); - b.AppendFutureData(kDataSize); + auto b = std::make_unique<BlobDataBuilder>(kUuid); + b->AppendFutureData(kDataSize); BlobStatus can_populate_status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; blob_handle_ = context_.BuildBlob( - b, base::Bind(&SaveBlobStatusAndFiles, &can_populate_status, &files)); + std::move(b), + base::BindOnce(&SaveBlobStatusAndFiles, &can_populate_status, &files)); EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, can_populate_status); provider_ = new MockFileStreamReaderProvider(); reader_.reset(new BlobReader(blob_handle_.get())); @@ -1209,12 +1211,13 @@ const size_t kDataSize = 8ul; std::vector<FileCreationInfo> files; - BlobDataBuilder b(kUuid); - BlobDataBuilder::FutureData future_data = b.AppendFutureData(kDataSize); + auto b = std::make_unique<BlobDataBuilder>(kUuid); + BlobDataBuilder::FutureData future_data = b->AppendFutureData(kDataSize); BlobStatus can_populate_status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; blob_handle_ = context_.BuildBlob( - b, base::Bind(&SaveBlobStatusAndFiles, &can_populate_status, &files)); + std::move(b), + base::BindOnce(&SaveBlobStatusAndFiles, &can_populate_status, &files)); EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, can_populate_status); provider_ = new MockFileStreamReaderProvider(); reader_.reset(new BlobReader(blob_handle_.get()));
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc index 784f4dea0..20ec2b0 100644 --- a/storage/browser/blob/blob_registry_impl.cc +++ b/storage/browser/blob/blob_registry_impl.cc
@@ -33,11 +33,12 @@ std::vector<blink::mojom::DataElementPtr> elements, mojo::ReportBadMessageCallback bad_message_callback) : blob_registry_(blob_registry), - builder_(uuid), + uuid_(uuid), + builder_(std::make_unique<BlobDataBuilder>(uuid)), bad_message_callback_(std::move(bad_message_callback)), weak_ptr_factory_(this) { - builder_.set_content_type(content_type); - builder_.set_content_disposition(content_disposition); + builder_->set_content_type(content_type); + builder_->set_content_disposition(content_disposition); for (auto& element : elements) elements_.emplace_back(std::move(element)); } @@ -50,7 +51,7 @@ ~BlobUnderConstruction() = default; - const std::string& uuid() const { return builder_.uuid(); } + const std::string& uuid() const { return uuid_; } private: // Holds onto a blink::mojom::DataElement struct and optionally a bound @@ -168,10 +169,13 @@ // BlobRegistryImpl we belong to. BlobRegistryImpl* blob_registry_; + // UUID of the blob being built. + std::string uuid_; + // BlobDataBuilder for the blob under construction. Is created in the // constructor, but not filled until all referenced blob UUIDs have been // resolved. - BlobDataBuilder builder_; + std::unique_ptr<BlobDataBuilder> builder_; // Elements as passed in to Register. std::vector<ElementEntry> elements_; @@ -249,7 +253,7 @@ } transport_strategy_ = BlobTransportStrategy::Create( - memory_strategy, &builder_, + memory_strategy, builder_.get(), base::BindOnce(&BlobUnderConstruction::TransportComplete, weak_ptr_factory_.GetWeakPtr()), memory_controller.limits()); @@ -358,19 +362,20 @@ entry.bytes_provider); } else if (element->is_file()) { const auto& f = element->get_file(); - builder_.AppendFile(f->path, f->offset, f->length, - f->expected_modification_time.value_or(base::Time())); + builder_->AppendFile( + f->path, f->offset, f->length, + f->expected_modification_time.value_or(base::Time())); } else if (element->is_file_filesystem()) { const auto& f = element->get_file_filesystem(); - builder_.AppendFileSystemFile( + builder_->AppendFileSystemFile( f->url, f->offset, f->length, f->expected_modification_time.value_or(base::Time()), blob_registry_->file_system_context_); } else if (element->is_blob()) { DCHECK(blob_uuid_it != referenced_blob_uuids_.end()); const std::string& blob_uuid = *blob_uuid_it++; - builder_.AppendBlob(blob_uuid, element->get_blob()->offset, - element->get_blob()->length); + builder_->AppendBlob(blob_uuid, element->get_blob()->offset, + element->get_blob()->length, context()->registry()); } } @@ -382,7 +387,7 @@ // MarkAsFinishedAndDeleteSelf synchronously, so don't access any members // after this call. std::unique_ptr<BlobDataHandle> new_handle = - context()->BuildPreregisteredBlob(builder_, callback); + context()->BuildPreregisteredBlob(std::move(builder_), callback); // TODO(mek): Update BlobImpl with new BlobDataHandle. Although handles // only differ in their size() attribute, which is currently not used by
diff --git a/storage/browser/blob/blob_registry_impl_unittest.cc b/storage/browser/blob/blob_registry_impl_unittest.cc index 577a337..978fa71b 100644 --- a/storage/browser/blob/blob_registry_impl_unittest.cc +++ b/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -124,10 +124,10 @@ std::unique_ptr<BlobDataHandle> CreateBlobFromString( const std::string& uuid, const std::string& contents) { - BlobDataBuilder builder(uuid); - builder.set_content_type("text/plain"); - builder.AppendData(contents); - return context_->AddFinishedBlob(builder); + auto builder = std::make_unique<BlobDataBuilder>(uuid); + builder->set_content_type("text/plain"); + builder->AppendData(contents); + return context_->AddFinishedBlob(std::move(builder)); } std::string UUIDFromBlob(blink::mojom::Blob* blob) { @@ -943,10 +943,10 @@ EXPECT_FALSE(context_->registry().HasEntry(kId)); // Now cause construction to complete, if it would still be going on. - BlobDataBuilder builder(kDepId); - builder.AppendData(kData); + auto builder = std::make_unique<BlobDataBuilder>(kDepId); + builder->AppendData(kData); context_->BuildPreregisteredBlob( - builder, BlobStorageContext::TransportAllowedCallback()); + std::move(builder), BlobStorageContext::TransportAllowedCallback()); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0u, BlobsUnderConstruction()); }
diff --git a/storage/browser/blob/blob_slice_unittest.cc b/storage/browser/blob/blob_slice_unittest.cc index ef6f0f38..18810e9b 100644 --- a/storage/browser/blob/blob_slice_unittest.cc +++ b/storage/browser/blob/blob_slice_unittest.cc
@@ -18,12 +18,14 @@ namespace { const char kType[] = "type"; const char kDisposition[] = ""; +const char kId[] = "uuid"; } // namespace +// Historically BlobSlice was a separate class. All that functionality +// was merged into BlobDataBuilder though, so now this test just tests that +// subset of the BlobDataBuilder functionality. class BlobSliceTest : public testing::Test { protected: - using BlobSlice = BlobStorageContext::BlobSlice; - BlobSliceTest() = default; ~BlobSliceTest() override = default; @@ -58,41 +60,25 @@ ShareableBlobDataItem::QUOTA_NEEDED)); }; - void ExpectFirstSlice(const BlobSlice& slice, - scoped_refptr<ShareableBlobDataItem> source_item, - size_t first_item_slice_offset, - size_t size) { - EXPECT_TRUE(slice.first_source_item); - EXPECT_EQ(first_item_slice_offset, slice.first_item_slice_offset); - - ASSERT_LE(1u, slice.dest_items.size()); - - scoped_refptr<ShareableBlobDataItem> item = slice.dest_items[0]; - EXPECT_EQ(ShareableBlobDataItem::QUOTA_NEEDED, item->state()); - const network::DataElement& dest_element = item->item()->data_element(); - - EXPECT_EQ(network::DataElement::TYPE_BYTES_DESCRIPTION, - dest_element.type()); - EXPECT_EQ(static_cast<uint64_t>(size), dest_element.length()); - - EXPECT_EQ(*source_item, *slice.first_source_item); + void Slice(BlobDataBuilder& builder, + BlobEntry* source, + uint64_t slice_offset, + uint64_t slice_size) { + builder.SliceBlob(source, slice_offset, slice_size); } - void ExpectLastSlice(const BlobSlice& slice, - scoped_refptr<ShareableBlobDataItem> source_item, - size_t size) { - EXPECT_TRUE(slice.last_source_item); - - ASSERT_LE(2u, slice.dest_items.size()); - scoped_refptr<ShareableBlobDataItem> item = slice.dest_items.back(); - EXPECT_EQ(ShareableBlobDataItem::QUOTA_NEEDED, item->state()); - const network::DataElement& dest_element = item->item()->data_element(); - + void ExpectSlice(scoped_refptr<ShareableBlobDataItem> dest_item, + const BlobEntry::ItemCopyEntry& copy, + scoped_refptr<ShareableBlobDataItem> source_item, + size_t slice_offset, + size_t size) { + EXPECT_EQ(source_item, copy.source_item); + EXPECT_EQ(slice_offset, copy.source_item_offset); + EXPECT_EQ(dest_item, copy.dest_item); + EXPECT_EQ(size, dest_item->item()->length()); + EXPECT_EQ(ShareableBlobDataItem::QUOTA_NEEDED, dest_item->state()); EXPECT_EQ(network::DataElement::TYPE_BYTES_DESCRIPTION, - dest_element.type()); - EXPECT_EQ(static_cast<uint64_t>(size), dest_element.length()); - - EXPECT_EQ(*source_item, *slice.last_source_item); + dest_item->item()->data_element().type()); } }; @@ -103,14 +89,11 @@ scoped_refptr<ShareableBlobDataItem> item = CreateDataItem(kSize); data.AppendSharedBlobItem(item); - BlobSlice slice(data, 0, 5); - EXPECT_EQ(0u, slice.copying_memory_size.ValueOrDie()); - EXPECT_FALSE(slice.first_source_item); - EXPECT_FALSE(slice.last_source_item); - EXPECT_FALSE(slice.first_source_item); - EXPECT_FALSE(slice.last_source_item); - ASSERT_EQ(1u, slice.dest_items.size()); - EXPECT_EQ(item, slice.dest_items[0]); + BlobDataBuilder builder(kId); + Slice(builder, &data, 0, 5); + EXPECT_TRUE(builder.copies().empty()); + ASSERT_EQ(1u, builder.items().size()); + EXPECT_EQ(item, builder.items()[0]); } TEST_F(BlobSliceTest, SliceSingleItem) { @@ -120,11 +103,12 @@ scoped_refptr<ShareableBlobDataItem> item = CreateDataItem(kSize); data.AppendSharedBlobItem(item); - BlobSlice slice(data, 1, 3); - EXPECT_EQ(3u, slice.copying_memory_size.ValueOrDie()); - EXPECT_FALSE(slice.last_source_item); - ExpectFirstSlice(slice, item, 1, 3); - ASSERT_EQ(1u, slice.dest_items.size()); + BlobDataBuilder builder(kId); + Slice(builder, &data, 1, 3); + ASSERT_EQ(1u, builder.copies().size()); + ASSERT_EQ(1u, builder.items().size()); + + ExpectSlice(builder.items()[0], builder.copies()[0], item, 1, 3); } TEST_F(BlobSliceTest, SliceSingleLastItem) { @@ -137,10 +121,12 @@ data.AppendSharedBlobItem(item1); data.AppendSharedBlobItem(item2); - BlobSlice slice(data, 6, 2); - EXPECT_EQ(2u, slice.copying_memory_size.ValueOrDie()); - ExpectFirstSlice(slice, item2, 1, 2); - ASSERT_EQ(1u, slice.dest_items.size()); + BlobDataBuilder builder(kId); + Slice(builder, &data, 6, 2); + ASSERT_EQ(1u, builder.copies().size()); + ASSERT_EQ(1u, builder.items().size()); + + ExpectSlice(builder.items()[0], builder.copies()[0], item2, 1, 2); } TEST_F(BlobSliceTest, SliceAcrossTwoItems) { @@ -153,11 +139,13 @@ data.AppendSharedBlobItem(item1); data.AppendSharedBlobItem(item2); - BlobSlice slice(data, 4, 10); - EXPECT_EQ(10u, slice.copying_memory_size.ValueOrDie()); - ExpectFirstSlice(slice, item1, 4, 1); - ExpectLastSlice(slice, item2, 9); - ASSERT_EQ(2u, slice.dest_items.size()); + BlobDataBuilder builder(kId); + Slice(builder, &data, 4, 10); + ASSERT_EQ(2u, builder.copies().size()); + ASSERT_EQ(2u, builder.items().size()); + + ExpectSlice(builder.items()[0], builder.copies()[0], item1, 4, 1); + ExpectSlice(builder.items()[1], builder.copies()[1], item2, 0, 9); } TEST_F(BlobSliceTest, SliceFileAndLastItem) { @@ -170,13 +158,13 @@ data.AppendSharedBlobItem(item1); data.AppendSharedBlobItem(item2); - BlobSlice slice(data, 4, 2); - EXPECT_EQ(1u, slice.copying_memory_size.ValueOrDie()); - EXPECT_FALSE(slice.first_source_item); - ExpectLastSlice(slice, item2, 1); - ASSERT_EQ(2u, slice.dest_items.size()); + BlobDataBuilder builder(kId); + Slice(builder, &data, 4, 2); + ASSERT_EQ(1u, builder.copies().size()); + ASSERT_EQ(2u, builder.items().size()); - EXPECT_EQ(*CreateFileItem(4u, 1u)->item(), *slice.dest_items[0]->item()); + EXPECT_EQ(*CreateFileItem(4u, 1u)->item(), *builder.items()[0]->item()); + ExpectSlice(builder.items()[1], builder.copies()[0], item2, 0, 1); } TEST_F(BlobSliceTest, SliceAcrossLargeItem) { @@ -192,32 +180,33 @@ data.AppendSharedBlobItem(item2); data.AppendSharedBlobItem(item3); - BlobSlice slice(data, 2, 20); - EXPECT_EQ(3u + 7u, slice.copying_memory_size.ValueOrDie()); - ExpectFirstSlice(slice, item1, 2, 3); - ExpectLastSlice(slice, item3, 7); - ASSERT_EQ(3u, slice.dest_items.size()); + BlobDataBuilder builder(kId); + Slice(builder, &data, 2, 20); + ASSERT_EQ(2u, builder.copies().size()); + ASSERT_EQ(3u, builder.items().size()); - EXPECT_EQ(*item2, *slice.dest_items[1]); + ExpectSlice(builder.items()[0], builder.copies()[0], item1, 2, 3); + EXPECT_EQ(item2, builder.items()[1]); + ExpectSlice(builder.items()[2], builder.copies()[1], item3, 0, 7); } TEST_F(BlobSliceTest, SliceTempFileItem) { BlobEntry data(kType, kDisposition); scoped_refptr<ShareableBlobDataItem> item1 = CreateTempFileItem(1u, 10u); data.AppendSharedBlobItem(item1); - BlobSlice slice(data, 2, 5); - EXPECT_EQ(0u, slice.copying_memory_size.ValueOrDie()); - EXPECT_TRUE(slice.first_source_item); - EXPECT_EQ(2u, slice.first_item_slice_offset); - ASSERT_LE(1u, slice.dest_items.size()); - scoped_refptr<ShareableBlobDataItem> item = slice.dest_items[0]; - EXPECT_EQ(ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA, item->state()); - const network::DataElement& dest_element = item->item()->data_element(); - EXPECT_EQ(network::DataElement::TYPE_FILE, dest_element.type()); - EXPECT_EQ(static_cast<uint64_t>(5), dest_element.length()); - EXPECT_EQ(*item1, *slice.first_source_item); - ASSERT_EQ(1u, slice.dest_items.size()); + BlobDataBuilder builder(kId); + Slice(builder, &data, 2, 5); + ASSERT_EQ(1u, builder.copies().size()); + ASSERT_EQ(1u, builder.items().size()); + auto dest_item = builder.items()[0]; + EXPECT_EQ(item1, builder.copies()[0].source_item); + EXPECT_EQ(2u, builder.copies()[0].source_item_offset); + EXPECT_EQ(dest_item, builder.copies()[0].dest_item); + EXPECT_EQ(5u, dest_item->item()->length()); + EXPECT_EQ(ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA, dest_item->state()); + EXPECT_EQ(network::DataElement::TYPE_FILE, + dest_item->item()->data_element().type()); } } // namespace storage
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc index 0b45e874..79cd22d 100644 --- a/storage/browser/blob/blob_storage_context.cc +++ b/storage/browser/blob/blob_storage_context.cc
@@ -34,360 +34,8 @@ namespace { using ItemCopyEntry = BlobEntry::ItemCopyEntry; using QuotaAllocationTask = BlobMemoryController::QuotaAllocationTask; - -bool IsBytes(network::DataElement::Type type) { - return type == network::DataElement::TYPE_BYTES || - type == network::DataElement::TYPE_BYTES_DESCRIPTION; -} - -void RecordBlobItemSizeStats(const network::DataElement& input_element) { - uint64_t length = input_element.length(); - - switch (input_element.type()) { - case network::DataElement::TYPE_BYTES: - case network::DataElement::TYPE_BYTES_DESCRIPTION: - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.Bytes", length / 1024); - break; - case network::DataElement::TYPE_BLOB: - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.Blob", length / 1024); - break; - case network::DataElement::TYPE_FILE: { - bool full_file = (length == std::numeric_limits<uint64_t>::max()); - UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.File.Unknown", full_file); - if (!full_file) { - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.File", length / 1024); - } - break; - } - case network::DataElement::TYPE_FILE_FILESYSTEM: { - bool full_file = (length == std::numeric_limits<uint64_t>::max()); - UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.FileSystem.Unknown", - full_file); - if (!full_file) { - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.FileSystem", - length / 1024); - } - break; - } - case network::DataElement::TYPE_DISK_CACHE_ENTRY: - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.CacheEntry", length / 1024); - break; - case network::DataElement::TYPE_RAW_FILE: - case network::DataElement::TYPE_DATA_PIPE: - case network::DataElement::TYPE_UNKNOWN: - NOTREACHED(); - break; - } -} } // namespace -BlobStorageContext::BlobFlattener::BlobFlattener( - const BlobDataBuilder& input_builder, - BlobEntry* output_blob, - BlobStorageRegistry* registry) { - const std::string& uuid = input_builder.uuid_; - std::set<std::string> dependent_blob_uuids; - - size_t num_files_with_unknown_size = 0; - size_t num_building_dependent_blobs = 0; - - bool found_memory_transport = false; - bool found_file_transport = false; - - base::CheckedNumeric<uint64_t> checked_total_size = 0; - base::CheckedNumeric<uint64_t> checked_total_memory_size = 0; - base::CheckedNumeric<uint64_t> checked_transport_quota_needed = 0; - base::CheckedNumeric<uint64_t> checked_copy_quota_needed = 0; - - for (scoped_refptr<BlobDataItem> input_item : input_builder.items_) { - const network::DataElement& input_element = input_item->data_element(); - network::DataElement::Type type = input_element.type(); - uint64_t length = input_element.length(); - - RecordBlobItemSizeStats(input_element); - - if (IsBytes(type)) { - DCHECK_NE(0 + network::DataElement::kUnknownSize, input_element.length()); - found_memory_transport = true; - if (found_file_transport) { - // We cannot have both memory and file transport items. - status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - return; - } - contains_unpopulated_transport_items |= - (type == network::DataElement::TYPE_BYTES_DESCRIPTION); - checked_transport_quota_needed += length; - checked_total_size += length; - checked_total_memory_size += length; - scoped_refptr<ShareableBlobDataItem> item = new ShareableBlobDataItem( - std::move(input_item), ShareableBlobDataItem::QUOTA_NEEDED); - pending_transport_items.push_back(item); - transport_items.push_back(item.get()); - output_blob->AppendSharedBlobItem(std::move(item)); - continue; - } - if (type == network::DataElement::TYPE_BLOB) { - BlobEntry* ref_entry = registry->GetEntry(input_element.blob_uuid()); - - if (!ref_entry || input_element.blob_uuid() == uuid) { - status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - return; - } - - if (BlobStatusIsError(ref_entry->status())) { - status = BlobStatus::ERR_REFERENCED_BLOB_BROKEN; - return; - } - - if (ref_entry->total_size() == network::DataElement::kUnknownSize) { - // We can't reference a blob with unknown size. - status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - return; - } - - if (dependent_blob_uuids.find(input_element.blob_uuid()) == - dependent_blob_uuids.end()) { - dependent_blobs.push_back( - std::make_pair(input_element.blob_uuid(), ref_entry)); - dependent_blob_uuids.insert(input_element.blob_uuid()); - if (BlobStatusIsPending(ref_entry->status())) { - num_building_dependent_blobs++; - } - } - - length = length == network::DataElement::kUnknownSize - ? ref_entry->total_size() - : input_element.length(); - checked_total_size += length; - - // If we're referencing the whole blob, then we don't need to slice. - if (input_element.offset() == 0 && length == ref_entry->total_size()) { - for (const auto& shareable_item : ref_entry->items()) { - output_blob->AppendSharedBlobItem(shareable_item); - } - continue; - } - - // Validate our reference has good offset & length. - uint64_t end_byte; - if (!base::CheckAdd(input_element.offset(), length) - .AssignIfValid(&end_byte) || - end_byte > ref_entry->total_size()) { - status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - return; - } - - BlobSlice slice(*ref_entry, input_element.offset(), length); - - if (!slice.copying_memory_size.IsValid() || - !slice.total_memory_size.IsValid()) { - status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - return; - } - checked_total_memory_size += slice.total_memory_size; - - if (slice.first_source_item) { - copies.push_back(ItemCopyEntry(slice.first_source_item, - slice.first_item_slice_offset, - slice.dest_items.front())); - pending_copy_items.push_back(slice.dest_items.front()); - } - if (slice.last_source_item) { - copies.push_back( - ItemCopyEntry(slice.last_source_item, 0, slice.dest_items.back())); - pending_copy_items.push_back(slice.dest_items.back()); - } - checked_copy_quota_needed += slice.copying_memory_size; - - for (auto& shareable_item : slice.dest_items) { - output_blob->AppendSharedBlobItem(std::move(shareable_item)); - } - continue; - } - - // If the source item is a temporary file item, then we need to keep track - // of that and mark it as needing quota. - scoped_refptr<ShareableBlobDataItem> item; - if (BlobDataBuilder::IsFutureFileItem(input_element)) { - found_file_transport = true; - if (found_memory_transport) { - // We cannot have both memory and file transport items. - status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - return; - } - contains_unpopulated_transport_items = true; - item = new ShareableBlobDataItem(std::move(input_item), - ShareableBlobDataItem::QUOTA_NEEDED); - pending_transport_items.push_back(item); - transport_items.push_back(item.get()); - checked_transport_quota_needed += length; - } else { - item = new ShareableBlobDataItem( - std::move(input_item), - ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA); - } - if (length == network::DataElement::kUnknownSize) - num_files_with_unknown_size++; - - checked_total_size += length; - output_blob->AppendSharedBlobItem(std::move(item)); - } - - if (num_files_with_unknown_size > 1 && input_builder.items_.size() > 1) { - status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - return; - } - if (!checked_total_size.IsValid() || !checked_total_memory_size.IsValid() || - !checked_transport_quota_needed.IsValid() || - !checked_copy_quota_needed.IsValid()) { - status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - return; - } - total_size = checked_total_size.ValueOrDie(); - total_memory_size = checked_total_memory_size.ValueOrDie(); - transport_quota_needed = checked_transport_quota_needed.ValueOrDie(); - copy_quota_needed = checked_copy_quota_needed.ValueOrDie(); - transport_quota_type = found_file_transport ? TransportQuotaType::FILE - : TransportQuotaType::MEMORY; - if (transport_quota_needed) { - status = BlobStatus::PENDING_QUOTA; - } else { - status = BlobStatus::PENDING_INTERNALS; - } -} - -BlobStorageContext::BlobFlattener::~BlobFlattener() = default; - -BlobStorageContext::BlobSlice::BlobSlice(const BlobEntry& source, - uint64_t slice_offset, - uint64_t slice_size) { - const auto& source_items = source.items(); - const auto& offsets = source.offsets(); - DCHECK_LE(slice_offset + slice_size, source.total_size()); - size_t item_index = - std::upper_bound(offsets.begin(), offsets.end(), slice_offset) - - offsets.begin(); - uint64_t item_offset = - item_index == 0 ? slice_offset : slice_offset - offsets[item_index - 1]; - size_t num_items = source_items.size(); - - size_t first_item_index = item_index; - - // Read starting from 'first_item_index' and 'item_offset'. - for (uint64_t total_sliced = 0; - item_index < num_items && total_sliced < slice_size; item_index++) { - const scoped_refptr<BlobDataItem>& source_item = - source_items[item_index]->item(); - uint64_t source_length = source_item->length(); - network::DataElement::Type type = source_item->type(); - DCHECK_NE(source_length, std::numeric_limits<uint64_t>::max()); - DCHECK_NE(source_length, 0ull); - - uint64_t read_size = - std::min(source_length - item_offset, slice_size - total_sliced); - total_sliced += read_size; - - bool reusing_blob_item = (read_size == source_length); - UMA_HISTOGRAM_BOOLEAN("Storage.Blob.ReusedItem", reusing_blob_item); - if (reusing_blob_item) { - // We can share the entire item. - dest_items.push_back(source_items[item_index]); - if (IsBytes(type)) { - total_memory_size += source_length; - } - continue; - } - - scoped_refptr<BlobDataItem> data_item; - ShareableBlobDataItem::State state = - ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA; - switch (type) { - case network::DataElement::TYPE_BYTES_DESCRIPTION: - case network::DataElement::TYPE_BYTES: { - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.Bytes", - read_size / 1024); - if (item_index == first_item_index) { - first_item_slice_offset = item_offset; - first_source_item = source_items[item_index]; - } else { - last_source_item = source_items[item_index]; - } - copying_memory_size += read_size; - total_memory_size += read_size; - // Since we don't have quota yet for memory, we create temporary items - // for this data. When our blob is finished constructing, all dependent - // blobs are done, and we have enough memory quota, we'll copy the data - // over. - std::unique_ptr<network::DataElement> element( - new network::DataElement()); - element->SetToBytesDescription(base::checked_cast<size_t>(read_size)); - data_item = new BlobDataItem(std::move(element)); - state = ShareableBlobDataItem::QUOTA_NEEDED; - break; - } - case network::DataElement::TYPE_FILE: { - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.File", - read_size / 1024); - std::unique_ptr<network::DataElement> element( - new network::DataElement()); - element->SetToFilePathRange( - source_item->path(), source_item->offset() + item_offset, read_size, - source_item->expected_modification_time()); - data_item = - new BlobDataItem(std::move(element), source_item->data_handle_); - - if (BlobDataBuilder::IsFutureFileItem(source_item->data_element())) { - // The source file isn't a real file yet (path is fake), so store the - // items we need to copy from later. - if (item_index == first_item_index) { - first_item_slice_offset = item_offset; - first_source_item = source_items[item_index]; - } else { - last_source_item = source_items[item_index]; - } - } - break; - } - case network::DataElement::TYPE_FILE_FILESYSTEM: { - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.FileSystem", - read_size / 1024); - std::unique_ptr<network::DataElement> element( - new network::DataElement()); - element->SetToFileSystemUrlRange( - source_item->filesystem_url(), source_item->offset() + item_offset, - read_size, source_item->expected_modification_time()); - data_item = new BlobDataItem(std::move(element), - source_item->file_system_context()); - break; - } - case network::DataElement::TYPE_DISK_CACHE_ENTRY: { - UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.CacheEntry", - read_size / 1024); - std::unique_ptr<network::DataElement> element( - new network::DataElement()); - element->SetToDiskCacheEntryRange(source_item->offset() + item_offset, - read_size); - data_item = - new BlobDataItem(std::move(element), source_item->data_handle_, - source_item->disk_cache_entry(), - source_item->disk_cache_stream_index(), - source_item->disk_cache_side_stream_index()); - break; - } - case network::DataElement::TYPE_RAW_FILE: - case network::DataElement::TYPE_BLOB: - case network::DataElement::TYPE_DATA_PIPE: - case network::DataElement::TYPE_UNKNOWN: - CHECK(false) << "Illegal blob item type: " << type; - } - dest_items.push_back( - new ShareableBlobDataItem(std::move(data_item), state)); - item_offset = 0; - } -} - -BlobStorageContext::BlobSlice::~BlobSlice() = default; - BlobStorageContext::BlobStorageContext() : memory_controller_(base::FilePath(), scoped_refptr<base::TaskRunner>()), ptr_factory_(this) {} @@ -418,15 +66,9 @@ } std::unique_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob( - const BlobDataBuilder& external_builder) { + std::unique_ptr<BlobDataBuilder> external_builder) { TRACE_EVENT0("Blob", "Context::AddFinishedBlob"); - return BuildBlob(external_builder, TransportAllowedCallback()); -} - -std::unique_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob( - const BlobDataBuilder* builder) { - DCHECK(builder); - return AddFinishedBlob(*builder); + return BuildBlob(std::move(external_builder), TransportAllowedCallback()); } std::unique_ptr<BlobDataHandle> BlobStorageContext::AddBrokenBlob( @@ -474,55 +116,74 @@ } std::unique_ptr<BlobDataHandle> BlobStorageContext::BuildPreregisteredBlob( - const BlobDataBuilder& content, + std::unique_ptr<BlobDataBuilder> content, TransportAllowedCallback transport_allowed_callback) { - BlobEntry* entry = registry_.GetEntry(content.uuid()); + BlobEntry* entry = registry_.GetEntry(content->uuid()); DCHECK(entry); DCHECK_EQ(BlobStatus::PENDING_CONSTRUCTION, entry->status()); entry->set_size(0); - return BuildBlobInternal(entry, content, + return BuildBlobInternal(entry, std::move(content), std::move(transport_allowed_callback)); } std::unique_ptr<BlobDataHandle> BlobStorageContext::BuildBlob( - const BlobDataBuilder& content, + std::unique_ptr<BlobDataBuilder> content, TransportAllowedCallback transport_allowed_callback) { - DCHECK(!registry_.HasEntry(content.uuid_)); + DCHECK(!registry_.HasEntry(content->uuid_)); BlobEntry* entry = registry_.CreateEntry( - content.uuid(), content.content_type_, content.content_disposition_); + content->uuid(), content->content_type_, content->content_disposition_); - return BuildBlobInternal(entry, content, + return BuildBlobInternal(entry, std::move(content), std::move(transport_allowed_callback)); } std::unique_ptr<BlobDataHandle> BlobStorageContext::BuildBlobInternal( BlobEntry* entry, - const BlobDataBuilder& content, + std::unique_ptr<BlobDataBuilder> content, TransportAllowedCallback transport_allowed_callback) { - // This flattens all blob references in the transportion content out and - // stores the complete item representation in the internal data. - BlobFlattener flattener(content, entry, ®istry_); +#if DCHECK_IS_ON() + bool contains_unpopulated_transport_items = false; + for (const auto& item : content->pending_transport_items()) { + if (item->item()->type() == network::DataElement::TYPE_BYTES_DESCRIPTION || + item->item()->type() == network::DataElement::TYPE_FILE) + contains_unpopulated_transport_items = true; + } - DCHECK(!flattener.contains_unpopulated_transport_items || - transport_allowed_callback) + DCHECK(!contains_unpopulated_transport_items || transport_allowed_callback) << "If we have pending unpopulated content then a callback is required"; +#endif - DCHECK(flattener.total_size == 0 || - flattener.total_size == entry->total_size()); - entry->set_size(flattener.total_size); - entry->set_status(flattener.status); - std::unique_ptr<BlobDataHandle> handle = CreateHandle(content.uuid_, entry); + entry->SetSharedBlobItems(content->ReleaseItems()); + + DCHECK((content->total_size() == 0 && !content->IsValid()) || + content->total_size() == entry->total_size()) + << content->total_size() << " vs " << entry->total_size(); + + if (!content->IsValid()) { + entry->set_size(0); + entry->set_status(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS); + } else if (content->transport_quota_needed()) { + entry->set_status(BlobStatus::PENDING_QUOTA); + } else { + entry->set_status(BlobStatus::PENDING_INTERNALS); + } + + std::unique_ptr<BlobDataHandle> handle = CreateHandle(content->uuid_, entry); UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.ItemCount", entry->items().size()); UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.TotalSize", - flattener.total_memory_size / 1024); + content->total_memory_size() / 1024); + + TransportQuotaType transport_quota_type = content->found_memory_transport() + ? TransportQuotaType::MEMORY + : TransportQuotaType::FILE; uint64_t total_memory_needed = - flattener.copy_quota_needed + - (flattener.transport_quota_type == TransportQuotaType::MEMORY - ? flattener.transport_quota_needed + content->copy_quota_needed() + + (transport_quota_type == TransportQuotaType::MEMORY + ? content->transport_quota_needed() : 0); UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.TotalUnsharedSize", total_memory_needed / 1024); @@ -535,26 +196,40 @@ // dependent blob is dereferenced, then we're the last blob holding onto that // data item, and we need to account for that. So we prevent that case by // holding onto all blobs. - for (const std::pair<std::string, BlobEntry*>& pending_blob : - flattener.dependent_blobs) { - dependent_blobs.push_back( - CreateHandle(pending_blob.first, pending_blob.second)); - if (BlobStatusIsPending(pending_blob.second->status())) { - pending_blob.second->building_state_->build_completion_callbacks - .push_back(base::Bind(&BlobStorageContext::OnDependentBlobFinished, - ptr_factory_.GetWeakPtr(), content.uuid_)); + for (const std::string& dependent_blob_uuid : content->dependent_blobs()) { + BlobEntry* blob_entry = registry_.GetEntry(dependent_blob_uuid); + DCHECK(blob_entry); + if (BlobStatusIsError(blob_entry->status())) { + entry->set_status(BlobStatus::ERR_REFERENCED_BLOB_BROKEN); + break; + } + dependent_blobs.push_back(CreateHandle(dependent_blob_uuid, blob_entry)); + if (BlobStatusIsPending(blob_entry->status())) { + blob_entry->building_state_->build_completion_callbacks.push_back( + base::BindOnce(&BlobStorageContext::OnDependentBlobFinished, + ptr_factory_.GetWeakPtr(), content->uuid_)); num_building_dependent_blobs++; } } + std::vector<ShareableBlobDataItem*> transport_items; + transport_items.reserve(content->pending_transport_items().size()); + for (const auto& item : content->pending_transport_items()) + transport_items.emplace_back(item.get()); + + std::vector<scoped_refptr<ShareableBlobDataItem>> pending_copy_items; + pending_copy_items.reserve(content->copies().size()); + for (const auto& copy : content->copies()) + pending_copy_items.emplace_back(copy.dest_item); + auto previous_building_state = std::move(entry->building_state_); entry->set_building_state(std::make_unique<BlobEntry::BuildingState>( - !flattener.pending_transport_items.empty(), + !content->pending_transport_items().empty(), std::move(transport_allowed_callback), num_building_dependent_blobs)); BlobEntry::BuildingState* building_state = entry->building_state_.get(); - std::swap(building_state->copies, flattener.copies); + building_state->copies = content->ReleaseCopies(); std::swap(building_state->dependent_blobs, dependent_blobs); - std::swap(building_state->transport_items, flattener.transport_items); + std::swap(building_state->transport_items, transport_items); if (previous_building_state) { DCHECK(!previous_building_state->transport_items_present); DCHECK(!previous_building_state->transport_allowed_callback); @@ -571,49 +246,49 @@ // Break ourselves if we have an error. BuildingState must be set first so the // callback is called correctly. - if (BlobStatusIsError(flattener.status)) { - CancelBuildingBlobInternal(entry, flattener.status); + if (BlobStatusIsError(entry->status())) { + CancelBuildingBlobInternal(entry, entry->status()); return handle; } // Avoid the state where we might grant only one quota. - if (!memory_controller_.CanReserveQuota(flattener.copy_quota_needed + - flattener.transport_quota_needed)) { + if (!memory_controller_.CanReserveQuota(content->copy_quota_needed() + + content->transport_quota_needed())) { CancelBuildingBlobInternal(entry, BlobStatus::ERR_OUT_OF_MEMORY); return handle; } - if (flattener.copy_quota_needed > 0) { + if (content->copy_quota_needed() > 0) { // The blob can complete during the execution of |ReserveMemoryQuota|. base::WeakPtr<QuotaAllocationTask> pending_request = memory_controller_.ReserveMemoryQuota( - std::move(flattener.pending_copy_items), + std::move(pending_copy_items), base::Bind(&BlobStorageContext::OnEnoughSpaceForCopies, - ptr_factory_.GetWeakPtr(), content.uuid_)); + ptr_factory_.GetWeakPtr(), content->uuid_)); // Building state will be null if the blob is already finished. if (entry->building_state_) entry->building_state_->copy_quota_request = std::move(pending_request); } - if (flattener.transport_quota_needed > 0) { + if (content->transport_quota_needed() > 0) { base::WeakPtr<QuotaAllocationTask> pending_request; - switch (flattener.transport_quota_type) { + switch (transport_quota_type) { case TransportQuotaType::MEMORY: { // The blob can complete during the execution of |ReserveMemoryQuota|. std::vector<BlobMemoryController::FileCreationInfo> empty_files; pending_request = memory_controller_.ReserveMemoryQuota( - std::move(flattener.pending_transport_items), + content->ReleasePendingTransportItems(), base::Bind(&BlobStorageContext::OnEnoughSpaceForTransport, - ptr_factory_.GetWeakPtr(), content.uuid_, + ptr_factory_.GetWeakPtr(), content->uuid_, base::Passed(&empty_files))); break; } case TransportQuotaType::FILE: pending_request = memory_controller_.ReserveFileQuota( - std::move(flattener.pending_transport_items), + content->ReleasePendingTransportItems(), base::Bind(&BlobStorageContext::OnEnoughSpaceForTransport, - ptr_factory_.GetWeakPtr(), content.uuid_)); + ptr_factory_.GetWeakPtr(), content->uuid_)); break; } @@ -755,7 +430,6 @@ void BlobStorageContext::FinishBuilding(BlobEntry* entry) { DCHECK(entry); - BlobStatus status = entry->status_; DCHECK_NE(BlobStatus::DONE, status);
diff --git a/storage/browser/blob/blob_storage_context.h b/storage/browser/blob/blob_storage_context.h index b6c3485..be4ef13 100644 --- a/storage/browser/blob/blob_storage_context.h +++ b/storage/browser/blob/blob_storage_context.h
@@ -39,7 +39,6 @@ class BlobDataBuilder; class BlobDataHandle; class BlobDataSnapshot; -class ShareableBlobDataItem; // This class handles the logistics of blob storage within the browser process. // This class is not threadsafe, access on IO thread. In Chromium there is one @@ -62,11 +61,7 @@ // BlobStatus::RunOnConstructionComplete(callback) to determine construction // completion and possible errors. std::unique_ptr<BlobDataHandle> AddFinishedBlob( - const BlobDataBuilder& builder); - - // Deprecated, use const ref version above or BuildBlob below. - std::unique_ptr<BlobDataHandle> AddFinishedBlob( - const BlobDataBuilder* builder); + std::unique_ptr<BlobDataBuilder> builder); std::unique_ptr<BlobDataHandle> AddBrokenBlob( const std::string& uuid, @@ -98,7 +93,7 @@ // * REFERENCED_BLOB_BROKEN if a referenced blob is broken or we're // referencing ourself. std::unique_ptr<BlobDataHandle> BuildBlob( - const BlobDataBuilder& input_builder, + std::unique_ptr<BlobDataBuilder> input_builder, TransportAllowedCallback transport_allowed_callback); // Similar to BuildBlob, but this merely registers a blob that will be built @@ -117,7 +112,7 @@ // Same as BuildBlob, but for a blob that was previously registered by calling // AddFutureBlob. std::unique_ptr<BlobDataHandle> BuildPreregisteredBlob( - const BlobDataBuilder& input_builder, + std::unique_ptr<BlobDataBuilder> input_builder, TransportAllowedCallback transport_allowed_callback); // This breaks a blob that is currently being built by using the BuildBlob @@ -140,6 +135,10 @@ return ptr_factory_.GetWeakPtr(); } + void set_limits_for_testing(const BlobStorageLimits& limits) { + mutable_memory_controller()->set_limits_for_testing(limits); + } + protected: friend class content::BlobDispatcherHost; friend class content::BlobDispatcherHostTest; @@ -149,88 +148,11 @@ friend class BlobTransportHost; friend class BlobDataHandle; friend class BlobDataHandle::BlobDataHandleShared; - friend class BlobFlattenerTest; friend class BlobRegistryImplTest; - friend class BlobSliceTest; friend class BlobStorageContextTest; enum class TransportQuotaType { MEMORY, FILE }; - // Transforms a BlobDataBuilder into a BlobEntry with no blob references. - // BlobSlice is used to flatten out these references. Records the total size - // and items for memory and file quota requests. - // Exposed in the header file for testing. - struct STORAGE_EXPORT BlobFlattener { - BlobFlattener(const BlobDataBuilder& input_builder, - BlobEntry* output_blob, - BlobStorageRegistry* registry); - ~BlobFlattener(); - - // This can be: - // * PENDING_QUOTA if we need memory quota, if we're populated and don't - // need quota. - // * PENDING_INTERNALS if we're waiting on dependent blobs or we're done. - // * INVALID_CONSTRUCTION_ARGUMENTS if we have invalid input. - // * REFERENCED_BLOB_BROKEN if one of the referenced blobs is broken or we - // reference ourself. - BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - - bool contains_unpopulated_transport_items = false; - - // This is the total size of the blob, including all memory, files, etc. - uint64_t total_size = 0; - // Total memory size of the blob (not including files, etc). - uint64_t total_memory_size = 0; - - std::vector<std::pair<std::string, BlobEntry*>> dependent_blobs; - - TransportQuotaType transport_quota_type = TransportQuotaType::MEMORY; - uint64_t transport_quota_needed = 0; - std::vector<scoped_refptr<ShareableBlobDataItem>> pending_transport_items; - // Hold a separate vector of pointers to declare them as populated. - std::vector<ShareableBlobDataItem*> transport_items; - - // Copy quota is always memory quota. - uint64_t copy_quota_needed = 0; - std::vector<scoped_refptr<ShareableBlobDataItem>> pending_copy_items; - - // These record all future copies we'll need to do from referenced blobs. - // This happens when we do a partial slice from a pending data or file - // item. - std::vector<BlobEntry::ItemCopyEntry> copies; - - private: - DISALLOW_COPY_AND_ASSIGN(BlobFlattener); - }; - - // Used when a blob reference has a size and offset. Records the source items - // and memory we need to copy if either side of slice intersects an item. - // Exposed in the header file for testing. - struct STORAGE_EXPORT BlobSlice { - BlobSlice(const BlobEntry& source, - uint64_t slice_offset, - uint64_t slice_size); - ~BlobSlice(); - - // Size of memory copying from the source blob. - base::CheckedNumeric<size_t> copying_memory_size = 0; - // Size of all memory for UMA stats. - base::CheckedNumeric<size_t> total_memory_size = 0; - - size_t first_item_slice_offset = 0; - // Populated if our first slice item is a temporary item that we'll copy to - // later from this |first_source_item|, at offset |first_item_slice_offset|. - scoped_refptr<ShareableBlobDataItem> first_source_item; - // Populated if our last slice item is a temporary item that we'll copy to - // later from this |last_source_item|. - scoped_refptr<ShareableBlobDataItem> last_source_item; - - std::vector<scoped_refptr<ShareableBlobDataItem>> dest_items; - - private: - DISALLOW_COPY_AND_ASSIGN(BlobSlice); - }; - void IncrementBlobRefCount(const std::string& uuid); void DecrementBlobRefCount(const std::string& uuid); @@ -259,7 +181,7 @@ private: std::unique_ptr<BlobDataHandle> BuildBlobInternal( BlobEntry* entry, - const BlobDataBuilder& input_builder, + std::unique_ptr<BlobDataBuilder> input_builder, TransportAllowedCallback transport_allowed_callback); std::unique_ptr<BlobDataHandle> CreateHandle(const std::string& uuid,
diff --git a/storage/browser/blob/blob_storage_context_unittest.cc b/storage/browser/blob/blob_storage_context_unittest.cc index 839c962d..71ef114 100644 --- a/storage/browser/blob/blob_storage_context_unittest.cc +++ b/storage/browser/blob/blob_storage_context_unittest.cc
@@ -122,10 +122,10 @@ } std::unique_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) { - BlobDataBuilder builder(id); - builder.AppendData("1", 1); - builder.set_content_type("text/plain"); - return context_->AddFinishedBlob(builder); + auto builder = std::make_unique<BlobDataBuilder>(id); + builder->AppendData("1", 1); + builder->set_content_type("text/plain"); + return context_->AddFinishedBlob(std::move(builder)); } void SetTestMemoryLimits() { @@ -161,12 +161,15 @@ const size_t kSize = 10u; BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - BlobDataBuilder builder(kId); - BlobDataBuilder::FutureData future_data = builder.AppendFutureData(kSize); - builder.set_content_type("text/plain"); + auto builder = std::make_unique<BlobDataBuilder>(kId); + BlobDataBuilder::FutureData future_data = builder->AppendFutureData(kSize); + builder->set_content_type("text/plain"); + std::unique_ptr<BlobDataSnapshot> builder_snapshot = + builder->CreateSnapshot(); EXPECT_EQ(0lu, context_->memory_controller().memory_usage()); std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob( - builder, base::Bind(&SaveBlobStatusAndFiles, &status, &files_)); + std::move(builder), + base::BindOnce(&SaveBlobStatusAndFiles, &status, &files_)); EXPECT_EQ(10lu, context_->memory_controller().memory_usage()); EXPECT_TRUE(handle->IsBeingBuilt()) << static_cast<int>(handle->GetBlobStatus()); @@ -174,7 +177,7 @@ BlobStatus construction_done = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; handle->RunOnConstructionComplete( - base::Bind(&SaveBlobStatus, &construction_done)); + base::BindOnce(&SaveBlobStatus, &construction_done)); EXPECT_EQ(10u, context_->memory_controller().memory_usage()); @@ -186,7 +189,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(BlobStatus::DONE, construction_done); - EXPECT_EQ(builder, *handle->CreateSnapshot()); + EXPECT_EQ(*builder_snapshot, *handle->CreateSnapshot()); handle.reset(); base::RunLoop().RunUntilIdle(); @@ -198,12 +201,13 @@ const size_t kSize = 10u; BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; - BlobDataBuilder builder(kId); - builder.AppendFutureData(kSize); - builder.set_content_type("text/plain"); + auto builder = std::make_unique<BlobDataBuilder>(kId); + builder->AppendFutureData(kSize); + builder->set_content_type("text/plain"); EXPECT_EQ(0lu, context_->memory_controller().memory_usage()); std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob( - builder, base::Bind(&SaveBlobStatusAndFiles, &status, &files_)); + std::move(builder), + base::BindOnce(&SaveBlobStatusAndFiles, &status, &files_)); EXPECT_EQ(10lu, context_->memory_controller().memory_usage()); EXPECT_TRUE(handle->IsBeingBuilt()); EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, status); @@ -211,7 +215,7 @@ BlobStatus construction_done = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; handle->RunOnConstructionComplete( - base::Bind(&SaveBlobStatus, &construction_done)); + base::BindOnce(&SaveBlobStatus, &construction_done)); context_->CancelBuildingBlob(kId, BlobStatus::ERR_SOURCE_DIED_IN_TRANSIT); EXPECT_TRUE(handle->IsBroken()); @@ -230,32 +234,33 @@ BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; // Start our first blob. - BlobDataBuilder builder(kId1); - builder.AppendFutureData(kSize); - builder.set_content_type("text/plain"); + auto builder = std::make_unique<BlobDataBuilder>(kId1); + builder->AppendFutureData(kSize); + builder->set_content_type("text/plain"); EXPECT_EQ(0lu, context_->memory_controller().memory_usage()); std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob( - builder, base::Bind(&SaveBlobStatusAndFiles, &status, &files_)); + std::move(builder), + base::BindOnce(&SaveBlobStatusAndFiles, &status, &files_)); EXPECT_EQ(10lu, context_->memory_controller().memory_usage()); EXPECT_TRUE(handle->IsBeingBuilt()); EXPECT_EQ(BlobStatus::PENDING_TRANSPORT, status); BlobStatus construction_done = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; handle->RunOnConstructionComplete( - base::Bind(&SaveBlobStatus, &construction_done)); + base::BindOnce(&SaveBlobStatus, &construction_done)); EXPECT_EQ(10u, context_->memory_controller().memory_usage()); // Create our second blob, which depends on the first. - BlobDataBuilder builder2(kId2); - builder2.AppendBlob(kId1); - builder2.set_content_type("text/plain"); + auto builder2 = std::make_unique<BlobDataBuilder>(kId2); + builder2->AppendBlob(kId1, context_->registry()); + builder2->set_content_type("text/plain"); std::unique_ptr<BlobDataHandle> handle2 = context_->BuildBlob( - builder2, BlobStorageContext::TransportAllowedCallback()); + std::move(builder2), BlobStorageContext::TransportAllowedCallback()); BlobStatus construction_done2 = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; handle->RunOnConstructionComplete( - base::Bind(&SaveBlobStatus, &construction_done2)); + base::BindOnce(&SaveBlobStatus, &construction_done2)); EXPECT_TRUE(handle2->IsBeingBuilt()); EXPECT_EQ(10lu, context_->memory_controller().memory_usage()); @@ -284,10 +289,10 @@ EXPECT_EQ(1lu, context_->memory_controller().memory_usage()); - BlobDataBuilder builder(kId2); - builder.AppendBlob(kId1, 1, 10); + auto builder = std::make_unique<BlobDataBuilder>(kId2); + builder->AppendBlob(kId1, 1, 10, context_->registry()); std::unique_ptr<BlobDataHandle> handle2 = context_->BuildBlob( - builder, BlobStorageContext::TransportAllowedCallback()); + std::move(builder), BlobStorageContext::TransportAllowedCallback()); EXPECT_TRUE(handle2->IsBroken()); EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, @@ -345,24 +350,24 @@ const std::string kId1("id1"); const std::string kId2("id2"); - BlobDataBuilder builder1(kId1); - BlobDataBuilder builder2(kId2); - builder1.AppendData("Data1Data2"); - builder2.AppendBlob(kId1); - builder2.AppendBlob(kId1); - builder2.AppendBlob(kId1); - builder2.AppendBlob(kId1); - builder2.AppendBlob(kId1); - builder2.AppendBlob(kId1); - builder2.AppendBlob(kId1); - + auto builder1 = std::make_unique<BlobDataBuilder>(kId1); + builder1->AppendData("Data1Data2"); EXPECT_EQ(0lu, context_->memory_controller().memory_usage()); std::unique_ptr<BlobDataHandle> blob_data_handle = - context_->AddFinishedBlob(&builder1); + context_->AddFinishedBlob(std::move(builder1)); EXPECT_EQ(10lu, context_->memory_controller().memory_usage()); + + auto builder2 = std::make_unique<BlobDataBuilder>(kId2); + builder2->AppendBlob(kId1, context_->registry()); + builder2->AppendBlob(kId1, context_->registry()); + builder2->AppendBlob(kId1, context_->registry()); + builder2->AppendBlob(kId1, context_->registry()); + builder2->AppendBlob(kId1, context_->registry()); + builder2->AppendBlob(kId1, context_->registry()); + builder2->AppendBlob(kId1, context_->registry()); std::unique_ptr<BlobDataHandle> blob_data_handle2 = - context_->AddFinishedBlob(&builder2); + context_->AddFinishedBlob(std::move(builder2)); EXPECT_EQ(10lu, context_->memory_controller().memory_usage()); EXPECT_EQ(2u, context_->registry().blob_count()); @@ -384,21 +389,20 @@ const std::string kId2("id12"); const std::string kId3("id3"); - BlobDataBuilder builder1(kId1); - BlobDataBuilder builder2(kId2); + auto builder1 = std::make_unique<BlobDataBuilder>(kId1); + builder1->AppendData("Data1Data2"); + std::unique_ptr<BlobDataSnapshot> builder1_data = builder1->CreateSnapshot(); + std::unique_ptr<BlobDataHandle> blob_data_handle = + context_->AddFinishedBlob(std::move(builder1)); + + auto builder2 = std::make_unique<BlobDataBuilder>(kId2); + builder2->AppendBlob(kId1, 5, 5, context_->registry()); + builder2->AppendData(" is the best"); BlobDataBuilder canonicalized_blob_data2(kId2); - builder1.AppendData("Data1Data2"); - builder2.AppendBlob(kId1, 5, 5); - builder2.AppendData(" is the best"); canonicalized_blob_data2.AppendData("Data2"); canonicalized_blob_data2.AppendData(" is the best"); - - BlobStorageContext context; - - std::unique_ptr<BlobDataHandle> blob_data_handle = - context_->AddFinishedBlob(&builder1); std::unique_ptr<BlobDataHandle> blob_data_handle2 = - context_->AddFinishedBlob(&builder2); + context_->AddFinishedBlob(std::move(builder2)); EXPECT_EQ(10u + 12u + 5u, context_->memory_controller().memory_usage()); @@ -406,7 +410,7 @@ ASSERT_TRUE(blob_data_handle2); std::unique_ptr<BlobDataSnapshot> data1 = blob_data_handle->CreateSnapshot(); std::unique_ptr<BlobDataSnapshot> data2 = blob_data_handle2->CreateSnapshot(); - EXPECT_EQ(*data1, builder1); + EXPECT_EQ(*data1, *builder1_data); EXPECT_EQ(*data2, canonicalized_blob_data2); blob_data_handle.reset(); data2.reset(); @@ -422,11 +426,11 @@ EXPECT_EQ(*data2, canonicalized_blob_data2); // Test shared elements stick around. - BlobDataBuilder builder3(kId3); - builder3.AppendBlob(kId2); - builder3.AppendBlob(kId2); + auto builder3 = std::make_unique<BlobDataBuilder>(kId3); + builder3->AppendBlob(kId2, context_->registry()); + builder3->AppendBlob(kId2, context_->registry()); std::unique_ptr<BlobDataHandle> blob_data_handle3 = - context_->AddFinishedBlob(&builder3); + context_->AddFinishedBlob(std::move(builder3)); EXPECT_FALSE(blob_data_handle3->IsBeingBuilt()); blob_data_handle2.reset(); base::RunLoop().RunUntilIdle(); @@ -461,17 +465,17 @@ const std::string kId1("id1"); const std::string kId2("id2"); - BlobDataBuilder builder1(kId1); - builder1.AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now(), - nullptr); - - BlobDataBuilder builder2(kId2); - builder2.AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength); - + auto builder1 = std::make_unique<BlobDataBuilder>(kId1); + builder1->AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now(), + nullptr); std::unique_ptr<BlobDataHandle> blob_data_handle1 = - context_->AddFinishedBlob(&builder1); + context_->AddFinishedBlob(std::move(builder1)); + + auto builder2 = std::make_unique<BlobDataBuilder>(kId2); + builder2->AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength, + context_->registry()); std::unique_ptr<BlobDataHandle> blob_data_handle2 = - context_->AddFinishedBlob(&builder2); + context_->AddFinishedBlob(std::move(builder2)); ASSERT_TRUE(blob_data_handle1); ASSERT_TRUE(blob_data_handle2); @@ -505,15 +509,16 @@ canonicalized_blob_data.AppendData(kTestBlobData.c_str()); const std::string kId1("id1"); - BlobDataBuilder builder(kId1); + auto builder = std::make_unique<BlobDataBuilder>(kId1); - builder.AppendDiskCacheEntry( - data_handle, entry.get(), kTestDiskCacheStreamIndex); + builder->AppendDiskCacheEntry(data_handle, entry.get(), + kTestDiskCacheStreamIndex); + std::unique_ptr<BlobDataSnapshot> builder_data = builder->CreateSnapshot(); std::unique_ptr<BlobDataHandle> blob_data_handle = - context.AddFinishedBlob(&builder); + context.AddFinishedBlob(std::move(builder)); std::unique_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); - EXPECT_EQ(*data, builder); + EXPECT_EQ(*data, *builder_data); EXPECT_FALSE(data_handle->HasOneRef()) << "Data handle was destructed while context and builder still exist."; } @@ -528,19 +533,20 @@ std::make_unique<BlobStorageContext>(temp_dir_.GetPath(), file_runner_); SetTestMemoryLimits(); - BlobDataBuilder builder(kId1); - builder.set_content_type("text/plain"); - BlobDataBuilder::FutureFile future_file = builder.AppendFutureFile(0, 10, 0); + auto builder = std::make_unique<BlobDataBuilder>(kId1); + builder->set_content_type("text/plain"); + BlobDataBuilder::FutureFile future_file = builder->AppendFutureFile(0, 10, 0); BlobStatus status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob( - builder, base::Bind(&SaveBlobStatusAndFiles, &status, &files_)); + std::move(builder), + base::BindOnce(&SaveBlobStatusAndFiles, &status, &files_)); size_t blobs_finished = 0; EXPECT_EQ(BlobStatus::PENDING_QUOTA, handle->GetBlobStatus()); EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS, status); handle->RunOnConstructionComplete( - base::Bind(&IncrementNumber, &blobs_finished)); + base::BindOnce(&IncrementNumber, &blobs_finished)); EXPECT_EQ(0u, blobs_finished); EXPECT_TRUE(file_runner_->HasPendingTask()); @@ -564,7 +570,6 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(1u, blobs_finished); - builder.Clear(); handle.reset(); files_.clear(); base::RunLoop().RunUntilIdle(); @@ -586,26 +591,39 @@ ASSERT_TRUE(base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1)); ASSERT_TRUE(base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2)); - BlobDataBuilder blob_data1(kId1); - blob_data1.AppendData("Data1"); - blob_data1.AppendData("Data2"); - blob_data1.AppendFile(base::FilePath(FILE_PATH_LITERAL("File1.txt")), 10, - 1024, time1); + auto blob_data1_builder = std::make_unique<BlobDataBuilder>(kId1); + blob_data1_builder->AppendData("Data1"); + blob_data1_builder->AppendData("Data2"); + blob_data1_builder->AppendFile(base::FilePath(FILE_PATH_LITERAL("File1.txt")), + 10, 1024, time1); + std::unique_ptr<BlobDataSnapshot> blob_data1 = + blob_data1_builder->CreateSnapshot(); - BlobDataBuilder blob_data2(kId2); - blob_data2.AppendData("Data3"); - blob_data2.AppendBlob(kId1, 8, 100); - blob_data2.AppendFile(base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, - time2); + std::unique_ptr<BlobDataHandle> blob_data_handle; + // Test a blob referring to only data and a file. + blob_data_handle = context_->AddFinishedBlob(std::move(blob_data1_builder)); - BlobDataBuilder blob_data3(kId3); - blob_data3.AppendData("Data4"); + ASSERT_TRUE(blob_data_handle); + std::unique_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); + ASSERT_TRUE(blob_data_handle); + EXPECT_EQ(*data, *blob_data1); + + auto blob_data2 = std::make_unique<BlobDataBuilder>(kId2); + blob_data2->AppendData("Data3"); + blob_data2->AppendBlob(kId1, 8, 100, context_->registry()); + blob_data2->AppendFile(base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, + time2); + + auto blob_data3_builder = std::make_unique<BlobDataBuilder>(kId3); + blob_data3_builder->AppendData("Data4"); std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); ASSERT_TRUE(cache); disk_cache::ScopedEntryPtr disk_cache_entry = CreateDiskCacheEntry(cache.get(), "another key", "Data5"); - blob_data3.AppendDiskCacheEntry(new EmptyDataHandle(), disk_cache_entry.get(), - kTestDiskCacheStreamIndex); + blob_data3_builder->AppendDiskCacheEntry( + new EmptyDataHandle(), disk_cache_entry.get(), kTestDiskCacheStreamIndex); + std::unique_ptr<BlobDataSnapshot> blob_data3 = + blob_data3_builder->CreateSnapshot(); BlobDataBuilder canonicalized_blob_data2(kId2); canonicalized_blob_data2.AppendData("Data3"); @@ -615,29 +633,18 @@ canonicalized_blob_data2.AppendFile( base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2); - BlobStorageContext context; - std::unique_ptr<BlobDataHandle> blob_data_handle; - - // Test a blob referring to only data and a file. - blob_data_handle = context_->AddFinishedBlob(&blob_data1); - - ASSERT_TRUE(blob_data_handle); - std::unique_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); - ASSERT_TRUE(blob_data_handle); - EXPECT_EQ(*data, blob_data1); - // Test a blob composed in part with another blob. - blob_data_handle = context_->AddFinishedBlob(&blob_data2); + blob_data_handle = context_->AddFinishedBlob(std::move(blob_data2)); data = blob_data_handle->CreateSnapshot(); ASSERT_TRUE(blob_data_handle); ASSERT_TRUE(data); EXPECT_EQ(*data, canonicalized_blob_data2); // Test a blob referring to only data and a disk cache entry. - blob_data_handle = context_->AddFinishedBlob(&blob_data3); + blob_data_handle = context_->AddFinishedBlob(std::move(blob_data3_builder)); data = blob_data_handle->CreateSnapshot(); ASSERT_TRUE(blob_data_handle); - EXPECT_EQ(*data, blob_data3); + EXPECT_EQ(*data, *blob_data3); blob_data_handle.reset(); base::RunLoop().RunUntilIdle(); @@ -687,10 +694,11 @@ EXPECT_TRUE(context_->registry().HasEntry(kBrokenId)); // Try to create a blob with a reference to an unknown blob. - BlobDataBuilder builder(kReferencingId); - builder.AppendData("data"); - builder.AppendBlob(kUnknownId); - std::unique_ptr<BlobDataHandle> handle = context_->AddFinishedBlob(builder); + auto builder = std::make_unique<BlobDataBuilder>(kReferencingId); + builder->AppendData("data"); + builder->AppendBlob(kUnknownId, context_->registry()); + std::unique_ptr<BlobDataHandle> handle = + context_->AddFinishedBlob(std::move(builder)); EXPECT_TRUE(handle->IsBroken()); EXPECT_TRUE(context_->registry().HasEntry(kReferencingId)); handle.reset(); @@ -698,10 +706,10 @@ EXPECT_FALSE(context_->registry().HasEntry(kReferencingId)); // Try to create a blob with a reference to the broken blob. - BlobDataBuilder builder2(kReferencingId); - builder2.AppendData("data"); - builder2.AppendBlob(kBrokenId); - handle = context_->AddFinishedBlob(builder2); + auto builder2 = std::make_unique<BlobDataBuilder>(kReferencingId); + builder2->AppendData("data"); + builder2->AppendBlob(kBrokenId, context_->registry()); + handle = context_->AddFinishedBlob(std::move(builder2)); EXPECT_TRUE(handle->IsBroken()); EXPECT_TRUE(context_->registry().HasEntry(kReferencingId)); handle.reset(); @@ -709,10 +717,10 @@ EXPECT_FALSE(context_->registry().HasEntry(kReferencingId)); // Try to create a blob with a reference to the building blob. - BlobDataBuilder builder3(kReferencingId); - builder3.AppendData("data"); - builder3.AppendBlob(kBuildingId); - handle = context_->AddFinishedBlob(builder3); + auto builder3 = std::make_unique<BlobDataBuilder>(kReferencingId); + builder3->AppendData("data"); + builder3->AppendBlob(kBuildingId, context_->registry()); + handle = context_->AddFinishedBlob(std::move(builder3)); EXPECT_TRUE(handle->IsBroken()); EXPECT_TRUE(context_->registry().HasEntry(kReferencingId)); handle.reset(); @@ -772,7 +780,6 @@ } void PopulateDataInBuilder( - BlobDataBuilder* builder, std::vector<BlobDataBuilder::FutureData>* future_datas, std::vector<BlobDataBuilder::FutureFile>* future_files, size_t index, @@ -822,15 +829,6 @@ sizes.push_back(size); } - for (size_t i = 0; i < kTotalSlicedBlobs; i++) { - builders.emplace_back( - new BlobDataBuilder(base::NumberToString(i + kTotalRawBlobs))); - size_t source_size = sizes[i]; - size_t offset = source_size == 1 ? 0 : i % (source_size - 1); - size_t size = (i % (source_size - offset)) + 1; - builders.back()->AppendBlob(base::NumberToString(i), offset, size); - } - size_t total_finished_blobs = 0; std::vector<std::unique_ptr<BlobDataHandle>> handles; std::vector<BlobStatus> statuses; @@ -839,18 +837,36 @@ BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS); populated.resize(kTotalRawBlobs, false); for (size_t i = 0; i < builders.size(); i++) { - BlobDataBuilder& builder = *builders[i]; - builder.set_content_type("text/plain"); + std::unique_ptr<BlobDataBuilder> builder = std::move(builders[i]); + builder->set_content_type("text/plain"); bool has_pending_memory = DoesBuilderHaveFutureData(i); std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob( - builder, + std::move(builder), has_pending_memory - ? base::Bind(&SaveBlobStatusAndFiles, &statuses[0] + i, &files_) + ? base::BindOnce(&SaveBlobStatusAndFiles, &statuses[0] + i, &files_) : BlobStorageContext::TransportAllowedCallback()); handle->RunOnConstructionComplete( - base::Bind(&IncrementNumber, &total_finished_blobs)); + base::BindOnce(&IncrementNumber, &total_finished_blobs)); handles.push_back(std::move(handle)); } + builders.clear(); + + for (size_t i = 0; i < kTotalSlicedBlobs; i++) { + auto builder = std::make_unique<BlobDataBuilder>( + base::NumberToString(i + kTotalRawBlobs)); + size_t source_size = sizes[i]; + size_t offset = source_size == 1 ? 0 : i % (source_size - 1); + size_t size = (i % (source_size - offset)) + 1; + builder->AppendBlob(base::NumberToString(i), offset, size, + context_->registry()); + builder->set_content_type("text/plain"); + std::unique_ptr<BlobDataHandle> handle = context_->BuildBlob( + std::move(builder), BlobStorageContext::TransportAllowedCallback()); + handle->RunOnConstructionComplete( + base::BindOnce(&IncrementNumber, &total_finished_blobs)); + handles.push_back(std::move(handle)); + } + base::RunLoop().RunUntilIdle(); // We should be needing to send a page or two to disk. @@ -860,10 +876,9 @@ base::RunLoop().RunUntilIdle(); // Continue populating data for items that can fit. for (size_t i = 0; i < kTotalRawBlobs; i++) { - BlobDataBuilder* builder = builders[i].get(); if (DoesBuilderHaveFutureData(i) && !populated[i] && statuses[i] == BlobStatus::PENDING_TRANSPORT) { - PopulateDataInBuilder(builder, &future_datas[i], &future_files[i], i, + PopulateDataInBuilder(&future_datas[i], &future_files[i], i, file_runner_.get()); context_->NotifyTransportComplete(base::NumberToString(i)); populated[i] = true; @@ -905,10 +920,11 @@ EXPECT_EQ(1lu, context_->memory_controller().memory_usage()); - BlobDataBuilder builder(kId2); - builder.AppendBlob(kId1, static_cast<uint64_t>(-10), 11); + auto builder = std::make_unique<BlobDataBuilder>(kId2); + builder->AppendBlob(kId1, static_cast<uint64_t>(-10), 11, + context_->registry()); std::unique_ptr<BlobDataHandle> handle2 = context_->BuildBlob( - builder, BlobStorageContext::TransportAllowedCallback()); + std::move(builder), BlobStorageContext::TransportAllowedCallback()); EXPECT_TRUE(handle2->IsBroken()); EXPECT_EQ(BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS,
diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc index f6cac5a3..48aedfdd 100644 --- a/storage/browser/blob/blob_url_store_impl_unittest.cc +++ b/storage/browser/blob/blob_url_store_impl_unittest.cc
@@ -39,11 +39,12 @@ BlobPtr CreateBlobFromString(const std::string& uuid, const std::string& contents) { - BlobDataBuilder builder(uuid); - builder.set_content_type("text/plain"); - builder.AppendData(contents); + auto builder = std::make_unique<BlobDataBuilder>(uuid); + builder->set_content_type("text/plain"); + builder->AppendData(contents); BlobPtr blob; - BlobImpl::Create(context_->AddFinishedBlob(builder), MakeRequest(&blob)); + BlobImpl::Create(context_->AddFinishedBlob(std::move(builder)), + MakeRequest(&blob)); return blob; }
diff --git a/storage/browser/test/mock_blob_url_request_context.cc b/storage/browser/test/mock_blob_url_request_context.cc index 1cba629..54fb8e6 100644 --- a/storage/browser/test/mock_blob_url_request_context.cc +++ b/storage/browser/test/mock_blob_url_request_context.cc
@@ -32,10 +32,10 @@ const std::string& data) : blob_id_(blob_id), context_(request_context.blob_storage_context()) { DCHECK(context_); - storage::BlobDataBuilder blob_builder(blob_id_); + auto blob_builder = std::make_unique<storage::BlobDataBuilder>(blob_id_); if (!data.empty()) - blob_builder.AppendData(data); - handle_ = context_->AddFinishedBlob(&blob_builder); + blob_builder->AppendData(data); + handle_ = context_->AddFinishedBlob(std::move(blob_builder)); } ScopedTextBlob::~ScopedTextBlob() = default;
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 0a8f099..8e22eaa8 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -1161,6 +1161,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "vr_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "vr_pixeltests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "webkit_unit_tests" }, { @@ -1899,6 +1911,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "vr_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "vr_pixeltests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "webkit_unit_tests" }, { @@ -2379,6 +2403,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "vr_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "vr_pixeltests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "webkit_unit_tests" }, {
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter index 0cae3f6af..340188f 100644 --- a/testing/buildbot/filters/fuchsia.base_unittests.filter +++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -38,17 +38,17 @@ # These tests are occasionally flaking. See https://crbug.com/738275. Please be # pretty confident you've fixed their rarely-flakiness before re-enabling. --AllModes/TaskSchedulerSingleThreadTaskRunnerManagerCommonTest.* +#AllModes/TaskSchedulerSingleThreadTaskRunnerManagerCommonTest.* -AllocationRegisterTest.InsertRemoveRandomOrder -ConditionVariableTest.MultiThreadConsumerTest -MemoryPeakDetectorTest.StdDev -MemoryPeakDetectorTest.Throttle -ObserverListThreadSafeTest.CrossThreadObserver --OneTraitsExecutionModePair/TaskSchedulerImplTest.* --ProcessUtilTest.DelayedTermination --ProcessUtilTest.ImmediateTermination +#OneTraitsExecutionModePair/TaskSchedulerImplTest.* +#ProcessUtilTest.DelayedTermination +#ProcessUtilTest.ImmediateTermination -TraceCategoryTest.ThreadRaces --MemoryDumpManagerTest.PostTaskForSequencedTaskRunner +#MemoryDumpManagerTest.PostTaskForSequencedTaskRunner # This test expects a task to complete no later than 250ms after it's expected # to, but that's easily a poor assumption when running on QEMU without hardware
diff --git a/testing/buildbot/filters/fuchsia.content_unittests.filter b/testing/buildbot/filters/fuchsia.content_unittests.filter index 9d3504af..24e8103d 100644 --- a/testing/buildbot/filters/fuchsia.content_unittests.filter +++ b/testing/buildbot/filters/fuchsia.content_unittests.filter
@@ -60,6 +60,8 @@ # Flaky, https://crbug.com/784449. -WebContentsAudioInputStreamTest.MirroringOneStreamAfterTargetChange* -# Flaky, https://crbug.com/802375. +# Flaky, https://crbug.com/802375 and https://crbug.com/776424. -RenderWidgetHostViewAuraOverscrollTest.GestureScrollDebounceTimerOverscroll -RenderWidgetHostViewAuraOverscrollTest.TouchGestureEndDispatchedAfterOverscrollComplete +-RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest.TimerBasedWheelEventPhaseInfo +-RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest.TimerBasedWheelEventPhaseInfo
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 2fd39926..4ed806b 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3702,6 +3702,8 @@ # chromium.fyi 'Chromium Win 10 GCE Tests', 'Out of Process Profiling Android', + # chromium.sandbox + 'Linux Tests SANDBOX', # chromium.win 'Win 7 Tests x64 (1)', 'Win10 Tests x64', @@ -3755,6 +3757,8 @@ 'Chromium Win 10 GCE Tests', 'Out of Process Profiling Android', 'VR Linux', + # chromium.sandbox + 'Linux Tests SANDBOX', # chromium.win 'Win 7 Tests x64 (1)', 'Win10 Tests x64',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 2d87759..702bdd8d 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -1878,6 +1878,7 @@ 'site_isolation_chromium_gtests', 'site_isolation_chromium_linux_gtests', 'viz_gtests', + 'vr_platform_specific_non_clang_win_chromium_gtests', ], 'linux_chromeos_dbg_gtests': [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index 1df01af..123340a 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -241,3 +241,10 @@ # Started failing @ r529490 Bug(none) virtual/layout_ng/fast/inline/positioned-object-between-replaced-elements.html [ Failure ] + +# http://crbug.com/803958: Tests failing on bot but not in local checkout. +crbug.com/803958 external/wpt/websockets/cookies/001.html?wss [ Failure ] +crbug.com/803958 external/wpt/websockets/cookies/002.html?wss [ Failure ] +crbug.com/803958 external/wpt/websockets/cookies/003.html?wss [ Failure ] +crbug.com/803958 external/wpt/websockets/cookies/007.html [ Failure ] +crbug.com/803958 external/wpt/websockets/cookies/007.html?wss [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175 index 0ee1309..c66f51b 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v175
@@ -91,7 +91,6 @@ crbug.com/771643 css3/filters/filterRegions.html [ Failure ] crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ] crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ] -crbug.com/771643 fast/forms/focus-on-control-with-zero-size.html [ Crash ] crbug.com/771643 fast/reflections/reflection-masks-outset.html [ Pass Failure ] crbug.com/771643 fast/replaced/width100percent-textarea.html [ Failure ] crbug.com/771643 http/tests/misc/slow-loading-mask.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 2d77006..86cb17a 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -308,6 +308,28 @@ #### external/wpt/css/css-position crbug.com/752022 external/wpt/css/css-position/position-sticky-offset-overflow.html [ Failure ] +crbug.com/702927 external/wpt/css/css-position/position-sticky-table-tr-top.html [ Failure ] +crbug.com/702927 external/wpt/css/css-position/position-sticky-table-tr-bottom.html [ Failure ] +crbug.com/702927 external/wpt/css/css-position/position-sticky-table-tfoot-bottom.html [ Failure ] +crbug.com/702927 external/wpt/css/css-position/position-sticky-table-thead-top.html [ Failure ] +crbug.com/702927 external/wpt/css/css-position/position-sticky-parsing.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tbody-left-absolute-child.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tbody-left.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tbody-top-absolute-child.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tbody-top.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tfoot-left-absolute-child.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tfoot-left.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tfoot-top-absolute-child.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tfoot-top.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-thead-left-absolute-child.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-thead-left.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-thead-top-absolute-child.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-thead-top.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tr-left-absolute-child.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tr-left.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tr-top-absolute-child.html [ Failure ] +crbug.com/417223 external/wpt/css/css-position/position-relative-table-tr-top.html [ Failure ] + #### crbug.com/783229 overflow crbug.com/724697 overflow/overflow-basic-002.html [ Failure ] @@ -2431,7 +2453,7 @@ crbug.com/664450 http/tests/devtools/console/console-on-animation-worklet.js [ Skip ] -# Fail when run with --enable-wptserve due to data: URLs treated as cross-origin: (crbug.com/508730) +# Fail due to data: URLs treated as cross-origin: (crbug.com/508730) crbug.com/508730 crbug.com/472300 external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html [ Failure ] crbug.com/508730 crbug.com/472300 external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html [ Failure ] crbug.com/508730 crbug.com/472300 external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html [ Failure ] @@ -2441,18 +2463,9 @@ crbug.com/508730 crbug.com/472300 external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html [ Failure ] crbug.com/508730 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html [ Failure ] -# Fail when run with --enable-wptserve: (crbug.com/508734) -crbug.com/508734 external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html [ Failure ] -crbug.com/508734 external/wpt/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3.html [ Failure ] -crbug.com/508734 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Pass Failure Timeout ] +crbug.com/803951 external/wpt/html/browsers/history/the-location-interface/reload_post_1.html [ Failure Timeout ] -# Fail differently when run with --enable-wptserve: (crbug.com/508728) -crbug.com/508728 crbug.com/664268 external/wpt/html/browsers/history/the-location-interface/reload_post_1.html [ Failure Timeout ] - -crbug.com/508728 external/wpt/workers/Worker_cross_origin_security_err.htm [ Timeout ] - -# This test needs to be updated: fails because it expects showModalDialog and some other APIs. -crbug.com/508728 external/wpt/html/browsers/the-window-object/security-window/window-security.html [ Failure ] +crbug.com/651778 external/wpt/workers/Worker_cross_origin_security_err.htm [ Timeout ] # This test requires a special browser flag and seems not suitable for a wpt test, see bug. crbug.com/691944 external/wpt/service-workers/service-worker/update-after-oneday.https.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 1ecfb30..23182f39 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -337343,7 +337343,7 @@ "manual" ], "presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html": [ - "1830e4420c668b77dbd835912f518920743c5592", + "a1ca78e036505bae01d207a0810e84c465586bd2", "manual" ], "presentation-api/receiving-ua/cache.txt": [ @@ -337383,11 +337383,11 @@ "support" ], "presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html": [ - "84f37932fc911d5dbf692b42569b564ebf9b8e7d", + "68f0a929fa97a9dce8566237e538f769860c14fe", "support" ], "presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua_child.html": [ - "9320e6d42c5b2856934ff1d80d89276a010b48f1", + "d0a87a3ca4dbb9bb706133ee3ca638be929e56d4", "support" ], "presentation-api/receiving-ua/support/PresentationReceiver_unreached_receiving-ua.html": [ @@ -361499,7 +361499,7 @@ "testharness" ], "xhr/xmlhttprequest-sync-default-feature-policy.sub.html": [ - "f83a057d1874e5e633c4529d3fac91249de652b3", + "33c86511fb9047346a9d28546b89b64fe323fde6", "testharness" ], "xhr/xmlhttprequest-sync-not-hang-scriptloader-subframe.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3-expected.txt new file mode 100644 index 0000000..3c78835 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Restoring window.name on cross-origin history traversal Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt index 8721942..b272766 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt
@@ -1,30 +1,24 @@ -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html -Blocked access to external URL http://www1.127.0.0.1:8001/html/browsers/origin/cross-origin-objects/frame.html This is a testharness.js-based test. -FAIL Basic sanity-checking assert_equals: Need to run the top-level test from domain 127.0.0.1 expected "127.0.0.1" but got "web-platform.test" -FAIL Only whitelisted properties are accessible cross-origin assert_throws: Should throw when accessing speechSynthesis on Window function "function () { C[prop]; }" did not throw +PASS Basic sanity-checking +PASS Only whitelisted properties are accessible cross-origin PASS [[GetPrototypeOf]] should return null -FAIL [[SetPrototypeOf]] should throw assert_throws: proto set on cross-origin Location function "function () { C.location.__proto__ = new Object(); }" did not throw +FAIL [[SetPrototypeOf]] should return false assert_throws: proto setter |call| on cross-origin Window function "function() { protoSetter.call(C, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") PASS [[IsExtensible]] should return true for cross-origin objects -FAIL [[PreventExtensions]] should throw for cross-origin objects assert_throws: preventExtensions on cross-origin Window should throw function "function () { Object.preventExtensions(C) }" did not throw +FAIL [[PreventExtensions]] should throw for cross-origin objects assert_throws: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(C) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") FAIL [[GetOwnProperty]] - Properties on cross-origin objects should be reported |own| Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. -FAIL [[GetOwnProperty]] - Property descriptors for cross-origin properties should be set up correctly assert_equals: property descriptor for location should be non-enumerable expected false but got true +FAIL [[GetOwnProperty]] - Property descriptors for cross-origin properties should be set up correctly assert_equals: property descriptor for 0 should be enumerable expected true but got false PASS [[Delete]] Should throw on cross-origin objects -FAIL [[DefineOwnProperty]] Should throw for cross-origin objects assert_throws: Can't define cross-origin value property length function "function () { Object.defineProperty(obj, prop, valueDesc); }" did not throw -PASS [[Enumerate]] should return an empty iterator -FAIL [[OwnPropertyKeys]] should return all properties from cross-origin objects assert_array_equals: Object.getOwnPropertyNames() gives the right answer for cross-origin Window lengths differ, expected 863 got 13 +PASS [[DefineOwnProperty]] Should throw for cross-origin objects +FAIL Can only enumerate safelisted enumerable properties assert_equals: Enumerate all enumerable safelisted cross-origin Window properties expected 2 but got 0 +FAIL [[OwnPropertyKeys]] should return all properties from cross-origin objects assert_array_equals: Object.getOwnPropertyNames() gives the right answer for cross-origin Window lengths differ, expected 15 got 13 +FAIL [[OwnPropertyKeys]] should return the right symbol-named properties for cross-origin objects assert_array_equals: Object.getOwnPropertySymbols() should return the three symbol-named properties that are exposed on a cross-origin Window lengths differ, expected 3 got 0 +FAIL [[OwnPropertyKeys]] should place the symbols after the property names after the subframe indices assert_array_equals: Reflect.ownKeys should start with the indices exposed on the cross-origin window. property 0, expected "0" but got "window" PASS A and B jointly observe the same identity for cross-origin Window and Location PASS Cross-origin functions get local Function.prototype FAIL Cross-origin Window accessors get local Function.prototype Cannot read property 'name' of undefined FAIL Same-origin observers get different functions for cross-origin objects assert_true: same-origin Window functions get their own object expected true got false FAIL Same-origin observers get different accessors for cross-origin Window assert_true: different Window accessors per-incumbent script settings object expected true got false -FAIL Same-origin observers get different accessors for cross-origin Location assert_true: different Location accessors per-incumbent script settings object expected true got false +FAIL Same-origin observers get different accessors for cross-origin Location Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. +FAIL {}.toString.call() does the right thing on cross-origin objects assert_equals: expected "[object Object]" but got "[object Location]" Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/security-window/window-security-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/security-window/window-security-expected.txt index a5483c8..8cc8ac9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/security-window/window-security-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/security-window/window-security-expected.txt
@@ -1,998 +1,118 @@ This is a testharness.js-based test. +Found 126 tests; 125 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Window Security testing -FAIL A SecurityError exception must be thrown when window.applicationCache is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.devicePixelRatio is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.document is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.external is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.frameElement is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.history is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.innerWidth is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.innerHeight is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.locationbar is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.localStorage is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.menubar is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.name is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.navigator is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onabort is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onafterprint is accessed from a different origin. assert_true: window.onafterprint should exist. expected true got false -FAIL A SecurityError exception must be thrown when window.onbeforeprint is accessed from a different origin. assert_true: window.onbeforeprint should exist. expected true got false -FAIL A SecurityError exception must be thrown when window.onbeforeunload is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onblur is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.oncancel is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.oncanplay is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.oncanplaythrough is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onchange is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onclick is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onclose is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.oncontextmenu is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.oncuechange is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondblclick is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondrag is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondragend is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondragenter is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondragleave is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondragover is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondragstart is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondrop is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ondurationchange is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onemptied is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onended is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onerror is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onfocus is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onhashchange is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.oninput is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.oninvalid is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onkeydown is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onkeypress is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onkeyup is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onload is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onloadeddata is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onloadedmetadata is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onloadstart is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onmessage is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onmousedown is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onmousemove is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onmouseout is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onmouseover is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onmouseup is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onmousewheel is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onoffline is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ononline is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onpause is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onplay is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onplaying is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onpagehide is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onpageshow is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onpopstate is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onprogress is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onratechange is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onreset is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onresize is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onscroll is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onseeked is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onseeking is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onselect is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onshow is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onstalled is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onstorage is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onsubmit is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onsuspend is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.ontimeupdate is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onunload is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onvolumechange is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.onwaiting is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.pageXOffset is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.pageYOffset is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.personalbar is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.screen is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.scrollbars is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.statusbar is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.status is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.screenX is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.screenY is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.sessionStorage is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.toolbar is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.alert is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.clearInterval is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.clearTimeout is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.confirm is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.getComputedStyle is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.getSelection is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.matchMedia is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.moveBy is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.moveTo is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.open is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.print is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.prompt is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.resizeTo is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.resizeBy is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.scroll is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.scrollTo is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.scrollBy is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.setInterval is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.setTimeout is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw -FAIL A SecurityError exception must be thrown when window.showModalDialog is accessed from a different origin. assert_true: window.showModalDialog should exist. expected true got false -FAIL A SecurityError exception must be thrown when window.stop is accessed from a different origin. assert_throws: A SecurityError exception should be thrown. function "function () { - if (item.isMethod) - if (item.args) - fr.contentWindow[item.name](item.args[0], item.args[1]); - else - fr.contentWindow[item.name](); - else - fr.contentWindow[item.name]; - }" did not throw +PASS A SecurityError exception must be thrown when window.applicationCache is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.devicePixelRatio is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.document is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.external is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.frameElement is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.history is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.innerWidth is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.innerHeight is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.locationbar is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.localStorage is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.menubar is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.name is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.navigator is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onabort is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onafterprint is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onbeforeprint is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onbeforeunload is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onblur is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.oncancel is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.oncanplay is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.oncanplaythrough is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onchange is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onclick is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onclose is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.oncontextmenu is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.oncuechange is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondblclick is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondrag is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondragend is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondragenter is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondragleave is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondragover is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondragstart is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondrop is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ondurationchange is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onemptied is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onended is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onerror is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onfocus is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onhashchange is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.oninput is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.oninvalid is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onkeydown is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onkeypress is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onkeyup is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onload is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onloadeddata is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onloadedmetadata is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onloadstart is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onmessage is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onmousedown is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onmousemove is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onmouseout is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onmouseover is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onmouseup is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onmousewheel is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onoffline is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ononline is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onpause is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onplay is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onplaying is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onpagehide is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onpageshow is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onpopstate is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onprogress is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onratechange is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onreset is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onresize is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onscroll is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onseeked is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onseeking is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onselect is accessed from a different origin. +FAIL A SecurityError exception must be thrown when window.onshow is accessed from a different origin. assert_true: window.onshow should exist. expected true got false +PASS A SecurityError exception must be thrown when window.onstalled is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onstorage is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onsubmit is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onsuspend is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.ontimeupdate is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onunload is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onvolumechange is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.onwaiting is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.pageXOffset is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.pageYOffset is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.personalbar is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.screen is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.scrollbars is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.statusbar is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.status is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.screenX is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.screenY is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.sessionStorage is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.toolbar is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.alert is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.clearInterval is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.clearTimeout is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.confirm is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.getComputedStyle is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.getSelection is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.matchMedia is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.moveBy is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.moveTo is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.open is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.print is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.prompt is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.resizeTo is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.resizeBy is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.scroll is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.scrollTo is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.scrollBy is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.setInterval is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.setTimeout is accessed from a different origin. +PASS A SecurityError exception must be thrown when window.stop is accessed from a different origin. PASS A SecurityError exception should not be thrown when window.closed is accessed from a different origin. PASS A SecurityError exception should not be thrown when window.frames is accessed from a different origin. PASS A SecurityError exception should not be thrown when window.length is accessed from a different origin.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01-expected.txt new file mode 100644 index 0000000..7ec33099b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +PASS Should get an error event for a 404 error. +PASS Should get an error event for an unsupported URL. +FAIL Should get an error event for a text/plain response. assert_unreached: load event should not be fired Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html index 67b8c43..96fc6f3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html
@@ -25,8 +25,14 @@ } }); - let connection, db; + let connection; const presentBtn = document.getElementById('presentBtn'); + + const dbName = { + controller: 'db-presentation-api-controlling-ua', + receiver: 'db-presentation-api-receiving-ua' + }; + const main = () => { promise_test(t => { presentBtn.disabled = true; @@ -38,14 +44,14 @@ notice.parentNode.removeChild(notice); stash.stop(); - //history.back(); + // history.back(); document.cookie = 'PresentationApiTest=true; Expires=' + new Date().toUTCString(); sessionStorage.removeItem('presentation_api_test'); localStorage.removeItem('presentation_api_test'); - if (db) - db.close(); - indexedDB.deleteDatabase(dbName); + Object.values(dbName).forEach(name => { + indexedDB.deleteDatabase(name); + }); if (connection) { connection.onconnect = () => { connection.terminate(); }; @@ -75,28 +81,12 @@ sessionStorage.setItem(storageName, storageValue); localStorage.setItem(storageName, storageValue); - const dbName = 'db-presentation-api'; - const storeName = 'store-controlling-ua'; - const storeData = { - id: 'controller', - data: 'controlling user agent' - }; const openIndexedDB = () => { if ('indexedDB' in window) { - const dbReq = indexedDB.open(dbName, 1); - return new Promise((resolve, reject) => { - dbReq.onupgradeneeded = () => { - db = dbReq.result; - const store = db.createObjectStore(storeName, { keyPath: 'id' }); - store.add(storeData); - }; - dbReq.onsuccess = () => { - db = dbReq.result; - db.close(); - db = null; - resolve(); - }; - dbReq.onerror = reject; + const req = indexedDB.open(dbName.controller, 1); + const eventWatcher = new EventWatcher(t, req, 'upgradeneeded'); + return eventWatcher.wait_for('upgradeneeded').then(evt => { + evt.target.result.close(); }); } else @@ -115,6 +105,8 @@ }; reg.active.postMessage('', [channel.port2]); } + else + resolve([]); }); }); }; @@ -153,29 +145,19 @@ // Indexed Database const checkIndexedDB = t => { if ('indexedDB' in window) { - const message = 'Indexed Database is not shared with a receiving user agent.'; - let req = indexedDB.open(dbName, 1), store; - let eventWatcher = new EventWatcher(t, req, 'success'); - return eventWatcher.wait_for('success').then(() => { - db = req.result; - const transaction = db.transaction(storeName, 'readwrite'); - store = transaction.objectStore(storeName); - req = store.openCursor(); - eventWatcher = new EventWatcher(t, req, 'success'); - return eventWatcher.wait_for('success'); - }).then(() => { - assert_true(req.result instanceof IDBCursorWithValue, message); - const cursor = req.result; - const item = cursor.value; - assert_equals(item.id, storeData.id, message); - assert_equals(item.data, storeData.data, message); - cursor.continue(); - return eventWatcher.wait_for('success'); - }).then(() => { - assert_equals(req.result, null, message); - db.close(); - db = null; - }); + const req = indexedDB.open(dbName.receiver); + const upgradeneededWatcher = new EventWatcher(t, req, 'upgradeneeded'); + const successWatcher = new EventWatcher(t, req, 'success'); + return Promise.race([ + upgradeneededWatcher.wait_for('upgradeneeded').then(evt => { + evt.target.result.close(); + }), + successWatcher.wait_for('success').then(evt => { + evt.target.result.close(); + // This would fail if the database created by the receiving UA is visible to the controlling UA + assert_unreached('Indexed Database is not shared with a receiving user agent.'); + }) + ]); } else return Promise.resolve(); @@ -231,6 +213,7 @@ return request.start().then(c => { connection = c; enableTimeout(); + // This Promise.race will be rejected if a receiving side terminates/closes the connection when window.close() is invoked return Promise.race([ openIndexedDB() @@ -249,7 +232,7 @@ // Check accessibility to window clients before terminating a presentation return getClientUrls().then(urls => { assert_true(urls.length === clientUrls.length && urls.every((value, index) => { return clientUrls[index] === value}), - 'A window client in a receiving user agent is not accessible to a service worker on a controlling user agent.') + 'A window client in a receiving user agent is not accessible to a service worker on a controlling user agent.'); const eventWatcher = new EventWatcher(t, connection, 'terminate'); connection.terminate(); return eventWatcher.wait_for('terminate');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html index 8edb88e..53f76014 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html +++ b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua.html
@@ -37,6 +37,11 @@ const notice = document.getElementById('notice'); const modal = document.getElementById('modal'); + const dbName = { + controller: 'db-presentation-api-controlling-ua', + receiver: 'db-presentation-api-receiving-ua' + }; + promise_test(t => { t.add_cleanup(() => { document.cookie = cookieName + '=False;Expires=' + new Date().toUTCString(); @@ -46,9 +51,10 @@ sessionStorage.removeItem(storageNameChild); localStorage.removeItem(storageNameChild); - if (db) - db.close(); - indexedDB.deleteDatabase(dbName); + Object.values(dbName).forEach(name => { + indexedDB.deleteDatabase(name); + }); + if ('serviceWorker' in navigator) { navigator.serviceWorker.getRegistrations().then(registrations => { return Promise.all(registrations.map(reg => reg.unregister())); @@ -97,37 +103,27 @@ assert_equals(document.cookie, '', 'A cookie store is set to an empty store.') // Indexed Database - const dbName = 'db-presentation-api'; - const storeName = 'store-controlling-ua'; - const storeData = { - parent: { id: 'parent', data: 'receiving user agent' }, - child: { id: 'child', data: 'nested browsing context' } - }; - let db; const checkIndexedDB = () => { if ('indexedDB' in window) { - let req = indexedDB.open(dbName, 1), store; - let eventWatcher = new EventWatcher(t, req, ['upgradeneeded', 'success']); - return eventWatcher.wait_for('upgradeneeded').then(() => { - db = req.result; - const store = db.createObjectStore(storeName, { keyPath: 'id' }); - return eventWatcher.wait_for('success'); - }).then(() => { - db = req.result; - const transaction = db.transaction(storeName, 'readwrite'); - store = transaction.objectStore(storeName); - req = store.openCursor(); - eventWatcher = new EventWatcher(t, req, 'success'); - return eventWatcher.wait_for('success'); - }).then(() => { - assert_equals(req.result, null, 'Indexed Database is set to an empty storage.'); - req = store.put(storeData.parent); - eventWatcher = new EventWatcher(t, req, 'success'); - return eventWatcher.wait_for('success'); - }).then(() => { - db.close(); - db = null; - }); + // The test would fail when the database is already created by the controlling UA + const req = indexedDB.open(dbName.controller); + const upgradeneededWatcher = new EventWatcher(t, req, 'upgradeneeded'); + const successWatcher = new EventWatcher(t, req, 'success'); + return Promise.race([ + upgradeneededWatcher.wait_for('upgradeneeded').then(evt => { + evt.target.result.close(); + const req = indexedDB.open(dbName.receiver, 2); + const eventWatcher = new EventWatcher(t, req, 'upgradeneeded'); + return eventWatcher.wait_for('upgradeneeded'); + }).then(evt => { + evt.target.result.close(); + }), + successWatcher.wait_for('success').then(evt => { + evt.target.result.close(); + // This would fail if the database created by the controlling UA is visible to the receiving UA + assert_unreached('Indexed Database is set to an empty storage.'); + }) + ]); } else return Promise.resolve(); @@ -253,33 +249,24 @@ // Indexed Database const checkUpdatedIndexedDB = () => { if ('indexedDB' in window) { - let req = indexedDB.open(dbName, 1), store; - let eventWatcher = new EventWatcher(t, req, 'success'); message = 'Indexed Database is shared by top-level and nested browsing contexts.'; - const checkItem = event => { - assert_true(event.target.result instanceof IDBCursorWithValue, message); - const cursor = event.target.result; - const item = cursor.value; - assert_equals(storeData[item.id].data, item.data, message); - delete storeData[item.id] - cursor.continue(); - return eventWatcher.wait_for('success'); - }; - return eventWatcher.wait_for('success').then(() => { - db = req.result; - const transaction = db.transaction(storeName, 'readwrite'); - store = transaction.objectStore(storeName); - req = store.openCursor(); - eventWatcher = new EventWatcher(t, req, 'success'); - return eventWatcher.wait_for('success'); - }).then(checkItem) - .then(checkItem) - .then(event => { - assert_equals(event.target.result, null, message); - assert_equals(Object.keys(storeData).length, 0, message); - db.close(); - db = null; - }); + const req = indexedDB.open(dbName.receiver); + const upgradeneededWatcher = new EventWatcher(t, req, 'upgradeneeded'); + const successWatcher = new EventWatcher(t, req, 'success'); + return Promise.race([ + upgradeneededWatcher.wait_for('upgradeneeded').then(evt => { + evt.target.result.close(); + // Check if the version of the database is upgraded to 3 by the nested browsing context + assert_unreached(message); + }), + successWatcher.wait_for('success').then(evt => { + const db = evt.target.result; + const version = db.version; + db.close(); + // Check if the version of the database is upgraded to 3 by the nested browsing context + assert_equals(version, 3, message); + }) + ]); } else return Promise.resolve();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua_child.html b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua_child.html index aa0e191..2f67f7f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua_child.html +++ b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/receiving-ua/support/PresentationReceiver_create_receiving-ua_child.html
@@ -44,7 +44,7 @@ modal.textContent = 'confirm()'; confirm(message); modal.textContent = 'print()'; - //print(); + print(); modal.textContent = 'prompt()'; prompt(message); notice.style.display = 'none'; @@ -60,36 +60,36 @@ assert_equals(document.cookie, 'PresentationApiTest=Receiving-UA', 'A cookie store is shared by top-level and nested browsing contexts.'); // Indexed Database - let db; + const dbName = 'db-presentation-api-receiving-ua'; const checkIndexedDB = () => { if ('indexedDB' in window) { message = 'Indexed Database is shared by top-level and nested browsing contexts.'; - let req = indexedDB.open('db-presentation-api', 1), store; - let eventWatcher = new EventWatcher(t, req, 'success'); - return eventWatcher.wait_for('success').then(() => { - db = req.result; - const transaction = db.transaction('store-controlling-ua', 'readwrite'); - store = transaction.objectStore('store-controlling-ua'); - req = store.openCursor(); - eventWatcher = new EventWatcher(t, req, 'success'); - return eventWatcher.wait_for('success'); - }).then(() => { - assert_true(req.result instanceof IDBCursorWithValue, message); - const cursor = req.result; - const item = cursor.value; - assert_equals(item.id, 'parent', message); - assert_equals(item.data, 'receiving user agent', message); - cursor.continue(); - return eventWatcher.wait_for('success'); - }).then(() => { - assert_equals(req.result, null, message); - req = store.put({ id: 'child', data: 'nested browsing context' }); - eventWatcher = new EventWatcher(t, req, 'success'); - return eventWatcher.wait_for('success'); - }).then(() => { - db.close(); - db = null; - }); + + const req = indexedDB.open(dbName); + const upgradeneededWatcher = new EventWatcher(t, req, 'upgradeneeded'); + const successWatcher = new EventWatcher(t, req, 'success'); + return Promise.race([ + upgradeneededWatcher.wait_for('upgradeneeded').then(evt => { + evt.target.result.close(); + // This would fail if the database is not created by the top-level browsing context + assert_unreached(message); + }), + successWatcher.wait_for('success').then(evt => { + evt.target.result.close(); + const db = evt.target.result; + const version = db.version; + db.close(); + // Check if the version of the database is 2 as specified by the top-level browsing context + assert_equals(version, 2, message); + + // Upgrade the version + const req = indexedDB.open(dbName, 3); + const eventWatcher = new EventWatcher(t, req, 'upgradeneeded'); + return eventWatcher.wait_for('upgradeneeded'); + }).then(evt => { + evt.target.result.close(); + }) + ]); } else return Promise.resolve();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/server-timing/cross_origin.html b/third_party/WebKit/LayoutTests/external/wpt/server-timing/cross_origin.html new file mode 100644 index 0000000..80035888 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/server-timing/cross_origin.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<head> + <meta charset='utf-8' /> + <script src="/resources/testharness.js"></script> + <script src='/resources/testharnessreport.js'></script> + <script src="/common/performance-timeline-utils.js"></script> + <script> + setup({explicit_done: true}) + + const {location: {href}} = document + const urls = {} + urls['same-origin'] = `${href.substring(0, href.lastIndexOf('/'))}/resources/blue.png` + urls['cross-origin'] = urls['same-origin'].replace('://', '://www.') + Object.keys(urls).forEach(function(key) { + const img = document.createElement('img') + img.src = urls[key] + document.getElementsByTagName('script')[0].parentNode.appendChild(img) + }) + + window.addEventListener('load', function() { + function assertServerTimingEntries(url, expectedEntryCount) { + test_equals(performance.getEntriesByName(url)[0].serverTiming.length, + expectedEntryCount, + `Expected entry count for ${url}: ${expectedEntryCount}`) + } + assertServerTimingEntries(urls['same-origin'], 1) + assertServerTimingEntries(urls['cross-origin'], 0) + done() + }) + </script> +</head>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-blob-in-workers.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-blob-in-workers.html index 128141d..98f1f0e0 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-blob-in-workers.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-blob-in-workers.html
@@ -10,8 +10,8 @@ description('Test race condition for createImageBitmap from blob in workers and main.'); -var imgWidth = 20; -var imgHeight = 20; +var imgWidth = 300; +var imgHeight = 150; var numOfBitmaps = 5; var bitmapArray = [];
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-drawImage-video.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-drawImage-video.html index 502666b..b41e698 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-drawImage-video.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-drawImage-video.html
@@ -133,17 +133,17 @@ ctx1.drawImage(video, 0, 0); compareTwoCanvases(0, 0, 352, 288, ctx, ctx1); - // shrunk to (0, 0), (100, 100) + // shrunk to (0, 0), (500, 500) clearContext(ctx, ctx1); - ctx.drawImage(imageBitmap, 0, 0, 100, 100); - ctx1.drawImage(video, 0, 0, 100, 100); - compareTwoCanvases(0, 0, 100, 100, ctx, ctx1); + ctx.drawImage(imageBitmap, 0, 0, 500, 500); + ctx1.drawImage(video, 0, 0, 500, 500); + compareTwoCanvases(0, 0, 500, 500, ctx, ctx1); - // shrunk to (100, 100), (250, 200) + // shrunk to (100, 100), (380, 380) clearContext(ctx, ctx1); - ctx.drawImage(imageBitmap, 100, 100, 150, 100); - ctx1.drawImage(video, 100, 100, 150, 100); - compareTwoCanvases(100, 100, 150, 100, ctx, ctx1); + ctx.drawImage(imageBitmap, 100, 100, 380, 380); + ctx1.drawImage(video, 100, 100, 380, 380); + compareTwoCanvases(100, 100, 380, 380, ctx, ctx1); // black should be drawn to (100, 100), (200, 200) clearContext(ctx, ctx1);
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-from-canvas-toBlob.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-from-canvas-toBlob.html index 99da913b..0546cd7e 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-from-canvas-toBlob.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-from-canvas-toBlob.html
@@ -11,15 +11,15 @@ var canvas1 = document.createElement("canvas"); var ctx1 = canvas1.getContext("2d"); ctx1.fillStyle = "#FF0000"; -ctx1.fillRect(0, 0, 150, 75); +ctx1.fillRect(0, 0, 300, 150); var newImg = new Image(); newImg.onload = function() { var canvas3 = document.createElement("canvas"); var ctx3 = canvas3.getContext("2d"); - ctx3.drawImage(newImg, 0, 0, 150, 75); + ctx3.drawImage(newImg, 0, 0, 300, 150); - imageData3 = ctx3.getImageData(0, 0, 150, 75).data; + imageData3 = ctx3.getImageData(0, 0, 300, 150).data; var imageMatched = true; for (var i = 1; i < imageData2.length; i++) { if (imageData2[i] != imageData3[i]) { @@ -38,8 +38,8 @@ createImageBitmap(blob).then(imageBitmap => { var canvas2 = document.createElement("canvas"); var ctx2 = canvas2.getContext("2d"); - ctx2.drawImage(imageBitmap, 0, 0, 150, 75); - imageData2 = ctx2.getImageData(0, 0, 150, 75).data; + ctx2.drawImage(imageBitmap, 0, 0, 300, 150); + imageData2 = ctx2.getImageData(0, 0, 300, 150).data; url = URL.createObjectURL(blob); newImg.src = url; });
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-video-resize.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-video-resize.html index 632f3fd..3593d77 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-video-resize.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-video-resize.html
@@ -12,14 +12,14 @@ return ctx; } -function checkLowResult(imageBitmap, video, sx, sy, sw, sh) +function checkLowResult(imageBitmap, bw, bh, video, sx, sy, sw, sh) { - var ctx1 = createNewCanvas(50, 50); - var ctx2 = createNewCanvas(50, 50); + var ctx1 = createNewCanvas(bw, bh); + var ctx2 = createNewCanvas(bw, bh); ctx1.drawImage(imageBitmap, 0, 0); - ctx2.drawImage(video, sx, sy, sw, sh, 0, 0, 40, 30); - var data1 = ctx1.getImageData(0, 0, 50, 50).data; - var data2 = ctx2.getImageData(0, 0, 50, 50).data; + ctx2.drawImage(video, sx, sy, sw, sh, 0, 0, bw, bh); + var data1 = ctx1.getImageData(0, 0, bw, bh).data; + var data2 = ctx2.getImageData(0, 0, bw, bh).data; var dataMatched = true; for (var i = 0; i < data1.length; i++) { // data1[i] is strictly the same as data2[i] on software rendering. @@ -34,18 +34,14 @@ function generateTest() { + bitmapWidth = video.videoWidth/2; + bitmapHeight = video.videoHeight/2; return Promise.all([ - createImageBitmap(video, {resizeWidth: 40, resizeHeight: 30, resizeQuality: "high"}), - createImageBitmap(video, {resizeWidth: 40, resizeHeight: 30, resizeQuality: "medium"}), - createImageBitmap(video, {resizeWidth: 40, resizeHeight: 30, resizeQuality: "low"}), - createImageBitmap(video, {resizeWidth: 40, resizeHeight: 30, resizeQuality: "pixelated"}), - createImageBitmap(video, 50, 50, 160, 120, {resizeWidth: 40, resizeHeight: 30, resizeQuality: "high"}), - createImageBitmap(video, 50, 50, 160, 120, {resizeWidth: 40, resizeHeight: 30, resizeQuality: "medium"}), - createImageBitmap(video, 50, 50, 160, 120, {resizeWidth: 40, resizeHeight: 30, resizeQuality: "low"}), - createImageBitmap(video, 50, 50, 160, 120, {resizeWidth: 40, resizeHeight: 30, resizeQuality: "pixelated"}), - ]).then(t.step_func_done(([noCropHigh, noCropMedium, noCropLow, noCropPixelated, cropHigh, cropMedium, cropLow, cropPixelated]) => { - checkLowResult(noCropLow, video, 0, 0, video.videoWidth, video.videoHeight); - checkLowResult(cropLow, video, 50, 50, 160, 120); + createImageBitmap(video, {resizeWidth: bitmapWidth, resizeHeight: bitmapHeight, resizeQuality: "low"}), + createImageBitmap(video, 10, 10, bitmapWidth, bitmapHeight, {resizeWidth: bitmapWidth, resizeHeight: bitmapHeight, resizeQuality: "low"}), + ]).then(t.step_func_done(([noCropLow, cropLow]) => { + checkLowResult(noCropLow, bitmapWidth, bitmapHeight, video, 0, 0, video.videoWidth, video.videoHeight); + checkLowResult(cropLow, bitmapWidth, bitmapHeight, video, 10, 10, bitmapWidth, bitmapHeight); }), t.step_func_done(function() { assert_true(false, 'Promise rejected'); }));
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/downsample-quality.html b/third_party/WebKit/LayoutTests/fast/canvas/downsample-quality.html index ed2f31d6..4c5e56f7 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/downsample-quality.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/downsample-quality.html
@@ -3,7 +3,6 @@ <script> // This test should show two side-by-side thin circle outlines // with good visual quality, i.e. no aliasing from image downsampling. -// Both circles should look identical. if (window.testRunner) { testRunner.dumpAsTextWithPixelResults();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/dynamic-navigator-frame-attach-detach.js b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/dynamic-navigator-frame-attach-detach.js index 90078397..66858e87 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/dynamic-navigator-frame-attach-detach.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/dynamic-navigator-frame-attach-detach.js
@@ -8,7 +8,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.markStep('dumpInitialNavigator');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-frame-attach-detach.js b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-frame-attach-detach.js index ee371af..835b85a4 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-frame-attach-detach.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-frame-attach-detach.js
@@ -7,7 +7,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.markStep('dumpInitialNavigator');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-frame-navigate.js b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-frame-navigate.js index 53f4278..d081ac72 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-frame-navigate.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-frame-navigate.js
@@ -7,7 +7,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.markStep('dumpInitialNavigator');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-main-frame-navigated.js b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-main-frame-navigated.js index c0ba4975..50c60b4e 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-main-frame-navigated.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-main-frame-navigated.js
@@ -7,7 +7,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.markStep('dumpInitialNavigator');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-multiple-frames.js b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-multiple-frames.js index b20170b2..99707b4e 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-multiple-frames.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/navigator-multiple-frames.js
@@ -7,7 +7,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.markStep('dumpInitialNavigator');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/shadowdom-navigator.js b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/shadowdom-navigator.js index e8f74ce6..add46470 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/shadowdom-navigator.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/shadowdom-navigator.js
@@ -23,7 +23,7 @@ </template> `); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.markStep('dumpInitialNavigator');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/sourcemap-navigator-multiple-frames.js b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/sourcemap-navigator-multiple-frames.js index 16dd11f..d1b3224b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/sourcemap-navigator-multiple-frames.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/sourcemap-navigator-multiple-frames.js
@@ -7,7 +7,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.markStep('initialWorkspace');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/suspendtarget-navigator.js b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/suspendtarget-navigator.js index d4cb7e5..d5c01671 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/suspendtarget-navigator.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/suspendtarget-navigator.js
@@ -7,7 +7,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.markStep('initialWorkspace');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/elements/styles/styles-do-not-add-inline-stylesheets-in-navigator.js b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/styles/styles-do-not-add-inline-stylesheets-in-navigator.js index bafc7262..22553d2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/elements/styles/styles-do-not-add-inline-stylesheets-in-navigator.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/styles/styles-do-not-add-inline-stylesheets-in-navigator.js
@@ -24,7 +24,7 @@ .then(onInjected); function onInjected() { - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); SourcesTestRunner.dumpNavigatorView(sourcesNavigator); TestRunner.completeTest(); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-mapping-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-mapping-expected.txt deleted file mode 100644 index abf42de..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-mapping-expected.txt +++ /dev/null
@@ -1,190 +0,0 @@ -Tests FileSystemMapping - -Testing file system mapping. - file system paths: - -Adding file system file:///home/username/projects/foo -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - -Adding file system file:///home/username/projects/bar -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - file:///home/username/projects/bar - -Adding file system file:///home/username/project/build -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - file:///home/username/projects/bar - - file:///home/username/project/build - -Adding file system file:///www/site1 -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - file:///home/username/projects/bar - - file:///home/username/project/build - - file:///www/site1 - -Adding file mapping (file:///www/site1, http://localhost/, /) -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - file:///home/username/projects/bar - - file:///home/username/project/build - - file:///www/site1 - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"} - -Adding file mapping (file:///www/site1, http://www.foo.com/, /foo/) -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - file:///home/username/projects/bar - - file:///home/username/project/build - - file:///www/site1 - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"} - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"} - -Adding file mapping (file:///home/username/projects/foo, http://www.example.com/bar/, /foo/) -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"} - - file:///home/username/projects/bar - - file:///home/username/project/build - - file:///www/site1 - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"} - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"} - -Adding file mapping for resource (http://www.bar.com/foo/folder/42.js, file:///home/username/projects/foo, file:///home/username/projects/foo/baz/folder/42.js) -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"} - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.bar.com/foo/","pathPrefix":"/baz/"} - - file:///home/username/projects/bar - - file:///home/username/project/build - - file:///www/site1 - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"} - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"} - -Adding file mapping for resource (http://localhost:3333/build/layout.css, file:///home/username/project/build, file:///home/username/project/build/layout.css) -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"} - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.bar.com/foo/","pathPrefix":"/baz/"} - - file:///home/username/projects/bar - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - - file:///www/site1 - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"} - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"} - -Testing mappings for url: - Has mapping for 'http://www.bar.com/foo/folder/42.js': true - File for 'http://www.bar.com/foo/folder/42.js': file:///home/username/projects/foo/baz/folder/42.js - Has mapping for 'http://www.foo.com/bar/folder/42.js': true - File for 'http://www.foo.com/bar/folder/42.js': file:///www/site1/foo/bar/folder/42.js - Has mapping for 'http://localhost/index.html': true - File for 'http://localhost/index.html': file:///www/site1/index.html - Has mapping for 'https://localhost/index.html': false - File for 'https://localhost/index.html': null - Has mapping for 'http://localhost:8080/index.html': false - File for 'http://localhost:8080/index.html': null - Has mapping for 'http://localhost/': true - File for 'http://localhost/': file:///www/site1/ - Has mapping for 'http://localhost:3333/build/main.css': true - File for 'http://localhost:3333/build/main.css': file:///home/username/project/build/main.css - -Testing mappings for path: - URL for path 'file:///home/username/projects/foo/baz/folder/42.js': http://www.bar.com/foo/folder/42.js - URL for path 'file:///home/username/projects/foo/baz/folder/43.js': http://www.bar.com/foo/folder/43.js - URL for path 'file:///home/username/projects/foo/bar/folder/42.js': - URL for path 'file:///home/username/projects/foo/foo/folder/42.js': http://www.example.com/bar/folder/42.js - URL for path 'file:///home/username/projects/foo/foo2/folder/42.js': - URL for path 'file:///www/site1/foo/index.html': http://www.foo.com/index.html - URL for path 'file:///www/site1/index.html': http://localhost/index.html - URL for path 'file:///www/site1/foo': http://localhost/foo - URL for path 'file:///www/site1/foo/': http://www.foo.com/ - -Creating another file system mapping. -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"} - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.bar.com/foo/","pathPrefix":"/baz/"} - - file:///home/username/projects/bar - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - - file:///www/site1 - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"} - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"} - -Removing file mapping for url http://www.bar.com/foo/folder/42.js -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"} - - file:///home/username/projects/bar - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - - file:///www/site1 - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"} - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"} - -Removing file mapping (file:///www/site1, http://localhost/, /) -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"} - - file:///home/username/projects/bar - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - - file:///www/site1 - - {"fileSystemPath":"file:///www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"} - -Removing file mapping (file:///www/site1, http://www.foo.com/, /foo/) -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - {"fileSystemPath":"file:///home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"} - - file:///home/username/projects/bar - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - - file:///www/site1 - -Removing file mapping (file:///home/username/projects/foo, http://www.example.com/bar/, /foo/) -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - file:///home/username/projects/bar - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - - file:///www/site1 - -Removing file system file:///www/site1 -Testing file system mapping. - file system paths: - - file:///home/username/projects/foo - - file:///home/username/projects/bar - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - -Removing file system file:///home/username/projects/foo -Testing file system mapping. - file system paths: - - file:///home/username/projects/bar - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - -Removing file system file:///home/username/projects/bar -Testing file system mapping. - file system paths: - - file:///home/username/project/build - - {"fileSystemPath":"file:///home/username/project/build","urlPrefix":"http://localhost:3333/build/","pathPrefix":"/"} - -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-mapping.js b/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-mapping.js deleted file mode 100644 index 382b940..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-mapping.js +++ /dev/null
@@ -1,144 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - TestRunner.addResult(`Tests FileSystemMapping\n`); - - - var paths = { - FOO: 'file:///home/username/projects/foo', - BAR: 'file:///home/username/projects/bar', - BUILD: 'file:///home/username/project/build', - SITE1: 'file:///www/site1' - }; - - function addFileSystem(fileSystemMapping, path) { - TestRunner.addResult('Adding file system ' + path); - fileSystemMapping._addFileSystemPath(path); - checkAndDumpFileSystemMapping(fileSystemMapping); - } - - function removeFileSystem(fileSystemMapping, path) { - TestRunner.addResult('Removing file system ' + path); - fileSystemMapping._removeFileSystemPath(path); - checkAndDumpFileSystemMapping(fileSystemMapping); - } - - function addFileMapping(fileSystemMapping, fileSystemPath, urlPrefix, pathPrefix) { - TestRunner.addResult('Adding file mapping (' + fileSystemPath + ', ' + urlPrefix + ', ' + pathPrefix + ')'); - fileSystemMapping.addFileMapping(fileSystemPath, urlPrefix, pathPrefix); - checkAndDumpFileSystemMapping(fileSystemMapping); - } - - function removeFileMapping(fileSystemMapping, fileSystemPath, urlPrefix, pathPrefix) { - TestRunner.addResult('Removing file mapping (' + fileSystemPath + ', ' + urlPrefix + ', ' + pathPrefix + ')'); - fileSystemMapping.removeFileMapping(fileSystemPath, urlPrefix, pathPrefix); - checkAndDumpFileSystemMapping(fileSystemMapping); - } - - function removeMappingForURL(fileSystemMapping, urlPrefix) { - TestRunner.addResult('Removing file mapping for url ' + urlPrefix); - fileSystemMapping.removeMappingForURL(urlPrefix); - checkAndDumpFileSystemMapping(fileSystemMapping); - } - - function addMappingForResource(fileSystemMapping, url, fileSystemPath, filePath) { - TestRunner.addResult('Adding file mapping for resource (' + url + ', ' + fileSystemPath + ', ' + filePath + ')'); - fileSystemMapping.addMappingForResource(url, fileSystemPath, filePath); - checkAndDumpFileSystemMapping(fileSystemMapping); - } - - function dumpFileForURL(fileSystemMapping, url) { - var hasMappingForNetworkURL = fileSystemMapping.hasMappingForNetworkURL(url); - TestRunner.addResult(' Has mapping for \'' + url + '\': ' + hasMappingForNetworkURL); - var fileForURL = fileSystemMapping.fileForURL(url); - if (!fileForURL) - TestRunner.addResult(' File for \'' + url + '\': null'); - else - TestRunner.addResult(' File for \'' + url + '\': ' + fileForURL.fileURL); - } - - function dumpURLForPath(fileSystemMapping, fileSystemPath, filePath) { - var url = fileSystemMapping.networkURLForFileSystemURL(fileSystemPath, filePath); - TestRunner.addResult(' URL for path \'' + filePath + '\': ' + url); - } - - function checkAndDumpFileSystemMapping(fileSystemMapping) { - var fileSystemPaths = Object.keys(fileSystemMapping._fileSystemMappings); - TestRunner.addResult('Testing file system mapping.'); - TestRunner.addResult(' file system paths:'); - for (var i = 0; i < fileSystemPaths.length; ++i) { - TestRunner.addResult(' - ' + fileSystemPaths[i]); - var entries = fileSystemMapping.mappingEntries(fileSystemPaths[i]); - for (var j = 0; j < entries.length; ++j) { - var entry = entries[j]; - TestRunner.addResult(' - ' + JSON.stringify(entries[j])); - } - } - TestRunner.addResult(''); - } - - // At first create file system mapping and clear it. - var fileSystemMapping = new Persistence.FileSystemMapping(Persistence.isolatedFileSystemManager); - var fileSystemPaths = Object.keys(fileSystemMapping._fileSystemMappings); - for (var i = 0; i < fileSystemPaths.length; ++i) - fileSystemMapping._removeFileSystemPath(fileSystemPaths[i]); - - // Now fill it with file systems. - checkAndDumpFileSystemMapping(fileSystemMapping); - addFileSystem(fileSystemMapping, paths.FOO); - addFileSystem(fileSystemMapping, paths.BAR); - addFileSystem(fileSystemMapping, paths.BUILD); - addFileSystem(fileSystemMapping, paths.SITE1); - - // Now fill it with file mappings. - addFileMapping(fileSystemMapping, paths.SITE1, 'http://localhost/', '/'); - addFileMapping(fileSystemMapping, paths.SITE1, 'http://www.foo.com/', '/foo/'); - addFileMapping(fileSystemMapping, paths.FOO, 'http://www.example.com/bar/', '/foo/'); - addMappingForResource( - fileSystemMapping, 'http://www.bar.com/foo/folder/42.js', paths.FOO, paths.FOO + '/baz/folder/42.js'); - addMappingForResource( - fileSystemMapping, 'http://localhost:3333/build/layout.css', paths.BUILD, paths.BUILD + '/layout.css'); - - TestRunner.addResult('Testing mappings for url:'); - dumpFileForURL(fileSystemMapping, 'http://www.bar.com/foo/folder/42.js'); - dumpFileForURL(fileSystemMapping, 'http://www.foo.com/bar/folder/42.js'); - dumpFileForURL(fileSystemMapping, 'http://localhost/index.html'); - dumpFileForURL(fileSystemMapping, 'https://localhost/index.html'); - dumpFileForURL(fileSystemMapping, 'http://localhost:8080/index.html'); - dumpFileForURL(fileSystemMapping, 'http://localhost/'); - dumpFileForURL(fileSystemMapping, 'http://localhost:3333/build/main.css'); - TestRunner.addResult(''); - - TestRunner.addResult('Testing mappings for path:'); - dumpURLForPath(fileSystemMapping, paths.FOO, paths.FOO + '/baz/folder/42.js'); - dumpURLForPath(fileSystemMapping, paths.FOO, paths.FOO + '/baz/folder/43.js'); - dumpURLForPath(fileSystemMapping, paths.FOO, paths.FOO + '/bar/folder/42.js'); - dumpURLForPath(fileSystemMapping, paths.FOO, paths.FOO + '/foo/folder/42.js'); - dumpURLForPath(fileSystemMapping, paths.FOO, paths.FOO + '/foo2/folder/42.js'); - dumpURLForPath(fileSystemMapping, paths.SITE1, paths.SITE1 + '/foo/index.html'); - dumpURLForPath(fileSystemMapping, paths.SITE1, paths.SITE1 + '/index.html'); - dumpURLForPath(fileSystemMapping, paths.SITE1, paths.SITE1 + '/foo'); - dumpURLForPath(fileSystemMapping, paths.SITE1, paths.SITE1 + '/foo/'); - TestRunner.addResult(''); - - // Then create another file mapping to make sure it is correctly restored from the settings. - TestRunner.addResult('Creating another file system mapping.'); - fileSystemMapping.dispose(); - var fileSystemMapping = new Persistence.FileSystemMapping(Persistence.isolatedFileSystemManager); - checkAndDumpFileSystemMapping(fileSystemMapping); - - // Now remove file mappings. - removeMappingForURL(fileSystemMapping, 'http://www.bar.com/foo/folder/42.js'); - removeFileMapping(fileSystemMapping, paths.SITE1, 'http://localhost/', '/'); - removeFileMapping(fileSystemMapping, paths.SITE1, 'http://www.foo.com/', '/foo/'); - removeFileMapping(fileSystemMapping, paths.FOO, 'http://www.example.com/bar/', '/foo/'); - - // Now remove file systems. - removeFileSystem(fileSystemMapping, paths.SITE1); - removeFileSystem(fileSystemMapping, paths.FOO); - removeFileSystem(fileSystemMapping, paths.BAR); - - TestRunner.completeTest(); -})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-project.js b/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-project.js index 1712662c..da038fd7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-project.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/file-system-project.js
@@ -76,9 +76,7 @@ function testFileSystems(next) { TestRunner.addResult('Adding first file system.'); var fs1 = new BindingsTestRunner.TestFileSystem('file:///var/www'); - fs1.addFileMapping('http://localhost/', '/localhost/'); var fs2 = new BindingsTestRunner.TestFileSystem('file:///foo/bar'); - fs2.addFileMapping('http://www.example.com/', '/'); TestRunner.addResult('Adding second file system.'); TestRunner.addResult('Adding files to file systems.');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/oopif-content-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/oopif-content-expected.txt new file mode 100644 index 0000000..3c3533d --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/oopif-content-expected.txt
@@ -0,0 +1,11 @@ +Tests content is available for a cross-process iframe. + +content: <html> +<head> +</head> +<body> + <p>Cross origin frame.<p> +</body> +</html> + +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/oopif-content.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/oopif-content.js new file mode 100644 index 0000000..dc8ea82 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/oopif-content.js
@@ -0,0 +1,21 @@ +// 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. + +(async function() { + // TestRunner.startDumpingProtocolMessages(); + TestRunner.addResult(`Tests content is available for a cross-process iframe.\n`); + await TestRunner.loadModule('network_test_runner'); + await TestRunner.showPanel('network'); + NetworkTestRunner.recordNetwork(); + await TestRunner.addIframe('http://devtools.oopif.test:8000/devtools/resources/cross-origin-iframe.html'); + const request = NetworkTestRunner.networkRequests().pop(); + if (!request || !request.finished) { + TestRunner.addResult('FAILED: request not finished!'); + TestRunner.completeTest(); + return; + } + const content = await request.requestContent(); + TestRunner.addResult(`content: ${content}`); + TestRunner.completeTest(); +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/navigator-create-file-copy.js b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/navigator-create-file-copy.js index 67639ff..529c1181 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/navigator-create-file-copy.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/navigator-create-file-copy.js
@@ -14,7 +14,7 @@ fs.reportCreated(function() {}); var uiSourceCode = await TestRunner.waitForUISourceCode('script.js'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); TestRunner.addResult('BEFORE:\n' + fs.dumpAsText()); sourcesNavigator._handleContextMenuCreate(uiSourceCode.project(), '', uiSourceCode);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-do-not-bind-dirty-sourcecode.js b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-do-not-bind-dirty-sourcecode.js index 19655ed..ad15b040 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-do-not-bind-dirty-sourcecode.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-do-not-bind-dirty-sourcecode.js
@@ -9,7 +9,6 @@ await TestRunner.loadModule('bindings_test_runner'); await TestRunner.addScriptTag('resources/foo.js'); - Runtime.experiments.enableForTest('persistence2'); var testMapping = BindingsTestRunner.initializeTestMapping(); var fs = new BindingsTestRunner.TestFileSystem('file:///var/www'); BindingsTestRunner.addFooJSFile(fs);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator-expected.txt deleted file mode 100644 index 3961a07f..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator-expected.txt +++ /dev/null
@@ -1,41 +0,0 @@ -Verify that navigator view removes mapped UISourceCodes. - - -Running: addFileSystem - -Running: waitForUISourceCodes -[largeicon-navigator-frame] top - [largeicon-navigator-domain] 127.0.0.1:8000 - [largeicon-navigator-folder] devtools - [largeicon-navigator-folder] persistence/resources - [largeicon-navigator-file] foo.js - [largeicon-navigator-folder] resources - [largeicon-navigator-file] inspected-page.html -[largeicon-navigator-folder] www [dimmed] - [largeicon-navigator-folder] devtools/persistence/resources [dimmed] - [largeicon-navigator-file] foo.js - -Running: addFileMapping -[largeicon-navigator-frame] top - [largeicon-navigator-domain] 127.0.0.1:8000 - [largeicon-navigator-folder] devtools - [largeicon-navigator-folder] persistence/resources - [largeicon-navigator-file-sync, badge-navigator-file-sync] foo.js - [largeicon-navigator-folder] resources - [largeicon-navigator-file] inspected-page.html -[largeicon-navigator-folder] www - [largeicon-navigator-folder] devtools/persistence/resources - [largeicon-navigator-file-sync, badge-navigator-file-sync] foo.js - -Running: removeFileMapping -[largeicon-navigator-frame] top - [largeicon-navigator-domain] 127.0.0.1:8000 - [largeicon-navigator-folder] devtools - [largeicon-navigator-folder] persistence/resources - [largeicon-navigator-file] foo.js - [largeicon-navigator-folder] resources - [largeicon-navigator-file] inspected-page.html -[largeicon-navigator-folder] www [dimmed] - [largeicon-navigator-folder] devtools/persistence/resources [dimmed] - [largeicon-navigator-file] foo.js -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator-unique-names.js b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator-unique-names.js index cf879e09..652ef61c4 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator-unique-names.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator-unique-names.js
@@ -6,7 +6,6 @@ TestRunner.addResult(`Verify that navigator view removes mapped UISourceCodes.\n`); await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - Runtime.experiments.enableForTest('persistence2'); var filesNavigator = new Sources.FilesNavigatorView(); filesNavigator.show(UI.inspectorView.element);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator.js b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator.js deleted file mode 100644 index e78e356..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-navigator.js +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - TestRunner.addResult(`Verify that navigator view removes mapped UISourceCodes.\n`); - await TestRunner.loadModule('sources_test_runner'); - await TestRunner.loadModule('bindings_test_runner'); - await TestRunner.addScriptTag('resources/foo.js'); - - var testMapping = BindingsTestRunner.initializeTestMapping(); - Runtime.experiments.enableForTest('persistence2'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); - sourcesNavigator.show(UI.inspectorView.element); - var fs = new BindingsTestRunner.TestFileSystem('file:///var/www'); - var fsEntry = BindingsTestRunner.addFooJSFile(fs); - - TestRunner.runTestSuite([ - function addFileSystem(next) { - fs.reportCreated(next); - }, - - function waitForUISourceCodes(next) { - var promises = [ - TestRunner.waitForUISourceCode('foo.js', Workspace.projectTypes.Network), - TestRunner.waitForUISourceCode('foo.js', Workspace.projectTypes.FileSystem) - ]; - Promise.all(promises).then(onUISourceCodesAdded); - - function onUISourceCodesAdded() { - SourcesTestRunner.dumpNavigatorView(sourcesNavigator, true); - next(); - } - }, - - function addFileMapping(next) { - testMapping.addBinding('foo.js'); - BindingsTestRunner.waitForBinding('foo.js').then(onBindingCreated); - - function onBindingCreated(binding) { - SourcesTestRunner.dumpNavigatorView(sourcesNavigator, true); - next(); - } - }, - - function removeFileMapping(next) { - Persistence.persistence.addEventListener(Persistence.Persistence.Events.BindingRemoved, onBindingRemoved); - testMapping.removeBinding('foo.js'); - - function onBindingRemoved(event) { - var binding = event.data; - if (binding.network.name() !== 'foo.js') - return; - Persistence.persistence.removeEventListener(Persistence.Persistence.Events.BindingRemoved, onBindingRemoved); - SourcesTestRunner.dumpNavigatorView(sourcesNavigator, true); - next(); - } - }, - ]); -})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-rename-mapped-file-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-rename-mapped-file-expected.txt deleted file mode 100644 index 8087ad1..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-rename-mapped-file-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -Verify that binding gets removed as the fileSystem file gets renamed. - -Binding created: { - network: http://127.0.0.1:8000/devtools/persistence/resources/foo.js - fileSystem: file:///var/www/devtools/persistence/resources/foo.js - exactMatch: false -} -Renaming foo.js -> bar.js -Binding successfully removed: { - network: http://127.0.0.1:8000/devtools/persistence/resources/foo.js - fileSystem: file:///var/www/devtools/persistence/resources/bar.js - exactMatch: false -} -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-rename-mapped-file.js b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-rename-mapped-file.js deleted file mode 100644 index d70b148..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-rename-mapped-file.js +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - TestRunner.addResult(`Verify that binding gets removed as the fileSystem file gets renamed.\n`); - await TestRunner.loadModule('sources_test_runner'); - await TestRunner.loadModule('bindings_test_runner'); - await TestRunner.addScriptTag('resources/foo.js'); - - BindingsTestRunner.forceUseDefaultMapping(); - var fs = new BindingsTestRunner.TestFileSystem('file:///var/www'); - var fsEntry = BindingsTestRunner.addFooJSFile(fs); - fs.addFileMapping('http://127.0.0.1:8000', '/'); - fs.reportCreated(function() {}); - BindingsTestRunner.waitForBinding('foo.js').then(onBindingCreated); - Persistence.persistence.addEventListener(Persistence.Persistence.Events.BindingRemoved, onBindingRemoved); - - function onBindingCreated(binding) { - TestRunner.addResult('Binding created: ' + binding); - TestRunner.addResult('Renaming foo.js -> bar.js'); - binding.fileSystem.rename('bar.js', function() {}); - } - - function onBindingRemoved(event) { - var binding = event.data; - TestRunner.addResult('Binding successfully removed: ' + binding); - TestRunner.completeTest(); - } -})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-tabbed-editor-tabs-order.js b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-tabbed-editor-tabs-order.js index cce43be..4366a00 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-tabbed-editor-tabs-order.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/persistence-tabbed-editor-tabs-order.js
@@ -7,25 +7,22 @@ `Verify that tabbed editor doesn't shuffle tabs when bindings are dropped and then re-added during reload.\n`); await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('bindings_test_runner'); - /* - TestRunner.addScriptTag('resources/foo.js'), - TestRunner.addScriptTag('resources/bar.js'), - TestRunner.addScriptTag('resources/baz.js'), - */ await TestRunner.showPanel('sources'); await TestRunner.navigatePromise(TestRunner.url('resources/persistence-tabbed-editor-tab-order.html')); - BindingsTestRunner.forceUseDefaultMapping(); + var testMapping = BindingsTestRunner.initializeTestMapping(); var fs = new BindingsTestRunner.TestFileSystem('file:///var/www'); var folder = fs.root.mkdir('devtools').mkdir('persistence').mkdir('resources'); folder.addFile('foo.js', '\n\nwindow.foo = ()=>\'foo\';'); folder.addFile('bar.js', 'window.bar = () => "bar";'); folder.addFile('baz.js', 'window.baz = () => "baz";'); - fs.addFileMapping('http://127.0.0.1:8000', '/'); fs.reportCreated(function() {}); TestRunner.runTestSuite([ async function waitForBindings(next) { + testMapping.addBinding('foo.js'); + testMapping.addBinding('bar.js'); + testMapping.addBinding('baz.js'); await Promise.all([ BindingsTestRunner.waitForBinding('foo.js'), BindingsTestRunner.waitForBinding('bar.js'),
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/css-sourcemaps-toggle-enabled.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/css-sourcemaps-toggle-enabled.js index d5d0aac..c3d6ec09 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/css-sourcemaps-toggle-enabled.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/css-sourcemaps-toggle-enabled.js
@@ -7,7 +7,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.showPanel('sources'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); Common.moduleSetting('cssSourceMapsEnabled').set(true);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-ui/scripts-panel.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-ui/scripts-panel.js index f93591e..e512d6bb 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-ui/scripts-panel.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-ui/scripts-panel.js
@@ -14,7 +14,7 @@ } function createNavigatorView() { - var navigatorView = new Sources.SourcesNavigatorView(); + var navigatorView = new Sources.NetworkNavigatorView(); navigatorView.show(UI.inspectorView.element); return navigatorView; }
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-ui/scripts-sorting.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-ui/scripts-sorting.js index e989cc2b..db39825 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-ui/scripts-sorting.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-ui/scripts-sorting.js
@@ -14,7 +14,7 @@ return navigatorView; } - sourcesNavigatorView = createNavigatorView(Sources.SourcesNavigatorView); + sourcesNavigatorView = createNavigatorView(Sources.NetworkNavigatorView); contentScriptsNavigatorView = createNavigatorView(Sources.ContentScriptsNavigatorView); Bindings.NetworkProject.forTarget(TestRunner.mainTarget)._resetForTest();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/navigator-view.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/navigator-view.js index dce44ac..ec5c979e 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/navigator-view.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/navigator-view.js
@@ -19,7 +19,7 @@ var networkProject2 = Bindings.NetworkProject.forTarget(target2); var subframe = TestRunner.mainFrame().childFrames[0]; - var sourcesNavigatorView = new Sources.SourcesNavigatorView(); + var sourcesNavigatorView = new Sources.NetworkNavigatorView(); sourcesNavigatorView.show(UI.inspectorView.element); var contentScriptsNavigatorView = new Sources.ContentScriptsNavigatorView(); contentScriptsNavigatorView.show(UI.inspectorView.element);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/js-sourcemaps-toggle-enabled.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/js-sourcemaps-toggle-enabled.js index 343db549..cf9c4aa 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/js-sourcemaps-toggle-enabled.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/js-sourcemaps-toggle-enabled.js
@@ -7,7 +7,7 @@ await TestRunner.loadModule('sources_test_runner'); await TestRunner.showPanel('sources'); - var sourcesNavigator = new Sources.SourcesNavigatorView(); + var sourcesNavigator = new Sources.NetworkNavigatorView(); sourcesNavigator.show(UI.inspectorView.element); Common.moduleSetting('jsSourceMapsEnabled').set(true);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/navigator-view-content-scripts.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/navigator-view-content-scripts.js index f4ce881c..38f64be 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/navigator-view-content-scripts.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/navigator-view-content-scripts.js
@@ -9,7 +9,7 @@ await TestRunner.showPanel('sources'); var rootURL = 'http://localhost:8080/LayoutTests/inspector/debugger/'; - var sourcesNavigatorView = new Sources.SourcesNavigatorView(); + var sourcesNavigatorView = new Sources.NetworkNavigatorView(); sourcesNavigatorView.show(UI.inspectorView.element); TestRunner.addResult('\n\n================================================');
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/resources/iframe-that-performs-top-navigation-without-user-gesture.html b/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/resources/iframe-that-performs-top-navigation-without-user-gesture.html index d07fe06..fc545868 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/resources/iframe-that-performs-top-navigation-without-user-gesture.html +++ b/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/resources/iframe-that-performs-top-navigation-without-user-gesture.html
@@ -1,14 +1,14 @@ <html> <body> -The navigation should fail. This text should be visible. +The navigation should succeed. This text shouldn't appear. <script> window.onload = function() { try { top.location = "http://localhost:8000/security/frameNavigation/resources/navigation-changed-iframe.html"; - top.postMessage("FAIL", "*"); - } catch(e) { top.postMessage("PASS", "*"); + } catch(e) { + top.postMessage("FAIL", "*"); } } </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/xss-DENIED-top-navigation-user-gesture-in-parent-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/xss-DENIED-top-navigation-user-gesture-in-parent-expected.txt index ee18088..4ec5fe0 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/xss-DENIED-top-navigation-user-gesture-in-parent-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/xss-DENIED-top-navigation-user-gesture-in-parent-expected.txt
@@ -1,6 +1,2 @@ - - --------- -Frame: '<!--framePath //<!--frame0-->-->' --------- -The navigation should fail. This text should be visible. +localhost +PASSED: Navigation succeeded.
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture-expected.txt index 3558992..5a29641 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture-expected.txt
@@ -1,8 +1,3 @@ -CONSOLE ERROR: line 8: Unsafe JavaScript attempt to initiate navigation for frame with URL 'http://127.0.0.1:8000/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html' from frame with URL 'http://localhost:8000/security/frameNavigation/resources/iframe-that-performs-top-navigation-without-user-gesture.html'. The frame attempting navigation is targeting its top-level window, but is neither same-origin with its target nor has it received a user gesture. See https://www.chromestatus.com/features/5851021045661696. - - - --------- -Frame: '<!--framePath //<!--frame0-->-->' --------- -The navigation should fail. This text should be visible. +CONSOLE WARNING: line 8: Frame with URL 'http://localhost:8000/security/frameNavigation/resources/iframe-that-performs-top-navigation-without-user-gesture.html' attempted to navigate its top-level window with URL 'http://127.0.0.1:8000/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html'. Navigating the top-level window from a cross-origin iframe will soon require that the iframe has received a user gesture. See https://www.chromestatus.com/features/5851021045661696. +localhost +PASSED: Navigation succeeded.
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-expected.txt index 7d331431..5e75a9ea 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-expected.txt
@@ -22,7 +22,7 @@ "passive": false, "once": false, "scriptId": "<string>", - "lineNumber": 42, + "lineNumber": 43, "columnNumber": 46 } ] @@ -99,11 +99,13 @@ "childNodeIndexes": [ 10, 11, - 61, - 62, + 12, + 13, 63, 64, - 66 + 65, + 66, + 68 ], "attributes": [ { @@ -121,23 +123,44 @@ }, { "nodeType": 1, + "nodeName": "IMG", + "nodeValue": "", + "backendNodeId": "<number>", + "attributes": [ + { + "name": "srcset", + "value": "1x.png 1x, 2x.png 2x" + } + ], + "layoutNodeIndex": 3, + "currentSourceURL": "<string>WebKit/LayoutTests/inspector-protocol/resources/1x.png" + }, + { + "nodeType": 3, + "nodeName": "#text", + "nodeValue": "\n", + "backendNodeId": "<number>", + "layoutNodeIndex": 4 + }, + { + "nodeType": 1, "nodeName": "DIV", "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 12, - 13, + 14, 15, - 16, - 29, - 30, + 17, + 18, + 31, 32, - 33, - 47, - 48, - 57, - 58, - 60 + 34, + 35, + 49, + 50, + 59, + 60, + 62 ], "attributes": [ { @@ -145,7 +168,7 @@ "value": "font-family: ahem;" } ], - "layoutNodeIndex": 3 + "layoutNodeIndex": 5 }, { "nodeType": 3, @@ -159,7 +182,7 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 14 + 16 ], "attributes": [ { @@ -167,21 +190,21 @@ "value": "class1" } ], - "layoutNodeIndex": 4 + "layoutNodeIndex": 6 }, { "nodeType": 3, "nodeName": "#text", "nodeValue": "Some Text", "backendNodeId": "<number>", - "layoutNodeIndex": 5 + "layoutNodeIndex": 7 }, { "nodeType": 3, "nodeName": "#text", "nodeValue": " And More Text\n ", "backendNodeId": "<number>", - "layoutNodeIndex": 6 + "layoutNodeIndex": 8 }, { "nodeType": 1, @@ -189,11 +212,11 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 17, - 18, + 19, 20, - 21, - 28 + 22, + 23, + 30 ], "attributes": [ { @@ -205,7 +228,7 @@ "value": "A" } ], - "layoutNodeIndex": 7, + "layoutNodeIndex": 9, "eventListeners": [ { "type": "listenerA", @@ -213,7 +236,7 @@ "passive": false, "once": false, "scriptId": "<string>", - "lineNumber": 39, + "lineNumber": 40, "columnNumber": 59 } ] @@ -230,16 +253,16 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 19 + 21 ], - "layoutNodeIndex": 8 + "layoutNodeIndex": 10 }, { "nodeType": 3, "nodeName": "#text", "nodeValue": "\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque sit amet est sem.\n Aenean ut neque volutpat, posuere odio at, mollis nibh. Aenean sodales nulla et\n ligula efficitur sollicitudin blandit sed lectus. Duis orci enim, sodales ac lectus sed,\n hendrerit efficitur est. Quisque gravida facilisis viverra.\n ", "backendNodeId": "<number>", - "layoutNodeIndex": 9 + "layoutNodeIndex": 11 }, { "nodeType": 3, @@ -253,11 +276,11 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 22, - 23, 24, 25, - 27 + 26, + 27, + 29 ], "attributes": [ { @@ -265,7 +288,7 @@ "value": "class3" } ], - "layoutNodeIndex": 10 + "layoutNodeIndex": 12 }, { "nodeType": 3, @@ -284,7 +307,7 @@ "value": "class4" } ], - "layoutNodeIndex": 11 + "layoutNodeIndex": 13 }, { "nodeType": 3, @@ -298,7 +321,7 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 26 + 28 ], "attributes": [ { @@ -306,7 +329,7 @@ "value": "B" } ], - "layoutNodeIndex": 12, + "layoutNodeIndex": 14, "eventListeners": [ { "type": "listenerB", @@ -314,64 +337,6 @@ "passive": false, "once": false, "scriptId": "<string>", - "lineNumber": 40, - "columnNumber": 59 - } - ] - }, - { - "nodeType": 3, - "nodeName": "#text", - "nodeValue": "Lets have a span", - "backendNodeId": "<number>", - "layoutNodeIndex": 13 - }, - { - "nodeType": 3, - "nodeName": "#text", - "nodeValue": "\n ", - "backendNodeId": "<number>", - "layoutNodeIndex": 14 - }, - { - "nodeType": 3, - "nodeName": "#text", - "nodeValue": "\n ", - "backendNodeId": "<number>" - }, - { - "nodeType": 3, - "nodeName": "#text", - "nodeValue": "\n ", - "backendNodeId": "<number>", - "layoutNodeIndex": 15 - }, - { - "nodeType": 1, - "nodeName": "DIV", - "nodeValue": "", - "backendNodeId": "<number>", - "childNodeIndexes": [ - 31 - ], - "attributes": [ - { - "name": "style", - "value": "transform: rotateZ(90deg); width: 200px" - }, - { - "name": "id", - "value": "C" - } - ], - "layoutNodeIndex": 16, - "eventListeners": [ - { - "type": "listenerC", - "useCapture": false, - "passive": false, - "once": false, - "scriptId": "<string>", "lineNumber": 41, "columnNumber": 59 } @@ -380,11 +345,69 @@ { "nodeType": 3, "nodeName": "#text", - "nodeValue": "Rotated text!", + "nodeValue": "Lets have a span", + "backendNodeId": "<number>", + "layoutNodeIndex": 15 + }, + { + "nodeType": 3, + "nodeName": "#text", + "nodeValue": "\n ", + "backendNodeId": "<number>", + "layoutNodeIndex": 16 + }, + { + "nodeType": 3, + "nodeName": "#text", + "nodeValue": "\n ", + "backendNodeId": "<number>" + }, + { + "nodeType": 3, + "nodeName": "#text", + "nodeValue": "\n ", "backendNodeId": "<number>", "layoutNodeIndex": 17 }, { + "nodeType": 1, + "nodeName": "DIV", + "nodeValue": "", + "backendNodeId": "<number>", + "childNodeIndexes": [ + 33 + ], + "attributes": [ + { + "name": "style", + "value": "transform: rotateZ(90deg); width: 200px" + }, + { + "name": "id", + "value": "C" + } + ], + "layoutNodeIndex": 18, + "eventListeners": [ + { + "type": "listenerC", + "useCapture": false, + "passive": false, + "once": false, + "scriptId": "<string>", + "lineNumber": 42, + "columnNumber": 59 + } + ] + }, + { + "nodeType": 3, + "nodeName": "#text", + "nodeValue": "Rotated text!", + "backendNodeId": "<number>", + "layoutNodeIndex": 19 + }, + { "nodeType": 3, "nodeName": "#text", "nodeValue": "\n ", @@ -409,9 +432,9 @@ "value": "200" } ], - "layoutNodeIndex": 18, + "layoutNodeIndex": 20, "frameId": "<string>", - "contentDocumentIndex": 34 + "contentDocumentIndex": 36 }, { "nodeType": 9, @@ -419,9 +442,9 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 35 + 37 ], - "layoutNodeIndex": 19, + "layoutNodeIndex": 21, "documentURL": "<string>", "baseURL": "<string>", "documentEncoding": "windows-1252", @@ -433,11 +456,11 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 36, - 41, - 42 + 38, + 43, + 44 ], - "layoutNodeIndex": 20, + "layoutNodeIndex": 22, "frameId": "<string>" }, { @@ -446,9 +469,9 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 37, - 38, - 40 + 39, + 40, + 42 ] }, { @@ -463,7 +486,7 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 39 + 41 ] }, { @@ -490,11 +513,11 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 43, - 44, - 46 + 45, + 46, + 48 ], - "layoutNodeIndex": 21 + "layoutNodeIndex": 23 }, { "nodeType": 3, @@ -508,7 +531,7 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 45 + 47 ], "attributes": [ { @@ -516,14 +539,14 @@ "value": "font-family: ahem;" } ], - "layoutNodeIndex": 22 + "layoutNodeIndex": 24 }, { "nodeType": 3, "nodeName": "#text", "nodeValue": "\nHello from the iframe.\n", "backendNodeId": "<number>", - "layoutNodeIndex": 23 + "layoutNodeIndex": 25 }, { "nodeType": 3, @@ -536,7 +559,7 @@ "nodeName": "#text", "nodeValue": "\n ", "backendNodeId": "<number>", - "layoutNodeIndex": 24 + "layoutNodeIndex": 26 }, { "nodeType": 1, @@ -544,11 +567,11 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 49, - 50, + 51, 52, - 53, - 56 + 54, + 55, + 58 ], "attributes": [ { @@ -556,7 +579,7 @@ "value": "shadow-host" } ], - "layoutNodeIndex": 25 + "layoutNodeIndex": 27 }, { "nodeType": 3, @@ -570,7 +593,7 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 51 + 53 ] }, { @@ -591,7 +614,7 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 54 + 56 ], "attributes": [ { @@ -599,7 +622,7 @@ "value": "font-family: ahem;" } ], - "layoutNodeIndex": 26 + "layoutNodeIndex": 28 }, { "nodeType": 1, @@ -607,16 +630,16 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 55 + 57 ], - "layoutNodeIndex": 27 + "layoutNodeIndex": 29 }, { "nodeType": 3, "nodeName": "#text", "nodeValue": "Hi!", "backendNodeId": "<number>", - "layoutNodeIndex": 28 + "layoutNodeIndex": 30 }, { "nodeType": 3, @@ -636,7 +659,7 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 59 + 61 ], "attributes": [ { @@ -644,7 +667,7 @@ "value": "https://www.google.com/" } ], - "layoutNodeIndex": 29, + "layoutNodeIndex": 31, "isClickable": true }, { @@ -652,14 +675,14 @@ "nodeName": "#text", "nodeValue": "Click ME!", "backendNodeId": "<number>", - "layoutNodeIndex": 30 + "layoutNodeIndex": 32 }, { "nodeType": 3, "nodeName": "#text", "nodeValue": "\n", "backendNodeId": "<number>", - "layoutNodeIndex": 31 + "layoutNodeIndex": 33 }, { "nodeType": 3, @@ -695,7 +718,7 @@ "nodeValue": "", "backendNodeId": "<number>", "childNodeIndexes": [ - 65 + 67 ] }, { @@ -727,7 +750,7 @@ "x": 0, "y": 0, "width": 785, - "height": 935 + "height": 1135 }, "styleIndex": 0 }, @@ -737,7 +760,7 @@ "x": 8, "y": 8, "width": 769, - "height": 919 + "height": 1119 }, "styleIndex": 1 }, @@ -746,26 +769,47 @@ "boundingBox": { "x": 8, "y": 8, - "width": 769, - "height": 919 + "width": 200, + "height": 200 }, - "styleIndex": 1 + "styleIndex": 2 + }, + { + "domNodeIndex": 12, + "boundingBox": { + "x": 0, + "y": 0, + "width": 0, + "height": 0 + }, + "layoutText": "\n", + "styleIndex": 3 }, { "domNodeIndex": 13, "boundingBox": { "x": 8, - "y": 8, + "y": 208, + "width": 769, + "height": 919 + }, + "styleIndex": 4 + }, + { + "domNodeIndex": 15, + "boundingBox": { + "x": 8, + "y": 208, "width": 769, "height": 16 }, - "styleIndex": 2 + "styleIndex": 5 }, { - "domNodeIndex": 14, + "domNodeIndex": 16, "boundingBox": { "x": 8, - "y": 8, + "y": 208, "width": 144, "height": 16 }, @@ -774,7 +818,7 @@ { "boundingBox": { "x": 8, - "y": 8, + "y": 208, "width": 144, "height": 16 }, @@ -785,10 +829,10 @@ "styleIndex": 3 }, { - "domNodeIndex": 15, + "domNodeIndex": 17, "boundingBox": { "x": 8, - "y": 568, + "y": 768, "width": 224, "height": 16 }, @@ -797,7 +841,7 @@ { "boundingBox": { "x": 8, - "y": 568, + "y": 768, "width": 224, "height": 16 }, @@ -808,30 +852,30 @@ "styleIndex": 3 }, { - "domNodeIndex": 16, - "boundingBox": { - "x": 232, - "y": 24, - "width": 200, - "height": 576 - }, - "styleIndex": 4 - }, - { "domNodeIndex": 18, "boundingBox": { "x": 232, - "y": 40, + "y": 224, + "width": 200, + "height": 576 + }, + "styleIndex": 6 + }, + { + "domNodeIndex": 20, + "boundingBox": { + "x": 232, + "y": 240, "width": 200, "height": 480 }, - "styleIndex": 5 + "styleIndex": 7 }, { - "domNodeIndex": 19, + "domNodeIndex": 21, "boundingBox": { "x": 232, - "y": 40, + "y": 240, "width": 192, "height": 480 }, @@ -840,7 +884,7 @@ { "boundingBox": { "x": 232, - "y": 40, + "y": 240, "width": 176, "height": 16 }, @@ -850,7 +894,7 @@ { "boundingBox": { "x": 232, - "y": 56, + "y": 256, "width": 144, "height": 16 }, @@ -860,7 +904,7 @@ { "boundingBox": { "x": 232, - "y": 72, + "y": 272, "width": 80, "height": 16 }, @@ -870,7 +914,7 @@ { "boundingBox": { "x": 232, - "y": 88, + "y": 288, "width": 176, "height": 16 }, @@ -880,7 +924,7 @@ { "boundingBox": { "x": 232, - "y": 104, + "y": 304, "width": 160, "height": 16 }, @@ -890,7 +934,7 @@ { "boundingBox": { "x": 232, - "y": 120, + "y": 320, "width": 80, "height": 16 }, @@ -900,7 +944,7 @@ { "boundingBox": { "x": 232, - "y": 136, + "y": 336, "width": 192, "height": 16 }, @@ -910,7 +954,7 @@ { "boundingBox": { "x": 232, - "y": 152, + "y": 352, "width": 192, "height": 16 }, @@ -920,7 +964,7 @@ { "boundingBox": { "x": 232, - "y": 168, + "y": 368, "width": 80, "height": 16 }, @@ -930,7 +974,7 @@ { "boundingBox": { "x": 312, - "y": 168, + "y": 368, "width": 96, "height": 16 }, @@ -940,7 +984,7 @@ { "boundingBox": { "x": 232, - "y": 184, + "y": 384, "width": 128, "height": 16 }, @@ -950,7 +994,7 @@ { "boundingBox": { "x": 232, - "y": 200, + "y": 400, "width": 144, "height": 16 }, @@ -960,7 +1004,7 @@ { "boundingBox": { "x": 232, - "y": 216, + "y": 416, "width": 192, "height": 16 }, @@ -970,7 +1014,7 @@ { "boundingBox": { "x": 232, - "y": 232, + "y": 432, "width": 160, "height": 16 }, @@ -980,7 +1024,7 @@ { "boundingBox": { "x": 232, - "y": 248, + "y": 448, "width": 192, "height": 16 }, @@ -990,7 +1034,7 @@ { "boundingBox": { "x": 232, - "y": 264, + "y": 464, "width": 112, "height": 16 }, @@ -1000,7 +1044,7 @@ { "boundingBox": { "x": 232, - "y": 280, + "y": 480, "width": 128, "height": 16 }, @@ -1010,7 +1054,7 @@ { "boundingBox": { "x": 232, - "y": 296, + "y": 496, "width": 96, "height": 16 }, @@ -1020,7 +1064,7 @@ { "boundingBox": { "x": 232, - "y": 312, + "y": 512, "width": 144, "height": 16 }, @@ -1030,7 +1074,7 @@ { "boundingBox": { "x": 232, - "y": 328, + "y": 528, "width": 192, "height": 16 }, @@ -1040,7 +1084,7 @@ { "boundingBox": { "x": 232, - "y": 344, + "y": 544, "width": 176, "height": 16 }, @@ -1050,7 +1094,7 @@ { "boundingBox": { "x": 232, - "y": 360, + "y": 560, "width": 192, "height": 16 }, @@ -1060,7 +1104,7 @@ { "boundingBox": { "x": 232, - "y": 376, + "y": 576, "width": 160, "height": 16 }, @@ -1070,7 +1114,7 @@ { "boundingBox": { "x": 232, - "y": 392, + "y": 592, "width": 160, "height": 16 }, @@ -1080,7 +1124,7 @@ { "boundingBox": { "x": 232, - "y": 408, + "y": 608, "width": 176, "height": 16 }, @@ -1090,7 +1134,7 @@ { "boundingBox": { "x": 232, - "y": 424, + "y": 624, "width": 144, "height": 16 }, @@ -1100,7 +1144,7 @@ { "boundingBox": { "x": 232, - "y": 440, + "y": 640, "width": 144, "height": 16 }, @@ -1110,7 +1154,7 @@ { "boundingBox": { "x": 232, - "y": 456, + "y": 656, "width": 192, "height": 16 }, @@ -1120,7 +1164,7 @@ { "boundingBox": { "x": 232, - "y": 472, + "y": 672, "width": 112, "height": 16 }, @@ -1130,7 +1174,7 @@ { "boundingBox": { "x": 232, - "y": 488, + "y": 688, "width": 144, "height": 16 }, @@ -1140,7 +1184,7 @@ { "boundingBox": { "x": 232, - "y": 504, + "y": 704, "width": 128, "height": 16 }, @@ -1151,40 +1195,40 @@ "styleIndex": 3 }, { - "domNodeIndex": 21, + "domNodeIndex": 23, "boundingBox": { "x": 232, - "y": 536, + "y": 736, "width": 200, "height": 48 }, - "styleIndex": 6 - }, - { - "domNodeIndex": 23, - "boundingBox": { - "x": 272, - "y": 536, - "width": 160, - "height": 16 - }, - "styleIndex": 7 + "styleIndex": 8 }, { "domNodeIndex": 25, "boundingBox": { "x": 272, - "y": 552, + "y": 736, + "width": 160, + "height": 16 + }, + "styleIndex": 9 + }, + { + "domNodeIndex": 27, + "boundingBox": { + "x": 272, + "y": 752, "width": 144, "height": 32 }, - "styleIndex": 8 + "styleIndex": 10 }, { - "domNodeIndex": 26, + "domNodeIndex": 28, "boundingBox": { "x": 272, - "y": 552, + "y": 752, "width": 144, "height": 32 }, @@ -1193,7 +1237,7 @@ { "boundingBox": { "x": 272, - "y": 552, + "y": 752, "width": 144, "height": 16 }, @@ -1203,7 +1247,7 @@ { "boundingBox": { "x": 272, - "y": 568, + "y": 768, "width": 96, "height": 16 }, @@ -1211,10 +1255,10 @@ "numCharacters": 6 } ], - "styleIndex": 8 + "styleIndex": 10 }, { - "domNodeIndex": 27, + "domNodeIndex": 29, "boundingBox": { "x": 0, "y": 0, @@ -1225,7 +1269,7 @@ "styleIndex": 3 }, { - "domNodeIndex": 29, + "domNodeIndex": 31, "boundingBox": { "x": 0, "y": 0, @@ -1236,20 +1280,20 @@ "styleIndex": 3 }, { - "domNodeIndex": 30, + "domNodeIndex": 32, "boundingBox": { "x": 92, - "y": 516, + "y": 716, "width": 32, "height": 200 }, - "styleIndex": 9 + "styleIndex": 11 }, { - "domNodeIndex": 31, + "domNodeIndex": 33, "boundingBox": { "x": 92, - "y": 516, + "y": 716, "width": 32, "height": 112 }, @@ -1258,7 +1302,7 @@ { "boundingBox": { "x": 108, - "y": 516, + "y": 716, "width": 16, "height": 112 }, @@ -1268,7 +1312,7 @@ { "boundingBox": { "x": 92, - "y": 516, + "y": 716, "width": 16, "height": 80 }, @@ -1276,20 +1320,20 @@ "numCharacters": 5 } ], - "styleIndex": 10 + "styleIndex": 12 }, { - "domNodeIndex": 33, + "domNodeIndex": 35, "boundingBox": { "x": 8, - "y": 632, + "y": 832, "width": 404, "height": 204 }, - "styleIndex": 11 + "styleIndex": 13 }, { - "domNodeIndex": 34, + "domNodeIndex": 36, "boundingBox": { "x": 0, "y": 0, @@ -1298,24 +1342,14 @@ } }, { - "domNodeIndex": 35, + "domNodeIndex": 37, "boundingBox": { "x": 0, "y": 0, "width": 400, "height": 200 }, - "styleIndex": 12 - }, - { - "domNodeIndex": 42, - "boundingBox": { - "x": 8, - "y": 8, - "width": 384, - "height": 184 - }, - "styleIndex": 13 + "styleIndex": 14 }, { "domNodeIndex": 44, @@ -1323,12 +1357,22 @@ "x": 8, "y": 8, "width": 384, - "height": 16 + "height": 184 }, - "styleIndex": 14 + "styleIndex": 15 }, { - "domNodeIndex": 45, + "domNodeIndex": 46, + "boundingBox": { + "x": 8, + "y": 8, + "width": 384, + "height": 16 + }, + "styleIndex": 16 + }, + { + "domNodeIndex": 47, "boundingBox": { "x": 8, "y": 8, @@ -1351,7 +1395,7 @@ "styleIndex": 3 }, { - "domNodeIndex": 47, + "domNodeIndex": 49, "boundingBox": { "x": 0, "y": 0, @@ -1362,40 +1406,40 @@ "styleIndex": 3 }, { - "domNodeIndex": 48, + "domNodeIndex": 50, "boundingBox": { "x": 8, - "y": 857, + "y": 1057, "width": 769, "height": 33 }, - "styleIndex": 15 - }, - { - "domNodeIndex": 53, - "boundingBox": { - "x": 8, - "y": 857, - "width": 769, - "height": 33 - }, - "styleIndex": 15 - }, - { - "domNodeIndex": 54, - "boundingBox": { - "x": 8, - "y": 857, - "width": 769, - "height": 33 - }, - "styleIndex": 15 + "styleIndex": 17 }, { "domNodeIndex": 55, "boundingBox": { "x": 8, - "y": 857, + "y": 1057, + "width": 769, + "height": 33 + }, + "styleIndex": 17 + }, + { + "domNodeIndex": 56, + "boundingBox": { + "x": 8, + "y": 1057, + "width": 769, + "height": 33 + }, + "styleIndex": 17 + }, + { + "domNodeIndex": 57, + "boundingBox": { + "x": 8, + "y": 1057, "width": 96, "height": 33 }, @@ -1404,7 +1448,7 @@ { "boundingBox": { "x": 8, - "y": 857.4375, + "y": 1057.4375, "width": 96, "height": 32 }, @@ -1412,23 +1456,23 @@ "numCharacters": 3 } ], - "styleIndex": 16 + "styleIndex": 18 }, { - "domNodeIndex": 58, + "domNodeIndex": 60, "boundingBox": { "x": 8, - "y": 910, + "y": 1110, "width": 144, "height": 17 }, - "styleIndex": 17 + "styleIndex": 19 }, { - "domNodeIndex": 59, + "domNodeIndex": 61, "boundingBox": { "x": 8, - "y": 910, + "y": 1110, "width": 144, "height": 17 }, @@ -1437,7 +1481,7 @@ { "boundingBox": { "x": 8, - "y": 910.875, + "y": 1110.875, "width": 144, "height": 16 }, @@ -1445,10 +1489,10 @@ "numCharacters": 9 } ], - "styleIndex": 17 + "styleIndex": 19 }, { - "domNodeIndex": 60, + "domNodeIndex": 62, "boundingBox": { "x": 0, "y": 0, @@ -1468,11 +1512,11 @@ }, { "name": "transform-origin", - "value": "392.5px 467.438px" + "value": "392.5px 567.438px" }, { "name": "height", - "value": "934.875px" + "value": "1134.88px" }, { "name": "width", @@ -1500,6 +1544,102 @@ }, { "name": "transform-origin", + "value": "384.5px 559.438px" + }, + { + "name": "height", + "value": "1118.88px" + }, + { + "name": "width", + "value": "769px" + }, + { + "name": "display", + "value": "block" + }, + { + "name": "outline-color", + "value": "rgb(0, 0, 0)" + }, + { + "name": "color", + "value": "rgb(0, 0, 0)" + } + ] + }, + { + "properties": [ + { + "name": "transform", + "value": "none" + }, + { + "name": "transform-origin", + "value": "100px 100px" + }, + { + "name": "height", + "value": "200px" + }, + { + "name": "width", + "value": "200px" + }, + { + "name": "display", + "value": "inline" + }, + { + "name": "outline-color", + "value": "rgb(0, 0, 0)" + }, + { + "name": "color", + "value": "rgb(0, 0, 0)" + } + ] + }, + { + "properties": [ + { + "name": "transform", + "value": "none" + }, + { + "name": "transform-origin", + "value": "0px 0px" + }, + { + "name": "height", + "value": "auto" + }, + { + "name": "width", + "value": "auto" + }, + { + "name": "display", + "value": "block" + }, + { + "name": "outline-color", + "value": "rgb(0, 0, 0)" + }, + { + "name": "color", + "value": "rgb(0, 0, 0)" + } + ] + }, + { + "properties": [ + { + "name": "transform", + "value": "none" + }, + { + "name": "transform-origin", "value": "384.5px 459.438px" }, { @@ -1564,38 +1704,6 @@ }, { "name": "transform-origin", - "value": "0px 0px" - }, - { - "name": "height", - "value": "auto" - }, - { - "name": "width", - "value": "auto" - }, - { - "name": "display", - "value": "block" - }, - { - "name": "outline-color", - "value": "rgb(0, 0, 0)" - }, - { - "name": "color", - "value": "rgb(0, 0, 0)" - } - ] - }, - { - "properties": [ - { - "name": "transform", - "value": "none" - }, - { - "name": "transform-origin", "value": "100px 288px" }, {
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js index 04f1f76..656fd32 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js
@@ -15,6 +15,8 @@ return '<' + typeof(value) + '>'; if (typeof value === 'string' && value.indexOf('/dom-snapshot/') !== -1) value = '<value>'; + if (typeof value === 'string' && value.indexOf('file://') !== -1) + value = '<string>' + value.substr(value.indexOf("WebKit/")); return value; }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/1x.png b/third_party/WebKit/LayoutTests/inspector-protocol/resources/1x.png new file mode 100644 index 0000000..e99c23e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/1x.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/2x.png b/third_party/WebKit/LayoutTests/inspector-protocol/resources/2x.png new file mode 100644 index 0000000..b14d2e0d --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/2x.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/dom-snapshot.html b/third_party/WebKit/LayoutTests/inspector-protocol/resources/dom-snapshot.html index c1bc20a8..72c5b30 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/resources/dom-snapshot.html +++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/dom-snapshot.html
@@ -16,6 +16,7 @@ </template> </head> <body class="body-class"> +<img srcset="1x.png 1x, 2x.png 2x"> <div style="font-family: ahem;"> <div class="class1">Some Text</div> And More Text <div style="display:inline-block; width: 200px" id="A">
diff --git a/third_party/WebKit/LayoutTests/media/controls/picture-in-picture-button.html b/third_party/WebKit/LayoutTests/media/controls/picture-in-picture-button.html new file mode 100644 index 0000000..e666e09 --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/controls/picture-in-picture-button.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<title>media controls picture in picture button</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../media-file.js"></script> +<script src="../media-controls.js"></script> +<body> +<script> +async_test(t => { + enablePictureInPictureForTest(t); + + var video = document.createElement('video'); + video.setAttribute('controls', ''); + video.src = findMediaFile('video', '../content/test'); + document.body.appendChild(video); + + video.onloadedmetadata = t.step_func_done(function() { + // Should have a picture in picture button. + var button = pictureInPictureButton(video); + assert_false( + ("display" in button.style) && (button.style.display == "none"), + "button should exist"); + + // Check its position is to the right of the timeline. + var buttonBoundingRect = button.getBoundingClientRect(); + var x = buttonBoundingRect.left + buttonBoundingRect.width / 2; + var timelinePosition = + mediaControlsButtonCoordinates(video, "timeline"); + assert_greater_than(x, timelinePosition[0], + "button should be to right of timeline"); + + // Button should be to the left of the fullscreen button. + var fullscreenPosition = + mediaControlsButtonCoordinates(video, "fullscreen-button"); + assert_less_than(x, fullscreenPosition[0], + "button should be to left of fullscreen button"); + }); +}); +</script> +</body> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/controls/picture-in-picture-interstitial.html b/third_party/WebKit/LayoutTests/media/controls/picture-in-picture-interstitial.html new file mode 100644 index 0000000..136104a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/controls/picture-in-picture-interstitial.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<title>media controls picture in picture button</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../media-file.js"></script> +<script src="../media-controls.js"></script> +<body> +<script> +async_test(t => { + enablePictureInPictureForTest(t); + + var video = document.createElement('video'); + video.setAttribute('controls', ''); + video.src = findMediaFile('video', '../content/test'); + document.body.appendChild(video); + + video.play(); + + video.onloadedmetadata = t.step_func(function() { + // Should have a picture in picture button. + var button = pictureInPictureButton(video); + assert_false( + ("display" in button.style) && (button.style.display == "none"), + "button should exist"); + + // Should not have a picture in picture interstitial while the video + // is not playing. + checkPictureInPictureInterstitialDoesNotExist(video); + + button.onclick = setTimeout(t.step_func_done(function() { + // Interstitial should appear when picture in picture button is clicked. + var interstitial = pictureInPictureInterstitial(video); + assert_equals(interstitial.style.display, '', + 'interstitial should be visible when the video is not playing'); + })); + + video.play(); + button.click(); + }); +}); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/media/controls/picture-in-picture.js b/third_party/WebKit/LayoutTests/media/controls/picture-in-picture.js new file mode 100644 index 0000000..698f983 --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/controls/picture-in-picture.js
@@ -0,0 +1,66 @@ +function assertPictureInPictureButtonVisible(videoElement) +{ + assert_true(isVisible(pictureInPictureButton(videoElement)), + "Picture in picture button should be visible."); +} + +function assertPictureInPictureButtonNotVisible(videoElement) +{ + assert_false(isVisible(pictureInPictureButton(videoElement)), + "Picture in picture button should not be visible."); +} + +function pictureInPictureButton(videoElement) +{ + var elementId = '-internal-media-controls-picture-in-picture-button'; + var button = mediaControlsElement( + window.internals.shadowRoot(videoElement).firstChild, + elementId); + if (!button) + throw 'Failed to find picture in picture button.'; + return button; +} + +function assertPictureInPictureInterstitialVisible(videoElement) +{ + assert_true(isVisible(pictureInPictureInterstitial(videoElement)), + "Picture in picture interstitial should be visible."); +} + +function assertPictureInPictureInterstitialNotVisible(videoElement) +{ + assert_false(isVisible(pictureInPictureInterstitial(videoElement)), + "Picture in picture interstitial should not be visible."); +} + +function pictureInPictureInterstitial(videoElement) +{ + var elementId = '-internal-picture-in-picture-interstitial'; + var interstitial = mediaControlsElement( + window.internals.shadowRoot(videoElement).firstChild, + elementId); + if (!interstitial) + throw 'Failed to find picture in picture interstitial.'; + return interstitial; +} + +function enablePictureInPictureForTest(t) +{ + var pictureInPictureEnabledValue = + internals.runtimeFlags.pictureInPictureEnabled; + internals.runtimeFlags.pictureInPictureEnabled = true; + + t.add_cleanup(() => { + internals.runtimeFlags.pictureInPictureEnabled = + pictureInPictureEnabledValue; + }); +} + +function click(button) +{ + const pos = offset(button); + const rect = button.getBoundingClientRect(); + singleTapAtCoordinates( + Math.ceil(pos.left + rect.width / 2), + Math.ceil(pos.top + rect.height / 2)); +} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/media-controls.js b/third_party/WebKit/LayoutTests/media/media-controls.js index 0725066..380f8283 100644 --- a/third_party/WebKit/LayoutTests/media/media-controls.js +++ b/third_party/WebKit/LayoutTests/media/media-controls.js
@@ -24,6 +24,15 @@ return button; } +function pictureInPictureButton(videoElement) { + var controlID = '-internal-media-controls-picture-in-picture-button'; + + var button = mediaControlsElement(window.internals.shadowRoot(videoElement).firstChild, controlID); + if (!button) + throw 'Failed to find picture in picture button'; + return button; +} + function downloadButton(videoElement) { var controlID = '-internal-media-controls-download-button'; var button = mediaControlsElement(window.internals.shadowRoot(videoElement).firstChild, controlID); @@ -321,6 +330,23 @@ return element; } +function pictureInPictureInterstitial(videoElement) { + var controlID = '-internal-picture-in-picture-interstitial'; + + var interstitial = getElementByPseudoId(window.internals.shadowRoot(videoElement).firstChild, controlID); + if (!interstitial) + throw 'Failed to find picture in picture interstitial'; + return interstitial; +} + +function checkPictureInPictureInterstitialDoesNotExist(videoElement) { + var controlID = '-internal-picture-in-picture-interstitial'; + + var interstitial = getElementByPseudoId(internals.oldestShadowRoot(videoElement), controlID); + if (interstitial) + throw 'Should not have a picture in picture interstitial'; +} + function doubleTapAtCoordinates(x, y, timeout, callback) { if (timeout == undefined) timeout = 100; @@ -361,3 +387,47 @@ doubleTapToJumpOnVideoEnabledValue; }); } + +function enablePictureInPictureForTest(t) { + var pictureInPictureEnabledValue = + internals.runtimeFlags.pictureInPictureEnabled; + internals.runtimeFlags.pictureInPictureEnabled = true; + + t.add_cleanup(() => { + internals.runtimeFlags.pictureInPictureEnabled = + pictureInPictureEnabledValue; + }); +} + +function traverseNextNode(node, stayWithin) { + var nextNode = node.firstChild; + if (nextNode) + return nextNode; + + if (stayWithin && node === stayWithin) + return null; + + nextNode = node.nextSibling; + if (nextNode) + return nextNode; + + nextNode = node; + while (nextNode && !nextNode.nextSibling && (!stayWithin || !nextNode.parentNode || nextNode.parentNode !== stayWithin)) + nextNode = nextNode.parentNode; + if (!nextNode) + return null; + + return nextNode.nextSibling; +} + +function getElementByPseudoId(root, pseudoId) { + if (!window.internals) + return null; + var node = root; + while (node) { + if (node.nodeType === Node.ELEMENT_NODE && internals.shadowPseudoId(node) === pseudoId) + return node; + node = traverseNextNode(node, root); + } + return null; +} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png rename to third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/downsample-quality-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/downsample-quality-expected.png new file mode 100644 index 0000000..38523ea --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/downsample-quality-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/downsample-quality-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/downsample-quality-expected.png new file mode 100644 index 0000000..0a9dc0c --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/downsample-quality-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png deleted file mode 100644 index d87cf60..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png index 564b4dc..d67d3cb 100644 --- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png +++ b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-drawImage-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png index a23bd9d..a3333f7 100644 --- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/yuv-video-on-accelerated-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/Source/core/css/CSSGradientValue.cpp b/third_party/WebKit/Source/core/css/CSSGradientValue.cpp index 6a888d4e..a2130a8 100644 --- a/third_party/WebKit/Source/core/css/CSSGradientValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSGradientValue.cpp
@@ -36,7 +36,6 @@ #include "core/css/CSSValuePair.h" #include "core/dom/NodeComputedStyle.h" #include "core/dom/TextLinkColors.h" -#include "core/layout/LayoutObject.h" #include "platform/geometry/IntSize.h" #include "platform/graphics/ColorBlend.h" #include "platform/graphics/Gradient.h" @@ -120,27 +119,24 @@ } // We need to create an image. - scoped_refptr<Gradient> gradient; - const ComputedStyle* root_style = document.documentElement()->GetComputedStyle(); - // TODO: Break dependency on LayoutObject. - const LayoutObject& layout_object = static_cast<const LayoutObject&>(client); CSSToLengthConversionData conversion_data( - &style, root_style, layout_object.View(), style.EffectiveZoom()); + &style, root_style, document.GetLayoutView(), style.EffectiveZoom()); + scoped_refptr<Gradient> gradient; switch (GetClassType()) { case kLinearGradientClass: gradient = ToCSSLinearGradientValue(this)->CreateGradient( - conversion_data, size, layout_object); + conversion_data, size, document, style); break; case kRadialGradientClass: gradient = ToCSSRadialGradientValue(this)->CreateGradient( - conversion_data, size, layout_object); + conversion_data, size, document, style); break; case kConicGradientClass: gradient = ToCSSConicGradientValue(this)->CreateGradient( - conversion_data, size, layout_object); + conversion_data, size, document, style); break; default: NOTREACHED(); @@ -294,13 +290,9 @@ stop_color, style.VisitedDependentColor(GetCSSPropertyColor())); } -static Color ResolveStopColor(const CSSValue& stop_color, - const LayoutObject& obj) { - return ResolveStopColor(stop_color, obj.GetDocument(), obj.StyleRef()); -} - void CSSGradientValue::AddDeprecatedStops(GradientDesc& desc, - const LayoutObject& object) { + const Document& document, + const ComputedStyle& style) { DCHECK(gradient_type_ == kCSSDeprecatedLinearGradient || gradient_type_ == kCSSDeprecatedRadialGradient); @@ -317,7 +309,8 @@ else offset = stop.offset_->GetFloatValue(); - desc.stops.emplace_back(offset, ResolveStopColor(*stop.color_, object)); + const Color color = ResolveStopColor(*stop.color_, document, style); + desc.stops.emplace_back(offset, color); } } @@ -463,10 +456,11 @@ void CSSGradientValue::AddStops( CSSGradientValue::GradientDesc& desc, const CSSToLengthConversionData& conversion_data, - const LayoutObject& object) { + const Document& document, + const ComputedStyle& style) { if (gradient_type_ == kCSSDeprecatedLinearGradient || gradient_type_ == kCSSDeprecatedRadialGradient) { - AddDeprecatedStops(desc, object); + AddDeprecatedStops(desc, document, style); return; } @@ -497,7 +491,7 @@ if (stop.IsHint()) has_hints = true; else - stops[i].color = ResolveStopColor(*stop.color_, object); + stops[i].color = ResolveStopColor(*stop.color_, document, style); if (stop.offset_) { if (stop.offset_->IsPercentage()) { @@ -719,12 +713,15 @@ return true; } -void CSSGradientValue::GetStopColors(Vector<Color>& stop_colors, - const LayoutObject& object) const { - for (auto& stop : stops_) { +Vector<Color> CSSGradientValue::GetStopColors( + const Document& document, + const ComputedStyle& style) const { + Vector<Color> stop_colors; + for (const auto& stop : stops_) { if (!stop.IsHint()) - stop_colors.push_back(ResolveStopColor(*stop.color_, object)); + stop_colors.push_back(ResolveStopColor(*stop.color_, document, style)); } + return stop_colors; } void CSSGradientValue::TraceAfterDispatch(blink::Visitor* visitor) { @@ -878,7 +875,8 @@ scoped_refptr<Gradient> CSSLinearGradientValue::CreateGradient( const CSSToLengthConversionData& conversion_data, const LayoutSize& size, - const LayoutObject& object) { + const Document& document, + const ComputedStyle& style) { DCHECK(!size.IsEmpty()); FloatPoint first_point; @@ -943,7 +941,7 @@ GradientDesc desc(first_point, second_point, repeating_ ? kSpreadMethodRepeat : kSpreadMethodPad); - AddStops(desc, conversion_data, object); + AddStops(desc, conversion_data, document, style); scoped_refptr<Gradient> gradient = Gradient::CreateLinear(desc.p0, desc.p1, desc.spread_method, @@ -1244,7 +1242,8 @@ scoped_refptr<Gradient> CSSRadialGradientValue::CreateGradient( const CSSToLengthConversionData& conversion_data, const LayoutSize& size, - const LayoutObject& object) { + const Document& document, + const ComputedStyle& style) { DCHECK(!size.IsEmpty()); FloatPoint first_point = @@ -1316,7 +1315,7 @@ GradientDesc desc(first_point, second_point, first_radius, is_degenerate ? 0 : second_radius.Width(), repeating_ ? kSpreadMethodRepeat : kSpreadMethodPad); - AddStops(desc, conversion_data, object); + AddStops(desc, conversion_data, document, style); scoped_refptr<Gradient> gradient = Gradient::CreateRadial( desc.p0, desc.r0, desc.p1, desc.r1, @@ -1420,7 +1419,8 @@ scoped_refptr<Gradient> CSSConicGradientValue::CreateGradient( const CSSToLengthConversionData& conversion_data, const LayoutSize& size, - const LayoutObject& object) { + const Document& document, + const ComputedStyle& style) { DCHECK(!size.IsEmpty()); const float angle = from_angle_ ? from_angle_->ComputeDegrees() : 0; @@ -1433,7 +1433,7 @@ GradientDesc desc(position, position, repeating_ ? kSpreadMethodRepeat : kSpreadMethodPad); - AddStops(desc, conversion_data, object); + AddStops(desc, conversion_data, document, style); scoped_refptr<Gradient> gradient = Gradient::CreateConic( position, angle, desc.start_angle, desc.end_angle, desc.spread_method,
diff --git a/third_party/WebKit/Source/core/css/CSSGradientValue.h b/third_party/WebKit/Source/core/css/CSSGradientValue.h index 47ee780..5a4ab0d64 100644 --- a/third_party/WebKit/Source/core/css/CSSGradientValue.h +++ b/third_party/WebKit/Source/core/css/CSSGradientValue.h
@@ -37,7 +37,6 @@ class Color; class Gradient; class Document; -class LayoutObject; namespace cssvalue { @@ -117,7 +116,7 @@ void LoadSubimages(const Document&) {} - void GetStopColors(Vector<Color>& stop_colors, const LayoutObject&) const; + Vector<Color> GetStopColors(const Document&, const ComputedStyle&) const; void TraceAfterDispatch(blink::Visitor*); @@ -135,8 +134,9 @@ void AddStops(GradientDesc&, const CSSToLengthConversionData&, - const LayoutObject&); - void AddDeprecatedStops(GradientDesc&, const LayoutObject&); + const Document&, + const ComputedStyle&); + void AddDeprecatedStops(GradientDesc&, const Document&, const ComputedStyle&); void AppendCSSTextForColorStops(StringBuilder&, bool requires_separator) const; @@ -171,7 +171,8 @@ // Create the gradient for a given size. scoped_refptr<Gradient> CreateGradient(const CSSToLengthConversionData&, const LayoutSize&, - const LayoutObject&); + const Document&, + const ComputedStyle&); bool Equals(const CSSLinearGradientValue&) const; @@ -244,7 +245,8 @@ // Create the gradient for a given size. scoped_refptr<Gradient> CreateGradient(const CSSToLengthConversionData&, const LayoutSize&, - const LayoutObject&); + const Document&, + const ComputedStyle&); bool Equals(const CSSRadialGradientValue&) const; @@ -310,7 +312,8 @@ // Create the gradient for a given size. scoped_refptr<Gradient> CreateGradient(const CSSToLengthConversionData&, const LayoutSize&, - const LayoutObject&); + const Document&, + const ComputedStyle&); bool Equals(const CSSConicGradientValue&) const;
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp index 364504f..906bd0f 100644 --- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
@@ -45,18 +45,19 @@ void GeneratedImageCache::PutImage(const LayoutSize& size, scoped_refptr<Image> image) { + DCHECK(!size.IsEmpty()); images_.insert(size, std::move(image)); } void GeneratedImageCache::AddSize(const LayoutSize& size) { - if (size.IsEmpty()) - return; + DCHECK(!size.IsEmpty()); sizes_.insert(size); } void GeneratedImageCache::RemoveSize(const LayoutSize& size) { - if (size.IsEmpty()) - return; + DCHECK(!size.IsEmpty()); + DCHECK(sizes_.Contains(size)); + DCHECK(images_.Contains(size)); if (sizes_.erase(size)) images_.erase(size); } @@ -90,7 +91,10 @@ SECURITY_DCHECK(it != clients_.end()); SizeAndCount& size_count = it->value; - cached_images_.RemoveSize(size_count.size); + if (!size_count.size.IsEmpty()) { + cached_images_.RemoveSize(size_count.size); + size_count.size = LayoutSize(); + } if (!--size_count.count) clients_.erase(client); @@ -108,12 +112,15 @@ DCHECK(keep_alive_); SizeAndCount& size_count = it->value; if (size_count.size != size) { - cached_images_.RemoveSize(size_count.size); - cached_images_.AddSize(size); + if (!size_count.size.IsEmpty()) { + cached_images_.RemoveSize(size_count.size); + size_count.size = LayoutSize(); + } - // If there's only one use for this client, then update the size. - if (size_count.count == 1) + if (!size.IsEmpty()) { + cached_images_.AddSize(size); size_count.size = size; + } } } return cached_images_.GetImage(size);
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h index 62e3205..e896effa 100644 --- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h +++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
@@ -61,7 +61,11 @@ DISALLOW_NEW(); SizeAndCount() : size(), count(0) {} + // The non-zero size associated with this client. A client must only + // ever be present at one non-zero size, with as many zero sizes as it wants. LayoutSize size; + + // The net number of times this client has been added. int count; };
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp index 76af20a..ff449d3 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
@@ -350,6 +350,18 @@ style.GetWritingMode() != layout_parent_style.GetWritingMode()) style.SetDisplay(EDisplay::kInlineBlock); + // We do not honor position: relative or sticky for table rows, headers, and + // footers. This is correct for position: relative in CSS2.1 (and caused a + // crash in containingBlock() on some sites) and position: sticky is defined + // as following position: relative behavior for table elements. It is + // incorrect for CSS3. + if ((style.Display() == EDisplay::kTableHeaderGroup || + style.Display() == EDisplay::kTableRowGroup || + style.Display() == EDisplay::kTableFooterGroup || + style.Display() == EDisplay::kTableRow) && + style.HasInFlowPosition()) + style.SetPosition(EPosition::kStatic); + // Cannot support position: sticky for table columns and column groups because // current code is only doing background painting through columns / column // groups.
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h index 1940242..78d7d23 100644 --- a/third_party/WebKit/Source/core/dom/Node.h +++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -328,6 +328,7 @@ virtual bool IsCharacterDataNode() const { return false; } virtual bool IsFrameOwnerElement() const { return false; } virtual bool IsMediaRemotingInterstitial() const { return false; } + virtual bool IsPictureInPictureInterstitial() const { return false; } // Traverses the ancestors of this node and returns true if any of them are // either a MediaControlElement or MediaControls.
diff --git a/third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp b/third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp index d56b443..6dfbc80 100644 --- a/third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp +++ b/third_party/WebKit/Source/core/editing/CaretDisplayItemClient.cpp
@@ -252,10 +252,10 @@ // paint invalidation. if (IsImmediateFullPaintInvalidationReason( layout_block_->FullPaintInvalidationReason()) || - // For non-SPv2, kSubtreeInvalidationChecking may hint change of + // For SPv1, kSubtreeInvalidationChecking may hint change of // paint offset. See ObjectPaintInvalidatorWithContext:: // invalidatePaintIfNeededWithComputedReason(). - (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() && + (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && (context.subtree_flags & PaintInvalidatorContext::kSubtreeInvalidationChecking))) { object_invalidator.InvalidateDisplayItemClient(
diff --git a/third_party/WebKit/Source/core/editing/LocalCaretRect.h b/third_party/WebKit/Source/core/editing/LocalCaretRect.h index ba14f94..597e94e1 100644 --- a/third_party/WebKit/Source/core/editing/LocalCaretRect.h +++ b/third_party/WebKit/Source/core/editing/LocalCaretRect.h
@@ -35,6 +35,10 @@ LocalCaretRect LocalSelectionRectOfPosition(const PositionWithAffinity&); +// Exposed to tests only. Implemented in LocalCaretRectTest.cpp. +bool operator==(const LocalCaretRect&, const LocalCaretRect&); +std::ostream& operator<<(std::ostream&, const LocalCaretRect&); + } // namespace blink #endif // LocalCaretRect_h
diff --git a/third_party/WebKit/Source/core/editing/LocalCaretRectTest.cpp b/third_party/WebKit/Source/core/editing/LocalCaretRectTest.cpp index 17457da..9fc9960 100644 --- a/third_party/WebKit/Source/core/editing/LocalCaretRectTest.cpp +++ b/third_party/WebKit/Source/core/editing/LocalCaretRectTest.cpp
@@ -7,9 +7,19 @@ #include "core/editing/PositionWithAffinity.h" #include "core/editing/TextAffinity.h" #include "core/editing/testing/EditingTestBase.h" +#include "core/layout/LayoutObject.h" namespace blink { +bool operator==(const LocalCaretRect& rect1, const LocalCaretRect& rect2) { + return rect1.layout_object == rect2.layout_object && rect1.rect == rect2.rect; +} + +std::ostream& operator<<(std::ostream& out, const LocalCaretRect& caret_rect) { + return out << "layout_object = " << caret_rect.layout_object->GetNode() + << ", rect = " << caret_rect.rect; +} + class LocalCaretRectTest : public EditingTestBase {}; TEST_F(LocalCaretRectTest, DOMAndFlatTrees) { @@ -29,9 +39,7 @@ LocalCaretRectOfPosition(PositionInFlatTree(one->firstChild(), 0)); EXPECT_FALSE(caret_rect_from_dom_tree.IsEmpty()); - EXPECT_EQ(caret_rect_from_dom_tree.layout_object, - caret_rect_from_flat_tree.layout_object); - EXPECT_EQ(caret_rect_from_dom_tree.rect, caret_rect_from_flat_tree.rect); + EXPECT_EQ(caret_rect_from_dom_tree, caret_rect_from_flat_tree); } TEST_F(LocalCaretRectTest, SimpleText) { @@ -43,21 +51,17 @@ const Node* foo = GetElementById("div")->firstChild(); EXPECT_EQ( - LayoutRect(0, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(10, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(10, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(20, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(20, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(29, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(29, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream})); } TEST_F(LocalCaretRectTest, MixedHeightText) { @@ -69,21 +73,17 @@ const Node* foo = GetElementById("div")->firstChild(); EXPECT_EQ( - LayoutRect(0, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(10, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(10, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(20, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(20, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(29, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(29, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream})); } TEST_F(LocalCaretRectTest, RtlText) { @@ -96,21 +96,17 @@ const Node* foo = GetElementById("bdo")->firstChild(); EXPECT_EQ( - LayoutRect(29, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(29, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(20, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(20, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(10, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(10, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(0, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream})); } TEST_F(LocalCaretRectTest, VerticalText) { @@ -123,21 +119,17 @@ const Node* foo = GetElementById("div")->firstChild(); EXPECT_EQ( - LayoutRect(0, 0, 10, 1), - LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 0, 10, 1)), + LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(0, 10, 10, 1), - LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 10, 10, 1)), + LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(0, 20, 10, 1), - LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 20, 10, 1)), + LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(0, 29, 10, 1), - LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 29, 10, 1)), + LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream})); } TEST_F(LocalCaretRectTest, TwoLinesOfTextWithSoftWrap) { @@ -151,39 +143,58 @@ // First line EXPECT_EQ( - LayoutRect(0, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 0), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(10, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(10, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 1), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(20, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(20, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 2), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(29, 0, 1, 10), - LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kUpstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(29, 0, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kUpstream})); // Second line EXPECT_EQ( - LayoutRect(0, 10, 1, 10), - LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(0, 10, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 3), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(10, 10, 1, 10), - LocalCaretRectOfPosition({Position(foo, 4), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(10, 10, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 4), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(20, 10, 1, 10), - LocalCaretRectOfPosition({Position(foo, 5), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(20, 10, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 5), TextAffinity::kDownstream})); EXPECT_EQ( - LayoutRect(29, 10, 1, 10), - LocalCaretRectOfPosition({Position(foo, 6), TextAffinity::kDownstream}) - .rect); + LocalCaretRect(foo->GetLayoutObject(), LayoutRect(29, 10, 1, 10)), + LocalCaretRectOfPosition({Position(foo, 6), TextAffinity::kDownstream})); +} + +TEST_F(LocalCaretRectTest, CaretRectAtBR) { + // This test only records the current behavior. Future changes are allowed. + + LoadAhem(); + SetBodyContent( + "<div style='font: 10px/10px Ahem; width: 30px'><br>foo</div>"); + const Element& br = *GetDocument().QuerySelector("br"); + + EXPECT_EQ(LocalCaretRect(br.GetLayoutObject(), LayoutRect(0, 0, 1, 10)), + LocalCaretRectOfPosition( + {Position::BeforeNode(br), TextAffinity::kDownstream})); +} + +TEST_F(LocalCaretRectTest, CaretRectAtRtlBR) { + // This test only records the current behavior. Future changes are allowed. + + LoadAhem(); + SetBodyContent( + "<bdo dir=rtl style='display: block; font: 10px/10px Ahem; width: 30px'>" + "<br>foo</bdo>"); + const Element& br = *GetDocument().QuerySelector("br"); + + EXPECT_EQ(LocalCaretRect(br.GetLayoutObject(), LayoutRect(29, 0, 1, 10)), + LocalCaretRectOfPosition( + {Position::BeforeNode(br), TextAffinity::kDownstream})); } TEST_F(LocalCaretRectTest, Images) { @@ -199,27 +210,23 @@ const Element& img1 = *GetElementById("img1"); - EXPECT_EQ(LayoutRect(0, 0, 1, 10), + EXPECT_EQ(LocalCaretRect(img1.GetLayoutObject(), LayoutRect(0, 0, 1, 10)), LocalCaretRectOfPosition( - {Position::BeforeNode(img1), TextAffinity::kDownstream}) - .rect); - EXPECT_EQ(LayoutRect(9, 0, 1, 10), + {Position::BeforeNode(img1), TextAffinity::kDownstream})); + EXPECT_EQ(LocalCaretRect(img1.GetLayoutObject(), LayoutRect(9, 0, 1, 10)), LocalCaretRectOfPosition( - {Position::AfterNode(img1), TextAffinity::kDownstream}) - .rect); + {Position::AfterNode(img1), TextAffinity::kDownstream})); const Element& img2 = *GetElementById("img2"); // Box-anchored LocalCaretRect is local to the box itself, instead of its // containing block. - EXPECT_EQ(LayoutRect(0, 0, 1, 10), + EXPECT_EQ(LocalCaretRect(img2.GetLayoutObject(), LayoutRect(0, 0, 1, 10)), LocalCaretRectOfPosition( - {Position::BeforeNode(img2), TextAffinity::kDownstream}) - .rect); - EXPECT_EQ(LayoutRect(9, 0, 1, 10), + {Position::BeforeNode(img2), TextAffinity::kDownstream})); + EXPECT_EQ(LocalCaretRect(img2.GetLayoutObject(), LayoutRect(9, 0, 1, 10)), LocalCaretRectOfPosition( - {Position::AfterNode(img2), TextAffinity::kDownstream}) - .rect); + {Position::AfterNode(img2), TextAffinity::kDownstream})); } TEST_F(LocalCaretRectTest, TextAndImageMixedHeight) { @@ -236,32 +243,26 @@ const Node* text1 = img.previousSibling(); const Node* text2 = img.nextSibling(); - EXPECT_EQ( - LayoutRect(0, 0, 1, 10), - LocalCaretRectOfPosition({Position(text1, 0), TextAffinity::kDownstream}) - .rect); - EXPECT_EQ( - LayoutRect(10, 0, 1, 10), - LocalCaretRectOfPosition({Position(text1, 1), TextAffinity::kDownstream}) - .rect); - - EXPECT_EQ(LayoutRect(0, -5, 1, 10), + EXPECT_EQ(LocalCaretRect(text1->GetLayoutObject(), LayoutRect(0, 0, 1, 10)), LocalCaretRectOfPosition( - {Position::BeforeNode(img), TextAffinity::kDownstream}) - .rect); - EXPECT_EQ(LayoutRect(9, -5, 1, 10), + {Position(text1, 0), TextAffinity::kDownstream})); + EXPECT_EQ(LocalCaretRect(text1->GetLayoutObject(), LayoutRect(10, 0, 1, 10)), LocalCaretRectOfPosition( - {Position::AfterNode(img), TextAffinity::kDownstream}) - .rect); + {Position(text1, 1), TextAffinity::kDownstream})); - EXPECT_EQ( - LayoutRect(20, 5, 1, 10), - LocalCaretRectOfPosition({Position(text2, 0), TextAffinity::kDownstream}) - .rect); - EXPECT_EQ( - LayoutRect(29, 0, 1, 10), - LocalCaretRectOfPosition({Position(text2, 1), TextAffinity::kDownstream}) - .rect); + EXPECT_EQ(LocalCaretRect(img.GetLayoutObject(), LayoutRect(0, -5, 1, 10)), + LocalCaretRectOfPosition( + {Position::BeforeNode(img), TextAffinity::kDownstream})); + EXPECT_EQ(LocalCaretRect(img.GetLayoutObject(), LayoutRect(9, -5, 1, 10)), + LocalCaretRectOfPosition( + {Position::AfterNode(img), TextAffinity::kDownstream})); + + EXPECT_EQ(LocalCaretRect(text2->GetLayoutObject(), LayoutRect(20, 5, 1, 10)), + LocalCaretRectOfPosition( + {Position(text2, 0), TextAffinity::kDownstream})); + EXPECT_EQ(LocalCaretRect(text2->GetLayoutObject(), LayoutRect(29, 0, 1, 10)), + LocalCaretRectOfPosition( + {Position(text2, 1), TextAffinity::kDownstream})); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp index 286bf14..95b880f 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -540,6 +540,10 @@ return !first_layout_; } +bool LocalFrameView::LifecycleUpdatesActive() const { + return !lifecycle_updates_throttled_; +} + void LocalFrameView::InvalidateRect(const IntRect& rect) { auto* layout_object = frame_->OwnerLayoutObject(); if (!layout_object)
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h index 2b16e0f..5a88677 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -154,6 +154,7 @@ void UpdateLayout(); bool DidFirstLayout() const; + bool LifecycleUpdatesActive() const; void ScheduleRelayout(); void ScheduleRelayoutOfSubtree(LayoutObject*); bool LayoutPending() const;
diff --git a/third_party/WebKit/Source/core/html/BUILD.gn b/third_party/WebKit/Source/core/html/BUILD.gn index d49e7d6..76adaae 100644 --- a/third_party/WebKit/Source/core/html/BUILD.gn +++ b/third_party/WebKit/Source/core/html/BUILD.gn
@@ -497,6 +497,8 @@ "media/MediaFragmentURIParser.h", "media/MediaRemotingInterstitial.cpp", "media/MediaRemotingInterstitial.h", + "media/PictureInPictureInterstitial.cpp", + "media/PictureInPictureInterstitial.h", "shadow/DetailsMarkerControl.cpp", "shadow/DetailsMarkerControl.h", "shadow/ProgressShadowElement.cpp",
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp index 973d4ec..e9c7942 100644 --- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -276,6 +276,7 @@ } } else if (name == decodingAttr && RuntimeEnabledFeatures::ImageDecodingAttributeEnabled()) { + UseCounter::Count(GetDocument(), WebFeature::kImageDecodingAttribute); decoding_mode_ = ParseImageDecodingMode(params.new_value); } else { HTMLElement::ParseAttribute(params);
diff --git a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp index 68209f4..16a853f 100644 --- a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp
@@ -441,7 +441,6 @@ std::unique_ptr<Canvas2DLayerBridge> bridge = CreateUnaccelerated2dBuffer(); if (bridge && canvas2d_bridge_) { - RestoreCanvasMatrixClipStack(bridge->Canvas()); ReplaceExistingCanvas2DBuffer(std::move(bridge)); UpdateMemoryUsage(); } @@ -1239,7 +1238,6 @@ std::unique_ptr<Canvas2DLayerBridge> surface = CreateAccelerated2dBuffer(&msaa_sample_count); if (surface) { - RestoreCanvasMatrixClipStack(surface->Canvas()); ReplaceExistingCanvas2DBuffer(std::move(surface)); UpdateMemoryUsage(); SetNeedsCompositingUpdate(); @@ -1553,6 +1551,8 @@ return; new_buffer->Canvas()->drawImage(image->PaintImageForCurrentFrame(), 0, 0); } + + RestoreCanvasMatrixClipStack(new_buffer->Canvas()); canvas2d_bridge_ = std::move(new_buffer); }
diff --git a/third_party/WebKit/Source/core/html/media/HTMLAudioElement.h b/third_party/WebKit/Source/core/html/media/HTMLAudioElement.h index 43ebe15..03f8b60 100644 --- a/third_party/WebKit/Source/core/html/media/HTMLAudioElement.h +++ b/third_party/WebKit/Source/core/html/media/HTMLAudioElement.h
@@ -48,6 +48,8 @@ // WebMediaPlayerClient implementation. void MediaRemotingStarted( const WebString& remote_device_friendly_name) override {} + void PictureInPictureStarted() override {} + void PictureInPictureStopped() override {} void MediaRemotingStopped(WebLocalizedString::Name error_msg) override {} private:
diff --git a/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp index dfea559..f07f1e1 100644 --- a/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp
@@ -2574,6 +2574,11 @@ return volume_; } +void HTMLMediaElement::pictureInPicture() { + if (GetWebMediaPlayer()) + GetWebMediaPlayer()->PictureInPicture(); +} + // The spec says to fire periodic timeupdate events (those sent while playing) // every "15 to 250ms", we choose the slowest frequency static const TimeDelta kMaxTimeupdateEventFrequency = @@ -3602,11 +3607,11 @@ // static void HTMLMediaElement::AssertShadowRootChildren(ShadowRoot& shadow_root) { #if DCHECK_IS_ON() - // There can be up to three children: media remoting interstitial, text track - // container, and media controls. The media controls has to be the last child - // if presend, and has to be the next sibling of the text track container if - // both present. When present, media remoting interstitial has to be the first - // child. + // There can be up to three children: an interstitial (media remoting or + // picture in picture), text track container, and media controls. The media + // controls has to be the last child if presend, and has to be the next + // sibling of the text track container if both present. When present, media + // remoting interstitial has to be the first child. unsigned number_of_children = shadow_root.CountChildren(); DCHECK_LE(number_of_children, 3u); Node* first_child = shadow_root.firstChild(); @@ -3614,16 +3619,19 @@ if (number_of_children == 1) { DCHECK(first_child->IsTextTrackContainer() || first_child->IsMediaControls() || - first_child->IsMediaRemotingInterstitial()); + first_child->IsMediaRemotingInterstitial() || + first_child->IsPictureInPictureInterstitial()); } else if (number_of_children == 2) { DCHECK(first_child->IsTextTrackContainer() || - first_child->IsMediaRemotingInterstitial()); + first_child->IsMediaRemotingInterstitial() || + first_child->IsPictureInPictureInterstitial()); DCHECK(last_child->IsTextTrackContainer() || last_child->IsMediaControls()); if (first_child->IsTextTrackContainer()) DCHECK(last_child->IsMediaControls()); } else if (number_of_children == 3) { Node* second_child = first_child->nextSibling(); - DCHECK(first_child->IsMediaRemotingInterstitial()); + DCHECK(first_child->IsMediaRemotingInterstitial() || + first_child->IsPictureInPictureInterstitial()); DCHECK(second_child->IsTextTrackContainer()); DCHECK(last_child->IsMediaControls()); }
diff --git a/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h index 02826f0c..30d8c35 100644 --- a/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h +++ b/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h
@@ -310,6 +310,8 @@ // Returns the "effective media volume" value as specified in the HTML5 spec. double EffectiveMediaVolume() const; + void pictureInPicture(); + // Predicates also used when dispatching wrapper creation (cf. // [SpecialWrapFor] IDL attribute usage.) virtual bool IsHTMLAudioElement() const { return false; }
diff --git a/third_party/WebKit/Source/core/html/media/HTMLVideoElement.cpp b/third_party/WebKit/Source/core/html/media/HTMLVideoElement.cpp index d5a89b7..ff797c2 100644 --- a/third_party/WebKit/Source/core/html/media/HTMLVideoElement.cpp +++ b/third_party/WebKit/Source/core/html/media/HTMLVideoElement.cpp
@@ -37,6 +37,7 @@ #include "core/fullscreen/Fullscreen.h" #include "core/html/media/MediaCustomControlsFullscreenDetector.h" #include "core/html/media/MediaRemotingInterstitial.h" +#include "core/html/media/PictureInPictureInterstitial.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html_names.h" #include "core/imagebitmap/ImageBitmap.h" @@ -66,7 +67,9 @@ } // anonymous namespace inline HTMLVideoElement::HTMLVideoElement(Document& document) - : HTMLMediaElement(videoTag, document), remoting_interstitial_(nullptr) { + : HTMLMediaElement(videoTag, document), + remoting_interstitial_(nullptr), + picture_in_picture_interstitial_(nullptr) { if (document.GetSettings()) { default_poster_url_ = AtomicString(document.GetSettings()->GetDefaultVideoPosterURL()); @@ -89,6 +92,7 @@ visitor->Trace(image_loader_); visitor->Trace(custom_controls_fullscreen_detector_); visitor->Trace(remoting_interstitial_); + visitor->Trace(picture_in_picture_interstitial_); HTMLMediaElement::Trace(visitor); } @@ -189,10 +193,13 @@ // Notify the player when the poster image URL changes. if (GetWebMediaPlayer()) GetWebMediaPlayer()->SetPoster(PosterImageURL()); - // Media remoting doesn't show the original poster image, instead, it shows - // a grayscaled and blurred copy. + + // Media remoting and picture in picture doesn't show the original poster + // image, instead, it shows a grayscaled and blurred copy. if (remoting_interstitial_) remoting_interstitial_->OnPosterImageChanged(); + if (picture_in_picture_interstitial_) + picture_in_picture_interstitial_->OnPosterImageChanged(); } else { HTMLMediaElement::ParseAttribute(params); } @@ -527,6 +534,22 @@ remoting_interstitial_->Hide(error_msg); } +void HTMLVideoElement::PictureInPictureStarted() { + if (!picture_in_picture_interstitial_) { + picture_in_picture_interstitial_ = new PictureInPictureInterstitial(*this); + ShadowRoot& shadow_root = EnsureUserAgentShadowRootV1(); + shadow_root.InsertBefore(picture_in_picture_interstitial_, + shadow_root.firstChild()); + HTMLMediaElement::AssertShadowRootChildren(shadow_root); + } + picture_in_picture_interstitial_->Show(); +} + +void HTMLVideoElement::PictureInPictureStopped() { + if (picture_in_picture_interstitial_) + picture_in_picture_interstitial_->Hide(); +} + WebMediaPlayer::DisplayType HTMLVideoElement::DisplayType() const { if (is_picture_in_picture_) return WebMediaPlayer::DisplayType::kPictureInPicture;
diff --git a/third_party/WebKit/Source/core/html/media/HTMLVideoElement.h b/third_party/WebKit/Source/core/html/media/HTMLVideoElement.h index f2fe629..0e1dac1 100644 --- a/third_party/WebKit/Source/core/html/media/HTMLVideoElement.h +++ b/third_party/WebKit/Source/core/html/media/HTMLVideoElement.h
@@ -43,6 +43,7 @@ class ImageBitmapOptions; class MediaCustomControlsFullscreenDetector; class MediaRemotingInterstitial; +class PictureInPictureInterstitial; class CORE_EXPORT HTMLVideoElement final : public HTMLMediaElement, public CanvasImageSource, @@ -146,6 +147,8 @@ bool IsRemotingInterstitialVisible() const; void MediaRemotingStarted(const WebString& remote_device_friendly_name) final; + void PictureInPictureStarted() final; + void PictureInPictureStopped() final; void MediaRemotingStopped(WebLocalizedString::Name error_msg) final; WebMediaPlayer::DisplayType DisplayType() const final; @@ -180,6 +183,7 @@ custom_controls_fullscreen_detector_; Member<MediaRemotingInterstitial> remoting_interstitial_; + Member<PictureInPictureInterstitial> picture_in_picture_interstitial_; AtomicString default_poster_url_;
diff --git a/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.cpp b/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.cpp new file mode 100644 index 0000000..c4909f4 --- /dev/null +++ b/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.cpp
@@ -0,0 +1,93 @@ +// 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 "core/html/media/PictureInPictureInterstitial.h" + +#include "bindings/core/v8/ExceptionState.h" +#include "core/dom/Document.h" +#include "core/html/HTMLImageElement.h" +#include "core/html/media/HTMLVideoElement.h" +#include "platform/text/PlatformLocale.h" +#include "public/platform/WebLocalizedString.h" +namespace { + +constexpr double kPictureInPictureStyleChangeTransSeconds = 0.2; +constexpr double kPictureInPictureHiddenAnimationSeconds = 0.3; + +} // namespace + +namespace blink { + +PictureInPictureInterstitial::PictureInPictureInterstitial( + HTMLVideoElement& videoElement) + : HTMLDivElement(videoElement.GetDocument()), + interstitial_timer_( + videoElement.GetDocument().GetTaskRunner(TaskType::kUnthrottled), + this, + &PictureInPictureInterstitial::ToggleInterstitialTimerFired), + video_element_(&videoElement) { + SetShadowPseudoId(AtomicString("-internal-picture-in-picture-interstitial")); + background_image_ = HTMLImageElement::Create(GetDocument()); + background_image_->SetShadowPseudoId( + AtomicString("-internal-picture-in-picture-background-image")); + background_image_->SetSrc(videoElement.getAttribute(HTMLNames::posterAttr)); + AppendChild(background_image_); + + HTMLDivElement* message_element_ = HTMLDivElement::Create(GetDocument()); + message_element_->SetShadowPseudoId( + AtomicString("-internal-picture-in-picture-message")); + message_element_->setInnerText( + GetVideoElement().GetLocale().QueryString( + WebLocalizedString::kPictureInPictureInterstitialText), + ASSERT_NO_EXCEPTION); + AppendChild(message_element_); +} + +void PictureInPictureInterstitial::Show() { + if (should_be_visible_) + return; + + if (interstitial_timer_.IsActive()) + interstitial_timer_.Stop(); + should_be_visible_ = true; + RemoveInlineStyleProperty(CSSPropertyDisplay); + interstitial_timer_.StartOneShot(kPictureInPictureStyleChangeTransSeconds, + FROM_HERE); +} + +void PictureInPictureInterstitial::Hide() { + if (!should_be_visible_) + return; + if (interstitial_timer_.IsActive()) + interstitial_timer_.Stop(); + should_be_visible_ = false; + SetInlineStyleProperty(CSSPropertyOpacity, 0, + CSSPrimitiveValue::UnitType::kNumber); + interstitial_timer_.StartOneShot(kPictureInPictureHiddenAnimationSeconds, + FROM_HERE); +} + +void PictureInPictureInterstitial::ToggleInterstitialTimerFired(TimerBase*) { + interstitial_timer_.Stop(); + if (should_be_visible_) { + SetInlineStyleProperty(CSSPropertyOpacity, 1, + CSSPrimitiveValue::UnitType::kNumber); + } else { + SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); + } +} + +void PictureInPictureInterstitial::OnPosterImageChanged() { + background_image_->SetSrc( + GetVideoElement().getAttribute(HTMLNames::posterAttr)); +} + +void PictureInPictureInterstitial::Trace(blink::Visitor* visitor) { + visitor->Trace(video_element_); + visitor->Trace(background_image_); + visitor->Trace(message_element_); + HTMLDivElement::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.h b/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.h new file mode 100644 index 0000000..bbafdf4 --- /dev/null +++ b/third_party/WebKit/Source/core/html/media/PictureInPictureInterstitial.h
@@ -0,0 +1,59 @@ +// 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 PictureInPictureInterstitial_h +#define PictureInPictureInterstitial_h + +#include "core/html/HTMLDivElement.h" +#include "platform/Timer.h" +#include "platform/WebTaskRunner.h" + +namespace blink { + +class HTMLImageElement; +class HTMLVideoElement; +// class PictureInPictureMessageElement; + +// Picture in Picture UI. DOM structure looks like: +// +// PictureInPictureInterstitial +// (-internal-picture-in-picture-interstitial) +// +-HTMLImageElement +// | (-internal-picture-in-picture-background-image) +// \-PictureInPictureMessageElement +// | (-internal-picture-in-picture-message) +class PictureInPictureInterstitial final : public HTMLDivElement { + public: + explicit PictureInPictureInterstitial(HTMLVideoElement&); + + void Show(); + void Hide(); + + void OnPosterImageChanged(); + bool IsVisible() const { return should_be_visible_; } + + HTMLVideoElement& GetVideoElement() const { return *video_element_; } + + // Element: + void Trace(blink::Visitor*) override; + + private: + // Node override. + bool IsPictureInPictureInterstitial() const override { return true; } + + void ToggleInterstitialTimerFired(TimerBase*); + + // Indicates whether the interstitial should be visible. It is updated + // when Show()/Hide() is called. + bool should_be_visible_ = false; + + TaskRunnerTimer<PictureInPictureInterstitial> interstitial_timer_; + Member<HTMLVideoElement> video_element_; + Member<HTMLImageElement> background_image_; + Member<HTMLDivElement> message_element_; +}; + +} // namespace blink + +#endif // PictureInPictureInterstitial_h
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp index e74aaa3..7dfbb4f 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.cpp +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -258,8 +258,13 @@ // page. Furthermore, mousemove events before the first layout should not // lead to a premature layout() happening, which could show a flash of white. // See also the similar code in Document::performMouseEventHitTest. + // The check to LifecycleUpdatesActive() prevents hit testing to frames + // that have already had layout but are throttled to prevent painting + // because the current Document isn't ready to render yet. In that case + // the lifecycle update prompted by HitTest() would fail. if (!frame_->ContentLayoutObject() || !frame_->View() || - !frame_->View()->DidFirstLayout()) + !frame_->View()->DidFirstLayout() || + !frame_->View()->LifecycleUpdatesActive()) return result; frame_->ContentLayoutObject()->HitTest(result);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp index 4c4fe133..45e86bdc 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -178,14 +178,15 @@ bool& found_non_transparent_color, bool& found_opaque_color, const LayoutObject& layout_object) { - Vector<Color> stop_colors; - gradient->GetStopColors(stop_colors, layout_object); + const Document& document = layout_object.GetDocument(); + const ComputedStyle& style = layout_object.StyleRef(); + Vector<Color> stop_colors = gradient->GetStopColors(document, style); if (colors.IsEmpty()) { colors.AppendRange(stop_colors.begin(), stop_colors.end()); } else { if (colors.size() > 1) { - // Gradient on gradient is too complicated, bail out + // Gradient on gradient is too complicated, bail out. colors.clear(); return; } @@ -198,9 +199,8 @@ colors.push_back(existing_color.Blend(stop_color)); } } - found_opaque_color = found_opaque_color || - gradient->KnownToBeOpaque(layout_object.GetDocument(), - layout_object.StyleRef()); + found_opaque_color = + found_opaque_color || gradient->KnownToBeOpaque(document, style); } // Gets the colors from an image style, if one exists and it is a gradient.
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp index ebb4043d..31ef4c90 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
@@ -18,6 +18,7 @@ #include "core/dom/QualifiedName.h" #include "core/frame/LocalFrame.h" #include "core/html/HTMLFrameOwnerElement.h" +#include "core/html/HTMLImageElement.h" #include "core/html/HTMLLinkElement.h" #include "core/html/HTMLTemplateElement.h" #include "core/html/forms/HTMLInputElement.h" @@ -259,6 +260,10 @@ value->setPseudoElementIndexes( VisitPseudoElements(element, include_event_listeners)); } + + HTMLImageElement* image_element = ToHTMLImageElementOrNull(node); + if (image_element) + value->setCurrentSourceURL(image_element->currentSrc()); } else if (node->IsDocumentNode()) { Document* document = ToDocument(node); value->setDocumentURL(InspectorDOMAgent::DocumentURLString(document));
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 52ca171..b4f0f4e 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -4325,6 +4325,12 @@ "items": { "$ref": "DOMDebugger.EventListener" } + }, + { + "name": "currentSourceURL", + "description": "The selected url for nodes with a srcset attribute.", + "optional": true, + "type": "string" } ] },
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.pdl b/third_party/WebKit/Source/core/inspector/browser_protocol.pdl index 97803be..f5714ff 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.pdl +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.pdl
@@ -1981,6 +1981,8 @@ optional boolean isClickable # Details of the node's event listeners, if any. optional array of DOMDebugger.EventListener eventListeners + # The selected url for nodes with a srcset attribute. + optional string currentSourceURL # Details of post layout rendered text positions. The exact layout should not be regarded as # stable and may change between versions.
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp index 6a9162d..c6e1d4a 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -32,7 +32,6 @@ #include "core/layout/LayoutFlexibleBox.h" #include "core/layout/LayoutGeometryMap.h" #include "core/layout/LayoutInline.h" -#include "core/layout/LayoutTableCell.h" #include "core/layout/LayoutView.h" #include "core/paint/ObjectPaintInvalidator.h" #include "core/paint/PaintLayer.h" @@ -807,9 +806,7 @@ LayoutBlock* containing_block = ContainingBlock(); // The location container for boxes is not always the containing block. LayoutObject* location_container = - IsLayoutInline() || IsTableCell() - ? Container() - : ToLayoutBox(this)->LocationContainer(); + IsLayoutInline() ? Container() : ToLayoutBox(this)->LocationContainer(); // Skip anonymous containing blocks. while (containing_block->IsAnonymous()) { containing_block = containing_block->ContainingBlock();
diff --git a/third_party/WebKit/Source/core/layout/LayoutMedia.cpp b/third_party/WebKit/Source/core/layout/LayoutMedia.cpp index 091bc25..b0f86512 100644 --- a/third_party/WebKit/Source/core/layout/LayoutMedia.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutMedia.cpp
@@ -59,19 +59,21 @@ // overlap checking, see LayoutVTTCue. #if DCHECK_IS_ON() bool seen_text_track_container = false; - bool seen_media_remoting_interstitial = false; + bool seen_interstitial = false; #endif for (LayoutObject* child = children_.LastChild(); child; child = child->PreviousSibling()) { #if DCHECK_IS_ON() if (child->GetNode()->IsMediaControls()) { DCHECK(!seen_text_track_container); - DCHECK(!seen_media_remoting_interstitial); + DCHECK(!seen_interstitial); } else if (child->GetNode()->IsTextTrackContainer()) { seen_text_track_container = true; - DCHECK(!seen_media_remoting_interstitial); - } else if (child->GetNode()->IsMediaRemotingInterstitial()) { - seen_media_remoting_interstitial = true; + DCHECK(!seen_interstitial); + } else if (child->GetNode()->IsMediaRemotingInterstitial() || + child->GetNode()->IsPictureInPictureInterstitial()) { + // Only one interstitial can be shown at a time. + seen_interstitial = true; } else { NOTREACHED(); } @@ -122,7 +124,8 @@ return child->IsFlexibleBox(); if (child->GetNode()->IsTextTrackContainer() || - child->GetNode()->IsMediaRemotingInterstitial()) + child->GetNode()->IsMediaRemotingInterstitial() || + child->GetNode()->IsPictureInPictureInterstitial()) return true; return false;
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.h b/third_party/WebKit/Source/core/layout/LayoutTableRow.h index 201e457a..e6cfb7e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableRow.h +++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.h
@@ -139,7 +139,7 @@ PaintLayerType LayerTypeRequired() const override { if (HasTransformRelatedProperty() || HasHiddenBackface() || HasClipPath() || CreatesGroup() || Style()->ShouldCompositeForCurrentAnimations() || - IsInFlowPositioned()) + IsStickyPositioned()) return kNormalPaintLayer; if (HasOverflowClip())
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.cpp b/third_party/WebKit/Source/core/loader/ImageLoader.cpp index 2dd045f..48e3cc0 100644 --- a/third_party/WebKit/Source/core/loader/ImageLoader.cpp +++ b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
@@ -761,6 +761,8 @@ return ScriptPromise(); } + UseCounter::Count(GetElement()->GetDocument(), WebFeature::kImageDecodeAPI); + auto* request = new DecodeRequest(this, ScriptPromiseResolver::Create(script_state)); Microtask::EnqueueMicrotask(
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp index bd026e0a..38b44a7 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
@@ -272,20 +272,23 @@ ClipRect& background_rect, ClipRect& foreground_rect, const LayoutPoint* offset_from_root) const { - LayoutPoint offset(context.sub_pixel_accumulation); if (offset_from_root) { - offset = *offset_from_root; + layer_bounds.SetLocation(*offset_from_root); } else { + layer_bounds.SetX(context.sub_pixel_accumulation.Width()); + layer_bounds.SetY(context.sub_pixel_accumulation.Height()); // This takes into account not just PaintLayer offset, but // conversion of flow thread to visual coordinates for intervening // fragmentation. if (layer_.ShouldFragmentCompositedBounds(context.root_layer)) { PaintLayer* enclosing_pagination_layer = layer_.EnclosingPaginationLayer(); - layer_.ConvertToLayerCoords(enclosing_pagination_layer, offset); - offset.MoveBy(fragment_data.PaginationOffset()); - offset.MoveBy(enclosing_pagination_layer->VisualOffsetFromAncestor( + LayoutPoint location(layer_bounds.Location()); + layer_.ConvertToLayerCoords(enclosing_pagination_layer, location); + location.MoveBy(fragment_data.PaginationOffset()); + location.MoveBy(enclosing_pagination_layer->VisualOffsetFromAncestor( context.root_layer)); + layer_bounds.SetLocation(location); } else { const auto* current_transform = fragment_data.PreEffectProperties().Transform(); @@ -295,43 +298,48 @@ root_fragment.LocalBorderBoxProperties()->Transform(); if (&layer_ == context.root_layer || current_transform == root_transform) { - offset.MoveBy(fragment_data.PaintOffset()); - offset.MoveBy(-root_fragment.PaintOffset()); + layer_bounds.MoveBy(fragment_data.PaintOffset()); + layer_bounds.MoveBy(-root_fragment.PaintOffset()); } else { const TransformationMatrix& transform = GeometryMapper::SourceToDestinationProjection(current_transform, root_transform); if (transform.IsIdentityOr2DTranslation()) { - offset.MoveBy(fragment_data.PaintOffset()); + layer_bounds.MoveBy(fragment_data.PaintOffset()); // The transform should be an integer translation, up to floating // point error. - offset.Move(LayoutSize((float)transform.E(), (float)transform.F())); - offset.MoveBy(-root_fragment.PaintOffset()); + layer_bounds.Move( + LayoutSize((float)transform.E(), (float)transform.F())); + layer_bounds.MoveBy(-root_fragment.PaintOffset()); } else { // This branch can happen due to perspective transforms. // TODO(chrishtr): investigate whether the paint code is broken // in this case. - layer_.ConvertToLayerCoords(context.root_layer, offset); + LayoutPoint location(layer_bounds.Location()); + layer_.ConvertToLayerCoords(context.root_layer, location); + layer_bounds.SetLocation(location); } } } } - layer_bounds = LayoutRect(offset, LayoutSize(layer_.PixelSnappedSize())); + layer_bounds.SetSize(LayoutSize(layer_.PixelSnappedSize())); CalculateBackgroundClipRectWithGeometryMapper(context, fragment_data, background_rect); background_rect.Intersect(paint_dirty_rect); - foreground_rect = background_rect; if (ShouldClipOverflow(context)) { LayoutBoxModelObject& layout_object = layer_.GetLayoutObject(); - LayoutRect overflow_and_clip_rect = + foreground_rect = ToLayoutBox(layout_object) - .OverflowClipRect(offset, context.overlay_scrollbar_clip_behavior); - foreground_rect.Intersect(overflow_and_clip_rect); + .OverflowClipRect(layer_bounds.Location(), + context.overlay_scrollbar_clip_behavior); if (layout_object.StyleRef().HasBorderRadius()) foreground_rect.SetHasRadius(true); + foreground_rect.Intersect(background_rect); + } else { + foreground_rect = background_rect; } } @@ -483,10 +491,10 @@ return; } - PropertyTreeState source_property_tree_state(nullptr, nullptr, nullptr); + PropertyTreeState* source_property_tree_state = nullptr; PropertyTreeState destination_property_tree_state(nullptr, nullptr, nullptr); InitializeCommonClipRectState(context, fragment_data, - source_property_tree_state, + &source_property_tree_state, destination_property_tree_state); // The background rect applies all clips *above* m_layer, but not the overflow @@ -511,16 +519,16 @@ clip_behavior = kIgnorePlatformOverlayScrollbarSize; FloatClipRect clip_rect((FloatRect(LocalVisualRect(context)))); - clip_rect.MoveBy(FloatPoint(fragment_data.PaintOffset())); + clip_rect.MoveBy(FloatPoint(fragment_data.PaintOffset())); - GeometryMapper::LocalToAncestorVisualRect(source_property_tree_state, - destination_property_tree_state, - clip_rect, clip_behavior); - output.SetRect(clip_rect); + GeometryMapper::LocalToAncestorVisualRect(*source_property_tree_state, + destination_property_tree_state, + clip_rect, clip_behavior); + output.SetRect(clip_rect); } else { const FloatClipRect& clipped_rect_in_root_layer_space = GeometryMapper::LocalToAncestorClipRect( - source_property_tree_state, destination_property_tree_state, + *source_property_tree_state, destination_property_tree_state, context.overlay_scrollbar_clip_behavior); output.SetRect(clipped_rect_in_root_layer_space); } @@ -535,11 +543,12 @@ void PaintLayerClipper::InitializeCommonClipRectState( const ClipRectsContext& context, const FragmentData& fragment_data, - PropertyTreeState& source_property_tree_state, + PropertyTreeState** source_property_tree_state, PropertyTreeState& destination_property_tree_state) const { DCHECK(use_geometry_mapper_); DCHECK(fragment_data.LocalBorderBoxProperties()); - source_property_tree_state = *fragment_data.LocalBorderBoxProperties(); + *source_property_tree_state = + const_cast<PropertyTreeState*>(fragment_data.LocalBorderBoxProperties()); DCHECK(context.root_layer->GetLayoutObject() .FirstFragment()
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.h b/third_party/WebKit/Source/core/paint/PaintLayerClipper.h index 611e2a2..2b57266 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.h +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.h
@@ -219,8 +219,8 @@ ALWAYS_INLINE void InitializeCommonClipRectState( const ClipRectsContext&, const FragmentData&, - PropertyTreeState& descendant_property_tree_state, - PropertyTreeState& ancestor_property_tree_state) const; + PropertyTreeState** source_property_tree_state, + PropertyTreeState& destination_property_tree_state) const; // Same as calculateRects, but using GeometryMapper. ALWAYS_INLINE void CalculateRectsWithGeometryMapper(
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp index 54a8140..44e3a39d 100644 --- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp +++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -136,7 +136,7 @@ if (!object.HasLayer()) return; - PaintLayer* paint_layer = object.EnclosingLayer(); + PaintLayer* paint_layer = ToLayoutBoxModelObject(object).Layer(); paint_layer->UpdateAncestorOverflowLayer( context.ancestor_overflow_paint_layer);
diff --git a/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc b/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc index 033da33..0f0edad 100644 --- a/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/WebKit/Source/core/paint/ng/ng_box_fragment_painter.cc
@@ -20,6 +20,7 @@ #include "core/paint/PaintInfo.h" #include "core/paint/PaintLayer.h" #include "core/paint/PaintPhase.h" +#include "core/paint/ScrollRecorder.h" #include "core/paint/ScrollableAreaPainter.h" #include "core/paint/ng/ng_box_clipper.h" #include "core/paint/ng/ng_fragment_painter.h" @@ -172,26 +173,52 @@ // ObjectPainter(box_fragment_) // .AddPDFURLRectIfNeeded(paint_info, paint_offset); - // TODO(layout-dev): Add support for scrolling. - Optional<PaintInfo> scrolled_paint_info; + if (paint_phase != PaintPhase::kSelfOutlineOnly) { + // TODO(layout-dev): Figure out where paint properties should live. + const auto& layout_object = *box_fragment_.GetLayoutObject(); + Optional<PaintInfo> scrolled_paint_info; + if (const auto* fragment = paint_info.FragmentToPaint(layout_object)) { + Optional<ScopedPaintChunkProperties> scoped_scroll_property; + Optional<ScrollRecorder> scroll_recorder; + DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled()); + const auto* object_properties = fragment->PaintProperties(); + auto* scroll_translation = + object_properties ? object_properties->ScrollTranslation() : nullptr; + if (scroll_translation) { + scoped_scroll_property.emplace( + paint_info.context.GetPaintController(), scroll_translation, + box_fragment_, DisplayItem::PaintPhaseToScrollType(paint_phase)); + scrolled_paint_info.emplace(paint_info); + if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { + scrolled_paint_info->UpdateCullRectForScrollingContents( + EnclosingIntRect(box_fragment_.OverflowClipRect( + paint_offset, kIgnorePlatformOverlayScrollbarSize)), + scroll_translation->Matrix().ToAffineTransform()); + } else { + scrolled_paint_info->UpdateCullRect( + scroll_translation->Matrix().ToAffineTransform()); + } + } + } - const PaintInfo& contents_paint_info = - scrolled_paint_info ? *scrolled_paint_info : paint_info; + const PaintInfo& contents_paint_info = + scrolled_paint_info ? *scrolled_paint_info : paint_info; - // Paint our background, border and box-shadow. - // TODO(eae): We should only paint box-decorations during the foreground phase - // for inline boxes. Split this method into PaintBlock and PaintInline once we - // can tell the two types of fragments apart or we've eliminated the extra - // block wrapper fragments. - if (paint_info.phase == PaintPhase::kForeground && is_inline_) - PaintBoxDecorationBackground(paint_info, paint_offset); + // Paint our background, border and box-shadow. + // TODO(eae): We should only paint box-decorations during the foreground + // phase for inline boxes. Split this method into PaintBlock and PaintInline + // once we can tell the two types of fragments apart or we've eliminated the + // extra block wrapper fragments. + if (paint_info.phase == PaintPhase::kForeground && is_inline_) + PaintBoxDecorationBackground(paint_info, paint_offset); - PaintContents(contents_paint_info, paint_offset); + PaintContents(contents_paint_info, paint_offset); - if (paint_phase == PaintPhase::kFloat || - paint_phase == PaintPhase::kSelection || - paint_phase == PaintPhase::kTextClip) - PaintFloats(contents_paint_info, paint_offset); + if (paint_phase == PaintPhase::kFloat || + paint_phase == PaintPhase::kSelection || + paint_phase == PaintPhase::kTextClip) + PaintFloats(contents_paint_info, paint_offset); + } if (ShouldPaintSelfOutline(paint_phase)) NGFragmentPainter(box_fragment_).PaintOutline(paint_info, paint_offset);
diff --git a/third_party/WebKit/Source/core/svg/SVGImageElement.cpp b/third_party/WebKit/Source/core/svg/SVGImageElement.cpp index 2754ced..c6cda0d0 100644 --- a/third_party/WebKit/Source/core/svg/SVGImageElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
@@ -23,6 +23,7 @@ #include "core/CSSPropertyNames.h" #include "core/css/StyleChangeReason.h" +#include "core/frame/UseCounter.h" #include "core/layout/LayoutImageResource.h" #include "core/layout/svg/LayoutSVGImage.h" #include "core/svg_names.h" @@ -155,6 +156,7 @@ const AttributeModificationParams& params) { if (params.name == SVGNames::decodingAttr && RuntimeEnabledFeatures::ImageDecodingAttributeEnabled()) { + UseCounter::Count(GetDocument(), WebFeature::kImageDecodingAttribute); decoding_mode_ = ParseImageDecodingMode(params.new_value); } else { SVGElement::ParseAttribute(params);
diff --git a/third_party/WebKit/Source/core/timing/Performance.cpp b/third_party/WebKit/Source/core/timing/Performance.cpp index 2295bc8..e5e8a53a 100644 --- a/third_party/WebKit/Source/core/timing/Performance.cpp +++ b/third_party/WebKit/Source/core/timing/Performance.cpp
@@ -150,8 +150,7 @@ if (!info) return nullptr; WebVector<WebServerTimingInfo> server_timing = - PerformanceServerTiming::ParseServerTiming( - *info, PerformanceServerTiming::ShouldAllowTimingDetails::Yes); + PerformanceServerTiming::ParseServerTiming(*info); if (!server_timing.empty()) UseCounter::Count(GetFrame(), WebFeature::kPerformanceServerTiming); return new PerformanceNavigationTiming(GetFrame(), info, GetTimeOrigin(),
diff --git a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp index fe89486..a363c80 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceBase.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceBase.cpp
@@ -365,7 +365,14 @@ redirect_chain.back().GetResourceLoadTiming()->ReceiveHeadersEnd(); if (!result.allow_redirect_details) { - result.start_time = final_response.GetResourceLoadTiming()->RequestTime(); + // TODO(https://crbug.com/803913): There was previously a DCHECK that + // |final_timing| is non-null. However, it clearly can be null: removing + // this check caused https://crbug.com/803811. Figure out how this can + // happen so test coverage can be added. + if (ResourceLoadTiming* final_timing = + final_response.GetResourceLoadTiming()) { + result.start_time = final_timing->RequestTime(); + } } } else { result.allow_redirect_details = false; @@ -378,10 +385,9 @@ result.did_reuse_connection = final_response.ConnectionReused(); result.allow_negative_values = info.NegativeAllowed(); - result.server_timing = PerformanceServerTiming::ParseServerTiming( - info, result.allow_timing_details - ? PerformanceServerTiming::ShouldAllowTimingDetails::Yes - : PerformanceServerTiming::ShouldAllowTimingDetails::No); + if (result.allow_timing_details) { + result.server_timing = PerformanceServerTiming::ParseServerTiming(info); + } if (!result.server_timing.empty()) { UseCounter::Count(&context_for_use_counter, WebFeature::kPerformanceServerTiming);
diff --git a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.cpp index 9316641..4894f47 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.cpp
@@ -27,8 +27,7 @@ } WebVector<WebServerTimingInfo> PerformanceServerTiming::ParseServerTiming( - const ResourceTimingInfo& info, - ShouldAllowTimingDetails should_allow_timing_details) { + const ResourceTimingInfo& info) { WebVector<WebServerTimingInfo> result; if (RuntimeEnabledFeatures::ServerTimingEnabled()) { const ResourceResponse& response = info.FinalResponse(); @@ -36,12 +35,8 @@ response.HttpHeaderField(HTTPNames::Server_Timing)); result.reserve(headers->size()); for (const auto& header : *headers) { - if (should_allow_timing_details == ShouldAllowTimingDetails::Yes) { - result.emplace_back(header->Name(), header->Duration(), - header->Description()); - } else { - result.emplace_back(header->Name(), 0.0, String()); - } + result.emplace_back(header->Name(), header->Duration(), + header->Description()); } } return result;
diff --git a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.h b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.h index 50724039..0c18ed5 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.h +++ b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.h
@@ -20,11 +20,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - enum class ShouldAllowTimingDetails { - Yes, - No, - }; - ~PerformanceServerTiming(); const String& name() const { return name_; } @@ -32,8 +27,7 @@ const String& description() const { return description_; } static WebVector<WebServerTimingInfo> ParseServerTiming( - const ResourceTimingInfo&, - ShouldAllowTimingDetails); + const ResourceTimingInfo&); static HeapVector<Member<PerformanceServerTiming>> FromParsedServerTiming( const WebVector<WebServerTimingInfo>&);
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn index 14dc62d..5e745c20 100644 --- a/third_party/WebKit/Source/devtools/BUILD.gn +++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -433,10 +433,8 @@ "front_end/performance_test_runner/TimelineDataTestRunner.js", "front_end/performance_test_runner/TimelineTestRunner.js", "front_end/persistence/Automapping.js", - "front_end/persistence/DefaultMapping.js", "front_end/persistence/editFileSystemView.css", "front_end/persistence/EditFileSystemView.js", - "front_end/persistence/FileSystemMapping.js", "front_end/persistence/FileSystemWorkspaceBinding.js", "front_end/persistence/IsolatedFileSystem.js", "front_end/persistence/IsolatedFileSystemManager.js", @@ -651,7 +649,6 @@ "front_end/sources/ThreadsSidebarPane.js", "front_end/sources/watchExpressionsSidebarPane.css", "front_end/sources/WatchExpressionsSidebarPane.js", - "front_end/sources/WorkspaceMappingTip.js", "front_end/sources/xhrBreakpointsSidebarPane.css", "front_end/sources/XHRBreakpointsSidebarPane.js", "front_end/sources_test_runner/AutocompleteTestRunner.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js index 941d976..4448b50 100644 --- a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js
@@ -69,7 +69,7 @@ dump(UI.panels.resources._sidebar._resourcesSection._treeElement, ''); if (!ApplicationTestRunner._testSourceNavigator) { - ApplicationTestRunner._testSourceNavigator = new Sources.SourcesNavigatorView(); + ApplicationTestRunner._testSourceNavigator = new Sources.NetworkNavigatorView(); ApplicationTestRunner._testSourceNavigator.show(UI.inspectorView.element); }
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js index e99f25c..65e54f5 100644 --- a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js
@@ -67,14 +67,6 @@ InspectorFrontendHostAPI.Events.FileSystemRemoved, this.fileSystemPath); }, - addFileMapping: function(urlPrefix, pathPrefix) { - var fileSystemMapping = new Persistence.FileSystemMapping(Persistence.isolatedFileSystemManager); - fileSystemMapping._addFileSystemPath(this.fileSystemPath); - fileSystemMapping.addFileMapping(this.fileSystemPath, urlPrefix, pathPrefix); - fileSystemMapping.dispose(); - Persistence.fileSystemMapping._loadFromSettings(); - }, - addFile: function(path, content, lastModified) { var pathTokens = path.split('/'); var node = this.root;
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js index 58be5f5..6861c31 100644 --- a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js
@@ -41,13 +41,6 @@ .addFile('foo.js', '\n\nwindow.foo = ()=>\'foo\';'); }; -BindingsTestRunner.forceUseDefaultMapping = function() { - Persistence.persistence._setMappingForTest((bindingCreated, bindingRemoved) => { - return new Persistence.DefaultMapping( - Workspace.workspace, Persistence.fileSystemMapping, bindingCreated, bindingRemoved); - }); -}; - BindingsTestRunner.initializeTestMapping = function() { var testMapping;
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/SensorsView.js b/third_party/WebKit/Source/devtools/front_end/emulation/SensorsView.js index 6d1bf14..eb4736c 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/SensorsView.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/SensorsView.js
@@ -82,7 +82,7 @@ this._latitudeInput.value = 0; this._latitudeSetter = UI.bindInput( this._latitudeInput, this._applyGeolocationUserInput.bind(this), - SDK.EmulationModel.Geolocation.latitudeValidator, true); + SDK.EmulationModel.Geolocation.latitudeValidator, true, 0.1); this._latitudeSetter(String(geolocation.latitude)); this._longitudeInput = UI.createInput('', 'number'); @@ -91,9 +91,14 @@ this._longitudeInput.value = 0; this._longitudeSetter = UI.bindInput( this._longitudeInput, this._applyGeolocationUserInput.bind(this), - SDK.EmulationModel.Geolocation.longitudeValidator, true); + SDK.EmulationModel.Geolocation.longitudeValidator, true, 0.1); this._longitudeSetter(String(geolocation.longitude)); + var cmdOrCtrl = Host.isMac() ? '\u2318' : 'Ctrl'; + var modifierKeyMessage = ls`Adjust with mousewheel or up/down keys. ${cmdOrCtrl}: ±10, Shift: ±1, Alt: ±0.01`; + this._latitudeInput.title = modifierKeyMessage; + this._longitudeInput.title = modifierKeyMessage; + latitudeGroup.createChild('div', 'latlong-title').textContent = Common.UIString('Latitude'); longitudeGroup.createChild('div', 'latlong-title').textContent = Common.UIString('Longitude'); }
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index a35ea67..ee3aed6a 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -119,7 +119,6 @@ Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true); Runtime.experiments.register('logManagement', 'Log management', true); Runtime.experiments.register('performanceMonitor', 'Performance Monitor', true); - Runtime.experiments.register('persistence2', 'Persistence 2.0'); Runtime.experiments.register('sourceDiff', 'Source diff'); Runtime.experiments.register( 'stepIntoAsync', 'Introduce separate step action, stepInto becomes powerful enough to go inside async call'); @@ -149,8 +148,8 @@ } Runtime.experiments.setDefaultExperiments([ - 'accessibilityInspection', 'colorContrastRatio', 'logManagement', 'performanceMonitor', 'persistence2', - 'stepIntoAsync', 'timelineKeepHistory' + 'accessibilityInspection', 'colorContrastRatio', 'logManagement', 'performanceMonitor', 'stepIntoAsync', + 'timelineKeepHistory' ]); } @@ -196,7 +195,6 @@ Workspace.fileManager = new Workspace.FileManager(); Workspace.workspace = new Workspace.Workspace(); - Persistence.fileSystemMapping = new Persistence.FileSystemMapping(Persistence.isolatedFileSystemManager); Bindings.networkProjectManager = new Bindings.NetworkProjectManager(SDK.targetManager, Workspace.workspace); Bindings.resourceMapping = new Bindings.ResourceMapping(SDK.targetManager, Workspace.workspace); @@ -208,8 +206,7 @@ Extensions.extensionServer = new Extensions.ExtensionServer(); new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, Workspace.workspace); - Persistence.persistence = - new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager, Persistence.fileSystemMapping); + Persistence.persistence = new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager); Persistence.networkPersistenceManager = new Persistence.NetworkPersistenceManager(Workspace.workspace); new Main.ExecutionContextSelector(SDK.targetManager, UI.context);
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/DefaultMapping.js b/third_party/WebKit/Source/devtools/front_end/persistence/DefaultMapping.js deleted file mode 100644 index 761c21e..0000000 --- a/third_party/WebKit/Source/devtools/front_end/persistence/DefaultMapping.js +++ /dev/null
@@ -1,149 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/** - * @implements {Persistence.MappingSystem} - * @unrestricted - */ -Persistence.DefaultMapping = class { - /** - * @param {!Workspace.Workspace} workspace - * @param {!Persistence.FileSystemMapping} fileSystemMapping - * @param {function(!Persistence.PersistenceBinding)} onBindingCreated - * @param {function(!Persistence.PersistenceBinding)} onBindingRemoved - */ - constructor(workspace, fileSystemMapping, onBindingCreated, onBindingRemoved) { - this._workspace = workspace; - this._fileSystemMapping = fileSystemMapping; - /** @type {!Set<!Persistence.PersistenceBinding>} */ - this._bindings = new Set(); - this._onBindingCreated = onBindingCreated; - this._onBindingRemoved = onBindingRemoved; - - this._eventListeners = [ - workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, this._onUISourceCodeAdded, this), - workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeRemoved, this._onUISourceCodeRemoved, this), - workspace.addEventListener(Workspace.Workspace.Events.ProjectRemoved, this._onProjectRemoved, this), - this._fileSystemMapping.addEventListener( - Persistence.FileSystemMapping.Events.FileMappingAdded, this._remap, this), - this._fileSystemMapping.addEventListener( - Persistence.FileSystemMapping.Events.FileMappingRemoved, this._remap, this) - ]; - this._remap(); - } - - _remap() { - for (var binding of this._bindings.valuesArray()) - this._unbind(binding.network); - var networkProjects = this._workspace.projectsForType(Workspace.projectTypes.Network); - for (var networkProject of networkProjects) { - for (var uiSourceCode of networkProject.uiSourceCodes()) - this._bind(uiSourceCode); - } - } - - /** - * @param {!Common.Event} event - */ - _onUISourceCodeAdded(event) { - var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data); - this._bind(uiSourceCode); - } - - /** - * @param {!Common.Event} event - */ - _onUISourceCodeRemoved(event) { - var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data); - this._unbind(uiSourceCode); - } - - /** - * @param {!Common.Event} event - */ - _onProjectRemoved(event) { - var project = /** @type {!Workspace.Project} */ (event.data); - for (var uiSourceCode of project.uiSourceCodes()) - this._unbind(uiSourceCode); - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - * @return {?Persistence.PersistenceBinding} - */ - _createBinding(uiSourceCode) { - if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) { - var fileSystemPath = Persistence.FileSystemWorkspaceBinding.fileSystemPath(uiSourceCode.project().id()); - var networkURL = this._fileSystemMapping.networkURLForFileSystemURL(fileSystemPath, uiSourceCode.url()); - var networkSourceCode = networkURL ? this._workspace.uiSourceCodeForURL(networkURL) : null; - return networkSourceCode ? new Persistence.PersistenceBinding(networkSourceCode, uiSourceCode, false) : null; - } - if (uiSourceCode.project().type() === Workspace.projectTypes.Network) { - var file = this._fileSystemMapping.fileForURL(uiSourceCode.url()); - var projectId = file ? Persistence.FileSystemWorkspaceBinding.projectId(file.fileSystemPath) : null; - var fileSourceCode = file && projectId ? this._workspace.uiSourceCode(projectId, file.fileURL) : null; - return fileSourceCode ? new Persistence.PersistenceBinding(uiSourceCode, fileSourceCode, false) : null; - } - return null; - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - */ - _bind(uiSourceCode) { - console.assert(!uiSourceCode[Persistence.DefaultMapping._binding], 'Cannot bind already bound UISourceCode!'); - var binding = this._createBinding(uiSourceCode); - if (!binding) - return; - // TODO(lushnikov): remove this check once there's a single uiSourceCode per url. @see crbug.com/670180 - if (binding.network[Persistence.DefaultMapping._binding] || binding.fileSystem[Persistence.DefaultMapping._binding]) - return; - - this._bindings.add(binding); - binding.network[Persistence.DefaultMapping._binding] = binding; - binding.fileSystem[Persistence.DefaultMapping._binding] = binding; - - binding.fileSystem.addEventListener( - Workspace.UISourceCode.Events.TitleChanged, this._onFileSystemUISourceCodeRenamed, this); - - this._onBindingCreated.call(null, binding); - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - */ - _unbind(uiSourceCode) { - var binding = uiSourceCode[Persistence.DefaultMapping._binding]; - if (!binding) - return; - this._bindings.delete(binding); - binding.network[Persistence.DefaultMapping._binding] = null; - binding.fileSystem[Persistence.DefaultMapping._binding] = null; - - binding.fileSystem.removeEventListener( - Workspace.UISourceCode.Events.TitleChanged, this._onFileSystemUISourceCodeRenamed, this); - - this._onBindingRemoved.call(null, binding); - } - - /** - * @param {!Common.Event} event - */ - _onFileSystemUISourceCodeRenamed(event) { - var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data); - var binding = uiSourceCode[Persistence.DefaultMapping._binding]; - this._unbind(binding.network); - this._bind(binding.network); - } - - /** - * @override - */ - dispose() { - for (var binding of this._bindings.valuesArray()) - this._unbind(binding.network); - Common.EventTarget.removeEventListeners(this._eventListeners); - } -}; - -Persistence.DefaultMapping._binding = Symbol('DefaultMapping.Binding');
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/EditFileSystemView.js b/third_party/WebKit/Source/devtools/front_end/persistence/EditFileSystemView.js index ee6412f..40810a71 100644 --- a/third_party/WebKit/Source/devtools/front_end/persistence/EditFileSystemView.js +++ b/third_party/WebKit/Source/devtools/front_end/persistence/EditFileSystemView.js
@@ -41,31 +41,12 @@ this._fileSystemPath = fileSystemPath; this._eventListeners = [ - Persistence.fileSystemMapping.addEventListener( - Persistence.FileSystemMapping.Events.FileMappingAdded, this._update, this), - Persistence.fileSystemMapping.addEventListener( - Persistence.FileSystemMapping.Events.FileMappingRemoved, this._update, this), Persistence.isolatedFileSystemManager.addEventListener( Persistence.IsolatedFileSystemManager.Events.ExcludedFolderAdded, this._update, this), Persistence.isolatedFileSystemManager.addEventListener( Persistence.IsolatedFileSystemManager.Events.ExcludedFolderRemoved, this._update, this) ]; - - if (!Runtime.experiments.isEnabled('persistence2')) { - this._mappingsList = new UI.ListWidget(this); - this._mappingsList.element.classList.add('file-system-list'); - this._mappingsList.registerRequiredCSS('persistence/editFileSystemView.css'); - var mappingsPlaceholder = createElementWithClass('div', 'file-system-list-empty'); - var mappingsHeader = this.contentElement.createChild('div', 'file-system-header'); - mappingsHeader.createChild('div', 'file-system-header-text').textContent = Common.UIString('Mappings'); - mappingsPlaceholder.textContent = Common.UIString('None'); - mappingsHeader.appendChild( - UI.createTextButton(Common.UIString('Add'), this._addMappingButtonClicked.bind(this), 'add-button')); - this._mappingsList.setEmptyPlaceholder(mappingsPlaceholder); - this._mappingsList.show(this.contentElement); - } - var excludedFoldersHeader = this.contentElement.createChild('div', 'file-system-header'); excludedFoldersHeader.createChild('div', 'file-system-header-text').textContent = Common.UIString('Excluded folders'); @@ -91,8 +72,6 @@ if (this._muteUpdate) return; - this._mappings = []; - this._excludedFoldersList.clear(); this._excludedFolders = []; for (var folder of Persistence.isolatedFileSystemManager.fileSystem(this._fileSystemPath) @@ -101,21 +80,6 @@ this._excludedFolders.push(folder); this._excludedFoldersList.appendItem(folder, true); } - - if (Runtime.experiments.isEnabled('persistence2')) - return; - - this._mappingsList.clear(); - var mappings = Persistence.fileSystemMapping.mappingEntries(this._fileSystemPath); - for (var entry of mappings) { - this._mappingsList.appendItem(entry, true); - this._mappings.push(entry); - } - } - - _addMappingButtonClicked() { - var entry = new Persistence.FileSystemMapping.Entry(this._fileSystemPath, '', ''); - this._mappingsList.addNewItem(0, entry); } _addExcludedFolderButtonClicked() { @@ -130,21 +94,10 @@ */ renderItem(item, editable) { var element = createElementWithClass('div', 'file-system-list-item'); - if (item instanceof Persistence.FileSystemMapping.Entry) { - var entry = /** @type {!Persistence.FileSystemMapping.Entry} */ (item); - var urlPrefixElement = element.createChild('div', 'file-system-value'); - urlPrefixElement.textContent = entry.urlPrefix; - urlPrefixElement.title = entry.urlPrefix; - element.createChild('div', 'file-system-separator'); - var pathPrefixElement = element.createChild('div', 'file-system-value'); - pathPrefixElement.textContent = entry.pathPrefix; - pathPrefixElement.title = entry.pathPrefix; - } else { - var pathPrefix = /** @type {string} */ (editable ? item : Common.UIString('%s (via .devtools)', item)); - var pathPrefixElement = element.createChild('div', 'file-system-value'); - pathPrefixElement.textContent = pathPrefix; - pathPrefixElement.title = pathPrefix; - } + var pathPrefix = /** @type {string} */ (editable ? item : Common.UIString('%s (via .devtools)', item)); + var pathPrefixElement = element.createChild('div', 'file-system-value'); + pathPrefixElement.textContent = pathPrefix; + pathPrefixElement.title = pathPrefix; return element; } @@ -154,13 +107,8 @@ * @param {number} index */ removeItemRequested(item, index) { - if (item instanceof Persistence.FileSystemMapping.Entry) { - var entry = this._mappings[index]; - Persistence.fileSystemMapping.removeFileMapping(entry.fileSystemPath, entry.urlPrefix, entry.pathPrefix); - } else { - Persistence.isolatedFileSystemManager.fileSystem(this._fileSystemPath) - .removeExcludedFolder(this._excludedFolders[index]); - } + Persistence.isolatedFileSystemManager.fileSystem(this._fileSystemPath) + .removeExcludedFolder(this._excludedFolders[index]); } /** @@ -171,21 +119,12 @@ */ commitEdit(item, editor, isNew) { this._muteUpdate = true; - if (item instanceof Persistence.FileSystemMapping.Entry) { - var entry = /** @type {!Persistence.FileSystemMapping.Entry} */ (item); - if (!isNew) - Persistence.fileSystemMapping.removeFileMapping(this._fileSystemPath, entry.urlPrefix, entry.pathPrefix); - Persistence.fileSystemMapping.addFileMapping( - this._fileSystemPath, this._normalizePrefix(editor.control('urlPrefix').value), - this._normalizePrefix(editor.control('pathPrefix').value)); - } else { - if (!isNew) { - Persistence.isolatedFileSystemManager.fileSystem(this._fileSystemPath) - .removeExcludedFolder(/** @type {string} */ (item)); - } + if (!isNew) { Persistence.isolatedFileSystemManager.fileSystem(this._fileSystemPath) - .addExcludedFolder(this._normalizePrefix(editor.control('pathPrefix').value)); + .removeExcludedFolder(/** @type {string} */ (item)); } + Persistence.isolatedFileSystemManager.fileSystem(this._fileSystemPath) + .addExcludedFolder(this._normalizePrefix(editor.control('pathPrefix').value)); this._muteUpdate = false; this._update(); } @@ -196,76 +135,9 @@ * @return {!UI.ListWidget.Editor} */ beginEdit(item) { - if (item instanceof Persistence.FileSystemMapping.Entry) { - var entry = /** @type {!Persistence.FileSystemMapping.Entry} */ (item); - var editor = this._createMappingEditor(); - editor.control('urlPrefix').value = entry.urlPrefix; - editor.control('pathPrefix').value = entry.pathPrefix; - return editor; - } else { - var editor = this._createExcludedFolderEditor(); - editor.control('pathPrefix').value = item; - return editor; - } - } - - /** - * @return {!UI.ListWidget.Editor} - */ - _createMappingEditor() { - if (this._mappingEditor) - return this._mappingEditor; - - var editor = new UI.ListWidget.Editor(); - this._mappingEditor = editor; - var content = editor.contentElement(); - - var titles = content.createChild('div', 'file-system-edit-row'); - titles.createChild('div', 'file-system-value').textContent = Common.UIString('URL prefix'); - titles.createChild('div', 'file-system-separator file-system-separator-invisible'); - titles.createChild('div', 'file-system-value').textContent = Common.UIString('Folder path'); - - var fields = content.createChild('div', 'file-system-edit-row'); - fields.createChild('div', 'file-system-value') - .appendChild( - editor.createInput('urlPrefix', 'text', 'http://localhost:8000/url', urlPrefixValidator.bind(this))); - fields.createChild('div', 'file-system-separator file-system-separator-invisible'); - fields.createChild('div', 'file-system-value') - .appendChild(editor.createInput('pathPrefix', 'text', '/path/to/folder/', pathPrefixValidator.bind(this))); - + var editor = this._createExcludedFolderEditor(); + editor.control('pathPrefix').value = item; return editor; - - /** - * @param {*} item - * @param {number} index - * @param {!HTMLInputElement|!HTMLSelectElement} input - * @return {boolean} - * @this {Persistence.EditFileSystemView} - */ - function urlPrefixValidator(item, index, input) { - var prefix = this._normalizePrefix(input.value); - for (var i = 0; i < this._mappings.length; ++i) { - if (i !== index && this._mappings[i].urlPrefix === prefix) - return false; - } - return !!prefix; - } - - /** - * @param {*} item - * @param {number} index - * @param {!HTMLInputElement|!HTMLSelectElement} input - * @return {boolean} - * @this {Persistence.EditFileSystemView} - */ - function pathPrefixValidator(item, index, input) { - var prefix = this._normalizePrefix(input.value); - for (var i = 0; i < this._mappings.length; ++i) { - if (i !== index && this._mappings[i].pathPrefix === prefix) - return false; - } - return !!prefix; - } } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/FileSystemMapping.js b/third_party/WebKit/Source/devtools/front_end/persistence/FileSystemMapping.js deleted file mode 100644 index 3922fea..0000000 --- a/third_party/WebKit/Source/devtools/front_end/persistence/FileSystemMapping.js +++ /dev/null
@@ -1,348 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -Persistence.FileSystemMapping = class extends Common.Object { - /** - * @param {!Persistence.IsolatedFileSystemManager} fileSystemManager - */ - constructor(fileSystemManager) { - super(); - this._fileSystemMappingSetting = Common.settings.createLocalSetting('fileSystemMapping', {}); - /** @type {!Object<string, !Persistence.FileSystemMapping.Entry>} */ - this._mappingForURLPrefix = {}; - /** @type {!Array<string>} */ - this._urlPrefixes = []; - - /** @type {!Object.<string, !Array.<!Persistence.FileSystemMapping.Entry>>} */ - this._fileSystemMappings = {}; - this._loadFromSettings(); - - this._eventListeners = [ - fileSystemManager.addEventListener( - Persistence.IsolatedFileSystemManager.Events.FileSystemAdded, this._fileSystemAdded, this), - fileSystemManager.addEventListener( - Persistence.IsolatedFileSystemManager.Events.FileSystemRemoved, this._fileSystemRemoved, this), - ]; - fileSystemManager.waitForFileSystems().then(this._fileSystemsLoaded.bind(this)); - } - - /** - * @param {!Array<!Persistence.IsolatedFileSystem>} fileSystems - */ - _fileSystemsLoaded(fileSystems) { - for (var fileSystem of fileSystems) - this._addFileSystemPath(fileSystem.path()); - } - - /** - * @param {!Common.Event} event - */ - _fileSystemAdded(event) { - var fileSystem = /** @type {!Persistence.IsolatedFileSystem} */ (event.data); - this._addFileSystemPath(fileSystem.path()); - } - - /** - * @param {!Common.Event} event - */ - _fileSystemRemoved(event) { - var fileSystem = /** @type {!Persistence.IsolatedFileSystem} */ (event.data); - this._removeFileSystemPath(fileSystem.path()); - } - - _loadFromSettings() { - var savedMapping = this._fileSystemMappingSetting.get(); - this._fileSystemMappings = {}; - for (var fileSystemPath in savedMapping) { - var savedFileSystemMappings = savedMapping[fileSystemPath]; - fileSystemPath = Common.ParsedURL.platformPathToURL(fileSystemPath); - this._fileSystemMappings[fileSystemPath] = []; - var fileSystemMappings = this._fileSystemMappings[fileSystemPath]; - - for (var i = 0; i < savedFileSystemMappings.length; ++i) { - var savedEntry = savedFileSystemMappings[i]; - var entry = - new Persistence.FileSystemMapping.Entry(fileSystemPath, savedEntry.urlPrefix, savedEntry.pathPrefix); - fileSystemMappings.push(entry); - } - } - - this._rebuildIndexes(); - } - - _saveToSettings() { - var setting = {}; - for (var fileSystemPath in this._fileSystemMappings) { - setting[fileSystemPath] = []; - var entries = this._fileSystemMappings[fileSystemPath]; - for (var entry of entries) - setting[fileSystemPath].push(entry); - } - this._fileSystemMappingSetting.set(setting); - } - - _rebuildIndexes() { - // We are building an index here to search for the longest url prefix match faster. - this._mappingForURLPrefix = {}; - for (var fileSystemMapping of Object.values(this._fileSystemMappings)) { - for (var entry of fileSystemMapping) - this._mappingForURLPrefix[entry.urlPrefix] = entry; - } - this._urlPrefixes = Object.keys(this._mappingForURLPrefix).sort(); - } - - /** - * @param {string} fileSystemPath - */ - _addFileSystemPath(fileSystemPath) { - if (this._fileSystemMappings[fileSystemPath]) - return; - - this._fileSystemMappings[fileSystemPath] = []; - this._saveToSettings(); - } - - /** - * @param {string} fileSystemPath - */ - _removeFileSystemPath(fileSystemPath) { - if (!this._fileSystemMappings[fileSystemPath]) - return; - delete this._fileSystemMappings[fileSystemPath]; - this._rebuildIndexes(); - this._saveToSettings(); - } - - /** - * @param {string} fileSystemPath - * @param {string} urlPrefix - * @param {string} pathPrefix - */ - addFileMapping(fileSystemPath, urlPrefix, pathPrefix) { - if (!urlPrefix.endsWith('/')) - urlPrefix += '/'; - if (!pathPrefix.endsWith('/')) - pathPrefix += '/'; - if (!pathPrefix.startsWith('/')) - pathPrefix = '/' + pathPrefix; - this._innerAddFileMapping(fileSystemPath, urlPrefix, pathPrefix); - this._saveToSettings(); - } - - /** - * @param {string} fileSystemPath - * @param {string} urlPrefix - * @param {string} pathPrefix - */ - _innerAddFileMapping(fileSystemPath, urlPrefix, pathPrefix) { - var entry = new Persistence.FileSystemMapping.Entry(fileSystemPath, urlPrefix, pathPrefix); - this._fileSystemMappings[fileSystemPath].push(entry); - this._rebuildIndexes(); - this.dispatchEventToListeners(Persistence.FileSystemMapping.Events.FileMappingAdded, entry); - } - - /** - * @param {string} fileSystemPath - * @param {string} urlPrefix - * @param {string} pathPrefix - */ - removeFileMapping(fileSystemPath, urlPrefix, pathPrefix) { - var entry = this._configurableMappingEntryForPathPrefix(fileSystemPath, pathPrefix); - if (!entry) - return; - this._fileSystemMappings[fileSystemPath].remove(entry); - this._rebuildIndexes(); - this._saveToSettings(); - this.dispatchEventToListeners(Persistence.FileSystemMapping.Events.FileMappingRemoved, entry); - } - - /** - * @param {string} url - * @return {?Persistence.FileSystemMapping.Entry} - */ - _mappingEntryForURL(url) { - for (var i = this._urlPrefixes.length - 1; i >= 0; --i) { - var urlPrefix = this._urlPrefixes[i]; - if (url.startsWith(urlPrefix)) - return this._mappingForURLPrefix[urlPrefix]; - } - return null; - } - - /** - * @param {string} fileSystemPath - * @param {string} filePath - * @return {?Persistence.FileSystemMapping.Entry} - */ - _mappingEntryForPath(fileSystemPath, filePath) { - var entries = this._fileSystemMappings[fileSystemPath]; - if (!entries) - return null; - - var entry = null; - for (var i = 0; i < entries.length; ++i) { - var pathPrefix = entries[i].pathPrefix; - // We are looking for the longest pathPrefix match. - if (entry && entry.pathPrefix.length > pathPrefix.length) - continue; - if (filePath.startsWith(pathPrefix)) - entry = entries[i]; - } - return entry; - } - - /** - * @param {string} fileSystemPath - * @param {string} pathPrefix - * @return {?Persistence.FileSystemMapping.Entry} - */ - _configurableMappingEntryForPathPrefix(fileSystemPath, pathPrefix) { - var entries = this._fileSystemMappings[fileSystemPath]; - for (var i = 0; i < entries.length; ++i) { - if (pathPrefix === entries[i].pathPrefix) - return entries[i]; - } - return null; - } - - /** - * @param {string} fileSystemPath - * @return {!Array.<!Persistence.FileSystemMapping.Entry>} - */ - mappingEntries(fileSystemPath) { - return this._fileSystemMappings[fileSystemPath].slice(); - } - - /** - * @param {string} url - * @return {boolean} - */ - hasMappingForNetworkURL(url) { - return !!this._mappingEntryForURL(url); - } - - /** - * @param {string} url - * @return {?{fileSystemPath: string, fileURL: string}} - */ - fileForURL(url) { - var entry = this._mappingEntryForURL(url); - if (!entry) - return null; - var file = {}; - file.fileSystemPath = entry.fileSystemPath; - file.fileURL = entry.fileSystemPath + entry.pathPrefix + url.substr(entry.urlPrefix.length); - return file; - } - - /** - * @param {string} fileSystemPath - * @param {string} filePath - * @return {string} - */ - networkURLForFileSystemURL(fileSystemPath, filePath) { - var relativePath = filePath.substring(fileSystemPath.length); - var entry = this._mappingEntryForPath(fileSystemPath, relativePath); - if (!entry) - return ''; - return entry.urlPrefix + relativePath.substring(entry.pathPrefix.length); - } - - /** - * @param {string} url - */ - removeMappingForURL(url) { - var entry = this._mappingEntryForURL(url); - if (!entry) - return; - this._fileSystemMappings[entry.fileSystemPath].remove(entry); - this._saveToSettings(); - } - - /** - * @param {string} url - * @param {string} fileSystemPath - * @param {string} filePath - */ - addMappingForResource(url, fileSystemPath, filePath) { - var commonPathSuffixLength = 0; - for (var i = 0; i < filePath.length; ++i) { - var filePathCharacter = filePath[filePath.length - 1 - i]; - var urlCharacter = url[url.length - 1 - i]; - if (filePathCharacter !== urlCharacter) - break; - if (filePathCharacter === '/') - commonPathSuffixLength = i; - } - var from = fileSystemPath.length; - var to = filePath.length - commonPathSuffixLength; - var pathPrefix = filePath.substring(from, to); - var urlPrefix = url.substr(0, url.length - commonPathSuffixLength); - if (to >= from) - this.addFileMapping(fileSystemPath, urlPrefix, pathPrefix); - else - this.addFileMapping(fileSystemPath, urlPrefix + pathPrefix, '/'); - } - - resetForTesting() { - this._fileSystemMappings = {}; - } - - dispose() { - Common.EventTarget.removeEventListeners(this._eventListeners); - } -}; - -/** @enum {symbol} */ -Persistence.FileSystemMapping.Events = { - FileMappingAdded: Symbol('FileMappingAdded'), - FileMappingRemoved: Symbol('FileMappingRemoved') -}; - -Persistence.FileSystemMapping.Entry = class { - /** - * @param {string} fileSystemPath - * @param {string} urlPrefix - * @param {string} pathPrefix - */ - constructor(fileSystemPath, urlPrefix, pathPrefix) { - /** @const */ - this.fileSystemPath = fileSystemPath; - /** @const */ - this.urlPrefix = urlPrefix; - /** @const */ - this.pathPrefix = pathPrefix; - } -}; - -/** - * @type {!Persistence.FileSystemMapping} - */ -Persistence.fileSystemMapping;
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/Persistence.js b/third_party/WebKit/Source/devtools/front_end/persistence/Persistence.js index cf8a45b..7692bb51 100644 --- a/third_party/WebKit/Source/devtools/front_end/persistence/Persistence.js +++ b/third_party/WebKit/Source/devtools/front_end/persistence/Persistence.js
@@ -9,9 +9,8 @@ /** * @param {!Workspace.Workspace} workspace * @param {!Bindings.BreakpointManager} breakpointManager - * @param {!Persistence.FileSystemMapping} fileSystemMapping */ - constructor(workspace, breakpointManager, fileSystemMapping) { + constructor(workspace, breakpointManager) { super(); this._workspace = workspace; this._breakpointManager = breakpointManager; @@ -21,23 +20,17 @@ /** @type {!Multimap<!Workspace.UISourceCode, function()>} */ this._subscribedBindingEventListeners = new Multimap(); - if (Runtime.experiments.isEnabled('persistence2')) { - var linkDecorator = new Persistence.PersistenceUtils.LinkDecorator(this); - Components.Linkifier.setLinkDecorator(linkDecorator); - this._mapping = - new Persistence.Automapping(workspace, this._validateBinding.bind(this), this._onBindingRemoved.bind(this)); - } else { - this._mapping = new Persistence.DefaultMapping( - workspace, fileSystemMapping, this._validateBinding.bind(this), this._onBindingRemoved.bind(this)); - } + var linkDecorator = new Persistence.PersistenceUtils.LinkDecorator(this); + Components.Linkifier.setLinkDecorator(linkDecorator); + this._mapping = + new Persistence.Automapping(workspace, this._validateBinding.bind(this), this._onBindingRemoved.bind(this)); } /** * @param {boolean} enabled */ setAutomappingEnabled(enabled) { - if (this._mapping instanceof Persistence.Automapping) - this._mapping.setEnabled(enabled); + this._mapping.setEnabled(enabled); } /** @@ -66,8 +59,7 @@ * @param {!Persistence.PersistenceBinding} binding */ _validateBinding(binding) { - if (!Runtime.experiments.isEnabled('persistence2') || binding.network.contentType().isFromSourceMap() || - !binding.fileSystem.contentType().isTextType()) { + if (binding.network.contentType().isFromSourceMap() || !binding.fileSystem.contentType().isTextType()) { this._establishBinding(binding); return; }
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/PersistenceUtils.js b/third_party/WebKit/Source/devtools/front_end/persistence/PersistenceUtils.js index 3a021fe4..e79e844 100644 --- a/third_party/WebKit/Source/devtools/front_end/persistence/PersistenceUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/persistence/PersistenceUtils.js
@@ -23,8 +23,6 @@ * @return {?UI.Icon} */ static iconForUISourceCode(uiSourceCode) { - if (!Runtime.experiments.isEnabled('persistence2')) - return null; var binding = Persistence.persistence.binding(uiSourceCode); if (binding) { var icon = UI.Icon.create('mediumicon-file-sync');
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/WorkspaceSettingsTab.js b/third_party/WebKit/Source/devtools/front_end/persistence/WorkspaceSettingsTab.js index 8aba142..c41aeab 100644 --- a/third_party/WebKit/Source/devtools/front_end/persistence/WorkspaceSettingsTab.js +++ b/third_party/WebKit/Source/devtools/front_end/persistence/WorkspaceSettingsTab.js
@@ -24,14 +24,12 @@ folderExcludePatternInput.classList.add('folder-exclude-pattern'); this.containerElement.appendChild(folderExcludePatternInput); - if (Runtime.experiments.isEnabled('persistence2')) { - var div = this.containerElement.createChild('div', 'settings-info-message'); - div.createTextChild(Common.UIString('Mappings are inferred automatically. Please ')); - div.appendChild(UI.XLink.create( - 'https://bugs.chromium.org/p/chromium/issues/entry?template=Defect%20report%20from%20user&components=Platform%3EDevTools%3EAuthoring&comment=DevTools%20failed%20to%20link%20network%20resource%20to%20filesystem.%0A%0APlatform%3A%20%3CLinux%2FWin%2FMac%3E%0AChrome%20version%3A%20%3Cyour%20chrome%20version%3E%0A%0AWhat%20are%20the%20details%20of%20your%20project%3F%0A-%20Source%20code%20(if%20any)%3A%20http%3A%2F%2Fgithub.com%2Fexample%2Fexample%0A-%20Build%20System%3A%20gulp%2Fgrunt%2Fwebpack%2Frollup%2F...%0A-%20HTTP%20server%3A%20node%20HTTP%2Fnginx%2Fapache...%0A%0AAssets%20failed%20to%20link%20(or%20incorrectly%20linked)%3A%0A1.%0A2.%0A3.%0A%0AIf%20possible%2C%20please%20attach%20a%20screenshot%20of%20network%20sources%20navigator%20which%20should%0Ashow%20which%20resources%20failed%20to%20map', - Common.UIString('report'))); - div.createTextChild(Common.UIString(' any bugs.')); - } + var div = this.containerElement.createChild('div', 'settings-info-message'); + div.createTextChild(Common.UIString('Mappings are inferred automatically. Please ')); + div.appendChild(UI.XLink.create( + 'https://bugs.chromium.org/p/chromium/issues/entry?template=Defect%20report%20from%20user&components=Platform%3EDevTools%3EAuthoring&comment=DevTools%20failed%20to%20link%20network%20resource%20to%20filesystem.%0A%0APlatform%3A%20%3CLinux%2FWin%2FMac%3E%0AChrome%20version%3A%20%3Cyour%20chrome%20version%3E%0A%0AWhat%20are%20the%20details%20of%20your%20project%3F%0A-%20Source%20code%20(if%20any)%3A%20http%3A%2F%2Fgithub.com%2Fexample%2Fexample%0A-%20Build%20System%3A%20gulp%2Fgrunt%2Fwebpack%2Frollup%2F...%0A-%20HTTP%20server%3A%20node%20HTTP%2Fnginx%2Fapache...%0A%0AAssets%20failed%20to%20link%20(or%20incorrectly%20linked)%3A%0A1.%0A2.%0A3.%0A%0AIf%20possible%2C%20please%20attach%20a%20screenshot%20of%20network%20sources%20navigator%20which%20should%0Ashow%20which%20resources%20failed%20to%20map', + Common.UIString('report'))); + div.createTextChild(Common.UIString(' any bugs.')); this._fileSystemsListContainer = this.containerElement.createChild('div', '');
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/editFileSystemView.css b/third_party/WebKit/Source/devtools/front_end/persistence/editFileSystemView.css index ae99688..022e3cf 100644 --- a/third_party/WebKit/Source/devtools/front_end/persistence/editFileSystemView.css +++ b/third_party/WebKit/Source/devtools/front_end/persistence/editFileSystemView.css
@@ -53,18 +53,6 @@ flex: 1 1 0px; } -.file-system-separator { - flex: 0 0 1px; - background-color: rgb(231, 231, 231); - height: 30px; - margin: 0 4px; -} - -.file-system-separator-invisible { - visibility: hidden; - height: 100% !important; -} - .file-system-edit-row { flex: none; display: flex;
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/module.json b/third_party/WebKit/Source/devtools/front_end/persistence/module.json index 1115870d..254391a 100644 --- a/third_party/WebKit/Source/devtools/front_end/persistence/module.json +++ b/third_party/WebKit/Source/devtools/front_end/persistence/module.json
@@ -47,13 +47,11 @@ "IsolatedFileSystem.js", "IsolatedFileSystemManager.js", "FileSystemWorkspaceBinding.js", - "DefaultMapping.js", "Automapping.js", "NetworkPersistenceManager.js", "Persistence.js", "PersistenceActions.js", "PersistenceUtils.js", - "FileSystemMapping.js", "EditFileSystemView.js", "WorkspaceSettingsTab.js" ],
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js index d8d31ab4..7f1414ca 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -491,6 +491,8 @@ dataReceived(requestId, time, dataLength, encodedDataLength) { var networkRequest = this._inflightRequestsById[requestId]; if (!networkRequest) + networkRequest = this._maybeAdoptMainResourceRequest(requestId); + if (!networkRequest) return; networkRequest.resourceSize += dataLength; @@ -511,6 +513,8 @@ loadingFinished(requestId, finishTime, encodedDataLength, blockedCrossSiteDocument) { var networkRequest = this._inflightRequestsById[requestId]; if (!networkRequest) + networkRequest = this._maybeAdoptMainResourceRequest(requestId); + if (!networkRequest) return; this._finishNetworkRequest(networkRequest, finishTime, encodedDataLength, blockedCrossSiteDocument); } @@ -722,11 +726,33 @@ } /** + * @param {string} requestId + * @return {?SDK.NetworkRequest} + */ + _maybeAdoptMainResourceRequest(requestId) { + var request = SDK.multitargetNetworkManager._inflightMainResourceRequests.get(requestId); + if (!request) + return null; + var oldDispatcher = SDK.NetworkManager.forRequest(request)._dispatcher; + delete oldDispatcher._inflightRequestsById[requestId]; + delete oldDispatcher._inflightRequestsByURL[request.url()]; + this._inflightRequestsById[requestId] = request; + this._inflightRequestsByURL[request.url()] = request; + request[SDK.NetworkManager._networkManagerForRequestSymbol] = this._manager; + return request; + } + + /** * @param {!SDK.NetworkRequest} networkRequest */ _startNetworkRequest(networkRequest) { this._inflightRequestsById[networkRequest.requestId()] = networkRequest; this._inflightRequestsByURL[networkRequest.url()] = networkRequest; + // The following relies on the fact that loaderIds and requestIds are + // globally unique and that the main request has them equal. + if (networkRequest.loaderId === networkRequest.requestId()) + SDK.multitargetNetworkManager._inflightMainResourceRequests.set(networkRequest.requestId(), networkRequest); + this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestStarted, networkRequest); } @@ -751,6 +777,7 @@ this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestFinished, networkRequest); delete this._inflightRequestsById[networkRequest.requestId()]; delete this._inflightRequestsByURL[networkRequest.url()]; + SDK.multitargetNetworkManager._inflightMainResourceRequests.delete(networkRequest.requestId()); if (blockedCrossSiteDocument) { var message = Common.UIString( @@ -798,6 +825,8 @@ this._userAgentOverride = ''; /** @type {!Set<!Protocol.NetworkAgent>} */ this._agents = new Set(); + /** @type {!Map<string, !SDK.NetworkRequest>} */ + this._inflightMainResourceRequests = new Map(); /** @type {!SDK.NetworkManager.Conditions} */ this._networkConditions = SDK.NetworkManager.NoThrottlingConditions; /** @type {?Promise} */ @@ -852,6 +881,12 @@ * @param {!SDK.Target} target */ targetRemoved(target) { + for (var entry of this._inflightMainResourceRequests) { + var manager = SDK.NetworkManager.forRequest(/** @type {!SDK.NetworkRequest} */ (entry[1])); + if (manager.target() !== target) + continue; + this._inflightMainResourceRequests.delete(/** @type {string} */ (entry[0])); + } this._agents.delete(target.networkAgent()); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js index e423419d..2b7e5432 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
@@ -58,17 +58,10 @@ this._initGrouping(); - if (Runtime.experiments.isEnabled('persistence2')) { - Persistence.persistence.addEventListener( - Persistence.Persistence.Events.BindingCreated, this._onBindingChanged, this); - Persistence.persistence.addEventListener( - Persistence.Persistence.Events.BindingRemoved, this._onBindingChanged, this); - } else { - Persistence.persistence.addEventListener( - Persistence.Persistence.Events.BindingCreated, this._onBindingCreated, this); - Persistence.persistence.addEventListener( - Persistence.Persistence.Events.BindingRemoved, this._onBindingRemoved, this); - } + Persistence.persistence.addEventListener( + Persistence.Persistence.Events.BindingCreated, this._onBindingChanged, this); + Persistence.persistence.addEventListener( + Persistence.Persistence.Events.BindingRemoved, this._onBindingChanged, this); SDK.targetManager.addEventListener(SDK.TargetManager.Events.NameChanged, this._targetNameChanged, this); SDK.targetManager.observeTargets(this); @@ -166,22 +159,6 @@ /** * @param {!Common.Event} event */ - _onBindingCreated(event) { - var binding = /** @type {!Persistence.PersistenceBinding} */ (event.data); - this._removeUISourceCode(binding.network); - } - - /** - * @param {!Common.Event} event - */ - _onBindingRemoved(event) { - var binding = /** @type {!Persistence.PersistenceBinding} */ (event.data); - this._addUISourceCode(binding.network); - } - - /** - * @param {!Common.Event} event - */ _onBindingChanged(event) { var binding = /** @type {!Persistence.PersistenceBinding} */ (event.data); @@ -289,13 +266,7 @@ * @return {boolean} */ _acceptsUISourceCode(uiSourceCode) { - if (!this.acceptProject(uiSourceCode.project())) - return false; - - var binding = Persistence.persistence.binding(uiSourceCode); - if (!Runtime.experiments.isEnabled('persistence2') && binding && binding.network === uiSourceCode) - return false; - return true; + return this.acceptProject(uiSourceCode.project()); } /** @@ -1011,7 +982,7 @@ updateIcon() { var binding = Persistence.persistence.binding(this._uiSourceCode); - if (binding && Runtime.experiments.isEnabled('persistence2')) { + if (binding) { var container = createElementWithClass('span', 'icon-stack'); var icon = UI.Icon.create('largeicon-navigator-file-sync', 'icon'); var badge = UI.Icon.create('badge-navigator-file-sync', 'icon-badge'); @@ -1491,9 +1462,7 @@ return; var absoluteFileSystemPath = Persistence.FileSystemWorkspaceBinding.fileSystemPath(this._project.id()) + '/' + this._folderPath; - var hasMappedFiles = Runtime.experiments.isEnabled('persistence2') ? - Persistence.persistence.filePathHasBindings(absoluteFileSystemPath) : - true; + var hasMappedFiles = Persistence.persistence.filePathHasBindings(absoluteFileSystemPath); this._treeElement.listItemElement.classList.toggle('has-mapped-files', hasMappedFiles); } @@ -1666,10 +1635,6 @@ updateTitle() { if (!this._treeElement || this._project.type() !== Workspace.projectTypes.FileSystem) return; - if (!Runtime.experiments.isEnabled('persistence2')) { - this._treeElement.listItemElement.classList.add('has-mapped-files'); - return; - } var fileSystemPath = Persistence.FileSystemWorkspaceBinding.fileSystemPath(this._project.id()); var wasActive = this._treeElement.listItemElement.classList.contains('has-mapped-files'); var isActive = Persistence.persistence.filePathHasBindings(fileSystemPath);
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/OpenFileQuickOpen.js b/third_party/WebKit/Source/devtools/front_end/sources/OpenFileQuickOpen.js index b2500fe..39dfe70 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/OpenFileQuickOpen.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/OpenFileQuickOpen.js
@@ -47,54 +47,3 @@ return true; } }; - -Sources.SelectUISourceCodeForProjectTypesDialog = class extends Sources.FilteredUISourceCodeListProvider { - /** - * @param {!Array.<string>} types - * @param {function(?Workspace.UISourceCode)} callback - */ - constructor(types, callback) { - super(); - this._types = types; - this._callback = callback; - } - - /** - * @param {string} name - * @param {!Array.<string>} types - * @param {function(?Workspace.UISourceCode)} callback - */ - static show(name, types, callback) { - var filteredItemSelectionDialog = - new QuickOpen.FilteredListWidget(new Sources.SelectUISourceCodeForProjectTypesDialog(types, callback)); - filteredItemSelectionDialog.showAsDialog(); - filteredItemSelectionDialog.setQuery(name); - } - - /** - * @override - * @param {?Workspace.UISourceCode} uiSourceCode - * @param {number=} lineNumber - * @param {number=} columnNumber - */ - uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber) { - this._callback(uiSourceCode); - } - - /** - * @override - * @param {!Workspace.Project} project - * @return {boolean} - */ - filterProject(project) { - return this._types.indexOf(project.type()) !== -1; - } - - /** - * @override - * @return {boolean} - */ - renderAsTwoRows() { - return true; - } -};
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js index b5a09da..f9981ab 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesNavigator.js
@@ -29,67 +29,6 @@ /** * @unrestricted */ -Sources.SourcesNavigatorView = class extends Sources.NavigatorView { - constructor() { - super(); - SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged, this._inspectedURLChanged, this); - } - - /** - * @override - * @param {!Workspace.Project} project - * @return {boolean} - */ - acceptProject(project) { - if (!super.acceptProject(project)) - return false; - return project.type() !== Workspace.projectTypes.ContentScripts && - project.type() !== Workspace.projectTypes.Snippets; - } - - /** - * @param {!Common.Event} event - */ - _inspectedURLChanged(event) { - var mainTarget = SDK.targetManager.mainTarget(); - if (event.data !== mainTarget) - return; - var inspectedURL = mainTarget && mainTarget.inspectedURL(); - if (!inspectedURL) - return; - for (var uiSourceCode of this.workspace().uiSourceCodes()) { - if (this.acceptProject(uiSourceCode.project()) && uiSourceCode.url() === inspectedURL) - this.revealUISourceCode(uiSourceCode, true); - } - } - - /** - * @override - * @param {!Workspace.UISourceCode} uiSourceCode - */ - uiSourceCodeAdded(uiSourceCode) { - var mainTarget = SDK.targetManager.mainTarget(); - var inspectedURL = mainTarget && mainTarget.inspectedURL(); - if (!inspectedURL) - return; - if (uiSourceCode.url() === inspectedURL) - this.revealUISourceCode(uiSourceCode, true); - } - - /** - * @override - * @param {!Event} event - */ - handleContextMenu(event) { - var contextMenu = new UI.ContextMenu(event); - Sources.NavigatorView.appendAddFolderItem(contextMenu); - contextMenu.show(); - } -}; - -/** - * @unrestricted - */ Sources.NetworkNavigatorView = class extends Sources.NavigatorView { constructor() { super(); @@ -359,7 +298,7 @@ /** * @implements {UI.ActionDelegate} */ -Sources.SourcesNavigatorView.CreatingActionDelegate = class { +Sources.SnippetsNavigatorView.CreatingActionDelegate = class { /** * @override * @param {!UI.Context} context
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js index 54eab15..48151e1 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -118,7 +118,6 @@ event => this._debuggerResumed(/** @type {!SDK.DebuggerModel} */ (event.data))); SDK.targetManager.addEventListener( SDK.TargetManager.Events.AvailableNodeTargetsChanged, this._availableNodeTargetsChanged, this); - new Sources.WorkspaceMappingTip(this, this._workspace); Extensions.extensionServer.addEventListener( Extensions.ExtensionServer.Events.SidebarPaneAdded, this._extensionSidebarPaneAdded, this); SDK.targetManager.observeTargets(this); @@ -736,88 +735,6 @@ } /** - * @param {!Workspace.UISourceCode} uiSourceCode - */ - mapFileSystemToNetwork(uiSourceCode) { - Sources.SelectUISourceCodeForProjectTypesDialog.show( - uiSourceCode.name(), [Workspace.projectTypes.Network, Workspace.projectTypes.ContentScripts], - mapFileSystemToNetwork); - - /** - * @param {?Workspace.UISourceCode} networkUISourceCode - */ - function mapFileSystemToNetwork(networkUISourceCode) { - if (!networkUISourceCode) - return; - var fileSystemPath = Persistence.FileSystemWorkspaceBinding.fileSystemPath(uiSourceCode.project().id()); - Persistence.fileSystemMapping.addMappingForResource( - networkUISourceCode.url(), fileSystemPath, uiSourceCode.url()); - } - } - - /** - * @param {!Workspace.UISourceCode} networkUISourceCode - */ - mapNetworkToFileSystem(networkUISourceCode) { - Sources.SelectUISourceCodeForProjectTypesDialog.show( - networkUISourceCode.name(), [Workspace.projectTypes.FileSystem], mapNetworkToFileSystem); - - /** - * @param {?Workspace.UISourceCode} uiSourceCode - */ - function mapNetworkToFileSystem(uiSourceCode) { - if (!uiSourceCode) - return; - var fileSystemPath = Persistence.FileSystemWorkspaceBinding.fileSystemPath(uiSourceCode.project().id()); - Persistence.fileSystemMapping.addMappingForResource( - networkUISourceCode.url(), fileSystemPath, uiSourceCode.url()); - } - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - */ - _removeNetworkMapping(uiSourceCode) { - Persistence.fileSystemMapping.removeMappingForURL(uiSourceCode.url()); - } - - /** - * @param {!UI.ContextMenu} contextMenu - * @param {!Workspace.UISourceCode} uiSourceCode - */ - _appendUISourceCodeMappingItems(contextMenu, uiSourceCode) { - if (Runtime.experiments.isEnabled('persistence2')) - return; - if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) { - var binding = Persistence.persistence.binding(uiSourceCode); - if (!binding) { - contextMenu.debugSection().appendItem( - Common.UIString('Map to network resource\u2026'), this.mapFileSystemToNetwork.bind(this, uiSourceCode)); - } else { - contextMenu.debugSection().appendItem( - Common.UIString('Remove network mapping'), this._removeNetworkMapping.bind(this, binding.network)); - } - } - - /** - * @param {!Workspace.Project} project - */ - function filterProject(project) { - return project.type() === Workspace.projectTypes.FileSystem; - } - - if (uiSourceCode.project().type() === Workspace.projectTypes.Network || - uiSourceCode.project().type() === Workspace.projectTypes.ContentScripts) { - if (!this._workspace.projects().filter(filterProject).length) - return; - if (this._workspace.uiSourceCodeForURL(uiSourceCode.url()) === uiSourceCode) { - contextMenu.debugSection().appendItem( - Common.UIString('Map to file system resource\u2026'), this.mapNetworkToFileSystem.bind(this, uiSourceCode)); - } - } - } - - /** * @param {!Event} event * @param {!UI.ContextMenu} contextMenu * @param {!Object} target @@ -832,7 +749,6 @@ contextMenu.revealSection().appendItem( Common.UIString('Reveal in navigator'), this._handleContextMenuReveal.bind(this, uiSourceCode)); } - this._appendUISourceCodeMappingItems(contextMenu, uiSourceCode); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js index 030cf60..681dd9e 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesView.js
@@ -109,8 +109,7 @@ row.createChild('div', 'tabbed-pane-placeholder-key').textContent = shortcutKeyText; row.createChild('div', 'tabbed-pane-placeholder-value').textContent = shortcut.description; } - if (Runtime.experiments.isEnabled('persistence2')) - element.createChild('div').textContent = Common.UIString('Drop in a folder to add to workspace'); + element.createChild('div').textContent = Common.UIString('Drop in a folder to add to workspace'); return element; }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/WorkspaceMappingTip.js b/third_party/WebKit/Source/devtools/front_end/sources/WorkspaceMappingTip.js deleted file mode 100644 index 83aedaf0..0000000 --- a/third_party/WebKit/Source/devtools/front_end/sources/WorkspaceMappingTip.js +++ /dev/null
@@ -1,181 +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. -/** - * @unrestricted - */ -Sources.WorkspaceMappingTip = class { - /** - * @param {!Sources.SourcesPanel} sourcesPanel - * @param {!Workspace.Workspace} workspace - */ - constructor(sourcesPanel, workspace) { - this._sourcesPanel = sourcesPanel; - this._workspace = workspace; - - this._sourcesView = this._sourcesPanel.sourcesView(); - this._workspaceInfobarDisabledSetting = Common.settings.createSetting('workspaceInfobarDisabled', false); - this._workspaceMappingInfobarDisabledSetting = - Common.settings.createSetting('workspaceMappingInfobarDisabled', false); - - if (this._workspaceInfobarDisabledSetting.get() && this._workspaceMappingInfobarDisabledSetting.get()) - return; - this._sourcesView.addEventListener(Sources.SourcesView.Events.EditorSelected, this._editorSelected.bind(this)); - Persistence.persistence.addEventListener(Persistence.Persistence.Events.BindingCreated, this._bindingCreated, this); - } - - /** - * @param {!Common.Event} event - */ - _bindingCreated(event) { - var binding = /** @type {!Persistence.PersistenceBinding} */ (event.data); - if (binding.network[Sources.WorkspaceMappingTip._infobarSymbol]) - binding.network[Sources.WorkspaceMappingTip._infobarSymbol].dispose(); - if (binding.fileSystem[Sources.WorkspaceMappingTip._infobarSymbol]) - binding.fileSystem[Sources.WorkspaceMappingTip._infobarSymbol].dispose(); - } - - /** - * @param {!Common.Event} event - */ - _editorSelected(event) { - var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data); - if (this._editorSelectedTimer) - clearTimeout(this._editorSelectedTimer); - this._editorSelectedTimer = setTimeout(this._updateSuggestedMappingInfobar.bind(this, uiSourceCode), 3000); - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - */ - _updateSuggestedMappingInfobar(uiSourceCode) { - var uiSourceCodeFrame = this._sourcesView.viewForFile(uiSourceCode); - - if (!uiSourceCodeFrame.isShowing()) - return; - if (uiSourceCode[Sources.WorkspaceMappingTip._infobarSymbol]) - return; - - // First try mapping filesystem -> network. - if (!this._workspaceMappingInfobarDisabledSetting.get() && - uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) { - if (Persistence.persistence.binding(uiSourceCode)) - return; - - var networkProjects = this._workspace.projectsForType(Workspace.projectTypes.Network); - networkProjects = networkProjects.concat(this._workspace.projectsForType(Workspace.projectTypes.ContentScripts)); - for (var i = 0; i < networkProjects.length; ++i) { - var name = uiSourceCode.name(); - var networkUiSourceCodes = networkProjects[i].uiSourceCodes(); - for (var j = 0; j < networkUiSourceCodes.length; ++j) { - if (networkUiSourceCodes[j].name() === name && this._isLocalHost(networkUiSourceCodes[j].url())) { - this._showMappingInfobar(uiSourceCode, false); - return; - } - } - } - } - - // Then map network -> filesystem. - if (uiSourceCode.project().type() === Workspace.projectTypes.Network || - uiSourceCode.project().type() === Workspace.projectTypes.ContentScripts) { - // Suggest for localhost only. - if (!this._isLocalHost(uiSourceCode.url()) || Persistence.persistence.binding(uiSourceCode)) - return; - - var filesystemProjects = this._workspace.projectsForType(Workspace.projectTypes.FileSystem); - for (var i = 0; i < filesystemProjects.length; ++i) { - var name = uiSourceCode.name(); - var fsUiSourceCodes = filesystemProjects[i].uiSourceCodes(); - for (var j = 0; j < fsUiSourceCodes.length; ++j) { - if (fsUiSourceCodes[j].name() === name) { - this._showMappingInfobar(uiSourceCode, true); - return; - } - } - } - - this._showWorkspaceInfobar(uiSourceCode); - } - } - - /** - * @param {string} url - * @return {boolean} - */ - _isLocalHost(url) { - var parsedURL = url.asParsedURL(); - return !!parsedURL && parsedURL.host === 'localhost'; - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - */ - _showWorkspaceInfobar(uiSourceCode) { - var infobar = UI.Infobar.create( - UI.Infobar.Type.Info, Common.UIString('Serving from the file system? Add your files into the workspace.'), - this._workspaceInfobarDisabledSetting); - if (!infobar) - return; - infobar.createDetailsRowMessage( - Common.UIString('If you add files into your DevTools workspace, your changes will be persisted to disk.')); - infobar.createDetailsRowMessage( - Common.UIString('To add a folder into the workspace, drag and drop it into the Sources panel.')); - this._appendInfobar(uiSourceCode, infobar); - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - * @param {boolean} isNetwork - */ - _showMappingInfobar(uiSourceCode, isNetwork) { - var title; - if (isNetwork) - title = Common.UIString('Map network resource \'%s\' to workspace?', uiSourceCode.url()); - else - title = Common.UIString('Map workspace resource \'%s\' to network?', uiSourceCode.url()); - - var infobar = UI.Infobar.create(UI.Infobar.Type.Info, title, this._workspaceMappingInfobarDisabledSetting); - if (!infobar) - return; - infobar.createDetailsRowMessage(Common.UIString( - 'You can map files in your workspace to the ones loaded over the network. As a result, changes made in DevTools will be persisted to disk.')); - infobar.createDetailsRowMessage(Common.UIString('Use context menu to establish the mapping at any time.')); - var anchor = createElementWithClass('span', 'link'); - anchor.textContent = Common.UIString('Establish the mapping now...'); - anchor.addEventListener('click', this._establishTheMapping.bind(this, uiSourceCode), false); - infobar.createDetailsRowMessage('').appendChild(anchor); - this._appendInfobar(uiSourceCode, infobar); - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - * @param {?Event} event - */ - _establishTheMapping(uiSourceCode, event) { - event.consume(true); - if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) - this._sourcesPanel.mapFileSystemToNetwork(uiSourceCode); - else - this._sourcesPanel.mapNetworkToFileSystem(uiSourceCode); - } - - /** - * @param {!Workspace.UISourceCode} uiSourceCode - * @param {!UI.Infobar} infobar - */ - _appendInfobar(uiSourceCode, infobar) { - var uiSourceCodeFrame = this._sourcesView.viewForFile(uiSourceCode); - - var rowElement = - infobar.createDetailsRowMessage(Common.UIString('For more information on workspaces, refer to the ')); - rowElement.appendChild( - UI.createDocumentationLink('../setup/setup-workflow', Common.UIString('workspaces documentation'))); - rowElement.createTextChild('.'); - uiSourceCode[Sources.WorkspaceMappingTip._infobarSymbol] = infobar; - uiSourceCodeFrame.attachInfobars([infobar]); - UI.runCSSAnimationOnce(infobar.element, 'source-frame-infobar-animation'); - } -}; - -Sources.WorkspaceMappingTip._infobarSymbol = Symbol('infobar');
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/module.json b/third_party/WebKit/Source/devtools/front_end/sources/module.json index a62a78c..c5b7ef3 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/module.json +++ b/third_party/WebKit/Source/devtools/front_end/sources/module.json
@@ -296,22 +296,11 @@ { "type": "view", "location": "navigator-view", - "id": "navigator-sources", - "title": "Sources", - "order": 1, - "persistence": "permanent", - "className": "Sources.SourcesNavigatorView", - "experiment": "!persistence2" - }, - { - "type": "view", - "location": "navigator-view", "id": "navigator-network", "title": "Network", "order": 2, "persistence": "permanent", - "className": "Sources.NetworkNavigatorView", - "experiment": "persistence2" + "className": "Sources.NetworkNavigatorView" }, { "type": "view", @@ -320,8 +309,7 @@ "title": "Filesystem", "order": 3, "persistence": "permanent", - "className": "Sources.FilesNavigatorView", - "experiment": "persistence2" + "className": "Sources.FilesNavigatorView" }, { "type": "view", @@ -352,21 +340,13 @@ }, { "type": "@Sources.NavigatorView", - "viewId": "navigator-sources", - "className": "Sources.SourcesNavigatorView", - "experiment": "!persistence2" - }, - { - "type": "@Sources.NavigatorView", "viewId": "navigator-network", - "className": "Sources.NetworkNavigatorView", - "experiment": "persistence2" + "className": "Sources.NetworkNavigatorView" }, { "type": "@Sources.NavigatorView", "viewId": "navigator-files", - "className": "Sources.FilesNavigatorView", - "experiment": "persistence2" + "className": "Sources.FilesNavigatorView" }, { "type": "@Sources.NavigatorView", @@ -600,14 +580,14 @@ "type": "@UI.ActionDelegate", "category": "Sources", "actionId": "sources.create-snippet", - "className": "Sources.SourcesNavigatorView.CreatingActionDelegate", + "className": "Sources.SnippetsNavigatorView.CreatingActionDelegate", "title": "Create new snippet" }, { "type": "@UI.ActionDelegate", "category": "Sources", "actionId": "sources.add-folder-to-workspace", - "className": "Sources.SourcesNavigatorView.CreatingActionDelegate", + "className": "Sources.SnippetsNavigatorView.CreatingActionDelegate", "title": "Add folder to workspace" }, { @@ -752,7 +732,6 @@ "FileBasedSearchResultsPane.js", "SourcesSearchScope.js", "SourcesPanel.js", - "WorkspaceMappingTip.js", "XHRBreakpointsSidebarPane.js", "JavaScriptCompilerPlugin.js", "SnippetsPlugin.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SourcesTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SourcesTestRunner.js index bb69c3e..5ea3771 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SourcesTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SourcesTestRunner.js
@@ -64,7 +64,7 @@ * @param {string} mode */ SourcesTestRunner.dumpNavigatorViewInMode = function(view, mode) { - TestRunner.addResult(view instanceof Sources.SourcesNavigatorView ? 'Sources:' : 'Content Scripts:'); + TestRunner.addResult(view instanceof Sources.NetworkNavigatorView ? 'Sources:' : 'Content Scripts:'); view._groupByFrame = mode.includes('frame'); view._groupByDomain = mode.includes('domain'); view._groupByFolder = mode.includes('folder');
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js b/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js index b9a2faa..b3f25db 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
@@ -166,7 +166,7 @@ var showArrow = this._marginBehavior === UI.GlassPane.MarginBehavior.Arrow; var gutterSize = showArrow ? 8 : (this._marginBehavior === UI.GlassPane.MarginBehavior.NoMargin ? 0 : 3); - var scrollbarSize = 15; + var scrollbarSize = UI.measuredScrollbarWidth(this.element.ownerDocument); var arrowSize = 10; var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this.element.ownerDocument));
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index b7c8781a..402071a 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -285,7 +285,8 @@ return true; }; -UI.CSSNumberRegex = /^(-?(?:\d+(?:\.\d+)?|\.\d+))$/; +// Avoids Infinity, NaN, and scientific notation (e.g. 1e20), see crbug.com/81165. +UI._numberRegex = /^(-?(?:\d+(?:\.\d+)?|\.\d+))$/; UI.StyleValueDelimiters = ' \xA0\t\n"\':;,/()'; @@ -364,9 +365,10 @@ /** * @param {number} number * @param {!Event} event + * @param {number=} modifierMultiplier * @return {?number} */ -UI._modifiedFloatNumber = function(number, event) { +UI._modifiedFloatNumber = function(number, event, modifierMultiplier) { var direction = UI._valueModificationDirection(event); if (!direction) return null; @@ -388,13 +390,14 @@ if (direction === 'Down') delta *= -1; + if (modifierMultiplier) + delta *= modifierMultiplier; // Make the new number and constrain it to a precision of 6, this matches numbers the engine returns. // Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1. var result = Number((number + delta).toFixed(6)); - if (!String(result).match(UI.CSSNumberRegex)) + if (!String(result).match(UI._numberRegex)) return null; - return result; }; @@ -671,26 +674,29 @@ UI.themeSupport.injectCustomStyleSheets(element); element.classList.add('platform-' + Host.platform()); - /** - * Detect overlay scrollbar enable by checking clientWidth and offsetWidth of - * overflow: scroll div. - * @param {?Document=} document - * @return {boolean} - */ - function overlayScrollbarEnabled(document) { - var scrollDiv = document.createElement('div'); - scrollDiv.setAttribute('style', 'width: 100px; height: 100px; overflow: scroll;'); - document.body.appendChild(scrollDiv); - var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); - return scrollbarWidth === 0; - } - - if (!Host.isMac() && overlayScrollbarEnabled(element.ownerDocument)) + // Detect overlay scrollbar enable by checking for nonzero scrollbar width. + if (!Host.isMac() && UI.measuredScrollbarWidth(element.ownerDocument) === 0) element.classList.add('overlay-scrollbar-enabled'); }; /** + * @param {?Document} document + * @return {number} + */ +UI.measuredScrollbarWidth = function(document) { + if (typeof UI._measuredScrollbarWidth === 'number') + return UI._measuredScrollbarWidth; + if (!document) + return 16; + var scrollDiv = document.createElement('div'); + scrollDiv.setAttribute('style', 'width: 100px; height: 100px; overflow: scroll;'); + document.body.appendChild(scrollDiv); + UI._measuredScrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + return UI._measuredScrollbarWidth; +}; + +/** * @param {!Element} element * @param {string=} cssFile * @return {!DocumentFragment} @@ -1510,9 +1516,10 @@ * @param {function(string)} apply * @param {function(string):boolean} validate * @param {boolean} numeric + * @param {number=} modifierMultiplier * @return {function(string)} */ -UI.bindInput = function(input, apply, validate, numeric) { +UI.bindInput = function(input, apply, validate, numeric, modifierMultiplier) { input.addEventListener('change', onChange, false); input.addEventListener('input', onInput, false); input.addEventListener('keydown', onKeyDown, false); @@ -1543,17 +1550,7 @@ if (!numeric) return; - var increment = event.key === 'ArrowUp' ? 1 : event.key === 'ArrowDown' ? -1 : 0; - if (!increment) - return; - if (event.shiftKey) - increment *= 10; - - var value = input.value; - if (!validate(value) || !value) - return; - - value = (value ? Number(value) : 0) + increment; + var value = UI._modifiedFloatNumber(parseFloat(input.value), event, modifierMultiplier); var stringValue = value ? String(value) : ''; if (!validate(stringValue) || !value) return;
diff --git a/third_party/WebKit/Source/modules/exported/BUILD.gn b/third_party/WebKit/Source/modules/exported/BUILD.gn index 6691fd4..27b0278 100644 --- a/third_party/WebKit/Source/modules/exported/BUILD.gn +++ b/third_party/WebKit/Source/modules/exported/BUILD.gn
@@ -15,7 +15,6 @@ "WebIDBKey.cpp", "WebIDBKeyRange.cpp", "WebIDBValue.cpp", - "WebMediaDeviceChangeObserver.cpp", "WebMediaStreamRegistry.cpp", "WebSpeechGrammar.cpp", "WebSpeechRecognitionHandle.cpp",
diff --git a/third_party/WebKit/Source/modules/exported/WebMediaDeviceChangeObserver.cpp b/third_party/WebKit/Source/modules/exported/WebMediaDeviceChangeObserver.cpp deleted file mode 100644 index a488a13..0000000 --- a/third_party/WebKit/Source/modules/exported/WebMediaDeviceChangeObserver.cpp +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "public/web/WebMediaDeviceChangeObserver.h" - -#include "core/dom/Document.h" -#include "modules/mediastream/MediaDevices.h" -#include "platform/weborigin/SecurityOrigin.h" -#include "public/platform/WebSecurityOrigin.h" - -namespace blink { - -WebMediaDeviceChangeObserver::WebMediaDeviceChangeObserver() - : private_(nullptr) {} - -WebMediaDeviceChangeObserver::WebMediaDeviceChangeObserver(bool unused) - : private_(MediaDevices::Create(Document::CreateForTest())) {} - -WebMediaDeviceChangeObserver::WebMediaDeviceChangeObserver( - const WebMediaDeviceChangeObserver& other) { - Assign(other); -} - -WebMediaDeviceChangeObserver& WebMediaDeviceChangeObserver::operator=( - const WebMediaDeviceChangeObserver& other) { - Assign(other); - return *this; -} - -WebMediaDeviceChangeObserver::WebMediaDeviceChangeObserver( - MediaDevices* observer) - : private_(observer) {} - -WebMediaDeviceChangeObserver::~WebMediaDeviceChangeObserver() { - Reset(); -} - -bool WebMediaDeviceChangeObserver::IsNull() const { - return private_.IsNull(); -} - -void WebMediaDeviceChangeObserver::DidChangeMediaDevices() { - if (private_.IsNull()) - return; - - private_->DidChangeMediaDevices(); -} - -WebSecurityOrigin WebMediaDeviceChangeObserver::GetSecurityOrigin() const { - if (private_.IsNull()) - return WebSecurityOrigin(); - - return WebSecurityOrigin( - private_->GetExecutionContext()->GetSecurityOrigin()); -} - -void WebMediaDeviceChangeObserver::Assign( - const WebMediaDeviceChangeObserver& other) { - private_ = other.private_; -} - -void WebMediaDeviceChangeObserver::Reset() { - private_.Reset(); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPictureInPictureButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPictureInPictureButtonElement.cpp index d1004314..035e5a8 100644 --- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPictureInPictureButtonElement.cpp +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlPictureInPictureButtonElement.cpp
@@ -43,7 +43,9 @@ void MediaControlPictureInPictureButtonElement::DefaultEventHandler( Event* event) { - // TODO(apacible): On click, trigger picture in picture. + if (event->type() == EventTypeNames::click) + MediaElement().pictureInPicture(); + MediaControlInputElement::DefaultEventHandler(event); }
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControls.css b/third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControls.css index f652349..6642bfab 100644 --- a/third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControls.css +++ b/third_party/WebKit/Source/modules/media_controls/resources/legacyMediaControls.css
@@ -171,7 +171,8 @@ } /* TODO(xjz): Move media remoting elements to a separate css file. */ -video::-internal-media-remoting-interstitial { +video::-internal-media-remoting-interstitial, +video::-internal-picture-in-picture-interstitial { width: inherit; height: inherit; position: relative; @@ -190,7 +191,8 @@ transition: opacity .3s ease-in-out; } -video::-internal-media-remoting-background-image { +video::-internal-media-remoting-background-image, +video::-internal-picture-in-picture-background-image { display: flex; position: absolute; margin: 0; @@ -225,7 +227,8 @@ top: calc(50% - 3vw); } -video::-internal-media-remoting-cast-text-message { +video::-internal-media-remoting-cast-text-message, +video::-internal-picture-in-picture-message { display: inline; position: absolute; top: calc(50% + 1vw); @@ -241,6 +244,10 @@ margin: 0px; } +video::-internal-picture-in-picture-message { + top: calc(50%); +} + video::-internal-media-remoting-toast-message { display: inline; position: absolute;
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp b/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp index 29675b0..d5830a9 100644 --- a/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp +++ b/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
@@ -68,14 +68,14 @@ MediaDevices::MediaDevices(ExecutionContext* context) : PausableObject(context), - observing_(false), stopped_(false), dispatch_scheduled_event_runner_( context ? AsyncMethodRunner<MediaDevices>::Create( this, &MediaDevices::DispatchScheduledEvent, context->GetTaskRunner(TaskType::kMediaElementEvent)) - : nullptr) {} + : nullptr), + binding_(this) {} MediaDevices::~MediaDevices() = default; @@ -140,14 +140,6 @@ return promise; } -void MediaDevices::DidChangeMediaDevices() { - Document* document = ToDocument(GetExecutionContext()); - DCHECK(document); - - if (RuntimeEnabledFeatures::OnDeviceChangeEnabled()) - ScheduleDispatchEvent(Event::Create(EventTypeNames::devicechange)); -} - const AtomicString& MediaDevices::InterfaceName() const { return EventTargetNames::MediaDevices; } @@ -180,8 +172,8 @@ } bool MediaDevices::HasPendingActivity() const { - DCHECK(stopped_ || observing_ == HasEventListeners()); - return observing_; + DCHECK(stopped_ || binding_.is_bound() == HasEventListeners()); + return binding_.is_bound(); } void MediaDevices::ContextDestroyed(ExecutionContext*) { @@ -204,6 +196,20 @@ dispatch_scheduled_event_runner_->Unpause(); } +void MediaDevices::OnDevicesChanged( + MediaDeviceType type, + uint32_t subscription_id, + Vector<mojom::blink::MediaDeviceInfoPtr> device_infos) { + Document* document = ToDocument(GetExecutionContext()); + DCHECK(document); + + if (RuntimeEnabledFeatures::OnDeviceChangeEnabled()) + ScheduleDispatchEvent(Event::Create(EventTypeNames::devicechange)); + + if (device_change_test_callback_) + std::move(device_change_test_callback_).Run(); +} + void MediaDevices::ScheduleDispatchEvent(Event* event) { scheduled_events_.push_back(event); DCHECK(dispatch_scheduled_event_runner_); @@ -219,35 +225,25 @@ } void MediaDevices::StartObserving() { - if (observing_ || stopped_) + if (binding_.is_bound() || stopped_) return; - UserMediaController* user_media = GetUserMediaController(); - if (!user_media) + Document* document = ToDocument(GetExecutionContext()); + if (!document || !document->GetFrame()) return; - user_media->SetMediaDeviceChangeObserver(this); - observing_ = true; + mojom::blink::MediaDevicesListenerPtr listener; + binding_.Bind(mojo::MakeRequest(&listener)); + GetDispatcherHost(document->GetFrame()) + ->AddMediaDevicesListener(true /* audio input */, true /* video input */, + true /* audio output */, std::move(listener)); } void MediaDevices::StopObserving() { - if (!observing_) + if (!binding_.is_bound()) return; - UserMediaController* user_media = GetUserMediaController(); - if (!user_media) - return; - - user_media->SetMediaDeviceChangeObserver(nullptr); - observing_ = false; -} - -UserMediaController* MediaDevices::GetUserMediaController() { - Document* document = ToDocument(GetExecutionContext()); - if (!document) - return nullptr; - - return UserMediaController::From(document->GetFrame()); + binding_.Close(); } void MediaDevices::Dispose() {
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaDevices.h b/third_party/WebKit/Source/modules/mediastream/MediaDevices.h index 24e4770..b8e9baf 100644 --- a/third_party/WebKit/Source/modules/mediastream/MediaDevices.h +++ b/third_party/WebKit/Source/modules/mediastream/MediaDevices.h
@@ -12,6 +12,7 @@ #include "modules/EventTargetModules.h" #include "modules/ModulesExport.h" #include "modules/mediastream/MediaDeviceInfo.h" +#include "mojo/public/cpp/bindings/binding.h" #include "platform/AsyncMethodRunner.h" #include "platform/heap/HeapAllocator.h" #include "public/platform/modules/mediastream/media_devices.mojom-blink.h" @@ -24,12 +25,12 @@ class ScriptPromise; class ScriptPromiseResolver; class ScriptState; -class UserMediaController; class MODULES_EXPORT MediaDevices final : public EventTargetWithInlineData, public ActiveScriptWrappable<MediaDevices>, - public PausableObject { + public PausableObject, + public mojom::blink::MediaDevicesListener { USING_GARBAGE_COLLECTED_MIXIN(MediaDevices); DEFINE_WRAPPERTYPEINFO(); USING_PRE_FINALIZER(MediaDevices, Dispose); @@ -43,7 +44,6 @@ ScriptPromise getUserMedia(ScriptState*, const MediaStreamConstraints&, ExceptionState&); - void DidChangeMediaDevices(); // EventTarget overrides. const AtomicString& InterfaceName() const override; @@ -58,6 +58,11 @@ void Pause() override; void Unpause() override; + // mojom::blink::MediaDevicesListener implementation. + void OnDevicesChanged(MediaDeviceType, + uint32_t subscription_id, + Vector<mojom::blink::MediaDeviceInfoPtr>) override; + // Callback for testing only. using EnumerateDevicesTestCallback = base::OnceCallback<void(const MediaDeviceInfoVector&)>; @@ -73,6 +78,10 @@ connection_error_test_callback_ = std::move(test_callback); } + void SetDeviceChangeCallbackForTesting(base::OnceClosure test_callback) { + device_change_test_callback_ = std::move(test_callback); + } + virtual void Trace(blink::Visitor*); DEFINE_ATTRIBUTE_EVENT_LISTENER(devicechange); @@ -85,12 +94,12 @@ const RegisteredEventListener&) override; private: + FRIEND_TEST_ALL_PREFIXES(MediaDevicesTest, ObserveDeviceChangeEvent); explicit MediaDevices(ExecutionContext*); void ScheduleDispatchEvent(Event*); void DispatchScheduledEvent(); void StartObserving(); void StopObserving(); - UserMediaController* GetUserMediaController(); void Dispose(); void DevicesEnumerated(ScriptPromiseResolver*, Vector<Vector<mojom::blink::MediaDeviceInfoPtr>>); @@ -98,17 +107,18 @@ const mojom::blink::MediaDevicesDispatcherHostPtr& GetDispatcherHost( LocalFrame*); - bool observing_; bool stopped_; // Async runner may be null when there is no valid execution context. // No async work may be posted in this scenario. Member<AsyncMethodRunner<MediaDevices>> dispatch_scheduled_event_runner_; HeapVector<Member<Event>> scheduled_events_; mojom::blink::MediaDevicesDispatcherHostPtr dispatcher_host_; + mojo::Binding<mojom::blink::MediaDevicesListener> binding_; HeapHashSet<Member<ScriptPromiseResolver>> requests_; EnumerateDevicesTestCallback enumerate_devices_test_callback_; base::OnceClosure connection_error_test_callback_; + base::OnceClosure device_change_test_callback_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaDevicesTest.cpp b/third_party/WebKit/Source/modules/mediastream/MediaDevicesTest.cpp index 41ce570..c712c9f4 100644 --- a/third_party/WebKit/Source/modules/mediastream/MediaDevicesTest.cpp +++ b/third_party/WebKit/Source/modules/mediastream/MediaDevicesTest.cpp
@@ -32,7 +32,7 @@ bool request_video_input, bool request_audio_output, EnumerateDevicesCallback callback) override { - Vector<Vector<mojom::blink::MediaDeviceInfoPtr>> enumeration( + Vector<Vector<MediaDeviceInfoPtr>> enumeration( static_cast<size_t>(MediaDeviceType::NUM_MEDIA_DEVICE_TYPES)); MediaDeviceInfoPtr device_info; if (request_audio_input) { @@ -96,6 +96,14 @@ NOTREACHED(); } + void AddMediaDevicesListener( + bool subscribe_audio_input, + bool subscribe_video_input, + bool subscribe_audio_output, + mojom::blink::MediaDevicesListenerPtr listener) override { + listener_ = std::move(listener); + }; + MOCK_METHOD2(SubscribeDeviceChangeNotifications, void(MediaDeviceType type, uint32_t subscription_id)); MOCK_METHOD2(UnsubscribeDeviceChangeNotifications, @@ -109,7 +117,10 @@ void CloseBinding() { binding_.Close(); } + mojom::blink::MediaDevicesListenerPtr& listener() { return listener_; } + private: + mojom::blink::MediaDevicesListenerPtr listener_; mojo::Binding<mojom::blink::MediaDevicesDispatcherHost> binding_; }; @@ -166,17 +177,27 @@ public: using MediaDeviceInfos = PersistentHeapVector<Member<MediaDeviceInfo>>; - MediaDevicesTest() = default; + MediaDevicesTest() { + dispatcher_host_ = std::make_unique<MockMediaDevicesDispatcherHost>(); + } MediaDevices* GetMediaDevices(ExecutionContext* context) { if (!media_devices_) { media_devices_ = MediaDevices::Create(context); media_devices_->SetDispatcherHostForTesting( - dispatcher_host_.CreateInterfacePtrAndBind()); + dispatcher_host_->CreateInterfacePtrAndBind()); } return media_devices_; } + void CloseBinding() { dispatcher_host_->CloseBinding(); } + + void SimulateDeviceChange() { + DCHECK(listener()); + listener()->OnDevicesChanged(MediaDeviceType::MEDIA_AUDIO_INPUT, 1u, + Vector<MediaDeviceInfoPtr>()); + } + void DevicesEnumerated(const MediaDeviceInfoVector& device_infos) { devices_enumerated_ = true; for (size_t i = 0; i < device_infos.size(); i++) { @@ -186,15 +207,32 @@ } } - void OnDispatcherHostConnectionError() { connection_error_ = true; } + void OnDispatcherHostConnectionError() { + dispatcher_host_connection_error_ = true; + } - void CloseBinding() { dispatcher_host_.CloseBinding(); } + void OnDevicesChanged() { device_changed_ = true; } + + void OnListenerConnectionError() { + listener_connection_error_ = true; + device_changed_ = false; + } + + mojom::blink::MediaDevicesListenerPtr& listener() { + return dispatcher_host_->listener(); + } + + bool listener_connection_error() const { return listener_connection_error_; } const MediaDeviceInfos& device_infos() const { return device_infos_; } bool devices_enumerated() const { return devices_enumerated_; } - bool connection_error() const { return connection_error_; } + bool dispatcher_host_connection_error() const { + return dispatcher_host_connection_error_; + } + + bool device_changed() const { return device_changed_; } ScopedTestingPlatformSupport<TestingPlatformSupport>& platform() { return platform_; @@ -202,10 +240,12 @@ private: ScopedTestingPlatformSupport<TestingPlatformSupport> platform_; - MockMediaDevicesDispatcherHost dispatcher_host_; + std::unique_ptr<MockMediaDevicesDispatcherHost> dispatcher_host_; MediaDeviceInfos device_infos_; bool devices_enumerated_ = false; - bool connection_error_ = false; + bool dispatcher_host_connection_error_ = false; + bool device_changed_ = false; + bool listener_connection_error_ = false; Persistent<MediaDevices> media_devices_; }; @@ -296,7 +336,7 @@ media_devices->SetConnectionErrorCallbackForTesting( WTF::Bind(&MediaDevicesTest::OnDispatcherHostConnectionError, WTF::Unretained(this))); - EXPECT_FALSE(connection_error()); + EXPECT_FALSE(dispatcher_host_connection_error()); // Simulate a connection error by closing the binding. CloseBinding(); @@ -306,7 +346,7 @@ media_devices->enumerateDevices(scope.GetScriptState()); platform()->RunUntilIdle(); ASSERT_FALSE(promise.IsEmpty()); - EXPECT_TRUE(connection_error()); + EXPECT_TRUE(dispatcher_host_connection_error()); EXPECT_FALSE(devices_enumerated()); } @@ -318,7 +358,7 @@ media_devices->SetConnectionErrorCallbackForTesting( WTF::Bind(&MediaDevicesTest::OnDispatcherHostConnectionError, WTF::Unretained(this))); - EXPECT_FALSE(connection_error()); + EXPECT_FALSE(dispatcher_host_connection_error()); ScriptPromise promise = media_devices->enumerateDevices(scope.GetScriptState()); @@ -328,9 +368,38 @@ // Simulate a connection error by closing the binding. CloseBinding(); platform()->RunUntilIdle(); - - EXPECT_TRUE(connection_error()); + EXPECT_TRUE(dispatcher_host_connection_error()); EXPECT_TRUE(devices_enumerated()); } +TEST_F(MediaDevicesTest, ObserveDeviceChangeEvent) { + V8TestingScope scope; + auto media_devices = GetMediaDevices(scope.GetExecutionContext()); + media_devices->SetDeviceChangeCallbackForTesting( + WTF::Bind(&MediaDevicesTest::OnDevicesChanged, WTF::Unretained(this))); + EXPECT_FALSE(listener()); + + // Subscribe for device change event. + media_devices->StartObserving(); + platform()->RunUntilIdle(); + EXPECT_TRUE(listener()); + listener().set_connection_error_handler(WTF::Bind( + &MediaDevicesTest::OnListenerConnectionError, WTF::Unretained(this))); + + // Simulate a device change. + SimulateDeviceChange(); + platform()->RunUntilIdle(); + EXPECT_TRUE(device_changed()); + + // Unsubscribe. + media_devices->StopObserving(); + platform()->RunUntilIdle(); + EXPECT_TRUE(listener_connection_error()); + + // Simulate another device change. + SimulateDeviceChange(); + platform()->RunUntilIdle(); + EXPECT_FALSE(device_changed()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaClient.cpp b/third_party/WebKit/Source/modules/mediastream/UserMediaClient.cpp index b56e308..92e10dc 100644 --- a/third_party/WebKit/Source/modules/mediastream/UserMediaClient.cpp +++ b/third_party/WebKit/Source/modules/mediastream/UserMediaClient.cpp
@@ -35,7 +35,6 @@ #include "modules/mediastream/UserMediaRequest.h" #include "public/web/WebApplyConstraintsRequest.h" #include "public/web/WebFrameClient.h" -#include "public/web/WebMediaDeviceChangeObserver.h" #include "public/web/WebUserMediaClient.h" #include "public/web/WebUserMediaRequest.h" @@ -58,13 +57,6 @@ client_->CancelUserMediaRequest(WebUserMediaRequest(request)); } -void UserMediaClient::SetMediaDeviceChangeObserver(MediaDevices* observer) { - if (client_) { - client_->SetMediaDeviceChangeObserver( - WebMediaDeviceChangeObserver(observer)); - } -} - void UserMediaClient::ApplyConstraints(ApplyConstraintsRequest* request) { if (client_) { client_->ApplyConstraints(WebApplyConstraintsRequest(request));
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaClient.h b/third_party/WebKit/Source/modules/mediastream/UserMediaClient.h index be78d46..aa7c807d 100644 --- a/third_party/WebKit/Source/modules/mediastream/UserMediaClient.h +++ b/third_party/WebKit/Source/modules/mediastream/UserMediaClient.h
@@ -42,7 +42,6 @@ class ApplyConstraintsRequest; class LocalFrame; -class MediaDevices; class MediaStreamComponent; class UserMediaRequest; class WebUserMediaClient; @@ -55,7 +54,6 @@ void RequestUserMedia(UserMediaRequest*); void CancelUserMediaRequest(UserMediaRequest*); - void SetMediaDeviceChangeObserver(MediaDevices*); void ApplyConstraints(ApplyConstraintsRequest*); void StopTrack(MediaStreamComponent*);
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaController.h b/third_party/WebKit/Source/modules/mediastream/UserMediaController.h index b34040f7..32e9bd5 100644 --- a/third_party/WebKit/Source/modules/mediastream/UserMediaController.h +++ b/third_party/WebKit/Source/modules/mediastream/UserMediaController.h
@@ -33,7 +33,6 @@ namespace blink { class ApplyConstraintsRequest; -class MediaDevices; class MediaStreamComponent; class UserMediaRequest; @@ -50,7 +49,6 @@ void RequestUserMedia(UserMediaRequest*); void CancelUserMediaRequest(UserMediaRequest*); - void SetMediaDeviceChangeObserver(MediaDevices*); void ApplyConstraints(ApplyConstraintsRequest*); void StopTrack(MediaStreamComponent*); @@ -73,11 +71,6 @@ client_->CancelUserMediaRequest(request); } -inline void UserMediaController::SetMediaDeviceChangeObserver( - MediaDevices* observer) { - client_->SetMediaDeviceChangeObserver(observer); -} - inline void UserMediaController::ApplyConstraints( ApplyConstraintsRequest* request) { client_->ApplyConstraints(request);
diff --git a/third_party/WebKit/Source/modules/notifications/Notification.cpp b/third_party/WebKit/Source/modules/notifications/Notification.cpp index dcb30a5..903d685 100644 --- a/third_party/WebKit/Source/modules/notifications/Notification.cpp +++ b/third_party/WebKit/Source/modules/notifications/Notification.cpp
@@ -197,7 +197,7 @@ if (RuntimeEnabledFeatures::NotificationsWithMojoEnabled()) { NotificationManager::From(execution_context) - ->DisplayNonPersistentNotification(data_); + ->DisplayNonPersistentNotification(data_, loader->GetResources()); } else { GetWebNotificationManager()->Show(WebSecurityOrigin(origin), data_, loader->GetResources(), this);
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationManager.cpp b/third_party/WebKit/Source/modules/notifications/NotificationManager.cpp index c10d211..9c3b162 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationManager.cpp +++ b/third_party/WebKit/Source/modules/notifications/NotificationManager.cpp
@@ -110,9 +110,11 @@ } void NotificationManager::DisplayNonPersistentNotification( - const WebNotificationData& notification_data) { - // TODO(crbug.com/595685): Pass the notification resources through here too. - GetNotificationService()->DisplayNonPersistentNotification(notification_data); + const WebNotificationData& notification_data, + std::unique_ptr<WebNotificationResources> notification_resources) { + DCHECK(notification_resources); + GetNotificationService()->DisplayNonPersistentNotification( + notification_data, *notification_resources); } const mojom::blink::NotificationServicePtr&
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationManager.h b/third_party/WebKit/Source/modules/notifications/NotificationManager.h index be81474..02da256 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationManager.h +++ b/third_party/WebKit/Source/modules/notifications/NotificationManager.h
@@ -44,7 +44,9 @@ V8NotificationPermissionCallback* deprecated_callback); // Shows a notification that is not tied to any service worker. - void DisplayNonPersistentNotification(const WebNotificationData&); + void DisplayNonPersistentNotification( + const WebNotificationData&, + std::unique_ptr<WebNotificationResources>); virtual void Trace(blink::Visitor*);
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp index dfe18cd3..1fb8406 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -29,6 +29,8 @@ #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" #include "build/build_config.h" +#include "cc/test/skia_common.h" +#include "cc/test/stub_decode_cache.h" #include "components/viz/common/resources/single_release_callback.h" #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/test/test_gpu_memory_buffer_manager.h" @@ -126,6 +128,22 @@ viz::TestGpuMemoryBufferManager test_gpu_memory_buffer_manager_; }; +class ImageTrackingDecodeCache : public cc::StubDecodeCache { + public: + ImageTrackingDecodeCache(std::vector<cc::DrawImage>* decoded_images) + : decoded_images_(decoded_images) {} + ~ImageTrackingDecodeCache() override = default; + + cc::DecodedDrawImage GetDecodedImageForDraw( + const cc::DrawImage& image) override { + decoded_images_->push_back(image); + return cc::StubDecodeCache::GetDecodedImageForDraw(image); + } + + private: + std::vector<cc::DrawImage>* decoded_images_; +}; + } // anonymous namespace class Canvas2DLayerBridgeTest : public Test { @@ -140,18 +158,22 @@ return bridge; } void SetUp() override { - auto factory = [](FakeGLES2Interface* gl, bool* gpu_compositing_disabled) + auto factory = [](FakeGLES2Interface* gl, + std::vector<cc::DrawImage>* decoded_images, + bool* gpu_compositing_disabled) -> std::unique_ptr<WebGraphicsContext3DProvider> { *gpu_compositing_disabled = false; - return std::make_unique<FakeWebGraphicsContext3DProvider>(gl); + return std::make_unique<FakeWebGraphicsContext3DProvider>( + gl, std::make_unique<ImageTrackingDecodeCache>(decoded_images)); }; - SharedGpuContext::SetContextProviderFactoryForTesting( - WTF::BindRepeating(factory, WTF::Unretained(&gl_))); + SharedGpuContext::SetContextProviderFactoryForTesting(WTF::BindRepeating( + factory, WTF::Unretained(&gl_), WTF::Unretained(&decoded_images_))); } void TearDown() override { SharedGpuContext::ResetForTesting(); } protected: MockGLES2InterfaceWithImageSupport gl_; + std::vector<cc::DrawImage> decoded_images_; void FullLifecycleTest() { Canvas2DLayerBridgePtr bridge(WTF::WrapUnique(new Canvas2DLayerBridge( @@ -1242,4 +1264,54 @@ ::testing::Mock::VerifyAndClearExpectations(&gl_); } +TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) { + auto color_params = + CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque); + ASSERT_FALSE(color_params.NeedsSkColorSpaceXformCanvas()); + + Canvas2DLayerBridgePtr bridge(WTF::WrapUnique(new Canvas2DLayerBridge( + IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration, + color_params))); + std::vector<cc::DrawImage> images = { + cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), + SkIRect::MakeWH(10, 10), kNone_SkFilterQuality, + SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()), + cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), + SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(), + 0u, color_params.GetStorageGfxColorSpace())}; + + bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr); + bridge->Canvas()->drawImageRect( + images[1].paint_image(), SkRect::MakeWH(5u, 5u), SkRect::MakeWH(5u, 5u), + nullptr, cc::PaintCanvas::kFast_SrcRectConstraint); + bridge->NewImageSnapshot(kPreferAcceleration); + + EXPECT_EQ(decoded_images_, images); +} + +TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUseWithColorConversion) { + auto color_params = CanvasColorParams(kSRGBCanvasColorSpace, + kRGBA8CanvasPixelFormat, kOpaque); + ASSERT_TRUE(color_params.NeedsSkColorSpaceXformCanvas()); + + Canvas2DLayerBridgePtr bridge(WTF::WrapUnique(new Canvas2DLayerBridge( + IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration, + color_params))); + std::vector<cc::DrawImage> images = { + cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), + SkIRect::MakeWH(10, 10), kNone_SkFilterQuality, + SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()), + cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), + SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(), + 0u, color_params.GetStorageGfxColorSpace())}; + + bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr); + bridge->Canvas()->drawImageRect( + images[1].paint_image(), SkRect::MakeWH(5u, 5u), SkRect::MakeWH(5u, 5u), + nullptr, cc::PaintCanvas::kFast_SrcRectConstraint); + bridge->NewImageSnapshot(kPreferAcceleration); + + EXPECT_EQ(decoded_images_, images); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.cpp b/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.cpp index 7e97c85..e7f5b83 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.cpp +++ b/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.cpp
@@ -5,6 +5,7 @@ #include "platform/graphics/CanvasResourceProvider.h" #include "cc/paint/skia_paint_canvas.h" +#include "cc/raster/playback_image_provider.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" @@ -322,12 +323,20 @@ PaintCanvas* CanvasResourceProvider::Canvas() { if (!canvas_) { + std::unique_ptr<cc::ImageProvider> image_provider; + if (ImageDecodeCache()) { + image_provider = std::make_unique<cc::PlaybackImageProvider>( + ImageDecodeCache(), ColorParams().GetStorageGfxColorSpace(), + cc::PlaybackImageProvider::Settings()); + } + if (ColorParams().NeedsSkColorSpaceXformCanvas()) { canvas_ = std::make_unique<cc::SkiaPaintCanvas>( - GetSkSurface()->getCanvas(), ColorParams().GetSkColorSpace()); + GetSkSurface()->getCanvas(), ColorParams().GetSkColorSpace(), + std::move(image_provider)); } else { - canvas_ = - std::make_unique<cc::SkiaPaintCanvas>(GetSkSurface()->getCanvas()); + canvas_ = std::make_unique<cc::SkiaPaintCanvas>( + GetSkSurface()->getCanvas(), std::move(image_provider)); } } return canvas_.get(); @@ -433,4 +442,11 @@ return nullptr; } +cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCache() { + // TODO(khushalsagar): Hook up a software cache. + if (!context_provider_wrapper_) + return nullptr; + return context_provider_wrapper_->ContextProvider()->ImageDecodeCache(); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.h b/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.h index e736069..456020e 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.h +++ b/third_party/WebKit/Source/platform/graphics/CanvasResourceProvider.h
@@ -19,7 +19,7 @@ class SkCanvas; namespace cc { - +class ImageDecodeCache; class PaintCanvas; } @@ -124,6 +124,7 @@ private: virtual sk_sp<SkSurface> CreateSkSurface() const = 0; virtual scoped_refptr<CanvasResource> CreateResource(); + cc::ImageDecodeCache* ImageDecodeCache(); base::WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_; base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
diff --git a/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitterTest.cpp b/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitterTest.cpp index 0c37c8a4..4920609 100644 --- a/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitterTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/VideoFrameSubmitterTest.cpp
@@ -111,7 +111,7 @@ : now_src_(new base::SimpleTestTickClock()), begin_frame_source_(new viz::FakeExternalBeginFrameSource(0.f, false)), provider_(new StrictMock<MockVideoFrameProvider>()), - context_provider_(cc::TestContextProvider::Create()) { + context_provider_(cc::TestContextProvider::CreateWorker()) { context_provider_->BindToCurrentThread(); }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h index 4cd5c52..065f25ec 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h
@@ -54,6 +54,7 @@ void SetErrorMessageCallback( base::RepeatingCallback<void(const char*, int32_t id)>) {} void SignalQuery(uint32_t, base::OnceClosure) override {} + cc::ImageDecodeCache* ImageDecodeCache() override { return nullptr; } private: std::unique_ptr<gpu::gles2::GLES2Interface> gl_;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp index 56a9fd3..ed10e59 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp
@@ -55,6 +55,7 @@ Platform::ContextAttributes context_attributes; context_attributes.web_gl_version = 1; // GLES2 + context_attributes.enable_raster_interface = true; *gpu_compositing_disabled = Platform::Current()->IsGpuCompositingDisabled(); if (*gpu_compositing_disabled && only_if_gpu_compositing) {
diff --git a/third_party/WebKit/Source/platform/graphics/test/FakeWebGraphicsContext3DProvider.h b/third_party/WebKit/Source/platform/graphics/test/FakeWebGraphicsContext3DProvider.h index b4178fc..c39d80c5 100644 --- a/third_party/WebKit/Source/platform/graphics/test/FakeWebGraphicsContext3DProvider.h +++ b/third_party/WebKit/Source/platform/graphics/test/FakeWebGraphicsContext3DProvider.h
@@ -5,6 +5,7 @@ #ifndef FakeWebGraphicsContext3DProvider_h #define FakeWebGraphicsContext3DProvider_h +#include "cc/tiles/image_decode_cache.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/common/capabilities.h" #include "gpu/config/gpu_feature_info.h" @@ -17,10 +18,15 @@ class FakeWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider { public: - FakeWebGraphicsContext3DProvider(gpu::gles2::GLES2Interface* gl) : gl_(gl) { + FakeWebGraphicsContext3DProvider( + gpu::gles2::GLES2Interface* gl, + std::unique_ptr<cc::ImageDecodeCache> cache = nullptr) + : gl_(gl) { sk_sp<const GrGLInterface> gl_interface(GrGLCreateNullInterface()); gr_context_ = GrContext::MakeGL(std::move(gl_interface)); + image_decode_cache_ = std::move(cache); } + ~FakeWebGraphicsContext3DProvider() override = default; GrContext* GetGrContext() override { return gr_context_.get(); } void InvalidateGrContext(uint32_t state) override { @@ -46,12 +52,16 @@ void SetErrorMessageCallback( base::RepeatingCallback<void(const char*, int32_t id)>) {} void SignalQuery(uint32_t, base::OnceClosure) override {} + cc::ImageDecodeCache* ImageDecodeCache() override { + return image_decode_cache_.get(); + } private: gpu::gles2::GLES2Interface* gl_; sk_sp<GrContext> gr_context_; gpu::Capabilities capabilities_; gpu::GpuFeatureInfo gpu_feature_info_; + std::unique_ptr<cc::ImageDecodeCache> image_decode_cache_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/mojo/DEPS b/third_party/WebKit/Source/platform/mojo/DEPS index d1cce1bd..ed48649b 100644 --- a/third_party/WebKit/Source/platform/mojo/DEPS +++ b/third_party/WebKit/Source/platform/mojo/DEPS
@@ -8,5 +8,6 @@ "+mojo/public/cpp/bindings/binding.h", "+mojo/common/string16.mojom-blink.h", "+mojo/common/test_common_custom_types.mojom-blink.h", - "+services/network/public/interfaces/fetch_api.mojom-blink.h" + "+services/network/public/interfaces/fetch_api.mojom-blink.h", + "+skia/public/interfaces/bitmap_skbitmap_struct_traits.h" ]
diff --git a/third_party/WebKit/Source/platform/mojo/NotificationStructTraits.cpp b/third_party/WebKit/Source/platform/mojo/NotificationStructTraits.cpp index eadbe71..75ad6504 100644 --- a/third_party/WebKit/Source/platform/mojo/NotificationStructTraits.cpp +++ b/third_party/WebKit/Source/platform/mojo/NotificationStructTraits.cpp
@@ -256,4 +256,32 @@ return true; } +// static +base::span<const SkBitmap> +StructTraits<blink::mojom::NotificationResourcesDataView, + blink::WebNotificationResources>:: + action_icons(const blink::WebNotificationResources& resources) { + return base::make_span(resources.action_icons.Data(), + resources.action_icons.size()); +} + +// static +bool StructTraits<blink::mojom::NotificationResourcesDataView, + blink::WebNotificationResources>:: + Read(blink::mojom::NotificationResourcesDataView notification_resources, + blink::WebNotificationResources* out) { + // Cannot read to |out| directly because it expects a WebVector (see above). + Vector<SkBitmap> action_icons; + + if (!notification_resources.ReadImage(&out->image) || + !notification_resources.ReadIcon(&out->icon) || + !notification_resources.ReadBadge(&out->badge) || + !notification_resources.ReadActionIcons(&action_icons)) { + return false; + } + + out->action_icons = action_icons; + return true; +} + } // namespace mojo
diff --git a/third_party/WebKit/Source/platform/mojo/NotificationStructTraits.h b/third_party/WebKit/Source/platform/mojo/NotificationStructTraits.h index 677eebd0..83f0e45 100644 --- a/third_party/WebKit/Source/platform/mojo/NotificationStructTraits.h +++ b/third_party/WebKit/Source/platform/mojo/NotificationStructTraits.h
@@ -15,6 +15,8 @@ #include "platform/wtf/text/WTFString.h" #include "public/platform/modules/notifications/WebNotificationAction.h" #include "public/platform/modules/notifications/notification.mojom-blink.h" +#include "skia/public/interfaces/bitmap_skbitmap_struct_traits.h" +#include "third_party/skia/include/core/SkBitmap.h" namespace mojo { @@ -108,6 +110,31 @@ blink::WebNotificationData* output); }; +template <> +struct PLATFORM_EXPORT StructTraits<blink::mojom::NotificationResourcesDataView, + blink::WebNotificationResources> { + static const SkBitmap& image( + const blink::WebNotificationResources& resources) { + return resources.image; + } + + static const SkBitmap& icon( + const blink::WebNotificationResources& resources) { + return resources.icon; + } + + static const SkBitmap& badge( + const blink::WebNotificationResources& resources) { + return resources.badge; + } + + static base::span<const SkBitmap> action_icons( + const blink::WebNotificationResources&); + + static bool Read(blink::mojom::NotificationResourcesDataView, + blink::WebNotificationResources* output); +}; + } // namespace mojo #endif // NotificationStructTraits_h
diff --git a/third_party/WebKit/Source/platform/mojo/NotificationStructTraitsTest.cpp b/third_party/WebKit/Source/platform/mojo/NotificationStructTraitsTest.cpp index 7e72713..f0299f2 100644 --- a/third_party/WebKit/Source/platform/mojo/NotificationStructTraitsTest.cpp +++ b/third_party/WebKit/Source/platform/mojo/NotificationStructTraitsTest.cpp
@@ -11,17 +11,35 @@ #include "public/platform/WebURL.h" #include "public/platform/WebVector.h" #include "public/platform/modules/notifications/WebNotificationData.h" +#include "public/platform/modules/notifications/WebNotificationResources.h" #include "public/platform/modules/notifications/notification.mojom-blink.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace blink { namespace { const char kNotificationBaseUrl[] = "https://example.com/directory/"; + +SkBitmap CreateBitmap(int width, int height, SkColor color) { + SkBitmap bitmap; + bitmap.allocN32Pixels(width, height); + bitmap.eraseColor(color); + return bitmap; } -namespace blink { +// Returns true if |lhs| and |rhs| have the same width and height and the +// pixel at position (0, 0) is the same color in both. +bool ImagesShareDimensionsAndColor(const SkBitmap& lhs, const SkBitmap& rhs) { + return lhs.width() == rhs.width() && lhs.height() == rhs.height() && + lhs.getColor(0, 0) == rhs.getColor(0, 0); +} -TEST(NotificationStructTraitsTest, Roundtrip) { +} // namespace + +TEST(NotificationStructTraitsTest, NotificationDataRoundtrip) { WebNotificationData notification_data; notification_data.title = "Notification Title"; notification_data.direction = WebNotificationData::kDirectionRightToLeft; @@ -111,4 +129,47 @@ } } +TEST(NotificationStructTraitsTest, NotificationResourcesRoundtrip) { + WebNotificationResources resources; + + resources.image = CreateBitmap(300, 100, SK_ColorCYAN); + resources.icon = CreateBitmap(80, 100, SK_ColorRED); + resources.badge = CreateBitmap(50, 40, SK_ColorGREEN); + + WebVector<SkBitmap> action_icons(static_cast<size_t>(2)); + action_icons[0] = CreateBitmap(10, 10, SK_ColorLTGRAY); + action_icons[1] = CreateBitmap(11, 11, SK_ColorDKGRAY); + + resources.action_icons = action_icons; + + WebNotificationResources roundtrip_resources; + + ASSERT_TRUE(mojom::blink::NotificationResources::Deserialize( + mojom::blink::NotificationResources::Serialize(&resources), + &roundtrip_resources)); + + ASSERT_FALSE(roundtrip_resources.image.empty()); + EXPECT_TRUE(ImagesShareDimensionsAndColor(resources.image, + roundtrip_resources.image)); + + ASSERT_FALSE(roundtrip_resources.icon.empty()); + EXPECT_TRUE( + ImagesShareDimensionsAndColor(resources.icon, roundtrip_resources.icon)); + + ASSERT_FALSE(roundtrip_resources.badge.empty()); + EXPECT_TRUE(ImagesShareDimensionsAndColor(resources.badge, + roundtrip_resources.badge)); + + ASSERT_EQ(resources.action_icons.size(), + roundtrip_resources.action_icons.size()); + + for (size_t i = 0; i < roundtrip_resources.action_icons.size(); ++i) { + SCOPED_TRACE(base::StringPrintf("Action icon index: %zd", i)); + + ASSERT_FALSE(roundtrip_resources.action_icons[i].empty()); + EXPECT_TRUE(ImagesShareDimensionsAndColor( + resources.action_icons[i], roundtrip_resources.action_icons[i])); + } +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5 index f82f29a..e25617ce 100644 --- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 +++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -450,7 +450,7 @@ { name: "FramebustingNeedsSameOriginOrUserGesture", settable_from_internals: true, - status: "stable", + status: "experimental", }, { name: "FramesTimingFunction", @@ -818,6 +818,7 @@ }, { name: "PictureInPicture", + settable_from_internals: true, }, { name: "PreciseMemoryInfo",
diff --git a/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.h b/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.h index 2e4eaaab..4802f2a 100644 --- a/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.h +++ b/third_party/WebKit/Source/platform/testing/EmptyWebMediaPlayer.h
@@ -22,6 +22,7 @@ void Seek(double seconds) override {} void SetRate(double) override {} void SetVolume(double) override {} + void PictureInPicture() override {} WebTimeRanges Buffered() const override; WebTimeRanges Seekable() const override; void SetSinkId(const WebString& sink_id,
diff --git a/third_party/WebKit/common/OWNERS b/third_party/WebKit/common/OWNERS index 2fdf5e4..cdea22e 100644 --- a/third_party/WebKit/common/OWNERS +++ b/third_party/WebKit/common/OWNERS
@@ -3,5 +3,8 @@ kinuko@chromium.org tkent@chromium.org jbroman@chromium.org +pfeldman@chromium.org +dgozman@chromium.org +dcheng@chromium.org # COMPONENT: Blink
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index 6b758c26..c16c401 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -516,7 +516,6 @@ "web/WebLeakDetector.h", "web/WebLocalFrame.h", "web/WebMeaningfulLayout.h", - "web/WebMediaDeviceChangeObserver.h", "web/WebMediaPlayerAction.h", "web/WebMediaStreamRegistry.h", "web/WebMemoryStatistics.h",
diff --git a/third_party/WebKit/public/platform/Platform.h b/third_party/WebKit/public/platform/Platform.h index cc2a721a..0da86d4 100644 --- a/third_party/WebKit/public/platform/Platform.h +++ b/third_party/WebKit/public/platform/Platform.h
@@ -522,6 +522,9 @@ bool support_depth = false; bool support_antialias = false; bool support_stencil = false; + + // Offscreen contexts created for WebGL should not need the RasterInterface. + bool enable_raster_interface = false; }; struct GraphicsInfo { unsigned vendor_id = 0;
diff --git a/third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h b/third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h index 9e37b9d..27ea98b5 100644 --- a/third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h +++ b/third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h
@@ -35,6 +35,10 @@ class GrContext; +namespace cc { +class ImageDecodeCache; +} // namespace cc + namespace gpu { struct Capabilities; struct GpuFeatureInfo; @@ -74,6 +78,7 @@ virtual void SetErrorMessageCallback( base::RepeatingCallback<void(const char* msg, int32_t id)>) = 0; virtual void SignalQuery(uint32_t, base::OnceClosure) = 0; + virtual cc::ImageDecodeCache* ImageDecodeCache() = 0; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebLocalizedString.h b/third_party/WebKit/public/platform/WebLocalizedString.h index a0d98831..f379d9e7 100644 --- a/third_party/WebKit/public/platform/WebLocalizedString.h +++ b/third_party/WebKit/public/platform/WebLocalizedString.h
@@ -113,6 +113,7 @@ kOverflowMenuPause, kOverflowMenuDownload, kOverflowMenuPictureInPicture, + kPictureInPictureInterstitialText, // kPlaceholderForDayOfMonthField is for day placeholder text, e.g. // "dd", for date field used in multiple fields "date", "datetime", and // "datetime-local" input UI instead of "--".
diff --git a/third_party/WebKit/public/platform/WebMediaPlayer.h b/third_party/WebKit/public/platform/WebMediaPlayer.h index c2c2967..92635f3 100644 --- a/third_party/WebKit/public/platform/WebMediaPlayer.h +++ b/third_party/WebKit/public/platform/WebMediaPlayer.h
@@ -126,6 +126,7 @@ virtual void Seek(double seconds) = 0; virtual void SetRate(double) = 0; virtual void SetVolume(double) = 0; + virtual void PictureInPicture() = 0; virtual void RequestRemotePlayback() {} virtual void RequestRemotePlaybackControl() {}
diff --git a/third_party/WebKit/public/platform/WebMediaPlayerClient.h b/third_party/WebKit/public/platform/WebMediaPlayerClient.h index 55e2501..2bfbcce 100644 --- a/third_party/WebKit/public/platform/WebMediaPlayerClient.h +++ b/third_party/WebKit/public/platform/WebMediaPlayerClient.h
@@ -129,6 +129,9 @@ // to a localized string that explains the reason as user-readable text. virtual void MediaRemotingStopped(WebLocalizedString::Name error_msg) = 0; + virtual void PictureInPictureStarted() = 0; + virtual void PictureInPictureStopped() = 0; + // Returns whether the media element has native controls. It does not mean // that the controls are currently visible. virtual bool HasNativeControls() = 0;
diff --git a/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom b/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom index e09f4fc..1d1f8d64 100644 --- a/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom +++ b/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
@@ -82,6 +82,8 @@ GetAudioInputCapabilities() => (array<AudioInputDeviceCapabilities> audio_input_device_capabilities); + // TODO(c.padhi): Remove below two methods once device change migration to + // blink is complete, see https://crbug.com/793297. // Creates a subscription for device-change notifications for the calling // frame/security origin. It is the responsibility of the caller to send // |subscription_id| values that are unique per device type. @@ -96,11 +98,22 @@ // a nonexisting subscription with are invalid and result in a renderer crash. UnsubscribeDeviceChangeNotifications(MediaDeviceType type, uint32 subscription_id); + + // Subscribes |listener| to device-change notifications for the calling + // frame/security origin. |listener| will receive notifications only for + // device types decided by the boolean fields. Closing the pipe will cancel + // the subscription. + AddMediaDevicesListener(bool subscribe_audio_input, + bool subscribe_video_input, + bool subscribe_audio_output, + MediaDevicesListener listener); }; // This object lives in the renderer process and is used by the browser process // to pass device-change notifications to the renderer. interface MediaDevicesListener { + // TODO(c.padhi): Remove |subscription_id| once device change migration to + // blink is complete, see https://crbug.com/793297. // Called to notify a change in the set of devices of type |type| for // subscription |subscription_id|. |device_infos| contains the new list of // devices of type |type|, with device and group IDs obfuscated according to
diff --git a/third_party/WebKit/public/platform/modules/notifications/NotificationTypes.typemap b/third_party/WebKit/public/platform/modules/notifications/NotificationTypes.typemap index a7ac232..6a4763d 100644 --- a/third_party/WebKit/public/platform/modules/notifications/NotificationTypes.typemap +++ b/third_party/WebKit/public/platform/modules/notifications/NotificationTypes.typemap
@@ -3,7 +3,13 @@ # found in the LICENSE file. mojom = "//third_party/WebKit/public/platform/modules/notifications/notification.mojom" -public_headers = [ "//third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h" ] +public_headers = [ + "//third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h", + "//third_party/WebKit/public/platform/modules/notifications/WebNotificationResources.h", +] traits_headers = [ "//third_party/WebKit/Source/platform/mojo/NotificationStructTraits.h" ] -type_mappings = [ "blink.mojom.NotificationData=::blink::WebNotificationData" ] +type_mappings = [ + "blink.mojom.NotificationData=::blink::WebNotificationData", + "blink.mojom.NotificationResources=::blink::WebNotificationResources", +]
diff --git a/third_party/WebKit/public/platform/modules/notifications/notification.mojom b/third_party/WebKit/public/platform/modules/notifications/notification.mojom index e4f6c0b8..61247c99 100644 --- a/third_party/WebKit/public/platform/modules/notifications/notification.mojom +++ b/third_party/WebKit/public/platform/modules/notifications/notification.mojom
@@ -5,6 +5,7 @@ module blink.mojom; import "mojo/common/string16.mojom"; +import "skia/public/interfaces/bitmap.mojom"; import "url/mojo/url.mojom"; // Directionality options that can be indicated for notifications. @@ -100,3 +101,19 @@ // Actions that should be shown as buttons on the notification. array<NotificationAction>? actions; }; + +// Structure representing the resources associated with a Web Notification. +struct NotificationResources { + // Image contents of the notification. May be empty if no image was specified. + skia.mojom.Bitmap? image; + + // Icon to be displayed with the notification. + skia.mojom.Bitmap? icon; + + // Badge representing the website displaying the notification. + skia.mojom.Bitmap? badge; + + // Icons for the actions. The size of |action_icons| must match the size + // of |actions| in the corresponding NotificationData. + array<skia.mojom.Bitmap>? action_icons; +};
diff --git a/third_party/WebKit/public/platform/modules/notifications/notification_service.mojom b/third_party/WebKit/public/platform/modules/notifications/notification_service.mojom index acf5277..2f42087e 100644 --- a/third_party/WebKit/public/platform/modules/notifications/notification_service.mojom +++ b/third_party/WebKit/public/platform/modules/notifications/notification_service.mojom
@@ -17,6 +17,7 @@ [Sync] GetPermissionStatus() => (PermissionStatus status); // Shows a notification that is not associated with a service worker. - // TODO(crbug.com/595685): Pass the notification resources through too. - DisplayNonPersistentNotification(NotificationData notification_data); + DisplayNonPersistentNotification( + NotificationData notification_data, + NotificationResources notification_resources); };
diff --git a/third_party/WebKit/public/platform/web_feature.mojom b/third_party/WebKit/public/platform/web_feature.mojom index fbeb7b7b60..09dd45d 100644 --- a/third_party/WebKit/public/platform/web_feature.mojom +++ b/third_party/WebKit/public/platform/web_feature.mojom
@@ -1851,6 +1851,8 @@ kScrollToFragmentFailWithMixed = 2344, kScrollToFragmentFailWithInvalidEncoding = 2345, kRTCPeerConnectionWithActiveCsp = 2346, + kImageDecodingAttribute = 2347, + kImageDecodeAPI = 2348, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/public/web/WebMediaDeviceChangeObserver.h b/third_party/WebKit/public/web/WebMediaDeviceChangeObserver.h deleted file mode 100644 index 824b045..0000000 --- a/third_party/WebKit/public/web/WebMediaDeviceChangeObserver.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef WebMediaDeviceChangeObserver_h -#define WebMediaDeviceChangeObserver_h - -#include "public/platform/WebPrivatePtr.h" - -namespace blink { - -class MediaDevices; -class WebSecurityOrigin; - -class WebMediaDeviceChangeObserver { - public: - BLINK_EXPORT WebMediaDeviceChangeObserver(); - BLINK_EXPORT explicit WebMediaDeviceChangeObserver(bool); // for testing only - BLINK_EXPORT WebMediaDeviceChangeObserver( - const WebMediaDeviceChangeObserver&); - BLINK_EXPORT WebMediaDeviceChangeObserver& operator=( - const WebMediaDeviceChangeObserver&); - BLINK_EXPORT ~WebMediaDeviceChangeObserver(); - - // Notify that the set of media devices has changed. - BLINK_EXPORT void DidChangeMediaDevices(); - BLINK_EXPORT bool IsNull() const; - BLINK_EXPORT WebSecurityOrigin GetSecurityOrigin() const; - -#if INSIDE_BLINK - BLINK_EXPORT explicit WebMediaDeviceChangeObserver(MediaDevices*); -#endif - private: - void Assign(const WebMediaDeviceChangeObserver&); - void Reset(); - WebPrivatePtr<MediaDevices> private_; -}; - -} // namespace blink - -#endif
diff --git a/third_party/WebKit/public/web/WebUserMediaClient.h b/third_party/WebKit/public/web/WebUserMediaClient.h index a11c9ea..729ad751 100644 --- a/third_party/WebKit/public/web/WebUserMediaClient.h +++ b/third_party/WebKit/public/web/WebUserMediaClient.h
@@ -36,7 +36,6 @@ class WebApplyConstraintsRequest; class WebMediaStreamTrack; class WebUserMediaRequest; -class WebMediaDeviceChangeObserver; class WebUserMediaClient { public: @@ -44,8 +43,6 @@ virtual void RequestUserMedia(const WebUserMediaRequest&) = 0; virtual void CancelUserMediaRequest(const WebUserMediaRequest&) = 0; - virtual void SetMediaDeviceChangeObserver( - const WebMediaDeviceChangeObserver&) = 0; virtual void ApplyConstraints(const WebApplyConstraintsRequest&) = 0; virtual void StopTrack(const WebMediaStreamTrack&) = 0; };
diff --git a/third_party/closure_compiler/externs/networking_private.js b/third_party/closure_compiler/externs/networking_private.js index 8fda402..c07bea1 100644 --- a/third_party/closure_compiler/externs/networking_private.js +++ b/third_party/closure_compiler/externs/networking_private.js
@@ -1,4 +1,4 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -567,7 +567,7 @@ * Password: (string|undefined), * Port: (number|undefined), * Proto: (string|undefined), - * PushPeerInfo: (string|undefined), + * PushPeerInfo: (boolean|undefined), * RemoteCertEKU: (string|undefined), * RemoteCertKU: (!Array<string>|undefined), * RemoteCertTLS: (string|undefined), @@ -612,7 +612,7 @@ * Password: (!chrome.networkingPrivate.ManagedDOMString|undefined), * Port: (!chrome.networkingPrivate.ManagedLong|undefined), * Proto: (!chrome.networkingPrivate.ManagedDOMString|undefined), - * PushPeerInfo: (!chrome.networkingPrivate.ManagedDOMString|undefined), + * PushPeerInfo: (!chrome.networkingPrivate.ManagedBoolean|undefined), * RemoteCertEKU: (!chrome.networkingPrivate.ManagedDOMString|undefined), * RemoteCertKU: (!chrome.networkingPrivate.ManagedDOMStringList|undefined), * RemoteCertTLS: (!chrome.networkingPrivate.ManagedDOMString|undefined), @@ -1233,6 +1233,9 @@ * @param {function():void=} callback Called when the connect request has been * sent. Note: the connection may not have completed. Observe * $(ref:onNetworksChanged) to be notified when a network state changes. + * If the connect request immediately failed (e.g. the network is + * unconfigured), $(ref:runtime.lastError) will be set with a failure + * reason. * @see https://developer.chrome.com/extensions/networkingPrivate#method-startConnect */ chrome.networkingPrivate.startConnect = function(networkGuid, callback) {}; @@ -1359,7 +1362,7 @@ * This will not lock the SIM; that is handled automatically by the device. * NOTE: If the SIM is locked, it must first be unlocked with * unlockCellularSim() before this can be called (otherwise it will fail and - * chrome.runtime.lastError will be set to Error.SimLocked). + * $(ref:runtime.lastError) will be set to Error.SimLocked). * @param {string} networkGuid The GUID of the cellular network to set the SIM * state of. If empty, the default cellular device will be used. * @param {!chrome.networkingPrivate.CellularSimState} simState The SIM state to
diff --git a/tools/grit/grit/format/rc_header.py b/tools/grit/grit/format/rc_header.py index cea0cad..7dedd37 100755 --- a/tools/grit/grit/format/rc_header.py +++ b/tools/grit/grit/format/rc_header.py
@@ -28,45 +28,22 @@ for line in emit_lines or default_includes: yield line + '\n' - for line in FormatDefines(root, root.ShouldOutputAllResourceDefines(), - root.GetRcHeaderFormat()): + for line in FormatDefines(root, root.GetRcHeaderFormat()): yield line -def FormatDefines(root, output_all_resource_defines=True, - rc_header_format=None): +def FormatDefines(root, rc_header_format=None): '''Yields #define SYMBOL 1234 lines. Args: root: A GritNode. - output_all_resource_defines: If False, output only the symbols used in the - current output configuration. ''' - if output_all_resource_defines: - items = root.Preorder() - else: - items = root.ActiveDescendants() tids = root.GetIdMap() if not rc_header_format: rc_header_format = "#define {textual_id} {numeric_id}" rc_header_format += "\n" - seen = set() - for item in items: - if not isinstance(item, message.MessageNode): - with item: - for tid in item.GetTextualIds(): - if tid in tids and tid not in seen: - seen.add(tid) - yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid]) - - # Temporarily mimic old behavior: MessageNodes were only output if active, - # even with output_all_resource_defines set. TODO(benrg): Remove this after - # fixing problems in the Chrome tree. for item in root.ActiveDescendants(): - if isinstance(item, message.MessageNode): - with item: - for tid in item.GetTextualIds(): - if tid in tids and tid not in seen: - seen.add(tid) - yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid]) + with item: + for tid in item.GetTextualIds(): + yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid])
diff --git a/tools/grit/grit/format/rc_header_unittest.py b/tools/grit/grit/format/rc_header_unittest.py index 3cba963..2eb2a638 100755 --- a/tools/grit/grit/format/rc_header_unittest.py +++ b/tools/grit/grit/format/rc_header_unittest.py
@@ -23,7 +23,7 @@ class RcHeaderFormatterUnittest(unittest.TestCase): def FormatAll(self, grd): - output = rc_header.FormatDefines(grd, grd.ShouldOutputAllResourceDefines()) + output = rc_header.FormatDefines(grd) return ''.join(output).replace(' ', '') def testFormatter(self): @@ -78,7 +78,6 @@ output = self.FormatAll(grd) self.failUnless(output.count('IDS_FIRSTPRESENTSTRING10000')) self.failIf(output.count('IDS_MISSINGSTRING')) - self.failIf(output.count('10001')) # IDS_MISSINGSTRING should get this ID self.failUnless(output.count('IDS_LANGUAGESPECIFICSTRING10002')) self.failUnless(output.count('IDS_THIRDPRESENTSTRING10003')) @@ -119,8 +118,7 @@ </messages>''') # Using the default rc_header format string. - output = rc_header.FormatDefines(grd, grd.ShouldOutputAllResourceDefines(), - grd.GetRcHeaderFormat()) + output = rc_header.FormatDefines(grd, grd.GetRcHeaderFormat()) self.assertEqual(('#define IDR_LOGO 300\n' '#define IDS_GREETING 10000\n' '#define IDS_BONGO 10001\n'), ''.join(output)) @@ -128,8 +126,7 @@ # Using a custom rc_header format string. grd.AssignRcHeaderFormat( '#define {textual_id} _Pragma("{textual_id}") {numeric_id}') - output = rc_header.FormatDefines(grd, grd.ShouldOutputAllResourceDefines(), - grd.GetRcHeaderFormat()) + output = rc_header.FormatDefines(grd, grd.GetRcHeaderFormat()) self.assertEqual(('#define IDR_LOGO _Pragma("IDR_LOGO") 300\n' '#define IDS_GREETING _Pragma("IDS_GREETING") 10000\n' '#define IDS_BONGO _Pragma("IDS_BONGO") 10001\n'),
diff --git a/tools/grit/grit/format/resource_map.py b/tools/grit/grit/format/resource_map.py index d70216ff..5fee06b8 100755 --- a/tools/grit/grit/format/resource_map.py +++ b/tools/grit/grit/format/resource_map.py
@@ -122,23 +122,19 @@ id_map = root.GetIdMap() yield _FormatSourceHeader(root, output_dir, include_gzipped) seen = set() - active_descendants = [item for item in root.ActiveDescendants()] - output_all_resource_defines = root.ShouldOutputAllResourceDefines() - for item in root: + for item in root.ActiveDescendants(): if not item.IsResourceMapSource(): continue key = get_key(item) tid = item.attrs['name'] if tid not in id_map or key in seen: continue - if item.GeneratesResourceMapEntry(output_all_resource_defines, - item in active_descendants): - seen.add(key) - if include_gzipped: - gzipped = item.attrs.get('compress', '') == 'gzip' - yield ' {"%s", %s, %s},\n' % (key, tid, 'true' if gzipped else 'false') - else: - yield ' {"%s", %s},\n' % (key, tid) + seen.add(key) + if include_gzipped: + gzipped = item.attrs.get('compress', '') == 'gzip' + yield ' {"%s", %s, %s},\n' % (key, tid, 'true' if gzipped else 'false') + else: + yield ' {"%s", %s},\n' % (key, tid) yield _FormatSourceFooter(root)
diff --git a/tools/grit/grit/format/resource_map_unittest.py b/tools/grit/grit/format/resource_map_unittest.py index c6c8da1..8be4167 100755 --- a/tools/grit/grit/format/resource_map_unittest.py +++ b/tools/grit/grit/format/resource_map_unittest.py
@@ -67,7 +67,6 @@ const GritResourceMap kTheRcHeader[] = { {"IDC_KLONKMENU", IDC_KLONKMENU}, {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT}, - {"IDS_MISSING", IDS_MISSING}, {"IDS_LANGUAGESPECIFIC", IDS_LANGUAGESPECIFIC}, {"IDS_THIRDPRESENT", IDS_THIRDPRESENT}, }; @@ -82,9 +81,7 @@ const GritResourceMap kTheRcHeader[] = { {"grit/testdata/klonk.rc", IDC_KLONKMENU}, {"abc", IDS_FIRSTPRESENT}, - {"def", IDS_MISSING}, {"ghi", IDS_LANGUAGESPECIFIC}, - {"jkl", IDS_LANGUAGESPECIFIC}, {"mno", IDS_THIRDPRESENT}, }; const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output) @@ -134,7 +131,6 @@ const GzippedGritResourceMap kTheRcHeader[] = { {"grit/testdata/klonk.rc", IDC_KLONKMENU, true}, {"abc", IDS_FIRSTPRESENT, false}, - {"def", IDS_MISSING, false}, }; const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output) @@ -178,7 +174,7 @@ file="xyz.png" /> </if> </structures> - </release>''', run_gatherers=True, output_all_resource_defines=False) + </release>''', run_gatherers=True) output = util.StripBlankLinesAndComments(''.join( resource_map.GetFormatter('resource_map_header')(grd, 'en', '.'))) self.assertEqual('''\ @@ -257,7 +253,7 @@ <include type="foo" file="xyz" name="IDS_LAST" /> </if> </includes> - </release>''', run_gatherers=True, output_all_resource_defines=False) + </release>''', run_gatherers=True) output = util.StripBlankLinesAndComments(''.join( resource_map.GetFormatter('resource_map_header')(grd, 'en', '.'))) self.assertEqual('''\ @@ -329,7 +325,8 @@ </message> </if> </messages> - </release>''', run_gatherers=True, output_all_resource_defines=False) + </release>''', run_gatherers=True) + grd.InitializeIds() output = util.StripBlankLinesAndComments(''.join( resource_map.GetFormatter('resource_map_header')(grd, 'en', '.'))) self.assertEqual('''\
diff --git a/tools/grit/grit/node/base.py b/tools/grit/grit/node/base.py index 9fb1e47..e40bad8 100755 --- a/tools/grit/grit/node/base.py +++ b/tools/grit/grit/node/base.py
@@ -597,17 +597,6 @@ '''Whether this node is a resource map source.''' return False - def GeneratesResourceMapEntry(self, output_all_resource_defines, - is_active_descendant): - '''Whether this node should output a resource map entry. - - Args: - output_all_resource_defines: The value of output_all_resource_defines for - the root node. - is_active_descendant: Whether the current node is an active descendant - from the root node.''' - return False - def CompressDataIfNeeded(self, data): '''Compress data using the format specified in the compress attribute.
diff --git a/tools/grit/grit/node/include.py b/tools/grit/grit/node/include.py index 3ebdcf61..27cff17a10 100755 --- a/tools/grit/grit/node/include.py +++ b/tools/grit/grit/node/include.py
@@ -118,13 +118,6 @@ def IsResourceMapSource(self): return True - def GeneratesResourceMapEntry(self, output_all_resource_defines, - is_active_descendant): - # includes always generate resource entries. - if output_all_resource_defines: - return True - return is_active_descendant - @staticmethod def Construct(parent, name, type, file, translateable=True, filenameonly=False, mkoutput=False, relativepath=False):
diff --git a/tools/grit/grit/node/message.py b/tools/grit/grit/node/message.py index b8eca3e..1b887c2 100755 --- a/tools/grit/grit/node/message.py +++ b/tools/grit/grit/node/message.py
@@ -231,10 +231,6 @@ def IsResourceMapSource(self): return True - def GeneratesResourceMapEntry(self, output_all_resource_defines, - is_active_descendant): - return is_active_descendant - @staticmethod def Construct(parent, message, name, desc='', meaning='', translateable=True): '''Constructs a new message node that is a child of 'parent', with the
diff --git a/tools/grit/grit/node/misc.py b/tools/grit/grit/node/misc.py index 174e5b2..f3bcab90 100755 --- a/tools/grit/grit/node/misc.py +++ b/tools/grit/grit/node/misc.py
@@ -335,7 +335,6 @@ 'source_lang_id' : 'en', 'enc_check' : constants.ENCODING_CHECK, 'tc_project' : 'NEED_TO_SET_tc_project_ATTRIBUTE', - 'output_all_resource_defines': 'true', 'rc_header_format': None } @@ -427,18 +426,6 @@ """ return self.attrs['base_dir'] - def SetShouldOutputAllResourceDefines(self, value): - """Overrides the value of output_all_resource_defines found in the grd file. - """ - self.attrs['output_all_resource_defines'] = 'true' if value else 'false' - - def ShouldOutputAllResourceDefines(self): - """Returns true if all resource defines should be output, false if - defines for resources not emitted to resource files should be - skipped. - """ - return self.attrs['output_all_resource_defines'] == 'true' - def GetRcHeaderFormat(self): return self.attrs['rc_header_format']
diff --git a/tools/grit/grit/node/structure.py b/tools/grit/grit/node/structure.py index 89d5202..7b6f7bf 100755 --- a/tools/grit/grit/node/structure.py +++ b/tools/grit/grit/node/structure.py
@@ -333,12 +333,6 @@ def IsResourceMapSource(self): return True - def GeneratesResourceMapEntry(self, output_all_resource_defines, - is_active_descendant): - if output_all_resource_defines: - return True - return is_active_descendant - @staticmethod def Construct(parent, name, type, file, encoding='cp1252'): '''Creates a new node which is a child of 'parent', with attributes set
diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py index f1a1fdf..0f5b001 100755 --- a/tools/grit/grit/tool/build.py +++ b/tools/grit/grit/tool/build.py
@@ -118,11 +118,6 @@ and {numeric_id}. E.g. "#define {textual_id} {numeric_id}" Otherwise it will use the default "#define SYMBOL 1234" - --output-all-resource-defines - --no-output-all-resource-defines If specified, overrides the value of the - output_all_resource_defines attribute of the root <grit> - element of the input .grd file. - --write-only-new flag If flag is non-0, write output files to a temporary file first, and copy it to the real output only if the new file @@ -162,7 +157,6 @@ depfile = None depdir = None rc_header_format = None - output_all_resource_defines = None write_only_new = False depend_on_stamp = False js_minifier = None @@ -196,10 +190,6 @@ first_ids_file = val elif key == '-w': whitelist_filenames.append(val) - elif key == '--output-all-resource-defines': - output_all_resource_defines = True - elif key == '--no-output-all-resource-defines': - output_all_resource_defines = False elif key == '--no-replace-ellipsis': replace_ellipsis = False elif key == '-p': @@ -249,11 +239,6 @@ defines=self.defines, target_platform=target_platform) - # If the output_all_resource_defines option is specified, override the value - # found in the grd file. - if output_all_resource_defines is not None: - self.res.SetShouldOutputAllResourceDefines(output_all_resource_defines) - # Set an output context so that conditionals can use defines during the # gathering stage; we use a dummy language here since we are not outputting # a specific language. @@ -342,6 +327,24 @@ # consumers can account for terminating newlines. infofile.writelines(['\n'.join(node.info), '\n']) + @staticmethod + def _EncodingForOutputType(output_type): + # Microsoft's RC compiler can only deal with single-byte or double-byte + # files (no UTF-8), so we make all RC files UTF-16 to support all + # character sets. + if output_type in ('rc_header', 'resource_map_header', + 'resource_map_source', 'resource_file_map_source', + 'gzipped_resource_map_header', + 'gzipped_resource_file_map_source'): + return 'cp1252' + if output_type in ('android', 'c_format', 'js_map_format', 'plist', + 'plist_strings', 'doc', 'json', 'android_policy'): + return 'utf_8' + if output_type in ('chrome_messages_json'): + # Chrome Web Store currently expects BOM for UTF-8 files :-( + return 'utf-8-sig' + # TODO(gfeher) modify here to set utf-8 encoding for admx/adml + return 'utf_16' def Process(self): # Update filenames with those provided by SCons if we're being invoked @@ -367,23 +370,6 @@ for output in self.res.GetOutputFiles(): self.VerboseOut('Creating %s...' % output.GetOutputFilename()) - # Microsoft's RC compiler can only deal with single-byte or double-byte - # files (no UTF-8), so we make all RC files UTF-16 to support all - # character sets. - if output.GetType() in ('rc_header', 'resource_map_header', - 'resource_map_source', 'resource_file_map_source', - 'gzipped_resource_map_header', 'gzipped_resource_file_map_source'): - encoding = 'cp1252' - elif output.GetType() in ('android', 'c_format', 'js_map_format', 'plist', - 'plist_strings', 'doc', 'json', 'android_policy'): - encoding = 'utf_8' - elif output.GetType() in ('chrome_messages_json'): - # Chrome Web Store currently expects BOM for UTF-8 files :-( - encoding = 'utf-8-sig' - else: - # TODO(gfeher) modify here to set utf-8 encoding for admx/adml - encoding = 'utf_16' - # Set the context, for conditional inclusion of resources self.res.SetOutputLanguage(output.GetLanguage()) self.res.SetOutputContext(output.GetContext()) @@ -402,6 +388,7 @@ outfile = self.fo_create(output.GetOutputFilename() + '.tmp', 'wb') if output.GetType() != 'data_package': + encoding = self._EncodingForOutputType(output.GetType()) outfile = util.WrapOutputStream(outfile, encoding) # Iterate in-order through entire resource tree, calling formatters on
diff --git a/tools/grit/grit/tool/build_unittest.py b/tools/grit/grit/tool/build_unittest.py index d6e3727..7dad441 100755 --- a/tools/grit/grit/tool/build_unittest.py +++ b/tools/grit/grit/tool/build_unittest.py
@@ -21,6 +21,15 @@ class BuildUnittest(unittest.TestCase): + # IDs should not change based on whitelisting. + # Android WebView currently relies on this. + EXPECTED_ID_MAP = { + 'IDS_MESSAGE_WHITELISTED': 6889, + 'IDR_STRUCTURE_WHITELISTED': 11546, + 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED': 11548, + 'IDR_INCLUDE_WHITELISTED': 15601, + } + def testFindTranslationsWithSubstitutions(self): # This is a regression test; we had a bug where GRIT would fail to find # messages with substitutions e.g. "Hello [IDS_USER]" where IDS_USER is @@ -159,6 +168,13 @@ for whitelisted_id in whitelisted_ids: if whitelisted_id in line: whitelisted_ids_found.append(whitelisted_id) + if filename.endswith('.h'): + numeric_id = int(line.split()[2]) + expected_numeric_id = self.EXPECTED_ID_MAP.get(whitelisted_id) + self.assertEqual( + expected_numeric_id, numeric_id, + 'Numeric ID for {} was {} should be {}'.format( + whitelisted_id, numeric_id, expected_numeric_id)) for non_whitelisted_id in non_whitelisted_ids: if non_whitelisted_id in line: non_whitelisted_ids_found.append(non_whitelisted_id) @@ -238,73 +254,6 @@ non_whitelisted_ids, ) - def testOutputAllResourceDefinesTrue(self): - output_dir = tempfile.mkdtemp() - builder = build.RcBuilder() - class DummyOpts(object): - def __init__(self): - self.input = util.PathFromRoot('grit/testdata/whitelist_resources.grd') - self.verbose = False - self.extra_verbose = False - whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt') - builder.Run(DummyOpts(), ['-o', output_dir, - '-w', whitelist_file, - '--output-all-resource-defines',]) - header = os.path.join(output_dir, 'whitelist_test_resources.h') - map_cc = os.path.join(output_dir, 'whitelist_test_resources_map.cc') - - whitelisted_ids = [ - 'IDR_STRUCTURE_WHITELISTED', - 'IDR_STRUCTURE_NOT_WHITELISTED', - 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED', - 'IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED', - 'IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED', - 'IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED', - 'IDR_INCLUDE_WHITELISTED', - 'IDR_INCLUDE_NOT_WHITELISTED', - ] - non_whitelisted_ids = [] - for output_file in (header, map_cc): - self._verifyWhitelistedOutput( - output_file, - whitelisted_ids, - non_whitelisted_ids, - ) - - def testOutputAllResourceDefinesFalse(self): - output_dir = tempfile.mkdtemp() - builder = build.RcBuilder() - class DummyOpts(object): - def __init__(self): - self.input = util.PathFromRoot('grit/testdata/whitelist_resources.grd') - self.verbose = False - self.extra_verbose = False - whitelist_file = util.PathFromRoot('grit/testdata/whitelist.txt') - builder.Run(DummyOpts(), ['-o', output_dir, - '-w', whitelist_file, - '--no-output-all-resource-defines',]) - header = os.path.join(output_dir, 'whitelist_test_resources.h') - map_cc = os.path.join(output_dir, 'whitelist_test_resources_map.cc') - - whitelisted_ids = [ - 'IDR_STRUCTURE_WHITELISTED', - 'IDR_STRUCTURE_IN_TRUE_IF_WHITELISTED', - 'IDR_INCLUDE_WHITELISTED', - ] - non_whitelisted_ids = [ - 'IDR_STRUCTURE_NOT_WHITELISTED', - 'IDR_STRUCTURE_IN_TRUE_IF_NOT_WHITELISTED', - 'IDR_STRUCTURE_IN_FALSE_IF_WHITELISTED', - 'IDR_STRUCTURE_IN_FALSE_IF_NOT_WHITELISTED', - 'IDR_INCLUDE_NOT_WHITELISTED', - ] - for output_file in (header, map_cc): - self._verifyWhitelistedOutput( - output_file, - whitelisted_ids, - non_whitelisted_ids, - ) - def testWriteOnlyNew(self): output_dir = tempfile.mkdtemp() builder = build.RcBuilder()
diff --git a/tools/grit/grit/util.py b/tools/grit/grit/util.py index 4a710b7..aac2dd91 100755 --- a/tools/grit/grit/util.py +++ b/tools/grit/grit/util.py
@@ -320,7 +320,7 @@ def ParseGrdForUnittest(body, base_dir=None, predetermined_ids_file=None, - run_gatherers=False, output_all_resource_defines=True): + run_gatherers=False): '''Parse a skeleton .grd file and return it, for use in unit tests. Args: @@ -335,9 +335,7 @@ base_dir = PathFromRoot('.') lines = ['<?xml version="1.0" encoding="UTF-8"?>'] lines.append(('<grit latest_public_release="2" current_release="3" ' - 'source_lang_id="en" base_dir="{}" ' - 'output_all_resource_defines="{}">').format( - base_dir, str(output_all_resource_defines).lower())) + 'source_lang_id="en" base_dir="{}">').format(base_dir)) if '<outputs>' in body: lines.append(body) else:
diff --git a/tools/grit/grit_info.py b/tools/grit/grit_info.py index 07e9b9d..a7f9601 100755 --- a/tools/grit/grit_info.py +++ b/tools/grit/grit_info.py
@@ -119,12 +119,6 @@ parser.add_option("-E", action="append", dest="build_env", default=[]) parser.add_option("-p", action="store", dest="predetermined_ids_file") parser.add_option("-w", action="append", dest="whitelist_files", default=[]) - parser.add_option("--output-all-resource-defines", action="store_true", - dest="output_all_resource_defines", default=True, - help="Unused") - parser.add_option("--no-output-all-resource-defines", action="store_false", - dest="output_all_resource_defines", default=True, - help="Unused") parser.add_option("-f", dest="ids_file", default="") parser.add_option("-t", dest="target_platform", default=None)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b11c2f88..cf1a580 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -14599,6 +14599,7 @@ <int value="1209" label="CRYPTOTOKENPRIVATE_ISAPPIDHASHINENTERPRISECONTEXT"/> <int value="1210" label="CRYPTOTOKENPRIVATE_CANAPPIDGETATTESTATION"/> <int value="1211" label="SYSTEM_DISPLAY_SETMIRRORMODE"/> + <int value="1212" label="TTSENGINE_UPDATEVOICES"/> </enum> <enum name="ExtensionIconState"> @@ -17679,6 +17680,8 @@ <int value="2344" label="ScrollToFragmentFailWithMixed"/> <int value="2345" label="ScrollToFragmentFailWithInvalidEncoding"/> <int value="2346" label="RTCPeerConnectionWithActiveCsp"/> + <int value="2347" label="ImageDecodingAttribute"/> + <int value="2348" label="ImageDecodeAPI"/> </enum> <enum name="FeedbackSource"> @@ -25447,6 +25450,7 @@ <int value="-1490298774" label="enable-captive-portal-bypass-proxy-option"/> <int value="-1488744539" label="QuickUnlockFingerprint:enabled"/> <int value="-1487243228" label="NewUsbBackend:disabled"/> + <int value="-1486198877" label="VrIconInDaydreamHome:disabled"/> <int value="-1482730792" label="stop-in-background:enabled"/> <int value="-1482685863" label="enable-request-tablet-site"/> <int value="-1480926949" label="MaterialDesignBookmarks:enabled"/> @@ -26387,6 +26391,7 @@ <int value="1005684777" label="PictureInPicture:disabled"/> <int value="1007444341" label="enable-prefixed-encrypted-media"/> <int value="1015895665" label="drop-sync-credential:enabled"/> + <int value="1017364362" label="VrIconInDaydreamHome:enabled"/> <int value="1018998019" label="memlog"/> <int value="1019623058" label="ash-enable-shelf-model-synchronization"/> <int value="1019857902" @@ -46183,6 +46188,11 @@ <int value="1" label="GpuFence"/> </enum> +<enum name="XRRuntimeAvailable"> + <int value="0" label="None"/> + <int value="1" label="OpenVR"/> +</enum> + <enum name="YoungGenerationHandling"> <int value="0" label="Regular Scavenge"/> <int value="1" label="Scavenge using fast promotion mode"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 7ed52d58d..b07ce83 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -46455,6 +46455,23 @@ </summary> </histogram> +<histogram name="Net.QuicSession.ProbingRetryCountUntilSuccess" units="retries"> + <owner>zhongyi@chromium.org</owner> + <summary> + Number of retries to send connectivity probing packet on new path until + success. + </summary> +</histogram> + +<histogram name="Net.QuicSession.ProbingTimeInMillisecondsUntilSuccess" + units="ms"> + <owner>zhongyi@chromium.org</owner> + <summary> + The wait time to receive a matched probing response to mark connectivity + probing as successful. + </summary> +</histogram> + <histogram name="Net.QuicSession.PublicResetAddressMismatch" enum="QuicAddressMismatch"> <owner>wtc@chromium.org</owner> @@ -101340,6 +101357,13 @@ </summary> </histogram> +<histogram name="XR.RuntimeAvailable" enum="XRRuntimeAvailable"> + <owner>billorr@chromium.org</owner> + <summary> + Indicates which VR APIs are installed. Recorded shortly after startup. + </summary> +</histogram> + <histogram name="XR.WebXR.RenderPath.Used" enum="XRRenderPath"> <owner>klausw@chromium.org</owner> <summary>
diff --git a/tools/perf/contrib/oop_raster/oop_raster.py b/tools/perf/contrib/oop_raster/oop_raster.py index 161b08bf..6ae3ed28 100644 --- a/tools/perf/contrib/oop_raster/oop_raster.py +++ b/tools/perf/contrib/oop_raster/oop_raster.py
@@ -34,6 +34,7 @@ raster.""" tag = 'oop_rasterization' page_set = page_sets.KeyMobileSitesSmoothPageSet + options = {'story_tag_filter': 'fastpath'} def SetExtraBrowserOptions(self, options): super(ThreadTimesOopRasterKeyMobile, self).SetExtraBrowserOptions(options)
diff --git a/ui/app_list/app_list_view_delegate.h b/ui/app_list/app_list_view_delegate.h index 2aadc79..9c87b1b 100644 --- a/ui/app_list/app_list_view_delegate.h +++ b/ui/app_list/app_list_view_delegate.h
@@ -63,6 +63,9 @@ // Invoked when the app list UI is created. virtual void ViewInitialized() = 0; + // Invoked when the app list is shown. + virtual void ViewShown() = 0; + // Invoked to dismiss app list. This may leave the view open but hidden from // the user. virtual void Dismiss() = 0;
diff --git a/ui/app_list/presenter/app_list_presenter_impl.cc b/ui/app_list/presenter/app_list_presenter_impl.cc index bb575c4..3f7ea0e 100644 --- a/ui/app_list/presenter/app_list_presenter_impl.cc +++ b/ui/app_list/presenter/app_list_presenter_impl.cc
@@ -4,8 +4,8 @@ #include "ui/app_list/presenter/app_list_presenter_impl.h" -#include "ash/app_list/model/app_list_model.h" -#include "base/metrics/histogram_functions.h" +#include <utility> + #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "ui/app_list/app_list_constants.h" @@ -95,13 +95,7 @@ SetView(view); } presenter_delegate_->OnShown(display_id); - - base::RecordAction(base::UserMetricsAction("Launcher_Show")); - base::UmaHistogramSparse("Apps.AppListBadgedAppsCount", - presenter_delegate_->GetViewDelegate() - ->GetModel() - ->top_level_item_list() - ->BadgedItemCount()); + presenter_delegate_->GetViewDelegate()->ViewShown(); } void AppListPresenterImpl::Dismiss() {
diff --git a/ui/app_list/test/app_list_test_view_delegate.h b/ui/app_list/test/app_list_test_view_delegate.h index d62a1cb9..1b1b745 100644 --- a/ui/app_list/test/app_list_test_view_delegate.h +++ b/ui/app_list/test/app_list_test_view_delegate.h
@@ -53,6 +53,7 @@ int action_index, int event_flags) override {} void ViewInitialized() override {} + void ViewShown() override {} void Dismiss() override; void ViewClosing() override {} views::View* CreateStartPageWebView(const gfx::Size& size) override;
diff --git a/ui/base/l10n/l10n_util_win_unittest.cc b/ui/base/l10n/l10n_util_win_unittest.cc index 29ab718..3dfa853 100644 --- a/ui/base/l10n/l10n_util_win_unittest.cc +++ b/ui/base/l10n/l10n_util_win_unittest.cc
@@ -7,7 +7,7 @@ #include <windows.h> #include "base/command_line.h" -#include "base/win/win_util.h" +#include "base/win/win_client_metrics.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "ui/display/display.h"
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 2b7b961..1c807d5 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -25,4 +25,8 @@ #endif }; +// Enables the touchable chrome. +const base::Feature kTouchableChrome = {"TouchableChrome", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 191fc9ef..9df1cb92 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -17,6 +17,8 @@ UI_BASE_EXPORT extern const base::Feature kSecondaryUiMd; +UI_BASE_EXPORT extern const base::Feature kTouchableChrome; + } // namespace features #endif // UI_BASE_UI_BASE_FEATURES_H_
diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc index 0f8295d8..e6061dc 100644 --- a/ui/compositor/test/in_process_context_provider.cc +++ b/ui/compositor/test/in_process_context_provider.cc
@@ -187,6 +187,8 @@ } base::Lock* InProcessContextProvider::GetLock() { + if (!support_locking_) + return nullptr; return &context_lock_; }
diff --git a/ui/gfx/platform_font_win.cc b/ui/gfx/platform_font_win.cc index 759caf4..187ffbd 100644 --- a/ui/gfx/platform_font_win.cc +++ b/ui/gfx/platform_font_win.cc
@@ -24,7 +24,7 @@ #include "base/win/scoped_gdi_object.h" #include "base/win/scoped_hdc.h" #include "base/win/scoped_select_object.h" -#include "base/win/win_util.h" +#include "base/win/win_client_metrics.h" #include "third_party/skia/include/core/SkFontLCDConfig.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkTypeface.h"
diff --git a/ui/gfx/win/rendering_window_manager.cc b/ui/gfx/win/rendering_window_manager.cc index 4f2cbfb7..5c7261f 100644 --- a/ui/gfx/win/rendering_window_manager.cc +++ b/ui/gfx/win/rendering_window_manager.cc
@@ -22,6 +22,12 @@ info_.emplace(parent, EmeddingInfo()); } +void SetParentAndMoveToBottom(HWND child, HWND parent) { + ::SetParent(child, parent); + // Move D3D window behind Chrome's window to avoid losing some messages. + ::SetWindowPos(child, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); +} + bool RenderingWindowManager::RegisterChild(HWND parent, HWND child) { if (!child) return false; @@ -44,7 +50,7 @@ if (info.call_set_parent) { base::PostTaskWithTraits( FROM_HERE, {base::TaskPriority::USER_BLOCKING}, - base::BindOnce(base::IgnoreResult(&::SetParent), child, parent)); + base::BindOnce(&SetParentAndMoveToBottom, child, parent)); } return true; @@ -64,14 +70,14 @@ DCHECK(!info.call_set_parent); info.call_set_parent = true; - // Call ::SetParent() once RegisterChild() is called. + // Call SetParentAndMoveToBottom() once RegisterChild() is called. if (!info.child) return; child = info.child; } - ::SetParent(child, parent); + SetParentAndMoveToBottom(child, parent); } void RenderingWindowManager::UnregisterParent(HWND parent) {
diff --git a/ui/views/controls/menu/menu_config_win.cc b/ui/views/controls/menu/menu_config_win.cc index 34d29d7..6048ee0 100644 --- a/ui/views/controls/menu/menu_config_win.cc +++ b/ui/views/controls/menu/menu_config_win.cc
@@ -10,7 +10,7 @@ #include "base/logging.h" #include "base/win/scoped_gdi_object.h" -#include "base/win/win_util.h" +#include "base/win/win_client_metrics.h" #include "ui/base/l10n/l10n_util_win.h" #include "ui/gfx/color_utils.h" #include "ui/native_theme/native_theme_win.h"
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index 8797bf8..1e5991d 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc
@@ -57,7 +57,7 @@ #if defined(OS_WIN) #include "base/win/scoped_gdi_object.h" -#include "base/win/win_util.h" +#include "base/win/win_client_metrics.h" #include "ui/base/l10n/l10n_util_win.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h" #endif