Update from https://crrev.com/315085
This includes the switch to libc++ on Android.
Other fixes:
*) Add (dumb) impl of OrderingBarrier() to command buffer
*) "base/debug/trace_event.h" -> "base/trace_event/trace_event.h"
*) Added a few <cmath> includes to sky
Review URL: https://codereview.chromium.org/903273002
diff --git a/DEPS b/DEPS
index 97a3afe..2ac908e 100644
--- a/DEPS
+++ b/DEPS
@@ -21,19 +21,19 @@
'chromium_git': 'https://chromium.googlesource.com',
'dart_svn': 'https://dart.googlecode.com',
'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
- 'skia_revision': 'fef4c32bdf02f1bf3cde722cd48c4ac4cd137ab6',
+ 'skia_revision': '02c8fd0ad5e5279004dd49ec49fbae00f8522ec0',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Skia
# and V8 without interference from each other.
- 'v8_revision': '224d14897d9b7df09e08a94e4cbc13feb339346d',
+ 'v8_revision': '0aa5f75929fa3b383ec749555e045e47199ba6d5',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling ANGLE
# and whatever else without interference from each other.
- 'angle_revision': 'bc393df9cd8ae893da686533644da29a8c4911ae',
+ 'angle_revision': '592ab9dd91e653f5c2d4f7395267046d229e20c1',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling build tools
# and whatever else without interference from each other.
- 'buildtools_revision': '451dcd05a5b34936f5be67b2472cd63aaa508401',
+ 'buildtools_revision': 'da0df3fdac6036e862addb1155a2d6c11b6c18d5',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Dart
# and whatever else without interference from each other.
@@ -41,11 +41,11 @@
# 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': 'b3a788e5e37955620b26be5b6e3048d37b605e00',
+ 'pdfium_revision': '7061d1af45752617fafa85e2242dc5b2844650b5',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling BoringSSL
# and whatever else without interference from each other.
- 'boringssl_revision': 'be629e0e920ae32cca691f5e45410ff00db1a849',
+ 'boringssl_revision': '8f5e2ebcee628ef02add9b21955402b0c6256624',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling lss
# and whatever else without interference from each other.
@@ -159,7 +159,7 @@
Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
'src/third_party/android_tools':
- Var('chromium_git') + '/android_tools.git' + '@' + 'aaeda3d69df4b4352e3cac7c16bea7f16bd1ec12',
+ Var('chromium_git') + '/android_tools.git' + '@' + 'f6e2370dff438125897bb3b3800de1ad7aa62c27',
'src/third_party/appurify-python/src':
Var('chromium_git') + '/external/github.com/appurify/appurify-python.git' + '@' + 'ee7abd5c5ae3106f72b2a0b9d2cb55094688e867',
diff --git a/base/BUILD.gn b/base/BUILD.gn
index c1df2ec..44e656c 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -171,11 +171,6 @@
"debug/stack_trace_win.cc",
"debug/task_annotator.cc",
"debug/task_annotator.h",
- "debug/trace_event.h",
- "debug/trace_event_argument.h",
- "debug/trace_event_impl.h",
- "debug/trace_event_synthetic_delay.h",
- "debug/trace_event_win.h",
"deferred_sequenced_task_runner.cc",
"deferred_sequenced_task_runner.h",
"environment.cc",
@@ -347,7 +342,6 @@
"memory/ref_counted_delete_on_message_loop.h",
"memory/ref_counted_memory.cc",
"memory/ref_counted_memory.h",
- "memory/scoped_open_process.h",
"memory/scoped_policy.h",
"memory/scoped_ptr.h",
"memory/scoped_vector.h",
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index 602358b..2168c21 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -175,18 +175,12 @@
String apkFilePath = null;
boolean useMapExecSupportFallback = false;
- // If the Android build version pre-dates KitKat and the device
- // manufacturer is Samsung, skip the check for mmap exec support and
- // return false. This avoids triggering a warning on these devices.
- // The version check is included because these devices do not show
- // the warning on later OS builds.
+ // If manufacturer is Samsung then skip the mmap exec check.
//
// For more, see:
// https://code.google.com/p/chromium/issues/detail?id=448084
final String manufacturer = android.os.Build.MANUFACTURER;
- final int version = android.os.Build.VERSION.SDK_INT;
if (manufacturer != null
- && version < android.os.Build.VERSION_CODES.KITKAT
&& manufacturer.toLowerCase(Locale.ENGLISH).contains("samsung")) {
Log.w(TAG, "Suppressed load from APK support check on this device");
sProbeMapApkWithExecPermission = false;
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc
index a157354..4bebec7 100644
--- a/base/android/jni_array.cc
+++ b/base/android/jni_array.cc
@@ -7,6 +7,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
+#include "base/stl_util.h"
namespace base {
namespace android {
@@ -53,7 +54,7 @@
ScopedJavaLocalRef<jintArray> ToJavaIntArray(
JNIEnv* env, const std::vector<int>& ints) {
- return ToJavaIntArray(env, ints.begin(), ints.size());
+ return ToJavaIntArray(env, vector_as_array(&ints), ints.size());
}
ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
@@ -72,7 +73,7 @@
// Returns a new Java long array converted from the given int64 array.
BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
JNIEnv* env, const std::vector<int64>& longs) {
- return ToJavaLongArray(env, longs.begin(), longs.size());
+ return ToJavaLongArray(env, vector_as_array(&longs), longs.size());
}
ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
diff --git a/base/android/scoped_java_ref_unittest.cc b/base/android/scoped_java_ref_unittest.cc
index 36f253c..3f4419a 100644
--- a/base/android/scoped_java_ref_unittest.cc
+++ b/base/android/scoped_java_ref_unittest.cc
@@ -40,7 +40,7 @@
class ScopedJavaRefTest : public testing::Test {
protected:
- virtual void SetUp() {
+ void SetUp() override {
g_local_refs = 0;
g_global_refs = 0;
JNIEnv* env = AttachCurrentThread();
@@ -55,7 +55,7 @@
hooked_functions.DeleteLocalRef = &DeleteLocalRef;
}
- virtual void TearDown() {
+ void TearDown() override {
JNIEnv* env = AttachCurrentThread();
env->functions = g_previous_functions;
}
diff --git a/base/android/trace_event_binding.cc b/base/android/trace_event_binding.cc
index 94eb214..b8ce6d9 100644
--- a/base/android/trace_event_binding.cc
+++ b/base/android/trace_event_binding.cc
@@ -57,11 +57,11 @@
class TraceEnabledObserver : public debug::TraceLog::EnabledStateObserver {
public:
- virtual void OnTraceLogEnabled() override {
+ void OnTraceLogEnabled() override {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::Java_TraceEvent_setEnabled(env, true);
}
- virtual void OnTraceLogDisabled() override {
+ void OnTraceLogDisabled() override {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::Java_TraceEvent_setEnabled(env, false);
}
diff --git a/base/base.gypi b/base/base.gypi
index d4dd4dc..6dd6fcf 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -173,11 +173,6 @@
'debug/stack_trace_win.cc',
'debug/task_annotator.cc',
'debug/task_annotator.h',
- 'debug/trace_event.h',
- 'debug/trace_event_argument.h',
- 'debug/trace_event_impl.h',
- 'debug/trace_event_synthetic_delay.h',
- 'debug/trace_event_win.h',
'deferred_sequenced_task_runner.cc',
'deferred_sequenced_task_runner.h',
'environment.cc',
@@ -353,7 +348,6 @@
'memory/ref_counted_delete_on_message_loop.h',
'memory/ref_counted_memory.cc',
'memory/ref_counted_memory.h',
- 'memory/scoped_open_process.h',
'memory/scoped_policy.h',
'memory/scoped_ptr.h',
'memory/scoped_vector.h',
diff --git a/base/base.isolate b/base/base.isolate
index 021c01c..cb85965 100644
--- a/base/base.isolate
+++ b/base/base.isolate
@@ -9,13 +9,20 @@
'../third_party/icu/icu.isolate',
],
'conditions': [
- ['OS=="linux" and asan==1 and chromeos==0', {
+ ['use_custom_libcxx==1', {
'variables': {
'files': [
'<(PRODUCT_DIR)/lib/libc++.so',
],
},
}],
+ ['use_instrumented_libraries==1', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/instrumented_libraries/',
+ ],
+ },
+ }],
['OS=="mac" and asan==1', {
'variables': {
'files': [
@@ -30,7 +37,7 @@
],
},
}],
- ['OS=="linux" and asan==1', {
+ ['OS=="linux" and (asan==1 or lsan==1 or msan==1 or tsan==1)', {
'variables': {
'files': [
# For llvm-symbolizer.
@@ -38,7 +45,7 @@
],
},
}],
- ['asan==1', {
+ ['asan==1 or lsan==1 or msan==1 or tsan==1', {
'variables': {
'files': [
'../tools/valgrind/asan/',
@@ -53,27 +60,43 @@
],
},
}],
+ # Copy the VS runtime DLLs into the isolate so that they
+ # don't have to be preinstalled on the target machine.
+ ['OS=="win" and component=="shared_library" and CONFIGURATION_NAME=="Debug"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/x64/msvcp120d.dll',
+ '<(PRODUCT_DIR)/x64/msvcr120d.dll',
+ ],
+ },
+ }],
+ ['OS=="win" and component=="shared_library" and CONFIGURATION_NAME=="Release"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/x64/msvcp120.dll',
+ '<(PRODUCT_DIR)/x64/msvcr120.dll',
+ ],
+ },
+ }],
['OS=="win" and component=="shared_library" and (CONFIGURATION_NAME=="Debug" or CONFIGURATION_NAME=="Debug_x64")', {
'variables': {
'files': [
- # Copy the VS runtime DLLs into the isolate so that they
- # don't have to be preinstalled on the target machine.
'<(PRODUCT_DIR)/msvcp120d.dll',
'<(PRODUCT_DIR)/msvcr120d.dll',
- '<(PRODUCT_DIR)/x64/msvcp120d.dll',
- '<(PRODUCT_DIR)/x64/msvcr120d.dll',
],
},
}],
['OS=="win" and component=="shared_library" and (CONFIGURATION_NAME=="Release" or CONFIGURATION_NAME=="Release_x64")', {
'variables': {
'files': [
- # Copy the VS runtime DLLs into the isolate so that they
- # don't have to be preinstalled on the target machine.
'<(PRODUCT_DIR)/msvcp120.dll',
'<(PRODUCT_DIR)/msvcr120.dll',
],
},
}],
+ # Workaround for https://code.google.com/p/swarming/issues/detail?id=211
+ ['asan==0 or lsan==0 or msan==0 or tsan==0', {
+ 'variables': {},
+ }],
],
}
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate
index f561d20..0822b24 100644
--- a/base/base_unittests.isolate
+++ b/base/base_unittests.isolate
@@ -20,6 +20,8 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
],
'files': [
'../testing/xvfb.py',
@@ -51,6 +53,15 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
+ ],
+ },
+ }],
+ ['OS=="mac" and asan==1', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/base_unittests.dSYM/',
],
},
}],
diff --git a/base/bind.h b/base/bind.h
index 7874656..51be10d 100644
--- a/base/bind.h
+++ b/base/bind.h
@@ -52,13 +52,14 @@
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
- void()>::UnboundRunType>
+ internal::TypeList<>>::UnboundRunType>
Bind(Functor functor) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
- typedef internal::BindState<RunnableType, RunType, void()> BindState;
+ typedef internal::BindState<RunnableType, RunType,
+ internal::TypeList<>> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor)));
@@ -69,7 +70,8 @@
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
- void(typename internal::CallbackParamTraits<Args>::StorageType...)>
+ internal::TypeList<
+ typename internal::CallbackParamTraits<Args>::StorageType...>>
::UnboundRunType>
Bind(Functor functor, const Args&... args) {
// Typedefs for how to store and run the functor.
@@ -101,8 +103,10 @@
!internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value,
"a_parameter_is_refcounted_type_and_needs_scoped_refptr");
- typedef internal::BindState<RunnableType, RunType,
- void(typename internal::CallbackParamTraits<Args>::StorageType...)>
+ typedef internal::BindState<
+ RunnableType, RunType,
+ internal::TypeList<
+ typename internal::CallbackParamTraits<Args>::StorageType...>>
BindState;
return Callback<typename BindState::UnboundRunType>(
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
index f3efc31..f8e89bd 100644
--- a/base/bind_helpers.h
+++ b/base/bind_helpers.h
@@ -435,45 +435,46 @@
// Utility for handling different refcounting semantics in the Bind()
// function.
-template <bool is_method, typename T>
-struct MaybeRefcount;
+template <bool is_method, typename... T>
+struct MaybeScopedRefPtr;
-template <typename T>
-struct MaybeRefcount<false, T> {
- static void AddRef(const T&) {}
- static void Release(const T&) {}
+template <bool is_method>
+struct MaybeScopedRefPtr<is_method> {
+ MaybeScopedRefPtr() {}
};
-template <typename T, size_t n>
-struct MaybeRefcount<false, T[n]> {
- static void AddRef(const T*) {}
- static void Release(const T*) {}
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<false, T, Rest...> {
+ MaybeScopedRefPtr(const T&, const Rest&...) {}
};
-template <typename T>
-struct MaybeRefcount<true, T> {
- static void AddRef(const T&) {}
- static void Release(const T&) {}
+template <typename T, size_t n, typename... Rest>
+struct MaybeScopedRefPtr<false, T[n], Rest...> {
+ MaybeScopedRefPtr(const T*, const Rest&...) {}
};
-template <typename T>
-struct MaybeRefcount<true, T*> {
- static void AddRef(T* o) { o->AddRef(); }
- static void Release(T* o) { o->Release(); }
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<true, T, Rest...> {
+ MaybeScopedRefPtr(const T& o, const Rest&...) {}
+};
+
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<true, T*, Rest...> {
+ MaybeScopedRefPtr(T* o, const Rest&...) : ref_(o) {}
+ scoped_refptr<T> ref_;
};
// No need to additionally AddRef() and Release() since we are storing a
// scoped_refptr<> inside the storage object already.
-template <typename T>
-struct MaybeRefcount<true, scoped_refptr<T> > {
- static void AddRef(const scoped_refptr<T>& o) {}
- static void Release(const scoped_refptr<T>& o) {}
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<true, scoped_refptr<T>, Rest...> {
+ MaybeScopedRefPtr(const scoped_refptr<T>&, const Rest&...) {}
};
-template <typename T>
-struct MaybeRefcount<true, const T*> {
- static void AddRef(const T* o) { o->AddRef(); }
- static void Release(const T* o) { o->Release(); }
+template <typename T, typename... Rest>
+struct MaybeScopedRefPtr<true, const T*, Rest...> {
+ MaybeScopedRefPtr(const T* o, const Rest&...) : ref_(o) {}
+ scoped_refptr<const T> ref_;
};
// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
@@ -481,15 +482,89 @@
// InvokeHelper that will no-op itself in the event the WeakPtr<> for
// the target object is invalidated.
//
-// P1 should be the type of the object that will be received of the method.
-template <bool IsMethod, typename P1>
+// The first argument should be the type of the object that will be received by
+// the method.
+template <bool IsMethod, typename... Args>
struct IsWeakMethod : public false_type {};
-template <typename T>
-struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
+template <typename T, typename... Args>
+struct IsWeakMethod<true, WeakPtr<T>, Args...> : public true_type {};
-template <typename T>
-struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {};
+template <typename T, typename... Args>
+struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T>>, Args...>
+ : public true_type {};
+
+
+// Packs a list of types to hold them in a single type.
+template <typename... Types>
+struct TypeList {};
+
+// Used for DropTypeListItem implementation.
+template <size_t n, typename List>
+struct DropTypeListItemImpl;
+
+// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
+template <size_t n, typename T, typename... List>
+struct DropTypeListItemImpl<n, TypeList<T, List...>>
+ : DropTypeListItemImpl<n - 1, TypeList<List...>> {};
+
+template <typename T, typename... List>
+struct DropTypeListItemImpl<0, TypeList<T, List...>> {
+ typedef TypeList<T, List...> Type;
+};
+
+template <>
+struct DropTypeListItemImpl<0, TypeList<>> {
+ typedef TypeList<> Type;
+};
+
+// A type-level function that drops |n| list item from given TypeList.
+template <size_t n, typename List>
+using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
+
+// Used for ConcatTypeLists implementation.
+template <typename List1, typename List2>
+struct ConcatTypeListsImpl;
+
+template <typename... Types1, typename... Types2>
+struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
+ typedef TypeList<Types1..., Types2...> Type;
+};
+
+// A type-level function that concats two TypeLists.
+template <typename List1, typename List2>
+using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
+
+template <size_t n, typename List>
+struct NthTypeImpl;
+
+template <size_t n, typename T, typename... Types>
+struct NthTypeImpl<n, TypeList<T, Types...>>
+ : NthTypeImpl<n - 1, TypeList<Types...>> {
+};
+
+template <typename T, typename... Types>
+struct NthTypeImpl<0, TypeList<T, Types...>> {
+ typedef T Type;
+};
+
+// A type-level function that extracts |n|th type from a TypeList.
+template <size_t n, typename List>
+using NthType = typename NthTypeImpl<n, List>::Type;
+
+// Used for MakeFunctionType implementation.
+template <typename R, typename ArgList>
+struct MakeFunctionTypeImpl;
+
+template <typename R, typename... Args>
+struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
+ typedef R(Type)(Args...);
+};
+
+// A type-level function that constructs a function type that has |R| as its
+// return type and has TypeLists items as its arguments.
+template <typename R, typename ArgList>
+using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
} // namespace internal
diff --git a/base/bind_internal.h b/base/bind_internal.h
index b568c16..5fc1459 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -1,8 +1,3 @@
-// This file was GENERATED by command:
-// pump.py bind_internal.h.pump
-// DO NOT EDIT BY HAND!!!
-
-
// Copyright (c) 2011 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.
@@ -15,6 +10,7 @@
#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
+#include "base/tuple.h"
#include "build/build_config.h"
#if defined(OS_WIN)
@@ -51,10 +47,6 @@
// Types:
// RunnableAdapter<> -- Wraps the various "function" pointer types into an
// object that adheres to the Runnable interface.
-// FunctionTraits<> -- Type traits that unwrap a function signature into a
-// a set of easier to use typedefs. Used mainly for
-// compile time asserts.
-// There are |ARITY| FunctionTraits types.
// ForceVoidReturn<> -- Helper class for translating function signatures to
// equivalent forms with a "void" return type.
// FunctorTraits<> -- Type traits used determine the correct RunType and
@@ -64,12 +56,11 @@
// type class that represents the underlying Functor.
// There are |O(1)| MakeRunnable types.
// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
-// Handle the differing syntaxes needed for WeakPtr<> support,
-// and for ignoring return values. This is separate from
-// Invoker to avoid creating multiple version of Invoker<>
-// which grows at O(n^2) with the arity.
+// Handle the differing syntaxes needed for WeakPtr<>
+// support, and for ignoring return values. This is separate
+// from Invoker to avoid creating multiple version of
+// Invoker<>.
// Invoker<> -- Unwraps the curried parameters and executes the Runnable.
-// There are |(ARITY^2 + ARITY)/2| Invoketypes.
// BindState<> -- Stores the curried parameters, and is the main entry point
// into the Bind() system, doing most of the type resolution.
// There are ARITY BindState types.
@@ -209,84 +200,6 @@
R (T::*method_)(Args...) const;
};
-// TODO(tzik): Remove FunctionTraits after we finish removing bind.pump.
-// FunctionTraits<>
-//
-// Breaks a function signature apart into typedefs for easier introspection.
-template <typename Sig>
-struct FunctionTraits;
-
-template <typename R>
-struct FunctionTraits<R()> {
- typedef R ReturnType;
-};
-
-template <typename R, typename A1>
-struct FunctionTraits<R(A1)> {
- typedef R ReturnType;
- typedef A1 A1Type;
-};
-
-template <typename R, typename A1, typename A2>
-struct FunctionTraits<R(A1, A2)> {
- typedef R ReturnType;
- typedef A1 A1Type;
- typedef A2 A2Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-struct FunctionTraits<R(A1, A2, A3)> {
- typedef R ReturnType;
- typedef A1 A1Type;
- typedef A2 A2Type;
- typedef A3 A3Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-struct FunctionTraits<R(A1, A2, A3, A4)> {
- typedef R ReturnType;
- typedef A1 A1Type;
- typedef A2 A2Type;
- typedef A3 A3Type;
- typedef A4 A4Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5>
-struct FunctionTraits<R(A1, A2, A3, A4, A5)> {
- typedef R ReturnType;
- typedef A1 A1Type;
- typedef A2 A2Type;
- typedef A3 A3Type;
- typedef A4 A4Type;
- typedef A5 A5Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6>
-struct FunctionTraits<R(A1, A2, A3, A4, A5, A6)> {
- typedef R ReturnType;
- typedef A1 A1Type;
- typedef A2 A2Type;
- typedef A3 A3Type;
- typedef A4 A4Type;
- typedef A5 A5Type;
- typedef A6 A6Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7>
-struct FunctionTraits<R(A1, A2, A3, A4, A5, A6, A7)> {
- typedef R ReturnType;
- typedef A1 A1Type;
- typedef A2 A2Type;
- typedef A3 A3Type;
- typedef A4 A4Type;
- typedef A5 A5Type;
- typedef A6 A6Type;
- typedef A7 A7Type;
-};
-
// ForceVoidReturn<>
//
@@ -310,14 +223,14 @@
};
template <typename T>
-struct FunctorTraits<IgnoreResultHelper<T> > {
+struct FunctorTraits<IgnoreResultHelper<T>> {
typedef typename FunctorTraits<T>::RunnableType RunnableType;
typedef typename ForceVoidReturn<
typename RunnableType::RunType>::RunType RunType;
};
template <typename T>
-struct FunctorTraits<Callback<T> > {
+struct FunctorTraits<Callback<T>> {
typedef Callback<T> RunnableType;
typedef typename Callback<T>::RunType RunType;
};
@@ -339,7 +252,7 @@
}
template <typename T>
-const typename FunctorTraits<Callback<T> >::RunnableType&
+const typename FunctorTraits<Callback<T>>::RunnableType&
MakeRunnable(const Callback<T>& t) {
DCHECK(!t.is_null());
return t;
@@ -368,22 +281,21 @@
struct InvokeHelper;
template <typename ReturnType, typename Runnable, typename... Args>
-struct InvokeHelper<false, ReturnType, Runnable,
- void(Args...)> {
+struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> {
static ReturnType MakeItSo(Runnable runnable, Args... args) {
return runnable.Run(CallbackForward(args)...);
}
};
template <typename Runnable, typename... Args>
-struct InvokeHelper<false, void, Runnable, void(Args...)> {
+struct InvokeHelper<false, void, Runnable, TypeList<Args...>> {
static void MakeItSo(Runnable runnable, Args... args) {
runnable.Run(CallbackForward(args)...);
}
};
template <typename Runnable, typename BoundWeakPtr, typename... Args>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, Args...)> {
+struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> {
static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
if (!weak_ptr.get()) {
return;
@@ -408,1419 +320,30 @@
// Invoker<>
//
// See description at the top of the file.
-template <int NumBound, typename Storage, typename RunType>
+template <typename BoundIndices,
+ typename StorageType, typename Unwrappers,
+ typename InvokeHelperType, typename UnboundForwardRunType>
struct Invoker;
-// Arity 0 -> 0.
-template <typename StorageType, typename R>
-struct Invoker<0, StorageType, R()> {
- typedef R(RunType)(BindStateBase*);
-
- typedef R(UnboundRunType)();
-
- static R Run(BindStateBase* base) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void()>
- ::MakeItSo(storage->runnable_);
- }
-};
-
-// Arity 1 -> 1.
-template <typename StorageType, typename R,typename X1>
-struct Invoker<0, StorageType, R(X1)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X1>::ForwardType);
-
- typedef R(UnboundRunType)(X1);
-
+template <size_t... bound_indices,
+ typename StorageType,
+ typename... Unwrappers,
+ typename InvokeHelperType,
+ typename R,
+ typename... UnboundForwardArgs>
+struct Invoker<IndexSequence<bound_indices...>,
+ StorageType, TypeList<Unwrappers...>,
+ InvokeHelperType, R(UnboundForwardArgs...)> {
static R Run(BindStateBase* base,
- typename CallbackParamTraits<X1>::ForwardType x1) {
+ UnboundForwardArgs... unbound_args) {
StorageType* storage = static_cast<StorageType*>(base);
-
// Local references to make debugger stepping easier. If in a debugger,
// you really want to warp ahead and step through the
// InvokeHelper<>::MakeItSo() call below.
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename CallbackParamTraits<X1>::ForwardType x1)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1));
- }
-};
-
-// Arity 1 -> 0.
-template <typename StorageType, typename R,typename X1>
-struct Invoker<1, StorageType, R(X1)> {
- typedef R(RunType)(BindStateBase*);
-
- typedef R(UnboundRunType)();
-
- static R Run(BindStateBase* base) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1));
- }
-};
-
-// Arity 2 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker<0, StorageType, R(X1, X2)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X1>::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType);
-
- typedef R(UnboundRunType)(X1, X2);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2));
- }
-};
-
-// Arity 2 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker<1, StorageType, R(X1, X2)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X2>::ForwardType);
-
- typedef R(UnboundRunType)(X2);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X2>::ForwardType x2) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType x2)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2));
- }
-};
-
-// Arity 2 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2>
-struct Invoker<2, StorageType, R(X1, X2)> {
- typedef R(RunType)(BindStateBase*);
-
- typedef R(UnboundRunType)();
-
- static R Run(BindStateBase* base) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2));
- }
-};
-
-// Arity 3 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3>
-struct Invoker<0, StorageType, R(X1, X2, X3)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X1>::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType);
-
- typedef R(UnboundRunType)(X1, X2, X3);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3));
- }
-};
-
-// Arity 3 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3>
-struct Invoker<1, StorageType, R(X1, X2, X3)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType);
-
- typedef R(UnboundRunType)(X2, X3);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3));
- }
-};
-
-// Arity 3 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3>
-struct Invoker<2, StorageType, R(X1, X2, X3)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X3>::ForwardType);
-
- typedef R(UnboundRunType)(X3);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X3>::ForwardType x3) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType x3)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3));
- }
-};
-
-// Arity 3 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3>
-struct Invoker<3, StorageType, R(X1, X2, X3)> {
- typedef R(RunType)(BindStateBase*);
-
- typedef R(UnboundRunType)();
-
- static R Run(BindStateBase* base) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3));
- }
-};
-
-// Arity 4 -> 4.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X1>::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType);
-
- typedef R(UnboundRunType)(X1, X2, X3, X4);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4));
- }
-};
-
-// Arity 4 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType);
-
- typedef R(UnboundRunType)(X2, X3, X4);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4));
- }
-};
-
-// Arity 4 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType);
-
- typedef R(UnboundRunType)(X3, X4);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4));
- }
-};
-
-// Arity 4 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X4>::ForwardType);
-
- typedef R(UnboundRunType)(X4);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X4>::ForwardType x4) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType x4)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4));
- }
-};
-
-// Arity 4 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4)> {
- typedef R(RunType)(BindStateBase*);
-
- typedef R(UnboundRunType)();
-
- static R Run(BindStateBase* base) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4));
- }
-};
-
-// Arity 5 -> 5.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X1>::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType);
-
- typedef R(UnboundRunType)(X1, X2, X3, X4, X5);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5));
- }
-};
-
-// Arity 5 -> 4.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType);
-
- typedef R(UnboundRunType)(X2, X3, X4, X5);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5));
- }
-};
-
-// Arity 5 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType);
-
- typedef R(UnboundRunType)(X3, X4, X5);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5));
- }
-};
-
-// Arity 5 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType);
-
- typedef R(UnboundRunType)(X4, X5);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5));
- }
-};
-
-// Arity 5 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X5>::ForwardType);
-
- typedef R(UnboundRunType)(X5);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X5>::ForwardType x5) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType x5)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5));
- }
-};
-
-// Arity 5 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5)> {
- typedef R(RunType)(BindStateBase*);
-
- typedef R(UnboundRunType)();
-
- static R Run(BindStateBase* base) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
- typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- typename Bound5UnwrapTraits::ForwardType x5 =
- Bound5UnwrapTraits::Unwrap(storage->p5_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename Bound5UnwrapTraits::ForwardType)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5));
- }
-};
-
-// Arity 6 -> 6.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X1>::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType);
-
- typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6));
- }
-};
-
-// Arity 6 -> 5.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType);
-
- typedef R(UnboundRunType)(X2, X3, X4, X5, X6);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6));
- }
-};
-
-// Arity 6 -> 4.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType);
-
- typedef R(UnboundRunType)(X3, X4, X5, X6);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6));
- }
-};
-
-// Arity 6 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType);
-
- typedef R(UnboundRunType)(X4, X5, X6);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6));
- }
-};
-
-// Arity 6 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType);
-
- typedef R(UnboundRunType)(X5, X6);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6));
- }
-};
-
-// Arity 6 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X6>::ForwardType);
-
- typedef R(UnboundRunType)(X6);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X6>::ForwardType x6) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
- typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- typename Bound5UnwrapTraits::ForwardType x5 =
- Bound5UnwrapTraits::Unwrap(storage->p5_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename Bound5UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType x6)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6));
- }
-};
-
-// Arity 6 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6>
-struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6)> {
- typedef R(RunType)(BindStateBase*);
-
- typedef R(UnboundRunType)();
-
- static R Run(BindStateBase* base) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
- typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
- typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- typename Bound5UnwrapTraits::ForwardType x5 =
- Bound5UnwrapTraits::Unwrap(storage->p5_);
- typename Bound6UnwrapTraits::ForwardType x6 =
- Bound6UnwrapTraits::Unwrap(storage->p6_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename Bound5UnwrapTraits::ForwardType,
- typename Bound6UnwrapTraits::ForwardType)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6));
- }
-};
-
-// Arity 7 -> 7.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X1>::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType,
- typename CallbackParamTraits<X7>::ForwardType);
-
- typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6, X7);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename CallbackParamTraits<X1>::ForwardType x1,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6), CallbackForward(x7));
- }
-};
-
-// Arity 7 -> 6.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X2>::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType,
- typename CallbackParamTraits<X7>::ForwardType);
-
- typedef R(UnboundRunType)(X2, X3, X4, X5, X6, X7);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X2>::ForwardType x2,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6), CallbackForward(x7));
- }
-};
-
-// Arity 7 -> 5.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X3>::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType,
- typename CallbackParamTraits<X7>::ForwardType);
-
- typedef R(UnboundRunType)(X3, X4, X5, X6, X7);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X3>::ForwardType x3,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6), CallbackForward(x7));
- }
-};
-
-// Arity 7 -> 4.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X4>::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType,
- typename CallbackParamTraits<X7>::ForwardType);
-
- typedef R(UnboundRunType)(X4, X5, X6, X7);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X4>::ForwardType x4,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6), CallbackForward(x7));
- }
-};
-
-// Arity 7 -> 3.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X5>::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType,
- typename CallbackParamTraits<X7>::ForwardType);
-
- typedef R(UnboundRunType)(X5, X6, X7);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X5>::ForwardType x5,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6), CallbackForward(x7));
- }
-};
-
-// Arity 7 -> 2.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X6>::ForwardType,
- typename CallbackParamTraits<X7>::ForwardType);
-
- typedef R(UnboundRunType)(X6, X7);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
- typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- typename Bound5UnwrapTraits::ForwardType x5 =
- Bound5UnwrapTraits::Unwrap(storage->p5_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename Bound5UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X6>::ForwardType x6,
- typename CallbackParamTraits<X7>::ForwardType x7)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6), CallbackForward(x7));
- }
-};
-
-// Arity 7 -> 1.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
- typedef R(RunType)(BindStateBase*,
- typename CallbackParamTraits<X7>::ForwardType);
-
- typedef R(UnboundRunType)(X7);
-
- static R Run(BindStateBase* base,
- typename CallbackParamTraits<X7>::ForwardType x7) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
- typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
- typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- typename Bound5UnwrapTraits::ForwardType x5 =
- Bound5UnwrapTraits::Unwrap(storage->p5_);
- typename Bound6UnwrapTraits::ForwardType x6 =
- Bound6UnwrapTraits::Unwrap(storage->p6_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename Bound5UnwrapTraits::ForwardType,
- typename Bound6UnwrapTraits::ForwardType,
- typename CallbackParamTraits<X7>::ForwardType x7)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6), CallbackForward(x7));
- }
-};
-
-// Arity 7 -> 0.
-template <typename StorageType, typename R,typename X1, typename X2,
- typename X3, typename X4, typename X5, typename X6, typename X7>
-struct Invoker<7, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
- typedef R(RunType)(BindStateBase*);
-
- typedef R(UnboundRunType)();
-
- static R Run(BindStateBase* base) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
- typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
- typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
- typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
- typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
- typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
- typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
- typedef typename StorageType::Bound7UnwrapTraits Bound7UnwrapTraits;
-
- typename Bound1UnwrapTraits::ForwardType x1 =
- Bound1UnwrapTraits::Unwrap(storage->p1_);
- typename Bound2UnwrapTraits::ForwardType x2 =
- Bound2UnwrapTraits::Unwrap(storage->p2_);
- typename Bound3UnwrapTraits::ForwardType x3 =
- Bound3UnwrapTraits::Unwrap(storage->p3_);
- typename Bound4UnwrapTraits::ForwardType x4 =
- Bound4UnwrapTraits::Unwrap(storage->p4_);
- typename Bound5UnwrapTraits::ForwardType x5 =
- Bound5UnwrapTraits::Unwrap(storage->p5_);
- typename Bound6UnwrapTraits::ForwardType x6 =
- Bound6UnwrapTraits::Unwrap(storage->p6_);
- typename Bound7UnwrapTraits::ForwardType x7 =
- Bound7UnwrapTraits::Unwrap(storage->p7_);
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(typename Bound1UnwrapTraits::ForwardType,
- typename Bound2UnwrapTraits::ForwardType,
- typename Bound3UnwrapTraits::ForwardType,
- typename Bound4UnwrapTraits::ForwardType,
- typename Bound5UnwrapTraits::ForwardType,
- typename Bound6UnwrapTraits::ForwardType,
- typename Bound7UnwrapTraits::ForwardType)>
- ::MakeItSo(storage->runnable_, CallbackForward(x1),
- CallbackForward(x2), CallbackForward(x3),
- CallbackForward(x4), CallbackForward(x5),
- CallbackForward(x6), CallbackForward(x7));
+ return InvokeHelperType::MakeItSo(
+ storage->runnable_,
+ Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))...,
+ CallbackForward(unbound_args)...);
}
};
@@ -1837,275 +360,52 @@
//
// BoundArgsType contains the storage type for all the bound arguments by
// (ab)using a function type.
-template <typename Runnable, typename RunType, typename BoundArgsType>
+template <typename Runnable, typename RunType, typename BoundArgList>
struct BindState;
-template <typename Runnable, typename RunType>
-struct BindState<Runnable, RunType, void()> : public BindStateBase {
- typedef Runnable RunnableType;
- typedef false_type IsWeakCall;
- typedef Invoker<0, BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
- explicit BindState(const Runnable& runnable)
- : runnable_(runnable) {
- }
+template <typename Runnable,
+ typename R, typename... Args,
+ typename... BoundArgs>
+struct BindState<Runnable, R(Args...), TypeList<BoundArgs...>>
+ : public BindStateBase {
+ private:
+ using StorageType = BindState<Runnable, R(Args...), TypeList<BoundArgs...>>;
+ using RunnableType = Runnable;
+
+ // true_type if Runnable is a method invocation and the first bound argument
+ // is a WeakPtr.
+ using IsWeakCall =
+ IsWeakMethod<HasIsMethodTag<Runnable>::value, BoundArgs...>;
+
+ using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>;
+ using Unwrappers = TypeList<UnwrapTraits<BoundArgs>...>;
+ using UnboundForwardArgs = DropTypeListItem<
+ sizeof...(BoundArgs),
+ TypeList<typename CallbackParamTraits<Args>::ForwardType...>>;
+ using UnboundForwardRunType = MakeFunctionType<R, UnboundForwardArgs>;
+
+ using InvokeHelperArgs = ConcatTypeLists<
+ TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>,
+ UnboundForwardArgs>;
+ using InvokeHelperType =
+ InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>;
+
+ using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>;
+
+ public:
+ using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers,
+ InvokeHelperType, UnboundForwardRunType>;
+ using UnboundRunType = MakeFunctionType<R, UnboundArgs>;
+
+ BindState(const Runnable& runnable, const BoundArgs&... bound_args)
+ : runnable_(runnable), ref_(bound_args...), bound_args_(bound_args...) {}
RunnableType runnable_;
+ MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_;
+ Tuple<BoundArgs...> bound_args_;
private:
- ~BindState() override { }
-
-};
-
-template <typename Runnable, typename RunType, typename P1>
-struct BindState<Runnable, RunType, void(P1)> : public BindStateBase {
- typedef Runnable RunnableType;
- typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
- typedef Invoker<1, BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
-
- // Convenience typedefs for bound argument types.
- typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-
- BindState(const Runnable& runnable, const P1& p1)
- : runnable_(runnable),
- p1_(p1) {
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
- }
-
- RunnableType runnable_;
- P1 p1_;
-
- private:
- ~BindState() override { MaybeRefcount<HasIsMethodTag<Runnable>::value,
- P1>::Release(p1_); }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2>
-struct BindState<Runnable, RunType, void(P1, P2)> : public BindStateBase {
- typedef Runnable RunnableType;
- typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
- typedef Invoker<2, BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
-
- // Convenience typedefs for bound argument types.
- typedef UnwrapTraits<P1> Bound1UnwrapTraits;
- typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-
- BindState(const Runnable& runnable, const P1& p1, const P2& p2)
- : runnable_(runnable),
- p1_(p1),
- p2_(p2) {
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
- }
-
- RunnableType runnable_;
- P1 p1_;
- P2 p2_;
-
- private:
- ~BindState() override { MaybeRefcount<HasIsMethodTag<Runnable>::value,
- P1>::Release(p1_); }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
- typename P3>
-struct BindState<Runnable, RunType, void(P1, P2, P3)> : public BindStateBase {
- typedef Runnable RunnableType;
- typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
- typedef Invoker<3, BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
-
- // Convenience typedefs for bound argument types.
- typedef UnwrapTraits<P1> Bound1UnwrapTraits;
- typedef UnwrapTraits<P2> Bound2UnwrapTraits;
- typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-
- BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3)
- : runnable_(runnable),
- p1_(p1),
- p2_(p2),
- p3_(p3) {
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
- }
-
- RunnableType runnable_;
- P1 p1_;
- P2 p2_;
- P3 p3_;
-
- private:
- ~BindState() override { MaybeRefcount<HasIsMethodTag<Runnable>::value,
- P1>::Release(p1_); }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
- typename P3, typename P4>
-struct BindState<Runnable, RunType, void(P1, P2, P3,
- P4)> : public BindStateBase {
- typedef Runnable RunnableType;
- typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
- typedef Invoker<4, BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
-
- // Convenience typedefs for bound argument types.
- typedef UnwrapTraits<P1> Bound1UnwrapTraits;
- typedef UnwrapTraits<P2> Bound2UnwrapTraits;
- typedef UnwrapTraits<P3> Bound3UnwrapTraits;
- typedef UnwrapTraits<P4> Bound4UnwrapTraits;
-
- BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3,
- const P4& p4)
- : runnable_(runnable),
- p1_(p1),
- p2_(p2),
- p3_(p3),
- p4_(p4) {
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
- }
-
- RunnableType runnable_;
- P1 p1_;
- P2 p2_;
- P3 p3_;
- P4 p4_;
-
- private:
- ~BindState() override { MaybeRefcount<HasIsMethodTag<Runnable>::value,
- P1>::Release(p1_); }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
- typename P3, typename P4, typename P5>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4,
- P5)> : public BindStateBase {
- typedef Runnable RunnableType;
- typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
- typedef Invoker<5, BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
-
- // Convenience typedefs for bound argument types.
- typedef UnwrapTraits<P1> Bound1UnwrapTraits;
- typedef UnwrapTraits<P2> Bound2UnwrapTraits;
- typedef UnwrapTraits<P3> Bound3UnwrapTraits;
- typedef UnwrapTraits<P4> Bound4UnwrapTraits;
- typedef UnwrapTraits<P5> Bound5UnwrapTraits;
-
- BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3,
- const P4& p4, const P5& p5)
- : runnable_(runnable),
- p1_(p1),
- p2_(p2),
- p3_(p3),
- p4_(p4),
- p5_(p5) {
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
- }
-
- RunnableType runnable_;
- P1 p1_;
- P2 p2_;
- P3 p3_;
- P4 p4_;
- P5 p5_;
-
- private:
- ~BindState() override { MaybeRefcount<HasIsMethodTag<Runnable>::value,
- P1>::Release(p1_); }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
- typename P3, typename P4, typename P5, typename P6>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5,
- P6)> : public BindStateBase {
- typedef Runnable RunnableType;
- typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
- typedef Invoker<6, BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
-
- // Convenience typedefs for bound argument types.
- typedef UnwrapTraits<P1> Bound1UnwrapTraits;
- typedef UnwrapTraits<P2> Bound2UnwrapTraits;
- typedef UnwrapTraits<P3> Bound3UnwrapTraits;
- typedef UnwrapTraits<P4> Bound4UnwrapTraits;
- typedef UnwrapTraits<P5> Bound5UnwrapTraits;
- typedef UnwrapTraits<P6> Bound6UnwrapTraits;
-
- BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3,
- const P4& p4, const P5& p5, const P6& p6)
- : runnable_(runnable),
- p1_(p1),
- p2_(p2),
- p3_(p3),
- p4_(p4),
- p5_(p5),
- p6_(p6) {
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
- }
-
- RunnableType runnable_;
- P1 p1_;
- P2 p2_;
- P3 p3_;
- P4 p4_;
- P5 p5_;
- P6 p6_;
-
- private:
- ~BindState() override { MaybeRefcount<HasIsMethodTag<Runnable>::value,
- P1>::Release(p1_); }
-
-};
-
-template <typename Runnable, typename RunType, typename P1, typename P2,
- typename P3, typename P4, typename P5, typename P6, typename P7>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5, P6,
- P7)> : public BindStateBase {
- typedef Runnable RunnableType;
- typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
- typedef Invoker<7, BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
-
- // Convenience typedefs for bound argument types.
- typedef UnwrapTraits<P1> Bound1UnwrapTraits;
- typedef UnwrapTraits<P2> Bound2UnwrapTraits;
- typedef UnwrapTraits<P3> Bound3UnwrapTraits;
- typedef UnwrapTraits<P4> Bound4UnwrapTraits;
- typedef UnwrapTraits<P5> Bound5UnwrapTraits;
- typedef UnwrapTraits<P6> Bound6UnwrapTraits;
- typedef UnwrapTraits<P7> Bound7UnwrapTraits;
-
- BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3,
- const P4& p4, const P5& p5, const P6& p6, const P7& p7)
- : runnable_(runnable),
- p1_(p1),
- p2_(p2),
- p3_(p3),
- p4_(p4),
- p5_(p5),
- p6_(p6),
- p7_(p7) {
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
- }
-
- RunnableType runnable_;
- P1 p1_;
- P2 p2_;
- P3 p3_;
- P4 p4_;
- P5 p5_;
- P6 p6_;
- P7 p7_;
-
- private:
- ~BindState() override { MaybeRefcount<HasIsMethodTag<Runnable>::value,
- P1>::Release(p1_); }
-
+ ~BindState() override {}
};
} // namespace internal
diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump
deleted file mode 100644
index 0ed3ca2..0000000
--- a/base/bind_internal.h.pump
+++ /dev/null
@@ -1,516 +0,0 @@
-$$ This is a pump file for generating file templates. Pump is a python
-$$ script that is part of the Google Test suite of utilities. Description
-$$ can be found here:
-$$
-$$ http://code.google.com/p/googletest/wiki/PumpManual
-$$
-
-$$ See comment for MAX_ARITY in base/bind.h.pump.
-$var MAX_ARITY = 7
-$range ARITY 0..MAX_ARITY
-
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_BIND_INTERNAL_H_
-#define BASE_BIND_INTERNAL_H_
-
-#include "base/bind_helpers.h"
-#include "base/callback_internal.h"
-#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
-#include "base/memory/weak_ptr.h"
-#include "base/template_util.h"
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include "base/bind_internal_win.h"
-#endif
-
-namespace base {
-namespace internal {
-
-// See base/callback.h for user documentation.
-//
-//
-// CONCEPTS:
-// Runnable -- A type (really a type class) that has a single Run() method
-// and a RunType typedef that corresponds to the type of Run().
-// A Runnable can declare that it should treated like a method
-// call by including a typedef named IsMethod. The value of
-// this typedef is NOT inspected, only the existence. When a
-// Runnable declares itself a method, Bind() will enforce special
-// refcounting + WeakPtr handling semantics for the first
-// parameter which is expected to be an object.
-// Functor -- A copyable type representing something that should be called.
-// All function pointers, Callback<>, and Runnables are functors
-// even if the invocation syntax differs.
-// RunType -- A function type (as opposed to function _pointer_ type) for
-// a Run() function. Usually just a convenience typedef.
-// (Bound)ArgsType -- A function type that is being (ab)used to store the
-// types of set of arguments. The "return" type is always
-// void here. We use this hack so that we do not need
-// a new type name for each arity of type. (eg.,
-// BindState1, BindState2). This makes forward
-// declarations and friending much much easier.
-//
-// Types:
-// RunnableAdapter<> -- Wraps the various "function" pointer types into an
-// object that adheres to the Runnable interface.
-// FunctionTraits<> -- Type traits that unwrap a function signature into a
-// a set of easier to use typedefs. Used mainly for
-// compile time asserts.
-// There are |ARITY| FunctionTraits types.
-// ForceVoidReturn<> -- Helper class for translating function signatures to
-// equivalent forms with a "void" return type.
-// FunctorTraits<> -- Type traits used determine the correct RunType and
-// RunnableType for a Functor. This is where function
-// signature adapters are applied.
-// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
-// type class that represents the underlying Functor.
-// There are |O(1)| MakeRunnable types.
-// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
-// Handle the differing syntaxes needed for WeakPtr<> support,
-// and for ignoring return values. This is separate from
-// Invoker to avoid creating multiple version of Invoker<>
-// which grows at O(n^2) with the arity.
-// Invoker<> -- Unwraps the curried parameters and executes the Runnable.
-// There are |(ARITY^2 + ARITY)/2| Invoketypes.
-// BindState<> -- Stores the curried parameters, and is the main entry point
-// into the Bind() system, doing most of the type resolution.
-// There are ARITY BindState types.
-
-// HasNonConstReferenceParam selects true_type when any of the parameters in
-// |Sig| is a non-const reference.
-// Implementation note: This non-specialized case handles zero-arity case only.
-// Non-zero-arity cases should be handled by the specialization below.
-template <typename Sig>
-struct HasNonConstReferenceParam : false_type {};
-
-// Implementation note: Select true_type if the first parameter is a non-const
-// reference. Otherwise, skip the first parameter and check rest of parameters
-// recursively.
-template <typename R, typename T, typename... Args>
-struct HasNonConstReferenceParam<R(T, Args...)>
- : SelectType<is_non_const_reference<T>::value,
- true_type,
- HasNonConstReferenceParam<R(Args...)>>::Type {};
-
-// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
-// pointer to a RefCounted type.
-// Implementation note: This non-specialized case handles zero-arity case only.
-// Non-zero-arity cases should be handled by the specialization below.
-template <typename... Args>
-struct HasRefCountedTypeAsRawPtr : false_type {};
-
-// Implementation note: Select true_type if the first parameter is a raw pointer
-// to a RefCounted type. Otherwise, skip the first parameter and check rest of
-// parameters recursively.
-template <typename T, typename... Args>
-struct HasRefCountedTypeAsRawPtr<T, Args...>
- : SelectType<NeedsScopedRefptrButGetsRawPtr<T>::value,
- true_type,
- HasRefCountedTypeAsRawPtr<Args...>>::Type {};
-
-// BindsArrayToFirstArg selects true_type when |is_method| is true and the first
-// item of |Args| is an array type.
-// Implementation note: This non-specialized case handles !is_method case and
-// zero-arity case only. Other cases should be handled by the specialization
-// below.
-template <bool is_method, typename... Args>
-struct BindsArrayToFirstArg : false_type {};
-
-template <typename T, typename... Args>
-struct BindsArrayToFirstArg<true, T, Args...> : is_array<T> {};
-
-// HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except
-// when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument.
-// Implementation note: This non-specialized case handles !is_method case and
-// zero-arity case only. Other cases should be handled by the specialization
-// below.
-template <bool is_method, typename... Args>
-struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {};
-
-template <typename T, typename... Args>
-struct HasRefCountedParamAsRawPtr<true, T, Args...>
- : HasRefCountedTypeAsRawPtr<Args...> {};
-
-// RunnableAdapter<>
-//
-// The RunnableAdapter<> templates provide a uniform interface for invoking
-// a function pointer, method pointer, or const method pointer. The adapter
-// exposes a Run() method with an appropriate signature. Using this wrapper
-// allows for writing code that supports all three pointer types without
-// undue repetition. Without it, a lot of code would need to be repeated 3
-// times.
-//
-// For method pointers and const method pointers the first argument to Run()
-// is considered to be the received of the method. This is similar to STL's
-// mem_fun().
-//
-// This class also exposes a RunType typedef that is the function type of the
-// Run() function.
-//
-// If and only if the wrapper contains a method or const method pointer, an
-// IsMethod typedef is exposed. The existence of this typedef (NOT the value)
-// marks that the wrapper should be considered a method wrapper.
-
-template <typename Functor>
-class RunnableAdapter;
-
-// Function.
-template <typename R, typename... Args>
-class RunnableAdapter<R(*)(Args...)> {
- public:
- typedef R (RunType)(Args...);
-
- explicit RunnableAdapter(R(*function)(Args...))
- : function_(function) {
- }
-
- R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
- return function_(CallbackForward(args)...);
- }
-
- private:
- R (*function_)(Args...);
-};
-
-// Method.
-template <typename R, typename T, typename... Args>
-class RunnableAdapter<R(T::*)(Args...)> {
- public:
- typedef R (RunType)(T*, Args...);
- typedef true_type IsMethod;
-
- explicit RunnableAdapter(R(T::*method)(Args...))
- : method_(method) {
- }
-
- R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) {
- return (object->*method_)(CallbackForward(args)...);
- }
-
- private:
- R (T::*method_)(Args...);
-};
-
-// Const Method.
-template <typename R, typename T, typename... Args>
-class RunnableAdapter<R(T::*)(Args...) const> {
- public:
- typedef R (RunType)(const T*, Args...);
- typedef true_type IsMethod;
-
- explicit RunnableAdapter(R(T::*method)(Args...) const)
- : method_(method) {
- }
-
- R Run(const T* object,
- typename CallbackParamTraits<Args>::ForwardType... args) {
- return (object->*method_)(CallbackForward(args)...);
- }
-
- private:
- R (T::*method_)(Args...) const;
-};
-
-// TODO(tzik): Remove FunctionTraits after we finish removing bind.pump.
-// FunctionTraits<>
-//
-// Breaks a function signature apart into typedefs for easier introspection.
-template <typename Sig>
-struct FunctionTraits;
-
-$for ARITY [[
-$range ARG 1..ARITY
-
-template <typename R[[]]
-$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
-struct FunctionTraits<R($for ARG , [[A$(ARG)]])> {
- typedef R ReturnType;
-$for ARG [[
-
- typedef A$(ARG) A$(ARG)Type;
-]]
-
-};
-
-]]
-
-
-// ForceVoidReturn<>
-//
-// Set of templates that support forcing the function return type to void.
-template <typename Sig>
-struct ForceVoidReturn;
-
-template <typename R, typename... Args>
-struct ForceVoidReturn<R(Args...)> {
- typedef void(RunType)(Args...);
-};
-
-
-// FunctorTraits<>
-//
-// See description at top of file.
-template <typename T>
-struct FunctorTraits {
- typedef RunnableAdapter<T> RunnableType;
- typedef typename RunnableType::RunType RunType;
-};
-
-template <typename T>
-struct FunctorTraits<IgnoreResultHelper<T> > {
- typedef typename FunctorTraits<T>::RunnableType RunnableType;
- typedef typename ForceVoidReturn<
- typename RunnableType::RunType>::RunType RunType;
-};
-
-template <typename T>
-struct FunctorTraits<Callback<T> > {
- typedef Callback<T> RunnableType;
- typedef typename Callback<T>::RunType RunType;
-};
-
-
-// MakeRunnable<>
-//
-// Converts a passed in functor to a RunnableType using type inference.
-
-template <typename T>
-typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
- return RunnableAdapter<T>(t);
-}
-
-template <typename T>
-typename FunctorTraits<T>::RunnableType
-MakeRunnable(const IgnoreResultHelper<T>& t) {
- return MakeRunnable(t.functor_);
-}
-
-template <typename T>
-const typename FunctorTraits<Callback<T> >::RunnableType&
-MakeRunnable(const Callback<T>& t) {
- DCHECK(!t.is_null());
- return t;
-}
-
-
-// InvokeHelper<>
-//
-// There are 3 logical InvokeHelper<> specializations: normal, void-return,
-// WeakCalls.
-//
-// The normal type just calls the underlying runnable.
-//
-// We need a InvokeHelper to handle void return types in order to support
-// IgnoreResult(). Normally, if the Runnable's RunType had a void return,
-// the template system would just accept "return functor.Run()" ignoring
-// the fact that a void function is being used with return. This piece of
-// sugar breaks though when the Runnable's RunType is not void. Thus, we
-// need a partial specialization to change the syntax to drop the "return"
-// from the invocation call.
-//
-// WeakCalls similarly need special syntax that is applied to the first
-// argument to check if they should no-op themselves.
-template <bool IsWeakCall, typename ReturnType, typename Runnable,
- typename ArgsType>
-struct InvokeHelper;
-
-template <typename ReturnType, typename Runnable, typename... Args>
-struct InvokeHelper<false, ReturnType, Runnable,
- void(Args...)> {
- static ReturnType MakeItSo(Runnable runnable, Args... args) {
- return runnable.Run(CallbackForward(args)...);
- }
-};
-
-template <typename Runnable, typename... Args>
-struct InvokeHelper<false, void, Runnable, void(Args...)> {
- static void MakeItSo(Runnable runnable, Args... args) {
- runnable.Run(CallbackForward(args)...);
- }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename... Args>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, Args...)> {
- static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
- if (!weak_ptr.get()) {
- return;
- }
- runnable.Run(weak_ptr.get(), CallbackForward(args)...);
- }
-};
-
-#if !defined(_MSC_VER)
-
-template <typename ReturnType, typename Runnable, typename ArgsType>
-struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
- // WeakCalls are only supported for functions with a void return type.
- // Otherwise, the function result would be undefined if the the WeakPtr<>
- // is invalidated.
- COMPILE_ASSERT(is_void<ReturnType>::value,
- weak_ptrs_can_only_bind_to_methods_without_return_values);
-};
-
-#endif
-
-// Invoker<>
-//
-// See description at the top of the file.
-template <int NumBound, typename Storage, typename RunType>
-struct Invoker;
-
-$for ARITY [[
-
-$$ Number of bound arguments.
-$range BOUND 0..ARITY
-$for BOUND [[
-
-$var UNBOUND = ARITY - BOUND
-$range ARG 1..ARITY
-$range BOUND_ARG 1..BOUND
-$range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY
-
-// Arity $(ARITY) -> $(UNBOUND).
-template <typename StorageType, typename R[[]]
-$if ARITY > 0 [[,]][[]]
-$for ARG , [[typename X$(ARG)]]>
-struct Invoker<$(BOUND), StorageType, R($for ARG , [[X$(ARG)]])> {
- typedef R(RunType)(BindStateBase*[[]]
-$if UNBOUND != 0 [[, ]]
-$for UNBOUND_ARG , [[typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType]]);
-
- typedef R(UnboundRunType)($for UNBOUND_ARG , [[X$(UNBOUND_ARG)]]);
-
- static R Run(BindStateBase* base[[]]
-$if UNBOUND != 0 [[, ]][[]]
-$for UNBOUND_ARG , [[
-typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)
-]][[]]
-) {
- StorageType* storage = static_cast<StorageType*>(base);
-
- // Local references to make debugger stepping easier. If in a debugger,
- // you really want to warp ahead and step through the
- // InvokeHelper<>::MakeItSo() call below.
-$for BOUND_ARG
-[[
-
- typedef typename StorageType::Bound$(BOUND_ARG)UnwrapTraits Bound$(BOUND_ARG)UnwrapTraits;
-]]
-
-
-$for BOUND_ARG
-[[
-
- typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType x$(BOUND_ARG) =
- Bound$(BOUND_ARG)UnwrapTraits::Unwrap(storage->p$(BOUND_ARG)_);
-]]
-
- return InvokeHelper<StorageType::IsWeakCall::value, R,
- typename StorageType::RunnableType,
- void(
-$for BOUND_ARG , [[
-typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType
-]]
-
-$if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]]
-
-$for UNBOUND_ARG , [[
-typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)
-]]
-)>
- ::MakeItSo(storage->runnable_
-$if ARITY > 0[[, ]] $for ARG , [[CallbackForward(x$(ARG))]]);
- }
-};
-
-]] $$ for BOUND
-]] $$ for ARITY
-
-
-// BindState<>
-//
-// This stores all the state passed into Bind() and is also where most
-// of the template resolution magic occurs.
-//
-// Runnable is the functor we are binding arguments to.
-// RunType is type of the Run() function that the Invoker<> should use.
-// Normally, this is the same as the RunType of the Runnable, but it can
-// be different if an adapter like IgnoreResult() has been used.
-//
-// BoundArgsType contains the storage type for all the bound arguments by
-// (ab)using a function type.
-template <typename Runnable, typename RunType, typename BoundArgsType>
-struct BindState;
-
-$for ARITY [[
-$range ARG 1..ARITY
-
-template <typename Runnable, typename RunType[[]]
-$if ARITY > 0[[, ]] $for ARG , [[typename P$(ARG)]]>
-struct BindState<Runnable, RunType, void($for ARG , [[P$(ARG)]])> : public BindStateBase {
- typedef Runnable RunnableType;
-
-$if ARITY > 0 [[
- typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-]] $else [[
- typedef false_type IsWeakCall;
-]]
-
- typedef Invoker<$(ARITY), BindState, RunType> InvokerType;
- typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-$if ARITY > 0 [[
-
- // Convenience typedefs for bound argument types.
-
-$for ARG [[
- typedef UnwrapTraits<P$(ARG)> Bound$(ARG)UnwrapTraits;
-
-]] $$ for ARG
-
-
-]] $$ if ARITY > 0
-
-$$ The extra [[ ]] is needed to massage spacing. Silly pump.py.
-[[ ]]$if ARITY == 0 [[explicit ]]BindState(const Runnable& runnable
-$if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]])
- : runnable_(runnable)[[]]
-$if ARITY == 0 [[
- {
-
-]] $else [[
-, $for ARG , [[
-
- p$(ARG)_(p$(ARG))
-]] {
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-
-]]
- }
-
- RunnableType runnable_;
-
-$for ARG [[
- P$(ARG) p$(ARG)_;
-
-]]
-
- private:
- ~BindState() override {
-$if ARITY > 0 [[
- MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-]]
- }
-
-};
-
-]] $$ for ARITY
-
-} // namespace internal
-} // namespace base
-
-#endif // BASE_BIND_INTERNAL_H_
diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc
index 33b5f5c..2596386 100644
--- a/base/bind_unittest.nc
+++ b/base/bind_unittest.nc
@@ -190,7 +190,7 @@
weak_ptr_with_non_void_return_type.Run();
}
-#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERENT_TYPES) // [r"fatal error: no viable conversion from 'Callback<typename internal::BindState<typename internal::FunctorTraits<void \(\*\)\(int\)>::RunnableType, typename internal::FunctorTraits<void \(\*\)\(int\)>::RunType, void \(\)>::UnboundRunType>' to 'Callback<void \(\)>'"]
+#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERENT_TYPES) // [r"fatal error: no viable conversion from 'Callback<typename internal::BindState<typename internal::FunctorTraits<void \(\*\)\(int\)>::RunnableType, typename internal::FunctorTraits<void \(\*\)\(int\)>::RunType, internal::TypeList<> >::UnboundRunType>' to 'Callback<void \(\)>'"]
// Bind result cannot be assigned to Callbacks with a mismatching type.
void WontCompile() {
diff --git a/base/chromeos/memory_pressure_observer_chromeos.cc b/base/chromeos/memory_pressure_observer_chromeos.cc
index 8112c76..5691eb8 100644
--- a/base/chromeos/memory_pressure_observer_chromeos.cc
+++ b/base/chromeos/memory_pressure_observer_chromeos.cc
@@ -5,6 +5,7 @@
#include "base/chromeos/memory_pressure_observer_chromeos.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram_macros.h"
#include "base/process/process_metrics.h"
#include "base/time/time.h"
@@ -29,6 +30,16 @@
const int kAggressiveMemoryPressureModerateThresholdPercent = 35;
const int kAggressiveMemoryPressureCriticalThresholdPercent = 70;
+// The possible state for memory pressure level. The values should be in line
+// with values in MemoryPressureListener::MemoryPressureLevel and should be
+// updated if more memory pressure levels are introduced.
+enum MemoryPressureLevelUMA {
+ MEMORY_PRESSURE_LEVEL_NONE = 0,
+ MEMORY_PRESSURE_LEVEL_MODERATE,
+ MEMORY_PRESSURE_LEVEL_CRITICAL,
+ NUM_MEMORY_PRESSURE_LEVELS
+};
+
// Converts a |MemoryPressureThreshold| value into a used memory percentage for
// the moderate pressure event.
int GetModerateMemoryThresholdInPercent(
@@ -92,7 +103,8 @@
void MemoryPressureObserverChromeOS::StartObserving() {
timer_.Start(FROM_HERE,
TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
- Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure,
+ Bind(&MemoryPressureObserverChromeOS::
+ CheckMemoryPressureAndRecordStatistics,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -101,6 +113,28 @@
timer_.Stop();
}
+void MemoryPressureObserverChromeOS::CheckMemoryPressureAndRecordStatistics() {
+ CheckMemoryPressure();
+
+ // Record UMA histogram statistics for the current memory pressure level.
+ MemoryPressureLevelUMA memory_pressure_level_uma(MEMORY_PRESSURE_LEVEL_NONE);
+ switch (current_memory_pressure_level_) {
+ case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+ memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_NONE;
+ break;
+ case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+ memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_MODERATE;
+ break;
+ case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+ memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_CRITICAL;
+ break;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("ChromeOS.MemoryPressureLevel",
+ memory_pressure_level_uma,
+ NUM_MEMORY_PRESSURE_LEVELS);
+}
+
void MemoryPressureObserverChromeOS::CheckMemoryPressure() {
MemoryPressureListener::MemoryPressureLevel old_pressure =
current_memory_pressure_level_;
diff --git a/base/chromeos/memory_pressure_observer_chromeos.h b/base/chromeos/memory_pressure_observer_chromeos.h
index 739b795..9af07d4 100644
--- a/base/chromeos/memory_pressure_observer_chromeos.h
+++ b/base/chromeos/memory_pressure_observer_chromeos.h
@@ -76,6 +76,10 @@
// critical pressure levels.
void CheckMemoryPressure();
+ // The function periodically checks the memory pressure changes and records
+ // the UMA histogram statistics for the current memory pressure level.
+ void CheckMemoryPressureAndRecordStatistics();
+
// Get the memory pressure in percent (virtual for testing).
virtual int GetUsedMemoryInPercent();
diff --git a/base/containers/hash_tables.h b/base/containers/hash_tables.h
index 6bf029e..736e892 100644
--- a/base/containers/hash_tables.h
+++ b/base/containers/hash_tables.h
@@ -45,7 +45,7 @@
#undef __DEPRECATED
#endif
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && defined(USE_STLPORT)
#include <hash_map>
#include <hash_set>
#define BASE_HASH_IMPL_NAMESPACE std
@@ -84,7 +84,7 @@
}
};
-#if !defined(OS_ANDROID)
+#if !defined(USE_STLPORT)
// The GNU C++ library provides identity hash functions for many integral types,
// but not for |long long|. This hash function will truncate if |size_t| is
// narrower than |long long|. This is probably good enough for what we will
@@ -102,7 +102,7 @@
DEFINE_TRIVIAL_HASH(unsigned long long);
#undef DEFINE_TRIVIAL_HASH
-#endif // !defined(OS_ANDROID)
+#endif // !defined(USE_STLPORT)
// Implement string hash functions so that strings of various flavors can
// be used as keys in STL maps and sets. The hash algorithm comes from the
diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h
index 572f285..fb271b6 100644
--- a/base/debug/stack_trace.h
+++ b/base/debug/stack_trace.h
@@ -17,6 +17,7 @@
#if defined(OS_WIN)
struct _EXCEPTION_POINTERS;
+struct _CONTEXT;
#endif
namespace base {
@@ -54,6 +55,7 @@
// Note: this function will throw an import not found (StackWalk64) exception
// on system without dbghelp 5.1.
StackTrace(const _EXCEPTION_POINTERS* exception_pointers);
+ StackTrace(const _CONTEXT* context);
#endif
// Copying and assignment are allowed with the default functions.
@@ -76,6 +78,10 @@
std::string ToString() const;
private:
+#if defined(OS_WIN)
+ void InitTrace(_CONTEXT* context_record);
+#endif
+
// From http://msdn.microsoft.com/en-us/library/bb204633.aspx,
// the sum of FramesToSkip and FramesToCapture must be less than 63,
// so set it to 62. Even if on POSIX it could be a larger value, it usually
diff --git a/base/debug/stack_trace_win.cc b/base/debug/stack_trace_win.cc
index 8df6fc6..27661ed 100644
--- a/base/debug/stack_trace_win.cc
+++ b/base/debug/stack_trace_win.cc
@@ -214,24 +214,35 @@
#endif
StackTrace::StackTrace(const EXCEPTION_POINTERS* exception_pointers) {
- // When walking an exception stack, we need to use StackWalk64().
- count_ = 0;
// StackWalk64() may modify context record passed to it, so we will
// use a copy.
CONTEXT context_record = *exception_pointers->ContextRecord;
+ InitTrace(&context_record);
+}
+
+StackTrace::StackTrace(const CONTEXT* context) {
+ // StackWalk64() may modify context record passed to it, so we will
+ // use a copy.
+ CONTEXT context_record = *context;
+ InitTrace(&context_record);
+}
+
+void StackTrace::InitTrace(CONTEXT* context_record) {
+ // When walking an exception stack, we need to use StackWalk64().
+ count_ = 0;
// Initialize stack walking.
STACKFRAME64 stack_frame;
memset(&stack_frame, 0, sizeof(stack_frame));
#if defined(_WIN64)
int machine_type = IMAGE_FILE_MACHINE_AMD64;
- stack_frame.AddrPC.Offset = context_record.Rip;
- stack_frame.AddrFrame.Offset = context_record.Rbp;
- stack_frame.AddrStack.Offset = context_record.Rsp;
+ stack_frame.AddrPC.Offset = context_record->Rip;
+ stack_frame.AddrFrame.Offset = context_record->Rbp;
+ stack_frame.AddrStack.Offset = context_record->Rsp;
#else
int machine_type = IMAGE_FILE_MACHINE_I386;
- stack_frame.AddrPC.Offset = context_record.Eip;
- stack_frame.AddrFrame.Offset = context_record.Ebp;
- stack_frame.AddrStack.Offset = context_record.Esp;
+ stack_frame.AddrPC.Offset = context_record->Eip;
+ stack_frame.AddrFrame.Offset = context_record->Ebp;
+ stack_frame.AddrStack.Offset = context_record->Esp;
#endif
stack_frame.AddrPC.Mode = AddrModeFlat;
stack_frame.AddrFrame.Mode = AddrModeFlat;
@@ -240,7 +251,7 @@
GetCurrentProcess(),
GetCurrentThread(),
&stack_frame,
- &context_record,
+ context_record,
NULL,
&SymFunctionTableAccess64,
&SymGetModuleBase64,
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
deleted file mode 100644
index 7d97e16..0000000
--- a/base/debug/trace_event.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_H_
-#define BASE_DEBUG_TRACE_EVENT_H_
-
-#include "base/trace_event/trace_event.h"
-
-#endif // BASE_DEBUG_TRACE_EVENT_H_
diff --git a/base/debug/trace_event_argument.h b/base/debug/trace_event_argument.h
deleted file mode 100644
index 167b46c..0000000
--- a/base/debug/trace_event_argument.h
+++ /dev/null
@@ -1,14 +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.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
-#define BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
-
-#include "base/trace_event/trace_event_argument.h"
-
-#endif // BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h
deleted file mode 100644
index a619d29..0000000
--- a/base/debug/trace_event_impl.h
+++ /dev/null
@@ -1,14 +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.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_IMPL_H_
-#define BASE_DEBUG_TRACE_EVENT_IMPL_H_
-
-#include "base/trace_event/trace_event_impl.h"
-
-#endif // BASE_DEBUG_TRACE_EVENT_IMPL_H_
diff --git a/base/debug/trace_event_synthetic_delay.h b/base/debug/trace_event_synthetic_delay.h
deleted file mode 100644
index 1f1eafb..0000000
--- a/base/debug/trace_event_synthetic_delay.h
+++ /dev/null
@@ -1,14 +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.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_
-#define BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_
-
-#include "base/trace_event/trace_event_synthetic_delay.h"
-
-#endif // BASE_DEBUG_TRACE_EVENT_SYNTHETIC_DELAY_H_
diff --git a/base/debug/trace_event_win.h b/base/debug/trace_event_win.h
deleted file mode 100644
index 473e174..0000000
--- a/base/debug/trace_event_win.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// In the process of moving the trace event files. Right now the headers
-// are being forwarded. In next CLs the change will get completed
-// TODO(ssid): https://code.google.com/p/chromium/issues/detail?id=451032
-
-#ifndef BASE_DEBUG_TRACE_EVENT_WIN_H_
-#define BASE_DEBUG_TRACE_EVENT_WIN_H_
-
-#include "base/trace_event/trace_event_win.h"
-
-#endif // BASE_DEBUG_TRACE_EVENT_WIN_H_
diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc
index 73f9cfb..63e5480 100644
--- a/base/files/file_path_watcher_win.cc
+++ b/base/files/file_path_watcher_win.cc
@@ -149,7 +149,8 @@
void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("FilePathWatcherImpl_OnObjectSignaled"));
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 FilePathWatcherImpl::OnObjectSignaled"));
DCHECK(object == handle_);
// Make sure we stay alive through the body of this function.
diff --git a/base/json/json_string_value_serializer.cc b/base/json/json_string_value_serializer.cc
index 59f030d..b626640 100644
--- a/base/json/json_string_value_serializer.cc
+++ b/base/json/json_string_value_serializer.cc
@@ -10,6 +10,21 @@
using base::Value;
+JSONStringValueSerializer::JSONStringValueSerializer(std::string* json_string)
+ : json_string_(json_string),
+ json_string_readonly_(*json_string),
+ pretty_print_(false),
+ allow_trailing_comma_(false) {
+}
+
+JSONStringValueSerializer::JSONStringValueSerializer(
+ const base::StringPiece& json_string)
+ : json_string_(nullptr),
+ json_string_readonly_(json_string),
+ pretty_print_(false),
+ allow_trailing_comma_(false) {
+}
+
JSONStringValueSerializer::~JSONStringValueSerializer() {}
bool JSONStringValueSerializer::Serialize(const Value& root) {
@@ -23,7 +38,7 @@
bool JSONStringValueSerializer::SerializeInternal(const Value& root,
bool omit_binary_values) {
- if (!json_string_ || initialized_with_const_string_)
+ if (!json_string_)
return false;
int options = 0;
@@ -37,10 +52,7 @@
Value* JSONStringValueSerializer::Deserialize(int* error_code,
std::string* error_str) {
- if (!json_string_)
- return NULL;
-
- return base::JSONReader::ReadAndReturnError(*json_string_,
+ return base::JSONReader::ReadAndReturnError(json_string_readonly_,
allow_trailing_comma_ ? base::JSON_ALLOW_TRAILING_COMMAS :
base::JSON_PARSE_RFC,
error_code, error_str);
diff --git a/base/json/json_string_value_serializer.h b/base/json/json_string_value_serializer.h
index 6435051..7f99bc9 100644
--- a/base/json/json_string_value_serializer.h
+++ b/base/json/json_string_value_serializer.h
@@ -10,28 +10,20 @@
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/files/file_path.h"
+#include "base/strings/string_piece.h"
#include "base/values.h"
class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer {
public:
- // json_string is the string that will be source of the deserialization
+ // |json_string| is the string that will be source of the deserialization
// or the destination of the serialization. The caller of the constructor
- // retains ownership of the string.
- explicit JSONStringValueSerializer(std::string* json_string)
- : json_string_(json_string),
- initialized_with_const_string_(false),
- pretty_print_(false),
- allow_trailing_comma_(false) {
- }
+ // retains ownership of the string. |json_string| must not be null.
+ explicit JSONStringValueSerializer(std::string* json_string);
- // This version allows initialization with a const string reference for
- // deserialization only.
- explicit JSONStringValueSerializer(const std::string& json_string)
- : json_string_(&const_cast<std::string&>(json_string)),
- initialized_with_const_string_(true),
- pretty_print_(false),
- allow_trailing_comma_(false) {
- }
+ // This version allows initialization with a StringPiece for deserialization
+ // only. Retains a reference to the contents of |json_string|, so the data
+ // must outlive the JSONStringValueSerializer.
+ explicit JSONStringValueSerializer(const base::StringPiece& json_string);
~JSONStringValueSerializer() override;
@@ -46,7 +38,7 @@
// Attempt to deserialize the data structure encoded in the string passed
// in to the constructor into a structure of Value objects. If the return
- // value is NULL, and if |error_code| is non-null, |error_code| will
+ // value is null, and if |error_code| is non-null, |error_code| will
// contain an integer error code (a JsonParseError in this case).
// If |error_message| is non-null, it will be filled in with a formatted
// error message including the location of the error if appropriate.
@@ -64,8 +56,12 @@
private:
bool SerializeInternal(const base::Value& root, bool omit_binary_values);
+ // String for writing. Owned by the caller of the constructor. Will be null if
+ // the serializer was initialized with a const string.
std::string* json_string_;
- bool initialized_with_const_string_;
+ // String for reading. Data is owned by the caller of the constructor. If
+ // |json_string_| is non-null, this is a view onto |json_string_|.
+ base::StringPiece json_string_readonly_;
bool pretty_print_; // If true, serialization will span multiple lines.
// If true, deserialization will allow trailing commas.
bool allow_trailing_comma_;
diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc
index e3c349c..d2a84de 100644
--- a/base/json/json_value_serializer_unittest.cc
+++ b/base/json/json_value_serializer_unittest.cc
@@ -12,6 +12,7 @@
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -42,6 +43,20 @@
"\t\"compound\": { \"a\": 1, \"b\": 2, },\n"
"}\n";
+// kProperJSON with a few misc characters at the begin and end.
+const char kProperJSONPadded[] =
+ ")]}'\n"
+ "{\n"
+ " \"compound\": {\n"
+ " \"a\": 1,\n"
+ " \"b\": 2\n"
+ " },\n"
+ " \"some_String\": \"1337\",\n"
+ " \"some_int\": 42,\n"
+ " \"the_list\": [ \"val1\", \"val2\" ]\n"
+ "}\n"
+ "?!ab\n";
+
const char kWinLineEnds[] = "\r\n";
const char kLinuxLineEnds[] = "\n";
@@ -74,7 +89,43 @@
// Test proper JSON [de]serialization from string is working.
TEST(JSONValueSerializerTest, ReadProperJSONFromString) {
// Try to deserialize it through the serializer.
+ JSONStringValueSerializer str_deserializer(kProperJSON);
+
+ int error_code = 0;
+ std::string error_message;
+ scoped_ptr<Value> value(
+ str_deserializer.Deserialize(&error_code, &error_message));
+ ASSERT_TRUE(value.get());
+ ASSERT_EQ(0, error_code);
+ ASSERT_TRUE(error_message.empty());
+ // Verify if the same JSON is still there.
+ CheckJSONIsStillTheSame(*value);
+}
+
+// Test proper JSON deserialization from a string pointer is working.
+TEST(JSONValueSerializerTest, ReadProperJSONFromStringPointer) {
+ // Try to deserialize a string pointer through the serializer. (This exercises
+ // a separate code path to passing a StringPiece.)
std::string proper_json(kProperJSON);
+ JSONStringValueSerializer str_deserializer(&proper_json);
+
+ int error_code = 0;
+ std::string error_message;
+ scoped_ptr<Value> value(
+ str_deserializer.Deserialize(&error_code, &error_message));
+ ASSERT_TRUE(value.get());
+ ASSERT_EQ(0, error_code);
+ ASSERT_TRUE(error_message.empty());
+ // Verify if the same JSON is still there.
+ CheckJSONIsStillTheSame(*value);
+}
+
+// Test proper JSON deserialization from a StringPiece substring.
+TEST(JSONValueSerializerTest, ReadProperJSONFromStringPiece) {
+ // Create a StringPiece for the substring of kProperJSONPadded that matches
+ // kProperJSON.
+ base::StringPiece proper_json(kProperJSONPadded);
+ proper_json = proper_json.substr(5, proper_json.length() - 10);
JSONStringValueSerializer str_deserializer(proper_json);
int error_code = 0;
@@ -92,8 +143,7 @@
// the proper flag for that is set.
TEST(JSONValueSerializerTest, ReadJSONWithTrailingCommasFromString) {
// Try to deserialize it through the serializer.
- std::string proper_json(kProperJSONWithCommas);
- JSONStringValueSerializer str_deserializer(proper_json);
+ JSONStringValueSerializer str_deserializer(kProperJSONWithCommas);
int error_code = 0;
std::string error_message;
@@ -165,9 +215,9 @@
}
TEST(JSONValueSerializerTest, Roundtrip) {
- const std::string original_serialization =
+ static const char kOriginalSerialization[] =
"{\"bool\":true,\"double\":3.14,\"int\":42,\"list\":[1,2],\"null\":null}";
- JSONStringValueSerializer serializer(original_serialization);
+ JSONStringValueSerializer serializer(kOriginalSerialization);
scoped_ptr<Value> root(serializer.Deserialize(NULL, NULL));
ASSERT_TRUE(root.get());
ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
@@ -198,7 +248,7 @@
std::string test_serialization;
JSONStringValueSerializer mutable_serializer(&test_serialization);
ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
- ASSERT_EQ(original_serialization, test_serialization);
+ ASSERT_EQ(kOriginalSerialization, test_serialization);
mutable_serializer.set_pretty_print(true);
ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
@@ -273,15 +323,15 @@
string16 test(WideToUTF16(L"\x7F51\x9875"));
root.SetString("web", test);
- std::string expected = "{\"web\":\"\xE7\xBD\x91\xE9\xA1\xB5\"}";
+ static const char kExpected[] = "{\"web\":\"\xE7\xBD\x91\xE9\xA1\xB5\"}";
std::string actual;
JSONStringValueSerializer serializer(&actual);
ASSERT_TRUE(serializer.Serialize(root));
- ASSERT_EQ(expected, actual);
+ ASSERT_EQ(kExpected, actual);
// escaped ascii text -> json
- JSONStringValueSerializer deserializer(expected);
+ JSONStringValueSerializer deserializer(kExpected);
scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL));
ASSERT_TRUE(deserial_root.get());
DictionaryValue* dict_root =
@@ -297,15 +347,15 @@
string16 test(WideToUTF16(L"\x01\x02"));
root.SetString("test", test);
- std::string expected = "{\"test\":\"\\u0001\\u0002\"}";
+ static const char kExpected[] = "{\"test\":\"\\u0001\\u0002\"}";
std::string actual;
JSONStringValueSerializer serializer(&actual);
ASSERT_TRUE(serializer.Serialize(root));
- ASSERT_EQ(expected, actual);
+ ASSERT_EQ(kExpected, actual);
// escaped ascii text -> json
- JSONStringValueSerializer deserializer(expected);
+ JSONStringValueSerializer deserializer(kExpected);
scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL));
ASSERT_TRUE(deserial_root.get());
DictionaryValue* dict_root =
@@ -315,8 +365,8 @@
ASSERT_EQ(test, test_value);
// Test converting escaped regular chars
- std::string escaped_chars = "{\"test\":\"\\u0067\\u006f\"}";
- JSONStringValueSerializer deserializer2(escaped_chars);
+ static const char kEscapedChars[] = "{\"test\":\"\\u0067\\u006f\"}";
+ JSONStringValueSerializer deserializer2(kEscapedChars);
deserial_root.reset(deserializer2.Deserialize(NULL, NULL));
ASSERT_TRUE(deserial_root.get());
dict_root = static_cast<DictionaryValue*>(deserial_root.get());
@@ -327,12 +377,12 @@
TEST(JSONValueSerializerTest, AllowTrailingComma) {
scoped_ptr<Value> root;
scoped_ptr<Value> root_expected;
- std::string test_with_commas("{\"key\": [true,],}");
- std::string test_no_commas("{\"key\": [true]}");
+ static const char kTestWithCommas[] = "{\"key\": [true,],}";
+ static const char kTestNoCommas[] = "{\"key\": [true]}";
- JSONStringValueSerializer serializer(test_with_commas);
+ JSONStringValueSerializer serializer(kTestWithCommas);
serializer.set_allow_trailing_comma(true);
- JSONStringValueSerializer serializer_expected(test_no_commas);
+ JSONStringValueSerializer serializer_expected(kTestNoCommas);
root.reset(serializer.Deserialize(NULL, NULL));
ASSERT_TRUE(root.get());
root_expected.reset(serializer_expected.Deserialize(NULL, NULL));
diff --git a/base/memory/discardable_memory_ashmem.h b/base/memory/discardable_memory_ashmem.h
index c1cc077..100655b 100644
--- a/base/memory/discardable_memory_ashmem.h
+++ b/base/memory/discardable_memory_ashmem.h
@@ -25,20 +25,20 @@
DiscardableMemoryAshmemAllocator* allocator,
DiscardableMemoryManager* manager);
- virtual ~DiscardableMemoryAshmem();
+ ~DiscardableMemoryAshmem() override;
bool Initialize();
// Overridden from DiscardableMemory:
- virtual DiscardableMemoryLockStatus Lock() override;
- virtual void Unlock() override;
- virtual void* Memory() const override;
+ DiscardableMemoryLockStatus Lock() override;
+ void Unlock() override;
+ void* Memory() const override;
// Overridden from internal::DiscardableMemoryManagerAllocation:
- virtual bool AllocateAndAcquireLock() override;
- virtual void ReleaseLock() override;
- virtual void Purge() override;
- virtual bool IsMemoryResident() const override;
+ bool AllocateAndAcquireLock() override;
+ void ReleaseLock() override;
+ void Purge() override;
+ bool IsMemoryResident() const override;
private:
const size_t bytes_;
diff --git a/base/memory/scoped_open_process.h b/base/memory/scoped_open_process.h
deleted file mode 100644
index 8bb19e2..0000000
--- a/base/memory/scoped_open_process.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_MEMORY_SCOPED_OPEN_PROCESS_H_
-#define BASE_MEMORY_SCOPED_OPEN_PROCESS_H_
-
-#include "base/process/process_handle.h"
-
-namespace base {
-
-// A class that opens a process from its process id and closes it when the
-// instance goes out of scope.
-class ScopedOpenProcess {
- public:
- ScopedOpenProcess() : handle_(kNullProcessHandle) {
- }
-
- // Automatically close the process.
- ~ScopedOpenProcess() {
- Close();
- }
-
- // Open a new process by pid. Closes any previously opened process (even if
- // opening the new one fails).
- bool Open(ProcessId pid) {
- Close();
- return OpenProcessHandle(pid, &handle_);
- }
-
- // Close the previously opened process.
- void Close() {
- if (handle_ == kNullProcessHandle)
- return;
-
- CloseProcessHandle(handle_);
- handle_ = kNullProcessHandle;
- }
-
- ProcessHandle handle() const { return handle_; }
-
- private:
- ProcessHandle handle_;
- DISALLOW_COPY_AND_ASSIGN(ScopedOpenProcess);
-};
-} // namespace base
-
-#endif // BASE_MEMORY_SCOPED_OPEN_PROCESS_H_
diff --git a/base/message_loop/incoming_task_queue.cc b/base/message_loop/incoming_task_queue.cc
index 9e5b013..c1ce939 100644
--- a/base/message_loop/incoming_task_queue.cc
+++ b/base/message_loop/incoming_task_queue.cc
@@ -4,6 +4,8 @@
#include "base/message_loop/incoming_task_queue.h"
+#include <limits>
+
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
@@ -15,6 +17,13 @@
namespace {
+#ifndef NDEBUG
+// Delays larger than this are often bogus, and a warning should be emitted in
+// debug builds to warn developers. http://crbug.com/450045
+const int kTaskDelayWarningThresholdInSeconds =
+ 14 * 24 * 60 * 60; // 14 days.
+#endif
+
// Returns true if MessagePump::ScheduleWork() must be called one
// time for every task that is added to the MessageLoop incoming queue.
bool AlwaysNotifyPump(MessageLoop::Type type) {
@@ -43,6 +52,11 @@
const Closure& task,
TimeDelta delay,
bool nestable) {
+ DLOG_IF(WARNING,
+ delay.InSeconds() > kTaskDelayWarningThresholdInSeconds)
+ << "Requesting super-long task delay period of " << delay.InSeconds()
+ << " seconds from here: " << from_here.ToString();
+
AutoLock locked(incoming_queue_lock_);
PendingTask pending_task(
from_here, task, CalculateDelayedRuntime(delay), nestable);
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 24db543..86771e4 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -5,7 +5,6 @@
#include "base/message_loop/message_loop.h"
#include <algorithm>
-#include <limits>
#include "base/bind.h"
#include "base/compiler_specific.h"
@@ -44,12 +43,6 @@
LazyInstance<base::ThreadLocalPointer<MessageLoop> >::Leaky lazy_tls_ptr =
LAZY_INSTANCE_INITIALIZER;
-// Delays larger than this many microseconds are likely bogus, and a warning
-// should be emitted in debug builds to warn developers.
-// http://crbug.com/450045
-const int kTaskDelayWarningThresholdInMicroseconds =
- std::numeric_limits<int>::max() / 2;
-
// Logical events for Histogram profiling. Run with -message-loop-histogrammer
// to get an accounting of messages and actions taken on each thread.
const int kTaskRunEvent = 0x1;
@@ -286,10 +279,6 @@
const Closure& task,
TimeDelta delay) {
DCHECK(!task.is_null()) << from_here.ToString();
- DLOG_IF(WARNING,
- delay.InMicroseconds() > kTaskDelayWarningThresholdInMicroseconds)
- << "Requesting super-long task delay period of " << delay.InMicroseconds()
- << " usec from " << from_here.ToString();
incoming_task_queue_->AddToIncomingQueue(from_here, task, delay, true);
}
@@ -305,10 +294,6 @@
const Closure& task,
TimeDelta delay) {
DCHECK(!task.is_null()) << from_here.ToString();
- DLOG_IF(WARNING,
- delay.InMicroseconds() > kTaskDelayWarningThresholdInMicroseconds)
- << "Requesting super-long task delay period of " << delay.InMicroseconds()
- << " usec from " << from_here.ToString();
incoming_task_queue_->AddToIncomingQueue(from_here, task, delay, false);
}
diff --git a/base/message_loop/message_pump_android.h b/base/message_loop/message_pump_android.h
index 9b4540f..d48050d 100644
--- a/base/message_loop/message_pump_android.h
+++ b/base/message_loop/message_pump_android.h
@@ -22,12 +22,12 @@
class BASE_EXPORT MessagePumpForUI : public MessagePump {
public:
MessagePumpForUI();
- virtual ~MessagePumpForUI();
+ ~MessagePumpForUI() override;
- virtual void Run(Delegate* delegate) override;
- virtual void Quit() override;
- virtual void ScheduleWork() override;
- virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
+ void Run(Delegate* delegate) override;
+ void Quit() override;
+ void ScheduleWork() override;
+ void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
virtual void Start(Delegate* delegate);
diff --git a/base/process/kill_win.cc b/base/process/kill_win.cc
index 0a0c99c..4d7225f 100644
--- a/base/process/kill_win.cc
+++ b/base/process/kill_win.cc
@@ -73,7 +73,8 @@
void TimerExpiredTask::OnObjectSignaled(HANDLE object) {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("TimerExpiredTask_OnObjectSignaled"));
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 TimerExpiredTask::OnObjectSignaled"));
process_.Close();
}
diff --git a/base/process/process.h b/base/process/process.h
index 70aca6d..77d2bce 100644
--- a/base/process/process.h
+++ b/base/process/process.h
@@ -49,6 +49,9 @@
// Returns an object for the current process.
static Process Current();
+ // Returns a Process for the given |pid|.
+ static Process Open(ProcessId pid);
+
// Returns a Process for the given |pid|. On Windows the handle is opened
// with more access rights and must only be used by trusted code (can read the
// address space and duplicate handles).
diff --git a/base/process/process_handle.h b/base/process/process_handle.h
index 976552c..c99ea15 100644
--- a/base/process/process_handle.h
+++ b/base/process/process_handle.h
@@ -40,9 +40,7 @@
// Returns the ProcessHandle of the current process.
BASE_EXPORT ProcessHandle GetCurrentProcessHandle();
-// Converts a PID to a process handle. This handle must be closed by
-// CloseProcessHandle when you are done with it. Returns true on success.
-BASE_EXPORT bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle);
+
// Closes the process handle opened by OpenProcessHandle.
BASE_EXPORT void CloseProcessHandle(ProcessHandle process);
diff --git a/base/process/process_handle_posix.cc b/base/process/process_handle_posix.cc
index 3d92300..a661ecd 100644
--- a/base/process/process_handle_posix.cc
+++ b/base/process/process_handle_posix.cc
@@ -16,13 +16,6 @@
return GetCurrentProcId();
}
-bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
- // On Posix platforms, process handles are the same as PIDs, so we
- // don't need to do anything.
- *handle = pid;
- return true;
-}
-
void CloseProcessHandle(ProcessHandle process) {
// See OpenProcessHandle, nothing to do.
return;
diff --git a/base/process/process_handle_win.cc b/base/process/process_handle_win.cc
index 4683311..30b2066 100644
--- a/base/process/process_handle_win.cc
+++ b/base/process/process_handle_win.cc
@@ -20,22 +20,6 @@
return ::GetCurrentProcess();
}
-bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
- // We try to limit privileges granted to the handle. If you need this
- // for test code, consider using OpenPrivilegedProcessHandle instead of
- // adding more privileges here.
- ProcessHandle result = OpenProcess(PROCESS_TERMINATE |
- PROCESS_QUERY_INFORMATION |
- SYNCHRONIZE,
- FALSE, pid);
-
- if (result == NULL)
- return false;
-
- *handle = result;
- return true;
-}
-
void CloseProcessHandle(ProcessHandle process) {
CloseHandle(process);
}
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index e8db571..dd37236 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -399,17 +399,36 @@
return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached;
}
-// Exposed for testing.
int ParseProcStatCPU(const std::string& input) {
- std::vector<std::string> proc_stats;
- if (!internal::ParseProcStats(input, &proc_stats))
+ // |input| may be empty if the process disappeared somehow.
+ // e.g. http://crbug.com/145811.
+ if (input.empty())
return -1;
- if (proc_stats.size() <= internal::VM_STIME)
+ size_t start = input.find_last_of(')');
+ if (start == input.npos)
return -1;
- int utime = GetProcStatsFieldAsInt64(proc_stats, internal::VM_UTIME);
- int stime = GetProcStatsFieldAsInt64(proc_stats, internal::VM_STIME);
- return utime + stime;
+
+ // Number of spaces remaining until reaching utime's index starting after the
+ // last ')'.
+ int num_spaces_remaining = internal::VM_UTIME - 1;
+
+ size_t i = start;
+ while ((i = input.find(' ', i + 1)) != input.npos) {
+ // Validate the assumption that there aren't any contiguous spaces
+ // in |input| before utime.
+ DCHECK_NE(input[i - 1], ' ');
+ if (--num_spaces_remaining == 0) {
+ int utime = 0;
+ int stime = 0;
+ if (sscanf(&input.data()[i], "%d %d", &utime, &stime) != 2)
+ return -1;
+
+ return utime + stime;
+ }
+ }
+
+ return -1;
}
const char kProcSelfExe[] = "/proc/self/exe";
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc
index 69f5e83..dbfaa1a 100644
--- a/base/process/process_metrics_unittest.cc
+++ b/base/process/process_metrics_unittest.cc
@@ -323,6 +323,17 @@
"3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0";
EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat));
+
+ // Some weird long-running process with a weird name that I created for the
+ // purposes of this test.
+ const char kWeirdNameStat[] = "26115 (Hello) You ())) ) R 24614 26115 24614"
+ " 34839 26115 4218880 227 0 0 0 "
+ "5186 11 0 0 "
+ "20 0 1 0 36933953 4296704 90 18446744073709551615 4194304 4196116 "
+ "140735857761568 140735857761160 4195644 0 0 0 0 0 0 0 17 14 0 0 0 0 0 "
+ "6295056 6295616 16519168 140735857770710 140735857770737 "
+ "140735857770737 140735857774557 0";
+ EXPECT_EQ(5186 + 11, base::ParseProcStatCPU(kWeirdNameStat));
}
#endif // defined(OS_LINUX) || defined(OS_ANDROID)
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index 5d7007c..bc2f3f8 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -14,7 +14,6 @@
namespace base {
Process::Process(ProcessHandle handle) : process_(handle) {
- CHECK_NE(handle, GetCurrentProcessHandle());
}
Process::Process(RValue other)
@@ -32,19 +31,22 @@
// static
Process Process::Current() {
- Process process;
- process.process_ = GetCurrentProcessHandle();
- return process.Pass();
+ return Process(GetCurrentProcessHandle());
+}
+
+// static
+Process Process::Open(ProcessId pid) {
+ if (pid == GetCurrentProcId())
+ return Current();
+
+ // On POSIX process handles are the same as PIDs.
+ return Process(pid);
}
// static
Process Process::OpenWithExtraPriviles(ProcessId pid) {
- if (pid == GetCurrentProcId())
- return Current();
-
- // On POSIX process handles are the same as PIDs, and there are no privileges
- // to set.
- return Process(pid);
+ // On POSIX there are no privileges to set.
+ return Open(pid);
}
// static
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index 0107015..4e600f9 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -47,10 +47,14 @@
}
// static
+Process Process::Open(ProcessId pid) {
+ return Process(::OpenProcess(kBasicProcessAccess, FALSE, pid));
+}
+
+// static
Process Process::OpenWithExtraPriviles(ProcessId pid) {
DWORD access = kBasicProcessAccess | PROCESS_DUP_HANDLE | PROCESS_VM_READ;
- ProcessHandle handle = ::OpenProcess(access, FALSE, pid);
- return Process(handle);
+ return Process(::OpenProcess(access, FALSE, pid));
}
// static
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index f77034b..8f334da 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -454,8 +454,8 @@
return DoLowerCaseEqualsASCII(a_begin, a_end, b);
}
-// TODO(port): Resolve wchar_t/iterator issues that require OS_ANDROID here.
-#if !defined(OS_ANDROID)
+// TODO(jdduke): Remove guards after complete adoption of libc++ on Android.
+#if !defined(OS_ANDROID) || !defined(USE_STLPORT)
bool LowerCaseEqualsASCII(const char* a_begin,
const char* a_end,
const char* b) {
@@ -467,8 +467,7 @@
const char* b) {
return DoLowerCaseEqualsASCII(a_begin, a_end, b);
}
-
-#endif // !defined(OS_ANDROID)
+#endif // !defined(OS_ANDROID) || !defined(USE_STLPORT)
bool EqualsASCII(const string16& a, const base::StringPiece& b) {
if (a.length() != b.length())
diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h
index 602ba27..61eda20 100644
--- a/base/strings/string_util_win.h
+++ b/base/strings/string_util_win.h
@@ -34,12 +34,9 @@
inline int vsnprintf(char* buffer, size_t size,
const char* format, va_list arguments) {
- int length = _vsprintf_p(buffer, size, format, arguments);
- if (length < 0) {
- if (size > 0)
- buffer[0] = 0;
- return _vscprintf_p(format, arguments);
- }
+ int length = vsnprintf_s(buffer, size, size - 1, format, arguments);
+ if (length < 0)
+ return _vscprintf(format, arguments);
return length;
}
@@ -47,12 +44,9 @@
const wchar_t* format, va_list arguments) {
DCHECK(IsWprintfFormatPortable(format));
- int length = _vswprintf_p(buffer, size, format, arguments);
- if (length < 0) {
- if (size > 0)
- buffer[0] = 0;
- return _vscwprintf_p(format, arguments);
- }
+ int length = _vsnwprintf_s(buffer, size, size - 1, format, arguments);
+ if (length < 0)
+ return _vscwprintf(format, arguments);
return length;
}
diff --git a/base/strings/stringprintf_unittest.cc b/base/strings/stringprintf_unittest.cc
index 3217478..c49637c 100644
--- a/base/strings/stringprintf_unittest.cc
+++ b/base/strings/stringprintf_unittest.cc
@@ -163,19 +163,6 @@
}
#endif
-// Test that the positional parameters work.
-TEST(StringPrintfTest, PositionalParameters) {
- std::string out;
- SStringPrintf(&out, "%1$s %1$s", "test");
- EXPECT_STREQ("test test", out.c_str());
-
-#if defined(OS_WIN)
- std::wstring wout;
- SStringPrintf(&wout, L"%1$ls %1$ls", L"test");
- EXPECT_STREQ(L"test test", wout.c_str());
-#endif
-}
-
// Test that StringPrintf and StringAppendV do not change errno.
TEST(StringPrintfTest, StringPrintfErrno) {
errno = 1;
diff --git a/base/synchronization/waitable_event_watcher_win.cc b/base/synchronization/waitable_event_watcher_win.cc
index f5218f1..a04a435 100644
--- a/base/synchronization/waitable_event_watcher_win.cc
+++ b/base/synchronization/waitable_event_watcher_win.cc
@@ -39,7 +39,8 @@
void WaitableEventWatcher::OnObjectSignaled(HANDLE h) {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("WaitableEventWatche_OnObjectSignaled"));
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 WaitableEventWatcher::OnObjectSignaled"));
WaitableEvent* event = event_;
EventCallback callback = callback_;
diff --git a/base/test/test_support_android.cc b/base/test/test_support_android.cc
index eeab9ee..11a0871 100644
--- a/base/test/test_support_android.cc
+++ b/base/test/test_support_android.cc
@@ -72,14 +72,14 @@
// The MessagePumpForUI implementation for test purpose.
class MessagePumpForUIStub : public base::MessagePumpForUI {
- virtual ~MessagePumpForUIStub() {}
+ ~MessagePumpForUIStub() override {}
- virtual void Start(base::MessagePump::Delegate* delegate) override {
+ void Start(base::MessagePump::Delegate* delegate) override {
NOTREACHED() << "The Start() method shouldn't be called in test, using"
" Run() method should be used.";
}
- virtual void Run(base::MessagePump::Delegate* delegate) override {
+ void Run(base::MessagePump::Delegate* delegate) override {
// The following was based on message_pump_glib.cc, except we're using a
// WaitableEvent since there are no native message loop to use.
RunState state(delegate, g_state ? g_state->run_depth + 1 : 1);
@@ -119,16 +119,11 @@
g_state = previous_state;
}
- virtual void Quit() override {
- Waitable::GetInstance()->Quit();
- }
+ void Quit() override { Waitable::GetInstance()->Quit(); }
- virtual void ScheduleWork() override {
- Waitable::GetInstance()->Signal();
- }
+ void ScheduleWork() override { Waitable::GetInstance()->Signal(); }
- virtual void ScheduleDelayedWork(
- const base::TimeTicks& delayed_work_time) override {
+ void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) override {
Waitable::GetInstance()->Signal();
}
};
diff --git a/base/test/test_support_ios.mm b/base/test/test_support_ios.mm
index 67fae06..3b31da6 100644
--- a/base/test/test_support_ios.mm
+++ b/base/test/test_support_ios.mm
@@ -11,6 +11,7 @@
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_pump_default.h"
#include "base/test/test_suite.h"
+#include "testing/coverage_util_ios.h"
// Springboard will kill any iOS app that fails to check in after launch within
// a given time. Starting a UIApplication before invoking TestSuite::Run
@@ -165,6 +166,8 @@
UIApplication* application = [UIApplication sharedApplication];
[application _terminateWithStatus:exitStatus];
+ coverage_util::FlushCoverageDataIfNecessary();
+
exit(exitStatus);
}
diff --git a/base/threading/thread_checker.h b/base/threading/thread_checker.h
index 4d71f79..449247a 100644
--- a/base/threading/thread_checker.h
+++ b/base/threading/thread_checker.h
@@ -30,7 +30,7 @@
// right version for your build configuration.
class ThreadCheckerDoNothing {
public:
- bool CalledOnValidThread() const {
+ bool CalledOnValidThread() const WARN_UNUSED_RESULT {
return true;
}
diff --git a/base/threading/thread_checker_impl.h b/base/threading/thread_checker_impl.h
index 879ac3a..c92e143 100644
--- a/base/threading/thread_checker_impl.h
+++ b/base/threading/thread_checker_impl.h
@@ -6,6 +6,7 @@
#define BASE_THREADING_THREAD_CHECKER_IMPL_H_
#include "base/base_export.h"
+#include "base/compiler_specific.h"
#include "base/synchronization/lock.h"
#include "base/threading/platform_thread.h"
@@ -22,7 +23,7 @@
ThreadCheckerImpl();
~ThreadCheckerImpl();
- bool CalledOnValidThread() const;
+ bool CalledOnValidThread() const WARN_UNUSED_RESULT;
// Changes the thread that is checked for in CalledOnValidThread. This may
// be useful when an object may be created on one thread and then used
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index 7f73071..c8583d7 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -141,7 +141,7 @@
// means, if the category for the event is disabled, the conversion will not
// happen.
//
-// class MyData : public base::debug::ConvertableToTraceFormat {
+// class MyData : public base::trace_event::ConvertableToTraceFormat {
// public:
// MyData() {}
// virtual void AppendAsTraceFormat(std::string* out) const override {
@@ -596,6 +596,15 @@
category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
arg1_name, arg1_val)
+// Similar to TRACE_EVENT_ASYNC_STEP_INTOx but with a custom |at| timestamp
+// provided.
+#define TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category_group, name, \
+ id, step, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_STEP_INTO, category_group, name, id, \
+ static_cast<int>(base::PlatformThread::CurrentId()), \
+ timestamp, TRACE_EVENT_FLAG_NONE, "step", step)
+
// Records a single ASYNC_STEP_PAST event for |step| immediately. If the
// category is not enabled, then this does nothing. The |name| and |id| must
// match the ASYNC_BEGIN event above. The |step| param identifies this step
@@ -795,8 +804,8 @@
#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
- (base::debug::TraceLog::ENABLED_FOR_RECORDING | \
- base::debug::TraceLog::ENABLED_FOR_EVENT_CALLBACK))
+ (base::trace_event::TraceLog::ENABLED_FOR_RECORDING | \
+ base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK))
// Macro to efficiently determine if a given category group is enabled.
#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
@@ -839,16 +848,16 @@
// const unsigned char*
// TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
- base::debug::TraceLog::GetCategoryGroupEnabled
+ base::trace_event::TraceLog::GetCategoryGroupEnabled
// Get the number of times traces have been recorded. This is used to implement
// the TRACE_EVENT_IS_NEW_TRACE facility.
// unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED()
#define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \
- base::debug::TraceLog::GetInstance()->GetNumTracesRecorded
+ base::trace_event::TraceLog::GetInstance()->GetNumTracesRecorded
// Add a trace event to the platform tracing system.
-// base::debug::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT(
+// base::trace_event::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT(
// char phase,
// const unsigned char* category_group_enabled,
// const char* name,
@@ -859,10 +868,11 @@
// const unsigned long long* arg_values,
// unsigned char flags)
#define TRACE_EVENT_API_ADD_TRACE_EVENT \
- base::debug::TraceLog::GetInstance()->AddTraceEvent
+ base::trace_event::TraceLog::GetInstance()->AddTraceEvent
// Add a trace event to the platform tracing system.
-// base::debug::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
+// base::trace_event::TraceEventHandle
+// TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
// char phase,
// const unsigned char* category_group_enabled,
// const char* name,
@@ -875,15 +885,16 @@
// const unsigned long long* arg_values,
// unsigned char flags)
#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \
- base::debug::TraceLog::GetInstance()->AddTraceEventWithThreadIdAndTimestamp
+ base::trace_event::TraceLog::GetInstance() \
+ ->AddTraceEventWithThreadIdAndTimestamp
// Set the duration field of a COMPLETE trace event.
// void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
// const unsigned char* category_group_enabled,
// const char* name,
-// base::debug::TraceEventHandle id)
+// base::trace_event::TraceEventHandle id)
#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
- base::debug::TraceLog::GetInstance()->UpdateTraceEventDuration
+ base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDuration
// Defines atomic operations used internally by the tracing system.
#define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord
@@ -956,11 +967,12 @@
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
- base::debug::TraceEventHandle h = trace_event_internal::AddTraceEvent( \
- TRACE_EVENT_PHASE_COMPLETE, \
- INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
- name, trace_event_internal::kNoEventId, \
- TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
+ base::trace_event::TraceEventHandle h = \
+ trace_event_internal::AddTraceEvent( \
+ TRACE_EVENT_PHASE_COMPLETE, \
+ INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
+ trace_event_internal::kNoEventId, TRACE_EVENT_FLAG_NONE, \
+ ##__VA_ARGS__); \
INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \
INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \
}
@@ -1253,7 +1265,7 @@
// pointers to the internal c_str and pass through to the tracing API,
// the arg_values must live throughout these procedures.
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
@@ -1263,7 +1275,8 @@
const base::TimeTicks& timestamp,
unsigned char flags,
const char* arg1_name,
- const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val) {
+ const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
+ arg1_val) {
const int num_args = 1;
unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE };
return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
@@ -1272,7 +1285,7 @@
}
template<class ARG1_TYPE>
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
@@ -1284,7 +1297,8 @@
const char* arg1_name,
const ARG1_TYPE& arg1_val,
const char* arg2_name,
- const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg2_val) {
+ const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
+ arg2_val) {
const int num_args = 2;
const char* arg_names[2] = { arg1_name, arg2_name };
@@ -1293,7 +1307,8 @@
SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE;
- scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2];
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+ convertable_values[2];
convertable_values[1] = arg2_val;
return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
@@ -1302,7 +1317,7 @@
}
template<class ARG2_TYPE>
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
@@ -1312,7 +1327,7 @@
const base::TimeTicks& timestamp,
unsigned char flags,
const char* arg1_name,
- const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val,
+ const scoped_refptr<base::trace_event::ConvertableToTraceFormat>& arg1_val,
const char* arg2_name,
const ARG2_TYPE& arg2_val) {
const int num_args = 2;
@@ -1324,7 +1339,8 @@
arg_values[0] = 0;
SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
- scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2];
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+ convertable_values[2];
convertable_values[0] = arg1_val;
return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
@@ -1332,7 +1348,7 @@
num_args, arg_names, arg_types, arg_values, convertable_values, flags);
}
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
@@ -1342,22 +1358,23 @@
const base::TimeTicks& timestamp,
unsigned char flags,
const char* arg1_name,
- const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg1_val,
+ const scoped_refptr<base::trace_event::ConvertableToTraceFormat>& arg1_val,
const char* arg2_name,
- const scoped_refptr<base::debug::ConvertableToTraceFormat>& arg2_val) {
+ const scoped_refptr<base::trace_event::ConvertableToTraceFormat>&
+ arg2_val) {
const int num_args = 2;
const char* arg_names[2] = { arg1_name, arg2_name };
unsigned char arg_types[2] =
{ TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE };
- scoped_refptr<base::debug::ConvertableToTraceFormat> convertable_values[2] =
- { arg1_val, arg2_val };
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+ convertable_values[2] = {arg1_val, arg2_val};
return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
phase, category_group_enabled, name, id, thread_id, timestamp,
num_args, arg_names, arg_types, NULL, convertable_values, flags);
}
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
@@ -1371,7 +1388,7 @@
kZeroNumArgs, NULL, NULL, NULL, NULL, flags);
}
-static inline base::debug::TraceEventHandle AddTraceEvent(
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
char phase,
const unsigned char* category_group_enabled,
const char* name,
@@ -1384,7 +1401,7 @@
}
template<class ARG1_TYPE>
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
@@ -1405,7 +1422,7 @@
}
template<class ARG1_TYPE>
-static inline base::debug::TraceEventHandle AddTraceEvent(
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
char phase,
const unsigned char* category_group_enabled,
const char* name,
@@ -1421,7 +1438,7 @@
}
template<class ARG1_TYPE, class ARG2_TYPE>
-static inline base::debug::TraceEventHandle
+static inline base::trace_event::TraceEventHandle
AddTraceEventWithThreadIdAndTimestamp(
char phase,
const unsigned char* category_group_enabled,
@@ -1446,7 +1463,7 @@
}
template<class ARG1_TYPE, class ARG2_TYPE>
-static inline base::debug::TraceEventHandle AddTraceEvent(
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
char phase,
const unsigned char* category_group_enabled,
const char* name,
@@ -1478,7 +1495,7 @@
void Initialize(const unsigned char* category_group_enabled,
const char* name,
- base::debug::TraceEventHandle event_handle) {
+ base::trace_event::TraceEventHandle event_handle) {
data_.category_group_enabled = category_group_enabled;
data_.name = name;
data_.event_handle = event_handle;
@@ -1494,7 +1511,7 @@
struct Data {
const unsigned char* category_group_enabled;
const char* name;
- base::debug::TraceEventHandle event_handle;
+ base::trace_event::TraceEventHandle event_handle;
};
Data* p_data_;
Data data_;
@@ -1509,7 +1526,7 @@
private:
const unsigned char* category_group_enabled_;
const char* name_;
- base::debug::TraceEventHandle event_handle_;
+ base::trace_event::TraceEventHandle event_handle_;
};
// This macro generates less code then TRACE_EVENT0 but is also
@@ -1555,7 +1572,7 @@
} // namespace trace_event_internal
namespace base {
-namespace debug {
+namespace trace_event {
template<typename IDType> class TraceScopedTrackableObject {
public:
@@ -1583,7 +1600,15 @@
DISALLOW_COPY_AND_ASSIGN(TraceScopedTrackableObject);
};
-} // namespace debug
-} // namespace base
+} // namespace trace_event
+} // namespace base
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace base {
+namespace debug {
+using base::trace_event::TraceScopedTrackableObject;
+} // namespace debug
+} // namespace base
#endif /* BASE_TRACE_EVENT_TRACE_EVENT_H_ */
diff --git a/base/trace_event/trace_event_android.cc b/base/trace_event/trace_event_android.cc
index 31da26d..bcba436 100644
--- a/base/trace_event/trace_event_android.cc
+++ b/base/trace_event/trace_event_android.cc
@@ -24,8 +24,8 @@
unsigned long long id,
const char** arg_names,
const unsigned char* arg_types,
- const base::debug::TraceEvent::TraceValue* arg_values,
- const scoped_refptr<base::debug::ConvertableToTraceFormat>*
+ const base::trace_event::TraceEvent::TraceValue* arg_values,
+ const scoped_refptr<base::trace_event::ConvertableToTraceFormat>*
convertable_values,
unsigned char flags) {
std::string out = base::StringPrintf("%c|%d|%s", phase, getpid(), name);
@@ -33,7 +33,8 @@
base::StringAppendF(&out, "-%" PRIx64, static_cast<uint64>(id));
out += '|';
- for (int i = 0; i < base::debug::kTraceMaxNumArgs && arg_names[i]; ++i) {
+ for (int i = 0; i < base::trace_event::kTraceMaxNumArgs && arg_names[i];
+ ++i) {
if (i)
out += ';';
out += arg_names[i];
@@ -42,8 +43,8 @@
if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
convertable_values[i]->AppendAsTraceFormat(&out);
} else {
- base::debug::TraceEvent::AppendValueAsJSON(
- arg_types[i], arg_values[i], &out);
+ base::trace_event::TraceEvent::AppendValueAsJSON(arg_types[i],
+ arg_values[i], &out);
}
// Remove the quotes which may confuse the atrace script.
ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'");
@@ -65,7 +66,7 @@
complete_event->Signal();
}
-void EndChromeTracing(base::debug::TraceLog* trace_log,
+void EndChromeTracing(base::trace_event::TraceLog* trace_log,
base::WaitableEvent* complete_event) {
trace_log->SetDisabled();
// Delete the buffered trace events as they have been sent to atrace.
@@ -75,7 +76,7 @@
} // namespace
namespace base {
-namespace debug {
+namespace trace_event {
// These functions support Android systrace.py when 'webview' category is
// traced. With the new adb_profile_chrome, we may have two phases:
@@ -195,5 +196,5 @@
close(atrace_fd);
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_argument.cc b/base/trace_event/trace_event_argument.cc
index 00fcde1..91ed9e8 100644
--- a/base/trace_event/trace_event_argument.cc
+++ b/base/trace_event/trace_event_argument.cc
@@ -8,7 +8,7 @@
#include "base/values.h"
namespace base {
-namespace debug {
+namespace trace_event {
TracedValue::TracedValue() : root_(new DictionaryValue()) {
stack_.push_back(root_.get());
@@ -113,5 +113,5 @@
DCHECK_EQ(1u, stack_.size()) << tmp;
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h
index 08a5b50..43a0f38 100644
--- a/base/trace_event/trace_event_argument.h
+++ b/base/trace_event/trace_event_argument.h
@@ -16,7 +16,7 @@
class ListValue;
class Value;
-namespace debug {
+namespace trace_event {
class BASE_EXPORT TracedValue : public ConvertableToTraceFormat {
public:
@@ -53,6 +53,14 @@
DISALLOW_COPY_AND_ASSIGN(TracedValue);
};
+} // namespace trace_event
+} // namespace base
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace base {
+namespace debug {
+using base::trace_event::TracedValue;
} // namespace debug
} // namespace base
diff --git a/base/trace_event/trace_event_argument_unittest.cc b/base/trace_event/trace_event_argument_unittest.cc
index 39cafef..c59910e 100644
--- a/base/trace_event/trace_event_argument_unittest.cc
+++ b/base/trace_event/trace_event_argument_unittest.cc
@@ -6,7 +6,7 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
-namespace debug {
+namespace trace_event {
TEST(TraceEventArgumentTest, FlatDictionary) {
scoped_refptr<TracedValue> value = new TracedValue();
@@ -49,5 +49,5 @@
json);
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index a8a0cc1..95cf06d 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -41,8 +41,8 @@
class DeleteTraceLogForTesting {
public:
static void Delete() {
- Singleton<base::debug::TraceLog,
- LeakySingletonTraits<base::debug::TraceLog> >::OnExit(0);
+ Singleton<base::trace_event::TraceLog,
+ LeakySingletonTraits<base::trace_event::TraceLog>>::OnExit(0);
}
};
@@ -50,7 +50,7 @@
BASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state[3];
namespace base {
-namespace debug {
+namespace trace_event {
namespace {
@@ -2560,7 +2560,7 @@
return delays_;
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
namespace trace_event_internal {
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index 6d04c76..742f6b6 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -27,17 +27,17 @@
// Older style trace macros with explicit id and extra data
// Only these macros result in publishing data to ETW as currently implemented.
#define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
- base::debug::TraceLog::AddTraceEventEtw( \
+ base::trace_event::TraceLog::AddTraceEventEtw( \
TRACE_EVENT_PHASE_BEGIN, \
name, reinterpret_cast<const void*>(id), extra)
#define TRACE_EVENT_END_ETW(name, id, extra) \
- base::debug::TraceLog::AddTraceEventEtw( \
+ base::trace_event::TraceLog::AddTraceEventEtw( \
TRACE_EVENT_PHASE_END, \
name, reinterpret_cast<const void*>(id), extra)
#define TRACE_EVENT_INSTANT_ETW(name, id, extra) \
- base::debug::TraceLog::AddTraceEventEtw( \
+ base::trace_event::TraceLog::AddTraceEventEtw( \
TRACE_EVENT_PHASE_INSTANT, \
name, reinterpret_cast<const void*>(id), extra)
@@ -49,7 +49,7 @@
class WaitableEvent;
class MessageLoop;
-namespace debug {
+namespace trace_event {
// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
// class must implement this interface.
@@ -807,6 +807,23 @@
DISALLOW_COPY_AND_ASSIGN(TraceLog);
};
+} // namespace trace_event
+} // namespace base
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace base {
+namespace debug {
+using base::trace_event::CategoryFilter;
+using base::trace_event::ConvertableToTraceFormat;
+using base::trace_event::RECORD_UNTIL_FULL;
+using base::trace_event::RECORD_CONTINUOUSLY;
+using base::trace_event::RECORD_AS_MUCH_AS_POSSIBLE;
+using base::trace_event::TraceEventHandle;
+using base::trace_event::TraceLog;
+using base::trace_event::TraceLogStatus;
+using base::trace_event::TraceOptions;
+using base::trace_event::TraceResultBuffer;
} // namespace debug
} // namespace base
diff --git a/base/trace_event/trace_event_impl_constants.cc b/base/trace_event/trace_event_impl_constants.cc
index c46cf49..ffeacff 100644
--- a/base/trace_event/trace_event_impl_constants.cc
+++ b/base/trace_event/trace_event_impl_constants.cc
@@ -5,7 +5,7 @@
#include "base/trace_event/trace_event_impl.h"
namespace base {
-namespace debug {
+namespace trace_event {
// Enable everything but debug and test categories by default.
const char CategoryFilter::kDefaultCategoryFilterString[] = "-*Debug,-*Test";
@@ -24,5 +24,5 @@
const TraceLog::InternalTraceOptions
TraceLog::kInternalRecordAsMuchAsPossible = 1 << 4;
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_memory.cc b/base/trace_event/trace_event_memory.cc
index 96b28e4..2bf6d38 100644
--- a/base/trace_event/trace_event_memory.cc
+++ b/base/trace_event/trace_event_memory.cc
@@ -15,7 +15,7 @@
#include "base/trace_event/trace_event.h"
namespace base {
-namespace debug {
+namespace trace_event {
namespace {
@@ -26,13 +26,13 @@
/////////////////////////////////////////////////////////////////////////////
// Holds a memory dump until the tracing system needs to serialize it.
-class MemoryDumpHolder : public base::debug::ConvertableToTraceFormat {
+class MemoryDumpHolder : public base::trace_event::ConvertableToTraceFormat {
public:
// Takes ownership of dump, which must be a JSON string, allocated with
// malloc() and NULL terminated.
explicit MemoryDumpHolder(char* dump) : dump_(dump) {}
- // base::debug::ConvertableToTraceFormat overrides:
+ // base::trace_event::ConvertableToTraceFormat overrides:
void AppendAsTraceFormat(std::string* out) const override {
AppendHeapProfileAsTraceFormat(dump_, out);
}
@@ -165,7 +165,7 @@
TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
}
- // base::debug::TraceLog::EnabledStateChangedObserver overrides:
+// base::trace_event::TraceLog::EnabledStateChangedObserver overrides:
void TraceMemoryController::OnTraceLogEnabled() {
// Check to see if tracing is enabled for the memory category.
bool enabled;
@@ -436,5 +436,5 @@
return reinterpret_cast<const char*>(address);
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_memory.h b/base/trace_event/trace_event_memory.h
index f16467f..8e70020 100644
--- a/base/trace_event/trace_event_memory.h
+++ b/base/trace_event/trace_event_memory.h
@@ -22,7 +22,7 @@
class MessageLoopProxy;
-namespace debug {
+namespace trace_event {
// Watches for chrome://tracing to be enabled or disabled. When tracing is
// enabled, also enables tcmalloc heap profiling. This class is the preferred
@@ -46,7 +46,7 @@
GetHeapProfileFunction get_heap_profile_function);
virtual ~TraceMemoryController();
- // base::debug::TraceLog::EnabledStateChangedObserver overrides:
+ // base::trace_event::TraceLog::EnabledStateChangedObserver overrides:
void OnTraceLogEnabled() override;
void OnTraceLogDisabled() override;
@@ -146,7 +146,7 @@
// and "error" if |address| could not be parsed. Visible for testing.
BASE_EXPORT const char* StringFromHexAddress(const std::string& hex_address);
-} // namespace debug
+} // namespace trace_event
} // namespace base
// Make local variables with unique names based on the line number. Note that
@@ -159,7 +159,7 @@
// It generates a unique local variable name using the macros above.
#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
#define INTERNAL_TRACE_MEMORY(category, name) \
- base::debug::ScopedTraceMemory INTERNAL_TRACE_MEMORY_ID(category, name);
+ base::trace_event::ScopedTraceMemory INTERNAL_TRACE_MEMORY_ID(category, name);
#else
#define INTERNAL_TRACE_MEMORY(category, name)
#endif // defined(TRACE_MEMORY_SUPPORTED)
diff --git a/base/trace_event/trace_event_memory_unittest.cc b/base/trace_event/trace_event_memory_unittest.cc
index 220c0e6..4732733 100644
--- a/base/trace_event/trace_event_memory_unittest.cc
+++ b/base/trace_event/trace_event_memory_unittest.cc
@@ -16,7 +16,7 @@
#endif
namespace base {
-namespace debug {
+namespace trace_event {
// Tests for the trace event memory tracking system. Exists as a class so it
// can be a friend of TraceMemoryController.
@@ -236,5 +236,5 @@
EXPECT_STREQ(kHello, StringFromHexAddress(hex_address.str()));
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_synthetic_delay.cc b/base/trace_event/trace_event_synthetic_delay.cc
index 3651611..4b957c3 100644
--- a/base/trace_event/trace_event_synthetic_delay.cc
+++ b/base/trace_event/trace_event_synthetic_delay.cc
@@ -10,7 +10,7 @@
} // namespace
namespace base {
-namespace debug {
+namespace trace_event {
TraceEventSyntheticDelayClock::TraceEventSyntheticDelayClock() {}
TraceEventSyntheticDelayClock::~TraceEventSyntheticDelayClock() {}
@@ -200,7 +200,7 @@
TraceEventSyntheticDelayRegistry::GetInstance()->ResetAllDelays();
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
namespace trace_event_internal {
@@ -215,15 +215,16 @@
delay_impl_->EndParallel(end_time_);
}
-base::debug::TraceEventSyntheticDelay* GetOrCreateDelay(
+base::trace_event::TraceEventSyntheticDelay* GetOrCreateDelay(
const char* name,
base::subtle::AtomicWord* impl_ptr) {
- base::debug::TraceEventSyntheticDelay* delay_impl =
- reinterpret_cast<base::debug::TraceEventSyntheticDelay*>(
+ base::trace_event::TraceEventSyntheticDelay* delay_impl =
+ reinterpret_cast<base::trace_event::TraceEventSyntheticDelay*>(
base::subtle::Acquire_Load(impl_ptr));
if (!delay_impl) {
- delay_impl = base::debug::TraceEventSyntheticDelayRegistry::GetInstance()
- ->GetOrCreateDelay(name);
+ delay_impl =
+ base::trace_event::TraceEventSyntheticDelayRegistry::GetInstance()
+ ->GetOrCreateDelay(name);
base::subtle::Release_Store(
impl_ptr, reinterpret_cast<base::subtle::AtomicWord>(delay_impl));
}
diff --git a/base/trace_event/trace_event_synthetic_delay.h b/base/trace_event/trace_event_synthetic_delay.h
index b52f3b0..14801be 100644
--- a/base/trace_event/trace_event_synthetic_delay.h
+++ b/base/trace_event/trace_event_synthetic_delay.h
@@ -65,7 +65,7 @@
struct DefaultSingletonTraits;
namespace base {
-namespace debug {
+namespace trace_event {
// Time source for computing delay durations. Used for testing.
class TRACE_EVENT_API_CLASS_EXPORT TraceEventSyntheticDelayClock {
@@ -138,7 +138,7 @@
// Set the target durations of all registered synthetic delay points to zero.
TRACE_EVENT_API_CLASS_EXPORT void ResetTraceEventSyntheticDelays();
-} // namespace debug
+} // namespace trace_event
} // namespace base
namespace trace_event_internal {
@@ -151,14 +151,14 @@
~ScopedSyntheticDelay();
private:
- base::debug::TraceEventSyntheticDelay* delay_impl_;
+ base::trace_event::TraceEventSyntheticDelay* delay_impl_;
base::TimeTicks end_time_;
DISALLOW_COPY_AND_ASSIGN(ScopedSyntheticDelay);
};
// Helper for registering delays. Do not use directly.
-TRACE_EVENT_API_CLASS_EXPORT base::debug::TraceEventSyntheticDelay*
+TRACE_EVENT_API_CLASS_EXPORT base::trace_event::TraceEventSyntheticDelay*
GetOrCreateDelay(const char* name, base::subtle::AtomicWord* impl_ptr);
} // namespace trace_event_internal
diff --git a/base/trace_event/trace_event_synthetic_delay_unittest.cc b/base/trace_event/trace_event_synthetic_delay_unittest.cc
index 84ac75c..1dc0fc2 100644
--- a/base/trace_event/trace_event_synthetic_delay_unittest.cc
+++ b/base/trace_event/trace_event_synthetic_delay_unittest.cc
@@ -7,7 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
-namespace debug {
+namespace trace_event {
namespace {
const int kTargetDurationMs = 100;
@@ -150,5 +150,5 @@
EXPECT_LT((Now() - start_time).InMilliseconds(), kShortDurationMs);
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_system_stats_monitor.cc b/base/trace_event/trace_event_system_stats_monitor.cc
index 6fa0174..98f361a 100644
--- a/base/trace_event/trace_event_system_stats_monitor.cc
+++ b/base/trace_event/trace_event_system_stats_monitor.cc
@@ -16,13 +16,13 @@
#include "base/trace_event/trace_event.h"
namespace base {
-namespace debug {
+namespace trace_event {
namespace {
/////////////////////////////////////////////////////////////////////////////
// Holds profiled system stats until the tracing system needs to serialize it.
-class SystemStatsHolder : public base::debug::ConvertableToTraceFormat {
+class SystemStatsHolder : public base::trace_event::ConvertableToTraceFormat {
public:
SystemStatsHolder() { }
@@ -30,7 +30,7 @@
// Uses the previous stats to compute rates if this is not the first profile.
void GetSystemProfilingStats();
- // base::debug::ConvertableToTraceFormat overrides:
+ // base::trace_event::ConvertableToTraceFormat overrides:
void AppendAsTraceFormat(std::string* out) const override {
AppendSystemProfileAsTraceFormat(system_stats_, out);
}
@@ -129,5 +129,5 @@
*output += tmp;
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_system_stats_monitor.h b/base/trace_event/trace_event_system_stats_monitor.h
index 08fbfea..051669a 100644
--- a/base/trace_event/trace_event_system_stats_monitor.h
+++ b/base/trace_event/trace_event_system_stats_monitor.h
@@ -17,7 +17,7 @@
class SingleThreadTaskRunner;
-namespace debug {
+namespace trace_event {
// Watches for chrome://tracing to be enabled or disabled. When tracing is
// enabled, also enables system events profiling. This class is the preferred
@@ -35,7 +35,7 @@
virtual ~TraceEventSystemStatsMonitor();
- // base::debug::TraceLog::EnabledStateChangedObserver overrides:
+ // base::trace_event::TraceLog::EnabledStateChangedObserver overrides:
void OnTraceLogEnabled() override;
void OnTraceLogDisabled() override;
@@ -69,7 +69,7 @@
system_stats,
std::string* output);
-} // namespace debug
+} // namespace trace_event
} // namespace base
#endif // BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_
diff --git a/base/trace_event/trace_event_system_stats_monitor_unittest.cc b/base/trace_event/trace_event_system_stats_monitor_unittest.cc
index 143ac4a..995f53b 100644
--- a/base/trace_event/trace_event_system_stats_monitor_unittest.cc
+++ b/base/trace_event/trace_event_system_stats_monitor_unittest.cc
@@ -12,7 +12,7 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
-namespace debug {
+namespace trace_event {
#if !defined(OS_IOS)
// Tests for the system stats monitor.
@@ -62,5 +62,5 @@
}
#endif // !defined(OS_IOS)
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc
index 47b5ab6..a6bc0d4 100644
--- a/base/trace_event/trace_event_unittest.cc
+++ b/base/trace_event/trace_event_unittest.cc
@@ -25,7 +25,7 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
-namespace debug {
+namespace trace_event {
namespace {
@@ -3079,6 +3079,5 @@
}
}
-
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_win.cc b/base/trace_event/trace_event_win.cc
index d2c3dc8..ebb55c8 100644
--- a/base/trace_event/trace_event_win.cc
+++ b/base/trace_event/trace_event_win.cc
@@ -9,7 +9,7 @@
#include <initguid.h> // NOLINT
namespace base {
-namespace debug {
+namespace trace_event {
using base::win::EtwEventType;
using base::win::EtwMofEvent;
@@ -120,5 +120,5 @@
StaticMemorySingletonTraits<TraceEventETWProvider>::Resurrect();
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/trace_event/trace_event_win.h b/base/trace_event/trace_event_win.h
index e447c35..dcb5aac 100644
--- a/base/trace_event/trace_event_win.h
+++ b/base/trace_event/trace_event_win.h
@@ -17,7 +17,7 @@
struct StaticMemorySingletonTraits;
namespace base {
-namespace debug {
+namespace trace_event {
// This EtwTraceProvider subclass implements ETW logging
// for the macros above on Windows.
@@ -119,6 +119,20 @@
// Optionally the stack trace, consisting of a DWORD "depth", followed
// by an array of void* (machine bitness) of length "depth".
+} // namespace trace_event
+} // namespace base
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace base {
+namespace debug {
+using base::trace_event::kChromeTraceProviderName;
+using base::trace_event::kTraceEventClass32;
+using base::trace_event::kTraceEventClass64;
+using base::trace_event::kTraceEventTypeBegin;
+using base::trace_event::kTraceEventTypeEnd;
+using base::trace_event::kTraceEventTypeInstant;
+using base::trace_event::TraceEventETWProvider;
} // namespace debug
} // namespace base
diff --git a/base/trace_event/trace_event_win_unittest.cc b/base/trace_event/trace_event_win_unittest.cc
index a411301..7f1004e 100644
--- a/base/trace_event/trace_event_win_unittest.cc
+++ b/base/trace_event/trace_event_win_unittest.cc
@@ -20,7 +20,7 @@
#include <initguid.h> // NOLINT - must be last include.
namespace base {
-namespace debug {
+namespace trace_event {
namespace {
@@ -315,5 +315,5 @@
PlayLog();
}
-} // namespace debug
+} // namespace trace_event
} // namespace base
diff --git a/base/win/object_watcher.cc b/base/win/object_watcher.cc
index fe209f5..35609fc 100644
--- a/base/win/object_watcher.cc
+++ b/base/win/object_watcher.cc
@@ -77,7 +77,11 @@
return true;
}
-HANDLE ObjectWatcher::GetWatchedObject() {
+bool ObjectWatcher::IsWatching() const {
+ return object_ != NULL;
+}
+
+HANDLE ObjectWatcher::GetWatchedObject() const {
return object_;
}
diff --git a/base/win/object_watcher.h b/base/win/object_watcher.h
index bf7f8b3..ecd0415 100644
--- a/base/win/object_watcher.h
+++ b/base/win/object_watcher.h
@@ -74,9 +74,11 @@
//
bool StopWatching();
- // Returns the handle of the object being watched, or NULL if the object
- // watcher is stopped.
- HANDLE GetWatchedObject();
+ // Returns true if currently watching an object.
+ bool IsWatching() const;
+
+ // Returns the handle of the object being watched.
+ HANDLE GetWatchedObject() const;
private:
// Called on a background thread when done waiting.
diff --git a/base/win/object_watcher_unittest.cc b/base/win/object_watcher_unittest.cc
index 46b98de..1a5e9e2 100644
--- a/base/win/object_watcher_unittest.cc
+++ b/base/win/object_watcher_unittest.cc
@@ -37,7 +37,7 @@
MessageLoop message_loop(message_loop_type);
ObjectWatcher watcher;
- EXPECT_EQ(NULL, watcher.GetWatchedObject());
+ EXPECT_FALSE(watcher.IsWatching());
// A manual-reset event that is not yet signaled.
HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -45,13 +45,14 @@
QuitDelegate delegate;
bool ok = watcher.StartWatching(event, &delegate);
EXPECT_TRUE(ok);
+ EXPECT_TRUE(watcher.IsWatching());
EXPECT_EQ(event, watcher.GetWatchedObject());
SetEvent(event);
MessageLoop::current()->Run();
- EXPECT_EQ(NULL, watcher.GetWatchedObject());
+ EXPECT_FALSE(watcher.IsWatching());
CloseHandle(event);
}
@@ -115,7 +116,7 @@
MessageLoop::current()->Run();
- EXPECT_EQ(NULL, watcher.GetWatchedObject());
+ EXPECT_FALSE(watcher.IsWatching());
CloseHandle(event);
}
diff --git a/build/PRESUBMIT.py b/build/PRESUBMIT.py
new file mode 100644
index 0000000..3c70193
--- /dev/null
+++ b/build/PRESUBMIT.py
@@ -0,0 +1,18 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+WHITELIST = [ r'.+_test.py$' ]
+
+
+def _RunTests(input_api, output_api):
+ return (input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, '.', whitelist=[r'.+_test.py$']))
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return _RunTests(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return _RunTests(input_api, output_api)
diff --git a/build/all.gyp b/build/all.gyp
index 90c0120..8556aa7 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -750,7 +750,6 @@
'dependencies': [
'../chrome/chrome_syzygy.gyp:chrome_dll_syzygy',
'../content/content_shell_and_tests.gyp:content_shell_syzyasan',
- '../pdf/pdf.gyp:pdf_syzyasan',
],
'conditions': [
['chrome_multiple_dll==1', {
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index 7f3a868..d1daaf2 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -62,6 +62,7 @@
output_api,
unit_tests=[
J('pylib', 'device', 'device_utils_test.py'),
+ J('pylib', 'device', 'logcat_monitor_test.py'),
J('pylib', 'gtest', 'gtest_test_instance_test.py'),
J('pylib', 'instrumentation',
'instrumentation_test_instance_test.py'),
diff --git a/build/android/adb_gdb b/build/android/adb_gdb
index 97d37db..c71b816 100755
--- a/build/android/adb_gdb
+++ b/build/android/adb_gdb
@@ -26,6 +26,7 @@
TMPDIR=
GDBSERVER_PIDFILE=
TARGET_GDBSERVER=
+COMMAND_PREFIX=
clean_exit () {
if [ "$TMPDIR" ]; then
@@ -36,7 +37,7 @@
fi
if [ "$TARGET_GDBSERVER" ]; then
log "Removing target gdbserver binary: $TARGET_GDBSERVER."
- "$ADB" shell run-as "$PACKAGE_NAME" rm "$TARGET_GDBSERVER" >/dev/null 2>&1
+ "$ADB" shell "$COMMAND_PREFIX" rm "$TARGET_GDBSERVER" >/dev/null 2>&1
fi
log "Cleaning up: $TMPDIR"
rm -rf "$TMPDIR"
@@ -908,7 +909,7 @@
# Push gdbserver to the device
log "Pushing gdbserver $GDBSERVER to $TARGET_GDBSERVER"
adb push $GDBSERVER $TMP_TARGET_GDBSERVER &>/dev/null
-adb shell run-as $PACKAGE_NAME cp $TMP_TARGET_GDBSERVER .
+adb shell $COMMAND_PREFIX cp $TMP_TARGET_GDBSERVER $TARGET_GDBSERVER
adb shell rm $TMP_TARGET_GDBSERVER
fail_panic "Could not copy gdbserver to the device!"
diff --git a/build/android/finalize_apk_action.gypi b/build/android/finalize_apk_action.gypi
index 5ffbffa..9934c1a 100644
--- a/build/android/finalize_apk_action.gypi
+++ b/build/android/finalize_apk_action.gypi
@@ -12,7 +12,7 @@
# 'input_apk_path': 'relative/path/to/input.apk',
# 'output_apk_path': 'relative/path/to/output.apk',
# },
-# 'includes': [ '../../build/android/finalize_apk.gypi' ],
+# 'includes': [ '../../build/android/finalize_apk_action.gypi' ],
# },
#
@@ -34,8 +34,8 @@
],
},
'inputs': [
- '<(DEPTH)/build/android/gyp/util/build_utils.py',
'<(DEPTH)/build/android/gyp/finalize_apk.py',
+ '<(DEPTH)/build/android/gyp/util/build_utils.py',
'<(keystore_path)',
'<(input_apk_path)',
],
diff --git a/build/android/findbugs_filter/findbugs_known_bugs.txt b/build/android/findbugs_filter/findbugs_known_bugs.txt
index 5ec1107..09c12b2 100644
--- a/build/android/findbugs_filter/findbugs_known_bugs.txt
+++ b/build/android/findbugs_filter/findbugs_known_bugs.txt
@@ -5,4 +5,3 @@
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.webContents In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.originalIntent In PendingDocumentData.java
M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.url In PendingDocumentData.java
-M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.userGesture In PendingDocumentData.java
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index 1dbb1d8..7d11671 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -285,7 +285,8 @@
cmd, 'path does not specify an accessible directory in the device',
device_serial=self._device_serial)
- def Logcat(self, filter_spec=None, timeout=None):
+ def Logcat(self, clear=False, dump=False, filter_spec=None,
+ logcat_format=None, timeout=None):
"""Get an iterator over the logcat output.
Args:
@@ -296,6 +297,12 @@
logcat output line by line.
"""
cmd = ['logcat']
+ if clear:
+ cmd.append('-c')
+ if dump:
+ cmd.append('-d')
+ if logcat_format:
+ cmd.extend(['-v', logcat_format])
if filter_spec is not None:
cmd.append(filter_spec)
return self._IterRunDeviceAdbCmd(cmd, timeout)
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index 805df65..6b1a91c 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -6,7 +6,7 @@
Eventually, this will be based on adb_wrapper.
"""
-# pylint: disable=W0613
+# pylint: disable=unused-argument
import logging
import multiprocessing
@@ -24,6 +24,7 @@
from pylib.device import decorators
from pylib.device import device_errors
from pylib.device import intent
+from pylib.device import logcat_monitor
from pylib.device.commands import install_commands
from pylib.utils import apk_helper
from pylib.utils import device_temp_file
@@ -103,6 +104,9 @@
_MAX_ADB_COMMAND_LENGTH = 512
_VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
+ # Property in /data/local.prop that controls Java assertions.
+ JAVA_ASSERT_PROPERTY = 'dalvik.vm.enableassertions'
+
def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
default_retries=_DEFAULT_RETRIES):
"""DeviceUtils constructor.
@@ -350,11 +354,13 @@
@decorators.WithTimeoutAndRetriesDefaults(
REBOOT_DEFAULT_TIMEOUT,
REBOOT_DEFAULT_RETRIES)
- def Reboot(self, block=True, timeout=None, retries=None):
+ def Reboot(self, block=True, wifi=False, timeout=None, retries=None):
"""Reboot the device.
Args:
block: A boolean indicating if we should wait for the reboot to complete.
+ wifi: A boolean indicating if we should wait for wifi to be enabled after
+ the reboot. The option has no effect unless |block| is also True.
timeout: timeout in seconds
retries: number of retries
@@ -369,7 +375,7 @@
self._cache = {}
timeout_retry.WaitFor(device_offline, wait_period=1)
if block:
- self.WaitUntilFullyBooted()
+ self.WaitUntilFullyBooted(wifi=wifi)
INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT
INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES
@@ -1038,7 +1044,43 @@
Raises:
CommandTimeoutError on timeout.
"""
- return self.old_interface.SetJavaAssertsEnabled(enabled)
+ def find_property(lines, property_name):
+ for index, line in enumerate(lines):
+ key, value = (s.strip() for s in line.split('=', 1))
+ if key == property_name:
+ return index, value
+ return None, ''
+
+ new_value = 'all' if enabled else ''
+
+ # First ensure the desired property is persisted.
+ try:
+ properties = self.ReadFile(
+ constants.DEVICE_LOCAL_PROPERTIES_PATH).splitlines()
+ except device_errors.CommandFailedError:
+ properties = []
+ index, value = find_property(properties, self.JAVA_ASSERT_PROPERTY)
+ if new_value != value:
+ if new_value:
+ new_line = '%s=%s' % (self.JAVA_ASSERT_PROPERTY, new_value)
+ if index is None:
+ properties.append(new_line)
+ else:
+ properties[index] = new_line
+ else:
+ assert index is not None # since new_value == '' and new_value != value
+ properties.pop(index)
+ self.WriteFile(constants.DEVICE_LOCAL_PROPERTIES_PATH,
+ _JoinLines(properties))
+
+ # Next, check the current runtime value is what we need, and
+ # if not, set it and report that a reboot is required.
+ value = self.GetProp(self.JAVA_ASSERT_PROPERTY)
+ if new_value != value:
+ self.SetProp(self.JAVA_ASSERT_PROPERTY, new_value)
+ return True
+ else:
+ return False
@property
@@ -1288,6 +1330,19 @@
"""
return self.old_interface.GetMemoryUsageForPid(pid)
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def GetLogcatMonitor(self, timeout=None, retries=None, *args, **kwargs):
+ """Returns a new LogcatMonitor associated with this device.
+
+ Parameters passed to this function are passed directly to
+ |logcat_monitor.LogcatMonitor| and are documented there.
+
+ Args:
+ timeout: timeout in seconds
+ retries: number of retries
+ """
+ return logcat_monitor.LogcatMonitor(self.adb, *args, **kwargs)
+
def __str__(self):
"""Returns the device serial."""
return self.adb.GetDeviceSerial()
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 68c8b71..6071fd5 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -457,9 +457,17 @@
self.call.adb.Reboot(),
(self.call.device.IsOnline(), True),
(self.call.device.IsOnline(), False),
- self.call.device.WaitUntilFullyBooted()):
+ self.call.device.WaitUntilFullyBooted(wifi=False)):
self.device.Reboot(block=True)
+ def testReboot_blockUntilWifi(self):
+ with self.assertCalls(
+ self.call.adb.Reboot(),
+ (self.call.device.IsOnline(), True),
+ (self.call.device.IsOnline(), False),
+ self.call.device.WaitUntilFullyBooted(wifi=True)):
+ self.device.Reboot(block=True, wifi=True)
+
class DeviceUtilsInstallTest(DeviceUtilsNewImplTest):
@@ -1230,81 +1238,44 @@
self.device.Stat('/data/local/tmp/does.not.exist.txt')
-class DeviceUtilsSetJavaAssertsTest(DeviceUtilsOldImplTest):
-
- @staticmethod
- def mockNamedTemporary(name='/tmp/file/property.file',
- read_contents=''):
- mock_file = mock.MagicMock(spec=file)
- mock_file.name = name
- mock_file.__enter__.return_value = mock_file
- mock_file.read.return_value = read_contents
- return mock_file
+class DeviceUtilsSetJavaAssertsTest(DeviceUtilsNewImplTest):
def testSetJavaAsserts_enable(self):
- mock_file = self.mockNamedTemporary()
- with mock.patch('tempfile.NamedTemporaryFile',
- return_value=mock_file), (
- mock.patch('__builtin__.open', return_value=mock_file)):
- with self.assertCallsSequence(
- [('adb -s 0123456789abcdef shell ls %s' %
- constants.DEVICE_LOCAL_PROPERTIES_PATH,
- '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH),
- ('adb -s 0123456789abcdef pull %s %s' %
- (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name),
- '100 B/s (100 bytes in 1.000s)\r\n'),
- ('adb -s 0123456789abcdef push %s %s' %
- (mock_file.name, constants.DEVICE_LOCAL_PROPERTIES_PATH),
- '100 B/s (100 bytes in 1.000s)\r\n'),
- ('adb -s 0123456789abcdef shell '
- 'getprop dalvik.vm.enableassertions',
- '\r\n'),
- ('adb -s 0123456789abcdef shell '
- 'setprop dalvik.vm.enableassertions "all"',
- '')]):
- self.assertTrue(self.device.SetJavaAsserts(True))
+ with self.assertCalls(
+ (self.call.device.ReadFile(constants.DEVICE_LOCAL_PROPERTIES_PATH),
+ 'some.example.prop=with an example value\n'
+ 'some.other.prop=value_ok\n'),
+ self.call.device.WriteFile(
+ constants.DEVICE_LOCAL_PROPERTIES_PATH,
+ 'some.example.prop=with an example value\n'
+ 'some.other.prop=value_ok\n'
+ 'dalvik.vm.enableassertions=all\n'),
+ (self.call.device.GetProp('dalvik.vm.enableassertions'), ''),
+ self.call.device.SetProp('dalvik.vm.enableassertions', 'all')):
+ self.assertTrue(self.device.SetJavaAsserts(True))
def testSetJavaAsserts_disable(self):
- mock_file = self.mockNamedTemporary(
- read_contents='dalvik.vm.enableassertions=all\n')
- with mock.patch('tempfile.NamedTemporaryFile',
- return_value=mock_file), (
- mock.patch('__builtin__.open', return_value=mock_file)):
- with self.assertCallsSequence(
- [('adb -s 0123456789abcdef shell ls %s' %
- constants.DEVICE_LOCAL_PROPERTIES_PATH,
- '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH),
- ('adb -s 0123456789abcdef pull %s %s' %
- (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name),
- '100 B/s (100 bytes in 1.000s)\r\n'),
- ('adb -s 0123456789abcdef push %s %s' %
- (mock_file.name, constants.DEVICE_LOCAL_PROPERTIES_PATH),
- '100 B/s (100 bytes in 1.000s)\r\n'),
- ('adb -s 0123456789abcdef shell '
- 'getprop dalvik.vm.enableassertions',
- 'all\r\n'),
- ('adb -s 0123456789abcdef shell '
- 'setprop dalvik.vm.enableassertions ""',
- '')]):
- self.assertTrue(self.device.SetJavaAsserts(False))
+ with self.assertCalls(
+ (self.call.device.ReadFile(constants.DEVICE_LOCAL_PROPERTIES_PATH),
+ 'some.example.prop=with an example value\n'
+ 'dalvik.vm.enableassertions=all\n'
+ 'some.other.prop=value_ok\n'),
+ self.call.device.WriteFile(
+ constants.DEVICE_LOCAL_PROPERTIES_PATH,
+ 'some.example.prop=with an example value\n'
+ 'some.other.prop=value_ok\n'),
+ (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all'),
+ self.call.device.SetProp('dalvik.vm.enableassertions', '')):
+ self.assertTrue(self.device.SetJavaAsserts(False))
def testSetJavaAsserts_alreadyEnabled(self):
- mock_file = self.mockNamedTemporary(
- read_contents='dalvik.vm.enableassertions=all\n')
- with mock.patch('tempfile.NamedTemporaryFile',
- return_value=mock_file), (
- mock.patch('__builtin__.open', return_value=mock_file)):
- with self.assertCallsSequence(
- [('adb -s 0123456789abcdef shell ls %s' %
- constants.DEVICE_LOCAL_PROPERTIES_PATH,
- '%s\r\n' % constants.DEVICE_LOCAL_PROPERTIES_PATH),
- ('adb -s 0123456789abcdef pull %s %s' %
- (constants.DEVICE_LOCAL_PROPERTIES_PATH, mock_file.name),
- '100 B/s (100 bytes in 1.000s)\r\n'),
- ('adb -s 0123456789abcdef shell '
- 'getprop dalvik.vm.enableassertions',
- 'all\r\n')]):
- self.assertFalse(self.device.SetJavaAsserts(True))
+ with self.assertCalls(
+ (self.call.device.ReadFile(constants.DEVICE_LOCAL_PROPERTIES_PATH),
+ 'some.example.prop=with an example value\n'
+ 'dalvik.vm.enableassertions=all\n'
+ 'some.other.prop=value_ok\n'),
+ (self.call.device.GetProp('dalvik.vm.enableassertions'), 'all')):
+ self.assertFalse(self.device.SetJavaAsserts(True))
class DeviceUtilsGetPropTest(DeviceUtilsNewImplTest):
diff --git a/build/android/pylib/device/logcat_monitor.py b/build/android/pylib/device/logcat_monitor.py
new file mode 100644
index 0000000..7ede49c
--- /dev/null
+++ b/build/android/pylib/device/logcat_monitor.py
@@ -0,0 +1,143 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=unused-argument
+
+import collections
+import itertools
+import logging
+import subprocess
+import tempfile
+import time
+import re
+
+from pylib.device import adb_wrapper
+from pylib.device import decorators
+from pylib.device import device_errors
+
+
+class LogcatMonitor(object):
+
+ # Format: <DATE> <TIME> <PID> <TID> <LEVEL> <COMPONENT>: <MESSAGE>
+ _THREADTIME_RE_FORMAT = r'\S* +\S* +(%s) +(%s) +(%s) +(%s): +(%s)$'
+
+ def __init__(self, adb, clear=True):
+ """Create a LogcatMonitor instance.
+
+ Args:
+ adb: An instance of adb_wrapper.AdbWrapper.
+ clear: If True, clear the logcat when monitoring starts.
+ """
+ if isinstance(adb, adb_wrapper.AdbWrapper):
+ self._adb = adb
+ else:
+ raise ValueError('Unsupported type passed for argument "device"')
+ self._clear = clear
+ self._logcat_out = None
+ self._logcat_out_file = None
+ self._logcat_proc = None
+
+ @decorators.WithTimeoutAndRetriesDefaults(10, 0)
+ def WaitFor(self, success_regex, failure_regex=None, timeout=None,
+ retries=None):
+ """Wait for a matching logcat line or until a timeout occurs.
+
+ This will attempt to match lines in the logcat against both |success_regex|
+ and |failure_regex| (if provided). Note that this calls re.search on each
+ logcat line, not re.match, so the provided regular expressions don't have
+ to match an entire line.
+
+ Args:
+ success_regex: The regular expression to search for.
+ failure_regex: An optional regular expression that, if hit, causes this
+ to stop looking for a match. Can be None.
+ timeout: timeout in seconds
+ retries: number of retries
+
+ Returns:
+ A match object if |success_regex| matches a part of a logcat line, or
+ None if |failure_regex| matches a part of a logcat line.
+ Raises:
+ CommandFailedError on logcat failure (NOT on a |failure_regex| match).
+ CommandTimeoutError if no logcat line matching either |success_regex| or
+ |failure_regex| is found in |timeout| seconds.
+ DeviceUnreachableError if the device becomes unreachable.
+ """
+ if isinstance(success_regex, basestring):
+ success_regex = re.compile(success_regex)
+ if isinstance(failure_regex, basestring):
+ failure_regex = re.compile(failure_regex)
+
+ logging.debug('Waiting %d seconds for "%s"', timeout, success_regex.pattern)
+
+ # NOTE This will continue looping until:
+ # - success_regex matches a line, in which case the match object is
+ # returned.
+ # - failure_regex matches a line, in which case None is returned
+ # - the timeout is hit, in which case a CommandTimeoutError is raised.
+ for l in self._adb.Logcat():
+ m = success_regex.search(l)
+ if m:
+ return m
+ if failure_regex and failure_regex.search(l):
+ return None
+
+ def FindAll(self, message_regex, proc_id=None, thread_id=None, log_level=None,
+ component=None):
+ """Finds all lines in the logcat that match the provided constraints.
+
+ Args:
+ message_regex: The regular expression that the <message> section must
+ match.
+ proc_id: The process ID to match. If None, matches any process ID.
+ thread_id: The thread ID to match. If None, matches any thread ID.
+ log_level: The log level to match. If None, matches any log level.
+ component: The component to match. If None, matches any component.
+
+ Returns:
+ An iterable containing objects with five attributes:
+ |proc_id|: the process ID
+ |thread_id|: the thread ID
+ |log_level|: the log level
+ |component|: the component
+ |message|: the logcat message
+ """
+ LogcatLine = collections.namedtuple(
+ 'LogcatLine',
+ ['proc_id', 'thread_id', 'log_level', 'component', 'message'])
+
+ if proc_id is None:
+ proc_id = r'\d+'
+ if thread_id is None:
+ thread_id = r'\d+'
+ if log_level is None:
+ log_level = r'[VDIWEF]'
+ if component is None:
+ component = r'[^\s:]+'
+ threadtime_re = re.compile(
+ type(self)._THREADTIME_RE_FORMAT % (
+ proc_id, thread_id, log_level, component, message_regex))
+
+ regexed_lines = (
+ re.match(threadtime_re, l)
+ for l in self._adb.Logcat(dump=True, logcat_format='threadtime'))
+ only_matches = (m for m in regexed_lines if m)
+ return (LogcatLine(*m.group(1, 2, 3, 4, 5)) for m in only_matches)
+
+ def Start(self):
+ """Starts the logcat monitor.
+
+ Clears the logcat if |clear| was set in |__init__|.
+ """
+ if self._clear:
+ self._adb.Logcat(clear=True)
+
+ def __enter__(self):
+ """Starts the logcat monitor."""
+ self.Start()
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ """Stops the logcat monitor."""
+ pass
diff --git a/build/android/pylib/device/logcat_monitor_test.py b/build/android/pylib/device/logcat_monitor_test.py
new file mode 100755
index 0000000..7a6bf56
--- /dev/null
+++ b/build/android/pylib/device/logcat_monitor_test.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import itertools
+import os
+import sys
+import unittest
+
+from pylib import constants
+from pylib.device import adb_wrapper
+from pylib.device import decorators
+from pylib.device import logcat_monitor
+
+sys.path.append(os.path.join(
+ constants.DIR_SOURCE_ROOT, 'third_party', 'pymock'))
+import mock # pylint: disable=F0401
+
+
+class LogcatMonitorTest(unittest.TestCase):
+
+ _TEST_THREADTIME_LOGCAT_DATA = [
+ '01-01 01:02:03.456 7890 0987 V LogcatMonitorTest: '
+ 'verbose logcat monitor test message 1',
+ '01-01 01:02:03.457 8901 1098 D LogcatMonitorTest: '
+ 'debug logcat monitor test message 2',
+ '01-01 01:02:03.458 9012 2109 I LogcatMonitorTest: '
+ 'info logcat monitor test message 3',
+ '01-01 01:02:03.459 0123 3210 W LogcatMonitorTest: '
+ 'warning logcat monitor test message 4',
+ '01-01 01:02:03.460 1234 4321 E LogcatMonitorTest: '
+ 'error logcat monitor test message 5',
+ '01-01 01:02:03.461 2345 5432 F LogcatMonitorTest: '
+ 'fatal logcat monitor test message 6',
+ '01-01 01:02:03.462 3456 6543 D LogcatMonitorTest: '
+ 'ignore me',]
+
+ def _createTestLog(self, raw_logcat=None):
+ test_adb = adb_wrapper.AdbWrapper('0123456789abcdef')
+ test_adb.Logcat = mock.Mock(return_value=(l for l in raw_logcat))
+ test_log = logcat_monitor.LogcatMonitor(test_adb, clear=False)
+ return test_log
+
+ def assertIterEqual(self, expected_iter, actual_iter):
+ for expected, actual in itertools.izip_longest(expected_iter, actual_iter):
+ self.assertIsNotNone(
+ expected,
+ msg='actual has unexpected elements starting with %s' % str(actual))
+ self.assertIsNotNone(
+ actual,
+ msg='actual is missing elements starting with %s' % str(expected))
+ self.assertEqual(actual.proc_id, expected[0])
+ self.assertEqual(actual.thread_id, expected[1])
+ self.assertEqual(actual.log_level, expected[2])
+ self.assertEqual(actual.component, expected[3])
+ self.assertEqual(actual.message, expected[4])
+
+ with self.assertRaises(StopIteration):
+ next(actual_iter)
+ with self.assertRaises(StopIteration):
+ next(expected_iter)
+
+ def testWaitFor_success(self):
+ test_log = self._createTestLog(
+ raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+ actual_match = test_log.WaitFor(r'.*(fatal|error) logcat monitor.*', None)
+ self.assertTrue(actual_match)
+ self.assertEqual(
+ '01-01 01:02:03.460 1234 4321 E LogcatMonitorTest: '
+ 'error logcat monitor test message 5',
+ actual_match.group(0))
+ self.assertEqual('error', actual_match.group(1))
+
+ def testWaitFor_failure(self):
+ test_log = self._createTestLog(
+ raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+ actual_match = test_log.WaitFor(
+ r'.*My Success Regex.*', r'.*(fatal|error) logcat monitor.*')
+ self.assertIsNone(actual_match)
+
+ def testFindAll_defaults(self):
+ test_log = self._createTestLog(
+ raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+ expected_results = [
+ ('7890', '0987', 'V', 'LogcatMonitorTest',
+ 'verbose logcat monitor test message 1'),
+ ('8901', '1098', 'D', 'LogcatMonitorTest',
+ 'debug logcat monitor test message 2'),
+ ('9012', '2109', 'I', 'LogcatMonitorTest',
+ 'info logcat monitor test message 3'),
+ ('0123', '3210', 'W', 'LogcatMonitorTest',
+ 'warning logcat monitor test message 4'),
+ ('1234', '4321', 'E', 'LogcatMonitorTest',
+ 'error logcat monitor test message 5'),
+ ('2345', '5432', 'F', 'LogcatMonitorTest',
+ 'fatal logcat monitor test message 6')]
+ actual_results = test_log.FindAll(r'\S* logcat monitor test message \d')
+ self.assertIterEqual(iter(expected_results), actual_results)
+
+ def testFindAll_defaults_miss(self):
+ test_log = self._createTestLog(
+ raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+ expected_results = []
+ actual_results = test_log.FindAll(r'\S* nothing should match this \d')
+ self.assertIterEqual(iter(expected_results), actual_results)
+
+ def testFindAll_filterProcId(self):
+ test_log = self._createTestLog(
+ raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+ actual_results = test_log.FindAll(
+ r'\S* logcat monitor test message \d', proc_id=1234)
+ expected_results = [
+ ('1234', '4321', 'E', 'LogcatMonitorTest',
+ 'error logcat monitor test message 5')]
+ self.assertIterEqual(iter(expected_results), actual_results)
+
+ def testFindAll_filterThreadId(self):
+ test_log = self._createTestLog(
+ raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+ actual_results = test_log.FindAll(
+ r'\S* logcat monitor test message \d', thread_id=2109)
+ expected_results = [
+ ('9012', '2109', 'I', 'LogcatMonitorTest',
+ 'info logcat monitor test message 3')]
+ self.assertIterEqual(iter(expected_results), actual_results)
+
+ def testFindAll_filterLogLevel(self):
+ test_log = self._createTestLog(
+ raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+ actual_results = test_log.FindAll(
+ r'\S* logcat monitor test message \d', log_level=r'[DW]')
+ expected_results = [
+ ('8901', '1098', 'D', 'LogcatMonitorTest',
+ 'debug logcat monitor test message 2'),
+ ('0123', '3210', 'W', 'LogcatMonitorTest',
+ 'warning logcat monitor test message 4'),]
+ self.assertIterEqual(iter(expected_results), actual_results)
+
+ def testFindAll_filterComponent(self):
+ test_log = self._createTestLog(
+ raw_logcat=type(self)._TEST_THREADTIME_LOGCAT_DATA)
+ actual_results = test_log.FindAll(r'.*', component='LogcatMonitorTest')
+ expected_results = [
+ ('7890', '0987', 'V', 'LogcatMonitorTest',
+ 'verbose logcat monitor test message 1'),
+ ('8901', '1098', 'D', 'LogcatMonitorTest',
+ 'debug logcat monitor test message 2'),
+ ('9012', '2109', 'I', 'LogcatMonitorTest',
+ 'info logcat monitor test message 3'),
+ ('0123', '3210', 'W', 'LogcatMonitorTest',
+ 'warning logcat monitor test message 4'),
+ ('1234', '4321', 'E', 'LogcatMonitorTest',
+ 'error logcat monitor test message 5'),
+ ('2345', '5432', 'F', 'LogcatMonitorTest',
+ 'fatal logcat monitor test message 6'),
+ ('3456', '6543', 'D', 'LogcatMonitorTest',
+ 'ignore me'),]
+ self.assertIterEqual(iter(expected_results), actual_results)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
+
diff --git a/build/android/pylib/gtest/filter/unit_tests_disabled b/build/android/pylib/gtest/filter/unit_tests_disabled
index 93defbe..c7851fd 100644
--- a/build/android/pylib/gtest/filter/unit_tests_disabled
+++ b/build/android/pylib/gtest/filter/unit_tests_disabled
@@ -1,10 +1,5 @@
# List of suppressions
-# crbug.com/139429
-BrowserMainTest.WarmConnectionFieldTrial_Invalid
-BrowserMainTest.WarmConnectionFieldTrial_Random
-BrowserMainTest.WarmConnectionFieldTrial_WarmestSocket
-
# The UDP related tests currently do not work on Android because
# we lack a UDP forwarder tool.
NetworkStatsTestUDP.*
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index 424dcb3..fb9557e 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -51,6 +51,7 @@
super(TestRunner, self).__init__(device, test_options.tool,
test_options.cleanup_test_files)
self._lighttp_port = constants.LIGHTTPD_RANDOM_PORT_FIRST + shard_index
+ self._logcat_monitor = None
self.coverage_device_file = None
self.coverage_dir = test_options.coverage_dir
@@ -174,9 +175,10 @@
"""
if not self._IsPerfTest(test):
return
- self.device.old_interface.Adb().SendCommand(
- 'shell rm ' + TestRunner._DEVICE_PERF_OUTPUT_SEARCH_PREFIX)
- self.device.old_interface.StartMonitoringLogcat()
+ self.device.RunShellCommand(
+ ['rm', TestRunner._DEVICE_PERF_OUTPUT_SEARCH_PREFIX])
+ self._logcat_monitor = self.device.GetLogcatMonitor()
+ self._logcat_monitor.Start()
def TestTeardown(self, test, result):
"""Cleans up the test harness after running a particular test.
@@ -219,9 +221,8 @@
raw_test_name = test.split('#')[1]
# Wait and grab annotation data so we can figure out which traces to parse
- regex = self.device.old_interface.WaitForLogMatch(
- re.compile(r'\*\*PERFANNOTATION\(' + raw_test_name + r'\)\:(.*)'),
- None)
+ regex = self._logcat_monitor.WaitFor(
+ re.compile(r'\*\*PERFANNOTATION\(' + raw_test_name + r'\)\:(.*)'))
# If the test is set to run on a specific device type only (IE: only
# tablet or phone) and it is being run on the wrong device, the test
diff --git a/build/android/pylib/linker/test_case.py b/build/android/pylib/linker/test_case.py
index 13f68cb..8ebf803 100644
--- a/build/android/pylib/linker/test_case.py
+++ b/build/android/pylib/linker/test_case.py
@@ -42,6 +42,7 @@
from pylib import constants
from pylib.base import base_test_result
+from pylib.device import device_errors
from pylib.device import intent
@@ -70,10 +71,11 @@
#_LOGCAT_FILTERS = ['*:v'] ## DEBUG
# Regular expression used to match status lines in logcat.
-re_status_line = re.compile(r'(BROWSER|RENDERER)_LINKER_TEST: (FAIL|SUCCESS)')
+_RE_BROWSER_STATUS_LINE = re.compile(r' BROWSER_LINKER_TEST: (FAIL|SUCCESS)$')
+_RE_RENDERER_STATUS_LINE = re.compile(r' RENDERER_LINKER_TEST: (FAIL|SUCCESS)$')
# Regular expression used to mach library load addresses in logcat.
-re_library_address = re.compile(
+_RE_LIBRARY_ADDRESS = re.compile(
r'(BROWSER|RENDERER)_LIBRARY_ADDRESS: (\S+) ([0-9A-Fa-f]+)')
@@ -109,46 +111,6 @@
return configs[0]
-def _WriteCommandLineFile(device, command_line, command_line_file):
- """Create a command-line file on the device. This does not use FlagChanger
- because its implementation assumes the device has 'su', and thus does
- not work at all with production devices."""
- device.RunShellCommand(
- 'echo "%s" > %s' % (command_line, command_line_file))
-
-
-def _CheckLinkerTestStatus(logcat):
- """Parse the content of |logcat| and checks for both a browser and
- renderer status line.
-
- Args:
- logcat: A string to parse. Can include line separators.
-
- Returns:
- A tuple, result[0] is True if there is a complete match, then
- result[1] and result[2] will be True or False to reflect the
- test status for the browser and renderer processes, respectively.
- """
- browser_found = False
- renderer_found = False
- for m in re_status_line.finditer(logcat):
- process_type, status = m.groups()
- if process_type == 'BROWSER':
- browser_found = True
- browser_success = (status == 'SUCCESS')
- elif process_type == 'RENDERER':
- renderer_found = True
- renderer_success = (status == 'SUCCESS')
- else:
- assert False, 'Invalid process type ' + process_type
-
- if browser_found and renderer_found:
- return (True, browser_success, renderer_success)
-
- # Didn't find anything.
- return (False, None, None)
-
-
def _StartActivityAndWaitForLinkerTestStatus(device, timeout):
"""Force-start an activity and wait up to |timeout| seconds until the full
linker test status lines appear in the logcat, recorded through |device|.
@@ -159,38 +121,30 @@
A (status, logs) tuple, where status is a ResultType constant, and logs
if the final logcat output as a string.
"""
- # 1. Start recording logcat with appropriate filters.
- device.old_interface.StartRecordingLogcat(
- clear=True, filters=_LOGCAT_FILTERS)
- try:
+ # 1. Start recording logcat with appropriate filters.
+ with device.GetLogcatMonitor(filters=_LOGCAT_FILTERS) as logmon:
+
# 2. Force-start activity.
device.StartActivity(
intent.Intent(package=_PACKAGE_NAME, activity=_ACTIVITY_NAME),
force_stop=True)
# 3. Wait up to |timeout| seconds until the test status is in the logcat.
- num_tries = 0
- max_tries = timeout
- found = False
- while num_tries < max_tries:
- time.sleep(1)
- num_tries += 1
- found, browser_ok, renderer_ok = _CheckLinkerTestStatus(
- device.old_interface.GetCurrentRecordedLogcat())
- if found:
- break
+ result = ResultType.PASS
+ try:
+ browser_match = logmon.WaitFor(_RE_BROWSER_STATUS_LINE, timeout=timeout)
+ logging.debug('Found browser match: %s', browser_match.group(0))
+ renderer_match = logmon.WaitFor(_RE_RENDERER_STATUS_LINE,
+ timeout=timeout)
+ logging.debug('Found renderer match: %s', renderer_match.group(0))
+ if (browser_match.group(1) != 'SUCCESS'
+ or renderer_match.group(1) != 'SUCCESS'):
+ result = ResultType.FAIL
+ except device_errors.CommandTimeoutError:
+ result = ResultType.TIMEOUT
- finally:
- logs = device.old_interface.StopRecordingLogcat()
-
- if num_tries >= max_tries:
- return ResultType.TIMEOUT, logs
-
- if browser_ok and renderer_ok:
- return ResultType.PASS, logs
-
- return ResultType.FAIL, logs
+ return result, '\n'.join(device.adb.Logcat(dump=True))
class LibraryLoadMap(dict):
@@ -226,7 +180,7 @@
"""
browser_libs = LibraryLoadMap()
renderer_libs = LibraryLoadMap()
- for m in re_library_address.finditer(logs):
+ for m in _RE_LIBRARY_ADDRESS.finditer(logs):
process_type, lib_name, lib_address = m.groups()
lib_address = int(lib_address, 16)
if process_type == 'BROWSER':
@@ -323,7 +277,7 @@
command_line_flags = ''
if self.is_low_memory:
command_line_flags = '--low-memory-device'
- _WriteCommandLineFile(device, command_line_flags, _COMMAND_LINE_FILE)
+ device.WriteFile(_COMMAND_LINE_FILE, command_line_flags)
# Run the test.
status, logs = self._RunTest(device)
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py
index a701d95..cc39112 100644
--- a/build/android/pylib/remote/device/remote_device_environment.py
+++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -4,6 +4,8 @@
"""Environment setup and teardown for remote devices."""
+import distutils.version
+import json
import logging
import os
import random
@@ -28,50 +30,138 @@
error_func: error to show when using bad command line arguments.
"""
super(RemoteDeviceEnvironment, self).__init__()
-
- if args.api_key_file:
- with open(args.api_key_file) as api_key_file:
- self._api_key = api_key_file.read().strip()
- elif args.api_key:
- self._api_key = args.api_key
- else:
- error_func('Must set api key with --api-key or --api-key-file')
-
- if args.api_secret_file:
- with open(args.api_secret_file) as api_secret_file:
- self._api_secret = api_secret_file.read().strip()
- elif args.api_secret:
- self._api_secret = args.api_secret
- else:
- error_func('Must set api secret with --api-secret or --api-secret-file')
-
- if not args.api_protocol:
- error_func('Must set api protocol with --api-protocol. Example: http')
- self._api_protocol = args.api_protocol
-
- if not args.api_address:
- error_func('Must set api address with --api-address')
- self._api_address = args.api_address
-
- if not args.api_port:
- error_func('Must set api port with --api-port.')
- self._api_port = args.api_port
-
- self._access_token = ''
- self._results_path = args.results_path
- self._remote_device = args.remote_device
- self._remote_device_os = args.remote_device_os
- self._runner_package = args.runner_package
- self._runner_type = args.runner_type
- self._device = ''
- self._verbose_count = args.verbose_count
+ self._access_token = None
+ self._device = None
self._device_type = args.device_type
+ self._verbose_count = args.verbose_count
self._timeouts = {
'queueing': 60 * 10,
'installing': 60 * 10,
'in-progress': 60 * 30,
'unknown': 60 * 5
}
+ # Example config file:
+ # {
+ # "remote_device": ["Galaxy S4", "Galaxy S3"],
+ # "remote_device_os": ["4.4.2", "4.4.4"],
+ # "remote_device_minimum_os": "4.4.2",
+ # "api_address": "www.example.com",
+ # "api_port": "80",
+ # "api_protocol": "http",
+ # "api_secret": "apisecret",
+ # "api_key": "apikey",
+ # "timeouts": {
+ # "queueing": 600,
+ # "installing": 600,
+ # "in-progress": 1800,
+ # "unknown": 300
+ # }
+ # }
+ if args.remote_device_file:
+ with open(args.remote_device_file) as device_file:
+ device_json = json.load(device_file)
+ else:
+ device_json = {}
+
+ self._api_address = device_json.get('api_address', None)
+ self._api_key = device_json.get('api_key', None)
+ self._api_port = device_json.get('api_port', None)
+ self._api_protocol = device_json.get('api_protocol', None)
+ self._api_secret = device_json.get('api_secret', None)
+ self._device_oem = device_json.get('device_oem', None)
+ self._device_type = device_json.get('device_type', 'Android')
+ self._remote_device = device_json.get('remote_device', None)
+ self._remote_device_minimum_os = device_json.get(
+ 'remote_device_minimum_os', None)
+ self._remote_device_os = device_json.get('remote_device_os', None)
+ self._results_path = device_json.get('results_path', None)
+ self._runner_package = device_json.get('runner_package', None)
+ self._runner_type = device_json.get('runner_type', None)
+ if 'timeouts' in device_json:
+ for key in device_json['timeouts']:
+ self._timeouts[key] = device_json['timeouts'][key]
+
+ def command_line_override(
+ file_value, cmd_line_value, desc, print_value=True):
+ if cmd_line_value:
+ if file_value and file_value != cmd_line_value:
+ if print_value:
+ logging.info('Overriding %s from %s to %s',
+ desc, file_value, cmd_line_value)
+ else:
+ logging.info('overriding %s', desc)
+ return cmd_line_value
+ return file_value
+
+ self._api_address = command_line_override(
+ self._api_address, args.api_address, 'api_address')
+ self._api_port = command_line_override(
+ self._api_port, args.api_port, 'api_port')
+ self._api_protocol = command_line_override(
+ self._api_protocol, args.api_protocol, 'api_protocol')
+ self._device_oem = command_line_override(
+ self._device_oem, args.device_oem, 'device_oem')
+ self._device_type = command_line_override(
+ self._device_type, args.device_type, 'device_type')
+ self._remote_device = command_line_override(
+ self._remote_device, args.remote_device, 'remote_device')
+ self._remote_device_minimum_os = command_line_override(
+ self._remote_device_minimum_os, args.remote_device_minimum_os,
+ 'remote_device_minimum_os')
+ self._remote_device_os = command_line_override(
+ self._remote_device_os, args.remote_device_os, 'remote_device_os')
+ self._results_path = command_line_override(
+ self._results_path, args.results_path, 'results_path')
+ self._runner_package = command_line_override(
+ self._runner_package, args.runner_package, 'runner_package')
+ self._runner_type = command_line_override(
+ self._runner_type, args.runner_type, 'runner_type')
+
+ if args.api_key_file:
+ with open(args.api_key_file) as api_key_file:
+ temp_key = api_key_file.read().strip()
+ self._api_key = command_line_override(
+ self._api_key, temp_key, 'api_key', print_value=False)
+ self._api_key = command_line_override(
+ self._api_key, args.api_key, 'api_key', print_value=False)
+
+ if args.api_secret_file:
+ with open(args.api_secret_file) as api_secret_file:
+ temp_secret = api_secret_file.read().strip()
+ self._api_secret = command_line_override(
+ self._api_secret, temp_secret, 'api_secret', print_value=False)
+ self._api_secret = command_line_override(
+ self._api_secret, args.api_secret, 'api_secret', print_value=False)
+
+ if not self._api_address:
+ error_func('Must set api address with --api-address'
+ ' or in --remote-device-file.')
+ if not self._api_key:
+ error_func('Must set api key with --api-key, --api-key-file'
+ ' or in --remote-device-file')
+ if not self._api_port:
+ error_func('Must set api port with --api-port'
+ ' or in --remote-device-file')
+ if not self._api_protocol:
+ error_func('Must set api protocol with --api-protocol'
+ ' or in --remote-device-file. Example: http')
+ if not self._api_secret:
+ error_func('Must set api secret with --api-secret, --api-secret-file'
+ ' or in --remote-device-file')
+
+ logging.info('Api address: %s', self._api_address)
+ logging.info('Api port: %s', self._api_port)
+ logging.info('Api protocol: %s', self._api_protocol)
+ logging.info('Remote device: %s', self._remote_device)
+ logging.info('Remote device minimum OS: %s',
+ self._remote_device_minimum_os)
+ logging.info('Remote device OS: %s', self._remote_device_os)
+ logging.info('Remote device OEM: %s', self._device_oem)
+ logging.info('Remote device type: %s', self._device_type)
+ logging.info('Results Path: %s', self._results_path)
+ logging.info('Runner package: %s', self._runner_package)
+ logging.info('Runner type: %s', self._runner_type)
+ logging.info('Timeouts: %s', self._timeouts)
if not args.trigger and not args.collect:
self._trigger = True
@@ -150,10 +240,16 @@
for device in device_list:
if device['os_name'] != self._device_type:
continue
- if self._remote_device and device['name'] != self._remote_device:
+ if self._remote_device and device['name'] not in self._remote_device:
continue
if (self._remote_device_os
- and device['os_version'] != self._remote_device_os):
+ and device['os_version'] not in self._remote_device_os):
+ continue
+ if self._device_oem and device['brand'] not in self._device_oem:
+ continue
+ if (self._remote_device_minimum_os
+ and distutils.version.LooseVersion(device['os_version'])
+ < distutils.version.LooseVersion(self._remote_device_minimum_os)):
continue
if ((self._remote_device and self._remote_device_os)
or device['available_devices_count']):
diff --git a/build/android/pylib/remote/device/remote_device_test_run.py b/build/android/pylib/remote/device/remote_device_test_run.py
index 0b2deae..91701b0 100644
--- a/build/android/pylib/remote/device/remote_device_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -49,7 +49,7 @@
if self._env.trigger:
self._TriggerSetUp()
elif self._env.collect:
- assert isinstance(self._env.trigger, basestring), (
+ assert isinstance(self._env.collect, basestring), (
'File for storing test_run_id must be a string.')
with open(self._env.collect, 'r') as persisted_data_file:
persisted_data = json.loads(persisted_data_file.read())
diff --git a/build/android/pylib/uirobot/uirobot_test_instance.py b/build/android/pylib/uirobot/uirobot_test_instance.py
index f73c569..e3f6eb7 100644
--- a/build/android/pylib/uirobot/uirobot_test_instance.py
+++ b/build/android/pylib/uirobot/uirobot_test_instance.py
@@ -3,6 +3,8 @@
# found in the LICENSE file.
import os
+import json
+import logging
from pylib import constants
from pylib.base import test_instance
@@ -20,16 +22,27 @@
if not args.app_under_test:
error_func('Must set --app-under-test.')
self._app_under_test = args.app_under_test
+ self._minutes = args.minutes
- if args.device_type == 'Android':
+ if args.remote_device_file:
+ with open(args.remote_device_file) as remote_device_file:
+ device_json = json.load(remote_device_file)
+ else:
+ device_json = {}
+ device_type = device_json.get('device_type', 'Android')
+ if args.device_type:
+ if device_type and device_type != args.device_type:
+ logging.info('Overriding device_type from %s to %s',
+ device_type, args.device_type)
+ device_type = args.device_type
+
+ if device_type == 'Android':
self._suite = 'Android Uirobot'
self._package_name = apk_helper.GetPackageName(self._app_under_test)
-
- elif args.device_type == 'iOS':
+ elif device_type == 'iOS':
self._suite = 'iOS Uirobot'
self._package_name = self._app_under_test
- self._minutes = args.minutes
#override
def TestType(self):
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py
index afbee2a..845d093 100644
--- a/build/android/pylib/utils/isolator.py
+++ b/build/android/pylib/utils/isolator.py
@@ -33,8 +33,12 @@
'fastbuild': '0',
'icu_use_data_file_flag': '1',
'lsan': '0',
+ 'msan': '0',
# TODO(maruel): This may not always be true.
'target_arch': 'arm',
+ 'tsan': '0',
+ 'use_custom_libcxx': '0',
+ 'use_instrumented_libraries': '0',
'use_openssl': '0',
'use_ozone': '0',
'v8_use_external_startup_data': '0',
diff --git a/build/android/setup.gyp b/build/android/setup.gyp
index 7dce19d..b3c3422 100644
--- a/build/android/setup.gyp
+++ b/build/android/setup.gyp
@@ -16,7 +16,7 @@
{
'destination': '<(SHARED_LIB_DIR)/',
'files': [
- '<(android_stlport_libs_dir)/libstlport_shared.so',
+ '<(android_libcpp_libs_dir)/libc++_shared.so',
],
},
],
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index bc0980e..cc7bbee 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -121,28 +121,40 @@
def AddRemoteDeviceOptions(parser):
group = parser.add_argument_group('Remote Device Options')
- group.add_argument('--trigger', default='',
+ group.add_argument('--trigger',
help=('Only triggers the test if set. Stores test_run_id '
'in given file path. '))
- group.add_argument('--collect', default='',
+ group.add_argument('--collect',
help=('Only collects the test results if set. '
'Gets test_run_id from given file path.'))
- group.add_argument('--remote-device', default='',
+ group.add_argument('--remote-device', action='append',
help='Device type to run test on.')
- group.add_argument('--remote-device-os', default='',
- help='OS to have on the device.')
- group.add_argument('--results-path', default='',
+ group.add_argument('--results-path',
help='File path to download results to.')
group.add_argument('--api-protocol',
help='HTTP protocol to use. (http or https)')
- group.add_argument('--api-address', help='Address to send HTTP requests.')
- group.add_argument('--api-port', help='Port to send HTTP requests to.')
- group.add_argument('--runner-type', default='',
+ group.add_argument('--api-address',
+ help='Address to send HTTP requests.')
+ group.add_argument('--api-port',
+ help='Port to send HTTP requests to.')
+ group.add_argument('--runner-type',
help='Type of test to run as.')
- group.add_argument('--runner-package', help='Package name of test.')
- group.add_argument('--device-type', default='Android',
+ group.add_argument('--runner-package',
+ help='Package name of test.')
+ group.add_argument('--device-type',
choices=constants.VALID_DEVICE_TYPES,
help=('Type of device to run on. iOS or android'))
+ group.add_argument('--device-oem', action='append',
+ help='Device OEM to run on.')
+ group.add_argument('--remote-device-file',
+ help=('File with JSON to select remote device. '
+ 'Overrides all other flags.'))
+
+ device_os_group = group.add_mutually_exclusive_group()
+ device_os_group.add_argument('--remote-device-minimum-os',
+ help='Minimum OS on device.')
+ device_os_group.add_argument('--remote-device-os', action='append',
+ help='OS to have on the device.')
api_secret_group = group.add_mutually_exclusive_group()
api_secret_group.add_argument('--api-secret', default='',
@@ -513,7 +525,8 @@
"""Adds uirobot test options to |option_parser|."""
group = parser.add_argument_group('Uirobot Test Options')
- group.add_argument('--app-under-test', help='APK to run tests on.')
+ group.add_argument('--app-under-test', required=True,
+ help='APK to run tests on.')
group.add_argument(
'--minutes', default=5, type=int,
help='Number of minutes to run uirobot test [default: %default].')
diff --git a/build/common.gypi b/build/common.gypi
index 948dcec..153a500 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -318,7 +318,7 @@
# Only used on Windows.
'win_z7%' : 0,
- # Set to 1 to enable dcheck in release.
+ # Set to 1 to enable dcheck in Release build.
'dcheck_always_on%': 0,
# Set to 1 to make a build that disables unshipped tracing events.
@@ -1588,6 +1588,18 @@
'sysroot%': '<(sysroot)',
'CXX%': '<(CXX)',
}],
+ # Use a 64-bit linker to avoid running out of address space. The
+ # buildbots should have a 64-bit kernel and a 64-bit libc installed.
+ ['host_arch=="ia32" and target_arch=="ia32"', {
+ # TODO(thestig) This is a horrible way to force the desired
+ # configuration. Our gyp variable scoping is likely wrong and
+ # needs to be cleaned up. The GN configuration should be changed
+ # to match.
+ 'binutils_version%': 224,
+ 'linux_use_bundled_binutils%': '1',
+ 'linux_use_bundled_gold%': '1',
+ 'binutils_dir%': 'third_party/binutils/Linux_x64/Release/bin',
+ }],
# All Chrome builds have breakpad symbols, but only process the
# symbols from official builds.
['(branding=="Chrome" and buildtype=="Official")', {
@@ -1596,16 +1608,6 @@
# Omit unwind support in official release builds to save space. We
# can use breakpad for these builds.
'release_unwind_tables%': 0,
-
- 'conditions': [
- # For official builds, use a 64-bit linker to avoid running out
- # of address space. The buildbots should have a 64-bit kernel
- # and a 64-bit libc installed.
- ['host_arch=="ia32" and target_arch=="ia32"', {
- 'linux_use_bundled_gold%': '1',
- 'binutils_dir%': 'third_party/binutils/Linux_x64/Release/bin',
- }],
- ],
}],
],
}], # os_posix==1 and OS!="mac" and OS!="ios"
@@ -1666,7 +1668,7 @@
'android_ndk_root%': '<(android_ndk_root)',
'android_sdk_root%': '<(android_sdk_root)',
'android_sdk_version%': '<(android_sdk_version)',
- 'android_stlport_root': '<(android_ndk_root)/sources/cxx-stl/stlport',
+ 'android_libcpp_root': '<(android_ndk_root)/sources/cxx-stl/llvm-libc++',
'host_os%': '<(host_os)',
'android_sdk%': '<(android_sdk_root)/platforms/android-<(android_sdk_version)',
@@ -1743,9 +1745,10 @@
'android_sdk%': '<(android_sdk)',
'android_sdk_jar%': '<(android_sdk)/android.jar',
- 'android_stlport_root': '<(android_stlport_root)',
- 'android_stlport_include': '<(android_stlport_root)/stlport',
- 'android_stlport_libs_dir': '<(android_stlport_root)/libs/<(android_app_abi)',
+ 'android_libcpp_root': '<(android_libcpp_root)',
+ 'android_libcpp_include': '<(android_libcpp_root)/libcxx/include',
+ 'android_libcpp_libs_dir': '<(android_libcpp_root)/libs/<(android_app_abi)',
+
'host_os%': '<(host_os)',
# Location of the "objcopy" binary, used by both gyp and scripts.
@@ -2143,7 +2146,7 @@
'conditions': [
# TODO(dcheng): https://crbug.com/417463 -- work to enable this flag
# on all platforms is currently underway.
- ['OS=="linux" or OS=="mac" or OS=="ios"', {
+ ['OS=="android" or OS=="linux" or OS=="mac" or OS=="ios"', {
'clang_chrome_plugins_flags': [
'-Xclang',
'-plugin-arg-find-bad-constructs',
@@ -4403,10 +4406,8 @@
# https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
# Only apply this to the target linker, since the host
# linker might not be gold, but isn't used much anyway.
- # TODO(raymes): Disable threading because gold is frequently
- # crashing on the bots: crbug.com/161942.
- # '-Wl,--threads',
- # '-Wl,--thread-count=4',
+ '-Wl,--threads',
+ '-Wl,--thread-count=4',
],
}],
],
@@ -4498,9 +4499,9 @@
# Figure this out early since it needs symbols from libgcc.a, so it
# has to be before that in the set of libraries.
['component=="shared_library"', {
- 'android_stlport_library': 'stlport_shared',
+ 'android_libcpp_library': 'c++_shared',
}, {
- 'android_stlport_library': 'stlport_static',
+ 'android_libcpp_library': 'c++_static',
}],
],
@@ -4584,8 +4585,6 @@
'defines': [
'ANDROID',
'__GNU_SOURCE=1', # Necessary for clone()
- 'USE_STLPORT=1',
- '_STLP_USE_PTR_SPECIALIZATIONS=1',
'CHROME_BUILD_ID="<(chrome_build_id)"',
],
'ldflags!': [
@@ -4659,12 +4658,13 @@
'-nostdlib',
],
'libraries': [
- '-l<(android_stlport_library)',
+ '-l<(android_libcpp_library)',
+ '-latomic',
# Manually link the libgcc.a that the cross compiler uses.
'<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
+ '-lm',
'-lc',
'-ldl',
- '-lm',
],
}],
['android_webview_build==1', {
@@ -4716,20 +4716,20 @@
'-Wl,--icf=safe',
],
}],
- # NOTE: The stlport header include paths below are specified in
- # cflags rather than include_dirs because they need to come
- # after include_dirs. Think of them like system headers, but
- # don't use '-isystem' because the arm-linux-androideabi-4.4.3
- # toolchain (circa Gingerbread) will exhibit strange errors.
- # The include ordering here is important; change with caution.
['android_webview_build==0', {
'cflags': [
- '-isystem<(android_stlport_include)',
+ '-isystem<(android_libcpp_include)',
+ '-isystem<(android_ndk_root)/sources/cxx-stl/llvm-libc++abi/libcxxabi/include',
+ '-isystem<(android_ndk_root)/sources/android/support/include',
],
'ldflags': [
- '-L<(android_stlport_libs_dir)',
+ '-L<(android_libcpp_libs_dir)',
],
}, { # else: android_webview_build!=0
+ 'defines': [
+ 'USE_STLPORT=1',
+ '_STLP_USE_PTR_SPECIALIZATIONS=1',
+ ],
'aosp_build_settings': {
# Specify that we want to statically link stlport from the
# NDK. This will provide all the include and library paths
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index c57ba3f..5f93dd9 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -19,6 +19,9 @@
# TODO(sebmarchand): Update this comment once this flag guarantee that
# there's no build metadata in the build artifacts.
dont_embed_build_metadata = false
+
+ # Set to true to enable dcheck in Release builds.
+ dcheck_always_on = false
}
# TODO(brettw) Most of these should be removed. Instead of global feature
@@ -74,6 +77,9 @@
if (dont_embed_build_metadata) {
defines += [ "DONT_EMBED_BUILD_METADATA" ]
}
+ if (dcheck_always_on) {
+ defines += [ "DCHECK_ALWAYS_ON=1" ]
+ }
if (use_udev) {
# TODO(brettw) should probably be "=1".
defines += [ "USE_UDEV" ]
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 60934c2..c6202d4 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -129,14 +129,6 @@
android_gdbserver =
"$android_ndk_root/prebuilt/$android_prebuilt_arch/gdbserver/gdbserver"
- # stlport stuff --------------------------------------------------------------
-
- if (component_mode == "shared_library") {
- android_stlport_library = "stlport_shared"
- } else {
- android_stlport_library = "stlport_static"
- }
-
# ABI ------------------------------------------------------------------------
if (cpu_arch == "x86") {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 164b97d..b50a64c 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -380,10 +380,8 @@
# https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
# Only apply this to the target linker, since the host
# linker might not be gold, but isn't used much anyway.
- # TODO(raymes): Disable threading because gold is frequently
- # crashing on the bots: crbug.com/161942.
- #"-Wl,--threads",
- #"-Wl,--thread-count=4",
+ "-Wl,--threads",
+ "-Wl,--thread-count=4",
]
}
@@ -531,7 +529,7 @@
]
}
- # Stlport setup. Android uses a different (smaller) version of the STL.
+ # Android standard library setup.
if (is_android) {
if (is_clang) {
# Work around incompatibilities between bionic and clang headers.
@@ -541,55 +539,44 @@
]
}
- defines += [
- "USE_STLPORT=1",
- "_STLP_USE_PTR_SPECIALIZATIONS=1",
- "__GNU_SOURCE=1", # Necessary for clone().
- ]
+ defines += [ "__GNU_SOURCE=1" ] # Necessary for clone().
ldflags += [
"-Wl,--warn-shared-textrel",
"-nostdlib",
]
- # NOTE: The stlport header include paths below are specified in cflags
- # rather than include_dirs because they need to come after include_dirs.
- # Think of them like system headers, but don't use '-isystem' because the
- # arm-linux-androideabi-4.4.3 toolchain (circa Gingerbread) will exhibit
- # strange errors. The include ordering here is important; change with
- # caution.
- android_stlport_root = "$android_ndk_root/sources/cxx-stl/stlport"
+ android_libcpp_root = "$android_ndk_root/sources/cxx-stl/llvm-libc++"
- cflags += [ "-isystem" +
- rebase_path("$android_stlport_root/stlport", root_build_dir) ]
- lib_dirs += [ "$android_stlport_root/libs/$android_app_abi" ]
+ cflags += [
+ "-isystem" +
+ rebase_path("$android_libcpp_root/libcxx/include", root_build_dir),
+ "-isystem" + rebase_path(
+ "$android_ndk_root/sources/cxx-stl/llvm-libc++abi/libcxxabi/include",
+ root_build_dir),
+ "-isystem" +
+ rebase_path("$android_ndk_root/sources/android/support/include",
+ root_build_dir),
+ ]
+
+ lib_dirs += [ "$android_libcpp_root/libs/$android_app_abi" ]
if (component_mode == "shared_library") {
- libs += [ "stlport_shared" ]
+ android_libcpp_library = "c++_shared"
} else {
- libs += [ "stlport_static" ]
- }
-
- if (cpu_arch == "mipsel") {
- libs += [
- # ld linker is used for mips Android, and ld does not accept library
- # absolute path prefixed by "-l"; Since libgcc does not exist in mips
- # sysroot the proper library will be linked.
- # TODO(gordanac): Remove once gold linker is used for mips Android.
- "gcc",
- ]
- } else {
- libs += [
- # Manually link the libgcc.a that the cross compiler uses. This is
- # absolute because the linker will look inside the sysroot if it's not.
- rebase_path(android_libgcc_file),
- ]
+ android_libcpp_library = "c++_static"
}
libs += [
+ "$android_libcpp_library",
+ "atomic",
+
+ # Manually link the libgcc.a that the cross compiler uses. This is
+ # absolute because the linker will look inside the sysroot if it's not.
+ rebase_path(android_libgcc_file),
+ "m",
"c",
"dl",
- "m",
]
}
}
diff --git a/build/gyp_chromium b/build/gyp_chromium
index 1112575..45f3206 100755
--- a/build/gyp_chromium
+++ b/build/gyp_chromium
@@ -7,6 +7,7 @@
# This script is wrapper for Chromium that adds some support for how GYP
# is invoked by Chromium beyond what can be done in the gclient hooks.
+import argparse
import glob
import gyp_environment
import os
@@ -27,6 +28,7 @@
SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Add paths so that pymod_do_main(...) can import files.
+sys.path.insert(1, os.path.join(chrome_src, 'android_webview', 'tools'))
sys.path.insert(1, os.path.join(chrome_src, 'build', 'android', 'gyp'))
sys.path.insert(1, os.path.join(chrome_src, 'tools'))
sys.path.insert(1, os.path.join(chrome_src, 'tools', 'generate_shim_headers'))
@@ -124,15 +126,10 @@
env_items = ProcessGypDefinesItems(
shlex.split(os.environ.get('GYP_DEFINES', '')))
- # GYP defines from the command line. We can't use optparse since we want
- # to ignore all arguments other than "-D".
- cmdline_input_items = []
- for i in range(len(sys.argv))[1:]:
- if sys.argv[i].startswith('-D'):
- if sys.argv[i] == '-D' and i + 1 < len(sys.argv):
- cmdline_input_items += [sys.argv[i + 1]]
- elif len(sys.argv[i]) > 2:
- cmdline_input_items += [sys.argv[i][2:]]
+ # GYP defines from the command line.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-D', dest='defines', action='append', default=[])
+ cmdline_input_items = parser.parse_known_args()[0].defines
cmdline_items = ProcessGypDefinesItems(cmdline_input_items)
vars_dict = dict(supp_items + env_items + cmdline_items)
@@ -141,21 +138,21 @@
def GetOutputDirectory():
"""Returns the output directory that GYP will use."""
- # GYP generator flags from the command line. We can't use optparse since we
- # want to ignore all arguments other than "-G".
- needle = '-Goutput_dir='
- cmdline_input_items = []
- for item in sys.argv[1:]:
- if item.startswith(needle):
- return item[len(needle):]
- env_items = shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
+ # Handle command line generator flags.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-G', dest='genflags', default=[], action='append')
+ genflags = parser.parse_known_args()[0].genflags
+
+ # Handle generator flags from the environment.
+ genflags += shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
+
needle = 'output_dir='
- for item in env_items:
+ for item in genflags:
if item.startswith(needle):
return item[len(needle):]
- return "out"
+ return 'out'
def additional_include_files(supplemental_files, args=[]):
diff --git a/build/gyp_chromium_test.py b/build/gyp_chromium_test.py
new file mode 100755
index 0000000..0c0e479
--- /dev/null
+++ b/build/gyp_chromium_test.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import unittest
+
+SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
+SRC_DIR = os.path.dirname(SCRIPT_DIR)
+
+sys.path.append(os.path.join(SRC_DIR, 'third_party', 'pymock'))
+
+import mock
+
+# TODO(sbc): Make gyp_chromium more testable by putting the code in
+# a .py file.
+gyp_chromium = __import__('gyp_chromium')
+
+
+class TestGetOutputDirectory(unittest.TestCase):
+ @mock.patch('os.environ', {})
+ @mock.patch('sys.argv', [__file__])
+ def testDefaultValue(self):
+ self.assertEqual(gyp_chromium.GetOutputDirectory(), 'out')
+
+ @mock.patch('os.environ', {'GYP_GENERATOR_FLAGS': 'output_dir=envfoo'})
+ @mock.patch('sys.argv', [__file__])
+ def testEnvironment(self):
+ self.assertEqual(gyp_chromium.GetOutputDirectory(), 'envfoo')
+
+ @mock.patch('os.environ', {'GYP_GENERATOR_FLAGS': 'output_dir=envfoo'})
+ @mock.patch('sys.argv', [__file__, '-Goutput_dir=cmdfoo'])
+ def testGFlagOverridesEnv(self):
+ self.assertEqual(gyp_chromium.GetOutputDirectory(), 'cmdfoo')
+
+ @mock.patch('os.environ', {})
+ @mock.patch('sys.argv', [__file__, '-G', 'output_dir=foo'])
+ def testGFlagWithSpace(self):
+ self.assertEqual(gyp_chromium.GetOutputDirectory(), 'foo')
+
+
+class TestGetGypVars(unittest.TestCase):
+ @mock.patch('os.environ', {})
+ def testDefault(self):
+ self.assertEqual(gyp_chromium.GetGypVars([]), {})
+
+ @mock.patch('os.environ', {})
+ @mock.patch('sys.argv', [__file__, '-D', 'foo=bar'])
+ def testDFlags(self):
+ self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': 'bar'})
+
+ @mock.patch('os.environ', {})
+ @mock.patch('sys.argv', [__file__, '-D', 'foo'])
+ def testDFlagsNoValue(self):
+ self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': '1'})
+
+ @mock.patch('os.environ', {})
+ @mock.patch('sys.argv', [__file__, '-D', 'foo=bar', '-Dbaz'])
+ def testDFlagMulti(self):
+ self.assertEqual(gyp_chromium.GetGypVars([]), {'foo': 'bar', 'baz': '1'})
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/build/isolate.gypi b/build/isolate.gypi
index e6d2f98..d7070fe 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -74,24 +74,28 @@
# the .isolate file but are not considered relative paths.
'--extra-variable', 'version_full=<(version_full)',
- '--config-variable', 'OS=<(OS)',
'--config-variable', 'CONFIGURATION_NAME=<(CONFIGURATION_NAME)',
+ '--config-variable', 'OS=<(OS)',
'--config-variable', 'asan=<(asan)',
'--config-variable', 'chromeos=<(chromeos)',
'--config-variable', 'component=<(component)',
+ '--config-variable', 'disable_nacl=<(disable_nacl)',
'--config-variable', 'fastbuild=<(fastbuild)',
+ '--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
# TODO(kbr): move this to chrome_tests.gypi:gles2_conform_tests_run
# once support for user-defined config variables is added.
'--config-variable',
'internal_gles2_conform_tests=<(internal_gles2_conform_tests)',
- '--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
- '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
- '--config-variable', 'lsan=<(lsan)',
'--config-variable', 'libpeer_target_type=<(libpeer_target_type)',
- '--config-variable', 'use_openssl=<(use_openssl)',
+ '--config-variable', 'lsan=<(lsan)',
+ '--config-variable', 'msan=<(msan)',
'--config-variable', 'target_arch=<(target_arch)',
+ '--config-variable', 'tsan=<(tsan)',
+ '--config-variable', 'use_custom_libcxx=<(use_custom_libcxx)',
+ '--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)',
+ '--config-variable', 'use_openssl=<(use_openssl)',
'--config-variable', 'use_ozone=<(use_ozone)',
- '--config-variable', 'disable_nacl=<(disable_nacl)',
+ '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
],
'conditions': [
# Note: When gyp merges lists, it appends them to the old value.
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index ae69583..a15cba1 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -111,7 +111,8 @@
"race:content::GpuWatchdogThread::CheckArmed\n"
// http://crbug.com/257396
-"race:base::debug::TraceEventTestFixture_TraceSamplingScope_Test::TestBody\n"
+"race:base::trace_event::"
+ "TraceEventTestFixture_TraceSamplingScope_Test::TestBody\n"
// http://crbug.com/258479
"race:SamplingStateScope\n"
@@ -291,10 +292,10 @@
// http://crbug.com/397022
"deadlock:"
-"base::debug::TraceEventTestFixture_ThreadOnceBlocking_Test::TestBody\n"
+"base::trace_event::TraceEventTestFixture_ThreadOnceBlocking_Test::TestBody\n"
// http://crbug.com/415472
-"deadlock:base::debug::TraceLog::GetCategoryGroupEnabled\n"
+"deadlock:base::trace_event::TraceLog::GetCategoryGroupEnabled\n"
// http://crbug.com/425057
"deadlock:webrtc::ViEChannelManagerScoped::ViEChannelManagerScoped\n"
@@ -315,6 +316,15 @@
// https://crbug.com/448203
"race:blink::RemoteFrame::detach\n"
+// https://crbug.com/455638
+"deadlock:dbus::Bus::ShutdownAndBlock\n"
+
+// https://crbug.com/455665
+"race:mojo::common::*::tick_clock\n"
+
+// https://crbug.com/456095
+"race:blink::Scheduler\n"
+
// End of suppressions.
; // Please keep this semicolon.
diff --git a/build/secondary/third_party/libjpeg_turbo/BUILD.gn b/build/secondary/third_party/libjpeg_turbo/BUILD.gn
index 82472e7..be16302 100644
--- a/build/secondary/third_party/libjpeg_turbo/BUILD.gn
+++ b/build/secondary/third_party/libjpeg_turbo/BUILD.gn
@@ -84,7 +84,7 @@
} else if (is_mac) {
defines += [ "MACHO" ]
include_dirs = [ "mac" ]
- } else if (is_linux) {
+ } else if (is_linux || is_android) {
defines += [ "ELF" ]
include_dirs = [ "linux" ]
}
diff --git a/build/whitespace_file.txt b/build/whitespace_file.txt
index ee4f527..7191150 100644
--- a/build/whitespace_file.txt
+++ b/build/whitespace_file.txt
@@ -152,4 +152,3 @@
In the BUILD we trust.
^_^
-
diff --git a/cc/base/math_util.h b/cc/base/math_util.h
index d9cc43b..ddc8955 100644
--- a/cc/base/math_util.h
+++ b/cc/base/math_util.h
@@ -21,10 +21,16 @@
namespace base {
class Value;
-namespace debug {
+namespace trace_event {
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace gfx {
class QuadF;
diff --git a/cc/base/region.h b/cc/base/region.h
index 294ea63..b84dbd5 100644
--- a/cc/base/region.h
+++ b/cc/base/region.h
@@ -15,10 +15,16 @@
namespace base {
class Value;
-namespace debug {
+namespace trace_event {
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
class SimpleEnclosedRegion;
diff --git a/cc/base/synced_property.h b/cc/base/synced_property.h
index 8b554c6..6b02e7a 100644
--- a/cc/base/synced_property.h
+++ b/cc/base/synced_property.h
@@ -24,7 +24,7 @@
template <typename T>
class SyncedProperty : public base::RefCounted<SyncedProperty<T>> {
public:
- SyncedProperty() {}
+ SyncedProperty() : clobber_active_value_(false) {}
// Returns the canonical value for the specified tree, including the sum of
// all deltas. The pending tree should use this for activation purposes and
@@ -84,6 +84,7 @@
active_base_ = pending_base_;
active_delta_ = PendingDelta();
sent_delta_ = T::Identity();
+ clobber_active_value_ = false;
return true;
}
@@ -105,7 +106,13 @@
// The new delta we would use if we decide to activate now. This delta
// excludes the amount that we expect the main thread to reflect back at the
// impl thread during the commit.
- T PendingDelta() const { return active_delta_.InverseCombine(sent_delta_); }
+ T PendingDelta() const {
+ if (clobber_active_value_)
+ return T::Identity();
+ return active_delta_.InverseCombine(sent_delta_);
+ }
+
+ void set_clobber_active_value() { clobber_active_value_ = true; }
private:
// Value last committed to the pending tree.
@@ -117,6 +124,9 @@
// The value sent to the main thread (on the last BeginFrame); this is always
// identity outside of the BeginFrame-to-activation interval.
T sent_delta_;
+ // When true the pending delta is always identity so that it does not change
+ // and will clobber the active value on push.
+ bool clobber_active_value_;
friend class base::RefCounted<SyncedProperty<T>>;
~SyncedProperty() {}
diff --git a/cc/blink/context_provider_web_context.h b/cc/blink/context_provider_web_context.h
new file mode 100644
index 0000000..21d1df3
--- /dev/null
+++ b/cc/blink/context_provider_web_context.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_BLINK_CONTEXT_PROVIDER_WEB_CONTEXT_H_
+#define CC_BLINK_CONTEXT_PROVIDER_WEB_CONTEXT_H_
+
+#include "cc/output/context_provider.h"
+
+namespace blink { class WebGraphicsContext3D; }
+
+namespace cc_blink {
+
+class ContextProviderWebContext : public cc::ContextProvider {
+ public:
+ virtual blink::WebGraphicsContext3D* WebContext3D() = 0;
+
+ protected:
+ ~ContextProviderWebContext() override {}
+};
+
+} // namespace cc_blink
+
+#endif // CC_BLINK_CONTEXT_PROVIDER_WEB_CONTEXT_H_
diff --git a/cc/blink/web_content_layer_impl.cc b/cc/blink/web_content_layer_impl.cc
index abe3eb3..9224223 100644
--- a/cc/blink/web_content_layer_impl.cc
+++ b/cc/blink/web_content_layer_impl.cc
@@ -19,6 +19,21 @@
namespace cc_blink {
+static blink::WebContentLayerClient::PaintingControlSetting
+PaintingControlToWeb(
+ cc::ContentLayerClient::PaintingControlSetting painting_control) {
+ switch (painting_control) {
+ case cc::ContentLayerClient::PAINTING_BEHAVIOR_NORMAL:
+ return blink::WebContentLayerClient::PaintDefaultBehavior;
+ case cc::ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED:
+ return blink::WebContentLayerClient::DisplayListConstructionDisabled;
+ case cc::ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED:
+ return blink::WebContentLayerClient::DisplayListCachingDisabled;
+ }
+ NOTREACHED();
+ return blink::WebContentLayerClient::PaintDefaultBehavior;
+}
+
WebContentLayerImpl::WebContentLayerImpl(blink::WebContentLayerClient* client)
: client_(client) {
if (WebLayerImpl::UsingPictureLayer())
@@ -50,30 +65,22 @@
void WebContentLayerImpl::PaintContents(
SkCanvas* canvas,
const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus graphics_context_status) {
+ cc::ContentLayerClient::PaintingControlSetting painting_control) {
if (!client_)
return;
- client_->paintContents(
- canvas, clip,
- graphics_context_status == ContentLayerClient::GRAPHICS_CONTEXT_ENABLED
- ? blink::WebContentLayerClient::GraphicsContextEnabled
- : blink::WebContentLayerClient::GraphicsContextDisabled);
+ client_->paintContents(canvas, clip, PaintingControlToWeb(painting_control));
}
scoped_refptr<cc::DisplayItemList>
WebContentLayerImpl::PaintContentsToDisplayList(
const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus graphics_context_status) {
+ cc::ContentLayerClient::PaintingControlSetting painting_control) {
if (!client_)
return cc::DisplayItemList::Create();
WebDisplayItemListImpl list;
- client_->paintContents(
- &list, clip,
- graphics_context_status == ContentLayerClient::GRAPHICS_CONTEXT_ENABLED
- ? blink::WebContentLayerClient::GraphicsContextEnabled
- : blink::WebContentLayerClient::GraphicsContextDisabled);
+ client_->paintContents(&list, clip, PaintingControlToWeb(painting_control));
return list.ToDisplayItemList();
}
diff --git a/cc/blink/web_content_layer_impl.h b/cc/blink/web_content_layer_impl.h
index 148f4fc..3e7b55c 100644
--- a/cc/blink/web_content_layer_impl.h
+++ b/cc/blink/web_content_layer_impl.h
@@ -38,11 +38,10 @@
// ContentLayerClient implementation.
void PaintContents(SkCanvas* canvas,
const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus
- graphics_context_status) override;
+ PaintingControlSetting painting_control) override;
scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus graphics_context_status) override;
+ PaintingControlSetting painting_control) override;
bool FillsBoundsCompletely() const override;
scoped_ptr<WebLayerImpl> layer_;
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc
index 6ce8ac5..bcebfec 100644
--- a/cc/blink/web_layer_impl.cc
+++ b/cc/blink/web_layer_impl.cc
@@ -383,6 +383,28 @@
return result;
}
+static_assert(static_cast<ScrollBlocksOn>(blink::WebScrollBlocksOnNone) ==
+ ScrollBlocksOnNone,
+ "ScrollBlocksOn and WebScrollBlocksOn enums must match");
+static_assert(static_cast<ScrollBlocksOn>(blink::WebScrollBlocksOnStartTouch) ==
+ ScrollBlocksOnStartTouch,
+ "ScrollBlocksOn and WebScrollBlocksOn enums must match");
+static_assert(static_cast<ScrollBlocksOn>(blink::WebScrollBlocksOnWheelEvent) ==
+ ScrollBlocksOnWheelEvent,
+ "ScrollBlocksOn and WebScrollBlocksOn enums must match");
+static_assert(
+ static_cast<ScrollBlocksOn>(blink::WebScrollBlocksOnScrollEvent) ==
+ ScrollBlocksOnScrollEvent,
+ "ScrollBlocksOn and WebScrollBlocksOn enums must match");
+
+void WebLayerImpl::setScrollBlocksOn(blink::WebScrollBlocksOn blocks) {
+ layer_->SetScrollBlocksOn(static_cast<ScrollBlocksOn>(blocks));
+}
+
+blink::WebScrollBlocksOn WebLayerImpl::scrollBlocksOn() const {
+ return static_cast<blink::WebScrollBlocksOn>(layer_->scroll_blocks_on());
+}
+
void WebLayerImpl::setIsContainerForFixedPositionLayers(bool enable) {
layer_->SetIsContainerForFixedPositionLayers(enable);
}
diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h
index 111c6cf..787f632 100644
--- a/cc/blink/web_layer_impl.h
+++ b/cc/blink/web_layer_impl.h
@@ -31,10 +31,16 @@
}
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
}
+} // namespace base
namespace cc {
class Layer;
@@ -123,6 +129,8 @@
virtual void setTouchEventHandlerRegion(
const blink::WebVector<blink::WebRect>& region);
virtual blink::WebVector<blink::WebRect> touchEventHandlerRegion() const;
+ virtual void setScrollBlocksOn(blink::WebScrollBlocksOn);
+ virtual blink::WebScrollBlocksOn scrollBlocksOn() const;
virtual void setIsContainerForFixedPositionLayers(bool is_container);
virtual bool isContainerForFixedPositionLayers() const;
virtual void setPositionConstraint(
diff --git a/cc/cc_unittests.isolate b/cc/cc_unittests.isolate
index 4e5ac92..5d652d9 100644
--- a/cc/cc_unittests.isolate
+++ b/cc/cc_unittests.isolate
@@ -22,6 +22,8 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
],
'files': [
'../testing/xvfb.py',
@@ -46,6 +48,8 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
],
'files': [
'<(PRODUCT_DIR)/ffmpegsumo.so',
@@ -62,6 +66,8 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
],
'files': [
'<(PRODUCT_DIR)/ffmpegsumo.dll',
diff --git a/cc/debug/devtools_instrumentation.h b/cc/debug/devtools_instrumentation.h
index cfe3e5a..73788a5 100644
--- a/cc/debug/devtools_instrumentation.h
+++ b/cc/debug/devtools_instrumentation.h
@@ -6,6 +6,7 @@
#define CC_DEBUG_DEVTOOLS_INSTRUMENTATION_H_
#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
namespace cc {
namespace devtools_instrumentation {
@@ -14,6 +15,7 @@
const char kCategory[] = TRACE_DISABLED_BY_DEFAULT("devtools.timeline");
const char kCategoryFrame[] =
TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame");
+const char kData[] = "data";
const char kFrameId[] = "frameId";
const char kLayerId[] = "layerId";
const char kLayerTreeId[] = "layerTreeId";
@@ -23,7 +25,9 @@
const char kBeginFrame[] = "BeginFrame";
const char kActivateLayerTree[] = "ActivateLayerTree";
const char kRequestMainThreadFrame[] = "RequestMainThreadFrame";
+const char kBeginMainThreadFrame[] = "BeginMainThreadFrame";
const char kDrawFrame[] = "DrawFrame";
+const char kCompositeLayers[] = "CompositeLayers";
} // namespace internal
const char kPaintSetup[] = "PaintSetup";
@@ -77,6 +81,20 @@
DISALLOW_COPY_AND_ASSIGN(ScopedLayerTreeTask);
};
+struct ScopedCommitTrace {
+ public:
+ explicit ScopedCommitTrace(int layer_tree_host_id) {
+ TRACE_EVENT_BEGIN1(internal::kCategory, internal::kCompositeLayers,
+ internal::kLayerTreeId, layer_tree_host_id);
+ }
+ ~ScopedCommitTrace() {
+ TRACE_EVENT_END0(internal::kCategory, internal::kCompositeLayers);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedCommitTrace);
+};
+
struct ScopedLayerObjectTracker
: public base::debug::TraceScopedTrackableObject<int> {
explicit ScopedLayerObjectTracker(int layer_id)
@@ -124,6 +142,21 @@
layer_tree_host_id);
}
+inline scoped_refptr<base::debug::ConvertableToTraceFormat>
+BeginMainThreadFrameData(int frame_id) {
+ scoped_refptr<base::debug::TracedValue> value =
+ new base::debug::TracedValue();
+ value->SetInteger("frameId", frame_id);
+ return value;
+}
+
+inline void WillBeginMainThreadFrame(int layer_tree_host_id, int frame_id) {
+ TRACE_EVENT_INSTANT2(
+ internal::kCategoryFrame, internal::kBeginMainThreadFrame,
+ TRACE_EVENT_SCOPE_THREAD, internal::kLayerTreeId, layer_tree_host_id,
+ internal::kData, BeginMainThreadFrameData(frame_id));
+}
+
} // namespace devtools_instrumentation
} // namespace cc
diff --git a/cc/debug/frame_timing_request.h b/cc/debug/frame_timing_request.h
index 7ab97de..0937998 100644
--- a/cc/debug/frame_timing_request.h
+++ b/cc/debug/frame_timing_request.h
@@ -5,6 +5,7 @@
#ifndef CC_DEBUG_FRAME_TIMING_REQUEST_H_
#define CC_DEBUG_FRAME_TIMING_REQUEST_H_
+#include "cc/base/cc_export.h"
#include "ui/gfx/geometry/rect.h"
namespace cc {
@@ -13,12 +14,15 @@
// given rect (in layer space) and an associated request id. When this request
// is propagated to the active LayerImpl, it will cause events to be saved in
// FrameTimingTracker, which in turn can be consumed by the requester.
-class FrameTimingRequest {
+class CC_EXPORT FrameTimingRequest {
public:
FrameTimingRequest();
FrameTimingRequest(int64_t request_id, const gfx::Rect& rect);
+ // Return the ID for the request.
int64_t id() const { return id_; }
+
+ // Return the layer space rect for this request.
const gfx::Rect& rect() const { return rect_; }
private:
diff --git a/cc/debug/picture_record_benchmark.cc b/cc/debug/picture_record_benchmark.cc
index d0d031d..b1b8188 100644
--- a/cc/debug/picture_record_benchmark.cc
+++ b/cc/debug/picture_record_benchmark.cc
@@ -106,8 +106,9 @@
base::TimeTicks start = base::TimeTicks::Now();
- scoped_refptr<Picture> picture = Picture::Create(
- rect, painter, tile_grid_size, false, Picture::RECORD_NORMALLY);
+ scoped_refptr<Picture> picture =
+ Picture::Create(rect, painter, tile_grid_size, false,
+ RecordingSource::RECORD_NORMALLY);
base::TimeTicks end = base::TimeTicks::Now();
base::TimeDelta duration = end - start;
diff --git a/cc/debug/rasterize_and_record_benchmark.cc b/cc/debug/rasterize_and_record_benchmark.cc
index 3a0c98b..e56a1e1 100644
--- a/cc/debug/rasterize_and_record_benchmark.cc
+++ b/cc/debug/rasterize_and_record_benchmark.cc
@@ -34,10 +34,8 @@
const int kWarmupRuns = 0;
const int kTimeCheckInterval = 1;
-const char* kModeSuffixes[Picture::RECORDING_MODE_COUNT] = {
- "",
- "_sk_null_canvas",
- "_painting_disabled"};
+const char* kModeSuffixes[RecordingSource::RECORDING_MODE_COUNT] =
+ {"", "_sk_null_canvas", "_painting_disabled", "_caching_disabled"};
} // namespace
@@ -74,7 +72,7 @@
results_->SetInteger("pixels_recorded", record_results_.pixels_recorded);
results_->SetInteger("picture_memory_usage", record_results_.bytes_used);
- for (int i = 0; i < Picture::RECORDING_MODE_COUNT; i++) {
+ for (int i = 0; i < RecordingSource::RECORDING_MODE_COUNT; i++) {
std::string name = base::StringPrintf("record_time%s_ms", kModeSuffixes[i]);
results_->SetDouble(name,
record_results_.total_best_time[i].InMillisecondsF());
@@ -132,10 +130,10 @@
gfx::Size tile_grid_size = host_->settings().default_tile_size;
- for (int mode_index = 0; mode_index < Picture::RECORDING_MODE_COUNT;
+ for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
mode_index++) {
- Picture::RecordingMode mode =
- static_cast<Picture::RecordingMode>(mode_index);
+ RecordingSource::RecordingMode mode =
+ static_cast<RecordingSource::RecordingMode>(mode_index);
base::TimeDelta min_time = base::TimeDelta::Max();
size_t memory_used = 0;
@@ -164,7 +162,7 @@
min_time = duration;
}
- if (mode == Picture::RECORD_NORMALLY) {
+ if (mode == RecordingSource::RECORD_NORMALLY) {
record_results_.bytes_used += memory_used;
record_results_.pixels_recorded +=
visible_content_rect.width() * visible_content_rect.height();
@@ -180,49 +178,62 @@
DCHECK(host_ && host_->settings().use_display_lists);
- base::TimeDelta min_time = base::TimeDelta::Max();
- size_t memory_used = 0;
+ for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
+ mode_index++) {
+ ContentLayerClient::PaintingControlSetting painting_control =
+ ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
+ switch (static_cast<RecordingSource::RecordingMode>(mode_index)) {
+ case RecordingSource::RECORD_NORMALLY:
+ // Already setup for normal recording.
+ break;
+ case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
+ // TODO(schenney): Remove this when DisplayList recording is the only
+ // option. For now, fall through and disable construction.
+ case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
+ painting_control =
+ ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
+ break;
+ case RecordingSource::RECORD_WITH_CACHING_DISABLED:
+ painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
+ break;
+ default:
+ NOTREACHED();
+ }
+ base::TimeDelta min_time = base::TimeDelta::Max();
+ size_t memory_used = 0;
- // TODO(schenney): What are the corresponding Picture::RecordingMode modes
- // for Slimming Paint. We could disable SkPicture creation in
- // DrawingDisplayItems, or we could only generate the display list and not
- // do any work on it in the compositor, or something else, or all of the
- // above.
- scoped_refptr<DisplayItemList> display_list;
- for (int i = 0; i < record_repeat_count_; ++i) {
- // Run for a minimum amount of time to avoid problems with timer
- // quantization when the layer is very small.
- LapTimer timer(kWarmupRuns,
- base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
- kTimeCheckInterval);
+ scoped_refptr<DisplayItemList> display_list;
+ for (int i = 0; i < record_repeat_count_; ++i) {
+ // Run for a minimum amount of time to avoid problems with timer
+ // quantization when the layer is very small.
+ LapTimer timer(kWarmupRuns,
+ base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
+ kTimeCheckInterval);
- do {
- // TODO(schenney): Cached content will not be regenerated, which skews
- // the results significantly in favor of Slimming Paint (or should).
- // Add a flag or API call to disable caching, and maybe run the test
- // twice, without and with caching.
- display_list = painter->PaintContentsToDisplayList(
- visible_content_rect, ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+ do {
+ display_list = painter->PaintContentsToDisplayList(visible_content_rect,
+ painting_control);
- if (memory_used) {
- // Verify we are recording the same thing each time.
- DCHECK(memory_used == display_list->PictureMemoryUsage());
- } else {
- memory_used = display_list->PictureMemoryUsage();
- }
+ if (memory_used) {
+ // Verify we are recording the same thing each time.
+ DCHECK(memory_used == display_list->PictureMemoryUsage());
+ } else {
+ memory_used = display_list->PictureMemoryUsage();
+ }
- timer.NextLap();
- } while (!timer.HasTimeLimitExpired());
- base::TimeDelta duration =
- base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
- if (duration < min_time)
- min_time = duration;
+ timer.NextLap();
+ } while (!timer.HasTimeLimitExpired());
+ base::TimeDelta duration =
+ base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
+ if (duration < min_time)
+ min_time = duration;
+ }
+
+ record_results_.bytes_used += memory_used;
+ record_results_.pixels_recorded +=
+ visible_content_rect.width() * visible_content_rect.height();
+ record_results_.total_best_time[mode_index] += min_time;
}
-
- record_results_.bytes_used += memory_used;
- record_results_.pixels_recorded +=
- visible_content_rect.width() * visible_content_rect.height();
- record_results_.total_best_time[Picture::RECORD_NORMALLY] += min_time;
}
RasterizeAndRecordBenchmark::RecordResults::RecordResults()
diff --git a/cc/debug/rasterize_and_record_benchmark.h b/cc/debug/rasterize_and_record_benchmark.h
index 5ae45fa..30dcde0 100644
--- a/cc/debug/rasterize_and_record_benchmark.h
+++ b/cc/debug/rasterize_and_record_benchmark.h
@@ -51,7 +51,7 @@
int pixels_recorded;
size_t bytes_used;
- base::TimeDelta total_best_time[Picture::RECORDING_MODE_COUNT];
+ base::TimeDelta total_best_time[RecordingSource::RECORDING_MODE_COUNT];
};
RecordResults record_results_;
diff --git a/cc/debug/rendering_stats.cc b/cc/debug/rendering_stats.cc
index 9c62a3c..2247b3a 100644
--- a/cc/debug/rendering_stats.cc
+++ b/cc/debug/rendering_stats.cc
@@ -17,10 +17,13 @@
}
void RenderingStats::TimeDeltaList::AddToTracedValue(
+ const char* name,
base::debug::TracedValue* list_value) const {
+ list_value->BeginArray(name);
for (const auto& value : values) {
list_value->AppendDouble(value.InMillisecondsF());
}
+ list_value->EndArray();
}
void RenderingStats::TimeDeltaList::Add(const TimeDeltaList& other) {
@@ -48,30 +51,22 @@
record_data->SetInteger("visible_content_area", visible_content_area);
record_data->SetInteger("approximated_visible_content_area",
approximated_visible_content_area);
- record_data->BeginArray("draw_duration_ms");
- draw_duration.AddToTracedValue(record_data.get());
- record_data->EndArray();
+ draw_duration.AddToTracedValue("draw_duration_ms", record_data.get());
- record_data->BeginArray("draw_duration_estimate_ms");
- draw_duration_estimate.AddToTracedValue(record_data.get());
- record_data->EndArray();
+ draw_duration_estimate.AddToTracedValue("draw_duration_estimate_ms",
+ record_data.get());
- record_data->BeginArray("begin_main_frame_to_commit_duration_ms");
- begin_main_frame_to_commit_duration.AddToTracedValue(record_data.get());
- record_data->EndArray();
+ begin_main_frame_to_commit_duration.AddToTracedValue(
+ "begin_main_frame_to_commit_duration_ms", record_data.get());
- record_data->BeginArray("begin_main_frame_to_commit_duration_estimate_ms");
begin_main_frame_to_commit_duration_estimate.AddToTracedValue(
- record_data.get());
- record_data->EndArray();
+ "begin_main_frame_to_commit_duration_estimate_ms", record_data.get());
- record_data->BeginArray("commit_to_activate_duration_ms");
- commit_to_activate_duration.AddToTracedValue(record_data.get());
- record_data->EndArray();
+ commit_to_activate_duration.AddToTracedValue("commit_to_activate_duration_ms",
+ record_data.get());
- record_data->BeginArray("commit_to_activate_duration_estimate_ms");
- commit_to_activate_duration_estimate.AddToTracedValue(record_data.get());
- record_data->EndArray();
+ commit_to_activate_duration_estimate.AddToTracedValue(
+ "commit_to_activate_duration_estimate_ms", record_data.get());
return record_data;
}
diff --git a/cc/debug/rendering_stats.h b/cc/debug/rendering_stats.h
index 24acb93..3a72371 100644
--- a/cc/debug/rendering_stats.h
+++ b/cc/debug/rendering_stats.h
@@ -24,7 +24,8 @@
~TimeDeltaList();
void Append(base::TimeDelta value);
- void AddToTracedValue(base::debug::TracedValue* list_value) const;
+ void AddToTracedValue(const char* name,
+ base::debug::TracedValue* list_value) const;
void Add(const TimeDeltaList& other);
diff --git a/cc/debug/rendering_stats_unittest.cc b/cc/debug/rendering_stats_unittest.cc
index a634093..c1e189a 100644
--- a/cc/debug/rendering_stats_unittest.cc
+++ b/cc/debug/rendering_stats_unittest.cc
@@ -15,9 +15,7 @@
static std::string ToString(const RenderingStats::TimeDeltaList& list) {
scoped_refptr<base::debug::TracedValue> value =
new base::debug::TracedValue();
- value->BeginArray("list_value");
- list.AddToTracedValue(value.get());
- value->EndArray();
+ list.AddToTracedValue("list_value", value.get());
return value->ToString();
}
diff --git a/cc/debug/traced_value.h b/cc/debug/traced_value.h
index c5ea30a..db0a08a 100644
--- a/cc/debug/traced_value.h
+++ b/cc/debug/traced_value.h
@@ -6,10 +6,16 @@
#define CC_DEBUG_TRACED_VALUE_H_
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h
index 0208627..d899a85 100644
--- a/cc/input/input_handler.h
+++ b/cc/input/input_handler.h
@@ -143,7 +143,10 @@
ScrollInputType type) = 0;
virtual bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) = 0;
- virtual bool HaveTouchEventHandlersAt(const gfx::Point& viewport_point) = 0;
+
+ // Whether the page should be given the opportunity to suppress scrolling by
+ // consuming touch events that started at |viewport_point|.
+ virtual bool DoTouchEventsBlockScrollAt(const gfx::Point& viewport_point) = 0;
// Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped
// LatencyInfoSwapPromiseMonitor. During the life time of the
diff --git a/cc/layers/content_layer.cc b/cc/layers/content_layer.cc
index 53c7120..6af92ec 100644
--- a/cc/layers/content_layer.cc
+++ b/cc/layers/content_layer.cc
@@ -26,9 +26,8 @@
void ContentLayerPainter::Paint(SkCanvas* canvas,
const gfx::Rect& content_rect) {
- client_->PaintContents(canvas,
- content_rect,
- ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+ client_->PaintContents(canvas, content_rect,
+ ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
}
scoped_refptr<ContentLayer> ContentLayer::Create(ContentLayerClient* client) {
@@ -128,9 +127,8 @@
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0);
- client_->PaintContents(canvas,
- gfx::Rect(width, height),
- ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+ client_->PaintContents(canvas, gfx::Rect(width, height),
+ ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
return picture;
}
diff --git a/cc/layers/content_layer_client.h b/cc/layers/content_layer_client.h
index c8d3a7e..4f9c754 100644
--- a/cc/layers/content_layer_client.h
+++ b/cc/layers/content_layer_client.h
@@ -19,18 +19,19 @@
class CC_EXPORT ContentLayerClient {
public:
- enum GraphicsContextStatus {
- GRAPHICS_CONTEXT_DISABLED,
- GRAPHICS_CONTEXT_ENABLED
+ enum PaintingControlSetting {
+ PAINTING_BEHAVIOR_NORMAL,
+ DISPLAY_LIST_CONSTRUCTION_DISABLED,
+ DISPLAY_LIST_CACHING_DISABLED
};
virtual void PaintContents(SkCanvas* canvas,
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) = 0;
+ PaintingControlSetting painting_status) = 0;
virtual scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) = 0;
+ PaintingControlSetting painting_status) = 0;
// If true the layer may skip clearing the background before rasterizing,
// because it will cover any uncleared data with content.
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index cdb000f..60d984b 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -69,11 +69,10 @@
HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl,
int id)
: LayerImpl(tree_impl, id),
- typeface_(skia::AdoptRef(
- SkTypeface::CreateFromName("monospace", SkTypeface::kBold))),
fps_graph_(60.0, 80.0),
paint_time_graph_(16.0, 48.0),
- fade_step_(0) {}
+ fade_step_(0) {
+}
HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {}
@@ -173,36 +172,36 @@
return;
SkISize canvas_size;
- if (hud_canvas_)
- canvas_size = hud_canvas_->getDeviceSize();
+ if (hud_surface_)
+ canvas_size = hud_surface_->getCanvas()->getDeviceSize();
else
canvas_size.set(0, 0);
if (canvas_size.width() != content_bounds().width() ||
- canvas_size.height() != content_bounds().height() || !hud_canvas_) {
+ canvas_size.height() != content_bounds().height() || !hud_surface_) {
TRACE_EVENT0("cc", "ResizeHudCanvas");
- bool opaque = false;
- hud_canvas_ = make_scoped_ptr(skia::CreateBitmapCanvas(
- content_bounds().width(), content_bounds().height(), opaque));
+
+ hud_surface_ = skia::AdoptRef(SkSurface::NewRasterN32Premul(
+ content_bounds().width(), content_bounds().height()));
}
UpdateHudContents();
{
TRACE_EVENT0("cc", "DrawHudContents");
- hud_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
- hud_canvas_->save();
- hud_canvas_->scale(contents_scale_x(), contents_scale_y());
+ hud_surface_->getCanvas()->clear(SkColorSetARGB(0, 0, 0, 0));
+ hud_surface_->getCanvas()->save();
+ hud_surface_->getCanvas()->scale(contents_scale_x(), contents_scale_y());
- DrawHudContents(hud_canvas_.get());
+ DrawHudContents(hud_surface_->getCanvas());
- hud_canvas_->restore();
+ hud_surface_->getCanvas()->restore();
}
TRACE_EVENT0("cc", "UploadHudTexture");
SkImageInfo info;
size_t row_bytes = 0;
- const void* pixels = hud_canvas_->peekPixels(&info, &row_bytes);
+ const void* pixels = hud_surface_->getCanvas()->peekPixels(&info, &row_bytes);
DCHECK(pixels);
gfx::Rect content_rect(content_bounds());
DCHECK(info.colorType() == kN32_SkColorType);
@@ -300,7 +299,7 @@
paint->setTextSize(size);
paint->setTextAlign(align);
- paint->setTypeface(typeface_.get());
+ paint->setTypeface(layer_tree_impl()->settings().hud_typeface.get());
canvas->drawText(text.c_str(), text.length(), x, y, *paint);
paint->setAntiAlias(anti_alias);
@@ -706,7 +705,7 @@
SkPaint label_paint = CreatePaint();
label_paint.setTextSize(kFontHeight);
- label_paint.setTypeface(typeface_.get());
+ label_paint.setTypeface(layer_tree_impl()->settings().hud_typeface.get());
label_paint.setColor(stroke_color);
const SkScalar label_text_width =
diff --git a/cc/layers/heads_up_display_layer_impl.h b/cc/layers/heads_up_display_layer_impl.h
index 3e9436b..abba5dc 100644
--- a/cc/layers/heads_up_display_layer_impl.h
+++ b/cc/layers/heads_up_display_layer_impl.h
@@ -126,9 +126,7 @@
void ReleaseUnmatchedSizeResources(ResourceProvider* resource_provider);
ScopedPtrVector<ScopedResource> resources_;
- scoped_ptr<SkCanvas> hud_canvas_;
-
- skia::RefPtr<SkTypeface> typeface_;
+ skia::RefPtr<SkSurface> hud_surface_;
Graph fps_graph_;
Graph paint_time_graph_;
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index face433..01e67c5 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -71,6 +71,7 @@
force_render_surface_(false),
transform_is_invertible_(true),
has_render_surface_(false),
+ scroll_blocks_on_(ScrollBlocksOnNone),
background_color_(0),
opacity_(1.f),
blend_mode_(SkXfermode::kSrcOver_Mode),
@@ -758,6 +759,14 @@
SetNeedsCommit();
}
+void Layer::SetScrollBlocksOn(ScrollBlocksOn scroll_blocks_on) {
+ DCHECK(IsPropertyChangeAllowed());
+ if (scroll_blocks_on_ == scroll_blocks_on)
+ return;
+ scroll_blocks_on_ = scroll_blocks_on;
+ SetNeedsCommit();
+}
+
void Layer::SetDrawCheckerboardForMissingTiles(bool checkerboard) {
DCHECK(IsPropertyChangeAllowed());
if (draw_checkerboard_for_missing_tiles_ == checkerboard)
@@ -911,6 +920,7 @@
layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
+ layer->SetScrollBlocksOn(scroll_blocks_on_);
layer->SetContentsOpaque(contents_opaque_);
if (!layer->OpacityIsAnimatingOnImplOnly() && !OpacityIsAnimating())
layer->SetOpacity(opacity_);
@@ -978,10 +988,14 @@
layer->SetClipChildren(nullptr);
}
- layer->PushScrollOffsetFromMainThread(scroll_offset_);
- if (layer_animation_controller_->scroll_offset_animation_was_interrupted() &&
- layer->IsActive())
- layer->SetScrollDelta(gfx::Vector2dF());
+ // When a scroll offset animation is interrupted the new scroll position on
+ // the pending tree will clobber any impl-side scrolling occuring on the
+ // active tree. To do so, avoid scrolling the pending tree along with it
+ // instead of trying to undo that scrolling later.
+ if (layer_animation_controller_->scroll_offset_animation_was_interrupted())
+ layer->PushScrollOffsetFromMainThreadAndClobberActiveValue(scroll_offset_);
+ else
+ layer->PushScrollOffsetFromMainThread(scroll_offset_);
layer->SetScrollCompensationAdjustment(ScrollCompensationAdjustment());
// Wrap the copy_requests_ in a PostTask to the main thread.
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index db472c6..cf1356c 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -25,6 +25,7 @@
#include "cc/layers/layer_position_constraint.h"
#include "cc/layers/paint_properties.h"
#include "cc/layers/render_surface.h"
+#include "cc/layers/scroll_blocks_on.h"
#include "cc/output/filter_operations.h"
#include "cc/trees/property_tree.h"
#include "skia/ext/refptr.h"
@@ -43,10 +44,16 @@
}
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
}
+} // namespace base
namespace cc {
@@ -305,6 +312,9 @@
return touch_event_handler_region_;
}
+ void SetScrollBlocksOn(ScrollBlocksOn scroll_blocks_on);
+ ScrollBlocksOn scroll_blocks_on() const { return scroll_blocks_on_; }
+
void set_did_scroll_callback(const base::Closure& callback) {
did_scroll_callback_ = callback;
}
@@ -667,6 +677,7 @@
bool force_render_surface_ : 1;
bool transform_is_invertible_ : 1;
bool has_render_surface_ : 1;
+ ScrollBlocksOn scroll_blocks_on_ : 3;
Region non_fast_scrollable_region_;
Region touch_event_handler_region_;
gfx::PointF position_;
diff --git a/cc/layers/layer_client.h b/cc/layers/layer_client.h
index 4b98a95..efdbe51 100644
--- a/cc/layers/layer_client.h
+++ b/cc/layers/layer_client.h
@@ -11,10 +11,16 @@
#include "cc/base/cc_export.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
}
+} // namespace base
namespace cc {
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 55ffa7f..eae3685 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -54,6 +54,7 @@
should_scroll_on_main_thread_(false),
have_wheel_event_handlers_(false),
have_scroll_event_handlers_(false),
+ scroll_blocks_on_(ScrollBlocksOnNone),
user_scrollable_horizontal_(true),
user_scrollable_vertical_(true),
stacking_order_changed_(false),
@@ -392,7 +393,8 @@
InputHandler::ScrollStatus LayerImpl::TryScroll(
const gfx::PointF& screen_space_point,
- InputHandler::ScrollInputType type) const {
+ InputHandler::ScrollInputType type,
+ ScrollBlocksOn effective_block_mode) const {
if (should_scroll_on_main_thread()) {
TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
return InputHandler::ScrollOnMainThread;
@@ -430,7 +432,14 @@
}
}
- if (type == InputHandler::Wheel && have_wheel_event_handlers()) {
+ if (have_scroll_event_handlers() &&
+ effective_block_mode & ScrollBlocksOnScrollEvent) {
+ TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed ScrollEventHandlers");
+ return InputHandler::ScrollOnMainThread;
+ }
+
+ if (type == InputHandler::Wheel && have_wheel_event_handlers() &&
+ effective_block_mode & ScrollBlocksOnWheelEvent) {
TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
return InputHandler::ScrollOnMainThread;
}
@@ -487,6 +496,7 @@
layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
+ layer->SetScrollBlocksOn(scroll_blocks_on_);
layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
layer->SetContentsOpaque(contents_opaque_);
@@ -649,6 +659,17 @@
result->Set("TouchRegion", region.release());
}
+ if (scroll_blocks_on_) {
+ list = new base::ListValue;
+ if (scroll_blocks_on_ & ScrollBlocksOnStartTouch)
+ list->AppendString("StartTouch");
+ if (scroll_blocks_on_ & ScrollBlocksOnWheelEvent)
+ list->AppendString("WheelEvent");
+ if (scroll_blocks_on_ & ScrollBlocksOnScrollEvent)
+ list->AppendString("ScrollEvent");
+ result->Set("ScrollBlocksOn", list);
+ }
+
list = new base::ListValue;
for (size_t i = 0; i < children_.size(); ++i)
list->Append(children_[i]->LayerTreeAsJson());
@@ -1080,22 +1101,15 @@
PushScrollOffset(&scroll_offset);
}
+void LayerImpl::PushScrollOffsetFromMainThreadAndClobberActiveValue(
+ const gfx::ScrollOffset& scroll_offset) {
+ scroll_offset_->set_clobber_active_value();
+ PushScrollOffset(&scroll_offset);
+}
+
gfx::ScrollOffset LayerImpl::PullDeltaForMainThread() {
RefreshFromScrollDelegate();
-
- // TODO(aelias, miletus): Remove all this temporary flooring machinery when
- // Blink fully supports fractional scrolls.
- gfx::ScrollOffset current_offset = CurrentScrollOffset();
- gfx::Vector2dF current_delta = ScrollDelta();
- gfx::Vector2dF floored_delta(floor(current_delta.x()),
- floor(current_delta.y()));
- gfx::Vector2dF diff_delta = floored_delta - current_delta;
- gfx::ScrollOffset tmp_offset = ScrollOffsetWithDelta(current_offset,
- diff_delta);
- scroll_offset_->SetCurrent(tmp_offset);
- gfx::ScrollOffset delta = scroll_offset_->PullDeltaForMainThread();
- scroll_offset_->SetCurrent(current_offset);
- return delta;
+ return scroll_offset_->PullDeltaForMainThread();
}
void LayerImpl::RefreshFromScrollDelegate() {
@@ -1140,8 +1154,6 @@
}
if (IsActive()) {
changed |= scroll_offset_->PushPendingToActive();
- if (layer_animation_controller_->scroll_offset_animation_was_interrupted())
- SetScrollDelta(gfx::Vector2dF());
}
if (changed)
@@ -1177,6 +1189,9 @@
void LayerImpl::ReleaseResources() {}
+void LayerImpl::RecreateResources() {
+}
+
gfx::ScrollOffset LayerImpl::MaxScrollOffset() const {
if (!scroll_clip_layer_ || bounds().IsEmpty())
return gfx::ScrollOffset();
@@ -1440,6 +1455,9 @@
non_fast_scrollable_region_.AsValueInto(state);
state->EndArray();
}
+ if (scroll_blocks_on_) {
+ state->SetInteger("scroll_blocks_on", scroll_blocks_on_);
+ }
state->BeginArray("children");
for (size_t i = 0; i < children_.size(); ++i) {
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index f46c16e..96f915f 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -27,6 +27,7 @@
#include "cc/layers/layer_lists.h"
#include "cc/layers/layer_position_constraint.h"
#include "cc/layers/render_surface_impl.h"
+#include "cc/layers/scroll_blocks_on.h"
#include "cc/output/filter_operations.h"
#include "cc/quads/shared_quad_state.h"
#include "cc/resources/resource_provider.h"
@@ -41,13 +42,19 @@
#include "ui/gfx/transform.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
}
-class DictionaryValue;
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
}
+class DictionaryValue;
+} // namespace base
namespace cc {
@@ -399,6 +406,11 @@
void SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset);
void PushScrollOffsetFromMainThread(const gfx::ScrollOffset& scroll_offset);
+ // This method is similar to PushScrollOffsetFromMainThread but will cause the
+ // scroll offset given to clobber any scroll changes on the active tree in the
+ // time until this value is pushed to the active tree.
+ void PushScrollOffsetFromMainThreadAndClobberActiveValue(
+ const gfx::ScrollOffset& scroll_offset);
gfx::ScrollOffset PullDeltaForMainThread();
gfx::ScrollOffset CurrentScrollOffset() const;
gfx::ScrollOffset BaseScrollOffset() const;
@@ -474,6 +486,10 @@
return touch_event_handler_region_;
}
+ void SetScrollBlocksOn(ScrollBlocksOn scroll_blocks_on) {
+ scroll_blocks_on_ = scroll_blocks_on;
+ }
+ ScrollBlocksOn scroll_blocks_on() const { return scroll_blocks_on_; }
void SetDrawCheckerboardForMissingTiles(bool checkerboard) {
draw_checkerboard_for_missing_tiles_ = checkerboard;
}
@@ -483,7 +499,8 @@
InputHandler::ScrollStatus TryScroll(
const gfx::PointF& screen_space_point,
- InputHandler::ScrollInputType type) const;
+ InputHandler::ScrollInputType type,
+ ScrollBlocksOn effective_block_mode) const;
void SetDoubleSided(bool double_sided);
bool double_sided() const { return double_sided_; }
@@ -530,6 +547,10 @@
// that rendered this layer was lost or a rendering mode switch has occured.
virtual void ReleaseResources();
+ // Recreate resources that are required after they were released by a
+ // ReleaseResources call.
+ virtual void RecreateResources();
+
ScrollbarAnimationController* scrollbar_animation_controller() const {
return scrollbar_animation_controller_.get();
}
@@ -657,6 +678,10 @@
bool should_scroll_on_main_thread_ : 1;
bool have_wheel_event_handlers_ : 1;
bool have_scroll_event_handlers_ : 1;
+
+ static_assert(ScrollBlocksOnMax < (1 << 3), "ScrollBlocksOn too big");
+ ScrollBlocksOn scroll_blocks_on_ : 3;
+
bool user_scrollable_horizontal_ : 1;
bool user_scrollable_vertical_ : 1;
bool stacking_order_changed_ : 1;
diff --git a/cc/layers/picture_image_layer.cc b/cc/layers/picture_image_layer.cc
index 85bc582..9f35d6e 100644
--- a/cc/layers/picture_image_layer.cc
+++ b/cc/layers/picture_image_layer.cc
@@ -47,7 +47,7 @@
void PictureImageLayer::PaintContents(
SkCanvas* canvas,
const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus gc_status) {
+ ContentLayerClient::PaintingControlSetting painting_control) {
if (!bitmap_.width() || !bitmap_.height())
return;
@@ -65,12 +65,12 @@
scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) {
+ ContentLayerClient::PaintingControlSetting painting_control) {
scoped_refptr<DisplayItemList> display_item_list = DisplayItemList::Create();
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(gfx::RectToSkRect(clip));
- PaintContents(canvas, clip, gc_status);
+ PaintContents(canvas, clip, painting_control);
skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
display_item_list->AppendItem(
diff --git a/cc/layers/picture_image_layer.h b/cc/layers/picture_image_layer.h
index 57c7de2..8d40550 100644
--- a/cc/layers/picture_image_layer.h
+++ b/cc/layers/picture_image_layer.h
@@ -26,10 +26,10 @@
void PaintContents(
SkCanvas* canvas,
const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus gc_status) override;
+ ContentLayerClient::PaintingControlSetting painting_control) override;
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override;
+ ContentLayerClient::PaintingControlSetting painting_control) override;
bool FillsBoundsCompletely() const override;
protected:
diff --git a/cc/layers/picture_image_layer_unittest.cc b/cc/layers/picture_image_layer_unittest.cc
index acf691d..5b9375d 100644
--- a/cc/layers/picture_image_layer_unittest.cc
+++ b/cc/layers/picture_image_layer_unittest.cc
@@ -35,7 +35,7 @@
scoped_refptr<DisplayItemList> display_list =
layer->PaintContentsToDisplayList(
- layer_rect, ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+ layer_rect, ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
unsigned char actual_pixels[4 * 200 * 200] = {0};
DrawDisplayList(actual_pixels, layer_rect, display_list);
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index 0b7d699..52288e9 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -148,7 +148,7 @@
updated |= recording_source_->UpdateAndExpandInvalidation(
client_, &recording_invalidation_, can_use_lcd_text_for_update_,
layer_size, visible_layer_rect, update_source_frame_number_,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
last_updated_visible_content_rect_ = visible_content_rect();
if (updated) {
@@ -192,9 +192,8 @@
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0);
- client_->PaintContents(canvas,
- gfx::Rect(width, height),
- ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+ client_->PaintContents(canvas, gfx::Rect(width, height),
+ ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
return picture;
}
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 15059ba..3a0753f 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -602,8 +602,12 @@
void PictureLayerImpl::ReleaseResources() {
// Recreate tilings with new settings, since some of those might change when
// we release resources.
- tilings_ = CreatePictureLayerTilingSet();
+ tilings_ = nullptr;
ResetRasterScale();
+}
+
+void PictureLayerImpl::RecreateResources() {
+ tilings_ = CreatePictureLayerTilingSet();
// To avoid an edge case after lost context where the tree is up to date but
// the tilings have not been managed, request an update draw properties
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index fa40683..e7f4fba 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -62,6 +62,7 @@
void NotifyTileStateChanged(const Tile* tile) override;
void DidBeginTracing() override;
void ReleaseResources() override;
+ void RecreateResources() override;
skia::RefPtr<SkPicture> GetPicture() override;
// PictureLayerTilingClient overrides.
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 0a95f31..600f3e2 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -278,11 +278,14 @@
void ResetTilingsAndRasterScales() {
pending_layer_->ReleaseResources();
+ EXPECT_FALSE(pending_layer_->tilings());
+ pending_layer_->RecreateResources();
+ EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
+
active_layer_->ReleaseResources();
- if (pending_layer_)
- EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
- if (active_layer_)
- EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+ EXPECT_FALSE(active_layer_->tilings());
+ active_layer_->RecreateResources();
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
}
void AssertAllTilesRequired(PictureLayerTiling* tiling) {
@@ -711,7 +714,7 @@
VerifyAllTilesExistAndHavePile(tilings->tiling_at(i), pending_pile.get());
}
-TEST_F(PictureLayerImplTest, ManageTilingsCreatesTilings) {
+TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings) {
gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);
@@ -726,6 +729,8 @@
EXPECT_LT(low_res_factor, 1.f);
active_layer_->ReleaseResources();
+ EXPECT_FALSE(active_layer_->tilings());
+ active_layer_->RecreateResources();
EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
SetupDrawPropertiesAndUpdateTiles(active_layer_,
@@ -796,6 +801,8 @@
EXPECT_LT(low_res_factor, 1.f);
pending_layer_->ReleaseResources();
+ EXPECT_FALSE(pending_layer_->tilings());
+ pending_layer_->RecreateResources();
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
SetupDrawPropertiesAndUpdateTiles(pending_layer_,
@@ -1326,6 +1333,8 @@
// Drop resources and recreate them, still the same.
pending_mask->ReleaseResources();
active_mask->ReleaseResources();
+ pending_mask->RecreateResources();
+ active_mask->RecreateResources();
SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, false);
active_mask->HighResTiling()->CreateAllTilesForTesting();
EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
@@ -1369,6 +1378,8 @@
// Drop resources and recreate them, still the same.
pending_mask->ReleaseResources();
active_mask->ReleaseResources();
+ pending_mask->RecreateResources();
+ active_mask->RecreateResources();
SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, false);
active_mask->HighResTiling()->CreateAllTilesForTesting();
EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
@@ -1475,8 +1486,12 @@
// All tilings should be removed when losing output surface.
active_layer_->ReleaseResources();
+ EXPECT_FALSE(active_layer_->tilings());
+ active_layer_->RecreateResources();
EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
pending_layer_->ReleaseResources();
+ EXPECT_FALSE(pending_layer_->tilings());
+ pending_layer_->RecreateResources();
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
// This should create new tilings.
@@ -3744,8 +3759,12 @@
// All tilings should be removed when losing output surface.
active_layer_->ReleaseResources();
+ EXPECT_FALSE(active_layer_->tilings());
+ active_layer_->RecreateResources();
EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
pending_layer_->ReleaseResources();
+ EXPECT_FALSE(pending_layer_->tilings());
+ pending_layer_->RecreateResources();
EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings());
// This should create new tilings.
@@ -4644,7 +4663,7 @@
Region invalidation(layer_rect);
recording_source->UpdateAndExpandInvalidation(
&client, &invalidation, false, layer_bounds, layer_rect, frame_number++,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
scoped_refptr<RasterSource> pending_raster_source =
recording_source->CreateRasterSource();
@@ -4707,7 +4726,7 @@
Region invalidation1(layer_rect);
recording_source->UpdateAndExpandInvalidation(
&client, &invalidation1, false, layer_bounds, layer_rect, frame_number++,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
scoped_refptr<RasterSource> raster_source1 =
recording_source->CreateRasterSource();
@@ -4725,7 +4744,7 @@
Region invalidation2(layer_rect);
recording_source->UpdateAndExpandInvalidation(
&client, &invalidation2, false, layer_bounds, layer_rect, frame_number++,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
scoped_refptr<RasterSource> raster_source2 =
recording_source->CreateRasterSource();
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index 9327e13..afb6096 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -20,13 +20,12 @@
class MockContentLayerClient : public ContentLayerClient {
public:
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus gc_status) override {}
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {}
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override {
+ PaintingControlSetting picture_control) override {
NOTIMPLEMENTED();
return DisplayItemList::Create();
}
diff --git a/cc/layers/scroll_blocks_on.h b/cc/layers/scroll_blocks_on.h
new file mode 100644
index 0000000..2447298
--- /dev/null
+++ b/cc/layers/scroll_blocks_on.h
@@ -0,0 +1,25 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_LAYERS_SCROLL_BLOCKS_ON_H_
+#define CC_LAYERS_SCROLL_BLOCKS_ON_H_
+
+enum ScrollBlocksOn {
+ ScrollBlocksOnNone = 0x0,
+ ScrollBlocksOnStartTouch = 0x1,
+ ScrollBlocksOnWheelEvent = 0x2,
+ ScrollBlocksOnScrollEvent = 0x4,
+ ScrollBlocksOnMax = ScrollBlocksOnStartTouch | ScrollBlocksOnWheelEvent |
+ ScrollBlocksOnScrollEvent
+};
+
+inline ScrollBlocksOn operator|(ScrollBlocksOn a, ScrollBlocksOn b) {
+ return ScrollBlocksOn(static_cast<int>(a) | static_cast<int>(b));
+}
+
+inline ScrollBlocksOn& operator|=(ScrollBlocksOn& a, ScrollBlocksOn b) {
+ return a = a | b;
+}
+
+#endif // CC_LAYERS_SCROLL_BLOCKS_ON_H_
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 09de7d0..b24dcb1 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -107,8 +107,8 @@
// responded to on the main thread as the compositor does not yet implement
// scrollbar scrolling.
EXPECT_EQ(InputHandler::ScrollOnMainThread,
- scrollbar_layer_impl->TryScroll(gfx::Point(0, 0),
- InputHandler::Gesture));
+ scrollbar_layer_impl->TryScroll(
+ gfx::Point(0, 0), InputHandler::Gesture, ScrollBlocksOnNone));
// Create and attach an overlay scrollbar.
scrollbar.reset(new FakeScrollbar(false, false, true));
@@ -121,8 +121,8 @@
// The user shouldn't be able to drag an overlay scrollbar and the scroll
// may be handled in the compositor.
EXPECT_EQ(InputHandler::ScrollIgnored,
- scrollbar_layer_impl->TryScroll(gfx::Point(0, 0),
- InputHandler::Gesture));
+ scrollbar_layer_impl->TryScroll(
+ gfx::Point(0, 0), InputHandler::Gesture, ScrollBlocksOnNone));
}
TEST(PaintedScrollbarLayerTest, ScrollOffsetSynchronization) {
diff --git a/cc/output/begin_frame_args.h b/cc/output/begin_frame_args.h
index 53745f9..47430ca 100644
--- a/cc/output/begin_frame_args.h
+++ b/cc/output/begin_frame_args.h
@@ -12,11 +12,18 @@
#include "cc/base/cc_export.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
}
+} // namespace base
/**
* In debug builds we trace the creation origin of BeginFrameArgs objects. We
diff --git a/cc/output/filter_operation.h b/cc/output/filter_operation.h
index fc14cb1..157db99 100644
--- a/cc/output/filter_operation.h
+++ b/cc/output/filter_operation.h
@@ -16,11 +16,17 @@
#include "ui/gfx/geometry/point.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
-class Value;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+class Value;
+} // namespace base
namespace cc {
diff --git a/cc/output/filter_operations.h b/cc/output/filter_operations.h
index a8c206e..8e37933 100644
--- a/cc/output/filter_operations.h
+++ b/cc/output/filter_operations.h
@@ -12,11 +12,17 @@
#include "cc/output/filter_operation.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
-class Value;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+class Value;
+} // namespace base
namespace cc {
diff --git a/cc/output/overlay_candidate.cc b/cc/output/overlay_candidate.cc
index 4168253..46c3a7d 100644
--- a/cc/output/overlay_candidate.cc
+++ b/cc/output/overlay_candidate.cc
@@ -24,7 +24,7 @@
gfx::OverlayTransform OverlayCandidate::GetOverlayTransform(
const gfx::Transform& quad_transform,
bool flipped) {
- if (!quad_transform.IsIdentityOrTranslation())
+ if (!quad_transform.IsPositiveScaleOrTranslation())
return gfx::OVERLAY_TRANSFORM_INVALID;
return flipped ? gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
@@ -32,9 +32,105 @@
}
// static
+gfx::OverlayTransform OverlayCandidate::ModifyTransform(
+ gfx::OverlayTransform in,
+ gfx::OverlayTransform delta) {
+ // There are 8 different possible transforms. We can characterize these
+ // by looking at where the origin moves and the direction the horizontal goes.
+ // (TL=top-left, BR=bottom-right, H=horizontal, V=vertical).
+ // NONE: TL, H
+ // FLIP_VERTICAL: BL, H
+ // FLIP_HORIZONTAL: TR, H
+ // ROTATE_90: TR, V
+ // ROTATE_180: BR, H
+ // ROTATE_270: BL, V
+ // Missing transforms: TL, V & BR, V
+ // Basic combinations:
+ // Flip X & Y -> Rotate 180 (TL,H -> TR,H -> BR,H or TL,H -> BL,H -> BR,H)
+ // Flip X or Y + Rotate 180 -> other flip (eg, TL,H -> TR,H -> BL,H)
+ // Rotate + Rotate simply adds values.
+ // Rotate 90/270 + flip is invalid because we can only have verticals with
+ // the origin in TR or BL.
+ if (delta == gfx::OVERLAY_TRANSFORM_NONE)
+ return in;
+ switch (in) {
+ case gfx::OVERLAY_TRANSFORM_NONE:
+ return delta;
+ case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+ return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+ case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+ return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+}
+
+// static
gfx::Rect OverlayCandidate::GetOverlayRect(const gfx::Transform& quad_transform,
const gfx::Rect& rect) {
- DCHECK(quad_transform.IsIdentityOrTranslation());
+ DCHECK(quad_transform.IsPositiveScaleOrTranslation());
gfx::RectF float_rect(rect);
quad_transform.TransformRect(&float_rect);
diff --git a/cc/output/overlay_candidate.h b/cc/output/overlay_candidate.h
index 9a1e534..28ae8cb 100644
--- a/cc/output/overlay_candidate.h
+++ b/cc/output/overlay_candidate.h
@@ -20,6 +20,10 @@
static gfx::OverlayTransform GetOverlayTransform(
const gfx::Transform& quad_transform,
bool flipped);
+ // Apply transform |delta| to |in| and return the resulting transform,
+ // or OVERLAY_TRANSFORM_INVALID.
+ static gfx::OverlayTransform ModifyTransform(gfx::OverlayTransform in,
+ gfx::OverlayTransform delta);
static gfx::Rect GetOverlayRect(const gfx::Transform& quad_transform,
const gfx::Rect& rect);
diff --git a/cc/output/overlay_strategy_single_on_top.cc b/cc/output/overlay_strategy_single_on_top.cc
index 98d77ad..9a95206 100644
--- a/cc/output/overlay_strategy_single_on_top.cc
+++ b/cc/output/overlay_strategy_single_on_top.cc
@@ -4,8 +4,13 @@
#include "cc/output/overlay_strategy_single_on_top.h"
+#include <limits>
+
#include "cc/quads/draw_quad.h"
+#include "cc/quads/solid_color_draw_quad.h"
+#include "cc/quads/stream_video_draw_quad.h"
#include "cc/quads/texture_draw_quad.h"
+#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/transform.h"
@@ -17,6 +22,103 @@
: capability_checker_(capability_checker),
resource_provider_(resource_provider) {}
+bool OverlayStrategySingleOnTop::IsOverlayQuad(const DrawQuad* draw_quad) {
+ unsigned int resource_id;
+ switch (draw_quad->material) {
+ case DrawQuad::TEXTURE_CONTENT:
+ resource_id = TextureDrawQuad::MaterialCast(draw_quad)->resource_id;
+ break;
+ case DrawQuad::STREAM_VIDEO_CONTENT:
+ resource_id = StreamVideoDrawQuad::MaterialCast(draw_quad)->resource_id;
+ break;
+ default:
+ return false;
+ }
+ return resource_provider_->AllowOverlay(resource_id);
+}
+
+bool OverlayStrategySingleOnTop::GetTextureQuadInfo(
+ const TextureDrawQuad& quad,
+ OverlayCandidate* quad_info) {
+ gfx::OverlayTransform overlay_transform =
+ OverlayCandidate::GetOverlayTransform(quad.quadTransform(), quad.flipped);
+ if (quad.background_color != SK_ColorTRANSPARENT ||
+ quad.premultiplied_alpha ||
+ overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
+ return false;
+ quad_info->resource_id = quad.resource_id;
+ quad_info->transform = overlay_transform;
+ quad_info->uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right);
+ return true;
+}
+
+bool OverlayStrategySingleOnTop::GetVideoQuadInfo(
+ const StreamVideoDrawQuad& quad,
+ OverlayCandidate* quad_info) {
+ gfx::OverlayTransform overlay_transform =
+ OverlayCandidate::GetOverlayTransform(quad.quadTransform(), false);
+ if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
+ return false;
+ if (!quad.matrix.IsScaleOrTranslation()) {
+ // We cannot handle anything other than scaling & translation for texture
+ // coordinates yet.
+ return false;
+ }
+ quad_info->resource_id = quad.resource_id;
+ quad_info->transform = overlay_transform;
+
+ gfx::Point3F uv0 = gfx::Point3F(0, 0, 0);
+ gfx::Point3F uv1 = gfx::Point3F(1, 1, 0);
+ quad.matrix.TransformPoint(&uv0);
+ quad.matrix.TransformPoint(&uv1);
+ gfx::Vector3dF delta = uv1 - uv0;
+ if (delta.x() < 0) {
+ quad_info->transform = OverlayCandidate::ModifyTransform(
+ quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL);
+ float x0 = uv0.x();
+ uv0.set_x(uv1.x());
+ uv1.set_x(x0);
+ delta.set_x(-delta.x());
+ }
+
+ if (delta.y() < 0) {
+ // In this situation, uv0y < uv1y. Since we overlay inverted, a request
+ // to invert the source texture means we can just output the texture
+ // normally and it will be correct.
+ quad_info->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y());
+ } else {
+ quad_info->transform = OverlayCandidate::ModifyTransform(
+ quad_info->transform, gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL);
+ quad_info->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y());
+ }
+ return true;
+}
+
+bool OverlayStrategySingleOnTop::GetCandidateQuadInfo(
+ const DrawQuad& draw_quad,
+ OverlayCandidate* quad_info) {
+ // All quad checks.
+ if (draw_quad.needs_blending || draw_quad.shared_quad_state->opacity != 1.f ||
+ draw_quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode)
+ return false;
+
+ if (draw_quad.material == DrawQuad::TEXTURE_CONTENT) {
+ const TextureDrawQuad& quad = *TextureDrawQuad::MaterialCast(&draw_quad);
+ if (!GetTextureQuadInfo(quad, quad_info))
+ return false;
+ } else if (draw_quad.material == DrawQuad::STREAM_VIDEO_CONTENT) {
+ const StreamVideoDrawQuad& quad =
+ *StreamVideoDrawQuad::MaterialCast(&draw_quad);
+ if (!GetVideoQuadInfo(quad, quad_info))
+ return false;
+ }
+
+ quad_info->format = RGBA_8888;
+ quad_info->display_rect = OverlayCandidate::GetOverlayRect(
+ draw_quad.quadTransform(), draw_quad.rect);
+ return true;
+}
+
bool OverlayStrategySingleOnTop::Attempt(
RenderPassList* render_passes_in_draw_order,
OverlayCandidateList* candidate_list) {
@@ -27,15 +129,12 @@
RenderPass* root_render_pass = render_passes_in_draw_order->back();
DCHECK(root_render_pass);
+ OverlayCandidate candidate;
QuadList& quad_list = root_render_pass->quad_list;
auto candidate_iterator = quad_list.end();
for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
const DrawQuad* draw_quad = *it;
- if (draw_quad->material == DrawQuad::TEXTURE_CONTENT) {
- const TextureDrawQuad& quad = *TextureDrawQuad::MaterialCast(draw_quad);
- if (!resource_provider_->AllowOverlay(quad.resource_id)) {
- continue;
- }
+ if (IsOverlayQuad(draw_quad)) {
// Check that no prior quads overlap it.
bool intersects = false;
gfx::RectF rect = draw_quad->rect;
@@ -49,7 +148,7 @@
break;
}
}
- if (intersects)
+ if (intersects || !GetCandidateQuadInfo(*draw_quad, &candidate))
continue;
candidate_iterator = it;
break;
@@ -57,34 +156,14 @@
}
if (candidate_iterator == quad_list.end())
return false;
- const TextureDrawQuad& quad =
- *TextureDrawQuad::MaterialCast(*candidate_iterator);
-
- // Simple quads only.
- gfx::OverlayTransform overlay_transform =
- OverlayCandidate::GetOverlayTransform(quad.quadTransform(), quad.flipped);
- if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID ||
- !quad.quadTransform().IsIdentityOrTranslation() || quad.needs_blending ||
- quad.shared_quad_state->opacity != 1.f ||
- quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode ||
- quad.premultiplied_alpha || quad.background_color != SK_ColorTRANSPARENT)
- return false;
// Add our primary surface.
OverlayCandidateList candidates;
OverlayCandidate main_image;
main_image.display_rect = root_render_pass->output_rect;
- main_image.format = RGBA_8888;
candidates.push_back(main_image);
// Add the overlay.
- OverlayCandidate candidate;
- candidate.transform = overlay_transform;
- candidate.display_rect =
- OverlayCandidate::GetOverlayRect(quad.quadTransform(), quad.rect);
- candidate.uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right);
- candidate.format = RGBA_8888;
- candidate.resource_id = quad.resource_id;
candidate.plane_z_order = 1;
candidates.push_back(candidate);
diff --git a/cc/output/overlay_strategy_single_on_top.h b/cc/output/overlay_strategy_single_on_top.h
index e5518cc..f92e104 100644
--- a/cc/output/overlay_strategy_single_on_top.h
+++ b/cc/output/overlay_strategy_single_on_top.h
@@ -14,6 +14,8 @@
namespace cc {
class OverlayCandidateValidator;
+class StreamVideoDrawQuad;
+class TextureDrawQuad;
class CC_EXPORT OverlayStrategySingleOnTop : public OverlayProcessor::Strategy {
public:
@@ -23,6 +25,15 @@
OverlayCandidateList* candidate_list) override;
private:
+ bool IsOverlayQuad(const DrawQuad* draw_quad);
+ bool GetCandidateQuadInfo(const DrawQuad& draw_quad,
+ OverlayCandidate* quad_info);
+
+ bool GetTextureQuadInfo(const TextureDrawQuad& quad,
+ OverlayCandidate* quad_info);
+ bool GetVideoQuadInfo(const StreamVideoDrawQuad& quad,
+ OverlayCandidate* quad_info);
+
OverlayCandidateValidator* capability_checker_;
ResourceProvider* resource_provider_;
DISALLOW_COPY_AND_ASSIGN(OverlayStrategySingleOnTop);
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index 8fa35cb..4682679 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -11,6 +11,7 @@
#include "cc/output/overlay_strategy_single_on_top.h"
#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/render_pass.h"
+#include "cc/quads/stream_video_draw_quad.h"
#include "cc/quads/texture_draw_quad.h"
#include "cc/resources/resource_provider.h"
#include "cc/resources/texture_mailbox.h"
@@ -32,6 +33,16 @@
const gfx::Rect kOverlayBottomRightRect(64, 64, 64, 64);
const gfx::PointF kUVTopLeft(0.1f, 0.2f);
const gfx::PointF kUVBottomRight(1.0f, 1.0f);
+const gfx::Transform kNormalTransform =
+ gfx::Transform(0.9f, 0, 0, 0.8f, 0.1f, 0.2f); // x,y -> x,y.
+const gfx::Transform kXMirrorTransform =
+ gfx::Transform(-0.9f, 0, 0, 0.8f, 1.0f, 0.2f); // x,y -> 1-x,y.
+const gfx::Transform kYMirrorTransform =
+ gfx::Transform(0.9f, 0, 0, -0.8f, 0.1f, 1.0f); // x,y -> x,1-y.
+const gfx::Transform kBothMirrorTransform =
+ gfx::Transform(-0.9f, 0, 0, -0.8f, 1.0f, 1.0f); // x,y -> 1-x,1-y.
+const gfx::Transform kSwapTransform =
+ gfx::Transform(0, 1, 1, 0, 0, 0); // x,y -> y,x.
void MailboxReleased(unsigned sync_point,
bool lost_resource,
@@ -173,6 +184,22 @@
return overlay_quad;
}
+StreamVideoDrawQuad* CreateCandidateVideoQuadAt(
+ ResourceProvider* resource_provider,
+ const SharedQuadState* shared_quad_state,
+ RenderPass* render_pass,
+ const gfx::Rect& rect,
+ const gfx::Transform& transform) {
+ ResourceProvider::ResourceId resource_id = CreateResource(resource_provider);
+
+ StreamVideoDrawQuad* overlay_quad =
+ render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>();
+ overlay_quad->SetNew(shared_quad_state, rect, rect, rect, resource_id,
+ transform);
+
+ return overlay_quad;
+}
+
TextureDrawQuad* CreateFullscreenCandidateQuad(
ResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
@@ -181,6 +208,15 @@
resource_provider, shared_quad_state, render_pass, kOverlayRect);
}
+StreamVideoDrawQuad* CreateFullscreenCandidateVideoQuad(
+ ResourceProvider* resource_provider,
+ const SharedQuadState* shared_quad_state,
+ RenderPass* render_pass,
+ const gfx::Transform& transform) {
+ return CreateCandidateVideoQuadAt(resource_provider, shared_quad_state,
+ render_pass, kOverlayRect, transform);
+}
+
void CreateCheckeredQuadAt(ResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass,
@@ -484,13 +520,13 @@
EXPECT_EQ(0U, candidate_list.size());
}
-TEST_F(SingleOverlayOnTopTest, RejectTransform) {
+TEST_F(SingleOverlayOnTopTest, RejectNonScaleTransform) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(),
pass.get());
- pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.f,
- 2.f);
+ pass->shared_quad_state_list.back()
+ ->content_to_target_transform.RotateAboutXAxis(45.f);
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -500,6 +536,39 @@
EXPECT_EQ(0U, candidate_list.size());
}
+TEST_F(SingleOverlayOnTopTest, RejectNegativeScaleTransform) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(),
+ pass.get());
+ pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.0f,
+ -1.0f);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ EXPECT_EQ(0U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) {
+ gfx::Rect rect = kOverlayRect;
+ rect.set_width(rect.width() / 2);
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(), rect);
+ pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.0f,
+ 1.0f);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ EXPECT_EQ(2U, candidate_list.size());
+}
+
TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
CreateCheckeredQuadAt(resource_provider_.get(),
@@ -523,6 +592,76 @@
EXPECT_EQ(2U, candidate_list.size());
}
+TEST_F(SingleOverlayOnTopTest, RejectVideoSwapTransform) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(),
+ pass.get(), kSwapTransform);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ EXPECT_EQ(0U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowVideoXMirrorTransform) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(),
+ pass.get(), kXMirrorTransform);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ EXPECT_EQ(2U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowVideoBothMirrorTransform) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(),
+ pass.get(), kBothMirrorTransform);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ EXPECT_EQ(2U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowVideoNormalTransform) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(),
+ pass.get(), kNormalTransform);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ EXPECT_EQ(2U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(),
+ pass.get(), kYMirrorTransform);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ ASSERT_EQ(1U, pass_list.size());
+ EXPECT_EQ(2U, candidate_list.size());
+}
+
class OverlayInfoRendererGL : public GLRenderer {
public:
OverlayInfoRendererGL(RendererClient* client,
diff --git a/cc/quads/draw_quad.h b/cc/quads/draw_quad.h
index 61ca358..d9395cd 100644
--- a/cc/quads/draw_quad.h
+++ b/cc/quads/draw_quad.h
@@ -11,12 +11,18 @@
#include "cc/resources/resource_provider.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
+}
class Value;
class DictionaryValue;
-}
+} // namespace base
namespace cc {
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 2877588..8a40f17 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -20,11 +20,17 @@
#include "ui/gfx/transform.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
class Value;
-};
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
+}
+} // namespace base
namespace cc {
diff --git a/cc/quads/shared_quad_state.h b/cc/quads/shared_quad_state.h
index ebf7d11..0db23e1 100644
--- a/cc/quads/shared_quad_state.h
+++ b/cc/quads/shared_quad_state.h
@@ -12,11 +12,17 @@
#include "ui/gfx/transform.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
class Value;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
diff --git a/cc/resources/bitmap_tile_task_worker_pool.h b/cc/resources/bitmap_tile_task_worker_pool.h
index 404a3a5..20d57d2 100644
--- a/cc/resources/bitmap_tile_task_worker_pool.h
+++ b/cc/resources/bitmap_tile_task_worker_pool.h
@@ -11,10 +11,16 @@
#include "cc/resources/tile_task_worker_pool.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
}
+} // namespace base
namespace cc {
class ResourceProvider;
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc
index 7b98e50..e60e4c1 100644
--- a/cc/resources/display_list_recording_source.cc
+++ b/cc/resources/display_list_recording_source.cc
@@ -45,7 +45,7 @@
const gfx::Size& layer_size,
const gfx::Rect& visible_layer_rect,
int frame_number,
- Picture::RecordingMode recording_mode) {
+ RecordingMode recording_mode) {
bool updated = false;
if (size_ != layer_size) {
@@ -81,12 +81,37 @@
if (!updated && !invalidation->Intersects(recorded_viewport_))
return false;
- // TODO(ajuma): Does repeating this way really makes sense with display lists?
- // With Blink caching recordings, repeated calls will not cause re-recording.
- int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
+ ContentLayerClient::PaintingControlSetting painting_control =
+ ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
+
+ switch (recording_mode) {
+ case RECORD_NORMALLY:
+ // Already setup for normal recording.
+ break;
+ case RECORD_WITH_SK_NULL_CANVAS:
+ // TODO(schenney): Remove this when DisplayList recording is the only
+ // option. For now, fall through and disable construction.
+ case RECORD_WITH_PAINTING_DISABLED:
+ painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
+ break;
+ case RECORD_WITH_CACHING_DISABLED:
+ painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ int repeat_count = 1;
+ if (slow_down_raster_scale_factor_for_debug_ > 1) {
+ repeat_count = slow_down_raster_scale_factor_for_debug_;
+ if (painting_control !=
+ ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED) {
+ painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
+ }
+ }
for (int i = 0; i < repeat_count; ++i) {
- display_list_ = painter->PaintContentsToDisplayList(
- recorded_viewport_, ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+ display_list_ = painter->PaintContentsToDisplayList(recorded_viewport_,
+ painting_control);
}
display_list_->set_layer_rect(recorded_viewport_);
is_suitable_for_gpu_rasterization_ =
diff --git a/cc/resources/display_list_recording_source.h b/cc/resources/display_list_recording_source.h
index a2c8ea6..05e2ed7 100644
--- a/cc/resources/display_list_recording_source.h
+++ b/cc/resources/display_list_recording_source.h
@@ -18,14 +18,13 @@
~DisplayListRecordingSource() override;
// RecordingSource overrides.
- bool UpdateAndExpandInvalidation(
- ContentLayerClient* painter,
- Region* invalidation,
- bool can_use_lcd_text,
- const gfx::Size& layer_size,
- const gfx::Rect& visible_layer_rect,
- int frame_number,
- Picture::RecordingMode recording_mode) override;
+ bool UpdateAndExpandInvalidation(ContentLayerClient* painter,
+ Region* invalidation,
+ bool can_use_lcd_text,
+ const gfx::Size& layer_size,
+ const gfx::Rect& visible_layer_rect,
+ int frame_number,
+ RecordingMode recording_mode) override;
scoped_refptr<RasterSource> CreateRasterSource() const override;
gfx::Size GetSize() const final;
void SetEmptyBounds() override;
diff --git a/cc/resources/gpu_rasterizer.cc b/cc/resources/gpu_rasterizer.cc
index 3fdc8bb..369f12c 100644
--- a/cc/resources/gpu_rasterizer.cc
+++ b/cc/resources/gpu_rasterizer.cc
@@ -31,22 +31,22 @@
ContextProvider* context_provider,
ResourceProvider* resource_provider,
bool use_distance_field_text,
- bool tile_prepare_enabled,
+ bool threaded_gpu_rasterization_enabled,
int msaa_sample_count) {
return make_scoped_ptr<GpuRasterizer>(new GpuRasterizer(
context_provider, resource_provider, use_distance_field_text,
- tile_prepare_enabled, msaa_sample_count));
+ threaded_gpu_rasterization_enabled, msaa_sample_count));
}
GpuRasterizer::GpuRasterizer(ContextProvider* context_provider,
ResourceProvider* resource_provider,
bool use_distance_field_text,
- bool tile_prepare_enabled,
+ bool threaded_gpu_rasterization_enabled,
int msaa_sample_count)
: context_provider_(context_provider),
resource_provider_(resource_provider),
use_distance_field_text_(use_distance_field_text),
- tile_prepare_enabled_(tile_prepare_enabled),
+ threaded_gpu_rasterization_enabled_(threaded_gpu_rasterization_enabled),
msaa_sample_count_(msaa_sample_count) {
DCHECK(context_provider_);
}
@@ -55,8 +55,7 @@
}
PrepareTilesMode GpuRasterizer::GetPrepareTilesMode() {
- return tile_prepare_enabled_ ? PrepareTilesMode::PREPARE_PRIORITIZED_TILES
- : PrepareTilesMode::PREPARE_NONE;
+ return PrepareTilesMode::PREPARE_NONE;
}
void GpuRasterizer::RasterizeTiles(
diff --git a/cc/resources/gpu_rasterizer.h b/cc/resources/gpu_rasterizer.h
index 206b051..79a0596 100644
--- a/cc/resources/gpu_rasterizer.h
+++ b/cc/resources/gpu_rasterizer.h
@@ -22,11 +22,12 @@
public:
~GpuRasterizer() override;
- static scoped_ptr<GpuRasterizer> Create(ContextProvider* context_provider,
- ResourceProvider* resource_provider,
- bool use_distance_field_text,
- bool tile_prepare_enabled,
- int msaa_sample_count);
+ static scoped_ptr<GpuRasterizer> Create(
+ ContextProvider* context_provider,
+ ResourceProvider* resource_provider,
+ bool use_distance_field_text,
+ bool threaded_gpu_rasterization_enabled,
+ int msaa_sample_count);
PrepareTilesMode GetPrepareTilesMode() override;
void RasterizeTiles(
const TileVector& tiles,
@@ -38,7 +39,7 @@
GpuRasterizer(ContextProvider* context_provider,
ResourceProvider* resource_provider,
bool use_distance_filed_text,
- bool tile_prepare_enabled,
+ bool threaded_gpu_rasterization_enabled,
int msaa_sample_count);
using ScopedResourceWriteLocks =
@@ -55,7 +56,7 @@
SkMultiPictureDraw multi_picture_draw_;
bool use_distance_field_text_;
- bool tile_prepare_enabled_;
+ bool threaded_gpu_rasterization_enabled_;
int msaa_sample_count_;
DISALLOW_COPY_AND_ASSIGN(GpuRasterizer);
diff --git a/cc/resources/one_copy_tile_task_worker_pool.h b/cc/resources/one_copy_tile_task_worker_pool.h
index 4568d35..85b3f32 100644
--- a/cc/resources/one_copy_tile_task_worker_pool.h
+++ b/cc/resources/one_copy_tile_task_worker_pool.h
@@ -15,11 +15,18 @@
#include "cc/resources/tile_task_worker_pool.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
class ResourcePool;
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc
index 003a8f1..6bbeeaa 100644
--- a/cc/resources/picture.cc
+++ b/cc/resources/picture.cc
@@ -53,11 +53,12 @@
} // namespace
-scoped_refptr<Picture> Picture::Create(const gfx::Rect& layer_rect,
- ContentLayerClient* client,
- const gfx::Size& tile_grid_size,
- bool gather_pixel_refs,
- RecordingMode recording_mode) {
+scoped_refptr<Picture> Picture::Create(
+ const gfx::Rect& layer_rect,
+ ContentLayerClient* client,
+ const gfx::Size& tile_grid_size,
+ bool gather_pixel_refs,
+ RecordingSource::RecordingMode recording_mode) {
scoped_refptr<Picture> picture = make_scoped_refptr(new Picture(layer_rect));
picture->Record(client, tile_grid_size, recording_mode);
@@ -169,7 +170,7 @@
void Picture::Record(ContentLayerClient* painter,
const gfx::Size& tile_grid_size,
- RecordingMode recording_mode) {
+ RecordingSource::RecordingMode recording_mode) {
TRACE_EVENT2("cc",
"Picture::Record",
"data",
@@ -189,23 +190,27 @@
layer_rect_.width(), layer_rect_.height(), &factory,
SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag));
- ContentLayerClient::GraphicsContextStatus graphics_context_status =
- ContentLayerClient::GRAPHICS_CONTEXT_ENABLED;
+ ContentLayerClient::PaintingControlSetting painting_control =
+ ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
switch (recording_mode) {
- case RECORD_NORMALLY:
+ case RecordingSource::RECORD_NORMALLY:
// Already setup for normal recording.
break;
- case RECORD_WITH_SK_NULL_CANVAS:
+ case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
canvas = skia::AdoptRef(SkCreateNullCanvas());
break;
- case RECORD_WITH_PAINTING_DISABLED:
+ case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
// We pass a disable flag through the paint calls when perfromance
// testing (the only time this case should ever arise) when we want to
// prevent the Blink GraphicsContext object from consuming any compute
// time.
canvas = skia::AdoptRef(SkCreateNullCanvas());
- graphics_context_status = ContentLayerClient::GRAPHICS_CONTEXT_DISABLED;
+ painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
+ break;
+ case RecordingSource::RECORD_WITH_CACHING_DISABLED:
+ // This mode should give the same results as RECORD_NORMALLY.
+ painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
break;
default:
NOTREACHED();
@@ -221,7 +226,7 @@
layer_rect_.height());
canvas->clipRect(layer_skrect);
- painter->PaintContents(canvas.get(), layer_rect_, graphics_context_status);
+ painter->PaintContents(canvas.get(), layer_rect_, painting_control);
canvas->restore();
picture_ = skia::AdoptRef(recorder.endRecording());
diff --git a/cc/resources/picture.h b/cc/resources/picture.h
index ec76f45..a2a4ec2 100644
--- a/cc/resources/picture.h
+++ b/cc/resources/picture.h
@@ -18,6 +18,7 @@
#include "base/trace_event/trace_event.h"
#include "cc/base/cc_export.h"
#include "cc/base/region.h"
+#include "cc/resources/recording_source.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/geometry/rect.h"
@@ -44,18 +45,12 @@
typedef std::vector<SkPixelRef*> PixelRefs;
typedef base::hash_map<PixelRefMapKey, PixelRefs> PixelRefMap;
- enum RecordingMode {
- RECORD_NORMALLY,
- RECORD_WITH_SK_NULL_CANVAS,
- RECORD_WITH_PAINTING_DISABLED,
- RECORDING_MODE_COUNT, // Must be the last entry.
- };
-
- static scoped_refptr<Picture> Create(const gfx::Rect& layer_rect,
- ContentLayerClient* client,
- const gfx::Size& tile_grid_size,
- bool gather_pixels_refs,
- RecordingMode recording_mode);
+ static scoped_refptr<Picture> Create(
+ const gfx::Rect& layer_rect,
+ ContentLayerClient* client,
+ const gfx::Size& tile_grid_size,
+ bool gather_pixels_refs,
+ RecordingSource::RecordingMode recording_mode);
static scoped_refptr<Picture> CreateFromValue(const base::Value* value);
static scoped_refptr<Picture> CreateFromSkpValue(const base::Value* value);
@@ -141,7 +136,7 @@
// playback on a different thread this can only be called once.
void Record(ContentLayerClient* client,
const gfx::Size& tile_grid_size,
- RecordingMode recording_mode);
+ RecordingSource::RecordingMode recording_mode);
// Gather pixel refs from recording.
void GatherPixelRefs(const gfx::Size& tile_grid_info);
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h
index 15fdb43..c9672c9 100644
--- a/cc/resources/picture_layer_tiling.h
+++ b/cc/resources/picture_layer_tiling.h
@@ -21,10 +21,16 @@
#include "ui/gfx/geometry/rect.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc
index 779e2c0..7c36a3f 100644
--- a/cc/resources/picture_layer_tiling_set.cc
+++ b/cc/resources/picture_layer_tiling_set.cc
@@ -116,15 +116,16 @@
}
if (!tilings_.empty()) {
- size_t num_high_res = std::count_if(tilings_.begin(), tilings_.end(),
- [](PictureLayerTiling* tiling) {
- return tiling->resolution() == HIGH_RESOLUTION;
- });
- DCHECK_LE(num_high_res, 1u);
+ DCHECK_LE(NumHighResTilings(), 1);
// When commiting from the main thread the high res tiling may get dropped,
// but when cloning to the active tree, there should always be one.
- if (twin_set)
- DCHECK_EQ(1u, num_high_res);
+ if (twin_set) {
+ DCHECK_EQ(1, NumHighResTilings())
+ << " num tilings on active: " << tilings_.size()
+ << " num tilings on pending: " << twin_set->tilings_.size()
+ << " num high res on pending: " << twin_set->NumHighResTilings()
+ << " are on active tree: " << (client_->GetTree() == ACTIVE_TREE);
+ }
}
#endif
}
@@ -214,12 +215,10 @@
}
int PictureLayerTilingSet::NumHighResTilings() const {
- int num_high_res = 0;
- for (size_t i = 0; i < tilings_.size(); ++i) {
- if (tilings_[i]->resolution() == HIGH_RESOLUTION)
- num_high_res++;
- }
- return num_high_res;
+ return std::count_if(tilings_.begin(), tilings_.end(),
+ [](PictureLayerTiling* tiling) {
+ return tiling->resolution() == HIGH_RESOLUTION;
+ });
}
PictureLayerTiling* PictureLayerTilingSet::FindTilingWithScale(
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h
index 9f6eba9..3e31ed9 100644
--- a/cc/resources/picture_layer_tiling_set.h
+++ b/cc/resources/picture_layer_tiling_set.h
@@ -14,10 +14,16 @@
#include "ui/gfx/geometry/size.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index f42244c..dcfe49e 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -181,7 +181,7 @@
const gfx::Size& layer_size,
const gfx::Rect& visible_layer_rect,
int frame_number,
- Picture::RecordingMode recording_mode) {
+ RecordingSource::RecordingMode recording_mode) {
bool can_use_lcd_text_changed = can_use_lcd_text_ != can_use_lcd_text;
can_use_lcd_text_ = can_use_lcd_text;
@@ -532,7 +532,7 @@
}
void PicturePile::CreatePictures(ContentLayerClient* painter,
- Picture::RecordingMode recording_mode,
+ RecordingSource::RecordingMode recording_mode,
const std::vector<gfx::Rect>& record_rects) {
for (const auto& record_rect : record_rects) {
gfx::Rect padded_record_rect = PadRect(record_rect);
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h
index 1e3368c..8000c42 100644
--- a/cc/resources/picture_pile.h
+++ b/cc/resources/picture_pile.h
@@ -12,7 +12,7 @@
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "cc/base/tiling_data.h"
-#include "cc/resources/recording_source.h"
+#include "cc/resources/picture.h"
namespace cc {
class PicturePileImpl;
@@ -23,14 +23,13 @@
~PicturePile() override;
// RecordingSource overrides.
- bool UpdateAndExpandInvalidation(
- ContentLayerClient* painter,
- Region* invalidation,
- bool can_use_lcd_text,
- const gfx::Size& layer_size,
- const gfx::Rect& visible_layer_rect,
- int frame_number,
- Picture::RecordingMode recording_mode) override;
+ bool UpdateAndExpandInvalidation(ContentLayerClient* painter,
+ Region* invalidation,
+ bool can_use_lcd_text,
+ const gfx::Size& layer_size,
+ const gfx::Rect& visible_layer_rect,
+ int frame_number,
+ RecordingMode recording_mode) override;
scoped_refptr<RasterSource> CreateRasterSource() const override;
gfx::Size GetSize() const final;
void SetEmptyBounds() override;
@@ -106,7 +105,7 @@
friend class PicturePileImpl;
void CreatePictures(ContentLayerClient* painter,
- Picture::RecordingMode recording_mode,
+ RecordingMode recording_mode,
const std::vector<gfx::Rect>& record_rects);
void GetInvalidTileRects(const gfx::Rect& interest_rect,
Region* invalidation,
diff --git a/cc/resources/picture_pile_unittest.cc b/cc/resources/picture_pile_unittest.cc
index 4e3fe15..b834979 100644
--- a/cc/resources/picture_pile_unittest.cc
+++ b/cc/resources/picture_pile_unittest.cc
@@ -44,7 +44,7 @@
frame_number_++;
return pile_.UpdateAndExpandInvalidation(
&client_, invalidation, false, layer_size, visible_layer_rect,
- frame_number_, Picture::RECORD_NORMALLY);
+ frame_number_, RecordingSource::RECORD_NORMALLY);
}
bool UpdateWholePile() {
diff --git a/cc/resources/picture_unittest.cc b/cc/resources/picture_unittest.cc
index 0c41215..1e2ba44 100644
--- a/cc/resources/picture_unittest.cc
+++ b/cc/resources/picture_unittest.cc
@@ -44,7 +44,7 @@
scoped_refptr<Picture> one_rect_picture =
Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
scoped_ptr<base::Value> serialized_one_rect(one_rect_picture->AsValue());
// Reconstruct the picture.
@@ -66,7 +66,7 @@
scoped_refptr<Picture> two_rect_picture =
Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
scoped_ptr<base::Value> serialized_two_rect(two_rect_picture->AsValue());
@@ -118,7 +118,7 @@
scoped_refptr<Picture> picture =
Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
// Default iterator does not have any pixel refs
{
@@ -213,7 +213,7 @@
scoped_refptr<Picture> picture =
Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
// Default iterator does not have any pixel refs
{
@@ -331,7 +331,7 @@
scoped_refptr<Picture> picture =
Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
@@ -374,7 +374,7 @@
content_layer_client.add_draw_rect(layer_rect, red_paint);
scoped_refptr<Picture> one_rect_picture =
Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
scoped_ptr<base::Value> serialized_one_rect(
one_rect_picture->AsValue());
@@ -406,27 +406,36 @@
scoped_refptr<Picture> picture =
Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
- Picture::RECORD_NORMALLY);
+ RecordingSource::RECORD_NORMALLY);
EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
- EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_ENABLED,
- content_layer_client.last_context_status());
+ EXPECT_EQ(ContentLayerClient::PAINTING_BEHAVIOR_NORMAL,
+ content_layer_client.last_painting_control());
EXPECT_TRUE(picture.get());
picture = Picture::Create(layer_rect, &content_layer_client, tile_grid_size,
- false, Picture::RECORD_WITH_SK_NULL_CANVAS);
+ false, RecordingSource::RECORD_WITH_SK_NULL_CANVAS);
EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
- EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_ENABLED,
- content_layer_client.last_context_status());
+ EXPECT_EQ(ContentLayerClient::PAINTING_BEHAVIOR_NORMAL,
+ content_layer_client.last_painting_control());
EXPECT_TRUE(picture.get());
- picture = Picture::Create(layer_rect, &content_layer_client, tile_grid_size,
- false, Picture::RECORD_WITH_PAINTING_DISABLED);
+ picture =
+ Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
+ RecordingSource::RECORD_WITH_PAINTING_DISABLED);
EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
- EXPECT_EQ(ContentLayerClient::GRAPHICS_CONTEXT_DISABLED,
- content_layer_client.last_context_status());
+ EXPECT_EQ(ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED,
+ content_layer_client.last_painting_control());
EXPECT_TRUE(picture.get());
- EXPECT_EQ(3, Picture::RECORDING_MODE_COUNT);
+ picture =
+ Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false,
+ RecordingSource::RECORD_WITH_CACHING_DISABLED);
+ EXPECT_TRUE(content_layer_client.last_canvas() != NULL);
+ EXPECT_EQ(ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED,
+ content_layer_client.last_painting_control());
+ EXPECT_TRUE(picture.get());
+
+ EXPECT_EQ(4, RecordingSource::RECORDING_MODE_COUNT);
}
} // namespace
diff --git a/cc/resources/pixel_buffer_tile_task_worker_pool.h b/cc/resources/pixel_buffer_tile_task_worker_pool.h
index 8ee4b9c..edff89a 100644
--- a/cc/resources/pixel_buffer_tile_task_worker_pool.h
+++ b/cc/resources/pixel_buffer_tile_task_worker_pool.h
@@ -16,11 +16,18 @@
#include "cc/resources/tile_task_worker_pool.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
class ResourceProvider;
diff --git a/cc/resources/rasterizer.h b/cc/resources/rasterizer.h
index 95b9ce2..43df0b0 100644
--- a/cc/resources/rasterizer.h
+++ b/cc/resources/rasterizer.h
@@ -16,7 +16,6 @@
enum class PrepareTilesMode {
RASTERIZE_PRIORITIZED_TILES,
- PREPARE_PRIORITIZED_TILES,
PREPARE_NONE
};
diff --git a/cc/resources/recording_source.h b/cc/resources/recording_source.h
index 1e45047..d96c0fa 100644
--- a/cc/resources/recording_source.h
+++ b/cc/resources/recording_source.h
@@ -5,8 +5,8 @@
#ifndef CC_RESOURCES_RECORDING_SOURCE_H_
#define CC_RESOURCES_RECORDING_SOURCE_H_
+#include "base/memory/ref_counted.h"
#include "cc/base/cc_export.h"
-#include "cc/resources/picture.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -18,20 +18,27 @@
class CC_EXPORT RecordingSource {
public:
+ enum RecordingMode {
+ RECORD_NORMALLY,
+ RECORD_WITH_SK_NULL_CANVAS,
+ RECORD_WITH_PAINTING_DISABLED,
+ RECORD_WITH_CACHING_DISABLED,
+ RECORDING_MODE_COUNT, // Must be the last entry.
+ };
+
virtual ~RecordingSource() {}
// Re-record parts of the picture that are invalid.
// Invalidations are in layer space, and will be expanded to cover everything
// that was either recorded/changed or that has no recording, leaving out only
// pieces that we had a recording for and it was not changed.
// Return true iff the pile was modified.
- virtual bool UpdateAndExpandInvalidation(
- ContentLayerClient* painter,
- Region* invalidation,
- bool can_use_lcd_text,
- const gfx::Size& layer_size,
- const gfx::Rect& visible_layer_rect,
- int frame_number,
- Picture::RecordingMode recording_mode) = 0;
+ virtual bool UpdateAndExpandInvalidation(ContentLayerClient* painter,
+ Region* invalidation,
+ bool can_use_lcd_text,
+ const gfx::Size& layer_size,
+ const gfx::Rect& visible_layer_rect,
+ int frame_number,
+ RecordingMode recording_mode) = 0;
virtual scoped_refptr<RasterSource> CreateRasterSource() const = 0;
diff --git a/cc/resources/tile_manager.h b/cc/resources/tile_manager.h
index 37ab765..0af823e 100644
--- a/cc/resources/tile_manager.h
+++ b/cc/resources/tile_manager.h
@@ -26,11 +26,18 @@
#include "cc/resources/tile_task_runner.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
class PictureLayerImpl;
diff --git a/cc/resources/zero_copy_tile_task_worker_pool.h b/cc/resources/zero_copy_tile_task_worker_pool.h
index 8d3c0cf..4f3085c 100644
--- a/cc/resources/zero_copy_tile_task_worker_pool.h
+++ b/cc/resources/zero_copy_tile_task_worker_pool.h
@@ -11,10 +11,16 @@
#include "cc/resources/tile_task_worker_pool.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
}
+} // namespace base
namespace cc {
class ResourceProvider;
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc
index c245bd6..9b200e9 100644
--- a/cc/scheduler/begin_frame_source.cc
+++ b/cc/scheduler/begin_frame_source.cc
@@ -414,11 +414,10 @@
}
}
-void BeginFrameSourceMultiplexer::SetNeedsBeginFrames(bool needs_begin_frames) {
- DEBUG_FRAMES("BeginFrameSourceMultiplexer::SetNeedsBeginFrames",
- "active_source",
- active_source_,
- "needs_begin_frames",
+void BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange(
+ bool needs_begin_frames) {
+ DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange",
+ "active_source", active_source_, "needs_begin_frames",
needs_begin_frames);
if (active_source_) {
active_source_->SetNeedsBeginFrames(needs_begin_frames);
diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h
index 299db8e..1612a28 100644
--- a/cc/scheduler/begin_frame_source.h
+++ b/cc/scheduler/begin_frame_source.h
@@ -138,7 +138,7 @@
// BeginFrameSource
bool NeedsBeginFrames() const override;
- void SetNeedsBeginFrames(bool needs_begin_frames) override;
+ void SetNeedsBeginFrames(bool needs_begin_frames) final;
void DidFinishFrame(size_t remaining_frames) override {}
void AddObserver(BeginFrameObserver* obs) final;
void RemoveObserver(BeginFrameObserver* obs) final;
@@ -261,9 +261,11 @@
// BeginFrameSource
bool NeedsBeginFrames() const override;
- void SetNeedsBeginFrames(bool needs_begin_frames) override;
void DidFinishFrame(size_t remaining_frames) override;
+ // BeginFrameSourceMixIn
+ void OnNeedsBeginFramesChange(bool needs_begin_frames) override;
+
// Tracing
void AsValueInto(base::debug::TracedValue* dict) const override;
diff --git a/cc/scheduler/delay_based_time_source.h b/cc/scheduler/delay_based_time_source.h
index ea03f9d..da968a6 100644
--- a/cc/scheduler/delay_based_time_source.h
+++ b/cc/scheduler/delay_based_time_source.h
@@ -12,11 +12,17 @@
#include "cc/base/cc_export.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
-class SingleThreadTaskRunner;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+class SingleThreadTaskRunner;
+} // namespace base
namespace cc {
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index e06a133..ddc3f2f 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -24,11 +24,17 @@
#include "cc/scheduler/scheduler_state_machine.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
}
-class SingleThreadTaskRunner;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
}
+class SingleThreadTaskRunner;
+} // namespace base
namespace cc {
diff --git a/cc/scheduler/scheduler_settings.h b/cc/scheduler/scheduler_settings.h
index 4ff3c7e..90c1a9c 100644
--- a/cc/scheduler/scheduler_settings.h
+++ b/cc/scheduler/scheduler_settings.h
@@ -11,10 +11,16 @@
#include "cc/base/cc_export.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
}
+} // namespace base
namespace cc {
class LayerTreeSettings;
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index aa153c6..fb87c84 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -17,12 +17,19 @@
#include "cc/scheduler/scheduler_settings.h"
namespace base {
-namespace debug {
+namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
}
-class Value;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::ConvertableToTraceFormat;
+using ::base::trace_event::TracedValue;
}
+class Value;
+} // namespace base
namespace cc {
@@ -282,7 +289,6 @@
bool ShouldAnimate() const;
bool ShouldBeginOutputSurfaceCreation() const;
- bool ShouldDrawForced() const;
bool ShouldDraw() const;
bool ShouldActivatePendingTree() const;
bool ShouldSendBeginMainFrame() const;
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc
index 25f3114..065aa38 100644
--- a/cc/surfaces/surface.cc
+++ b/cc/surfaces/surface.cc
@@ -46,7 +46,11 @@
current_frame_ = frame.Pass();
factory_->ReceiveFromChild(
current_frame_->delegated_frame_data->resource_list);
- ++frame_index_;
+ // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't
+ // increment frame index for them.
+ if (!current_frame_ ||
+ !current_frame_->delegated_frame_data->render_pass_list.empty())
+ ++frame_index_;
if (previous_frame) {
ReturnedResourceArray previous_resources;
diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc
index ed6763d..068fe03 100644
--- a/cc/surfaces/surface_display_output_surface.cc
+++ b/cc/surfaces/surface_display_output_surface.cc
@@ -25,6 +25,9 @@
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
capabilities_.can_force_reclaim_resources = true;
+ // Frame always needs to be swapped because forced resource reclaiming
+ // destroys the Display's copy.
+ capabilities_.draw_and_swap_full_viewport_every_frame = true;
}
SurfaceDisplayOutputSurface::~SurfaceDisplayOutputSurface() {
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
index b5c2a63..b9c6bf5 100644
--- a/cc/surfaces/surface_factory_unittest.cc
+++ b/cc/surfaces/surface_factory_unittest.cc
@@ -360,6 +360,21 @@
}
}
+TEST_F(SurfaceFactoryTest, BlankNoIndexIncrement) {
+ SurfaceId surface_id(6);
+ factory_.Create(surface_id);
+ Surface* surface = manager_.GetSurfaceForId(surface_id);
+ ASSERT_NE(nullptr, surface);
+ EXPECT_EQ(2, surface->frame_index());
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+ frame->delegated_frame_data.reset(new DelegatedFrameData);
+
+ factory_.SubmitFrame(surface_id, frame.Pass(),
+ SurfaceFactory::DrawCallback());
+ EXPECT_EQ(2, surface->frame_index());
+ factory_.Destroy(surface_id);
+}
+
void DrawCallback(uint32* execute_count,
SurfaceDrawStatus* result,
SurfaceDrawStatus drawn) {
diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc
index 46d1baa..23b73f5 100644
--- a/cc/test/fake_content_layer_client.cc
+++ b/cc/test/fake_content_layer_client.cc
@@ -22,9 +22,9 @@
void FakeContentLayerClient::PaintContents(
SkCanvas* canvas,
const gfx::Rect& paint_rect,
- ContentLayerClient::GraphicsContextStatus gc_status) {
+ PaintingControlSetting painting_control) {
last_canvas_ = canvas;
- last_context_status_ = gc_status;
+ last_painting_control_ = painting_control;
canvas->clipRect(gfx::RectToSkRect(paint_rect));
for (RectPaintVector::const_iterator it = draw_rects_.begin();
@@ -58,7 +58,7 @@
scoped_refptr<DisplayItemList>
FakeContentLayerClient::PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) {
+ PaintingControlSetting painting_control) {
SkPictureRecorder recorder;
skia::RefPtr<SkCanvas> canvas;
skia::RefPtr<SkPicture> picture;
diff --git a/cc/test/fake_content_layer_client.h b/cc/test/fake_content_layer_client.h
index 1060d08..d53d34e 100644
--- a/cc/test/fake_content_layer_client.h
+++ b/cc/test/fake_content_layer_client.h
@@ -27,13 +27,12 @@
FakeContentLayerClient();
~FakeContentLayerClient() override;
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& rect,
- ContentLayerClient::GraphicsContextStatus gc_status) override;
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& rect,
+ PaintingControlSetting painting_control) override;
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override;
+ PaintingControlSetting painting_control) override;
bool FillsBoundsCompletely() const override;
void set_fill_with_nonsolid_color(bool nonsolid) {
@@ -56,8 +55,8 @@
SkCanvas* last_canvas() const { return last_canvas_; }
- ContentLayerClient::GraphicsContextStatus last_context_status() const {
- return last_context_status_;
+ PaintingControlSetting last_painting_control() const {
+ return last_painting_control_;
}
private:
@@ -68,7 +67,7 @@
RectPaintVector draw_rects_;
BitmapVector draw_bitmaps_;
SkCanvas* last_canvas_;
- ContentLayerClient::GraphicsContextStatus last_context_status_;
+ PaintingControlSetting last_painting_control_;
};
} // namespace cc
diff --git a/cc/test/fake_layer_tree_host_client.h b/cc/test/fake_layer_tree_host_client.h
index 5f7afa5..f5f3504 100644
--- a/cc/test/fake_layer_tree_host_client.h
+++ b/cc/test/fake_layer_tree_host_client.h
@@ -30,12 +30,12 @@
void SetLayerTreeHost(LayerTreeHost* host) { host_ = host; }
// LayerTreeHostClient implementation.
- void WillBeginMainFrame(int frame_id) override {}
+ void WillBeginMainFrame() override {}
void DidBeginMainFrame() override {}
void BeginMainFrame(const BeginFrameArgs& args) override {}
void Layout() override {}
- void ApplyViewportDeltas(const gfx::Vector2d& inner_delta,
- const gfx::Vector2d& outer_delta,
+ void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
const gfx::Vector2dF& elastic_overscroll_delta,
float page_scale,
float top_controls_delta) override {}
diff --git a/cc/test/fake_picture_pile_impl.cc b/cc/test/fake_picture_pile_impl.cc
index 420b5d6..bdba092 100644
--- a/cc/test/fake_picture_pile_impl.cc
+++ b/cc/test/fake_picture_pile_impl.cc
@@ -120,8 +120,9 @@
gfx::Rect bounds(tiling().TileBounds(x, y));
bounds.Inset(-buffer_pixels(), -buffer_pixels());
- scoped_refptr<Picture> picture(Picture::Create(
- bounds, &client_, tile_grid_size_, true, Picture::RECORD_NORMALLY));
+ scoped_refptr<Picture> picture(
+ Picture::Create(bounds, &client_, tile_grid_size_, true,
+ RecordingSource::RECORD_NORMALLY));
picture_map_[std::pair<int, int>(x, y)].SetPicture(picture);
EXPECT_TRUE(HasRecordingAt(x, y));
diff --git a/cc/test/layer_tree_json_parser.cc b/cc/test/layer_tree_json_parser.cc
index 1514d83..efe70a0 100644
--- a/cc/test/layer_tree_json_parser.cc
+++ b/cc/test/layer_tree_json_parser.cc
@@ -149,6 +149,23 @@
new_layer->SetTouchEventHandlerRegion(touch_region);
}
+ if (dict->HasKey("ScrollBlocksOn")) {
+ success &= dict->GetList("ScrollBlocksOn", &list);
+ ScrollBlocksOn blocks;
+ std::string str;
+ for (size_t i = 0; i < list->GetSize(); i++) {
+ success &= list->GetString(i, &str);
+ if (str == "StartTouch")
+ blocks |= ScrollBlocksOnStartTouch;
+ else if (str == "WheelEvent")
+ blocks |= ScrollBlocksOnWheelEvent;
+ else if (str == "ScrollEvent")
+ blocks |= ScrollBlocksOnScrollEvent;
+ else
+ success = false;
+ }
+ }
+
success &= dict->GetList("DrawTransform", &list);
double transform[16];
for (int i = 0; i < 16; ++i)
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index d02b510..ce69079 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -381,9 +381,7 @@
}
~LayerTreeHostClientForTesting() override {}
- void WillBeginMainFrame(int frame_id) override {
- test_hooks_->WillBeginMainFrame();
- }
+ void WillBeginMainFrame() override { test_hooks_->WillBeginMainFrame(); }
void DidBeginMainFrame() override { test_hooks_->DidBeginMainFrame(); }
@@ -393,8 +391,8 @@
void Layout() override { test_hooks_->Layout(); }
- void ApplyViewportDeltas(const gfx::Vector2d& inner_delta,
- const gfx::Vector2d& outer_delta,
+ void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
const gfx::Vector2dF& elastic_overscroll_delta,
float page_scale,
float top_controls_delta) override {
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 4abedd7..c2b18b1 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -65,8 +65,8 @@
virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl,
base::TimeTicks monotonic_time) {}
virtual void ApplyViewportDeltas(
- const gfx::Vector2d& inner_delta,
- const gfx::Vector2d& outer_delta,
+ const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
const gfx::Vector2dF& elastic_overscroll_delta,
float scale,
float top_controls_delta) {}
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h
index 78b8f4a..3562699 100644
--- a/cc/test/pixel_test.h
+++ b/cc/test/pixel_test.h
@@ -89,9 +89,6 @@
return static_cast<RendererType*>(renderer_.get());
}
- bool UseSkiaGPUBackend() const;
- bool ExpandedViewport() const;
-
protected:
void SetUp() override;
};
@@ -145,16 +142,6 @@
}
template<>
-inline bool RendererPixelTest<GLRenderer>::UseSkiaGPUBackend() const {
- return false;
-}
-
-template<>
-inline bool RendererPixelTest<GLRenderer>::ExpandedViewport() const {
- return false;
-}
-
-template<>
inline void RendererPixelTest<GLRendererWithExpandedViewport>::SetUp() {
SetUpGLRenderer(false, false);
ForceExpandedViewport(gfx::Size(50, 50));
@@ -162,68 +149,22 @@
}
template <>
-inline bool
-RendererPixelTest<GLRendererWithExpandedViewport>::UseSkiaGPUBackend() const {
- return false;
-}
-
-template <>
-inline bool
-RendererPixelTest<GLRendererWithExpandedViewport>::ExpandedViewport() const {
- return true;
-}
-
-template <>
inline void RendererPixelTest<GLRendererWithFlippedSurface>::SetUp() {
SetUpGLRenderer(false, true);
}
template <>
-inline bool RendererPixelTest<GLRendererWithFlippedSurface>::UseSkiaGPUBackend()
- const {
- return false;
-}
-
-template <>
-inline bool RendererPixelTest<GLRendererWithFlippedSurface>::ExpandedViewport()
- const {
- return true;
-}
-
-template <>
inline void RendererPixelTest<SoftwareRenderer>::SetUp() {
SetUpSoftwareRenderer();
}
template<>
-inline bool RendererPixelTest<SoftwareRenderer>::UseSkiaGPUBackend() const {
- return false;
-}
-
-template <>
-inline bool RendererPixelTest<SoftwareRenderer>::ExpandedViewport() const {
- return false;
-}
-
-template<>
inline void RendererPixelTest<SoftwareRendererWithExpandedViewport>::SetUp() {
SetUpSoftwareRenderer();
ForceExpandedViewport(gfx::Size(50, 50));
ForceViewportOffset(gfx::Vector2d(10, 20));
}
-template <>
-inline bool RendererPixelTest<
- SoftwareRendererWithExpandedViewport>::UseSkiaGPUBackend() const {
- return false;
-}
-
-template <>
-inline bool RendererPixelTest<
- SoftwareRendererWithExpandedViewport>::ExpandedViewport() const {
- return true;
-}
-
typedef RendererPixelTest<GLRenderer> GLRendererPixelTest;
typedef RendererPixelTest<SoftwareRenderer> SoftwareRendererPixelTest;
diff --git a/cc/test/solid_color_content_layer_client.cc b/cc/test/solid_color_content_layer_client.cc
index 701f004..7e97bb8 100644
--- a/cc/test/solid_color_content_layer_client.cc
+++ b/cc/test/solid_color_content_layer_client.cc
@@ -14,7 +14,7 @@
void SolidColorContentLayerClient::PaintContents(
SkCanvas* canvas,
const gfx::Rect& rect,
- ContentLayerClient::GraphicsContextStatus gc_status) {
+ PaintingControlSetting painting_control) {
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(color_);
@@ -28,7 +28,7 @@
scoped_refptr<DisplayItemList>
SolidColorContentLayerClient::PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) {
+ PaintingControlSetting painting_control) {
NOTIMPLEMENTED();
return DisplayItemList::Create();
}
diff --git a/cc/test/solid_color_content_layer_client.h b/cc/test/solid_color_content_layer_client.h
index 93fca84..1ab4c4d 100644
--- a/cc/test/solid_color_content_layer_client.h
+++ b/cc/test/solid_color_content_layer_client.h
@@ -16,13 +16,12 @@
explicit SolidColorContentLayerClient(SkColor color) : color_(color) {}
// ContentLayerClient implementation.
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& rect,
- ContentLayerClient::GraphicsContextStatus gc_status) override;
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& rect,
+ PaintingControlSetting painting_control) override;
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override;
+ PaintingControlSetting painting_control) override;
bool FillsBoundsCompletely() const override;
private:
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index cd69f92..8217ce0 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -38,7 +38,7 @@
const TransformNode* clip_transform_node =
transform_tree.Node(clip_node->data.transform_id);
const TransformNode* target_node =
- transform_tree.Node(layer->render_target()->transform_tree_index());
+ transform_tree.Node(transform_node->data.target_id);
gfx::Transform clip_to_target;
gfx::Transform content_to_target;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 0f48cb2..fa4dd5d 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -43,6 +43,7 @@
#include "cc/trees/thread_proxy.h"
#include "cc/trees/tree_synchronizer.h"
#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/geometry/vector2d_conversions.h"
namespace {
static base::StaticAtomicSequenceNumber s_layer_tree_host_sequence_number;
@@ -222,6 +223,12 @@
contents_texture_manager_->ClearAllMemory(resource_provider);
}
+void LayerTreeHost::WillBeginMainFrame() {
+ devtools_instrumentation::WillBeginMainThreadFrame(id(),
+ source_frame_number());
+ client_->WillBeginMainFrame();
+}
+
void LayerTreeHost::DidBeginMainFrame() {
client_->DidBeginMainFrame();
}
@@ -1087,8 +1094,8 @@
QueueSwapPromise(swap_promise.Pass());
}
- gfx::Vector2d inner_viewport_scroll_delta;
- gfx::Vector2d outer_viewport_scroll_delta;
+ gfx::Vector2dF inner_viewport_scroll_delta;
+ gfx::Vector2dF outer_viewport_scroll_delta;
if (root_layer_.get()) {
for (size_t i = 0; i < info->scrolls.size(); ++i) {
@@ -1131,10 +1138,13 @@
ApplyPageScaleDeltaFromImplSide(info->page_scale_delta);
elastic_overscroll_ += info->elastic_overscroll_delta;
if (!settings_.use_pinch_virtual_viewport) {
+ // TODO(miletus): Make sure either this code path is totally gone,
+ // or revisit the flooring here if the old pinch viewport code path
+ // is causing problems with fractional scroll offset.
client_->ApplyViewportDeltas(
- inner_viewport_scroll_delta + outer_viewport_scroll_delta,
- info->page_scale_delta,
- info->top_controls_delta);
+ gfx::ToFlooredVector2d(inner_viewport_scroll_delta +
+ outer_viewport_scroll_delta),
+ info->page_scale_delta, info->top_controls_delta);
} else {
// TODO(ccameron): pass the elastic overscroll here so that input events
// may be translated appropriately.
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 7db722f..f41e023 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -110,9 +110,7 @@
void SetLayerTreeHostClientReady();
// LayerTreeHost interface to Proxy.
- void WillBeginMainFrame() {
- client_->WillBeginMainFrame(source_frame_number_);
- }
+ void WillBeginMainFrame();
void DidBeginMainFrame();
void BeginMainFrame(const BeginFrameArgs& args);
void AnimateLayers(base::TimeTicks monotonic_frame_begin_time);
diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h
index ac025f2..574325b 100644
--- a/cc/trees/layer_tree_host_client.h
+++ b/cc/trees/layer_tree_host_client.h
@@ -22,15 +22,15 @@
class LayerTreeHostClient {
public:
- virtual void WillBeginMainFrame(int frame_id) = 0;
+ virtual void WillBeginMainFrame() = 0;
// Marks finishing compositing-related tasks on the main thread. In threaded
// mode, this corresponds to DidCommit().
virtual void BeginMainFrame(const BeginFrameArgs& args) = 0;
virtual void DidBeginMainFrame() = 0;
virtual void Layout() = 0;
virtual void ApplyViewportDeltas(
- const gfx::Vector2d& inner_delta,
- const gfx::Vector2d& outer_delta,
+ const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
const gfx::Vector2dF& elastic_overscroll_delta,
float page_scale,
float top_controls_delta) = 0;
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h
index 0955b9a..8666617 100644
--- a/cc/trees/layer_tree_host_common.h
+++ b/cc/trees/layer_tree_host_common.h
@@ -151,9 +151,7 @@
struct ScrollUpdateInfo {
int layer_id;
- // TODO(miletus) : Use ScrollOffset once LayerTreeHost/Blink fully supports
- // franctional scroll offset.
- gfx::Vector2d scroll_delta;
+ gfx::Vector2dF scroll_delta;
};
};
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index df2b30e..de5f44a 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -56,13 +56,12 @@
public:
MockContentLayerClient() {}
~MockContentLayerClient() override {}
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus gc_status) override {}
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {}
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override {
+ PaintingControlSetting picture_control) override {
NOTIMPLEMENTED();
return DisplayItemList::Create();
}
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 398ef81..672ffe8 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -116,18 +116,14 @@
gfx::ScrollOffset viewport_in_content_coordinates_;
};
-
void DidVisibilityChange(LayerTreeHostImpl* id, bool visible) {
if (visible) {
- TRACE_EVENT_ASYNC_BEGIN1("webkit",
- "LayerTreeHostImpl::SetVisible",
- id,
- "LayerTreeHostImpl",
- id);
+ TRACE_EVENT_ASYNC_BEGIN1("cc", "LayerTreeHostImpl::SetVisible", id,
+ "LayerTreeHostImpl", id);
return;
}
- TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::SetVisible", id);
+ TRACE_EVENT_ASYNC_END0("cc", "LayerTreeHostImpl::SetVisible", id);
}
size_t GetMaxTransferBufferUsageBytes(
@@ -229,7 +225,8 @@
gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
id_(id),
requires_high_res_to_draw_(false),
- is_likely_to_require_a_draw_(false) {
+ is_likely_to_require_a_draw_(false),
+ frame_timing_tracker_(FrameTimingTracker::Create()) {
DCHECK(proxy_->IsImplThread());
DidVisibilityChange(this, visible_);
animation_registrar_->set_supports_scroll_animations(
@@ -469,16 +466,39 @@
return layer_impl != NULL;
}
-bool LayerTreeHostImpl::HaveTouchEventHandlersAt(
- const gfx::Point& viewport_point) {
+static LayerImpl* NextScrollLayer(LayerImpl* layer) {
+ if (LayerImpl* scroll_parent = layer->scroll_parent())
+ return scroll_parent;
+ return layer->parent();
+}
+static ScrollBlocksOn EffectiveScrollBlocksOn(LayerImpl* layer) {
+ ScrollBlocksOn blocks = ScrollBlocksOnNone;
+ for (; layer; layer = NextScrollLayer(layer)) {
+ blocks |= layer->scroll_blocks_on();
+ }
+ return blocks;
+}
+
+bool LayerTreeHostImpl::DoTouchEventsBlockScrollAt(
+ const gfx::Point& viewport_point) {
gfx::PointF device_viewport_point =
gfx::ScalePoint(viewport_point, device_scale_factor_);
+ // First check if scrolling at this point is required to block on any
+ // touch event handlers. Note that we must start at the innermost layer
+ // (as opposed to only the layer found to contain a touch handler region
+ // below) to ensure all relevant scroll-blocks-on values are applied.
LayerImpl* layer_impl =
- active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion(
- device_viewport_point);
+ active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
+ ScrollBlocksOn blocking = EffectiveScrollBlocksOn(layer_impl);
+ if (!(blocking & ScrollBlocksOnStartTouch))
+ return false;
+ // Now determine if there are actually any handlers at that point.
+ // TODO(rbyers): Consider also honoring touch-action (crbug.com/347272).
+ layer_impl = active_tree_->FindLayerThatIsHitByPointInTouchHandlerRegion(
+ device_viewport_point);
return layer_impl != NULL;
}
@@ -674,6 +694,7 @@
if (root_surface_has_contributing_layers &&
root_surface_has_no_visible_damage &&
active_tree_->LayersWithCopyOutputRequest().empty() &&
+ !output_surface_->capabilities().can_force_reclaim_resources &&
!hud_wants_to_draw_) {
TRACE_EVENT0("cc",
"LayerTreeHostImpl::CalculateRenderPasses::EmptyDamageRect");
@@ -813,6 +834,18 @@
*it,
occlusion_tracker,
&append_quads_data);
+
+ // For layers that represent themselves, add composite frame timing
+ // requests if the visible rect intersects the requested rect.
+ for (const auto& request : it->frame_timing_requests()) {
+ const gfx::Rect& request_content_rect =
+ it->LayerRectToContentRect(request.rect());
+ if (request_content_rect.Intersects(it->visible_content_rect())) {
+ frame->composite_events.push_back(
+ FrameTimingTracker::FrameAndRectIds(
+ active_tree_->source_frame_number(), request.id()));
+ }
+ }
}
++layers_drawn;
@@ -1438,6 +1471,11 @@
TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers");
DCHECK(CanDraw());
+ if (!frame->composite_events.empty()) {
+ frame_timing_tracker_->SaveTimeStamps(frame_begin_time,
+ frame->composite_events);
+ }
+
if (frame->has_no_damage) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoDamage", TRACE_EVENT_SCOPE_THREAD);
DCHECK(!output_surface_->capabilities()
@@ -1577,6 +1615,7 @@
DestroyTileManager();
CreateAndSetTileManager();
}
+ RecreateTreeResources();
// We have released tilings for both active and pending tree.
// We would not have any content to draw until the pending tree is activated.
@@ -1895,6 +1934,14 @@
EvictAllUIResources();
}
+void LayerTreeHostImpl::RecreateTreeResources() {
+ active_tree_->RecreateResources();
+ if (pending_tree_)
+ pending_tree_->RecreateResources();
+ if (recycle_tree_)
+ recycle_tree_->RecreateResources();
+}
+
void LayerTreeHostImpl::CreateAndSetRenderer() {
DCHECK(!renderer_);
DCHECK(output_surface_);
@@ -1959,7 +2006,8 @@
ContextProvider* context_provider = output_surface_->context_provider();
if (use_gpu_rasterization_ && context_provider) {
return GpuRasterizer::Create(context_provider, resource_provider_.get(),
- settings_.use_distance_field_text, false,
+ settings_.use_distance_field_text,
+ settings_.threaded_gpu_rasterization_enabled,
settings_.gpu_rasterization_msaa_sample_count);
}
return SoftwareRasterizer::Create();
@@ -2085,8 +2133,12 @@
resource_provider_ = nullptr;
output_surface_ = nullptr;
- if (!output_surface->BindToClient(this))
+ if (!output_surface->BindToClient(this)) {
+ // Avoid recreating tree resources because we might not have enough
+ // information to do this yet (eg. we don't have a TileManager at this
+ // point).
return false;
+ }
output_surface_ = output_surface.Pass();
resource_provider_ = ResourceProvider::Create(
@@ -2103,6 +2155,7 @@
if (settings_.impl_side_painting)
CreateAndSetTileManager();
+ RecreateTreeResources();
// Initialize vsync parameters to sane values.
const base::TimeDelta display_refresh_interval =
@@ -2152,6 +2205,7 @@
CreateAndSetRenderer();
EnforceZeroBudget(false);
CreateAndSetTileManager();
+ RecreateTreeResources();
client_->SetNeedsCommitOnImplThread();
}
@@ -2171,6 +2225,7 @@
CreateAndSetRenderer();
EnforceZeroBudget(true);
CreateAndSetTileManager();
+ RecreateTreeResources();
client_->SetNeedsCommitOnImplThread();
}
@@ -2178,6 +2233,10 @@
void LayerTreeHostImpl::SetViewportSize(const gfx::Size& device_viewport_size) {
if (device_viewport_size == device_viewport_size_)
return;
+ TRACE_EVENT_INSTANT2("cc", "LayerTreeHostImpl::SetViewportSize",
+ TRACE_EVENT_SCOPE_THREAD, "width",
+ device_viewport_size.width(), "height",
+ device_viewport_size.height());
if (pending_tree_)
active_tree_->SetViewportSizeInvalid();
@@ -2255,12 +2314,6 @@
input_handler_client_ = client;
}
-static LayerImpl* NextScrollLayer(LayerImpl* layer) {
- if (LayerImpl* scroll_parent = layer->scroll_parent())
- return scroll_parent;
- return layer->parent();
-}
-
LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
const gfx::PointF& device_viewport_point,
InputHandler::ScrollInputType type,
@@ -2269,12 +2322,15 @@
bool* optional_has_ancestor_scroll_handler) const {
DCHECK(scroll_on_main_thread);
+ ScrollBlocksOn block_mode = EffectiveScrollBlocksOn(layer_impl);
+
// Walk up the hierarchy and look for a scrollable layer.
LayerImpl* potentially_scrolling_layer_impl = NULL;
for (; layer_impl; layer_impl = NextScrollLayer(layer_impl)) {
// The content layer can also block attempts to scroll outside the main
// thread.
- ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type);
+ ScrollStatus status =
+ layer_impl->TryScroll(device_viewport_point, type, block_mode);
if (status == ScrollOnMainThread) {
*scroll_on_main_thread = true;
return NULL;
@@ -2284,7 +2340,8 @@
if (!scroll_layer_impl)
continue;
- status = scroll_layer_impl->TryScroll(device_viewport_point, type);
+ status =
+ scroll_layer_impl->TryScroll(device_viewport_point, type, block_mode);
// If any layer wants to divert the scroll event to the main thread, abort.
if (status == ScrollOnMainThread) {
*scroll_on_main_thread = true;
@@ -2988,7 +3045,7 @@
if (!scroll_delta.IsZero()) {
LayerTreeHostCommon::ScrollUpdateInfo scroll;
scroll.layer_id = layer_impl->id();
- scroll.scroll_delta = gfx::Vector2d(scroll_delta.x(), scroll_delta.y());
+ scroll.scroll_delta = gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
scroll_info->scrolls.push_back(scroll);
}
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index eb84c54..f4052f1 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -18,6 +18,7 @@
#include "cc/animation/scrollbar_animation_controller.h"
#include "cc/base/cc_export.h"
#include "cc/base/synced_property.h"
+#include "cc/debug/frame_timing_tracker.h"
#include "cc/debug/micro_benchmark_controller_impl.h"
#include "cc/input/input_handler.h"
#include "cc/input/layer_scroll_offset_delegate.h"
@@ -167,7 +168,7 @@
bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point,
InputHandler::ScrollInputType type) override;
bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) override;
- bool HaveTouchEventHandlersAt(const gfx::Point& viewport_port) override;
+ bool DoTouchEventsBlockScrollAt(const gfx::Point& viewport_port) override;
scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
ui::LatencyInfo* latency) override;
ScrollElasticityHelper* CreateScrollElasticityHelper() override;
@@ -185,6 +186,7 @@
std::vector<gfx::Rect> occluding_screen_space_rects;
std::vector<gfx::Rect> non_occluding_screen_space_rects;
+ std::vector<FrameTimingTracker::FrameAndRectIds> composite_events;
RenderPassList render_passes;
RenderPassIdHashMap render_passes_by_id;
const LayerImplList* render_surface_layer_list;
@@ -514,6 +516,10 @@
bool prepare_tiles_needed() const { return tile_priorities_dirty_; }
+ FrameTimingTracker* frame_timing_tracker() {
+ return frame_timing_tracker_.get();
+ }
+
protected:
LayerTreeHostImpl(
const LayerTreeSettings& settings,
@@ -541,6 +547,7 @@
void CreateAndSetTileManager();
void DestroyTileManager();
void ReleaseTreeResources();
+ void RecreateTreeResources();
void EnforceZeroBudget(bool zero_budget);
bool UsePendingTreeForSync() const;
@@ -732,6 +739,8 @@
bool requires_high_res_to_draw_;
bool is_likely_to_require_a_draw_;
+ scoped_ptr<FrameTimingTracker> frame_timing_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
};
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index b016fff..1c486e3 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -192,13 +192,14 @@
static void ExpectContains(const ScrollAndScaleSet& scroll_info,
int id,
- const gfx::Vector2d& scroll_delta) {
+ const gfx::Vector2dF& scroll_delta) {
int times_encountered = 0;
for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
if (scroll_info.scrolls[i].layer_id != id)
continue;
- EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
+ EXPECT_VECTOR2DF_NEAR(scroll_delta, scroll_info.scrolls[i].scroll_delta,
+ 1.0e-10);
times_encountered++;
}
@@ -568,22 +569,180 @@
ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
}
-TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
+TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
DrawFrame();
LayerImpl* root = host_impl_->active_tree()->root_layer();
+ // With registered event handlers, wheel scrolls don't necessarily
+ // have to go to the main thread.
root->SetHaveWheelEventHandlers(true);
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+ host_impl_->ScrollEnd();
- // With registered event handlers, wheel scrolls have to go to the main
- // thread.
+ // But typically the scroll-blocks-on mode will require them to.
+ root->SetScrollBlocksOn(ScrollBlocksOnWheelEvent | ScrollBlocksOnStartTouch);
EXPECT_EQ(InputHandler::ScrollOnMainThread,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
// But gesture scrolls can still be handled.
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+ host_impl_->ScrollEnd();
+
+ // And if the handlers go away, wheel scrolls can again be processed
+ // on impl (despite the scroll-blocks-on mode).
+ root->SetHaveWheelEventHandlers(false);
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+ host_impl_->ScrollEnd();
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
+ LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+ DrawFrame();
+ LayerImpl* root = host_impl_->active_tree()->root_layer();
+
+ LayerImpl* child = 0;
+ {
+ scoped_ptr<LayerImpl> child_layer =
+ LayerImpl::Create(host_impl_->active_tree(), 6);
+ child = child_layer.get();
+ child_layer->SetDrawsContent(true);
+ child_layer->SetPosition(gfx::PointF(0, 20));
+ child_layer->SetBounds(gfx::Size(50, 50));
+ child_layer->SetContentBounds(gfx::Size(50, 50));
+ scroll->AddChild(child_layer.Pass());
+ }
+
+ // Touch handler regions determine whether touch events block scroll.
+ root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
+ EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
+ root->SetScrollBlocksOn(ScrollBlocksOnStartTouch | ScrollBlocksOnWheelEvent);
+ EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
+
+ // But they don't influence the actual handling of the scroll gestures.
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+ host_impl_->ScrollEnd();
+
+ // It's the union of scroll-blocks-on mode bits across all layers in the
+ // scroll paret chain that matters.
+ EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
+ root->SetScrollBlocksOn(ScrollBlocksOnNone);
+ EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
+ child->SetScrollBlocksOn(ScrollBlocksOnStartTouch);
+ EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
+ SetupScrollAndContentsLayers(gfx::Size(100, 100));
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+ DrawFrame();
+ LayerImpl* root = host_impl_->active_tree()->root_layer();
+
+ // With registered scroll handlers, scrolls don't generally have to go
+ // to the main thread.
+ root->SetHaveScrollEventHandlers(true);
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+ host_impl_->ScrollEnd();
+
+ // Even the default scroll blocks on mode doesn't require this.
+ root->SetScrollBlocksOn(ScrollBlocksOnWheelEvent | ScrollBlocksOnStartTouch);
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+ host_impl_->ScrollEnd();
+
+ // But the page can opt in to blocking on scroll event handlers.
+ root->SetScrollBlocksOn(ScrollBlocksOnScrollEvent);
+ EXPECT_EQ(InputHandler::ScrollOnMainThread,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+
+ // Gesture and Wheel scrolls behave identically in this regard.
+ EXPECT_EQ(InputHandler::ScrollOnMainThread,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
+
+ // And if the handlers go away, scrolls can again be processed on impl
+ // (despite the scroll-blocks-on mode).
+ root->SetHaveScrollEventHandlers(false);
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+ host_impl_->ScrollEnd();
+}
+
+TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
+ host_impl_->SetViewportSize(gfx::Size(50, 50));
+
+ // Create a normal scrollable root layer
+ LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
+ LayerImpl* root_child = root_scroll->children()[0];
+ LayerImpl* root = host_impl_->active_tree()->root_layer();
+ DrawFrame();
+
+ // Create two child scrollable layers
+ LayerImpl* child1 = 0;
+ {
+ scoped_ptr<LayerImpl> scrollable_child_clip_1 =
+ LayerImpl::Create(host_impl_->active_tree(), 6);
+ scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
+ 7, gfx::Size(10, 10), scrollable_child_clip_1.get());
+ child1 = scrollable_child_1.get();
+ scrollable_child_1->SetPosition(gfx::Point(5, 5));
+ scrollable_child_1->SetHaveWheelEventHandlers(true);
+ scrollable_child_1->SetHaveScrollEventHandlers(true);
+ scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
+ root_child->AddChild(scrollable_child_clip_1.Pass());
+ }
+
+ LayerImpl* child2 = 0;
+ {
+ scoped_ptr<LayerImpl> scrollable_child_clip_2 =
+ LayerImpl::Create(host_impl_->active_tree(), 8);
+ scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
+ 9, gfx::Size(10, 10), scrollable_child_clip_2.get());
+ child2 = scrollable_child_2.get();
+ scrollable_child_2->SetPosition(gfx::Point(5, 20));
+ scrollable_child_2->SetHaveWheelEventHandlers(true);
+ scrollable_child_2->SetHaveScrollEventHandlers(true);
+ scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
+ root_child->AddChild(scrollable_child_clip_2.Pass());
+ }
+
+ // Scroll-blocks-on on a layer affects scrolls that hit that layer.
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture));
+ host_impl_->ScrollEnd();
+ child1->SetScrollBlocksOn(ScrollBlocksOnScrollEvent);
+ EXPECT_EQ(InputHandler::ScrollOnMainThread,
+ host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture));
+
+ // But not those that hit only other layers.
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Gesture));
+ host_impl_->ScrollEnd();
+
+ // It's the union of bits set across the scroll ancestor chain that matters.
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Gesture));
+ host_impl_->ScrollEnd();
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Wheel));
+ host_impl_->ScrollEnd();
+ root->SetScrollBlocksOn(ScrollBlocksOnWheelEvent);
+ EXPECT_EQ(InputHandler::ScrollStarted,
+ host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Gesture));
+ host_impl_->ScrollEnd();
+ EXPECT_EQ(InputHandler::ScrollOnMainThread,
+ host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Wheel));
+ child2->SetScrollBlocksOn(ScrollBlocksOnScrollEvent);
+ EXPECT_EQ(InputHandler::ScrollOnMainThread,
+ host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Wheel));
+ EXPECT_EQ(InputHandler::ScrollOnMainThread,
+ host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::Gesture));
}
TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
@@ -3543,9 +3702,8 @@
// The layer should have scrolled down in its local coordinates.
scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
- ExpectContains(*scroll_info.get(),
- scroll_layer->id(),
- gfx::Vector2d(0, gesture_scroll_delta.x()));
+ ExpectContains(*scroll_info.get(), scroll_layer->id(),
+ gfx::Vector2dF(0, gesture_scroll_delta.x()));
// Reset and scroll down with the wheel.
scroll_layer->SetScrollDelta(gfx::Vector2dF());
@@ -3606,10 +3764,9 @@
// The child layer should have scrolled down in its local coordinates an
// amount proportional to the angle between it and the input scroll delta.
- gfx::Vector2d expected_scroll_delta(
- 0,
- gesture_scroll_delta.y() *
- std::cos(MathUtil::Deg2Rad(child_layer_angle)));
+ gfx::Vector2dF expected_scroll_delta(
+ 0, gesture_scroll_delta.y() *
+ std::cos(MathUtil::Deg2Rad(child_layer_angle)));
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
@@ -3630,17 +3787,16 @@
// The child layer should have scrolled down in its local coordinates an
// amount proportional to the angle between it and the input scroll delta.
- gfx::Vector2d expected_scroll_delta(
- 0,
- -gesture_scroll_delta.x() *
- std::sin(MathUtil::Deg2Rad(child_layer_angle)));
+ gfx::Vector2dF expected_scroll_delta(
+ 0, -gesture_scroll_delta.x() *
+ std::sin(MathUtil::Deg2Rad(child_layer_angle)));
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
// The root scroll layer should have scrolled more, since the input scroll
// delta was mostly orthogonal to the child layer's vertical scroll axis.
- gfx::Vector2d expected_root_scroll_delta(
+ gfx::Vector2dF expected_root_scroll_delta(
gesture_scroll_delta.x() *
std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
0);
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 1235e15..eecc5a0 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -26,10 +26,9 @@
bool FillsBoundsCompletely() const override { return false; }
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& rect,
- ContentLayerClient::GraphicsContextStatus gc_status) override {
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& rect,
+ PaintingControlSetting picture_control) override {
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(SkIntToScalar(2));
@@ -49,7 +48,7 @@
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override {
+ PaintingControlSetting picture_control) override {
NOTIMPLEMENTED();
return DisplayItemList::Create();
}
@@ -97,9 +96,8 @@
SkCanvas canvas(bitmap);
canvas.scale(SkIntToScalar(4), SkIntToScalar(4));
MaskContentLayerClient client(mask_bounds);
- client.PaintContents(&canvas,
- gfx::Rect(mask_bounds),
- ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
+ client.PaintContents(&canvas, gfx::Rect(mask_bounds),
+ ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
mask->SetBitmap(bitmap);
scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
diff --git a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
index 4d60baf..5d828c5 100644
--- a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
+++ b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
@@ -61,10 +61,9 @@
bool FillsBoundsCompletely() const override { return false; }
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus gc_status) override {
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {
SkPaint paint;
paint.setColor(SK_ColorBLUE);
canvas->drawRect(SkRect::MakeWH(layer_rect_.width(),
@@ -82,7 +81,7 @@
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override {
+ PaintingControlSetting picture_control) override {
NOTIMPLEMENTED();
return DisplayItemList::Create();
}
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index d4bfb6e..cff3b1f 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1104,17 +1104,16 @@
void SetTestLayer(Layer* test_layer) { test_layer_ = test_layer; }
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus gc_status) override {
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {
// Set layer opacity to 0.
if (test_layer_)
test_layer_->SetOpacity(0.f);
}
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override {
+ PaintingControlSetting picture_control) override {
NOTIMPLEMENTED();
return DisplayItemList::Create();
}
@@ -2066,7 +2065,7 @@
}
void AfterTest() override {
- EXPECT_GE(3, num_will_begin_impl_frame_);
+ EXPECT_GE(num_will_begin_impl_frame_, 3);
EXPECT_EQ(2, num_send_begin_main_frame_);
}
@@ -2327,17 +2326,16 @@
int paint_count() const { return paint_count_; }
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus gc_status) override {
- FakeContentLayerClient::PaintContents(canvas, clip, gc_status);
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {
+ FakeContentLayerClient::PaintContents(canvas, clip, picture_control);
++paint_count_;
}
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override {
+ PaintingControlSetting picture_control) override {
NOTIMPLEMENTED();
return DisplayItemList::Create();
}
@@ -2605,16 +2603,15 @@
void set_layer(Layer* layer) { layer_ = layer; }
- void PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& clip,
- ContentLayerClient::GraphicsContextStatus gc_status) override {
+ void PaintContents(SkCanvas* canvas,
+ const gfx::Rect& clip,
+ PaintingControlSetting picture_control) override {
layer_->SetBounds(gfx::Size(2, 2));
}
scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
const gfx::Rect& clip,
- GraphicsContextStatus gc_status) override {
+ PaintingControlSetting picture_control) override {
NOTIMPLEMENTED();
return DisplayItemList::Create();
}
@@ -5518,8 +5515,8 @@
EndTest();
}
- void ApplyViewportDeltas(const gfx::Vector2d& inner,
- const gfx::Vector2d& outer,
+ void ApplyViewportDeltas(const gfx::Vector2dF& inner,
+ const gfx::Vector2dF& outer,
const gfx::Vector2dF& elastic_overscroll_delta,
float scale_delta,
float top_controls_delta) override {
@@ -6096,6 +6093,73 @@
MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestOneActivatePerPrepareTiles);
+class LayerTreeHostTestFrameTimingRequestsSaveTimestamps
+ : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestFrameTimingRequestsSaveTimestamps()
+ : check_results_on_commit_(false) {}
+
+ void SetupTree() override {
+ scoped_refptr<FakePictureLayer> root_layer =
+ FakePictureLayer::Create(&client_);
+ root_layer->SetBounds(gfx::Size(200, 200));
+ root_layer->SetIsDrawable(true);
+
+ scoped_refptr<FakePictureLayer> child_layer =
+ FakePictureLayer::Create(&client_);
+ child_layer->SetBounds(gfx::Size(1500, 1500));
+ child_layer->SetIsDrawable(true);
+
+ std::vector<FrameTimingRequest> requests;
+ requests.push_back(FrameTimingRequest(1, gfx::Rect(0, 0, 100, 100)));
+ requests.push_back(FrameTimingRequest(2, gfx::Rect(300, 0, 100, 100)));
+ child_layer->SetFrameTimingRequests(requests);
+
+ root_layer->AddChild(child_layer);
+ layer_tree_host()->SetRootLayer(root_layer);
+ LayerTreeHostTest::SetupTree();
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
+ if (!check_results_on_commit_)
+ return;
+
+ // Since in reality, the events will be read by LayerTreeHost during commit,
+ // we check the requests here to ensure that they are correct at the next
+ // commit time (as opposed to checking in DrawLayers for instance).
+ // TODO(vmpstr): Change this to read things from the main thread when this
+ // information is propagated to the main thread (not yet implemented).
+ FrameTimingTracker* tracker = host_impl->frame_timing_tracker();
+ scoped_ptr<FrameTimingTracker::CompositeTimingSet> timing_set =
+ tracker->GroupCountsByRectId();
+ EXPECT_EQ(1u, timing_set->size());
+ auto rect_1_it = timing_set->find(1);
+ EXPECT_TRUE(rect_1_it != timing_set->end());
+ const auto& timing_events = rect_1_it->second;
+ EXPECT_EQ(1u, timing_events.size());
+ EXPECT_EQ(host_impl->active_tree()->source_frame_number(),
+ timing_events[0].frame_id);
+ EXPECT_GT(timing_events[0].timestamp, base::TimeTicks());
+
+ EndTest();
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
+ check_results_on_commit_ = true;
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void AfterTest() override {}
+
+ private:
+ FakeContentLayerClient client_;
+ bool check_results_on_commit_;
+};
+
+MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestFrameTimingRequestsSaveTimestamps);
+
class LayerTreeHostTestActivationCausesPrepareTiles : public LayerTreeHostTest {
public:
LayerTreeHostTestActivationCausesPrepareTiles()
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index bbdfe6b..e36f6a0 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1096,13 +1096,21 @@
host_impl->BlockNotifyReadyToActivateForTesting(false);
}
+ void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+ if (!host_impl->settings().impl_side_painting)
+ return;
+ if (host_impl->pending_tree()->source_frame_number() != 1)
+ return;
+ LayerImpl* scroll_layer_impl =
+ host_impl->pending_tree()->root_layer()->children()[0];
+ EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
+ }
+
void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+ if (host_impl->active_tree()->source_frame_number() != 1)
+ return;
LayerImpl* scroll_layer_impl =
host_impl->active_tree()->root_layer()->children()[0];
- if (scroll_layer_impl->layer_animation_controller()->GetAnimation(
- Animation::ScrollOffset))
- return;
-
EXPECT_EQ(final_postion_, scroll_layer_impl->CurrentScrollOffset());
EndTest();
}
diff --git a/cc/trees/layer_tree_host_unittest_no_message_loop.cc b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
index 75eda92..d2014ea 100644
--- a/cc/trees/layer_tree_host_unittest_no_message_loop.cc
+++ b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
@@ -54,12 +54,12 @@
~LayerTreeHostNoMessageLoopTest() override {}
// LayerTreeHostClient overrides.
- void WillBeginMainFrame(int frame_id) override {}
+ void WillBeginMainFrame() override {}
void BeginMainFrame(const BeginFrameArgs& args) override {}
void DidBeginMainFrame() override {}
void Layout() override {}
- void ApplyViewportDeltas(const gfx::Vector2d& inner_delta,
- const gfx::Vector2d& outer_delta,
+ void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
const gfx::Vector2dF& elastic_overscroll_delta,
float page_scale,
float top_controls_delta) override {}
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index 1c20b4c..03a0860 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -429,19 +429,14 @@
PostSetNeedsCommitToMainThread();
break;
case 1:
- EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(),
- gfx::ToFlooredVector2d(scroll_amount_));
- EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(),
- gfx::Vector2dF(fmod(scroll_amount_.x(), 1.0f), 0.0f));
+ EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(), scroll_amount_);
+ EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2dF());
PostSetNeedsCommitToMainThread();
break;
case 2:
- EXPECT_VECTOR_EQ(
- scroll_layer->BaseScrollOffset(),
- gfx::ToFlooredVector2d(scroll_amount_ + scroll_amount_));
- EXPECT_VECTOR_EQ(
- scroll_layer->ScrollDelta(),
- gfx::Vector2dF(fmod(2.0f * scroll_amount_.x(), 1.0f), 0.0f));
+ EXPECT_VECTOR_EQ(scroll_layer->BaseScrollOffset(),
+ (scroll_amount_ + scroll_amount_));
+ EXPECT_VECTOR_EQ(scroll_layer->ScrollDelta(), gfx::Vector2dF());
EndTest();
break;
}
@@ -1044,21 +1039,24 @@
// Set max_scroll_offset = (100, 100).
scroll_layer->SetBounds(
gfx::Size(root->bounds().width() + 100, root->bounds().height() + 100));
- EXPECT_EQ(InputHandler::ScrollStarted,
- scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f),
- InputHandler::Gesture));
+ EXPECT_EQ(
+ InputHandler::ScrollStarted,
+ scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture,
+ ScrollBlocksOnNone));
// Set max_scroll_offset = (0, 0).
scroll_layer->SetBounds(root->bounds());
- EXPECT_EQ(InputHandler::ScrollIgnored,
- scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f),
- InputHandler::Gesture));
+ EXPECT_EQ(
+ InputHandler::ScrollIgnored,
+ scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture,
+ ScrollBlocksOnNone));
// Set max_scroll_offset = (-100, -100).
scroll_layer->SetBounds(gfx::Size());
- EXPECT_EQ(InputHandler::ScrollIgnored,
- scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f),
- InputHandler::Gesture));
+ EXPECT_EQ(
+ InputHandler::ScrollIgnored,
+ scroll_layer->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture,
+ ScrollBlocksOnNone));
EndTest();
}
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 97ebb00..80ccf14 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -122,7 +122,12 @@
void LayerTreeImpl::ReleaseResources() {
if (root_layer_)
- ReleaseResourcesRecursive(root_layer_.get());
+ ProcessLayersRecursive(root_layer_.get(), &LayerImpl::ReleaseResources);
+}
+
+void LayerTreeImpl::RecreateResources() {
+ if (root_layer_)
+ ProcessLayersRecursive(root_layer_.get(), &LayerImpl::RecreateResources);
}
void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
@@ -1159,15 +1164,16 @@
return layers_with_copy_output_request_;
}
-void LayerTreeImpl::ReleaseResourcesRecursive(LayerImpl* current) {
+void LayerTreeImpl::ProcessLayersRecursive(LayerImpl* current,
+ void (LayerImpl::*function)()) {
DCHECK(current);
- current->ReleaseResources();
+ (current->*function)();
if (current->mask_layer())
- ReleaseResourcesRecursive(current->mask_layer());
+ ProcessLayersRecursive(current->mask_layer(), function);
if (current->replica_layer())
- ReleaseResourcesRecursive(current->replica_layer());
+ ProcessLayersRecursive(current->replica_layer(), function);
for (size_t i = 0; i < current->children().size(); ++i)
- ReleaseResourcesRecursive(current->children()[i]);
+ ProcessLayersRecursive(current->children()[i], function);
}
template <typename LayerType>
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index a58b645..2329139 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -19,10 +19,16 @@
#include "cc/resources/ui_resource_client.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+} // namespace base
namespace cc {
@@ -64,6 +70,7 @@
void Shutdown();
void ReleaseResources();
+ void RecreateResources();
// Methods called by the layer tree that pass-through or access LTHI.
// ---------------------------------------------------------------------------
@@ -336,7 +343,8 @@
LayerTreeHostImpl* layer_tree_host_impl,
scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
scoped_refptr<SyncedElasticOverscroll> elastic_overscroll);
- void ReleaseResourcesRecursive(LayerImpl* current);
+ void ProcessLayersRecursive(LayerImpl* current,
+ void (LayerImpl::*function)());
float ClampPageScaleFactorToLimits(float page_scale_factor) const;
void PushPageScaleFactorAndLimits(const float* page_scale_factor,
float min_page_scale_factor,
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index d578daf..07dfc29 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -30,6 +30,7 @@
gpu_rasterization_enabled(false),
gpu_rasterization_forced(false),
gpu_rasterization_msaa_sample_count(0),
+ threaded_gpu_rasterization_enabled(false),
create_low_res_tiling(false),
scrollbar_animator(NoAnimator),
scrollbar_fade_delay_ms(0),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 597a279..8ba859a 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -9,7 +9,9 @@
#include "cc/base/cc_export.h"
#include "cc/debug/layer_tree_debug_state.h"
#include "cc/output/renderer_settings.h"
+#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/geometry/size.h"
namespace cc {
@@ -36,6 +38,7 @@
bool gpu_rasterization_enabled;
bool gpu_rasterization_forced;
int gpu_rasterization_msaa_sample_count;
+ bool threaded_gpu_rasterization_enabled;
bool create_low_res_tiling;
enum ScrollbarAnimator {
@@ -82,6 +85,7 @@
bool record_full_layer;
bool use_display_lists;
bool verify_property_trees;
+ skia::RefPtr<SkTypeface> hud_typeface;
LayerTreeDebugState initial_debug_state;
};
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 1afd4bd..934e1fc 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -171,10 +171,12 @@
}
TransformNode* node = data_for_children->transform_tree->back();
+ layer->set_transform_tree_index(node->id);
node->data.flattens = layer->should_flatten_transform();
node->data.target_id =
data_from_ancestor.render_target->transform_tree_index();
+ DCHECK_NE(node->data.target_id, -1);
node->data.is_animated = layer->TransformIsAnimating();
gfx::Transform transform;
@@ -214,7 +216,6 @@
data_from_ancestor.transform_tree->UpdateScreenSpaceTransform(node->id);
layer->set_offset_to_transform_parent(gfx::Vector2dF());
- layer->set_transform_tree_index(node->id);
}
void BuildPropertyTreesInternal(Layer* layer,
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 206af66..2f181fc 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -17,11 +17,17 @@
#include "cc/base/cc_export.h"
namespace base {
-namespace debug {
+namespace trace_event {
class TracedValue;
}
-class SingleThreadTaskRunner;
+
+// TODO(ssid): remove these aliases after the tracing clients are moved to the
+// new trace_event namespace. See crbug.com/451032. ETA: March 2015
+namespace debug {
+using ::base::trace_event::TracedValue;
}
+class SingleThreadTaskRunner;
+} // namespace base
namespace gfx {
class Rect;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index dc58d39..f913c1f 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -7,6 +7,7 @@
#include "base/auto_reset.h"
#include "base/trace_event/trace_event.h"
#include "cc/debug/benchmark_instrumentation.h"
+#include "cc/debug/devtools_instrumentation.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
#include "cc/quads/draw_quad.h"
@@ -204,6 +205,8 @@
commit_requested_ = false;
layer_tree_host_->WillCommit();
+ devtools_instrumentation::ScopedCommitTrace commit_task(
+ layer_tree_host_->id());
// Commit immediately.
{
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 88f1314..5ee43ab 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -796,6 +796,8 @@
bool updated = layer_tree_host()->UpdateLayers(queue.get());
layer_tree_host()->WillCommit();
+ devtools_instrumentation::ScopedCommitTrace commit_task(
+ layer_tree_host()->id());
// Before calling animate, we set main().animate_requested to false. If it is
// true now, it means SetNeedAnimate was called again, but during a state when
diff --git a/crypto/openssl_util.cc b/crypto/openssl_util.cc
index f41b55a..8ea1232 100644
--- a/crypto/openssl_util.cc
+++ b/crypto/openssl_util.cc
@@ -48,6 +48,18 @@
private:
friend struct DefaultSingletonTraits<OpenSSLInitSingleton>;
OpenSSLInitSingleton() {
+#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
+ const bool has_neon =
+ (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
+ // CRYPTO_set_NEON_capable is called before |SSL_library_init| because this
+ // stops BoringSSL from probing for NEON support via SIGILL in the case
+ // that getauxval isn't present.
+ CRYPTO_set_NEON_capable(has_neon);
+ // See https://code.google.com/p/chromium/issues/detail?id=341598
+ base::CPU cpu;
+ CRYPTO_set_NEON_functional(!cpu.has_broken_neon());
+#endif
+
SSL_load_error_strings();
SSL_library_init();
int num_locks = CRYPTO_num_locks();
@@ -56,16 +68,6 @@
locks_.push_back(new base::Lock());
CRYPTO_set_locking_callback(LockingCallback);
CRYPTO_THREADID_set_callback(CurrentThreadId);
-
-#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
- const bool has_neon =
- (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
- if (has_neon)
- CRYPTO_set_NEON_capable(1);
- // See https://code.google.com/p/chromium/issues/detail?id=341598
- base::CPU cpu;
- CRYPTO_set_NEON_functional(!cpu.has_broken_neon());
-#endif
}
~OpenSSLInitSingleton() {
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc
index 21598a8..daa04f1 100644
--- a/gin/isolate_holder.cc
+++ b/gin/isolate_holder.cc
@@ -254,6 +254,7 @@
#endif
isolate_data_.reset();
isolate_->Dispose();
+ isolate_ = NULL;
}
// static
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 448fe05..0896026 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -140,6 +140,7 @@
"command_buffer/client/fenced_allocator_test.cc",
"command_buffer/client/gles2_implementation_unittest.cc",
"command_buffer/client/mapped_memory_unittest.cc",
+ "command_buffer/client/program_info_manager_unittest.cc",
"command_buffer/client/query_tracker_unittest.cc",
"command_buffer/client/ring_buffer_test.cc",
"command_buffer/client/transfer_buffer_unittest.cc",
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index 88bed32..9d3a0f9 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -86,6 +86,7 @@
#define glGenTransformFeedbacks GLES2_GET_FUN(GenTransformFeedbacks)
#define glGetActiveAttrib GLES2_GET_FUN(GetActiveAttrib)
#define glGetActiveUniform GLES2_GET_FUN(GetActiveUniform)
+#define glGetActiveUniformBlockName GLES2_GET_FUN(GetActiveUniformBlockName)
#define glGetAttachedShaders GLES2_GET_FUN(GetAttachedShaders)
#define glGetAttribLocation GLES2_GET_FUN(GetAttribLocation)
#define glGetBooleanv GLES2_GET_FUN(GetBooleanv)
@@ -109,6 +110,7 @@
#define glGetString GLES2_GET_FUN(GetString)
#define glGetTexParameterfv GLES2_GET_FUN(GetTexParameterfv)
#define glGetTexParameteriv GLES2_GET_FUN(GetTexParameteriv)
+#define glGetUniformBlockIndex GLES2_GET_FUN(GetUniformBlockIndex)
#define glGetUniformfv GLES2_GET_FUN(GetUniformfv)
#define glGetUniformiv GLES2_GET_FUN(GetUniformiv)
#define glGetUniformLocation GLES2_GET_FUN(GetUniformLocation)
@@ -148,6 +150,7 @@
#define glShaderSource GLES2_GET_FUN(ShaderSource)
#define glShallowFinishCHROMIUM GLES2_GET_FUN(ShallowFinishCHROMIUM)
#define glShallowFlushCHROMIUM GLES2_GET_FUN(ShallowFlushCHROMIUM)
+#define glOrderingBarrierCHROMIUM GLES2_GET_FUN(OrderingBarrierCHROMIUM)
#define glStencilFunc GLES2_GET_FUN(StencilFunc)
#define glStencilFuncSeparate GLES2_GET_FUN(StencilFuncSeparate)
#define glStencilMask GLES2_GET_FUN(StencilMask)
@@ -254,6 +257,7 @@
#define glRateLimitOffscreenContextCHROMIUM \
GLES2_GET_FUN(RateLimitOffscreenContextCHROMIUM)
#define glGetProgramInfoCHROMIUM GLES2_GET_FUN(GetProgramInfoCHROMIUM)
+#define glGetUniformBlocksCHROMIUM GLES2_GET_FUN(GetUniformBlocksCHROMIUM)
#define glCreateStreamTextureCHROMIUM GLES2_GET_FUN(CreateStreamTextureCHROMIUM)
#define glCreateImageCHROMIUM GLES2_GET_FUN(CreateImageCHROMIUM)
#define glDestroyImageCHROMIUM GLES2_GET_FUN(DestroyImageCHROMIUM)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index b0884b6..dc576d7 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1508,6 +1508,10 @@
'type': 'Bind',
'id_mapping': [ 'Buffer' ],
'gen_func': 'GenBuffersARB',
+ 'valid_args': {
+ '3': '4',
+ '4': '4'
+ },
'unsafe': True,
},
'BindFramebuffer': {
@@ -2030,6 +2034,15 @@
'uint32_t type',
],
},
+ 'GetActiveUniformBlockName': {
+ 'type': 'Custom',
+ 'data_transfer_methods': ['shm'],
+ 'cmd_args':
+ 'GLidProgram program, GLuint index, uint32_t name_bucket_id, '
+ 'void* result',
+ 'result': ['int32_t'],
+ 'unsafe': True,
+ },
'GetAttachedShaders': {
'type': 'Custom',
'data_transfer_methods': ['shm'],
@@ -2200,7 +2213,27 @@
'get_len_enum': 'GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE',
'unit_test': False,
'extension': True,
- },
+ },
+ 'GetUniformBlockIndex': {
+ 'type': 'Custom',
+ 'data_transfer_methods': ['shm'],
+ 'cmd_args':
+ 'GLidProgram program, uint32_t name_bucket_id, GLuint* index',
+ 'result': ['GLuint'],
+ 'error_return': 'GL_INVALID_INDEX',
+ 'unsafe': True,
+ },
+ 'GetUniformBlocksCHROMIUM': {
+ 'type': 'Custom',
+ 'expectation': False,
+ 'impl_func': False,
+ 'extension': True,
+ 'chromium': True,
+ 'client_test': False,
+ 'cmd_args': 'GLidProgram program, uint32_t bucket_id',
+ 'result': ['uint32_t'],
+ 'unsafe': True,
+ },
'GetUniformfv': {
'type': 'Custom',
'data_transfer_methods': ['shm'],
@@ -3021,6 +3054,13 @@
'chromium': True,
'client_test': False,
},
+ 'OrderingBarrierCHROMIUM': {
+ 'impl_func': False,
+ 'gen_cmd': False,
+ 'extension': True,
+ 'chromium': True,
+ 'client_test': False,
+ },
'TraceBeginCHROMIUM': {
'type': 'Custom',
'impl_func': False,
diff --git a/gpu/command_buffer/client/client_test_helper.cc b/gpu/command_buffer/client/client_test_helper.cc
index 3c50f6b..258e821 100644
--- a/gpu/command_buffer/client/client_test_helper.cc
+++ b/gpu/command_buffer/client/client_test_helper.cc
@@ -130,6 +130,10 @@
FlushHelper(put_offset);
}
+void MockClientCommandBuffer::OrderingBarrier(int32 put_offset) {
+ FlushHelper(put_offset);
+}
+
void MockClientCommandBuffer::DelegateToFake() {
ON_CALL(*this, DestroyTransferBuffer(_))
.WillByDefault(Invoke(
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h
index 6778a83..111c4f4 100644
--- a/gpu/command_buffer/client/client_test_helper.h
+++ b/gpu/command_buffer/client/client_test_helper.h
@@ -70,6 +70,7 @@
MOCK_METHOD1(DestroyTransferBuffer, void(int32 id));
virtual void Flush(int32 put_offset) override;
+ virtual void OrderingBarrier(int32 put_offset) override;
void DelegateToFake();
};
@@ -80,6 +81,7 @@
virtual ~MockClientCommandBufferMockFlush();
MOCK_METHOD1(Flush, void(int32 put_offset));
+ MOCK_METHOD1(OrderingBarrier, void(int32 put_offset));
void DelegateToFake();
};
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc
index a99201e..038ba41 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper.cc
@@ -150,7 +150,7 @@
if (put_ == total_entry_count_)
put_ = 0;
- if (usable() && last_put_sent_ != put_) {
+ if (usable()) {
last_flush_time_ = base::TimeTicks::Now();
last_put_sent_ = put_;
command_buffer_->Flush(put_);
@@ -159,6 +159,18 @@
}
}
+void CommandBufferHelper::OrderingBarrier() {
+ // Wrap put_ before setting the barrier.
+ if (put_ == total_entry_count_)
+ put_ = 0;
+
+ if (usable()) {
+ command_buffer_->OrderingBarrier(put_);
+ ++flush_generation_;
+ CalcImmediateEntries(0);
+ }
+}
+
#if defined(CMD_HELPER_PERIODIC_FLUSH_CHECK)
void CommandBufferHelper::PeriodicFlushCheck() {
base::TimeTicks current_time = base::TimeTicks::Now();
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h
index 053c1c9..3f7fba7 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.h
+++ b/gpu/command_buffer/client/cmd_buffer_helper.h
@@ -66,6 +66,11 @@
// returns, the command buffer service is aware of all pending commands.
void Flush();
+ // Ensures that commands up to the put pointer will be processed in the
+ // command buffer service before any future commands on other command buffers
+ // sharing a channel.
+ void OrderingBarrier();
+
// Waits until all the commands have been executed. Returns whether it
// was successful. The function will fail if the command buffer service has
// disconnected.
@@ -322,6 +327,7 @@
int32 token_;
int32 put_;
int32 last_put_sent_;
+ int32 last_barrier_put_sent_;
#if defined(CMD_HELPER_PERIODIC_FLUSH_CHECK)
int commands_issued_;
diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
index 2e807e2..ac83da5 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
@@ -709,4 +709,64 @@
EXPECT_EQ(error::kNoError, GetError());
}
+TEST_F(CommandBufferHelperTest, TestOrderingBarrierFlushGeneration) {
+ // Explicit flushing only.
+ helper_->SetAutomaticFlushes(false);
+
+ // Generation should change after OrderingBarrier() but not before.
+ uint32 gen1, gen2, gen3;
+
+ gen1 = GetHelperFlushGeneration();
+ AddUniqueCommandWithExpect(error::kNoError, 2);
+ gen2 = GetHelperFlushGeneration();
+ helper_->OrderingBarrier();
+ gen3 = GetHelperFlushGeneration();
+ EXPECT_EQ(gen2, gen1);
+ EXPECT_NE(gen3, gen2);
+
+ helper_->Finish();
+
+ // Check that the commands did happen.
+ Mock::VerifyAndClearExpectations(api_mock_.get());
+
+ // Check the error status.
+ EXPECT_EQ(error::kNoError, GetError());
+}
+
+// Expect Flush() to always call CommandBuffer::Flush().
+TEST_F(CommandBufferHelperTest, TestFlushToCommandBuffer) {
+ // Explicit flushing only.
+ helper_->SetAutomaticFlushes(false);
+
+ int flush_count1, flush_count2, flush_count3;
+
+ flush_count1 = command_buffer_->FlushCount();
+ AddUniqueCommandWithExpect(error::kNoError, 2);
+ helper_->Flush();
+ flush_count2 = command_buffer_->FlushCount();
+ helper_->Flush();
+ flush_count3 = command_buffer_->FlushCount();
+
+ EXPECT_EQ(flush_count2, flush_count1 + 1);
+ EXPECT_EQ(flush_count3, flush_count2 + 1);
+}
+
+// Expect OrderingBarrier() to always call CommandBuffer::OrderingBarrier().
+TEST_F(CommandBufferHelperTest, TestOrderingBarrierToCommandBuffer) {
+ // Explicit flushing only.
+ helper_->SetAutomaticFlushes(false);
+
+ int flush_count1, flush_count2, flush_count3;
+
+ flush_count1 = command_buffer_->FlushCount();
+ AddUniqueCommandWithExpect(error::kNoError, 2);
+ helper_->OrderingBarrier();
+ flush_count2 = command_buffer_->FlushCount();
+ helper_->OrderingBarrier();
+ flush_count3 = command_buffer_->FlushCount();
+
+ EXPECT_EQ(flush_count2, flush_count1 + 1);
+ EXPECT_EQ(flush_count3, flush_count2 + 1);
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc
index 0f15f1d..f10695e 100644
--- a/gpu/command_buffer/client/gl_in_process_context.cc
+++ b/gpu/command_buffer/client/gl_in_process_context.cc
@@ -68,7 +68,7 @@
size_t GetMappedMemoryLimit() override;
#if defined(OS_ANDROID)
- virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
+ scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
uint32 stream_id) override;
#endif
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 503fff0..dfe7a6a 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -338,6 +338,14 @@
gles2::GetGLContext()->GetActiveUniform(program, index, bufsize, length, size,
type, name);
}
+void GLES2GetActiveUniformBlockName(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* name) {
+ gles2::GetGLContext()->GetActiveUniformBlockName(program, index, bufsize,
+ length, name);
+}
void GLES2GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -431,6 +439,9 @@
void GLES2GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
gles2::GetGLContext()->GetTexParameteriv(target, pname, params);
}
+GLuint GLES2GetUniformBlockIndex(GLuint program, const char* name) {
+ return gles2::GetGLContext()->GetUniformBlockIndex(program, name);
+}
void GLES2GetUniformfv(GLuint program, GLint location, GLfloat* params) {
gles2::GetGLContext()->GetUniformfv(program, location, params);
}
@@ -578,6 +589,9 @@
void GLES2ShallowFlushCHROMIUM() {
gles2::GetGLContext()->ShallowFlushCHROMIUM();
}
+void GLES2OrderingBarrierCHROMIUM() {
+ gles2::GetGLContext()->OrderingBarrierCHROMIUM();
+}
void GLES2StencilFunc(GLenum func, GLint ref, GLuint mask) {
gles2::GetGLContext()->StencilFunc(func, ref, mask);
}
@@ -1038,6 +1052,12 @@
void* info) {
gles2::GetGLContext()->GetProgramInfoCHROMIUM(program, bufsize, size, info);
}
+void GLES2GetUniformBlocksCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) {
+ gles2::GetGLContext()->GetUniformBlocksCHROMIUM(program, bufsize, size, info);
+}
GLuint GLES2CreateStreamTextureCHROMIUM(GLuint texture) {
return gles2::GetGLContext()->CreateStreamTextureCHROMIUM(texture);
}
@@ -1539,6 +1559,10 @@
reinterpret_cast<GLES2FunctionPointer>(glGetActiveUniform),
},
{
+ "glGetActiveUniformBlockName",
+ reinterpret_cast<GLES2FunctionPointer>(glGetActiveUniformBlockName),
+ },
+ {
"glGetAttachedShaders",
reinterpret_cast<GLES2FunctionPointer>(glGetAttachedShaders),
},
@@ -1628,6 +1652,10 @@
reinterpret_cast<GLES2FunctionPointer>(glGetTexParameteriv),
},
{
+ "glGetUniformBlockIndex",
+ reinterpret_cast<GLES2FunctionPointer>(glGetUniformBlockIndex),
+ },
+ {
"glGetUniformfv",
reinterpret_cast<GLES2FunctionPointer>(glGetUniformfv),
},
@@ -1784,6 +1812,10 @@
reinterpret_cast<GLES2FunctionPointer>(glShallowFlushCHROMIUM),
},
{
+ "glOrderingBarrierCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glOrderingBarrierCHROMIUM),
+ },
+ {
"glStencilFunc",
reinterpret_cast<GLES2FunctionPointer>(glStencilFunc),
},
@@ -2192,6 +2224,10 @@
reinterpret_cast<GLES2FunctionPointer>(glGetProgramInfoCHROMIUM),
},
{
+ "glGetUniformBlocksCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glGetUniformBlocksCHROMIUM),
+ },
+ {
"glCreateStreamTextureCHROMIUM",
reinterpret_cast<GLES2FunctionPointer>(glCreateStreamTextureCHROMIUM),
},
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index 2ac4d69..fc0f76d 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -702,6 +702,18 @@
}
}
+void GetActiveUniformBlockName(GLuint program,
+ GLuint index,
+ uint32_t name_bucket_id,
+ uint32_t result_shm_id,
+ uint32_t result_shm_offset) {
+ gles2::cmds::GetActiveUniformBlockName* c =
+ GetCmdSpace<gles2::cmds::GetActiveUniformBlockName>();
+ if (c) {
+ c->Init(program, index, name_bucket_id, result_shm_id, result_shm_offset);
+ }
+}
+
void GetAttachedShaders(GLuint program,
uint32_t result_shm_id,
uint32_t result_shm_offset,
@@ -921,6 +933,17 @@
}
}
+void GetUniformBlockIndex(GLuint program,
+ uint32_t name_bucket_id,
+ uint32_t index_shm_id,
+ uint32_t index_shm_offset) {
+ gles2::cmds::GetUniformBlockIndex* c =
+ GetCmdSpace<gles2::cmds::GetUniformBlockIndex>();
+ if (c) {
+ c->Init(program, name_bucket_id, index_shm_id, index_shm_offset);
+ }
+}
+
void GetUniformfv(GLuint program,
GLint location,
uint32_t params_shm_id,
@@ -2145,6 +2168,14 @@
}
}
+void GetUniformBlocksCHROMIUM(GLuint program, uint32_t bucket_id) {
+ gles2::cmds::GetUniformBlocksCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::GetUniformBlocksCHROMIUM>();
+ if (c) {
+ c->Init(program, bucket_id);
+ }
+}
+
void GetTranslatedShaderSourceANGLE(GLuint shader, uint32_t bucket_id) {
gles2::cmds::GetTranslatedShaderSourceANGLE* c =
GetCmdSpace<gles2::cmds::GetTranslatedShaderSourceANGLE>();
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 7ef5444..30f9269 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -702,6 +702,15 @@
return true;
}
return false;
+ case GL_MAX_UNIFORM_BUFFER_BINDINGS:
+ *params = capabilities_.max_uniform_buffer_bindings;
+ return true;
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+ *params = capabilities_.max_transform_feedback_separate_attribs;
+ return true;
+ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+ *params = capabilities_.uniform_buffer_offset_alignment;
+ return true;
default:
return false;
}
@@ -834,6 +843,13 @@
// TODO(piman): Add the FreeEverything() logic here.
}
+void GLES2Implementation::OrderingBarrierCHROMIUM() {
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
+ // Flush command buffer at the GPU channel level. May be implemented as
+ // Flush().
+ helper_->CommandBufferHelper::OrderingBarrier();
+}
+
void GLES2Implementation::Finish() {
GPU_CLIENT_SINGLE_THREAD_CHECK();
FinishHelper();
@@ -1091,6 +1107,35 @@
return loc;
}
+GLuint GLES2Implementation::GetUniformBlockIndexHelper(
+ GLuint program, const char* name) {
+ typedef cmds::GetUniformBlockIndex::Result Result;
+ Result* result = GetResultAs<Result*>();
+ if (!result) {
+ return GL_INVALID_INDEX;
+ }
+ *result = GL_INVALID_INDEX;
+ SetBucketAsCString(kResultBucketId, name);
+ helper_->GetUniformBlockIndex(
+ program, kResultBucketId, GetResultShmId(), GetResultShmOffset());
+ WaitForCmd();
+ helper_->SetBucketSize(kResultBucketId, 0);
+ return *result;
+}
+
+GLuint GLES2Implementation::GetUniformBlockIndex(
+ GLuint program, const char* name) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
+ << program << ", " << name << ")");
+ TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
+ GLuint index = share_group_->program_info_manager()->GetUniformBlockIndex(
+ this, program, name);
+ GPU_CLIENT_LOG("returned " << index);
+ CheckGLError();
+ return index;
+}
+
void GLES2Implementation::LinkProgram(GLuint program) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program << ")");
@@ -2272,6 +2317,69 @@
CheckGLError();
}
+bool GLES2Implementation::GetActiveUniformBlockNameHelper(
+ GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, char* name) {
+ DCHECK_LE(0, bufsize);
+ // Clear the bucket so if the command fails nothing will be in it.
+ helper_->SetBucketSize(kResultBucketId, 0);
+ typedef cmds::GetActiveUniformBlockName::Result Result;
+ Result* result = GetResultAs<Result*>();
+ if (!result) {
+ return false;
+ }
+ // Set as failed so if the command fails we'll recover.
+ *result = 0;
+ helper_->GetActiveUniformBlockName(program, index, kResultBucketId,
+ GetResultShmId(), GetResultShmOffset());
+ WaitForCmd();
+ if (*result) {
+ if (bufsize == 0) {
+ if (length) {
+ *length = 0;
+ }
+ } else if (length || name) {
+ std::vector<int8> str;
+ GetBucketContents(kResultBucketId, &str);
+ DCHECK(str.size() > 0);
+ GLsizei max_size =
+ std::min(bufsize, static_cast<GLsizei>(str.size())) - 1;
+ if (length) {
+ *length = max_size;
+ }
+ if (name) {
+ memcpy(name, &str[0], max_size);
+ name[max_size] = '\0';
+ }
+ }
+ }
+ return *result != 0;
+}
+
+void GLES2Implementation::GetActiveUniformBlockName(
+ GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, char* name) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
+ << program << ", " << index << ", " << bufsize << ", "
+ << static_cast<const void*>(length) << ", "
+ << static_cast<const void*>(name) << ", ");
+ if (bufsize < 0) {
+ SetGLError(GL_INVALID_VALUE, "glGetActiveUniformBlockName", "bufsize < 0");
+ return;
+ }
+ TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
+ bool success =
+ share_group_->program_info_manager()->GetActiveUniformBlockName(
+ this, program, index, bufsize, length, name);
+ if (success) {
+ if (name) {
+ GPU_CLIENT_LOG(" name: " << name);
+ }
+ }
+ CheckGLError();
+}
+
void GLES2Implementation::GetAttachedShaders(
GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
@@ -2638,6 +2746,10 @@
// the old model but possibly not true in the new model if another context has
// deleted the resource.
+// NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
+// used even when Bind has failed. However, the bug is minor compared to the
+// overhead & duplicated checking in client side.
+
void GLES2Implementation::BindBufferHelper(
GLenum target, GLuint buffer_id) {
// TODO(gman): See note #1 above.
@@ -2662,8 +2774,7 @@
changed = true;
break;
}
- // TODO(gman): There's a bug here. If the target is invalid the ID will not be
- // used even though it's marked it as used here.
+ // TODO(gman): See note #2 above.
if (changed) {
GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(
this, target, buffer_id, &GLES2Implementation::BindBufferStub);
@@ -2679,8 +2790,7 @@
void GLES2Implementation::BindBufferBaseHelper(
GLenum target, GLuint index, GLuint buffer_id) {
// TODO(zmo): See note #1 above.
- // TODO(zmo): There's a bug here. If the target or index is invalid the ID
- // will not be used even though it's marked it as used here.
+ // TODO(zmo): See note #2 above.
GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(
this, target, index, buffer_id, &GLES2Implementation::BindBufferBaseStub);
}
@@ -2696,8 +2806,7 @@
GLenum target, GLuint index, GLuint buffer_id,
GLintptr offset, GLsizeiptr size) {
// TODO(zmo): See note #1 above.
- // TODO(zmo): There's a bug here. If an arguments is invalid the ID will not
- // be used even though it's marked it as used here.
+ // TODO(zmo): See note #2 above.
GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(
this, target, index, buffer_id, offset, size,
&GLES2Implementation::BindBufferRangeStub);
@@ -2777,8 +2886,7 @@
changed = true;
break;
}
- // TODO(gman): There's a bug here. If the target is invalid the ID will not be
- // used even though it's marked it as used here.
+ // TODO(zmo): See note #2 above.
if (changed) {
GetIdHandler(id_namespaces::kRenderbuffers)->MarkAsUsedForBind(
this, target, renderbuffer,
@@ -2827,8 +2935,7 @@
changed = true;
break;
}
- // TODO(gman): There's a bug here. If the target is invalid the ID will not be
- // used. even though it's marked it as used here.
+ // TODO(gman): See note #2 above.
if (changed) {
GetIdHandler(id_namespaces::kTextures)->MarkAsUsedForBind(
this, target, texture, &GLES2Implementation::BindTextureStub);
@@ -2847,7 +2954,6 @@
}
void GLES2Implementation::BindVertexArrayOESHelper(GLuint array) {
- // TODO(gman): See note #1 above.
bool changed = false;
if (vertex_array_object_manager_->BindVertexArray(array, &changed)) {
if (changed) {
@@ -2878,8 +2984,7 @@
changed = true;
break;
}
- // TODO(gman): There's a bug here. If the target is invalid the ID will not be
- // used even though it's marked it as used here.
+ // TODO(gman): See note #2 above.
if (changed) {
GetIdHandler(id_namespaces::kValuebuffers)->MarkAsUsedForBind(
this, target, valuebuffer,
@@ -3509,6 +3614,47 @@
memcpy(info, &result[0], result.size());
}
+void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
+ GLuint program, std::vector<int8>* result) {
+ DCHECK(result);
+ // Clear the bucket so if the command fails nothing will be in it.
+ helper_->SetBucketSize(kResultBucketId, 0);
+ helper_->GetUniformBlocksCHROMIUM(program, kResultBucketId);
+ GetBucketContents(kResultBucketId, result);
+}
+
+void GLES2Implementation::GetUniformBlocksCHROMIUM(
+ GLuint program, GLsizei bufsize, GLsizei* size, void* info) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ if (bufsize < 0) {
+ SetGLError(
+ GL_INVALID_VALUE, "glUniformBlocksCHROMIUM", "bufsize less than 0.");
+ return;
+ }
+ if (size == NULL) {
+ SetGLError(GL_INVALID_VALUE, "glUniformBlocksCHROMIUM", "size is null.");
+ return;
+ }
+ // Make sure they've set size to 0 else the value will be undefined on
+ // lost context.
+ DCHECK_EQ(0, *size);
+ std::vector<int8> result;
+ GetUniformBlocksCHROMIUMHelper(program, &result);
+ if (result.empty()) {
+ return;
+ }
+ *size = result.size();
+ if (!info) {
+ return;
+ }
+ if (static_cast<size_t>(bufsize) < result.size()) {
+ SetGLError(GL_INVALID_OPERATION,
+ "glUniformBlocksCHROMIUM", "bufsize is too small for result.");
+ return;
+ }
+ memcpy(info, &result[0], result.size());
+}
+
GLuint GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 470200e..193fbb8 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -220,6 +220,12 @@
bool GetActiveUniformHelper(
GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
GLint* size, GLenum* type, char* name);
+ void GetUniformBlocksCHROMIUMHelper(
+ GLuint program, std::vector<int8>* result);
+ GLuint GetUniformBlockIndexHelper(GLuint program, const char* name);
+ bool GetActiveUniformBlockNameHelper(
+ GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, char* name);
void FreeUnusedSharedMemory();
void FreeEverything();
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 3a6e5f3..3d6009a 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -255,6 +255,12 @@
GLenum* type,
char* name) override;
+void GetActiveUniformBlockName(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* name) override;
+
void GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -327,6 +333,8 @@
void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
+GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
+
void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
void GetUniformiv(GLuint program, GLint location, GLint* params) override;
@@ -431,6 +439,8 @@
void ShallowFlushCHROMIUM() override;
+void OrderingBarrierCHROMIUM() override;
+
void StencilFunc(GLenum func, GLint ref, GLuint mask) override;
void StencilFuncSeparate(GLenum face,
@@ -779,6 +789,11 @@
GLsizei* size,
void* info) override;
+void GetUniformBlocksCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
+
GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
GLuint CreateImageCHROMIUM(ClientBuffer buffer,
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index c88ba64..52a2cef 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -378,6 +378,8 @@
static const GLint kMaxVertexUniformVectors = 128;
static const GLint kNumCompressedTextureFormats = 0;
static const GLint kNumShaderBinaryFormats = 0;
+ static const GLuint kMaxTransformFeedbackSeparateAttribs = 4;
+ static const GLuint kMaxUniformBufferBindings = 36;
static const GLuint kStartId = 1024;
static const GLuint kBuffersStartId =
GLES2Implementation::kClientSideArrayId + 2 * kNumTestContexts;
@@ -439,6 +441,9 @@
capabilities.num_compressed_texture_formats =
kNumCompressedTextureFormats;
capabilities.num_shader_binary_formats = kNumShaderBinaryFormats;
+ capabilities.max_transform_feedback_separate_attribs =
+ kMaxTransformFeedbackSeparateAttribs;
+ capabilities.max_uniform_buffer_bindings = kMaxUniformBufferBindings;
capabilities.bind_generates_resource_chromium =
bind_generates_resource_service ? 1 : 0;
EXPECT_CALL(*gpu_control_, GetCapabilities())
@@ -2019,6 +2024,108 @@
EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
}
+TEST_F(GLES2ImplementationTest, GetUniformBlocksCHROMIUMGoodArgs) {
+ const uint32 kBucketId = GLES2Implementation::kResultBucketId;
+ const GLuint kProgramId = 123;
+ const char kBad = 0x12;
+ GLsizei size = 0;
+ const Str7 kString = {"foobar"};
+ char buf[20];
+
+ ExpectedMemoryInfo mem1 =
+ GetExpectedMemory(MaxTransferBufferSize());
+ ExpectedMemoryInfo result1 =
+ GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
+ ExpectedMemoryInfo result2 =
+ GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+
+ memset(buf, kBad, sizeof(buf));
+ EXPECT_CALL(*command_buffer(), OnFlush())
+ .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
+ SetMemory(mem1.ptr, kString)))
+ .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+
+ struct Cmds {
+ cmd::SetBucketSize set_bucket_size1;
+ cmds::GetUniformBlocksCHROMIUM get_uniform_blocks;
+ cmd::GetBucketStart get_bucket_start;
+ cmd::SetToken set_token1;
+ cmd::SetBucketSize set_bucket_size2;
+ };
+ Cmds expected;
+ expected.set_bucket_size1.Init(kBucketId, 0);
+ expected.get_uniform_blocks.Init(kProgramId, kBucketId);
+ expected.get_bucket_start.Init(
+ kBucketId, result1.id, result1.offset,
+ MaxTransferBufferSize(), mem1.id, mem1.offset);
+ expected.set_token1.Init(GetNextToken());
+ expected.set_bucket_size2.Init(kBucketId, 0);
+ gl_->GetUniformBlocksCHROMIUM(kProgramId, sizeof(buf), &size, &buf);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
+ EXPECT_EQ(sizeof(kString), static_cast<size_t>(size));
+ EXPECT_STREQ(kString.str, buf);
+ EXPECT_EQ(buf[sizeof(kString)], kBad);
+}
+
+TEST_F(GLES2ImplementationTest, GetUniformBlocksCHROMIUMBadArgs) {
+ const uint32 kBucketId = GLES2Implementation::kResultBucketId;
+ const GLuint kProgramId = 123;
+ GLsizei size = 0;
+ const Str7 kString = {"foobar"};
+ char buf[20];
+
+ ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
+ ExpectedMemoryInfo result1 =
+ GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
+ ExpectedMemoryInfo result2 =
+ GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+ ExpectedMemoryInfo result3 =
+ GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+ ExpectedMemoryInfo result4 =
+ GetExpectedResultMemory(sizeof(cmds::GetError::Result));
+
+ EXPECT_CALL(*command_buffer(), OnFlush())
+ .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
+ SetMemory(mem1.ptr, kString)))
+ .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
+ .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
+ .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
+ .RetiresOnSaturation();
+
+ // try bufsize not big enough.
+ struct Cmds {
+ cmd::SetBucketSize set_bucket_size1;
+ cmds::GetUniformBlocksCHROMIUM get_uniform_blocks;
+ cmd::GetBucketStart get_bucket_start;
+ cmd::SetToken set_token1;
+ cmd::SetBucketSize set_bucket_size2;
+ };
+ Cmds expected;
+ expected.set_bucket_size1.Init(kBucketId, 0);
+ expected.get_uniform_blocks.Init(kProgramId, kBucketId);
+ expected.get_bucket_start.Init(
+ kBucketId, result1.id, result1.offset,
+ MaxTransferBufferSize(), mem1.id, mem1.offset);
+ expected.set_token1.Init(GetNextToken());
+ expected.set_bucket_size2.Init(kBucketId, 0);
+ gl_->GetUniformBlocksCHROMIUM(kProgramId, 6, &size, &buf);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
+ ClearCommands();
+
+ // try bad bufsize
+ gl_->GetUniformBlocksCHROMIUM(kProgramId, -1, &size, &buf);
+ EXPECT_TRUE(NoCommandsWritten());
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
+ ClearCommands();
+ // try no size ptr.
+ gl_->GetUniformBlocksCHROMIUM(kProgramId, sizeof(buf), NULL, &buf);
+ EXPECT_TRUE(NoCommandsWritten());
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
+}
+
// Test that things are cached
TEST_F(GLES2ImplementationTest, GetIntegerCacheRead) {
struct PNameValue {
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 743458b..6dbcdcc 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -55,9 +55,9 @@
cmds::BindBufferRange cmd;
};
Cmds expected;
- expected.cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, 3, 4, 5);
+ expected.cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, 3, 4, 4);
- gl_->BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2, 3, 4, 5);
+ gl_->BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2, 3, 4, 4);
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
@@ -751,6 +751,7 @@
}
// TODO(zmo): Implement unit test for GetActiveAttrib
// TODO(zmo): Implement unit test for GetActiveUniform
+// TODO(zmo): Implement unit test for GetActiveUniformBlockName
// TODO(zmo): Implement unit test for GetAttachedShaders
// TODO(zmo): Implement unit test for GetAttribLocation
@@ -983,6 +984,7 @@
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
EXPECT_EQ(static_cast<Result::Type>(1), result);
}
+// TODO(zmo): Implement unit test for GetUniformBlockIndex
// TODO(zmo): Implement unit test for GetUniformfv
// TODO(zmo): Implement unit test for GetUniformiv
// TODO(zmo): Implement unit test for GetUniformLocation
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index c3a2c3e..352ff78 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -186,6 +186,11 @@
GLint* size,
GLenum* type,
char* name) = 0;
+virtual void GetActiveUniformBlockName(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* name) = 0;
virtual void GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -240,6 +245,7 @@
GLenum pname,
GLfloat* params) = 0;
virtual void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) = 0;
+virtual GLuint GetUniformBlockIndex(GLuint program, const char* name) = 0;
virtual void GetUniformfv(GLuint program, GLint location, GLfloat* params) = 0;
virtual void GetUniformiv(GLuint program, GLint location, GLint* params) = 0;
virtual GLint GetUniformLocation(GLuint program, const char* name) = 0;
@@ -309,6 +315,7 @@
const GLint* length) = 0;
virtual void ShallowFinishCHROMIUM() = 0;
virtual void ShallowFlushCHROMIUM() = 0;
+virtual void OrderingBarrierCHROMIUM() = 0;
virtual void StencilFunc(GLenum func, GLint ref, GLuint mask) = 0;
virtual void StencilFuncSeparate(GLenum face,
GLenum func,
@@ -564,6 +571,10 @@
GLsizei bufsize,
GLsizei* size,
void* info) = 0;
+virtual void GetUniformBlocksCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) = 0;
virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) = 0;
virtual GLuint CreateImageCHROMIUM(ClientBuffer buffer,
GLsizei width,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 34a0c42..0ca5199 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -185,6 +185,11 @@
GLint* size,
GLenum* type,
char* name) override;
+void GetActiveUniformBlockName(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* name) override;
void GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -235,6 +240,7 @@
const GLubyte* GetString(GLenum name) override;
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) override;
void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
+GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
void GetUniformiv(GLuint program, GLint location, GLint* params) override;
GLint GetUniformLocation(GLuint program, const char* name) override;
@@ -304,6 +310,7 @@
const GLint* length) override;
void ShallowFinishCHROMIUM() override;
void ShallowFlushCHROMIUM() override;
+void OrderingBarrierCHROMIUM() override;
void StencilFunc(GLenum func, GLint ref, GLuint mask) override;
void StencilFuncSeparate(GLenum face,
GLenum func,
@@ -551,6 +558,10 @@
GLsizei bufsize,
GLsizei* size,
void* info) override;
+void GetUniformBlocksCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
GLuint CreateImageCHROMIUM(ClientBuffer buffer,
GLsizei width,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index cf121fc..2a6f88e 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -286,6 +286,12 @@
GLenum* /* type */,
char* /* name */) {
}
+void GLES2InterfaceStub::GetActiveUniformBlockName(GLuint /* program */,
+ GLuint /* index */,
+ GLsizei /* bufsize */,
+ GLsizei* /* length */,
+ char* /* name */) {
+}
void GLES2InterfaceStub::GetAttachedShaders(GLuint /* program */,
GLsizei /* maxcount */,
GLsizei* /* count */,
@@ -376,6 +382,10 @@
GLenum /* pname */,
GLint* /* params */) {
}
+GLuint GLES2InterfaceStub::GetUniformBlockIndex(GLuint /* program */,
+ const char* /* name */) {
+ return 0;
+}
void GLES2InterfaceStub::GetUniformfv(GLuint /* program */,
GLint /* location */,
GLfloat* /* params */) {
@@ -516,6 +526,8 @@
}
void GLES2InterfaceStub::ShallowFlushCHROMIUM() {
}
+void GLES2InterfaceStub::OrderingBarrierCHROMIUM() {
+}
void GLES2InterfaceStub::StencilFunc(GLenum /* func */,
GLint /* ref */,
GLuint /* mask */) {
@@ -961,6 +973,11 @@
GLsizei* /* size */,
void* /* info */) {
}
+void GLES2InterfaceStub::GetUniformBlocksCHROMIUM(GLuint /* program */,
+ GLsizei /* bufsize */,
+ GLsizei* /* size */,
+ void* /* info */) {
+}
GLuint GLES2InterfaceStub::CreateStreamTextureCHROMIUM(GLuint /* texture */) {
return 0;
}
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index db9b375..da97a87 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -185,6 +185,11 @@
GLint* size,
GLenum* type,
char* name) override;
+void GetActiveUniformBlockName(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* name) override;
void GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -235,6 +240,7 @@
const GLubyte* GetString(GLenum name) override;
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) override;
void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
+GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
void GetUniformiv(GLuint program, GLint location, GLint* params) override;
GLint GetUniformLocation(GLuint program, const char* name) override;
@@ -304,6 +310,7 @@
const GLint* length) override;
void ShallowFinishCHROMIUM() override;
void ShallowFlushCHROMIUM() override;
+void OrderingBarrierCHROMIUM() override;
void StencilFunc(GLenum func, GLint ref, GLuint mask) override;
void StencilFuncSeparate(GLenum face,
GLenum func,
@@ -551,6 +558,10 @@
GLsizei bufsize,
GLsizei* size,
void* info) override;
+void GetUniformBlocksCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
GLuint CreateImageCHROMIUM(ClientBuffer buffer,
GLsizei width,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index 33bc3ae..df03be5 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -500,6 +500,15 @@
gl_->GetActiveUniform(program, index, bufsize, length, size, type, name);
}
+void GLES2TraceImplementation::GetActiveUniformBlockName(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* name) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetActiveUniformBlockName");
+ gl_->GetActiveUniformBlockName(program, index, bufsize, length, name);
+}
+
void GLES2TraceImplementation::GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -653,6 +662,12 @@
gl_->GetTexParameteriv(target, pname, params);
}
+GLuint GLES2TraceImplementation::GetUniformBlockIndex(GLuint program,
+ const char* name) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetUniformBlockIndex");
+ return gl_->GetUniformBlockIndex(program, name);
+}
+
void GLES2TraceImplementation::GetUniformfv(GLuint program,
GLint location,
GLfloat* params) {
@@ -899,6 +914,11 @@
gl_->ShallowFlushCHROMIUM();
}
+void GLES2TraceImplementation::OrderingBarrierCHROMIUM() {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::OrderingBarrierCHROMIUM");
+ gl_->OrderingBarrierCHROMIUM();
+}
+
void GLES2TraceImplementation::StencilFunc(GLenum func,
GLint ref,
GLuint mask) {
@@ -1647,6 +1667,14 @@
gl_->GetProgramInfoCHROMIUM(program, bufsize, size, info);
}
+void GLES2TraceImplementation::GetUniformBlocksCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetUniformBlocksCHROMIUM");
+ gl_->GetUniformBlocksCHROMIUM(program, bufsize, size, info);
+}
+
GLuint GLES2TraceImplementation::CreateStreamTextureCHROMIUM(GLuint texture) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu",
"GLES2Trace::CreateStreamTextureCHROMIUM");
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
index 7196372..04121aa 100644
--- a/gpu/command_buffer/client/program_info_manager.cc
+++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -44,11 +44,23 @@
ProgramInfoManager::Program::UniformInfo::~UniformInfo() {
}
+ProgramInfoManager::Program::UniformBlock::UniformBlock()
+ : binding(0),
+ data_size(0),
+ referenced_by_vertex_shader(false),
+ referenced_by_fragment_shader(false) {
+}
+
+ProgramInfoManager::Program::UniformBlock::~UniformBlock() {
+}
+
ProgramInfoManager::Program::Program()
- : cached_(false),
+ : cached_es2_(false),
max_attrib_name_length_(0),
max_uniform_name_length_(0),
- link_status_(false) {
+ link_status_(false),
+ cached_es3_uniform_blocks_(false),
+ active_uniform_block_max_name_length_(0) {
}
ProgramInfoManager::Program::~Program() {
@@ -78,6 +90,11 @@
&uniform_infos_[index] : NULL;
}
+const ProgramInfoManager::Program::UniformBlock*
+ProgramInfoManager::Program::GetUniformBlock(GLuint index) const {
+ return (index < uniform_blocks_.size()) ? &uniform_blocks_[index] : NULL;
+}
+
GLint ProgramInfoManager::Program::GetUniformLocation(
const std::string& name) const {
bool getting_array_location = false;
@@ -125,31 +142,45 @@
GLenum pname, GLint* params) {
switch (pname) {
case GL_LINK_STATUS:
- *params = link_status_;
+ *params = static_cast<GLint>(link_status_);
return true;
case GL_ACTIVE_ATTRIBUTES:
- *params = attrib_infos_.size();
+ *params = static_cast<GLint>(attrib_infos_.size());
return true;
case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
- *params = max_attrib_name_length_;
+ *params = static_cast<GLint>(max_attrib_name_length_);
return true;
case GL_ACTIVE_UNIFORMS:
- *params = uniform_infos_.size();
+ *params = static_cast<GLint>(uniform_infos_.size());
return true;
case GL_ACTIVE_UNIFORM_MAX_LENGTH:
- *params = max_uniform_name_length_;
+ *params = static_cast<GLint>(max_uniform_name_length_);
+ return true;
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ *params = static_cast<GLint>(uniform_blocks_.size());
+ return true;
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ *params = static_cast<GLint>(active_uniform_block_max_name_length_);
return true;
default:
+ NOTREACHED();
break;
}
return false;
}
-void ProgramInfoManager::Program::Update(
- GLES2Implementation* gl,
- GLuint program,
- const std::vector<int8>& result) {
- if (cached_) {
+GLuint ProgramInfoManager::Program::GetUniformBlockIndex(
+ const std::string& name) const {
+ for (size_t ii = 0; ii < uniform_blocks_.size(); ++ii) {
+ if (uniform_blocks_[ii].name == name) {
+ return static_cast<GLuint>(ii);
+ }
+ }
+ return GL_INVALID_INDEX;
+}
+
+void ProgramInfoManager::Program::UpdateES2(const std::vector<int8>& result) {
+ if (cached_es2_) {
return;
}
if (result.empty()) {
@@ -200,12 +231,93 @@
++input;
}
DCHECK_EQ(header->num_attribs + header->num_uniforms,
- static_cast<uint32>(input - inputs));
- cached_ = true;
+ static_cast<uint32>(input - inputs));
+ cached_es2_ = true;
}
-bool ProgramInfoManager::Program::cached() const {
- return cached_;
+void ProgramInfoManager::Program::UpdateES3UniformBlocks(
+ const std::vector<int8>& result) {
+ if (cached_es3_uniform_blocks_) {
+ return;
+ }
+ if (result.empty()) {
+ // This should only happen on a lost context.
+ return;
+ }
+ uniform_blocks_.clear();
+ active_uniform_block_max_name_length_ = 0;
+
+ // |result| comes from GPU process. We consider it trusted data. Therefore,
+ // no need to check for overflows as the GPU side did the checks already.
+ uint32_t header_size = sizeof(UniformBlocksHeader);
+ DCHECK_GE(result.size(), header_size);
+ const UniformBlocksHeader* header = LocalGetAs<const UniformBlocksHeader*>(
+ result, 0, header_size);
+ DCHECK(header);
+ if (header->num_uniform_blocks == 0) {
+ DCHECK_EQ(result.size(), header_size);
+ // TODO(zmo): Here we can't tell if no uniform blocks are defined, or
+ // the previous link failed.
+ return;
+ }
+ uniform_blocks_.resize(header->num_uniform_blocks);
+
+ uint32_t entry_size = sizeof(UniformBlockInfo) * header->num_uniform_blocks;
+ DCHECK_GE(result.size(), header_size + entry_size);
+ uint32_t data_size = result.size() - header_size - entry_size;
+ DCHECK_LT(0u, data_size);
+ const UniformBlockInfo* entries = LocalGetAs<const UniformBlockInfo*>(
+ result, header_size, entry_size);
+ DCHECK(entries);
+ const char* data = LocalGetAs<const char*>(
+ result, header_size + entry_size, data_size);
+ DCHECK(data);
+
+ uint32_t size = 0;
+ for (uint32_t ii = 0; ii < header->num_uniform_blocks; ++ii) {
+ uniform_blocks_[ii].binding = static_cast<GLuint>(entries[ii].binding);
+ uniform_blocks_[ii].data_size = static_cast<GLuint>(entries[ii].data_size);
+ uniform_blocks_[ii].active_uniform_indices.resize(
+ entries[ii].active_uniforms);
+ uniform_blocks_[ii].referenced_by_vertex_shader = static_cast<GLboolean>(
+ entries[ii].referenced_by_vertex_shader);
+ uniform_blocks_[ii].referenced_by_fragment_shader = static_cast<GLboolean>(
+ entries[ii].referenced_by_fragment_shader);
+ // Uniform block names can't be empty strings.
+ DCHECK_LT(1u, entries[ii].name_length);
+ if (entries[ii].name_length > active_uniform_block_max_name_length_) {
+ active_uniform_block_max_name_length_ = entries[ii].name_length;
+ }
+ size += entries[ii].name_length;
+ DCHECK_GE(data_size, size);
+ uniform_blocks_[ii].name = std::string(data, entries[ii].name_length - 1);
+ data += entries[ii].name_length;
+ size += entries[ii].active_uniforms * sizeof(uint32_t);
+ DCHECK_GE(data_size, size);
+ const uint32_t* indices = reinterpret_cast<const uint32_t*>(data);
+ for (uint32_t uu = 0; uu < entries[ii].active_uniforms; ++uu) {
+ uniform_blocks_[ii].active_uniform_indices[uu] =
+ static_cast<GLuint>(indices[uu]);
+ }
+ indices += entries[ii].active_uniforms;
+ data = reinterpret_cast<const char*>(indices);
+ }
+ DCHECK_EQ(data_size, size);
+ cached_es3_uniform_blocks_ = true;
+}
+
+bool ProgramInfoManager::Program::IsCached(ProgramInfoType type) const {
+ switch (type) {
+ case kES2:
+ return cached_es2_;
+ case kES3UniformBlocks:
+ return cached_es3_uniform_blocks_;
+ case kNone:
+ return true;
+ default:
+ NOTREACHED();
+ return true;
+ }
}
@@ -216,29 +328,42 @@
}
ProgramInfoManager::Program* ProgramInfoManager::GetProgramInfo(
- GLES2Implementation* gl, GLuint program) {
+ GLES2Implementation* gl, GLuint program, ProgramInfoType type) {
lock_.AssertAcquired();
ProgramInfoMap::iterator it = program_infos_.find(program);
if (it == program_infos_.end()) {
return NULL;
}
Program* info = &it->second;
- if (info->cached())
+ if (info->IsCached(type))
return info;
- std::vector<int8> result;
- {
- base::AutoUnlock unlock(lock_);
- // lock_ can't be held across IPC call or else it may deadlock in pepper.
- // http://crbug.com/418651
- gl->GetProgramInfoCHROMIUMHelper(program, &result);
- }
- it = program_infos_.find(program);
- if (it == program_infos_.end()) {
- return NULL;
+ std::vector<int8> result;
+ switch (type) {
+ case kES2:
+ {
+ base::AutoUnlock unlock(lock_);
+ // lock_ can't be held across IPC call or else it may deadlock in
+ // pepper. http://crbug.com/418651
+ gl->GetProgramInfoCHROMIUMHelper(program, &result);
+ }
+ info->UpdateES2(result);
+ break;
+ case kES3UniformBlocks:
+ {
+ base::AutoUnlock unlock(lock_);
+ // lock_ can't be held across IPC call or else it may deadlock in
+ // pepper. http://crbug.com/418651
+
+ // TODO(zmo): Uncomment the below line once GetUniformBlocksCHROMIUM
+ // command is implemented.
+ // gl->GetUniformBlocksCHROMIUMHeler(program, &result);
+ }
+ info->UpdateES3UniformBlocks(result);
+ default:
+ NOTREACHED();
+ return NULL;
}
- info = &it->second;
- info->Update(gl, program, result);
return info;
}
@@ -259,7 +384,23 @@
bool ProgramInfoManager::GetProgramiv(
GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
base::AutoLock auto_lock(lock_);
- Program* info = GetProgramInfo(gl, program);
+ ProgramInfoType type = kNone;
+ switch (pname) {
+ case GL_ACTIVE_ATTRIBUTES:
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ case GL_ACTIVE_UNIFORMS:
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ case GL_LINK_STATUS:
+ type = kES2;
+ break;
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ type = kES3UniformBlocks;
+ break;
+ default:
+ return false;
+ }
+ Program* info = GetProgramInfo(gl, program, type);
if (!info) {
return false;
}
@@ -270,7 +411,7 @@
GLES2Implementation* gl, GLuint program, const char* name) {
{
base::AutoLock auto_lock(lock_);
- Program* info = GetProgramInfo(gl, program);
+ Program* info = GetProgramInfo(gl, program, kES2);
if (info) {
return info->GetAttribLocation(name);
}
@@ -282,7 +423,7 @@
GLES2Implementation* gl, GLuint program, const char* name) {
{
base::AutoLock auto_lock(lock_);
- Program* info = GetProgramInfo(gl, program);
+ Program* info = GetProgramInfo(gl, program, kES2);
if (info) {
return info->GetUniformLocation(name);
}
@@ -296,7 +437,7 @@
// fetched altogether from the service side. See crbug.com/452104.
{
base::AutoLock auto_lock(lock_);
- Program* info = GetProgramInfo(gl, program);
+ Program* info = GetProgramInfo(gl, program, kNone);
if (info) {
GLint possible_loc = info->GetFragDataLocation(name);
if (possible_loc != -1)
@@ -306,7 +447,7 @@
GLint loc = gl->GetFragDataLocationHelper(program, name);
if (loc != -1) {
base::AutoLock auto_lock(lock_);
- Program* info = GetProgramInfo(gl, program);
+ Program* info = GetProgramInfo(gl, program, kNone);
if (info) {
info->CacheFragDataLocation(name, loc);
}
@@ -320,7 +461,7 @@
GLint* size, GLenum* type, char* name) {
{
base::AutoLock auto_lock(lock_);
- Program* info = GetProgramInfo(gl, program);
+ Program* info = GetProgramInfo(gl, program, kES2);
if (info) {
const Program::VertexAttrib* attrib_info = info->GetAttribInfo(index);
if (attrib_info) {
@@ -356,7 +497,7 @@
GLint* size, GLenum* type, char* name) {
{
base::AutoLock auto_lock(lock_);
- Program* info = GetProgramInfo(gl, program);
+ Program* info = GetProgramInfo(gl, program, kES2);
if (info) {
const Program::UniformInfo* uniform_info = info->GetUniformInfo(index);
if (uniform_info) {
@@ -386,6 +527,119 @@
program, index, bufsize, length, size, type, name);
}
+GLuint ProgramInfoManager::GetUniformBlockIndex(
+ GLES2Implementation* gl, GLuint program, const char* name) {
+ {
+ base::AutoLock auto_lock(lock_);
+ Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
+ if (info) {
+ return info->GetUniformBlockIndex(name);
+ }
+ }
+ return gl->GetUniformBlockIndexHelper(program, name);
+}
+
+bool ProgramInfoManager::GetActiveUniformBlockName(
+ GLES2Implementation* gl, GLuint program, GLuint index,
+ GLsizei buf_size, GLsizei* length, char* name) {
+ DCHECK_LE(0, buf_size);
+ if (!name) {
+ buf_size = 0;
+ }
+ {
+ base::AutoLock auto_lock(lock_);
+ Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
+ if (info) {
+ const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
+ if (uniform_block) {
+ if (buf_size == 0) {
+ if (length) {
+ *length = 0;
+ }
+ } else if (length || name) {
+ GLsizei max_size = std::min(
+ buf_size - 1, static_cast<GLsizei>(uniform_block->name.size()));
+ if (length) {
+ *length = max_size;
+ }
+ if (name) {
+ memcpy(name, uniform_block->name.data(), max_size);
+ name[max_size] = '\0';
+ }
+ }
+ return true;
+ }
+ }
+ }
+ return gl->GetActiveUniformBlockNameHelper(
+ program, index, buf_size, length, name);
+}
+
+bool ProgramInfoManager::GetActiveUniformBlockiv(
+ GLES2Implementation* gl, GLuint program, GLuint index,
+ GLenum pname, GLint* params) {
+ {
+ base::AutoLock auto_lock(lock_);
+ Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
+ if (info) {
+ const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
+ bool valid_pname;
+ switch (pname) {
+ case GL_UNIFORM_BLOCK_BINDING:
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ valid_pname = true;
+ break;
+ default:
+ valid_pname = false;
+ break;
+ }
+ if (uniform_block && valid_pname && params) {
+ switch (pname) {
+ case GL_UNIFORM_BLOCK_BINDING:
+ *params = static_cast<GLint>(uniform_block->binding);
+ break;
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ *params = static_cast<GLint>(uniform_block->data_size);
+ break;
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ *params = static_cast<GLint>(uniform_block->name.size()) + 1;
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ *params = static_cast<GLint>(
+ uniform_block->active_uniform_indices.size());
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ for (size_t ii = 0;
+ ii < uniform_block->active_uniform_indices.size(); ++ii) {
+ params[ii] = static_cast<GLint>(
+ uniform_block->active_uniform_indices[ii]);
+ }
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ *params = static_cast<GLint>(
+ uniform_block->referenced_by_vertex_shader);
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ *params = static_cast<GLint>(
+ uniform_block->referenced_by_fragment_shader);
+ break;
+ default:
+ NOTREACHED();
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ // TODO(zmo): return gl->GetActiveUniformBlockivHelper(
+ // program, index, pname, params);
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/client/program_info_manager.h b/gpu/command_buffer/client/program_info_manager.h
index 712b8ed..efbff73 100644
--- a/gpu/command_buffer/client/program_info_manager.h
+++ b/gpu/command_buffer/client/program_info_manager.h
@@ -5,12 +5,13 @@
#ifndef GPU_COMMAND_BUFFER_CLIENT_PROGRAM_INFO_MANAGER_H_
#define GPU_COMMAND_BUFFER_CLIENT_PROGRAM_INFO_MANAGER_H_
-#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
#include <string>
#include <vector>
#include "base/containers/hash_tables.h"
+#include "base/gtest_prod_util.h"
#include "base/synchronization/lock.h"
#include "gles2_impl_export.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
@@ -48,8 +49,30 @@
GLES2Implementation* gl, GLuint program, GLuint index, GLsizei bufsize,
GLsizei* length, GLint* size, GLenum* type, char* name);
+ GLuint GetUniformBlockIndex(
+ GLES2Implementation* gl, GLuint program, const char* name);
+
+ bool GetActiveUniformBlockName(
+ GLES2Implementation* gl, GLuint program, GLuint index,
+ GLsizei buf_size, GLsizei* length, char* name);
+
+ bool GetActiveUniformBlockiv(
+ GLES2Implementation* gl, GLuint program, GLuint index,
+ GLenum pname, GLint* params);
+
private:
- class Program {
+ friend class ProgramInfoManagerTest;
+
+ FRIEND_TEST_ALL_PREFIXES(ProgramInfoManagerTest, UpdateES3UniformBlocks);
+
+ enum ProgramInfoType {
+ kES2,
+ kES3UniformBlocks,
+ kNone,
+ };
+
+ // Need GLES2_IMPL_EXPORT for tests.
+ class GLES2_IMPL_EXPORT Program {
public:
struct UniformInfo {
UniformInfo(GLsizei _size, GLenum _type, const std::string& _name);
@@ -71,6 +94,17 @@
GLint location;
std::string name;
};
+ struct UniformBlock {
+ UniformBlock();
+ ~UniformBlock();
+
+ GLuint binding;
+ GLuint data_size;
+ std::vector<GLuint> active_uniform_indices;
+ GLboolean referenced_by_vertex_shader;
+ GLboolean referenced_by_fragment_shader;
+ std::string name;
+ };
Program();
~Program();
@@ -89,15 +123,20 @@
bool GetProgramiv(GLenum pname, GLint* params);
- // Updates the program info after a successful link.
- void Update(GLES2Implementation* gl,
- GLuint program,
- const std::vector<int8>& result);
+ // Gets the index of a uniform block by name.
+ GLuint GetUniformBlockIndex(const std::string& name) const;
+ const UniformBlock* GetUniformBlock(GLuint index) const;
- bool cached() const;
+ // Updates the ES2 only program info after a successful link.
+ void UpdateES2(const std::vector<int8>& result);
+
+ // Updates the ES3 UniformBlock info after a successful link.
+ void UpdateES3UniformBlocks(const std::vector<int8>& result);
+
+ bool IsCached(ProgramInfoType type) const;
private:
- bool cached_;
+ bool cached_es2_;
GLsizei max_attrib_name_length_;
@@ -109,13 +148,23 @@
// Uniform info by index.
std::vector<UniformInfo> uniform_infos_;
- base::hash_map<std::string, GLint> frag_data_locations_;
-
// This is true if glLinkProgram was successful last time it was called.
bool link_status_;
+
+ // BELOW ARE ES3 ONLY INFORMATION.
+
+ bool cached_es3_uniform_blocks_;
+
+ uint32_t active_uniform_block_max_name_length_;
+
+ // Uniform blocks by index.
+ std::vector<UniformBlock> uniform_blocks_;
+
+ base::hash_map<std::string, GLint> frag_data_locations_;
};
- Program* GetProgramInfo(GLES2Implementation* gl, GLuint program);
+ Program* GetProgramInfo(
+ GLES2Implementation* gl, GLuint program, ProgramInfoType type);
typedef base::hash_map<GLuint, Program> ProgramInfoMap;
diff --git a/gpu/command_buffer/client/program_info_manager_unittest.cc b/gpu/command_buffer/client/program_info_manager_unittest.cc
new file mode 100644
index 0000000..6b0576c
--- /dev/null
+++ b/gpu/command_buffer/client/program_info_manager_unittest.cc
@@ -0,0 +1,184 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/client/program_info_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+uint32 ComputeOffset(const void* start, const void* position) {
+ return static_cast<const uint8*>(position) -
+ static_cast<const uint8*>(start);
+}
+
+const GLuint kClientProgramId = 321;
+
+} // namespace anonymous
+
+namespace gpu {
+namespace gles2 {
+
+class ProgramInfoManagerTest : public testing::Test {
+ public:
+ ProgramInfoManagerTest() {}
+ ~ProgramInfoManagerTest() override {}
+
+ protected:
+ typedef ProgramInfoManager::Program Program;
+
+ struct UniformBlocksData {
+ UniformBlocksHeader header;
+ UniformBlockInfo entry[2];
+ char name0[4];
+ uint32_t indices0[2];
+ char name1[8];
+ uint32_t indices1[1];
+ };
+
+ void SetUp() override {
+ program_info_manager_.reset(new ProgramInfoManager);
+ program_info_manager_->CreateInfo(kClientProgramId);
+ {
+ base::AutoLock auto_lock(program_info_manager_->lock_);
+ program_ = program_info_manager_->GetProgramInfo(
+ NULL, kClientProgramId, ProgramInfoManager::kNone);
+ ASSERT_TRUE(program_ != NULL);
+ }
+ }
+
+ void TearDown() override {}
+
+ void SetupUniformBlocksData(UniformBlocksData* data) {
+ // The names needs to be of size 4*k-1 to avoid padding in the struct Data.
+ // This is a testing only problem.
+ const char* kName[] = { "cow", "chicken" };
+ const uint32_t kIndices0[] = { 1, 2 };
+ const uint32_t kIndices1[] = { 3 };
+ const uint32_t* kIndices[] = { kIndices0, kIndices1 };
+ data->header.num_uniform_blocks = 2;
+ data->entry[0].binding = 0;
+ data->entry[0].data_size = 8;
+ data->entry[0].name_offset = ComputeOffset(data, data->name0);
+ data->entry[0].name_length = arraysize(data->name0);
+ data->entry[0].active_uniforms = arraysize(data->indices0);
+ data->entry[0].active_uniform_offset = ComputeOffset(data, data->indices0);
+ data->entry[0].referenced_by_vertex_shader = static_cast<uint32_t>(true);
+ data->entry[0].referenced_by_fragment_shader = static_cast<uint32_t>(false);
+ data->entry[1].binding = 1;
+ data->entry[1].data_size = 4;
+ data->entry[1].name_offset = ComputeOffset(data, data->name1);
+ data->entry[1].name_length = arraysize(data->name1);
+ data->entry[1].active_uniforms = arraysize(data->indices1);
+ data->entry[1].active_uniform_offset = ComputeOffset(data, data->indices1);
+ data->entry[1].referenced_by_vertex_shader = static_cast<uint32_t>(false);
+ data->entry[1].referenced_by_fragment_shader = static_cast<uint32_t>(true);
+ memcpy(data->name0, kName[0], arraysize(data->name0));
+ data->indices0[0] = kIndices[0][0];
+ data->indices0[1] = kIndices[0][1];
+ memcpy(data->name1, kName[1], arraysize(data->name1));
+ data->indices1[0] = kIndices[1][0];
+ }
+
+ scoped_ptr<ProgramInfoManager> program_info_manager_;
+ Program* program_;
+};
+
+TEST_F(ProgramInfoManagerTest, UpdateES3UniformBlocks) {
+ UniformBlocksData data;
+ SetupUniformBlocksData(&data);
+ const std::string kName[] = { data.name0, data.name1 };
+ const uint32_t* kIndices[] = { data.indices0, data.indices1 };
+ std::vector<int8> result(sizeof(data));
+ memcpy(&result[0], &data, sizeof(data));
+ EXPECT_FALSE(program_->IsCached(ProgramInfoManager::kES3UniformBlocks));
+ program_->UpdateES3UniformBlocks(result);
+ EXPECT_TRUE(program_->IsCached(ProgramInfoManager::kES3UniformBlocks));
+
+ GLint uniform_block_count = 0;
+ EXPECT_TRUE(program_->GetProgramiv(
+ GL_ACTIVE_UNIFORM_BLOCKS, &uniform_block_count));
+ EXPECT_EQ(data.header.num_uniform_blocks,
+ static_cast<uint32_t>(uniform_block_count));
+ GLint max_name_length = 0;
+ EXPECT_TRUE(program_->GetProgramiv(
+ GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_name_length));
+ for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) {
+ EXPECT_EQ(ii, program_->GetUniformBlockIndex(kName[ii]));
+ const Program::UniformBlock* info = program_->GetUniformBlock(ii);
+ EXPECT_TRUE(info != NULL);
+ EXPECT_EQ(data.entry[ii].binding, info->binding);
+ EXPECT_EQ(data.entry[ii].data_size, info->data_size);
+ EXPECT_EQ(data.entry[ii].active_uniforms,
+ info->active_uniform_indices.size());
+ for (uint32_t uu = 0; uu < data.entry[ii].active_uniforms; ++uu) {
+ EXPECT_EQ(kIndices[ii][uu], info->active_uniform_indices[uu]);
+ }
+ EXPECT_EQ(data.entry[ii].referenced_by_vertex_shader,
+ static_cast<GLboolean>(info->referenced_by_vertex_shader));
+ EXPECT_EQ(data.entry[ii].referenced_by_fragment_shader,
+ static_cast<GLboolean>(info->referenced_by_fragment_shader));
+ EXPECT_EQ(kName[ii], info->name);
+ EXPECT_GE(max_name_length, static_cast<GLint>(info->name.size()) + 1);
+ }
+
+ EXPECT_EQ(GL_INVALID_INDEX, program_->GetUniformBlockIndex("BadName"));
+ EXPECT_EQ(NULL, program_->GetUniformBlock(data.header.num_uniform_blocks));
+}
+
+TEST_F(ProgramInfoManagerTest, GetUniformBlockIndexCached) {
+ UniformBlocksData data;
+ SetupUniformBlocksData(&data);
+ std::vector<int8> result(sizeof(data));
+ memcpy(&result[0], &data, sizeof(data));
+ program_->UpdateES3UniformBlocks(result);
+
+ EXPECT_EQ(0u, program_info_manager_->GetUniformBlockIndex(
+ NULL, kClientProgramId, data.name0));
+ EXPECT_EQ(1u, program_info_manager_->GetUniformBlockIndex(
+ NULL, kClientProgramId, data.name1));
+ EXPECT_EQ(GL_INVALID_INDEX, program_info_manager_->GetUniformBlockIndex(
+ NULL, kClientProgramId, "BadName"));
+}
+
+TEST_F(ProgramInfoManagerTest, GetActiveUniformBlockNameCached) {
+ UniformBlocksData data;
+ SetupUniformBlocksData(&data);
+ std::vector<int8> result(sizeof(data));
+ memcpy(&result[0], &data, sizeof(data));
+ program_->UpdateES3UniformBlocks(result);
+
+ GLsizei buf_size = std::max(strlen(data.name0), strlen(data.name1)) + 1;
+ std::vector<char> buffer(buf_size);
+ GLsizei length = 0;
+ EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+ NULL, kClientProgramId, 0, buf_size, &length, &buffer[0]));
+ EXPECT_EQ(static_cast<GLsizei>(strlen(data.name0)), length);
+ EXPECT_STREQ(data.name0, &buffer[0]);
+
+ EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+ NULL, kClientProgramId, 1, buf_size, &length, &buffer[0]));
+ EXPECT_EQ(static_cast<GLsizei>(strlen(data.name1)), length);
+ EXPECT_STREQ(data.name1, &buffer[0]);
+
+ // Test length == NULL.
+ EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+ NULL, kClientProgramId, 0, buf_size, NULL, &buffer[0]));
+ EXPECT_STREQ(data.name0, &buffer[0]);
+
+ // Test buffer == NULL.
+ EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+ NULL, kClientProgramId, 0, buf_size, &length, NULL));
+ EXPECT_EQ(0, length);
+
+ // Test buf_size smaller than string size.
+ buf_size = strlen(data.name0);
+ EXPECT_EQ(true, program_info_manager_->GetActiveUniformBlockName(
+ NULL, kClientProgramId, 0, buf_size, &length, &buffer[0]));
+ EXPECT_EQ(buf_size, length + 1);
+ EXPECT_STREQ(std::string(data.name0).substr(0, length).c_str(), &buffer[0]);
+}
+
+} // namespace gles2
+} // namespace gpu
+
diff --git a/gpu/command_buffer/client/query_tracker_unittest.cc b/gpu/command_buffer/client/query_tracker_unittest.cc
index 53f5195..f6f48ec 100644
--- a/gpu/command_buffer/client/query_tracker_unittest.cc
+++ b/gpu/command_buffer/client/query_tracker_unittest.cc
@@ -161,24 +161,23 @@
EXPECT_EQ(kToken, query->token());
EXPECT_EQ(1, query->submit_count());
- // Check CheckResultsAvailable.
- EXPECT_FALSE(query->CheckResultsAvailable(helper_.get()));
- EXPECT_FALSE(query->NeverUsed());
- EXPECT_TRUE(query->Pending());
-
// Flush only once if no more flushes happened between a call to
// EndQuery command and CheckResultsAvailable
// Advance put_ so flush calls in CheckResultsAvailable go through
// and updates flush_generation count
helper_->Noop(1);
- // Set Query in pending state_ to simulate EndQuery command is called
- query->MarkAsPending(kToken);
- EXPECT_TRUE(query->Pending());
+
// Store FlushGeneration count after EndQuery is called
uint32 gen1 = GetFlushGeneration();
+
+ // Check CheckResultsAvailable.
EXPECT_FALSE(query->CheckResultsAvailable(helper_.get()));
+ EXPECT_FALSE(query->NeverUsed());
+ EXPECT_TRUE(query->Pending());
+
uint32 gen2 = GetFlushGeneration();
EXPECT_NE(gen1, gen2);
+
// Repeated calls to CheckResultsAvailable should not flush unnecessarily
EXPECT_FALSE(query->CheckResultsAvailable(helper_.get()));
gen1 = GetFlushGeneration();
diff --git a/gpu/command_buffer/client/transfer_buffer_unittest.cc b/gpu/command_buffer/client/transfer_buffer_unittest.cc
index 7dac4f5..1a2a4b0 100644
--- a/gpu/command_buffer/client/transfer_buffer_unittest.cc
+++ b/gpu/command_buffer/client/transfer_buffer_unittest.cc
@@ -82,6 +82,7 @@
.Times(1)
.RetiresOnSaturation();
EXPECT_CALL(*command_buffer(), OnFlush()).Times(AtMost(1));
+ EXPECT_CALL(*command_buffer(), Flush(_)).Times(AtMost(1));
transfer_buffer_.reset();
}
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index dc4ce3a..c415e48 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -77,6 +77,7 @@
GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizeiNotNegative n, GLuint* ids);
GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, GLint* size, GLenum* type, char* name);
GL_APICALL void GL_APIENTRY glGetActiveUniform (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, char* name);
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLidProgram program, GLsizeiNotNegative maxcount, GLsizeiOptional* count, GLuint* shaders);
GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLidProgram program, const char* name);
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenumGLState pname, GLboolean* params);
@@ -99,6 +100,7 @@
GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenumStringType name);
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenumGetTexParamTarget target, GLenumTextureParameter pname, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenumGetTexParamTarget target, GLenumTextureParameter pname, GLint* params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLidProgram program, const char* name);
GL_APICALL void GL_APIENTRY glGetUniformfv (GLidProgram program, GLintUniformLocation location, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetUniformiv (GLidProgram program, GLintUniformLocation location, GLint* params);
GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLidProgram program, const char* name);
@@ -138,6 +140,7 @@
GL_APICALL void GL_APIENTRY glShaderSource (GLidShader shader, GLsizeiNotNegative count, const GLchar* const* str, const GLint* length);
GL_APICALL void GL_APIENTRY glShallowFinishCHROMIUM (void);
GL_APICALL void GL_APIENTRY glShallowFlushCHROMIUM (void);
+GL_APICALL void GL_APIENTRY glOrderingBarrierCHROMIUM (void);
GL_APICALL void GL_APIENTRY glStencilFunc (GLenumCmpFunction func, GLint ref, GLuint mask);
GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenumFaceType face, GLenumCmpFunction func, GLint ref, GLuint mask);
GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
@@ -242,6 +245,7 @@
GL_APICALL void GL_APIENTRY glRequestExtensionCHROMIUM (const char* extension);
GL_APICALL void GL_APIENTRY glRateLimitOffscreenContextCHROMIUM (void);
GL_APICALL void GL_APIENTRY glGetProgramInfoCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
+GL_APICALL void GL_APIENTRY glGetUniformBlocksCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
GL_APICALL GLuint GL_APIENTRY glCreateStreamTextureCHROMIUM (GLuint texture);
GL_APICALL GLuint GL_APIENTRY glCreateImageCHROMIUM (ClientBuffer buffer, GLsizei width, GLsizei height, GLenum internalformat);
GL_APICALL void GL_APIENTRY glDestroyImageCHROMIUM (GLuint image_id);
diff --git a/gpu/command_buffer/common/capabilities.cc b/gpu/command_buffer/common/capabilities.cc
index ab33aeb..97c26d8 100644
--- a/gpu/command_buffer/common/capabilities.cc
+++ b/gpu/command_buffer/common/capabilities.cc
@@ -23,6 +23,9 @@
num_compressed_texture_formats(0),
num_shader_binary_formats(0),
bind_generates_resource_chromium(0),
+ max_transform_feedback_separate_attribs(0),
+ max_uniform_buffer_bindings(0),
+ uniform_buffer_offset_alignment(1),
post_sub_buffer(false),
egl_image_external(false),
texture_format_bgra8888(false),
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h
index a465ca2..92c3c19 100644
--- a/gpu/command_buffer/common/capabilities.h
+++ b/gpu/command_buffer/common/capabilities.h
@@ -75,6 +75,9 @@
int num_compressed_texture_formats;
int num_shader_binary_formats;
int bind_generates_resource_chromium;
+ int max_transform_feedback_separate_attribs;
+ int max_uniform_buffer_bindings;
+ int uniform_buffer_offset_alignment;
bool post_sub_buffer;
bool egl_image_external;
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
index d846ec1..b699363 100644
--- a/gpu/command_buffer/common/command_buffer.h
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -90,6 +90,11 @@
// subsequent Flushes on the same GpuChannel.
virtual void Flush(int32 put_offset) = 0;
+ // As Flush, ensures that on the service side, commands up to put_offset
+ // are processed but before subsequent commands on the same GpuChannel but
+ // flushing to the service may be deferred.
+ virtual void OrderingBarrier(int32 put_offset) = 0;
+
// The writer calls this to wait until the current token is within a
// specific range, inclusive. Can return early if an error is generated.
virtual void WaitForTokenInRange(int32 start, int32 end) = 0;
diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h
index b7366f8..9e1f713 100644
--- a/gpu/command_buffer/common/command_buffer_mock.h
+++ b/gpu/command_buffer/common/command_buffer_mock.h
@@ -25,6 +25,7 @@
MOCK_METHOD0(GetLastState, State());
MOCK_METHOD0(GetLastToken, int32());
MOCK_METHOD1(Flush, void(int32 put_offset));
+ MOCK_METHOD1(OrderingBarrier, void(int32 put_offset));
MOCK_METHOD2(WaitForTokenInRange, void(int32 start, int32 end));
MOCK_METHOD2(WaitForGetOffsetInRange, void(int32 start, int32 end));
MOCK_METHOD1(SetGetBuffer, void(int32 transfer_buffer_id));
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 47c2b68..12b90c9 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -3374,6 +3374,69 @@
"offset of GetActiveUniform Result type should be "
"8");
+struct GetActiveUniformBlockName {
+ typedef GetActiveUniformBlockName ValueType;
+ static const CommandId kCmdId = kGetActiveUniformBlockName;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ typedef int32_t Result;
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _program,
+ GLuint _index,
+ uint32_t _name_bucket_id,
+ uint32_t _result_shm_id,
+ uint32_t _result_shm_offset) {
+ SetHeader();
+ program = _program;
+ index = _index;
+ name_bucket_id = _name_bucket_id;
+ result_shm_id = _result_shm_id;
+ result_shm_offset = _result_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _program,
+ GLuint _index,
+ uint32_t _name_bucket_id,
+ uint32_t _result_shm_id,
+ uint32_t _result_shm_offset) {
+ static_cast<ValueType*>(cmd)->Init(_program, _index, _name_bucket_id,
+ _result_shm_id, _result_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t index;
+ uint32_t name_bucket_id;
+ uint32_t result_shm_id;
+ uint32_t result_shm_offset;
+};
+
+static_assert(sizeof(GetActiveUniformBlockName) == 24,
+ "size of GetActiveUniformBlockName should be 24");
+static_assert(offsetof(GetActiveUniformBlockName, header) == 0,
+ "offset of GetActiveUniformBlockName header should be 0");
+static_assert(offsetof(GetActiveUniformBlockName, program) == 4,
+ "offset of GetActiveUniformBlockName program should be 4");
+static_assert(offsetof(GetActiveUniformBlockName, index) == 8,
+ "offset of GetActiveUniformBlockName index should be 8");
+static_assert(
+ offsetof(GetActiveUniformBlockName, name_bucket_id) == 12,
+ "offset of GetActiveUniformBlockName name_bucket_id should be 12");
+static_assert(offsetof(GetActiveUniformBlockName, result_shm_id) == 16,
+ "offset of GetActiveUniformBlockName result_shm_id should be 16");
+static_assert(
+ offsetof(GetActiveUniformBlockName, result_shm_offset) == 20,
+ "offset of GetActiveUniformBlockName result_shm_offset should be 20");
+
struct GetAttachedShaders {
typedef GetAttachedShaders ValueType;
static const CommandId kCmdId = kGetAttachedShaders;
@@ -4516,6 +4579,61 @@
static_assert(offsetof(GetTexParameteriv, params_shm_offset) == 16,
"offset of GetTexParameteriv params_shm_offset should be 16");
+struct GetUniformBlockIndex {
+ typedef GetUniformBlockIndex ValueType;
+ static const CommandId kCmdId = kGetUniformBlockIndex;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ typedef GLuint Result;
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _program,
+ uint32_t _name_bucket_id,
+ uint32_t _index_shm_id,
+ uint32_t _index_shm_offset) {
+ SetHeader();
+ program = _program;
+ name_bucket_id = _name_bucket_id;
+ index_shm_id = _index_shm_id;
+ index_shm_offset = _index_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _program,
+ uint32_t _name_bucket_id,
+ uint32_t _index_shm_id,
+ uint32_t _index_shm_offset) {
+ static_cast<ValueType*>(cmd)
+ ->Init(_program, _name_bucket_id, _index_shm_id, _index_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t name_bucket_id;
+ uint32_t index_shm_id;
+ uint32_t index_shm_offset;
+};
+
+static_assert(sizeof(GetUniformBlockIndex) == 20,
+ "size of GetUniformBlockIndex should be 20");
+static_assert(offsetof(GetUniformBlockIndex, header) == 0,
+ "offset of GetUniformBlockIndex header should be 0");
+static_assert(offsetof(GetUniformBlockIndex, program) == 4,
+ "offset of GetUniformBlockIndex program should be 4");
+static_assert(offsetof(GetUniformBlockIndex, name_bucket_id) == 8,
+ "offset of GetUniformBlockIndex name_bucket_id should be 8");
+static_assert(offsetof(GetUniformBlockIndex, index_shm_id) == 12,
+ "offset of GetUniformBlockIndex index_shm_id should be 12");
+static_assert(offsetof(GetUniformBlockIndex, index_shm_offset) == 16,
+ "offset of GetUniformBlockIndex index_shm_offset should be 16");
+
struct GetUniformfv {
typedef GetUniformfv ValueType;
static const CommandId kCmdId = kGetUniformfv;
@@ -10512,6 +10630,45 @@
"offset of GetProgramInfoCHROMIUM Result num_uniforms should be "
"8");
+struct GetUniformBlocksCHROMIUM {
+ typedef GetUniformBlocksCHROMIUM ValueType;
+ static const CommandId kCmdId = kGetUniformBlocksCHROMIUM;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ typedef uint32_t Result;
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _program, uint32_t _bucket_id) {
+ SetHeader();
+ program = _program;
+ bucket_id = _bucket_id;
+ }
+
+ void* Set(void* cmd, GLuint _program, uint32_t _bucket_id) {
+ static_cast<ValueType*>(cmd)->Init(_program, _bucket_id);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t bucket_id;
+};
+
+static_assert(sizeof(GetUniformBlocksCHROMIUM) == 12,
+ "size of GetUniformBlocksCHROMIUM should be 12");
+static_assert(offsetof(GetUniformBlocksCHROMIUM, header) == 0,
+ "offset of GetUniformBlocksCHROMIUM header should be 0");
+static_assert(offsetof(GetUniformBlocksCHROMIUM, program) == 4,
+ "offset of GetUniformBlocksCHROMIUM program should be 4");
+static_assert(offsetof(GetUniformBlocksCHROMIUM, bucket_id) == 8,
+ "offset of GetUniformBlocksCHROMIUM bucket_id should be 8");
+
struct GetTranslatedShaderSourceANGLE {
typedef GetTranslatedShaderSourceANGLE ValueType;
static const CommandId kCmdId = kGetTranslatedShaderSourceANGLE;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 804bebc..5174384 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -1095,6 +1095,24 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GetActiveUniformBlockName) {
+ cmds::GetActiveUniformBlockName& cmd =
+ *GetBufferAs<cmds::GetActiveUniformBlockName>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLuint>(12),
+ static_cast<uint32_t>(13), static_cast<uint32_t>(14),
+ static_cast<uint32_t>(15));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GetActiveUniformBlockName::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+ EXPECT_EQ(static_cast<uint32_t>(13), cmd.name_bucket_id);
+ EXPECT_EQ(static_cast<uint32_t>(14), cmd.result_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(15), cmd.result_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, GetAttachedShaders) {
cmds::GetAttachedShaders& cmd = *GetBufferAs<cmds::GetAttachedShaders>();
void* next_cmd =
@@ -1415,6 +1433,21 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GetUniformBlockIndex) {
+ cmds::GetUniformBlockIndex& cmd = *GetBufferAs<cmds::GetUniformBlockIndex>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12),
+ static_cast<uint32_t>(13), static_cast<uint32_t>(14));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GetUniformBlockIndex::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<uint32_t>(12), cmd.name_bucket_id);
+ EXPECT_EQ(static_cast<uint32_t>(13), cmd.index_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(14), cmd.index_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, GetUniformfv) {
cmds::GetUniformfv& cmd = *GetBufferAs<cmds::GetUniformfv>();
void* next_cmd =
@@ -3667,6 +3700,19 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GetUniformBlocksCHROMIUM) {
+ cmds::GetUniformBlocksCHROMIUM& cmd =
+ *GetBufferAs<cmds::GetUniformBlocksCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GetUniformBlocksCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<uint32_t>(12), cmd.bucket_id);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, GetTranslatedShaderSourceANGLE) {
cmds::GetTranslatedShaderSourceANGLE& cmd =
*GetBufferAs<cmds::GetTranslatedShaderSourceANGLE>();
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index df996d8..76364b7 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -87,195 +87,198 @@
OP(GenTransformFeedbacksImmediate) /* 328 */ \
OP(GetActiveAttrib) /* 329 */ \
OP(GetActiveUniform) /* 330 */ \
- OP(GetAttachedShaders) /* 331 */ \
- OP(GetAttribLocation) /* 332 */ \
- OP(GetBooleanv) /* 333 */ \
- OP(GetBufferParameteriv) /* 334 */ \
- OP(GetError) /* 335 */ \
- OP(GetFloatv) /* 336 */ \
- OP(GetFragDataLocation) /* 337 */ \
- OP(GetFramebufferAttachmentParameteriv) /* 338 */ \
- OP(GetIntegerv) /* 339 */ \
- OP(GetInternalformativ) /* 340 */ \
- OP(GetProgramiv) /* 341 */ \
- OP(GetProgramInfoLog) /* 342 */ \
- OP(GetRenderbufferParameteriv) /* 343 */ \
- OP(GetSamplerParameterfv) /* 344 */ \
- OP(GetSamplerParameteriv) /* 345 */ \
- OP(GetShaderiv) /* 346 */ \
- OP(GetShaderInfoLog) /* 347 */ \
- OP(GetShaderPrecisionFormat) /* 348 */ \
- OP(GetShaderSource) /* 349 */ \
- OP(GetString) /* 350 */ \
- OP(GetTexParameterfv) /* 351 */ \
- OP(GetTexParameteriv) /* 352 */ \
- OP(GetUniformfv) /* 353 */ \
- OP(GetUniformiv) /* 354 */ \
- OP(GetUniformLocation) /* 355 */ \
- OP(GetVertexAttribfv) /* 356 */ \
- OP(GetVertexAttribiv) /* 357 */ \
- OP(GetVertexAttribPointerv) /* 358 */ \
- OP(Hint) /* 359 */ \
- OP(InvalidateFramebufferImmediate) /* 360 */ \
- OP(InvalidateSubFramebufferImmediate) /* 361 */ \
- OP(IsBuffer) /* 362 */ \
- OP(IsEnabled) /* 363 */ \
- OP(IsFramebuffer) /* 364 */ \
- OP(IsProgram) /* 365 */ \
- OP(IsRenderbuffer) /* 366 */ \
- OP(IsSampler) /* 367 */ \
- OP(IsShader) /* 368 */ \
- OP(IsSync) /* 369 */ \
- OP(IsTexture) /* 370 */ \
- OP(IsTransformFeedback) /* 371 */ \
- OP(LineWidth) /* 372 */ \
- OP(LinkProgram) /* 373 */ \
- OP(PauseTransformFeedback) /* 374 */ \
- OP(PixelStorei) /* 375 */ \
- OP(PolygonOffset) /* 376 */ \
- OP(ReadBuffer) /* 377 */ \
- OP(ReadPixels) /* 378 */ \
- OP(ReleaseShaderCompiler) /* 379 */ \
- OP(RenderbufferStorage) /* 380 */ \
- OP(ResumeTransformFeedback) /* 381 */ \
- OP(SampleCoverage) /* 382 */ \
- OP(SamplerParameterf) /* 383 */ \
- OP(SamplerParameterfvImmediate) /* 384 */ \
- OP(SamplerParameteri) /* 385 */ \
- OP(SamplerParameterivImmediate) /* 386 */ \
- OP(Scissor) /* 387 */ \
- OP(ShaderBinary) /* 388 */ \
- OP(ShaderSourceBucket) /* 389 */ \
- OP(StencilFunc) /* 390 */ \
- OP(StencilFuncSeparate) /* 391 */ \
- OP(StencilMask) /* 392 */ \
- OP(StencilMaskSeparate) /* 393 */ \
- OP(StencilOp) /* 394 */ \
- OP(StencilOpSeparate) /* 395 */ \
- OP(TexImage2D) /* 396 */ \
- OP(TexImage3D) /* 397 */ \
- OP(TexParameterf) /* 398 */ \
- OP(TexParameterfvImmediate) /* 399 */ \
- OP(TexParameteri) /* 400 */ \
- OP(TexParameterivImmediate) /* 401 */ \
- OP(TexStorage3D) /* 402 */ \
- OP(TexSubImage2D) /* 403 */ \
- OP(TexSubImage3D) /* 404 */ \
- OP(TransformFeedbackVaryingsBucket) /* 405 */ \
- OP(Uniform1f) /* 406 */ \
- OP(Uniform1fvImmediate) /* 407 */ \
- OP(Uniform1i) /* 408 */ \
- OP(Uniform1ivImmediate) /* 409 */ \
- OP(Uniform1ui) /* 410 */ \
- OP(Uniform1uivImmediate) /* 411 */ \
- OP(Uniform2f) /* 412 */ \
- OP(Uniform2fvImmediate) /* 413 */ \
- OP(Uniform2i) /* 414 */ \
- OP(Uniform2ivImmediate) /* 415 */ \
- OP(Uniform2ui) /* 416 */ \
- OP(Uniform2uivImmediate) /* 417 */ \
- OP(Uniform3f) /* 418 */ \
- OP(Uniform3fvImmediate) /* 419 */ \
- OP(Uniform3i) /* 420 */ \
- OP(Uniform3ivImmediate) /* 421 */ \
- OP(Uniform3ui) /* 422 */ \
- OP(Uniform3uivImmediate) /* 423 */ \
- OP(Uniform4f) /* 424 */ \
- OP(Uniform4fvImmediate) /* 425 */ \
- OP(Uniform4i) /* 426 */ \
- OP(Uniform4ivImmediate) /* 427 */ \
- OP(Uniform4ui) /* 428 */ \
- OP(Uniform4uivImmediate) /* 429 */ \
- OP(UniformMatrix2fvImmediate) /* 430 */ \
- OP(UniformMatrix2x3fvImmediate) /* 431 */ \
- OP(UniformMatrix2x4fvImmediate) /* 432 */ \
- OP(UniformMatrix3fvImmediate) /* 433 */ \
- OP(UniformMatrix3x2fvImmediate) /* 434 */ \
- OP(UniformMatrix3x4fvImmediate) /* 435 */ \
- OP(UniformMatrix4fvImmediate) /* 436 */ \
- OP(UniformMatrix4x2fvImmediate) /* 437 */ \
- OP(UniformMatrix4x3fvImmediate) /* 438 */ \
- OP(UseProgram) /* 439 */ \
- OP(ValidateProgram) /* 440 */ \
- OP(VertexAttrib1f) /* 441 */ \
- OP(VertexAttrib1fvImmediate) /* 442 */ \
- OP(VertexAttrib2f) /* 443 */ \
- OP(VertexAttrib2fvImmediate) /* 444 */ \
- OP(VertexAttrib3f) /* 445 */ \
- OP(VertexAttrib3fvImmediate) /* 446 */ \
- OP(VertexAttrib4f) /* 447 */ \
- OP(VertexAttrib4fvImmediate) /* 448 */ \
- OP(VertexAttribI4i) /* 449 */ \
- OP(VertexAttribI4ivImmediate) /* 450 */ \
- OP(VertexAttribI4ui) /* 451 */ \
- OP(VertexAttribI4uivImmediate) /* 452 */ \
- OP(VertexAttribIPointer) /* 453 */ \
- OP(VertexAttribPointer) /* 454 */ \
- OP(Viewport) /* 455 */ \
- OP(BlitFramebufferCHROMIUM) /* 456 */ \
- OP(RenderbufferStorageMultisampleCHROMIUM) /* 457 */ \
- OP(RenderbufferStorageMultisampleEXT) /* 458 */ \
- OP(FramebufferTexture2DMultisampleEXT) /* 459 */ \
- OP(TexStorage2DEXT) /* 460 */ \
- OP(GenQueriesEXTImmediate) /* 461 */ \
- OP(DeleteQueriesEXTImmediate) /* 462 */ \
- OP(BeginQueryEXT) /* 463 */ \
- OP(BeginTransformFeedback) /* 464 */ \
- OP(EndQueryEXT) /* 465 */ \
- OP(EndTransformFeedback) /* 466 */ \
- OP(InsertEventMarkerEXT) /* 467 */ \
- OP(PushGroupMarkerEXT) /* 468 */ \
- OP(PopGroupMarkerEXT) /* 469 */ \
- OP(GenVertexArraysOESImmediate) /* 470 */ \
- OP(DeleteVertexArraysOESImmediate) /* 471 */ \
- OP(IsVertexArrayOES) /* 472 */ \
- OP(BindVertexArrayOES) /* 473 */ \
- OP(SwapBuffers) /* 474 */ \
- OP(GetMaxValueInBufferCHROMIUM) /* 475 */ \
- OP(EnableFeatureCHROMIUM) /* 476 */ \
- OP(ResizeCHROMIUM) /* 477 */ \
- OP(GetRequestableExtensionsCHROMIUM) /* 478 */ \
- OP(RequestExtensionCHROMIUM) /* 479 */ \
- OP(GetProgramInfoCHROMIUM) /* 480 */ \
- OP(GetTranslatedShaderSourceANGLE) /* 481 */ \
- OP(PostSubBufferCHROMIUM) /* 482 */ \
- OP(TexImageIOSurface2DCHROMIUM) /* 483 */ \
- OP(CopyTextureCHROMIUM) /* 484 */ \
- OP(DrawArraysInstancedANGLE) /* 485 */ \
- OP(DrawElementsInstancedANGLE) /* 486 */ \
- OP(VertexAttribDivisorANGLE) /* 487 */ \
- OP(GenMailboxCHROMIUM) /* 488 */ \
- OP(ProduceTextureCHROMIUMImmediate) /* 489 */ \
- OP(ProduceTextureDirectCHROMIUMImmediate) /* 490 */ \
- OP(ConsumeTextureCHROMIUMImmediate) /* 491 */ \
- OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 492 */ \
- OP(BindUniformLocationCHROMIUMBucket) /* 493 */ \
- OP(GenValuebuffersCHROMIUMImmediate) /* 494 */ \
- OP(DeleteValuebuffersCHROMIUMImmediate) /* 495 */ \
- OP(IsValuebufferCHROMIUM) /* 496 */ \
- OP(BindValuebufferCHROMIUM) /* 497 */ \
- OP(SubscribeValueCHROMIUM) /* 498 */ \
- OP(PopulateSubscribedValuesCHROMIUM) /* 499 */ \
- OP(UniformValuebufferCHROMIUM) /* 500 */ \
- OP(BindTexImage2DCHROMIUM) /* 501 */ \
- OP(ReleaseTexImage2DCHROMIUM) /* 502 */ \
- OP(TraceBeginCHROMIUM) /* 503 */ \
- OP(TraceEndCHROMIUM) /* 504 */ \
- OP(AsyncTexSubImage2DCHROMIUM) /* 505 */ \
- OP(AsyncTexImage2DCHROMIUM) /* 506 */ \
- OP(WaitAsyncTexImage2DCHROMIUM) /* 507 */ \
- OP(WaitAllAsyncTexImage2DCHROMIUM) /* 508 */ \
- OP(DiscardFramebufferEXTImmediate) /* 509 */ \
- OP(LoseContextCHROMIUM) /* 510 */ \
- OP(InsertSyncPointCHROMIUM) /* 511 */ \
- OP(WaitSyncPointCHROMIUM) /* 512 */ \
- OP(DrawBuffersEXTImmediate) /* 513 */ \
- OP(DiscardBackbufferCHROMIUM) /* 514 */ \
- OP(ScheduleOverlayPlaneCHROMIUM) /* 515 */ \
- OP(SwapInterval) /* 516 */ \
- OP(MatrixLoadfCHROMIUMImmediate) /* 517 */ \
- OP(MatrixLoadIdentityCHROMIUM) /* 518 */ \
- OP(BlendBarrierKHR) /* 519 */
+ OP(GetActiveUniformBlockName) /* 331 */ \
+ OP(GetAttachedShaders) /* 332 */ \
+ OP(GetAttribLocation) /* 333 */ \
+ OP(GetBooleanv) /* 334 */ \
+ OP(GetBufferParameteriv) /* 335 */ \
+ OP(GetError) /* 336 */ \
+ OP(GetFloatv) /* 337 */ \
+ OP(GetFragDataLocation) /* 338 */ \
+ OP(GetFramebufferAttachmentParameteriv) /* 339 */ \
+ OP(GetIntegerv) /* 340 */ \
+ OP(GetInternalformativ) /* 341 */ \
+ OP(GetProgramiv) /* 342 */ \
+ OP(GetProgramInfoLog) /* 343 */ \
+ OP(GetRenderbufferParameteriv) /* 344 */ \
+ OP(GetSamplerParameterfv) /* 345 */ \
+ OP(GetSamplerParameteriv) /* 346 */ \
+ OP(GetShaderiv) /* 347 */ \
+ OP(GetShaderInfoLog) /* 348 */ \
+ OP(GetShaderPrecisionFormat) /* 349 */ \
+ OP(GetShaderSource) /* 350 */ \
+ OP(GetString) /* 351 */ \
+ OP(GetTexParameterfv) /* 352 */ \
+ OP(GetTexParameteriv) /* 353 */ \
+ OP(GetUniformBlockIndex) /* 354 */ \
+ OP(GetUniformfv) /* 355 */ \
+ OP(GetUniformiv) /* 356 */ \
+ OP(GetUniformLocation) /* 357 */ \
+ OP(GetVertexAttribfv) /* 358 */ \
+ OP(GetVertexAttribiv) /* 359 */ \
+ OP(GetVertexAttribPointerv) /* 360 */ \
+ OP(Hint) /* 361 */ \
+ OP(InvalidateFramebufferImmediate) /* 362 */ \
+ OP(InvalidateSubFramebufferImmediate) /* 363 */ \
+ OP(IsBuffer) /* 364 */ \
+ OP(IsEnabled) /* 365 */ \
+ OP(IsFramebuffer) /* 366 */ \
+ OP(IsProgram) /* 367 */ \
+ OP(IsRenderbuffer) /* 368 */ \
+ OP(IsSampler) /* 369 */ \
+ OP(IsShader) /* 370 */ \
+ OP(IsSync) /* 371 */ \
+ OP(IsTexture) /* 372 */ \
+ OP(IsTransformFeedback) /* 373 */ \
+ OP(LineWidth) /* 374 */ \
+ OP(LinkProgram) /* 375 */ \
+ OP(PauseTransformFeedback) /* 376 */ \
+ OP(PixelStorei) /* 377 */ \
+ OP(PolygonOffset) /* 378 */ \
+ OP(ReadBuffer) /* 379 */ \
+ OP(ReadPixels) /* 380 */ \
+ OP(ReleaseShaderCompiler) /* 381 */ \
+ OP(RenderbufferStorage) /* 382 */ \
+ OP(ResumeTransformFeedback) /* 383 */ \
+ OP(SampleCoverage) /* 384 */ \
+ OP(SamplerParameterf) /* 385 */ \
+ OP(SamplerParameterfvImmediate) /* 386 */ \
+ OP(SamplerParameteri) /* 387 */ \
+ OP(SamplerParameterivImmediate) /* 388 */ \
+ OP(Scissor) /* 389 */ \
+ OP(ShaderBinary) /* 390 */ \
+ OP(ShaderSourceBucket) /* 391 */ \
+ OP(StencilFunc) /* 392 */ \
+ OP(StencilFuncSeparate) /* 393 */ \
+ OP(StencilMask) /* 394 */ \
+ OP(StencilMaskSeparate) /* 395 */ \
+ OP(StencilOp) /* 396 */ \
+ OP(StencilOpSeparate) /* 397 */ \
+ OP(TexImage2D) /* 398 */ \
+ OP(TexImage3D) /* 399 */ \
+ OP(TexParameterf) /* 400 */ \
+ OP(TexParameterfvImmediate) /* 401 */ \
+ OP(TexParameteri) /* 402 */ \
+ OP(TexParameterivImmediate) /* 403 */ \
+ OP(TexStorage3D) /* 404 */ \
+ OP(TexSubImage2D) /* 405 */ \
+ OP(TexSubImage3D) /* 406 */ \
+ OP(TransformFeedbackVaryingsBucket) /* 407 */ \
+ OP(Uniform1f) /* 408 */ \
+ OP(Uniform1fvImmediate) /* 409 */ \
+ OP(Uniform1i) /* 410 */ \
+ OP(Uniform1ivImmediate) /* 411 */ \
+ OP(Uniform1ui) /* 412 */ \
+ OP(Uniform1uivImmediate) /* 413 */ \
+ OP(Uniform2f) /* 414 */ \
+ OP(Uniform2fvImmediate) /* 415 */ \
+ OP(Uniform2i) /* 416 */ \
+ OP(Uniform2ivImmediate) /* 417 */ \
+ OP(Uniform2ui) /* 418 */ \
+ OP(Uniform2uivImmediate) /* 419 */ \
+ OP(Uniform3f) /* 420 */ \
+ OP(Uniform3fvImmediate) /* 421 */ \
+ OP(Uniform3i) /* 422 */ \
+ OP(Uniform3ivImmediate) /* 423 */ \
+ OP(Uniform3ui) /* 424 */ \
+ OP(Uniform3uivImmediate) /* 425 */ \
+ OP(Uniform4f) /* 426 */ \
+ OP(Uniform4fvImmediate) /* 427 */ \
+ OP(Uniform4i) /* 428 */ \
+ OP(Uniform4ivImmediate) /* 429 */ \
+ OP(Uniform4ui) /* 430 */ \
+ OP(Uniform4uivImmediate) /* 431 */ \
+ OP(UniformMatrix2fvImmediate) /* 432 */ \
+ OP(UniformMatrix2x3fvImmediate) /* 433 */ \
+ OP(UniformMatrix2x4fvImmediate) /* 434 */ \
+ OP(UniformMatrix3fvImmediate) /* 435 */ \
+ OP(UniformMatrix3x2fvImmediate) /* 436 */ \
+ OP(UniformMatrix3x4fvImmediate) /* 437 */ \
+ OP(UniformMatrix4fvImmediate) /* 438 */ \
+ OP(UniformMatrix4x2fvImmediate) /* 439 */ \
+ OP(UniformMatrix4x3fvImmediate) /* 440 */ \
+ OP(UseProgram) /* 441 */ \
+ OP(ValidateProgram) /* 442 */ \
+ OP(VertexAttrib1f) /* 443 */ \
+ OP(VertexAttrib1fvImmediate) /* 444 */ \
+ OP(VertexAttrib2f) /* 445 */ \
+ OP(VertexAttrib2fvImmediate) /* 446 */ \
+ OP(VertexAttrib3f) /* 447 */ \
+ OP(VertexAttrib3fvImmediate) /* 448 */ \
+ OP(VertexAttrib4f) /* 449 */ \
+ OP(VertexAttrib4fvImmediate) /* 450 */ \
+ OP(VertexAttribI4i) /* 451 */ \
+ OP(VertexAttribI4ivImmediate) /* 452 */ \
+ OP(VertexAttribI4ui) /* 453 */ \
+ OP(VertexAttribI4uivImmediate) /* 454 */ \
+ OP(VertexAttribIPointer) /* 455 */ \
+ OP(VertexAttribPointer) /* 456 */ \
+ OP(Viewport) /* 457 */ \
+ OP(BlitFramebufferCHROMIUM) /* 458 */ \
+ OP(RenderbufferStorageMultisampleCHROMIUM) /* 459 */ \
+ OP(RenderbufferStorageMultisampleEXT) /* 460 */ \
+ OP(FramebufferTexture2DMultisampleEXT) /* 461 */ \
+ OP(TexStorage2DEXT) /* 462 */ \
+ OP(GenQueriesEXTImmediate) /* 463 */ \
+ OP(DeleteQueriesEXTImmediate) /* 464 */ \
+ OP(BeginQueryEXT) /* 465 */ \
+ OP(BeginTransformFeedback) /* 466 */ \
+ OP(EndQueryEXT) /* 467 */ \
+ OP(EndTransformFeedback) /* 468 */ \
+ OP(InsertEventMarkerEXT) /* 469 */ \
+ OP(PushGroupMarkerEXT) /* 470 */ \
+ OP(PopGroupMarkerEXT) /* 471 */ \
+ OP(GenVertexArraysOESImmediate) /* 472 */ \
+ OP(DeleteVertexArraysOESImmediate) /* 473 */ \
+ OP(IsVertexArrayOES) /* 474 */ \
+ OP(BindVertexArrayOES) /* 475 */ \
+ OP(SwapBuffers) /* 476 */ \
+ OP(GetMaxValueInBufferCHROMIUM) /* 477 */ \
+ OP(EnableFeatureCHROMIUM) /* 478 */ \
+ OP(ResizeCHROMIUM) /* 479 */ \
+ OP(GetRequestableExtensionsCHROMIUM) /* 480 */ \
+ OP(RequestExtensionCHROMIUM) /* 481 */ \
+ OP(GetProgramInfoCHROMIUM) /* 482 */ \
+ OP(GetUniformBlocksCHROMIUM) /* 483 */ \
+ OP(GetTranslatedShaderSourceANGLE) /* 484 */ \
+ OP(PostSubBufferCHROMIUM) /* 485 */ \
+ OP(TexImageIOSurface2DCHROMIUM) /* 486 */ \
+ OP(CopyTextureCHROMIUM) /* 487 */ \
+ OP(DrawArraysInstancedANGLE) /* 488 */ \
+ OP(DrawElementsInstancedANGLE) /* 489 */ \
+ OP(VertexAttribDivisorANGLE) /* 490 */ \
+ OP(GenMailboxCHROMIUM) /* 491 */ \
+ OP(ProduceTextureCHROMIUMImmediate) /* 492 */ \
+ OP(ProduceTextureDirectCHROMIUMImmediate) /* 493 */ \
+ OP(ConsumeTextureCHROMIUMImmediate) /* 494 */ \
+ OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 495 */ \
+ OP(BindUniformLocationCHROMIUMBucket) /* 496 */ \
+ OP(GenValuebuffersCHROMIUMImmediate) /* 497 */ \
+ OP(DeleteValuebuffersCHROMIUMImmediate) /* 498 */ \
+ OP(IsValuebufferCHROMIUM) /* 499 */ \
+ OP(BindValuebufferCHROMIUM) /* 500 */ \
+ OP(SubscribeValueCHROMIUM) /* 501 */ \
+ OP(PopulateSubscribedValuesCHROMIUM) /* 502 */ \
+ OP(UniformValuebufferCHROMIUM) /* 503 */ \
+ OP(BindTexImage2DCHROMIUM) /* 504 */ \
+ OP(ReleaseTexImage2DCHROMIUM) /* 505 */ \
+ OP(TraceBeginCHROMIUM) /* 506 */ \
+ OP(TraceEndCHROMIUM) /* 507 */ \
+ OP(AsyncTexSubImage2DCHROMIUM) /* 508 */ \
+ OP(AsyncTexImage2DCHROMIUM) /* 509 */ \
+ OP(WaitAsyncTexImage2DCHROMIUM) /* 510 */ \
+ OP(WaitAllAsyncTexImage2DCHROMIUM) /* 511 */ \
+ OP(DiscardFramebufferEXTImmediate) /* 512 */ \
+ OP(LoseContextCHROMIUM) /* 513 */ \
+ OP(InsertSyncPointCHROMIUM) /* 514 */ \
+ OP(WaitSyncPointCHROMIUM) /* 515 */ \
+ OP(DrawBuffersEXTImmediate) /* 516 */ \
+ OP(DiscardBackbufferCHROMIUM) /* 517 */ \
+ OP(ScheduleOverlayPlaneCHROMIUM) /* 518 */ \
+ OP(SwapInterval) /* 519 */ \
+ OP(MatrixLoadfCHROMIUMImmediate) /* 520 */ \
+ OP(MatrixLoadIdentityCHROMIUM) /* 521 */ \
+ OP(BlendBarrierKHR) /* 522 */
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
index 2389dc1..9b6b7e2 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
@@ -77,13 +77,16 @@
AsyncPixelTransferManager* AsyncPixelTransferManager::Create(
gfx::GLContext* context) {
DCHECK(context->IsCurrent(NULL));
+ base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
+
// Threaded mailbox uses EGLImage which conflicts with EGL uploader.
// The spec only allows one EGL image per sibling group, but currently the
// image handle cannot be shared between the threaded mailbox code and
// AsyncPixelTransferManagerEGL.
bool uses_threaded_mailboxes =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableThreadedTextureMailboxes);
+ cl->HasSwitch(switches::kEnableThreadedTextureMailboxes);
+ // TexImage2D orphans the EGLImage used for threaded mailbox sharing.
+ bool use_teximage2d_over_texsubimage2d = !uses_threaded_mailboxes;
switch (gfx::GetGLImplementation()) {
case gfx::kGLImplementationEGLGLES2:
DCHECK(context);
@@ -93,15 +96,16 @@
context->HasExtension("EGL_KHR_image_base") &&
context->HasExtension("EGL_KHR_gl_texture_2D_image") &&
context->HasExtension("GL_OES_EGL_image") &&
- !uses_threaded_mailboxes &&
- AllowTransferThreadForGpu()) {
+ !uses_threaded_mailboxes && AllowTransferThreadForGpu()) {
TRACE_EVENT0("gpu", "AsyncPixelTransferManager_CreateWithThread");
return new AsyncPixelTransferManagerEGL;
}
- return new AsyncPixelTransferManagerIdle;
+ return new AsyncPixelTransferManagerIdle(
+ use_teximage2d_over_texsubimage2d);
case gfx::kGLImplementationOSMesaGL: {
TRACE_EVENT0("gpu", "AsyncPixelTransferManager_CreateIdle");
- return new AsyncPixelTransferManagerIdle;
+ return new AsyncPixelTransferManagerIdle(
+ use_teximage2d_over_texsubimage2d);
}
case gfx::kGLImplementationMockGL:
return new AsyncPixelTransferManagerStub;
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
index 2ed4f7d..b44b477 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
@@ -183,9 +183,8 @@
base::TimeTicks begin_time(base::TimeTicks::Now());
gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
- // If it's a full texture update, use glTexImage2D as it's faster.
- // TODO(epenner): Make this configurable (http://crbug.com/259924)
- if (tex_params.xoffset == 0 &&
+ if (shared_state_->use_teximage2d_over_texsubimage2d &&
+ tex_params.xoffset == 0 &&
tex_params.yoffset == 0 &&
tex_params.target == define_params_.target &&
tex_params.level == define_params_.level &&
@@ -234,8 +233,11 @@
AsyncPixelTransferManagerIdle::Task::~Task() {}
-AsyncPixelTransferManagerIdle::SharedState::SharedState()
- : texture_upload_count(0) {}
+AsyncPixelTransferManagerIdle::SharedState::SharedState(
+ bool use_teximage2d_over_texsubimage2d)
+ : use_teximage2d_over_texsubimage2d(use_teximage2d_over_texsubimage2d),
+ texture_upload_count(0) {
+}
AsyncPixelTransferManagerIdle::SharedState::~SharedState() {}
@@ -250,8 +252,9 @@
}
}
-AsyncPixelTransferManagerIdle::AsyncPixelTransferManagerIdle()
- : shared_state_() {
+AsyncPixelTransferManagerIdle::AsyncPixelTransferManagerIdle(
+ bool use_teximage2d_over_texsubimage2d)
+ : shared_state_(use_teximage2d_over_texsubimage2d) {
}
AsyncPixelTransferManagerIdle::~AsyncPixelTransferManagerIdle() {}
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h
index 8aba7ff..41a77b3 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.h
@@ -13,7 +13,8 @@
class AsyncPixelTransferManagerIdle : public AsyncPixelTransferManager {
public:
- AsyncPixelTransferManagerIdle();
+ explicit AsyncPixelTransferManagerIdle(
+ bool use_teximage2d_over_texsubimage2d);
~AsyncPixelTransferManagerIdle() override;
// AsyncPixelTransferManager implementation:
@@ -43,10 +44,11 @@
// State shared between Managers and Delegates.
struct SharedState {
- SharedState();
+ explicit SharedState(bool use_teximage2d_over_texsubimage2d);
~SharedState();
void ProcessNotificationTasks();
+ const bool use_teximage2d_over_texsubimage2d;
int texture_upload_count;
base::TimeDelta total_texture_upload_time;
std::list<Task> tasks;
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
index e756a46..b0cc463 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
@@ -28,7 +28,7 @@
case gfx::kGLImplementationOSMesaGL:
case gfx::kGLImplementationDesktopGL:
case gfx::kGLImplementationEGLGLES2:
- return new AsyncPixelTransferManagerIdle;
+ return new AsyncPixelTransferManagerIdle(true);
case gfx::kGLImplementationMockGL:
return new AsyncPixelTransferManagerStub;
default:
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
index 6f7c5d1..dcc7e18 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
@@ -18,7 +18,7 @@
case gfx::kGLImplementationOSMesaGL:
case gfx::kGLImplementationDesktopGL:
case gfx::kGLImplementationAppleGL:
- return new AsyncPixelTransferManagerIdle;
+ return new AsyncPixelTransferManagerIdle(true);
case gfx::kGLImplementationMockGL:
return new AsyncPixelTransferManagerStub;
default:
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
index 3bf32c0..dc106e8 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
@@ -18,7 +18,7 @@
case gfx::kGLImplementationOSMesaGL:
case gfx::kGLImplementationDesktopGL:
case gfx::kGLImplementationEGLGLES2:
- return new AsyncPixelTransferManagerIdle;
+ return new AsyncPixelTransferManagerIdle(true);
case gfx::kGLImplementationMockGL:
return new AsyncPixelTransferManagerStub;
default:
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
index 21e2ae4..f2444b3 100644
--- a/gpu/command_buffer/service/command_buffer_service.cc
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -79,6 +79,10 @@
put_offset_change_callback_.Run();
}
+void CommandBufferService::OrderingBarrier(int32 put_offset) {
+ Flush(put_offset);
+}
+
void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) {
DCHECK_EQ(-1, ring_buffer_id_);
DCHECK_EQ(put_offset_, get_offset_); // Only if it's empty.
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
index 69b9ad7..28a5f6f 100644
--- a/gpu/command_buffer/service/command_buffer_service.h
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -52,6 +52,7 @@
State GetLastState() override;
int32 GetLastToken() override;
void Flush(int32 put_offset) override;
+ void OrderingBarrier(int32 put_offset) override;
void WaitForTokenInRange(int32 start, int32 end) override;
void WaitForGetOffsetInRange(int32 start, int32 end) override;
void SetGetBuffer(int32 transfer_buffer_id) override;
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 5706086..803b121 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -17,6 +17,10 @@
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_implementation.h"
+#if !defined(OS_MACOSX)
+#include "ui/gl/gl_fence_egl.h"
+#endif
+
namespace gpu {
namespace gles2 {
@@ -1020,6 +1024,12 @@
texture_format_validators_[GL_RG_EXT].AddValue(GL_HALF_FLOAT_OES);
}
}
+
+#if !defined(OS_MACOSX)
+ if (workarounds_.ignore_egl_sync_failures) {
+ gfx::GLFenceEGL::SetIgnoreFailures();
+ }
+#endif
}
void FeatureInfo::AddExtensionString(const char* s) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index f37c61a..9b8e635 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1163,16 +1163,16 @@
GLuint client_id, GLint location, const char* name);
error::Error GetAttribLocationHelper(
- GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
- const std::string& name_str);
+ GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
+ const std::string& name_str);
error::Error GetUniformLocationHelper(
- GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
- const std::string& name_str);
+ GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
+ const std::string& name_str);
error::Error GetFragDataLocationHelper(
- GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
- const std::string& name_str);
+ GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
+ const std::string& name_str);
// Wrapper for glShaderSource.
void DoShaderSource(
@@ -2842,6 +2842,14 @@
DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
&caps.bind_generates_resource_chromium);
+ if (unsafe_es3_apis_enabled()) {
+ DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
+ &caps.max_transform_feedback_separate_attribs);
+ DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
+ &caps.max_uniform_buffer_bindings);
+ DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
+ &caps.uniform_buffer_offset_alignment);
+ }
caps.egl_image_external =
feature_info_->feature_flags().oes_egl_image_external;
@@ -7051,14 +7059,17 @@
GLuint client_id, GLsizei count, const char** data, const GLint* length) {
std::string str;
for (GLsizei ii = 0; ii < count; ++ii) {
- str.append(data[ii]);
+ if (length && length[ii] > 0)
+ str.append(data[ii], length[ii]);
+ else
+ str.append(data[ii]);
}
Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
if (!shader) {
return;
}
// Note: We don't actually call glShaderSource here. We wait until
- // the call to glCompileShader.
+ // we actually compile the shader.
shader->set_source(str);
}
@@ -7086,6 +7097,10 @@
vertex_translator_.get() : fragment_translator_.get();
}
+ shader->RequestCompile();
+
+ // TODO(dyen): Currently we compile immediately when glCompileShader is
+ // requested. Eventually this should be deffered to the linker stage.
shader->DoCompile(
translator,
feature_info_->feature_flags().angle_translated_shader_source ?
@@ -8186,6 +8201,39 @@
c.program, c.location_shm_id, c.location_shm_offset, name_str);
}
+error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
+ uint32 immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetUniformBlockIndex& c =
+ *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
+ Bucket* bucket = GetBucket(c.name_bucket_id);
+ if (!bucket) {
+ return error::kInvalidArguments;
+ }
+ std::string name_str;
+ if (!bucket->GetAsString(&name_str)) {
+ return error::kInvalidArguments;
+ }
+ GLuint* index = GetSharedMemoryAs<GLuint*>(
+ c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
+ if (!index) {
+ return error::kOutOfBounds;
+ }
+ // Require the client to init this in case the context is lost and we are no
+ // longer executing commands.
+ if (*index != GL_INVALID_INDEX) {
+ return error::kGenericError;
+ }
+ Program* program = GetProgramInfoNotShader(
+ c.program, "glGetUniformBlockIndex");
+ if (!program) {
+ return error::kNoError;
+ }
+ *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
const void* cmd_data) {
const gles2::cmds::GetString& c =
@@ -9682,6 +9730,59 @@
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
+ uint32 immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetActiveUniformBlockName& c =
+ *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
+ GLuint program_id = c.program;
+ GLuint index = c.index;
+ uint32 name_bucket_id = c.name_bucket_id;
+ typedef cmds::GetActiveUniformBlockName::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result));
+ if (!result) {
+ return error::kOutOfBounds;
+ }
+ // Check that the client initialized the result.
+ if (*result != 0) {
+ return error::kInvalidArguments;
+ }
+ Program* program = GetProgramInfoNotShader(
+ program_id, "glGetActiveUniformBlockName");
+ if (!program) {
+ return error::kNoError;
+ }
+ GLuint service_id = program->service_id();
+ GLint link_status = GL_FALSE;
+ glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
+ if (link_status != GL_TRUE) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glGetActiveActiveUniformBlockName", "program not linked");
+ return error::kNoError;
+ }
+ GLint max_length = 0;
+ glGetProgramiv(
+ service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
+ // Increase one so &buffer[0] is always valid.
+ GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
+ std::vector<char> buffer(buf_size);
+ GLsizei length = 0;
+ glGetActiveUniformBlockName(
+ service_id, index, buf_size, &length, &buffer[0]);
+ if (length == 0) {
+ *result = 0;
+ return error::kNoError;
+ }
+ *result = 1;
+ Bucket* bucket = CreateBucket(name_bucket_id);
+ DCHECK_GT(buf_size, length);
+ DCHECK_EQ(0, buffer[length]);
+ bucket->SetFromString(&buffer[0]);
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
const void* cmd_data) {
const gles2::cmds::GetActiveAttrib& c =
@@ -10016,6 +10117,25 @@
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
+ uint32 immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetUniformBlocksCHROMIUM& c =
+ *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
+ GLuint program_id = static_cast<GLuint>(c.program);
+ uint32 bucket_id = c.bucket_id;
+ Bucket* bucket = CreateBucket(bucket_id);
+ bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
+ Program* program = NULL;
+ program = GetProgram(program_id);
+ if (!program || !program->IsValid()) {
+ return error::kNoError;
+ }
+ program->GetUniformBlocks(bucket);
+ return error::kNoError;
+}
+
error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
switch (reset_status_) {
case GL_NO_ERROR:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
index 2b6a38f..99f26e9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
@@ -85,10 +85,10 @@
TEST_P(GLES2DecoderTest1, BindBufferRangeValidArgs) {
EXPECT_CALL(*gl_, BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2,
- kServiceBufferId, 4, 5));
+ kServiceBufferId, 4, 4));
SpecializedSetup<cmds::BindBufferRange, 0>(true);
cmds::BindBufferRange cmd;
- cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, client_buffer_id_, 4, 5);
+ cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, client_buffer_id_, 4, 4);
decoder_->set_unsafe_es3_apis_enabled(true);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
@@ -98,12 +98,12 @@
TEST_P(GLES2DecoderTest1, BindBufferRangeValidArgsNewId) {
EXPECT_CALL(*gl_, BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 2,
- kNewServiceId, 4, 5));
+ kNewServiceId, 4, 4));
EXPECT_CALL(*gl_, GenBuffersARB(1, _))
.WillOnce(SetArgumentPointee<1>(kNewServiceId));
SpecializedSetup<cmds::BindBufferRange, 0>(true);
cmds::BindBufferRange cmd;
- cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId, 4, 5);
+ cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId, 4, 4);
decoder_->set_unsafe_es3_apis_enabled(true);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
@@ -1208,6 +1208,8 @@
// TODO(gman): GetActiveUniform
+// TODO(gman): GetActiveUniformBlockName
+
// TODO(gman): GetAttachedShaders
// TODO(gman): GetAttribLocation
@@ -1953,6 +1955,4 @@
EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
EXPECT_EQ(0u, result->size);
}
-// TODO(gman): GetUniformfv
-
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
index 2947723..60d147b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -12,6 +12,10 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
+// TODO(gman): GetUniformBlockIndex
+
+// TODO(gman): GetUniformfv
+
// TODO(gman): GetUniformiv
// TODO(gman): GetUniformLocation
@@ -1497,33 +1501,4 @@
decoder_->set_unsafe_es3_apis_enabled(false);
EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
}
-
-TEST_P(GLES2DecoderTest2, VertexAttribI4ivImmediateValidArgs) {
- cmds::VertexAttribI4ivImmediate& cmd =
- *GetImmediateAs<cmds::VertexAttribI4ivImmediate>();
- SpecializedSetup<cmds::VertexAttribI4ivImmediate, 0>(true);
- GLint temp[4] = {
- 0,
- };
- cmd.Init(1, &temp[0]);
- EXPECT_CALL(*gl_, VertexAttribI4iv(1, reinterpret_cast<GLint*>(
- ImmediateDataAddress(&cmd))));
- decoder_->set_unsafe_es3_apis_enabled(true);
- EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
- decoder_->set_unsafe_es3_apis_enabled(false);
- EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp)));
-}
-
-TEST_P(GLES2DecoderTest2, VertexAttribI4uiValidArgs) {
- EXPECT_CALL(*gl_, VertexAttribI4ui(1, 2, 3, 4, 5));
- SpecializedSetup<cmds::VertexAttribI4ui, 0>(true);
- cmds::VertexAttribI4ui cmd;
- cmd.Init(1, 2, 3, 4, 5);
- decoder_->set_unsafe_es3_apis_enabled(true);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
- decoder_->set_unsafe_es3_apis_enabled(false);
- EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
-}
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
index 2eb4e58..6421985 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -12,6 +12,35 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_
#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_
+TEST_P(GLES2DecoderTest3, VertexAttribI4ivImmediateValidArgs) {
+ cmds::VertexAttribI4ivImmediate& cmd =
+ *GetImmediateAs<cmds::VertexAttribI4ivImmediate>();
+ SpecializedSetup<cmds::VertexAttribI4ivImmediate, 0>(true);
+ GLint temp[4] = {
+ 0,
+ };
+ cmd.Init(1, &temp[0]);
+ EXPECT_CALL(*gl_, VertexAttribI4iv(1, reinterpret_cast<GLint*>(
+ ImmediateDataAddress(&cmd))));
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp)));
+}
+
+TEST_P(GLES2DecoderTest3, VertexAttribI4uiValidArgs) {
+ EXPECT_CALL(*gl_, VertexAttribI4ui(1, 2, 3, 4, 5));
+ SpecializedSetup<cmds::VertexAttribI4ui, 0>(true);
+ cmds::VertexAttribI4ui cmd;
+ cmd.Init(1, 2, 3, 4, 5);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
TEST_P(GLES2DecoderTest3, VertexAttribI4uivImmediateValidArgs) {
cmds::VertexAttribI4uivImmediate& cmd =
*GetImmediateAs<cmds::VertexAttribI4uivImmediate>();
@@ -113,6 +142,8 @@
// TODO(gman): GetProgramInfoCHROMIUM
+// TODO(gman): GetUniformBlocksCHROMIUM
+
// TODO(gman): GetTranslatedShaderSourceANGLE
// TODO(gman): PostSubBufferCHROMIUM
// TODO(gman): TexImageIOSurface2DCHROMIUM
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
index 5eda0a9..c0e2364 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
@@ -81,6 +81,47 @@
EXPECT_EQ(0u, info->num_uniforms);
}
+TEST_P(GLES2DecoderWithShaderTest, GetUniformBlocksCHROMIUMValidArgs) {
+ const uint32 kBucketId = 123;
+ GetUniformBlocksCHROMIUM cmd;
+ cmd.Init(client_program_id_, kBucketId);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_BLOCKS, _))
+ .WillOnce(SetArgPointee<2>(0))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+ EXPECT_EQ(sizeof(UniformBlocksHeader), bucket->size());
+ UniformBlocksHeader* header =
+ bucket->GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader));
+ EXPECT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_uniform_blocks);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformBlocksCHROMIUMInvalidArgs) {
+ const uint32 kBucketId = 123;
+ CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+ EXPECT_TRUE(bucket == NULL);
+ GetUniformBlocksCHROMIUM cmd;
+ cmd.Init(kInvalidClientId, kBucketId);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ bucket = decoder_->GetBucket(kBucketId);
+ ASSERT_TRUE(bucket != NULL);
+ EXPECT_EQ(sizeof(UniformBlocksHeader), bucket->size());
+ UniformBlocksHeader* header =
+ bucket->GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader));
+ ASSERT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_uniform_blocks);
+}
+
TEST_P(GLES2DecoderWithShaderTest, GetUniformivSucceeds) {
GetUniformiv::Result* result =
static_cast<GetUniformiv::Result*>(shared_memory_address_);
@@ -530,6 +571,116 @@
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockNameSucceeds) {
+ const uint32 kBucketId = 123;
+ GetActiveUniformBlockName cmd;
+ typedef GetActiveUniformBlockName::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ *result = 0;
+ cmd.Init(client_program_id_,
+ 0,
+ kBucketId,
+ shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ const char kName[] = "HolyCow";
+ const GLsizei kMaxLength = strlen(kName) + 1;
+ EXPECT_CALL(*gl_,
+ GetProgramiv(kServiceProgramId,
+ GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, _))
+ .WillOnce(SetArgPointee<2>(kMaxLength))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetActiveUniformBlockName(kServiceProgramId, 0, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<3>(strlen(kName)),
+ SetArrayArgument<4>(kName, kName + strlen(kName) + 1)))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_NE(0, *result);
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+ ASSERT_TRUE(bucket != NULL);
+ EXPECT_EQ(0,
+ memcmp(bucket->GetData(0, bucket->size()), kName, bucket->size()));
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockNameUnlinkedProgram) {
+ const uint32 kBucketId = 123;
+ GetActiveUniformBlockName cmd;
+ typedef GetActiveUniformBlockName::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ *result = 0;
+ cmd.Init(client_program_id_,
+ 0,
+ kBucketId,
+ shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_FALSE))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, *result);
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+ GetActiveUniformBlockNameResultNotInitFails) {
+ const uint32 kBucketId = 123;
+ GetActiveUniformBlockName cmd;
+ typedef GetActiveUniformBlockName::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ *result = 1;
+ cmd.Init(client_program_id_,
+ 0,
+ kBucketId,
+ shared_memory_id_,
+ shared_memory_offset_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockNameBadProgramFails) {
+ const uint32 kBucketId = 123;
+ GetActiveUniformBlockName cmd;
+ typedef GetActiveUniformBlockName::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ *result = 0;
+ cmd.Init(kInvalidClientId,
+ 0,
+ kBucketId,
+ shared_memory_id_,
+ shared_memory_offset_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, *result);
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+ GetActiveUniformBlockNameBadSharedMemoryFails) {
+ const uint32 kBucketId = 123;
+ GetActiveUniformBlockName cmd;
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ cmd.Init(client_program_id_,
+ 0,
+ kBucketId,
+ kInvalidSharedMemoryId,
+ shared_memory_offset_);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(client_program_id_,
+ 0,
+ kBucketId,
+ shared_memory_id_,
+ kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribSucceeds) {
const GLuint kAttribIndex = 1;
const uint32 kBucketId = 123;
@@ -927,6 +1078,58 @@
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
+TEST_P(GLES2DecoderWithShaderTest, GetUniformBlockIndex) {
+ const uint32 kBucketId = 123;
+ const GLuint kIndex = 10;
+ const char* kName = "color";
+ typedef GetUniformBlockIndex::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>();
+ SetBucketAsCString(kBucketId, kName);
+ *result = GL_INVALID_INDEX;
+ GetUniformBlockIndex cmd;
+ cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformBlockIndex(kServiceProgramId, StrEq(kName)))
+ .WillOnce(Return(kIndex))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(kIndex, *result);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformBlockIndexInvalidArgs) {
+ const uint32 kBucketId = 123;
+ typedef GetUniformBlockIndex::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>();
+ *result = GL_INVALID_INDEX;
+ GetUniformBlockIndex cmd;
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ // Check no bucket
+ cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_INDEX, *result);
+ // Check bad program id.
+ const char* kName = "color";
+ SetBucketAsCString(kBucketId, kName);
+ cmd.Init(kInvalidClientId, kBucketId, kSharedMemoryId, kSharedMemoryOffset);
+ *result = GL_INVALID_INDEX;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_INVALID_INDEX, *result);
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+ // Check bad memory
+ cmd.Init(client_program_id_,
+ kBucketId,
+ kInvalidSharedMemoryId,
+ kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(client_program_id_,
+ kBucketId,
+ kSharedMemoryId,
+ kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
TEST_P(GLES2DecoderWithShaderTest, GetUniformLocation) {
const uint32 kBucketId = 123;
const char* kNonExistentName = "foobar";
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 7a6556b..5db80b0 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -631,6 +631,10 @@
QueueTask(task);
}
+void InProcessCommandBuffer::OrderingBarrier(int32 put_offset) {
+ Flush(put_offset);
+}
+
void InProcessCommandBuffer::WaitForTokenInRange(int32 start, int32 end) {
CheckSequencedThread();
while (!InRange(start, end, GetLastToken()) &&
diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h
index ab68f15..3be3602 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.h
+++ b/gpu/command_buffer/service/in_process_command_buffer.h
@@ -92,6 +92,7 @@
State GetLastState() override;
int32 GetLastToken() override;
void Flush(int32 put_offset) override;
+ void OrderingBarrier(int32 put_offset) override;
void WaitForTokenInRange(int32 start, int32 end) override;
void WaitForGetOffsetInRange(int32 start, int32 end) override;
void SetGetBuffer(int32 shm_id) override;
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.cc b/gpu/command_buffer/service/mailbox_manager_sync.cc
index b12e9b4..4f24bd7 100644
--- a/gpu/command_buffer/service/mailbox_manager_sync.cc
+++ b/gpu/command_buffer/service/mailbox_manager_sync.cc
@@ -59,7 +59,7 @@
sync_points.pop();
}
// Need to use EGL fences since we are likely not in a single share group.
- linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL(true)));
+ linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL));
if (fence.get()) {
std::pair<SyncPointToFenceMap::iterator, bool> result =
sync_point_to_fence.insert(std::make_pair(sync_point, fence));
diff --git a/gpu/command_buffer/service/memory_program_cache.cc b/gpu/command_buffer/service/memory_program_cache.cc
index 4bf16e3..1e8e11b 100644
--- a/gpu/command_buffer/service/memory_program_cache.cc
+++ b/gpu/command_buffer/service/memory_program_cache.cc
@@ -180,12 +180,12 @@
const ShaderCacheCallback& shader_callback) {
char a_sha[kHashLength];
char b_sha[kHashLength];
- DCHECK(shader_a && !shader_a->signature_source().empty() &&
- shader_b && !shader_b->signature_source().empty());
+ DCHECK(shader_a && !shader_a->last_compiled_source().empty() &&
+ shader_b && !shader_b->last_compiled_source().empty());
ComputeShaderHash(
- shader_a->signature_source(), translator_a, a_sha);
+ shader_a->last_compiled_source(), translator_a, a_sha);
ComputeShaderHash(
- shader_b->signature_source(), translator_b, b_sha);
+ shader_b->last_compiled_source(), translator_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
@@ -256,12 +256,12 @@
char a_sha[kHashLength];
char b_sha[kHashLength];
- DCHECK(shader_a && !shader_a->signature_source().empty() &&
- shader_b && !shader_b->signature_source().empty());
+ DCHECK(shader_a && !shader_a->last_compiled_source().empty() &&
+ shader_b && !shader_b->last_compiled_source().empty());
ComputeShaderHash(
- shader_a->signature_source(), translator_a, a_sha);
+ shader_a->last_compiled_source(), translator_a, a_sha);
ComputeShaderHash(
- shader_b->signature_source(), translator_b, b_sha);
+ shader_b->last_compiled_source(), translator_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
diff --git a/gpu/command_buffer/service/memory_program_cache_unittest.cc b/gpu/command_buffer/service/memory_program_cache_unittest.cc
index 7c39028..8f8c430 100644
--- a/gpu/command_buffer/service/memory_program_cache_unittest.cc
+++ b/gpu/command_buffer/service/memory_program_cache_unittest.cc
@@ -196,9 +196,9 @@
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->signature_source(),
+ vertex_shader_->last_compiled_source(),
NULL,
- fragment_shader_->signature_source(),
+ fragment_shader_->last_compiled_source(),
NULL,
NULL));
EXPECT_EQ(1, shader_cache_count());
@@ -221,9 +221,9 @@
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->signature_source(),
+ vertex_shader_->last_compiled_source(),
NULL,
- fragment_shader_->signature_source(),
+ fragment_shader_->last_compiled_source(),
NULL,
NULL));
EXPECT_EQ(1, shader_cache_count());
@@ -232,9 +232,9 @@
cache_->LoadProgram(shader_cache_shader());
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->signature_source(),
+ vertex_shader_->last_compiled_source(),
NULL,
- fragment_shader_->signature_source(),
+ fragment_shader_->last_compiled_source(),
NULL,
NULL));
}
@@ -396,7 +396,7 @@
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
- const std::string vertex_orig_source = vertex_shader_->signature_source();
+ const std::string vertex_orig_source = vertex_shader_->last_compiled_source();
vertex_shader_->set_source("different!");
TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true);
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
@@ -488,7 +488,7 @@
const GLuint kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1;
// save old source and modify for new program
- const std::string& old_source = fragment_shader_->signature_source();
+ const std::string& old_source = fragment_shader_->last_compiled_source();
fragment_shader_->set_source("al sdfkjdk");
TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
@@ -512,15 +512,15 @@
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->signature_source(),
+ vertex_shader_->last_compiled_source(),
NULL,
- fragment_shader_->signature_source(),
+ fragment_shader_->last_compiled_source(),
NULL,
NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus(
old_source,
NULL,
- fragment_shader_->signature_source(),
+ fragment_shader_->last_compiled_source(),
NULL,
NULL));
}
@@ -543,9 +543,9 @@
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->signature_source(),
+ vertex_shader_->last_compiled_source(),
NULL,
- fragment_shader_->signature_source(),
+ fragment_shader_->last_compiled_source(),
NULL,
NULL));
}
@@ -567,9 +567,9 @@
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->signature_source(),
+ vertex_shader_->last_compiled_source(),
NULL,
- fragment_shader_->signature_source(),
+ fragment_shader_->last_compiled_source(),
NULL,
NULL));
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index d866504..1f6b2d4 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -562,12 +562,12 @@
bool link = true;
ProgramCache* cache = manager_->program_cache_;
if (cache) {
- DCHECK(!attached_shaders_[0]->signature_source().empty() &&
- !attached_shaders_[1]->signature_source().empty());
+ DCHECK(!attached_shaders_[0]->last_compiled_source().empty() &&
+ !attached_shaders_[1]->last_compiled_source().empty());
ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
- attached_shaders_[0]->signature_source(),
+ attached_shaders_[0]->last_compiled_source(),
vertex_translator,
- attached_shaders_[1]->signature_source(),
+ attached_shaders_[1]->last_compiled_source(),
fragment_translator,
&bind_attrib_location_map_);
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc
index 2707b90..90b1576 100644
--- a/gpu/command_buffer/service/shader_manager.cc
+++ b/gpu/command_buffer/service/shader_manager.cc
@@ -26,6 +26,7 @@
Shader::Shader(GLuint service_id, GLenum shader_type)
: use_count_(0),
+ shader_state_(kShaderStateWaiting),
service_id_(service_id),
shader_type_(shader_type),
valid_(false) {
@@ -34,13 +35,28 @@
Shader::~Shader() {
}
+void Shader::RequestCompile() {
+ shader_state_ = kShaderStateCompileRequested;
+ last_compiled_source_ = source_;
+}
+
void Shader::DoCompile(ShaderTranslatorInterface* translator,
TranslatedShaderSourceType type) {
+ // We require that RequestCompile() must be called before DoCompile(),
+ // so we can return early if the shader state is not what we expect.
+ if (shader_state_ != kShaderStateCompileRequested) {
+ return;
+ }
+
+ // Signify the shader has been compiled, whether or not it is valid
+ // is dependent on the |valid_| member variable.
+ shader_state_ = kShaderStateCompiled;
+
// Translate GL ES 2.0 shader to Desktop GL shader and pass that to
// glShaderSource and then glCompileShader.
- const char* source_for_driver = source_.c_str();
+ const char* source_for_driver = last_compiled_source_.c_str();
if (translator) {
- valid_ = translator->Translate(source_,
+ valid_ = translator->Translate(last_compiled_source_,
&log_info_,
&translated_source_,
&attrib_map_,
@@ -50,7 +66,6 @@
if (!valid_) {
return;
}
- signature_source_ = source_;
source_for_driver = translated_source_.c_str();
}
@@ -61,13 +76,14 @@
glGetShaderiv(service_id_,
GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
&max_len);
- scoped_ptr<char[]> buffer(new char[max_len]);
+ translated_source_.resize(max_len);
GLint len = 0;
glGetTranslatedShaderSourceANGLE(
- service_id_, max_len, &len, buffer.get());
+ service_id_, translated_source_.size(),
+ &len, &translated_source_.at(0));
DCHECK(max_len == 0 || len < max_len);
- DCHECK(len == 0 || buffer[len] == '\0');
- translated_source_ = std::string(buffer.get(), len);
+ DCHECK(len == 0 || translated_source_[len] == '\0');
+ translated_source_.resize(len);
}
GLint status = GL_FALSE;
@@ -78,17 +94,17 @@
// All translated shaders must compile.
GLint max_len = 0;
glGetShaderiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
- scoped_ptr<char[]> buffer(new char[max_len]);
+ log_info_.resize(max_len);
GLint len = 0;
- glGetShaderInfoLog(service_id_, max_len, &len, buffer.get());
+ glGetShaderInfoLog(service_id_, log_info_.size(), &len, &log_info_.at(0));
DCHECK(max_len == 0 || len < max_len);
- DCHECK(len == 0 || buffer[len] == '\0');
+ DCHECK(len == 0 || log_info_[len] == '\0');
valid_ = false;
- log_info_ = std::string(buffer.get(), len);
+ log_info_.resize(len);
LOG_IF(ERROR, translator)
<< "Shader translator allowed/produced an invalid shader "
<< "unless the driver is buggy:"
- << "\n--original-shader--\n" << source_
+ << "\n--original-shader--\n" << last_compiled_source_
<< "\n--translated-shader--\n" << source_for_driver
<< "\n--info-log--\n" << log_info_;
}
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h
index c726767..11f567d 100644
--- a/gpu/command_buffer/service/shader_manager.h
+++ b/gpu/command_buffer/service/shader_manager.h
@@ -29,9 +29,21 @@
kGL, // GL or GLES
};
+ enum ShaderState {
+ kShaderStateWaiting,
+ kShaderStateCompileRequested,
+ kShaderStateCompiled, // Signifies compile happened, not valid compile.
+ };
+
+ void RequestCompile();
+
void DoCompile(ShaderTranslatorInterface* translator,
TranslatedShaderSourceType type);
+ ShaderState shader_state() const {
+ return shader_state_;
+ }
+
GLuint service_id() const {
return service_id_;
}
@@ -52,8 +64,8 @@
return translated_source_;
}
- const std::string& signature_source() const {
- return signature_source_;
+ const std::string& last_compiled_source() const {
+ return last_compiled_source_;
}
const sh::Attribute* GetAttribInfo(const std::string& name) const;
@@ -73,7 +85,7 @@
}
bool valid() const {
- return valid_;
+ return shader_state_ == kShaderStateCompiled && valid_;
}
bool IsDeleted() const {
@@ -131,8 +143,12 @@
int use_count_;
+ // The current state of the shader.
+ ShaderState shader_state_;
+
// The shader this Shader is tracking.
GLuint service_id_;
+
// Type of shader - GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
GLenum shader_type_;
@@ -143,7 +159,7 @@
std::string source_;
// The source the last compile used.
- std::string signature_source_;
+ std::string last_compiled_source_;
// The translated shader source.
std::string translated_source_;
diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc
index 4218d50..f5f6206 100644
--- a/gpu/command_buffer/service/shader_manager_unittest.cc
+++ b/gpu/command_buffer/service/shader_manager_unittest.cc
@@ -127,16 +127,30 @@
EXPECT_FALSE(shader1->InUse());
EXPECT_TRUE(shader1->source().empty());
EXPECT_TRUE(shader1->log_info().empty());
- EXPECT_TRUE(shader1->signature_source().empty());
+ EXPECT_TRUE(shader1->last_compiled_source().empty());
EXPECT_TRUE(shader1->translated_source().empty());
EXPECT_EQ(0u, shader1->attrib_map().size());
EXPECT_EQ(0u, shader1->uniform_map().size());
EXPECT_EQ(0u, shader1->varying_map().size());
+ EXPECT_EQ(Shader::kShaderStateWaiting, shader1->shader_state());
// Check we can set its source.
shader1->set_source(kClient1Source);
EXPECT_STREQ(kClient1Source, shader1->source().c_str());
- EXPECT_TRUE(shader1->signature_source().empty());
+ EXPECT_TRUE(shader1->last_compiled_source().empty());
+
+ // Check that DoCompile() will not work if RequestCompile() was not called.
+ MockShaderTranslator translator;
+ shader1->DoCompile(&translator, Shader::kANGLE);
+ EXPECT_EQ(Shader::kShaderStateWaiting, shader1->shader_state());
+ EXPECT_FALSE(shader1->valid());
+
+ // Check RequestCompile() will update the state and last compiled source, but
+ // still keep the actual compile state invalid.
+ shader1->RequestCompile();
+ EXPECT_EQ(Shader::kShaderStateCompileRequested, shader1->shader_state());
+ EXPECT_STREQ(kClient1Source, shader1->last_compiled_source().c_str());
+ EXPECT_FALSE(shader1->valid());
// Check DoCompile() will set compilation states, log, translated source,
// shader variables, and name mapping.
@@ -168,7 +182,7 @@
EXPECT_TRUE(shader1->valid());
// When compilation succeeds, no log is recorded.
EXPECT_STREQ("", shader1->log_info().c_str());
- EXPECT_STREQ(kClient1Source, shader1->signature_source().c_str());
+ EXPECT_STREQ(kClient1Source, shader1->last_compiled_source().c_str());
EXPECT_STREQ(kTranslatedSource.c_str(), shader1->translated_source().c_str());
// Check varying infos got copied.
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc
index 878490c..98d738d 100644
--- a/gpu/command_buffer/service/shader_translator.cc
+++ b/gpu/command_buffer/service/shader_translator.cc
@@ -123,7 +123,6 @@
compiler_ = ShConstructCompiler(
shader_type, shader_spec, shader_output, resources);
}
- compiler_options_ = *resources;
implementation_is_glsl_es_ = (glsl_implementation_type == kGlslES);
driver_bug_workarounds_ = driver_bug_workarounds;
return compiler_ != NULL;
diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h
index 6075896..ef25ebb 100644
--- a/gpu/command_buffer/service/shader_translator.h
+++ b/gpu/command_buffer/service/shader_translator.h
@@ -110,7 +110,6 @@
int GetCompileOptions() const;
ShHandle compiler_;
- ShBuiltInResources compiler_options_;
bool implementation_is_glsl_es_;
ShCompileOptions driver_bug_workarounds_;
ObserverList<DestructionObserver> destruction_observers_;
diff --git a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc
index 621e6a1..174edaa 100644
--- a/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc
+++ b/gpu/command_buffer/service/stream_texture_manager_in_process_android.cc
@@ -23,23 +23,23 @@
const base::Closure& release_callback);
// implement gfx::GLImage
- virtual void Destroy(bool have_context) override;
- virtual gfx::Size GetSize() override;
- virtual bool BindTexImage(unsigned target) override;
- virtual void ReleaseTexImage(unsigned target) override;
- virtual bool CopyTexImage(unsigned target) override;
- virtual void WillUseTexImage() override;
- virtual void DidUseTexImage() override {}
- virtual void WillModifyTexImage() override {}
- virtual void DidModifyTexImage() override {}
- virtual bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
- int z_order,
- gfx::OverlayTransform transform,
- const gfx::Rect& bounds_rect,
- const gfx::RectF& crop_rect) override;
+ void Destroy(bool have_context) override;
+ gfx::Size GetSize() override;
+ bool BindTexImage(unsigned target) override;
+ void ReleaseTexImage(unsigned target) override;
+ bool CopyTexImage(unsigned target) override;
+ void WillUseTexImage() override;
+ void DidUseTexImage() override {}
+ void WillModifyTexImage() override {}
+ void DidModifyTexImage() override {}
+ bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+ int z_order,
+ gfx::OverlayTransform transform,
+ const gfx::Rect& bounds_rect,
+ const gfx::RectF& crop_rect) override;
private:
- virtual ~GLImageImpl();
+ ~GLImageImpl() override;
scoped_refptr<gfx::SurfaceTexture> surface_texture_;
base::Closure release_callback_;
diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc
index 550e0cd..6cd0acf 100644
--- a/gpu/command_buffer/service/test_helper.cc
+++ b/gpu/command_buffer/service/test_helper.cc
@@ -790,6 +790,7 @@
.WillOnce(SetArgumentPointee<2>(GL_TRUE))
.RetiresOnSaturation();
}
+ shader->RequestCompile();
shader->DoCompile(&translator, Shader::kGL);
}
diff --git a/gpu/command_buffer/tests/gl_program_unittest.cc b/gpu/command_buffer/tests/gl_program_unittest.cc
index aec95b2..186b28b 100644
--- a/gpu/command_buffer/tests/gl_program_unittest.cc
+++ b/gpu/command_buffer/tests/gl_program_unittest.cc
@@ -121,6 +121,35 @@
GLTestHelper::CheckGLError("no errors", __LINE__);
}
+TEST_F(GLProgramTest, ShaderLengthSpecified) {
+ const std::string valid_shader_str = SHADER(
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+ );
+
+ const std::string invalid_shader = valid_shader_str + "invalid suffix";
+
+ // Compiling invalid program should fail.
+ const char* invalid_shader_strings[] = { invalid_shader.c_str() };
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, invalid_shader_strings, NULL);
+ glCompileShader(vs);
+
+ GLint compile_state = 0;
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_state);
+ EXPECT_EQ(GL_FALSE, compile_state);
+
+ // Compiling program cutting off invalid parts should succeed.
+ const GLint lengths[] = { valid_shader_str.length() };
+ glShaderSource(vs, 1, invalid_shader_strings, lengths);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_state);
+ EXPECT_EQ(GL_TRUE, compile_state);
+}
+
TEST_F(GLProgramTest, UniformsInCurrentProgram) {
static const char* v_shader_str = SHADER(
attribute vec4 a_position;
diff --git a/gpu/command_buffer/tests/gl_unittests_android.cc b/gpu/command_buffer/tests/gl_unittests_android.cc
index d3517a6..9bdd503 100644
--- a/gpu/command_buffer/tests/gl_unittests_android.cc
+++ b/gpu/command_buffer/tests/gl_unittests_android.cc
@@ -22,13 +22,9 @@
class GLSurfaceTextureTest : public testing::Test {
protected:
- virtual void SetUp() override {
- gl_.Initialize(GLManager::Options());
- }
+ void SetUp() override { gl_.Initialize(GLManager::Options()); }
- virtual void TearDown() override {
- gl_.Destroy();
- }
+ void TearDown() override { gl_.Destroy(); }
GLManager gl_;
};
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 26be952..382bcba 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@
{
"name": "gpu driver bug list",
// Please update the version number whenever you change this file.
- "version": "7.14",
+ "version": "7.15",
"entries": [
{
"id": 1,
@@ -1118,6 +1118,22 @@
"features": [
"use_non_zero_size_for_client_side_stream_buffers"
]
+ },
+ {
+ "id": 99,
+ "description": "Qualcomm driver before Lollipop deletes egl sync objects after context destruction",
+ "cr_bugs": [453857],
+ "os": {
+ "type": "android",
+ "version": {
+ "op": "<",
+ "value": "5.0.0"
+ }
+ },
+ "gl_vendor": "Qualcomm.*",
+ "features": [
+ "ignore_egl_sync_failures"
+ ]
}
]
}
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 77d721b..f03b7a2 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -58,6 +58,8 @@
gl_begin_gl_end_on_fbo_change_to_backbuffer) \
GPU_OP(GL_CLEAR_BROKEN, \
gl_clear_broken) \
+ GPU_OP(IGNORE_EGL_SYNC_FAILURES, \
+ ignore_egl_sync_failures) \
GPU_OP(INIT_GL_POSITION_IN_VERTEX_SHADER, \
init_gl_position_in_vertex_shader) \
GPU_OP(INIT_TEXTURE_MAX_ANISOTROPY, \
diff --git a/gpu/config/gpu_info_collector_win.cc b/gpu/config/gpu_info_collector_win.cc
index 04f66fa..a5686a9 100644
--- a/gpu/config/gpu_info_collector_win.cc
+++ b/gpu/config/gpu_info_collector_win.cc
@@ -8,6 +8,7 @@
#include "third_party/re2/re2/re2.h"
#include <windows.h>
+#include <cfgmgr32.h>
#include <d3d9.h>
#include <d3d11.h>
#include <dxgi.h>
@@ -363,6 +364,24 @@
base::Bind(CollectD3D11SupportOnWorkerThread),
false);
}
+
+void DeviceIDToVendorAndDevice(const std::wstring& id,
+ uint32* vendor_id,
+ uint32* device_id) {
+ *vendor_id = 0;
+ *device_id = 0;
+ if (id.length() < 21)
+ return;
+ base::string16 vendor_id_string = id.substr(8, 4);
+ base::string16 device_id_string = id.substr(17, 4);
+ int vendor = 0;
+ int device = 0;
+ base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor);
+ base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device);
+ *vendor_id = vendor;
+ *device_id = device;
+}
+
} // namespace anonymous
#if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD)
@@ -380,17 +399,35 @@
GPUInfo* gpu_info) {
TRACE_EVENT0("gpu", "CollectDriverInfoD3D");
+ // Display adapter class GUID from
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx
+ GUID display_class = {0x4d36e968,
+ 0xe325,
+ 0x11ce,
+ {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
+
// create device info for the display device
- HDEVINFO device_info = SetupDiGetClassDevsW(
- NULL, device_id.c_str(), NULL,
- DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
+ HDEVINFO device_info =
+ SetupDiGetClassDevsW(&display_class, NULL, NULL, DIGCF_PRESENT);
if (device_info == INVALID_HANDLE_VALUE) {
LOG(ERROR) << "Creating device info failed";
return kCollectInfoNonFatalFailure;
}
+ struct GPUDriver {
+ GPUInfo::GPUDevice device;
+ std::string driver_vendor;
+ std::string driver_version;
+ std::string driver_date;
+ };
+
+ std::vector<GPUDriver> drivers;
+
+ int primary_device = -1;
+ bool found_amd = false;
+ bool found_intel = false;
+
DWORD index = 0;
- bool found = false;
SP_DEVINFO_DATA device_info_data;
device_info_data.cbSize = sizeof(device_info_data);
while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) {
@@ -429,35 +466,85 @@
result = RegQueryValueExW(
key, L"ProviderName", NULL, NULL,
reinterpret_cast<LPBYTE>(value), &dwcb_data);
- if (result == ERROR_SUCCESS) {
+ if (result == ERROR_SUCCESS)
driver_vendor = base::UTF16ToASCII(std::wstring(value));
- if (driver_vendor == "Advanced Micro Devices, Inc." ||
- driver_vendor == "ATI Technologies Inc.") {
- // We are conservative and assume that in the absence of a clear
- // signal the videocard is assumed to be switchable. Additionally,
- // some switchable systems with Intel GPUs aren't correctly
- // detected, so always count them.
- GetAMDVideocardInfo(gpu_info);
- if (!gpu_info->amd_switchable &&
- gpu_info->gpu.vendor_id == 0x8086) {
- gpu_info->amd_switchable = true;
- gpu_info->secondary_gpus.push_back(gpu_info->gpu);
- gpu_info->gpu.vendor_id = 0x1002;
- gpu_info->gpu.device_id = 0; // Unknown discrete AMD GPU.
- }
- }
+
+ wchar_t new_device_id[MAX_DEVICE_ID_LEN];
+ CONFIGRET status = CM_Get_Device_ID(
+ device_info_data.DevInst, new_device_id, MAX_DEVICE_ID_LEN, 0);
+
+ if (status == CR_SUCCESS) {
+ GPUDriver driver;
+
+ driver.driver_vendor = driver_vendor;
+ driver.driver_version = driver_version;
+ driver.driver_date = driver_date;
+ std::wstring id = new_device_id;
+
+ if (id.compare(0, device_id.size(), device_id) == 0)
+ primary_device = drivers.size();
+
+ uint32 vendor_id = 0, device_id = 0;
+ DeviceIDToVendorAndDevice(id, &vendor_id, &device_id);
+ driver.device.vendor_id = vendor_id;
+ driver.device.device_id = device_id;
+ drivers.push_back(driver);
+
+ if (vendor_id == 0x8086)
+ found_intel = true;
+ if (vendor_id == 0x1002)
+ found_amd = true;
}
- gpu_info->driver_vendor = driver_vendor;
- gpu_info->driver_version = driver_version;
- gpu_info->driver_date = driver_date;
- found = true;
RegCloseKey(key);
- break;
}
}
}
SetupDiDestroyDeviceInfoList(device_info);
+ bool found = false;
+ if (found_amd && found_intel) {
+ // AMD Switchable system found.
+ for (const auto& driver : drivers) {
+ if (driver.device.vendor_id == 0x8086) {
+ gpu_info->gpu = driver.device;
+ }
+
+ if (driver.device.vendor_id == 0x1002) {
+ gpu_info->driver_vendor = driver.driver_vendor;
+ gpu_info->driver_version = driver.driver_version;
+ gpu_info->driver_date = driver.driver_date;
+ }
+ }
+ GetAMDVideocardInfo(gpu_info);
+
+ if (!gpu_info->amd_switchable) {
+ // Some machines aren't properly detected as AMD switchable, but count
+ // them anyway.
+ gpu_info->amd_switchable = true;
+ for (const auto& driver : drivers) {
+ if (driver.device.vendor_id == 0x1002) {
+ gpu_info->gpu = driver.device;
+ } else {
+ gpu_info->secondary_gpus.push_back(driver.device);
+ }
+ }
+ }
+ found = true;
+ } else {
+ for (size_t i = 0; i < drivers.size(); ++i) {
+ const GPUDriver& driver = drivers[i];
+ if (static_cast<int>(i) == primary_device) {
+ found = true;
+ gpu_info->gpu = driver.device;
+ gpu_info->driver_vendor = driver.driver_vendor;
+ gpu_info->driver_version = driver.driver_version;
+ gpu_info->driver_date = driver.driver_date;
+ } else {
+ gpu_info->secondary_gpus.push_back(driver.device);
+ }
+ }
+ }
+
return found ? kCollectInfoSuccess : kCollectInfoNonFatalFailure;
}
@@ -551,13 +638,7 @@
}
if (id.length() > 20) {
- int vendor = 0, device = 0;
- std::wstring vendor_string = id.substr(8, 4);
- std::wstring device_string = id.substr(17, 4);
- base::HexStringToInt(base::UTF16ToASCII(vendor_string), &vendor);
- base::HexStringToInt(base::UTF16ToASCII(device_string), &device);
- *vendor_id = vendor;
- *device_id = device;
+ DeviceIDToVendorAndDevice(id, vendor_id, device_id);
if (*vendor_id != 0 && *device_id != 0)
return kCollectInfoSuccess;
}
@@ -609,13 +690,8 @@
return kCollectInfoNonFatalFailure;
}
- int vendor_id = 0, device_id = 0;
- base::string16 vendor_id_string = id.substr(8, 4);
- base::string16 device_id_string = id.substr(17, 4);
- base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor_id);
- base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device_id);
- gpu_info->gpu.vendor_id = vendor_id;
- gpu_info->gpu.device_id = device_id;
+ DeviceIDToVendorAndDevice(id, &gpu_info->gpu.vendor_id,
+ &gpu_info->gpu.device_id);
// TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE.
if (!CollectDriverInfoD3D(id, gpu_info)) {
gpu_info->basic_info_state = kCollectInfoNonFatalFailure;
diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc
index b822056..93afd1a 100644
--- a/gpu/config/software_rendering_list_json.cc
+++ b/gpu/config/software_rendering_list_json.cc
@@ -18,7 +18,7 @@
{
"name": "software rendering list",
// Please update the version number whenever you change this file.
- "version": "9.16",
+ "version": "9.17",
"entries": [
{
"id": 1,
@@ -621,22 +621,6 @@
]
},
{
- "id": 62,
- "description": "Accelerated 2D canvas buggy on old Qualcomm Adreno",
- "cr_bugs": [161575],
- "os": {
- "type": "android"
- },
- "gl_renderer": ".*Adreno.*",
- "driver_version": {
- "op": "<",
- "value": "4.1"
- },
- "features": [
- "accelerated_2d_canvas"
- ]
- },
- {
"id": 64,
"description": "Hardware video decode is only supported in win7+",
"cr_bugs": [159458],
@@ -1035,7 +1019,7 @@
},
{
"id": 96,
- "description": "GPU rasterization whitelist",
+ "description": "Blacklist GPU raster/canvas on all except known good GPUs and newer Android releases",
"cr_bugs": [362779,424970],
"os": {
"type": "android"
@@ -1090,7 +1074,8 @@
}
],
"features": [
- "gpu_rasterization"
+ "gpu_rasterization",
+ "accelerated_2d_canvas"
]
},
{
@@ -1110,11 +1095,15 @@
},
{
"id": 100,
- "description": "GPU rasterization is blacklisted on Nexus 10",
+ "description": "GPU rasterization and canvas is blacklisted on Nexus 10",
"cr_bugs": [407144],
+ "os": {
+ "type": "android"
+ },
"gl_renderer": ".*Mali-T604.*",
"features": [
- "gpu_rasterization"
+ "gpu_rasterization",
+ "accelerated_2d_canvas"
]
},
{
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 138d858..73a1059 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -178,6 +178,7 @@
'command_buffer/client/fenced_allocator_test.cc',
'command_buffer/client/gles2_implementation_unittest.cc',
'command_buffer/client/mapped_memory_unittest.cc',
+ 'command_buffer/client/program_info_manager_unittest.cc',
'command_buffer/client/query_tracker_unittest.cc',
'command_buffer/client/ring_buffer_test.cc',
'command_buffer/client/transfer_buffer_unittest.cc',
diff --git a/gpu/gpu_unittests.isolate b/gpu/gpu_unittests.isolate
index 3380606..48fb1c5 100644
--- a/gpu/gpu_unittests.isolate
+++ b/gpu/gpu_unittests.isolate
@@ -21,6 +21,8 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
],
'files': [
'../testing/xvfb.py',
@@ -37,6 +39,8 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
],
},
}],
@@ -49,6 +53,8 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
],
},
}],
diff --git a/gpu/ipc/gpu_command_buffer_traits_multi.h b/gpu/ipc/gpu_command_buffer_traits_multi.h
index 8201f32..2f834a0 100644
--- a/gpu/ipc/gpu_command_buffer_traits_multi.h
+++ b/gpu/ipc/gpu_command_buffer_traits_multi.h
@@ -42,6 +42,9 @@
IPC_STRUCT_TRAITS_MEMBER(num_compressed_texture_formats)
IPC_STRUCT_TRAITS_MEMBER(num_shader_binary_formats)
IPC_STRUCT_TRAITS_MEMBER(bind_generates_resource_chromium)
+ IPC_STRUCT_TRAITS_MEMBER(max_transform_feedback_separate_attribs)
+ IPC_STRUCT_TRAITS_MEMBER(max_uniform_buffer_bindings)
+ IPC_STRUCT_TRAITS_MEMBER(uniform_buffer_offset_alignment)
IPC_STRUCT_TRAITS_MEMBER(post_sub_buffer)
IPC_STRUCT_TRAITS_MEMBER(egl_image_external)
IPC_STRUCT_TRAITS_MEMBER(texture_format_bgra8888)
diff --git a/mojo/common/trace_controller_impl.cc b/mojo/common/trace_controller_impl.cc
index 098dfb3..4409b30 100644
--- a/mojo/common/trace_controller_impl.cc
+++ b/mojo/common/trace_controller_impl.cc
@@ -4,7 +4,7 @@
#include "mojo/common/trace_controller_impl.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/application/application_connection.h"
#include "mojo/public/cpp/application/application_impl.h"
diff --git a/mojo/common/tracing_impl.cc b/mojo/common/tracing_impl.cc
index 9c4c276..3ef474c 100644
--- a/mojo/common/tracing_impl.cc
+++ b/mojo/common/tracing_impl.cc
@@ -4,7 +4,7 @@
#include "mojo/common/tracing_impl.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
#include "mojo/common/trace_controller_impl.h"
#include "mojo/public/cpp/application/application_connection.h"
#include "mojo/public/cpp/application/application_impl.h"
diff --git a/mojo/gles2/command_buffer_client_impl.cc b/mojo/gles2/command_buffer_client_impl.cc
index e8d3690..494ff3d 100644
--- a/mojo/gles2/command_buffer_client_impl.cc
+++ b/mojo/gles2/command_buffer_client_impl.cc
@@ -180,6 +180,11 @@
command_buffer_->Flush(put_offset);
}
+void CommandBufferClientImpl::OrderingBarrier(int32_t put_offset) {
+ // TODO(jamesr): Implement this more efficiently.
+ Flush(put_offset);
+}
+
void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
TryUpdateState();
while (!InRange(start, end, last_state_.token) &&
diff --git a/mojo/gles2/command_buffer_client_impl.h b/mojo/gles2/command_buffer_client_impl.h
index dcedb52..6bcacb2 100644
--- a/mojo/gles2/command_buffer_client_impl.h
+++ b/mojo/gles2/command_buffer_client_impl.h
@@ -42,14 +42,15 @@
// CommandBuffer implementation:
bool Initialize() override;
State GetLastState() override;
- int32 GetLastToken() override;
- void Flush(int32 put_offset) override;
- void WaitForTokenInRange(int32 start, int32 end) override;
- void WaitForGetOffsetInRange(int32 start, int32 end) override;
- void SetGetBuffer(int32 shm_id) override;
+ int32_t GetLastToken() override;
+ void Flush(int32_t put_offset) override;
+ void OrderingBarrier(int32_t put_offset) override;
+ void WaitForTokenInRange(int32_t start, int32_t end) override;
+ void WaitForGetOffsetInRange(int32_t start, int32_t end) override;
+ void SetGetBuffer(int32_t shm_id) override;
scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
- int32* id) override;
- void DestroyTransferBuffer(int32 id) override;
+ int32_t* id) override;
+ void DestroyTransferBuffer(int32_t id) override;
// gpu::GpuControl implementation:
gpu::Capabilities GetCapabilities() override;
@@ -96,8 +97,8 @@
State last_state_;
mojo::ScopedSharedBufferHandle shared_state_handle_;
gpu::CommandBufferSharedState* shared_state_;
- int32 last_put_offset_;
- int32 next_transfer_buffer_id_;
+ int32_t last_put_offset_;
+ int32_t next_transfer_buffer_id_;
const MojoAsyncWaiter* async_waiter_;
};
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc
index 0a109b8..d1ad338 100644
--- a/net/android/network_change_notifier_android.cc
+++ b/net/android/network_change_notifier_android.cc
@@ -77,20 +77,16 @@
// We're only interested in tunnel interface changes.
base::Bind(NotifyNetworkChangeNotifierObservers)) {}
- virtual ~DnsConfigServiceThread() {
- Stop();
- }
+ ~DnsConfigServiceThread() override { Stop(); }
- virtual void Init() override {
+ void Init() override {
address_tracker_.Init();
dns_config_service_ = DnsConfigService::CreateSystemService();
dns_config_service_->WatchConfig(
base::Bind(&NetworkChangeNotifier::SetDnsConfig));
}
- virtual void CleanUp() override {
- dns_config_service_.reset();
- }
+ void CleanUp() override { dns_config_service_.reset(); }
static void NotifyNetworkChangeNotifierObservers() {
NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
diff --git a/net/android/network_change_notifier_android.h b/net/android/network_change_notifier_android.h
index 0d90a56..f6d43d0 100644
--- a/net/android/network_change_notifier_android.h
+++ b/net/android/network_change_notifier_android.h
@@ -42,17 +42,17 @@
: public NetworkChangeNotifier,
public NetworkChangeNotifierDelegateAndroid::Observer {
public:
- virtual ~NetworkChangeNotifierAndroid();
+ ~NetworkChangeNotifierAndroid() override;
// NetworkChangeNotifier:
- virtual ConnectionType GetCurrentConnectionType() const override;
+ ConnectionType GetCurrentConnectionType() const override;
// Requires ACCESS_WIFI_STATE permission in order to provide precise WiFi link
// speed.
- virtual double GetCurrentMaxBandwidth() const override;
+ double GetCurrentMaxBandwidth() const override;
// NetworkChangeNotifierDelegateAndroid::Observer:
- virtual void OnConnectionTypeChanged() override;
- virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps) override;
+ void OnConnectionTypeChanged() override;
+ void OnMaxBandwidthChanged(double max_bandwidth_mbps) override;
static bool Register(JNIEnv* env);
diff --git a/net/android/network_change_notifier_android_unittest.cc b/net/android/network_change_notifier_android_unittest.cc
index 54e5583..83dd70e 100644
--- a/net/android/network_change_notifier_android_unittest.cc
+++ b/net/android/network_change_notifier_android_unittest.cc
@@ -25,11 +25,9 @@
: type_notifications_count_(0), max_bandwidth_notifications_count_(0) {}
// NetworkChangeNotifierDelegateAndroid::Observer:
- virtual void OnConnectionTypeChanged() override {
- type_notifications_count_++;
- }
+ void OnConnectionTypeChanged() override { type_notifications_count_++; }
- virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps) override {
+ void OnMaxBandwidthChanged(double max_bandwidth_mbps) override {
max_bandwidth_notifications_count_++;
}
@@ -49,7 +47,7 @@
NetworkChangeNotifierObserver() : notifications_count_(0) {}
// NetworkChangeNotifier::Observer:
- virtual void OnConnectionTypeChanged(
+ void OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType connection_type) override {
notifications_count_++;
}
@@ -68,7 +66,7 @@
protected:
typedef NetworkChangeNotifier::ConnectionType ConnectionType;
- virtual ~BaseNetworkChangeNotifierAndroidTest() {}
+ ~BaseNetworkChangeNotifierAndroidTest() override {}
void RunTest(
const base::Callback<int(void)>& notifications_count_getter,
@@ -148,7 +146,7 @@
delegate_.AddObserver(&other_delegate_observer_);
}
- virtual ~NetworkChangeNotifierDelegateAndroidTest() {
+ ~NetworkChangeNotifierDelegateAndroidTest() override {
delegate_.RemoveObserver(&delegate_observer_);
delegate_.RemoveObserver(&other_delegate_observer_);
}
diff --git a/net/android/network_change_notifier_factory_android.h b/net/android/network_change_notifier_factory_android.h
index d443fcd..035a84e 100644
--- a/net/android/network_change_notifier_factory_android.h
+++ b/net/android/network_change_notifier_factory_android.h
@@ -26,10 +26,10 @@
NetworkChangeNotifierFactoryAndroid();
// Must be called on the JNI thread.
- virtual ~NetworkChangeNotifierFactoryAndroid();
+ ~NetworkChangeNotifierFactoryAndroid() override;
// NetworkChangeNotifierFactory:
- virtual NetworkChangeNotifier* CreateInstance() override;
+ NetworkChangeNotifier* CreateInstance() override;
private:
// Delegate passed to the instances created by this class.
diff --git a/net/base/file_stream_context.cc b/net/base/file_stream_context.cc
index 5acaab6..fc2af1b 100644
--- a/net/base/file_stream_context.cc
+++ b/net/base/file_stream_context.cc
@@ -77,6 +77,12 @@
orphaned_ = true;
+#if defined(OS_WIN)
+ // Clean up weak pointers here to ensure that they are destroyed on the
+ // same thread where they were created.
+ weak_ptr_factory_.InvalidateWeakPtrs();
+#endif
+
if (!async_in_progress_) {
CloseAndDelete();
} else if (file_.IsValid()) {
diff --git a/net/base/file_stream_context.h b/net/base/file_stream_context.h
index 82a2412..4f01d9d 100644
--- a/net/base/file_stream_context.h
+++ b/net/base/file_stream_context.h
@@ -28,6 +28,7 @@
#define NET_BASE_FILE_STREAM_CONTEXT_H_
#include "base/files/file.h"
+#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/move.h"
#include "base/task_runner.h"
@@ -159,6 +160,35 @@
virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
DWORD bytes_read,
DWORD error) override;
+
+ // The ReadFile call on Windows can execute synchonously at times.
+ // http://support.microsoft.com/kb/156932. This ends up blocking the calling
+ // thread which is undesirable. To avoid this we execute the ReadFile call
+ // on a worker thread.
+ // The |context| parameter is a weak pointer instance passed to the worker
+ // pool.
+ // The |file| parameter is the handle to the file being read.
+ // The |buf| parameter is the buffer where we want the ReadFile to read the
+ // data into.
+ // The |buf_len| parameter contains the number of bytes to be read.
+ // The |overlapped| parameter is a pointer to the OVERLAPPED structure being
+ // used.
+ // The |origin_thread_loop| is a MessageLoopProxy instance used to post tasks
+ // back to the originating thread.
+ static void ReadAsync(
+ const base::WeakPtr<FileStream::Context>& context,
+ HANDLE file,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ OVERLAPPED* overlapped,
+ scoped_refptr<base::MessageLoopProxy> origin_thread_loop);
+
+ // This callback executes on the main calling thread. It informs the caller
+ // about the result of the ReadFile call.
+ // The |os_error| parameter contains the value of the last error returned by
+ // the ReadFile API.
+ void ReadAsyncResult(DWORD os_error);
+
#elif defined(OS_POSIX)
// ReadFileImpl() is a simple wrapper around read() that handles EINTR
// signals and calls RecordAndMapError() to map errno to net error codes.
@@ -179,6 +209,8 @@
base::MessageLoopForIO::IOContext io_context_;
CompletionCallback callback_;
scoped_refptr<IOBuffer> in_flight_buf_;
+ // WeakPtrFactory for posting tasks back to |this|.
+ base::WeakPtrFactory<Context> weak_ptr_factory_;
#endif
DISALLOW_COPY_AND_ASSIGN(Context);
diff --git a/net/base/file_stream_context_win.cc b/net/base/file_stream_context_win.cc
index 85a5968..d225ee3 100644
--- a/net/base/file_stream_context_win.cc
+++ b/net/base/file_stream_context_win.cc
@@ -8,9 +8,12 @@
#include "base/files/file_path.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/profiler/scoped_tracker.h"
#include "base/task_runner.h"
+#include "base/threading/worker_pool.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -37,7 +40,8 @@
: io_context_(),
async_in_progress_(false),
orphaned_(false),
- task_runner_(task_runner) {
+ task_runner_(task_runner),
+ weak_ptr_factory_(this) {
io_context_.handler = this;
memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
}
@@ -48,7 +52,8 @@
file_(file.Pass()),
async_in_progress_(false),
orphaned_(false),
- task_runner_(task_runner) {
+ task_runner_(task_runner),
+ weak_ptr_factory_(this) {
io_context_.handler = this;
memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
if (file_.IsValid()) {
@@ -69,20 +74,16 @@
DCHECK(!async_in_progress_);
- DWORD bytes_read;
- if (!ReadFile(file_.GetPlatformFile(), buf->data(), buf_len,
- &bytes_read, &io_context_.overlapped)) {
- IOResult error = IOResult::FromOSError(GetLastError());
- if (error.os_error == ERROR_HANDLE_EOF)
- return 0; // Report EOF by returning 0 bytes read.
- if (error.os_error == ERROR_IO_PENDING)
- IOCompletionIsPending(callback, buf);
- else
- LOG(WARNING) << "ReadFile failed: " << error.os_error;
- return static_cast<int>(error.result);
- }
-
IOCompletionIsPending(callback, buf);
+
+ base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&FileStream::Context::ReadAsync,
+ weak_ptr_factory_.GetWeakPtr(), file_.GetPlatformFile(),
+ make_scoped_refptr(buf), buf_len, &io_context_.overlapped,
+ base::MessageLoop::current()->message_loop_proxy()),
+ false);
+
return ERR_IO_PENDING;
}
@@ -165,4 +166,34 @@
temp_callback.Run(result);
}
+// static
+void FileStream::Context::ReadAsync(
+ const base::WeakPtr<FileStream::Context>& context,
+ HANDLE file,
+ scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ OVERLAPPED* overlapped,
+ scoped_refptr<base::MessageLoopProxy> origin_thread_loop) {
+ DWORD bytes_read = 0;
+ if (!ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped)) {
+ origin_thread_loop->PostTask(
+ FROM_HERE, base::Bind(&FileStream::Context::ReadAsyncResult, context,
+ ::GetLastError()));
+ }
+}
+
+void FileStream::Context::ReadAsyncResult(DWORD os_error) {
+ IOResult error = IOResult::FromOSError(os_error);
+ if (error.os_error == ERROR_HANDLE_EOF) {
+ // Report EOF by returning 0 bytes read.
+ OnIOCompleted(&io_context_, 0, error.os_error);
+ } else if (error.os_error != ERROR_IO_PENDING) {
+ // We don't need to inform the caller about ERROR_PENDING_IO as that was
+ // already done when the ReadFile call was queued to the worker pool.
+ if (error.os_error)
+ LOG(WARNING) << "ReadFile failed: " << error.os_error;
+ OnIOCompleted(&io_context_, 0, error.os_error);
+ }
+}
+
} // namespace net
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc
index fc9257e..8b47ecc 100644
--- a/net/base/file_stream_unittest.cc
+++ b/net/base/file_stream_unittest.cc
@@ -546,6 +546,25 @@
const CompletionCallback& callback() const { return callback_; }
+ void ValidateWrittenData() {
+ TestCompletionCallback callback;
+ int rv = 0;
+ for (;;) {
+ scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
+ rv = stream_->Read(buf.get(), buf->size(), callback.callback());
+ if (rv == ERR_IO_PENDING) {
+ base::MessageLoop::ScopedNestableTaskAllower allow(
+ base::MessageLoop::current());
+ rv = callback.WaitForResult();
+ }
+ EXPECT_LE(0, rv);
+ if (rv <= 0)
+ break;
+ *total_bytes_read_ += rv;
+ data_read_->append(buf->data(), rv);
+ }
+ }
+
private:
void OnComplete(int result) {
DCHECK_LT(0, result);
@@ -577,22 +596,6 @@
base::MessageLoop::current());
EXPECT_LE(0, callback64.WaitForResult());
}
-
- TestCompletionCallback callback;
- for (;;) {
- scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
- rv = stream_->Read(buf.get(), buf->size(), callback.callback());
- if (rv == ERR_IO_PENDING) {
- base::MessageLoop::ScopedNestableTaskAllower allow(
- base::MessageLoop::current());
- rv = callback.WaitForResult();
- }
- EXPECT_LE(0, rv);
- if (rv <= 0)
- break;
- *total_bytes_read_ += rv;
- data_read_->append(buf->data(), rv);
- }
}
result_ = *total_bytes_written_;
@@ -646,6 +649,8 @@
EXPECT_LT(0, rv);
EXPECT_EQ(kTestDataSize, total_bytes_written);
+ callback.ValidateWrittenData();
+
stream.reset();
EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
diff --git a/net/base/filename_util_unittest.cc b/net/base/filename_util_unittest.cc
index 9d91fb7..4a8c4b5 100644
--- a/net/base/filename_util_unittest.cc
+++ b/net/base/filename_util_unittest.cc
@@ -116,48 +116,56 @@
};
static const base::FilePath::CharType* kSafePortableRelativePaths[] = {
- FILE_PATH_LITERAL("a/a"),
+ FILE_PATH_LITERAL("a/a"),
#if defined(OS_WIN)
- FILE_PATH_LITERAL("a\\a"),
+ FILE_PATH_LITERAL("a\\a"),
#endif
};
TEST(FilenameUtilTest, IsSafePortablePathComponent) {
- for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
- EXPECT_TRUE(IsSafePortablePathComponent(base::FilePath(
- kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
+ for (size_t i = 0; i < arraysize(kSafePortableBasenames); ++i) {
+ EXPECT_TRUE(
+ IsSafePortablePathComponent(base::FilePath(kSafePortableBasenames[i])))
+ << kSafePortableBasenames[i];
}
- for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
- EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath(
- kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
+ for (size_t i = 0; i < arraysize(kUnsafePortableBasenames); ++i) {
+ EXPECT_FALSE(IsSafePortablePathComponent(
+ base::FilePath(kUnsafePortableBasenames[i])))
+ << kUnsafePortableBasenames[i];
}
- for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
- EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath(
- kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
+ for (size_t i = 0; i < arraysize(kSafePortableRelativePaths); ++i) {
+ EXPECT_FALSE(IsSafePortablePathComponent(
+ base::FilePath(kSafePortableRelativePaths[i])))
+ << kSafePortableRelativePaths[i];
}
}
TEST(FilenameUtilTest, IsSafePortableRelativePath) {
base::FilePath safe_dirname(FILE_PATH_LITERAL("a"));
- for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
- EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
- kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
- EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
- kSafePortableBasenames[i])))) << kSafePortableBasenames[i];
+ for (size_t i = 0; i < arraysize(kSafePortableBasenames); ++i) {
+ EXPECT_TRUE(
+ IsSafePortableRelativePath(base::FilePath(kSafePortableBasenames[i])))
+ << kSafePortableBasenames[i];
+ EXPECT_TRUE(IsSafePortableRelativePath(
+ safe_dirname.Append(base::FilePath(kSafePortableBasenames[i]))))
+ << kSafePortableBasenames[i];
}
- for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
- EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
- kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
- EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
- kSafePortableRelativePaths[i])))) << kSafePortableRelativePaths[i];
+ for (size_t i = 0; i < arraysize(kSafePortableRelativePaths); ++i) {
+ EXPECT_TRUE(IsSafePortableRelativePath(
+ base::FilePath(kSafePortableRelativePaths[i])))
+ << kSafePortableRelativePaths[i];
+ EXPECT_TRUE(IsSafePortableRelativePath(
+ safe_dirname.Append(base::FilePath(kSafePortableRelativePaths[i]))))
+ << kSafePortableRelativePaths[i];
}
- for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
- EXPECT_FALSE(IsSafePortableRelativePath(base::FilePath(
- kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
- if (!base::FilePath::StringType(kUnsafePortableBasenames[i]).empty()) {
- EXPECT_FALSE(IsSafePortableRelativePath(safe_dirname.Append(
- base::FilePath(kUnsafePortableBasenames[i]))))
+ for (size_t i = 0; i < arraysize(kUnsafePortableBasenames); ++i) {
+ EXPECT_FALSE(
+ IsSafePortableRelativePath(base::FilePath(kUnsafePortableBasenames[i])))
<< kUnsafePortableBasenames[i];
+ if (!base::FilePath::StringType(kUnsafePortableBasenames[i]).empty()) {
+ EXPECT_FALSE(IsSafePortableRelativePath(
+ safe_dirname.Append(base::FilePath(kUnsafePortableBasenames[i]))))
+ << kUnsafePortableBasenames[i];
}
}
}
@@ -168,19 +176,18 @@
#if defined(OS_WIN)
{L"C:\\foo\\bar.txt", "file:///C:/foo/bar.txt"},
{L"\\\\some computer\\foo\\bar.txt",
- "file://some%20computer/foo/bar.txt"}, // UNC
+ "file://some%20computer/foo/bar.txt"}, // UNC
{L"D:\\Name;with%some symbols*#",
"file:///D:/Name%3Bwith%25some%20symbols*%23"},
// issue 14153: To be tested with the OS default codepage other than 1252.
{L"D:\\latin1\\caf\x00E9\x00DD.txt",
"file:///D:/latin1/caf%C3%A9%C3%9D.txt"},
- {L"D:\\otherlatin\\caf\x0119.txt",
- "file:///D:/otherlatin/caf%C4%99.txt"},
+ {L"D:\\otherlatin\\caf\x0119.txt", "file:///D:/otherlatin/caf%C4%99.txt"},
{L"D:\\greek\\\x03B1\x03B2\x03B3.txt",
"file:///D:/greek/%CE%B1%CE%B2%CE%B3.txt"},
{L"D:\\Chinese\\\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
"file:///D:/Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD%91"
- "%E9%A1%B5.doc"},
+ "%E9%A1%B5.doc"},
{L"D:\\plane1\\\xD835\xDC00\xD835\xDC01.txt", // Math alphabet "AB"
"file:///D:/plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
#elif defined(OS_POSIX)
@@ -195,7 +202,7 @@
{L"/greek/\x03B1\x03B2\x03B3.txt", "file:///greek/%CE%B1%CE%B2%CE%B3.txt"},
{L"/Chinese/\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
"file:///Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD"
- "%91%E9%A1%B5.doc"},
+ "%91%E9%A1%B5.doc"},
{L"/plane1/\x1D400\x1D401.txt", // Math alphabet "AB"
"file:///plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
#endif
@@ -205,8 +212,8 @@
base::FilePath output;
for (size_t i = 0; i < arraysize(round_trip_cases); i++) {
// convert to the file URL
- GURL file_url(FilePathToFileURL(
- WStringAsFilePath(round_trip_cases[i].file)));
+ GURL file_url(
+ FilePathToFileURL(WStringAsFilePath(round_trip_cases[i].file)));
EXPECT_EQ(round_trip_cases[i].url, file_url.spec());
// Back to the filename.
@@ -239,13 +246,13 @@
{L"/foo/bar.txt", "file:////foo////bar.txt"},
{L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
{L"/c:/foo/bar.txt", "file:c:/foo/bar.txt"},
- // We get these wrong because GURL turns back slashes into forward
- // slashes.
- //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
- //{L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"},
- //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
- //{L"/foo%5Cbar.txt", "file:////foo\\bar.txt"},
- //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
+// We get these wrong because GURL turns back slashes into forward
+// slashes.
+// {L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
+// {L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"},
+// {L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
+// {L"/foo%5Cbar.txt", "file:////foo\\bar.txt"},
+// {L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
#endif
};
for (size_t i = 0; i < arraysize(url_cases); i++) {
@@ -253,14 +260,13 @@
EXPECT_EQ(url_cases[i].file, FilePathAsWString(output));
}
- // Unfortunately, UTF8ToWide discards invalid UTF8 input.
+// Unfortunately, UTF8ToWide discards invalid UTF8 input.
#ifdef BUG_878908_IS_FIXED
// Test that no conversion happens if the UTF-8 input is invalid, and that
// the input is preserved in UTF-8
const char invalid_utf8[] = "file:///d:/Blah/\xff.doc";
const wchar_t invalid_wide[] = L"D:\\Blah\\\xff.doc";
- EXPECT_TRUE(FileURLToFilePath(
- GURL(std::string(invalid_utf8)), &output));
+ EXPECT_TRUE(FileURLToFilePath(GURL(std::string(invalid_utf8)), &output));
EXPECT_EQ(std::wstring(invalid_wide), output);
#endif
@@ -288,144 +294,88 @@
const base::FilePath::CharType* expected_filename;
} safe_tests[] = {
#if defined(OS_WIN)
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
- FILE_PATH_LITERAL("C:\\foo\\bar.htm")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\bar.html"),
- FILE_PATH_LITERAL("C:\\foo\\bar.html")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\bar"),
- FILE_PATH_LITERAL("C:\\foo\\bar.htm")
- },
- {
- "image/png",
- FILE_PATH_LITERAL("C:\\bar.html"),
- FILE_PATH_LITERAL("C:\\bar.html")
- },
- {
- "image/png",
- FILE_PATH_LITERAL("C:\\bar"),
- FILE_PATH_LITERAL("C:\\bar.png")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
- FILE_PATH_LITERAL("C:\\foo\\bar.exe")
- },
- {
- "image/gif",
- FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
- FILE_PATH_LITERAL("C:\\foo\\bar.exe")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\google.com"),
- FILE_PATH_LITERAL("C:\\foo\\google.com")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\con.htm"),
- FILE_PATH_LITERAL("C:\\foo\\_con.htm")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\con"),
- FILE_PATH_LITERAL("C:\\foo\\_con.htm")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"),
- FILE_PATH_LITERAL("C:\\foo\\harmless.download")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\harmless.local"),
- FILE_PATH_LITERAL("C:\\foo\\harmless.download")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"),
- FILE_PATH_LITERAL("C:\\foo\\harmless.download")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"),
- FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-")
- },
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
+ FILE_PATH_LITERAL("C:\\foo\\bar.htm")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\bar.html"),
+ FILE_PATH_LITERAL("C:\\foo\\bar.html")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\bar"),
+ FILE_PATH_LITERAL("C:\\foo\\bar.htm")},
+ {"image/png",
+ FILE_PATH_LITERAL("C:\\bar.html"),
+ FILE_PATH_LITERAL("C:\\bar.html")},
+ {"image/png",
+ FILE_PATH_LITERAL("C:\\bar"),
+ FILE_PATH_LITERAL("C:\\bar.png")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
+ FILE_PATH_LITERAL("C:\\foo\\bar.exe")},
+ {"image/gif",
+ FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
+ FILE_PATH_LITERAL("C:\\foo\\bar.exe")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\google.com"),
+ FILE_PATH_LITERAL("C:\\foo\\google.com")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\con.htm"),
+ FILE_PATH_LITERAL("C:\\foo\\_con.htm")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\con"),
+ FILE_PATH_LITERAL("C:\\foo\\_con.htm")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"),
+ FILE_PATH_LITERAL("C:\\foo\\harmless.download")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\harmless.local"),
+ FILE_PATH_LITERAL("C:\\foo\\harmless.download")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"),
+ FILE_PATH_LITERAL("C:\\foo\\harmless.download")},
+ {"text/html",
+ FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"),
+ FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-")},
// Allow extension synonyms.
- {
- "image/jpeg",
- FILE_PATH_LITERAL("C:\\foo\\bar.jpg"),
- FILE_PATH_LITERAL("C:\\foo\\bar.jpg")
- },
- {
- "image/jpeg",
- FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"),
- FILE_PATH_LITERAL("C:\\foo\\bar.jpeg")
- },
-#else // !defined(OS_WIN)
- {
- "text/html",
- FILE_PATH_LITERAL("/foo/bar.htm"),
- FILE_PATH_LITERAL("/foo/bar.htm")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("/foo/bar.html"),
- FILE_PATH_LITERAL("/foo/bar.html")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("/foo/bar"),
- FILE_PATH_LITERAL("/foo/bar.html")
- },
- {
- "image/png",
- FILE_PATH_LITERAL("/bar.html"),
- FILE_PATH_LITERAL("/bar.html")
- },
- {
- "image/png",
- FILE_PATH_LITERAL("/bar"),
- FILE_PATH_LITERAL("/bar.png")
- },
- {
- "image/gif",
- FILE_PATH_LITERAL("/foo/bar.exe"),
- FILE_PATH_LITERAL("/foo/bar.exe")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("/foo/google.com"),
- FILE_PATH_LITERAL("/foo/google.com")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("/foo/con.htm"),
- FILE_PATH_LITERAL("/foo/con.htm")
- },
- {
- "text/html",
- FILE_PATH_LITERAL("/foo/con"),
- FILE_PATH_LITERAL("/foo/con.html")
- },
+ {"image/jpeg",
+ FILE_PATH_LITERAL("C:\\foo\\bar.jpg"),
+ FILE_PATH_LITERAL("C:\\foo\\bar.jpg")},
+ {"image/jpeg",
+ FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"),
+ FILE_PATH_LITERAL("C:\\foo\\bar.jpeg")},
+#else // !defined(OS_WIN)
+ {"text/html",
+ FILE_PATH_LITERAL("/foo/bar.htm"),
+ FILE_PATH_LITERAL("/foo/bar.htm")},
+ {"text/html",
+ FILE_PATH_LITERAL("/foo/bar.html"),
+ FILE_PATH_LITERAL("/foo/bar.html")},
+ {"text/html",
+ FILE_PATH_LITERAL("/foo/bar"),
+ FILE_PATH_LITERAL("/foo/bar.html")},
+ {"image/png",
+ FILE_PATH_LITERAL("/bar.html"),
+ FILE_PATH_LITERAL("/bar.html")},
+ {"image/png", FILE_PATH_LITERAL("/bar"), FILE_PATH_LITERAL("/bar.png")},
+ {"image/gif",
+ FILE_PATH_LITERAL("/foo/bar.exe"),
+ FILE_PATH_LITERAL("/foo/bar.exe")},
+ {"text/html",
+ FILE_PATH_LITERAL("/foo/google.com"),
+ FILE_PATH_LITERAL("/foo/google.com")},
+ {"text/html",
+ FILE_PATH_LITERAL("/foo/con.htm"),
+ FILE_PATH_LITERAL("/foo/con.htm")},
+ {"text/html",
+ FILE_PATH_LITERAL("/foo/con"),
+ FILE_PATH_LITERAL("/foo/con.html")},
// Allow extension synonyms.
- {
- "image/jpeg",
- FILE_PATH_LITERAL("/bar.jpg"),
- FILE_PATH_LITERAL("/bar.jpg")
- },
- {
- "image/jpeg",
- FILE_PATH_LITERAL("/bar.jpeg"),
- FILE_PATH_LITERAL("/bar.jpeg")
- },
+ {"image/jpeg",
+ FILE_PATH_LITERAL("/bar.jpg"),
+ FILE_PATH_LITERAL("/bar.jpg")},
+ {"image/jpeg",
+ FILE_PATH_LITERAL("/bar.jpeg"),
+ FILE_PATH_LITERAL("/bar.jpeg")},
#endif // !defined(OS_WIN)
};
@@ -442,392 +392,287 @@
// parameters and that Content-Disposition headers are properly
// handled including failovers when the header is malformed.
const GenerateFilenameCase selection_tests[] = {
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename=test.html",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename=\"test.html\"",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename= \"test.html\"",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename = \"test.html\"",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
- { // filename is whitespace. Should failover to URL host
- __LINE__,
- "http://www.google.com/",
- "attachment; filename= ",
- "",
- "",
- "",
- L"",
- L"www.google.com"
- },
- { // No filename.
- __LINE__,
- "http://www.google.com/path/test.html",
- "attachment",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
- { // Ditto
- __LINE__,
- "http://www.google.com/path/test.html",
- "attachment;",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
- { // No C-D
- __LINE__,
- "http://www.google.com/",
- "",
- "",
- "",
- "",
- L"",
- L"www.google.com"
- },
- {
- __LINE__,
- "http://www.google.com/test.html",
- "",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
- { // Now that we use src/url's ExtractFileName, this case falls back to
- // the hostname. If this behavior is not desirable, we'd better change
- // ExtractFileName (in url_parse.cc).
- __LINE__,
- "http://www.google.com/path/",
- "",
- "",
- "",
- "",
- L"",
- L"www.google.com"
- },
- {
- __LINE__,
- "http://www.google.com/path",
- "",
- "",
- "",
- "",
- L"",
- L"path"
- },
- {
- __LINE__,
- "file:///",
- "",
- "",
- "",
- "",
- L"",
- L"download"
- },
- {
- __LINE__,
- "file:///path/testfile",
- "",
- "",
- "",
- "",
- L"",
- L"testfile"
- },
- {
- __LINE__,
- "non-standard-scheme:",
- "",
- "",
- "",
- "",
- L"",
- L"download"
- },
- { // C-D should override default
- __LINE__,
- "http://www.google.com/",
- "attachment; filename =\"test.html\"",
- "",
- "",
- "",
- L"download",
- L"test.html"
- },
- { // But the URL shouldn't
- __LINE__,
- "http://www.google.com/",
- "",
- "",
- "",
- "",
- L"download",
- L"download"
- },
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename=\"../test.html\"",
- "",
- "",
- "",
- L"",
- L"-test.html"
- },
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename=\"..\\test.html\"",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename=\"..\\\\test.html\"",
- "",
- "",
- "",
- L"",
- L"-test.html"
- },
- { // Filename disappears after leading and trailing periods are removed.
- __LINE__,
- "http://www.google.com/",
- "attachment; filename=\"..\"",
- "",
- "",
- "",
- L"default",
- L"default"
- },
- { // C-D specified filename disappears. Failover to final filename.
- __LINE__,
- "http://www.google.com/test.html",
- "attachment; filename=\"..\"",
- "",
- "",
- "",
- L"default",
- L"default"
- },
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename=test.html",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename=\"test.html\"",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename= \"test.html\"",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename = \"test.html\"",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
+ {// filename is whitespace. Should failover to URL host
+ __LINE__,
+ "http://www.google.com/",
+ "attachment; filename= ",
+ "",
+ "",
+ "",
+ L"",
+ L"www.google.com"},
+ {// No filename.
+ __LINE__,
+ "http://www.google.com/path/test.html",
+ "attachment",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
+ {// Ditto
+ __LINE__,
+ "http://www.google.com/path/test.html",
+ "attachment;",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
+ {// No C-D
+ __LINE__,
+ "http://www.google.com/",
+ "",
+ "",
+ "",
+ "",
+ L"",
+ L"www.google.com"},
+ {__LINE__,
+ "http://www.google.com/test.html",
+ "",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
+ {// Now that we use src/url's ExtractFileName, this case falls back to
+ // the hostname. If this behavior is not desirable, we'd better change
+ // ExtractFileName (in url_parse.cc).
+ __LINE__,
+ "http://www.google.com/path/",
+ "",
+ "",
+ "",
+ "",
+ L"",
+ L"www.google.com"},
+ {__LINE__, "http://www.google.com/path", "", "", "", "", L"", L"path"},
+ {__LINE__, "file:///", "", "", "", "", L"", L"download"},
+ {__LINE__, "file:///path/testfile", "", "", "", "", L"", L"testfile"},
+ {__LINE__, "non-standard-scheme:", "", "", "", "", L"", L"download"},
+ {// C-D should override default
+ __LINE__,
+ "http://www.google.com/",
+ "attachment; filename =\"test.html\"",
+ "",
+ "",
+ "",
+ L"download",
+ L"test.html"},
+ {// But the URL shouldn't
+ __LINE__,
+ "http://www.google.com/",
+ "",
+ "",
+ "",
+ "",
+ L"download",
+ L"download"},
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename=\"../test.html\"",
+ "",
+ "",
+ "",
+ L"",
+ L"-test.html"},
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename=\"..\\test.html\"",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename=\"..\\\\test.html\"",
+ "",
+ "",
+ "",
+ L"",
+ L"-test.html"},
+ {// Filename disappears after leading and trailing periods are removed.
+ __LINE__,
+ "http://www.google.com/",
+ "attachment; filename=\"..\"",
+ "",
+ "",
+ "",
+ L"default",
+ L"default"},
+ {// C-D specified filename disappears. Failover to final filename.
+ __LINE__,
+ "http://www.google.com/test.html",
+ "attachment; filename=\"..\"",
+ "",
+ "",
+ "",
+ L"default",
+ L"default"},
// Below is a small subset of cases taken from HttpContentDisposition tests.
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename=\"%EC%98%88%EC%88%A0%20"
- "%EC%98%88%EC%88%A0.jpg\"",
- "",
- "",
- "",
- L"",
- L"\uc608\uc220 \uc608\uc220.jpg"
- },
- {
- __LINE__,
- "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
- "",
- "",
- "",
- "",
- L"download",
- L"\uc608\uc220 \uc608\uc220.jpg"
- },
- {
- __LINE__,
- "http://www.google.com/",
- "attachment;",
- "",
- "",
- "",
- L"\uB2E4\uC6B4\uB85C\uB4DC",
- L"\uB2E4\uC6B4\uB85C\uB4DC"
- },
- {
- __LINE__,
- "http://www.google.com/",
- "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
- "D13=2Epng?=\"",
- "",
- "",
- "",
- L"download",
- L"\u82b8\u88533.png"
- },
- {
- __LINE__,
- "http://www.example.com/images?id=3",
- "attachment; filename=caf\xc3\xa9.png",
- "iso-8859-1",
- "",
- "",
- L"",
- L"caf\u00e9.png"
- },
- {
- __LINE__,
- "http://www.example.com/images?id=3",
- "attachment; filename=caf\xe5.png",
- "windows-1253",
- "",
- "",
- L"",
- L"caf\u03b5.png"
- },
- {
- __LINE__,
- "http://www.example.com/file?id=3",
- "attachment; name=\xcf\xc2\xd4\xd8.zip",
- "GBK",
- "",
- "",
- L"",
- L"\u4e0b\u8f7d.zip"
- },
- { // Invalid C-D header. Extracts filename from url.
- __LINE__,
- "http://www.google.com/test.html",
- "attachment; filename==?iiso88591?Q?caf=EG?=",
- "",
- "",
- "",
- L"",
- L"test.html"
- },
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename=\"%EC%98%88%EC%88%A0%20"
+ "%EC%98%88%EC%88%A0.jpg\"",
+ "",
+ "",
+ "",
+ L"",
+ L"\uc608\uc220 \uc608\uc220.jpg"},
+ {__LINE__,
+ "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
+ "",
+ "",
+ "",
+ "",
+ L"download",
+ L"\uc608\uc220 \uc608\uc220.jpg"},
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment;",
+ "",
+ "",
+ "",
+ L"\uB2E4\uC6B4\uB85C\uB4DC",
+ L"\uB2E4\uC6B4\uB85C\uB4DC"},
+ {__LINE__,
+ "http://www.google.com/",
+ "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
+ "D13=2Epng?=\"",
+ "",
+ "",
+ "",
+ L"download",
+ L"\u82b8\u88533.png"},
+ {__LINE__,
+ "http://www.example.com/images?id=3",
+ "attachment; filename=caf\xc3\xa9.png",
+ "iso-8859-1",
+ "",
+ "",
+ L"",
+ L"caf\u00e9.png"},
+ {__LINE__,
+ "http://www.example.com/images?id=3",
+ "attachment; filename=caf\xe5.png",
+ "windows-1253",
+ "",
+ "",
+ L"",
+ L"caf\u03b5.png"},
+ {__LINE__,
+ "http://www.example.com/file?id=3",
+ "attachment; name=\xcf\xc2\xd4\xd8.zip",
+ "GBK",
+ "",
+ "",
+ L"",
+ L"\u4e0b\u8f7d.zip"},
+ {// Invalid C-D header. Extracts filename from url.
+ __LINE__,
+ "http://www.google.com/test.html",
+ "attachment; filename==?iiso88591?Q?caf=EG?=",
+ "",
+ "",
+ "",
+ L"",
+ L"test.html"},
// about: and data: URLs
- {
- __LINE__,
- "about:chrome",
- "",
- "",
- "",
- "",
- L"",
- L"download"
- },
- {
- __LINE__,
- "data:,looks/like/a.path",
- "",
- "",
- "",
- "",
- L"",
- L"download"
- },
- {
- __LINE__,
- "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=",
- "",
- "",
- "",
- "",
- L"",
- L"download"
- },
- {
- __LINE__,
- "data:,looks/like/a.path",
- "",
- "",
- "",
- "",
- L"default_filename_is_given",
- L"default_filename_is_given"
- },
- {
- __LINE__,
- "data:,looks/like/a.path",
- "",
- "",
- "",
- "",
- L"\u65e5\u672c\u8a9e", // Japanese Kanji.
- L"\u65e5\u672c\u8a9e"
- },
- { // The filename encoding is specified by the referrer charset.
- __LINE__,
- "http://example.com/V%FDvojov%E1%20psychologie.doc",
- "",
- "iso-8859-1",
- "",
- "",
- L"",
- L"V\u00fdvojov\u00e1 psychologie.doc"
- },
- { // Suggested filename takes precedence over URL
- __LINE__,
- "http://www.google.com/test",
- "",
- "",
- "suggested",
- "",
- L"",
- L"suggested"
- },
- { // The content-disposition has higher precedence over the suggested name.
- __LINE__,
- "http://www.google.com/test",
- "attachment; filename=test.html",
- "",
- "suggested",
- "",
- L"",
- L"test.html"
- },
- {
- __LINE__,
- "http://www.google.com/test",
- "attachment; filename=test",
- "utf-8",
- "",
- "image/png",
- L"",
- L"test"
- },
+ {__LINE__, "about:chrome", "", "", "", "", L"", L"download"},
+ {__LINE__, "data:,looks/like/a.path", "", "", "", "", L"", L"download"},
+ {__LINE__,
+ "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=",
+ "",
+ "",
+ "",
+ "",
+ L"",
+ L"download"},
+ {__LINE__,
+ "data:,looks/like/a.path",
+ "",
+ "",
+ "",
+ "",
+ L"default_filename_is_given",
+ L"default_filename_is_given"},
+ {__LINE__,
+ "data:,looks/like/a.path",
+ "",
+ "",
+ "",
+ "",
+ L"\u65e5\u672c\u8a9e", // Japanese Kanji.
+ L"\u65e5\u672c\u8a9e"},
+ {// The filename encoding is specified by the referrer charset.
+ __LINE__,
+ "http://example.com/V%FDvojov%E1%20psychologie.doc",
+ "",
+ "iso-8859-1",
+ "",
+ "",
+ L"",
+ L"V\u00fdvojov\u00e1 psychologie.doc"},
+ {// Suggested filename takes precedence over URL
+ __LINE__,
+ "http://www.google.com/test",
+ "",
+ "",
+ "suggested",
+ "",
+ L"",
+ L"suggested"},
+ {// The content-disposition has higher precedence over the suggested name.
+ __LINE__,
+ "http://www.google.com/test",
+ "attachment; filename=test.html",
+ "",
+ "suggested",
+ "",
+ L"",
+ L"test.html"},
+ {__LINE__,
+ "http://www.google.com/test",
+ "attachment; filename=test",
+ "utf-8",
+ "",
+ "image/png",
+ L"",
+ L"test"},
#if 0
{ // The filename encoding doesn't match the referrer charset, the system
// charset, or UTF-8.
@@ -843,108 +688,95 @@
},
#endif
// Raw 8bit characters in C-D
- {
- __LINE__,
- "http://www.example.com/images?id=3",
- "attachment; filename=caf\xc3\xa9.png",
- "iso-8859-1",
- "",
- "image/png",
- L"",
- L"caf\u00e9.png"
- },
- {
- __LINE__,
- "http://www.example.com/images?id=3",
- "attachment; filename=caf\xe5.png",
- "windows-1253",
- "",
- "image/png",
- L"",
- L"caf\u03b5.png"
- },
- { // No 'filename' keyword in the disposition, use the URL
- __LINE__,
- "http://www.evil.com/my_download.txt",
- "a_file_name.txt",
- "",
- "",
- "text/plain",
- L"download",
- L"my_download.txt"
- },
- { // Spaces in the disposition file name
- __LINE__,
- "http://www.frontpagehacker.com/a_download.exe",
- "filename=My Downloaded File.exe",
- "",
- "",
- "application/octet-stream",
- L"download",
- L"My Downloaded File.exe"
- },
- { // % encoded
- __LINE__,
- "http://www.examples.com/",
- "attachment; "
- "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
- "",
- "",
- "image/jpeg",
- L"download",
- L"\uc608\uc220 \uc608\uc220.jpg"
- },
- { // name= parameter
- __LINE__,
- "http://www.examples.com/q.cgi?id=abc",
- "attachment; name=abc de.pdf",
- "",
- "",
- "application/octet-stream",
- L"download",
- L"abc de.pdf"
- },
- {
- __LINE__,
- "http://www.example.com/path",
- "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
- "",
- "",
- "image/png",
- L"download",
- L"\x82b8\x8853" L"3.png"
- },
- { // The following two have invalid CD headers and filenames come from the
- // URL.
- __LINE__,
- "http://www.example.com/test%20123",
- "attachment; filename==?iiso88591?Q?caf=EG?=",
- "",
- "",
- "image/jpeg",
- L"download",
- L"test 123" JPEG_EXT
- },
- {
- __LINE__,
- "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
- "malformed_disposition",
- "",
- "",
- "image/jpeg",
- L"download",
- L"\uc608\uc220 \uc608\uc220.jpg"
- },
- { // Invalid C-D. No filename from URL. Falls back to 'download'.
- __LINE__,
- "http://www.google.com/path1/path2/",
- "attachment; filename==?iso88591?Q?caf=E3?",
- "",
- "",
- "image/jpeg",
- L"download",
- L"download" JPEG_EXT
- },
+ {__LINE__,
+ "http://www.example.com/images?id=3",
+ "attachment; filename=caf\xc3\xa9.png",
+ "iso-8859-1",
+ "",
+ "image/png",
+ L"",
+ L"caf\u00e9.png"},
+ {__LINE__,
+ "http://www.example.com/images?id=3",
+ "attachment; filename=caf\xe5.png",
+ "windows-1253",
+ "",
+ "image/png",
+ L"",
+ L"caf\u03b5.png"},
+ {// No 'filename' keyword in the disposition, use the URL
+ __LINE__,
+ "http://www.evil.com/my_download.txt",
+ "a_file_name.txt",
+ "",
+ "",
+ "text/plain",
+ L"download",
+ L"my_download.txt"},
+ {// Spaces in the disposition file name
+ __LINE__,
+ "http://www.frontpagehacker.com/a_download.exe",
+ "filename=My Downloaded File.exe",
+ "",
+ "",
+ "application/octet-stream",
+ L"download",
+ L"My Downloaded File.exe"},
+ {// % encoded
+ __LINE__,
+ "http://www.examples.com/",
+ "attachment; "
+ "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
+ "",
+ "",
+ "image/jpeg",
+ L"download",
+ L"\uc608\uc220 \uc608\uc220.jpg"},
+ {// name= parameter
+ __LINE__,
+ "http://www.examples.com/q.cgi?id=abc",
+ "attachment; name=abc de.pdf",
+ "",
+ "",
+ "application/octet-stream",
+ L"download",
+ L"abc de.pdf"},
+ {__LINE__,
+ "http://www.example.com/path",
+ "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
+ "",
+ "",
+ "image/png",
+ L"download",
+ L"\x82b8\x8853"
+ L"3.png"},
+ {// The following two have invalid CD headers and filenames come from the
+ // URL.
+ __LINE__,
+ "http://www.example.com/test%20123",
+ "attachment; filename==?iiso88591?Q?caf=EG?=",
+ "",
+ "",
+ "image/jpeg",
+ L"download",
+ L"test 123" JPEG_EXT},
+ {__LINE__,
+ "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
+ "malformed_disposition",
+ "",
+ "",
+ "image/jpeg",
+ L"download",
+ L"\uc608\uc220 \uc608\uc220.jpg"},
+ {// Invalid C-D. No filename from URL. Falls back to 'download'.
+ __LINE__,
+ "http://www.google.com/path1/path2/",
+ "attachment; filename==?iso88591?Q?caf=E3?",
+ "",
+ "",
+ "image/jpeg",
+ L"download",
+ L"download" JPEG_EXT},
};
// Tests filename generation. Once the correct filename is
@@ -1067,7 +899,7 @@
"text/plain",
L"download",
L"my-cat.jpg"},
- // Windows specific tests
+// Windows specific tests
#if defined(OS_WIN)
{__LINE__,
"http://www.goodguy.com/evil.exe",
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index a7fe9f3..e9b4e1a 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -359,6 +359,7 @@
"audio/mp3",
"audio/x-mp3",
"audio/mpeg",
+ "audio/aac",
#if defined(ENABLE_MPEG2TS_STREAM_PARSER)
// MPEG-2 TS.
diff --git a/net/base/mime_util_unittest.cc b/net/base/mime_util_unittest.cc
index a28c8b6..b5335b6 100644
--- a/net/base/mime_util_unittest.cc
+++ b/net/base/mime_util_unittest.cc
@@ -231,6 +231,7 @@
EXPECT_TRUE(IsSupportedMediaMimeType("audio/mp3"));
EXPECT_TRUE(IsSupportedMediaMimeType("audio/x-mp3"));
EXPECT_TRUE(IsSupportedMediaMimeType("audio/mpeg"));
+ EXPECT_TRUE(IsSupportedMediaMimeType("audio/aac"));
#if defined(ENABLE_MPEG2TS_STREAM_PARSER)
EXPECT_TRUE(IsSupportedMediaMimeType("video/mp2t"));
@@ -246,6 +247,7 @@
EXPECT_FALSE(IsSupportedMediaMimeType("audio/mp3"));
EXPECT_FALSE(IsSupportedMediaMimeType("audio/x-mp3"));
EXPECT_FALSE(IsSupportedMediaMimeType("audio/mpeg"));
+ EXPECT_FALSE(IsSupportedMediaMimeType("audio/aac"));
#endif // USE_PROPRIETARY_CODECS
EXPECT_FALSE(IsSupportedMediaMimeType("video/mp3"));
diff --git a/net/base/net_util_linux.cc b/net/base/net_util_linux.cc
index 36c9eb7..a348912 100644
--- a/net/base/net_util_linux.cc
+++ b/net/base/net_util_linux.cc
@@ -18,6 +18,7 @@
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
@@ -68,11 +69,7 @@
namespace internal {
inline const unsigned char* GetIPAddressData(const IPAddressNumber& ip) {
-#if defined(OS_ANDROID)
- return ip.begin();
-#else
- return ip.data();
-#endif
+ return vector_as_array(&ip);
}
// Gets the connection type for interface |ifname| by checking for wireless
diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc
index 0512594..03cc4c0 100644
--- a/net/base/network_change_notifier_win.cc
+++ b/net/base/network_change_notifier_win.cc
@@ -227,7 +227,7 @@
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "NetworkChangeNotifierWin_OnObjectSignaled"));
+ "418183 NetworkChangeNotifierWin::OnObjectSignaled"));
DCHECK(CalledOnValidThread());
DCHECK(is_watching_);
diff --git a/net/base/upload_file_element_reader.cc b/net/base/upload_file_element_reader.cc
index 9be9117..864584d 100644
--- a/net/base/upload_file_element_reader.cc
+++ b/net/base/upload_file_element_reader.cc
@@ -174,12 +174,15 @@
}
// If the underlying file has been changed and the expected file modification
- // time is set, treat it as error. Note that the expected modification time
- // from WebKit is based on time_t precision. So we have to convert both to
- // time_t to compare. This check is used for sliced files.
+ // time is set, treat it as error. Note that |expected_modification_time_| may
+ // have gone through multiple conversion steps involving loss of precision
+ // (including conversion to time_t). Therefore the check below only verifies
+ // that the timestamps are within one second of each other. This check is used
+ // for sliced files.
if (!expected_modification_time_.is_null() &&
- expected_modification_time_.ToTimeT() !=
- file_info->last_modified.ToTimeT()) {
+ (expected_modification_time_ - file_info->last_modified)
+ .magnitude()
+ .InSeconds() != 0) {
callback.Run(ERR_UPLOAD_FILE_CHANGED);
return;
}
diff --git a/net/base/upload_file_element_reader_unittest.cc b/net/base/upload_file_element_reader_unittest.cc
index b0374ac..719ce1e 100644
--- a/net/base/upload_file_element_reader_unittest.cc
+++ b/net/base/upload_file_element_reader_unittest.cc
@@ -210,25 +210,33 @@
// Expect one second before the actual modification time to simulate change.
const base::Time expected_modification_time =
info.last_modified - base::TimeDelta::FromSeconds(1);
- reader_.reset(
- new UploadFileElementReader(base::MessageLoopProxy::current().get(),
- temp_file_path_,
- 0,
- kuint64max,
- expected_modification_time));
+ reader_.reset(new UploadFileElementReader(
+ base::MessageLoopProxy::current().get(), temp_file_path_, 0, kuint64max,
+ expected_modification_time));
TestCompletionCallback init_callback;
ASSERT_EQ(ERR_IO_PENDING, reader_->Init(init_callback.callback()));
EXPECT_EQ(ERR_UPLOAD_FILE_CHANGED, init_callback.WaitForResult());
}
+TEST_F(UploadFileElementReaderTest, InexactExpectedTimeStamp) {
+ base::File::Info info;
+ ASSERT_TRUE(base::GetFileInfo(temp_file_path_, &info));
+
+ const base::Time expected_modification_time =
+ info.last_modified - base::TimeDelta::FromMilliseconds(900);
+ reader_.reset(new UploadFileElementReader(
+ base::MessageLoopProxy::current().get(), temp_file_path_, 0, kuint64max,
+ expected_modification_time));
+ TestCompletionCallback init_callback;
+ ASSERT_EQ(ERR_IO_PENDING, reader_->Init(init_callback.callback()));
+ EXPECT_EQ(OK, init_callback.WaitForResult());
+}
+
TEST_F(UploadFileElementReaderTest, WrongPath) {
const base::FilePath wrong_path(FILE_PATH_LITERAL("wrong_path"));
reader_.reset(
new UploadFileElementReader(base::MessageLoopProxy::current().get(),
- wrong_path,
- 0,
- kuint64max,
- base::Time()));
+ wrong_path, 0, kuint64max, base::Time()));
TestCompletionCallback init_callback;
ASSERT_EQ(ERR_IO_PENDING, reader_->Init(init_callback.callback()));
EXPECT_EQ(ERR_FILE_NOT_FOUND, init_callback.WaitForResult());
diff --git a/net/cert/cert_verify_proc_android.h b/net/cert/cert_verify_proc_android.h
index 7002718..6830df6 100644
--- a/net/cert/cert_verify_proc_android.h
+++ b/net/cert/cert_verify_proc_android.h
@@ -15,18 +15,18 @@
public:
CertVerifyProcAndroid();
- virtual bool SupportsAdditionalTrustAnchors() const override;
+ bool SupportsAdditionalTrustAnchors() const override;
protected:
- virtual ~CertVerifyProcAndroid();
+ ~CertVerifyProcAndroid() override;
private:
- virtual int VerifyInternal(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CRLSet* crl_set,
- const CertificateList& additional_trust_anchors,
- CertVerifyResult* verify_result) override;
+ int VerifyInternal(X509Certificate* cert,
+ const std::string& hostname,
+ int flags,
+ CRLSet* crl_set,
+ const CertificateList& additional_trust_anchors,
+ CertVerifyResult* verify_result) override;
};
} // namespace net
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc
index 7099225..388d0fc 100644
--- a/net/cert/cert_verify_proc_mac.cc
+++ b/net/cert/cert_verify_proc_mac.cc
@@ -175,12 +175,21 @@
return noErr;
}
-// Saves some information about the certificate chain |cert_chain| in
-// |*verify_result|. The caller MUST initialize |*verify_result| before
-// calling this function.
+// Stores the constructed certificate chain |cert_chain| and information about
+// the signature algorithms used into |*verify_result|. If the leaf cert in
+// |cert_chain| contains a weak (MD2, MD4, MD5, SHA-1) signature, stores that
+// in |*leaf_is_weak|.
void GetCertChainInfo(CFArrayRef cert_chain,
CSSM_TP_APPLE_EVIDENCE_INFO* chain_info,
- CertVerifyResult* verify_result) {
+ CertVerifyResult* verify_result,
+ bool* leaf_is_weak) {
+ *leaf_is_weak = false;
+ verify_result->verified_cert = nullptr;
+ verify_result->has_md2 = false;
+ verify_result->has_md4 = false;
+ verify_result->has_md5 = false;
+ verify_result->has_sha1 = false;
+
SecCertificateRef verified_cert = NULL;
std::vector<SecCertificateRef> verified_chain;
for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) {
@@ -223,10 +232,16 @@
const CSSM_OID* alg_oid = &sig_algorithm->algorithm;
if (CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA)) {
verify_result->has_md2 = true;
+ if (i == 0)
+ *leaf_is_weak = true;
} else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA)) {
verify_result->has_md4 = true;
+ if (i == 0)
+ *leaf_is_weak = true;
} else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA)) {
verify_result->has_md5 = true;
+ if (i == 0)
+ *leaf_is_weak = true;
} else if (CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA) ||
CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) ||
CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) ||
@@ -234,6 +249,8 @@
CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1)) {
verify_result->has_sha1 = true;
+ if (i == 0)
+ *leaf_is_weak = true;
}
}
if (!verified_cert)
@@ -446,80 +463,6 @@
return OK;
}
-// OS X ships with both "GTE CyberTrust Global Root" and "Baltimore CyberTrust
-// Root" as part of its trusted root store. However, a cross-certified version
-// of the "Baltimore CyberTrust Root" exists that chains to "GTE CyberTrust
-// Global Root". When OS X/Security.framework attempts to evaluate such a
-// certificate chain, it disregards the "Baltimore CyberTrust Root" that exists
-// within Keychain and instead attempts to terminate the chain in the "GTE
-// CyberTrust Global Root". However, the GTE root is scheduled to be removed in
-// a future OS X update (for sunsetting purposes), and once removed, such
-// chains will fail validation, even though a trust anchor still exists.
-//
-// Rather than over-generalizing a solution that may mask a number of TLS
-// misconfigurations, attempt to specifically match the affected
-// cross-certified certificate and remove it from certificate chain processing.
-bool IsBadBaltimoreGTECertificate(SecCertificateRef cert) {
- // Matches the GTE-signed Baltimore CyberTrust Root
- // https://cacert.omniroot.com/Baltimore-to-GTE-04-12.pem
- static const SHA1HashValue kBadBaltimoreHashNew =
- { { 0x4D, 0x34, 0xEA, 0x92, 0x76, 0x4B, 0x3A, 0x31, 0x49, 0x11,
- 0x99, 0x52, 0xF4, 0x19, 0x30, 0xCA, 0x11, 0x34, 0x83, 0x61 } };
- // Matches the legacy GTE-signed Baltimore CyberTrust Root
- // https://cacert.omniroot.com/gte-2-2025.pem
- static const SHA1HashValue kBadBaltimoreHashOld =
- { { 0x54, 0xD8, 0xCB, 0x49, 0x1F, 0xA1, 0x6D, 0xF8, 0x87, 0xDC,
- 0x94, 0xA9, 0x34, 0xCC, 0x83, 0x6B, 0xDA, 0xA8, 0xA3, 0x69 } };
-
- SHA1HashValue fingerprint = X509Certificate::CalculateFingerprint(cert);
-
- return fingerprint.Equals(kBadBaltimoreHashNew) ||
- fingerprint.Equals(kBadBaltimoreHashOld);
-}
-
-// Attempts to re-verify |cert_array| after adjusting the inputs to work around
-// known issues in OS X. To be used if BuildAndEvaluateSecTrustRef fails to
-// return a positive result for verification.
-//
-// This function should only be called while the Mac Security Services lock is
-// held.
-void RetrySecTrustEvaluateWithAdjustedChain(
- CFArrayRef cert_array,
- CFArrayRef trust_policies,
- int flags,
- ScopedCFTypeRef<SecTrustRef>* trust_ref,
- SecTrustResultType* trust_result,
- ScopedCFTypeRef<CFArrayRef>* verified_chain,
- CSSM_TP_APPLE_EVIDENCE_INFO** chain_info) {
- CFIndex count = CFArrayGetCount(*verified_chain);
- CFIndex slice_point = 0;
-
- for (CFIndex i = 1; i < count; ++i) {
- SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
- const_cast<void*>(CFArrayGetValueAtIndex(*verified_chain, i)));
- if (cert == NULL)
- return; // Strange times; can't fix things up.
-
- if (IsBadBaltimoreGTECertificate(cert)) {
- slice_point = i;
- break;
- }
- }
- if (slice_point == 0)
- return; // Nothing to do.
-
- ScopedCFTypeRef<CFMutableArrayRef> adjusted_cert_array(
- CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks));
- // Note: This excludes the certificate at |slice_point|.
- CFArrayAppendArray(adjusted_cert_array, cert_array,
- CFRangeMake(0, slice_point));
-
- // Ignore the result; failure will preserve the old verification results.
- BuildAndEvaluateSecTrustRef(
- adjusted_cert_array, trust_policies, flags, trust_ref, trust_result,
- verified_chain, chain_info);
-}
-
} // namespace
CertVerifyProcMac::CertVerifyProcMac() {}
@@ -547,7 +490,8 @@
// array of certificates, the first of which is the certificate we're
// verifying, and the subsequent (optional) certificates are used for
// chain building.
- ScopedCFTypeRef<CFArrayRef> cert_array(cert->CreateOSCertChainForCert());
+ ScopedCFTypeRef<CFMutableArrayRef> cert_array(
+ cert->CreateOSCertChainForCert());
// Serialize all calls that may use the Keychain, to work around various
// issues in OS X 10.6+ with multi-threaded access to Security.framework.
@@ -557,17 +501,106 @@
SecTrustResultType trust_result = kSecTrustResultDeny;
ScopedCFTypeRef<CFArrayRef> completed_chain;
CSSM_TP_APPLE_EVIDENCE_INFO* chain_info = NULL;
+ bool candidate_untrusted = true;
+ bool candidate_weak = false;
- int rv = BuildAndEvaluateSecTrustRef(
- cert_array, trust_policies, flags, &trust_ref, &trust_result,
- &completed_chain, &chain_info);
- if (rv != OK)
- return rv;
- if (trust_result != kSecTrustResultUnspecified &&
- trust_result != kSecTrustResultProceed) {
- RetrySecTrustEvaluateWithAdjustedChain(
- cert_array, trust_policies, flags, &trust_ref, &trust_result,
- &completed_chain, &chain_info);
+ // OS X lacks proper path discovery; it will take the input certs and never
+ // backtrack the graph attempting to discover valid paths.
+ // This can create issues in some situations:
+ // - When OS X changes the trust store, there may be a chain
+ // A -> B -> C -> D
+ // where OS X trusts D (on some versions) and trusts C (on some versions).
+ // If a server supplies a chain A, B, C (cross-signed by D), then this chain
+ // will successfully validate on systems that trust D, but fail for systems
+ // that trust C. If the server supplies a chain of A -> B, then it forces
+ // all clients to fetch C (via AIA) if they trust D, and not all clients
+ // (notably, Firefox and Android) will do this, thus breaking them.
+ // An example of this is the Verizon Business Services root - GTE CyberTrust
+ // and Baltimore CyberTrust roots represent old and new roots that cause
+ // issues depending on which version of OS X being used.
+ //
+ // - A server may be (misconfigured) to send an expired intermediate
+ // certificate. On platforms with path discovery, the graph traversal
+ // will back up to immediately before this intermediate, and then
+ // attempt an AIA fetch or retrieval from local store. However, OS X
+ // does not do this, and thus prevents access. While this is ostensibly
+ // a server misconfiguration issue, the fact that it works on other
+ // platforms is a jarring inconsistency for users.
+ //
+ // - When OS X trusts both C and D (simultaneously), it's possible that the
+ // version of C signed by D is signed using a weak algorithm (e.g. SHA-1),
+ // while the version of C in the trust store's signature doesn't matter.
+ // Since a 'strong' chain exists, it would be desirable to prefer this
+ // chain.
+ //
+ // - A variant of the above example, it may be that the version of B sent by
+ // the server is signed using a weak algorithm, but the version of B
+ // present in the AIA of A is signed using a strong algorithm. Since a
+ // 'strong' chain exists, it would be desirable to prefer this chain.
+ //
+ // Because of this, the code below first attempts to validate the peer's
+ // identity using the supplied chain. If it is not trusted (e.g. the OS only
+ // trusts C, but the version of C signed by D was sent, and D is not trusted),
+ // or if it contains a weak chain, it will begin lopping off certificates
+ // from the end of the chain and attempting to verify. If a stronger, trusted
+ // chain is found, it is used, otherwise, the algorithm continues until only
+ // the peer's certificate remains.
+ //
+ // This does cause a performance hit for these users, but only in cases where
+ // OS X is building weaker chains than desired, or when it would otherwise
+ // fail the connection.
+ while (CFArrayGetCount(cert_array) > 0) {
+ ScopedCFTypeRef<SecTrustRef> temp_ref;
+ SecTrustResultType temp_trust_result = kSecTrustResultDeny;
+ ScopedCFTypeRef<CFArrayRef> temp_chain;
+ CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL;
+
+ int rv = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, flags,
+ &temp_ref, &temp_trust_result,
+ &temp_chain, &temp_chain_info);
+ if (rv != OK)
+ return rv;
+
+ CertVerifyResult temp_verify_result;
+ bool leaf_is_weak = false;
+ GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result,
+ &leaf_is_weak);
+
+ bool untrusted = (temp_trust_result != kSecTrustResultUnspecified &&
+ temp_trust_result != kSecTrustResultProceed);
+ bool weak_chain =
+ !leaf_is_weak &&
+ (temp_verify_result.has_md2 || temp_verify_result.has_md4 ||
+ temp_verify_result.has_md5 || temp_verify_result.has_sha1);
+ // Set the result to the current chain if:
+ // - This is the first verification attempt. This ensures that if
+ // everything is awful (e.g. it may just be an untrusted cert), that
+ // what is reported is exactly what was sent by the server
+ // - If the current chain is trusted, and the old chain was not trusted,
+ // then prefer this chain. This ensures that if there is at least a
+ // valid path to a trust anchor, it's preferred over reporting an error.
+ // - If the current chain is trusted, and the old chain is trusted, but
+ // the old chain contained weak algorithms while the current chain only
+ // contains strong algorithms, then prefer the current chain over the
+ // old chain.
+ //
+ // Note: If the leaf certificate itself is weak, then the only
+ // consideration is whether or not there is a trusted chain. That's
+ // because no amount of path discovery will fix a weak leaf.
+ if (!trust_ref || (!untrusted && (candidate_untrusted ||
+ (candidate_weak && !weak_chain)))) {
+ trust_ref = temp_ref;
+ trust_result = temp_trust_result;
+ completed_chain = temp_chain;
+ chain_info = temp_chain_info;
+
+ candidate_untrusted = untrusted;
+ candidate_weak = weak_chain;
+ }
+ // Short-circuit when a current, trusted chain is found.
+ if (!untrusted && !weak_chain)
+ break;
+ CFArrayRemoveValueAtIndex(cert_array, CFArrayGetCount(cert_array) - 1);
}
if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED)
@@ -576,7 +609,9 @@
if (crl_set && !CheckRevocationWithCRLSet(completed_chain, crl_set))
verify_result->cert_status |= CERT_STATUS_REVOKED;
- GetCertChainInfo(completed_chain, chain_info, verify_result);
+ bool leaf_is_weak_unused = false;
+ GetCertChainInfo(completed_chain, chain_info, verify_result,
+ &leaf_is_weak_unused);
// As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits
// is encountered, CSSM returns CSSMERR_TP_VERIFY_ACTION_FAILED and adds
diff --git a/net/cert/x509_certificate.h b/net/cert/x509_certificate.h
index c1a4f6d..6c0f0e9 100644
--- a/net/cert/x509_certificate.h
+++ b/net/cert/x509_certificate.h
@@ -251,12 +251,12 @@
// Does this certificate's usage allow SSL client authentication?
bool SupportsSSLClientAuth() const;
- // Returns a new CFArrayRef containing this certificate and its intermediate
- // certificates in the form expected by Security.framework and Keychain
- // Services, or NULL on failure.
+ // Returns a new CFMutableArrayRef containing this certificate and its
+ // intermediate certificates in the form expected by Security.framework
+ // and Keychain Services, or NULL on failure.
// The first item in the array will be this certificate, followed by its
// intermediates, if any.
- CFArrayRef CreateOSCertChainForCert() const;
+ CFMutableArrayRef CreateOSCertChainForCert() const;
#endif
// Do any of the given issuer names appear in this cert's chain of trust?
diff --git a/net/cert/x509_certificate_mac.cc b/net/cert/x509_certificate_mac.cc
index f8bfe12..10cfb56 100644
--- a/net/cert/x509_certificate_mac.cc
+++ b/net/cert/x509_certificate_mac.cc
@@ -449,7 +449,7 @@
return true;
}
-CFArrayRef X509Certificate::CreateOSCertChainForCert() const {
+CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const {
CFMutableArrayRef cert_list =
CFArrayCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeArrayCallBacks);
diff --git a/net/disk_cache/blockfile/block_files.cc b/net/disk_cache/blockfile/block_files.cc
index 9aa8f0f..f46a937 100644
--- a/net/disk_cache/blockfile/block_files.cc
+++ b/net/disk_cache/blockfile/block_files.cc
@@ -656,11 +656,11 @@
if (file_size < file_header.Size())
return false; // file_size > 2GB is also an error.
- const int kMinBlockSize = 36;
- const int kMaxBlockSize = 4096;
+ const int kMinHeaderBlockSize = 36;
+ const int kMaxHeaderBlockSize = 4096;
BlockFileHeader* header = file_header.Header();
- if (header->entry_size < kMinBlockSize ||
- header->entry_size > kMaxBlockSize || header->num_entries < 0)
+ if (header->entry_size < kMinHeaderBlockSize ||
+ header->entry_size > kMaxHeaderBlockSize || header->num_entries < 0)
return false;
// Make sure that we survive crashes.
diff --git a/net/dns/dns_config_service_posix.cc b/net/dns/dns_config_service_posix.cc
index 4f6888b..135f3fd 100644
--- a/net/dns/dns_config_service_posix.cc
+++ b/net/dns/dns_config_service_posix.cc
@@ -64,7 +64,7 @@
NetworkChangeNotifier::AddNetworkChangeObserver(this);
}
- virtual ~DnsConfigWatcher() {
+ ~DnsConfigWatcher() override {
NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}
@@ -73,8 +73,7 @@
return true;
}
- virtual void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type)
- override {
+ void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override {
if (!callback_.is_null() && type != NetworkChangeNotifier::CONNECTION_NONE)
callback_.Run(true);
}
diff --git a/net/dns/dns_config_service_win.cc b/net/dns/dns_config_service_win.cc
index b0da34e..8d0ac54 100644
--- a/net/dns/dns_config_service_win.cc
+++ b/net/dns/dns_config_service_win.cc
@@ -312,7 +312,8 @@
void OnObjectSignaled() {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("RegistryWatcher_OnObjectSignaled"));
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 RegistryWatcher::OnObjectSignaled"));
DCHECK(CalledOnValidThread());
DCHECK(!callback_.is_null());
diff --git a/net/dns/dns_hosts.cc b/net/dns/dns_hosts.cc
index b4d213b..697ea14 100644
--- a/net/dns/dns_hosts.cc
+++ b/net/dns/dns_hosts.cc
@@ -131,7 +131,6 @@
DnsHosts* dns_hosts,
ParseHostsCommaMode comma_mode) {
CHECK(dns_hosts);
- DnsHosts& hosts = *dns_hosts;
StringPiece ip_text;
IPAddressNumber ip;
@@ -156,9 +155,9 @@
} else {
DnsHostsKey key(parser.token().as_string(), family);
base::StringToLowerASCII(&key.first);
- IPAddressNumber& mapped_ip = hosts[key];
- if (mapped_ip.empty())
- mapped_ip = ip;
+ IPAddressNumber* mapped_ip = &(*dns_hosts)[key];
+ if (mapped_ip->empty())
+ *mapped_ip = ip;
// else ignore this entry (first hit counts)
}
}
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index 2b308c7..ef6adb8 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -239,11 +239,6 @@
return OK;
}
-int FtpNetworkTransaction::RestartIgnoringLastError(
- const CompletionCallback& callback) {
- return ERR_NOT_IMPLEMENTED;
-}
-
int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info,
const CompletionCallback& callback,
const BoundNetLog& net_log) {
@@ -1033,16 +1028,18 @@
int FtpNetworkTransaction::ProcessResponseRETR(
const FtpCtrlResponse& response) {
+ // Resource type should be either filled in by DetectTypecode() or
+ // detected with CWD. RETR is sent only when the resource is a file.
+ DCHECK_EQ(RESOURCE_TYPE_FILE, resource_type_);
+
switch (GetErrorClass(response.status_code)) {
case ERROR_CLASS_INITIATED:
// We want the client to start reading the response at this point.
// It got here either through Start or RestartWithAuth. We want that
// method to complete. Not setting next state here will make DoLoop exit
// and in turn make Start/RestartWithAuth complete.
- resource_type_ = RESOURCE_TYPE_FILE;
break;
case ERROR_CLASS_OK:
- resource_type_ = RESOURCE_TYPE_FILE;
next_state_ = STATE_CTRL_WRITE_QUIT;
break;
case ERROR_CLASS_INFO_NEEDED:
@@ -1056,10 +1053,6 @@
return Stop(ERR_UNEXPECTED);
}
- // We should be sure about our resource type now. Otherwise we risk
- // an infinite loop (RETR can later send CWD, and CWD can later send RETR).
- DCHECK_NE(RESOURCE_TYPE_UNKNOWN, resource_type_);
-
return OK;
}
@@ -1095,6 +1088,7 @@
break;
case ERROR_CLASS_PERMANENT_ERROR:
// It's possible that SIZE failed because the path is a directory.
+ // TODO(xunjieli): Add a test for this case.
if (resource_type_ == RESOURCE_TYPE_UNKNOWN &&
response.status_code != 550) {
return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
@@ -1104,6 +1098,9 @@
NOTREACHED();
return Stop(ERR_UNEXPECTED);
}
+
+ // If the resource is known beforehand to be a file, RETR should be issued,
+ // otherwise do CWD which will detect the resource type.
if (resource_type_ == RESOURCE_TYPE_FILE)
EstablishDataConnection(STATE_CTRL_WRITE_RETR);
else
@@ -1119,13 +1116,14 @@
}
int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) {
- // We should never issue CWD if we know the target resource is a file.
+ // CWD should be invoked only when the resource is not a file.
DCHECK_NE(RESOURCE_TYPE_FILE, resource_type_);
switch (GetErrorClass(response.status_code)) {
case ERROR_CLASS_INITIATED:
return Stop(ERR_INVALID_RESPONSE);
case ERROR_CLASS_OK:
+ resource_type_ = RESOURCE_TYPE_DIRECTORY;
EstablishDataConnection(STATE_CTRL_WRITE_LIST);
break;
case ERROR_CLASS_INFO_NEEDED:
@@ -1158,9 +1156,7 @@
return Stop(ERR_FILE_NOT_FOUND);
}
- // We are here because SIZE failed and we are not sure what the resource
- // type is. It could still be file, and SIZE could fail because of
- // an access error (http://crbug.com/56734). Try RETR just to be sure.
+ // If it is not a directory, it is probably a file.
resource_type_ = RESOURCE_TYPE_FILE;
EstablishDataConnection(STATE_CTRL_WRITE_RETR);
@@ -1182,6 +1178,10 @@
int FtpNetworkTransaction::ProcessResponseLIST(
const FtpCtrlResponse& response) {
+ // Resource type should be either filled in by DetectTypecode() or
+ // detected with CWD. LIST is sent only when the resource is a directory.
+ DCHECK_EQ(RESOURCE_TYPE_DIRECTORY, resource_type_);
+
switch (GetErrorClass(response.status_code)) {
case ERROR_CLASS_INITIATED:
// We want the client to start reading the response at this point.
diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h
index fc94ae7..6bf01bd 100644
--- a/net/ftp/ftp_network_transaction.h
+++ b/net/ftp/ftp_network_transaction.h
@@ -33,8 +33,7 @@
ClientSocketFactory* socket_factory);
~FtpNetworkTransaction() override;
- virtual int Stop(int error);
- virtual int RestartIgnoringLastError(const CompletionCallback& callback);
+ int Stop(int error);
// FtpTransaction methods:
int Start(const FtpRequestInfo* request_info,
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
index ede22d3..79e1687 100644
--- a/net/ftp/ftp_network_transaction_unittest.cc
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -918,7 +918,7 @@
TEST_P(FtpNetworkTransactionTest, DirectoryTransactionWithTypecode) {
FtpSocketDataProviderDirectoryListing ctrl_socket;
- ExecuteTransaction(&ctrl_socket, "ftp://host;type=d", OK);
+ ExecuteTransaction(&ctrl_socket, "ftp://host/;type=d", OK);
EXPECT_TRUE(transaction_.GetResponseInfo()->is_directory_listing);
EXPECT_EQ(-1, transaction_.GetResponseInfo()->expected_content_size);
diff --git a/net/http/http_atom_list.h b/net/http/http_atom_list.h
deleted file mode 100644
index 4dac9fb..0000000
--- a/net/http/http_atom_list.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-HTTP_ATOM(ACCEPT)
-HTTP_ATOM(ACCEPT_CHARSET)
-HTTP_ATOM(ACCEPT_ENCODING)
-HTTP_ATOM(ACCEPT_LANGUAGE)
-HTTP_ATOM(ACCEPT_RANGES)
-HTTP_ATOM(AGE)
-HTTP_ATOM(ALLOW)
-HTTP_ATOM(AUTHORIZATION)
-HTTP_ATOM(CACHE_CONTROL)
-HTTP_ATOM(CONNECTION)
-HTTP_ATOM(CONTENT_BASE)
-HTTP_ATOM(CONTENT_DISPOSITION)
-HTTP_ATOM(CONTENT_ENCODING)
-HTTP_ATOM(CONTENT_LANGUAGE)
-HTTP_ATOM(CONTENT_LENGTH)
-HTTP_ATOM(CONTENT_LOCATION)
-HTTP_ATOM(CONTENT_MD5)
-HTTP_ATOM(CONTENT_RANGE)
-HTTP_ATOM(CONTENT_TRANSFER_ENCODING)
-HTTP_ATOM(CONTENT_TYPE)
-HTTP_ATOM(COOKIE)
-HTTP_ATOM(DATE)
-HTTP_ATOM(DERIVED_FROM)
-HTTP_ATOM(ETAG)
-HTTP_ATOM(EXPECT)
-HTTP_ATOM(EXPIRES)
-HTTP_ATOM(FORWARDED)
-HTTP_ATOM(FROM)
-HTTP_ATOM(HOST)
-HTTP_ATOM(IF_MATCH)
-HTTP_ATOM(IF_MODIFIED_SINCE)
-HTTP_ATOM(IF_NONE_MATCH)
-HTTP_ATOM(IF_RANGE)
-HTTP_ATOM(IF_UNMODIFIED_SINCE)
-HTTP_ATOM(LAST_MODIFIED)
-HTTP_ATOM(LINK)
-HTTP_ATOM(LOCATION)
-HTTP_ATOM(MAX_FORWARDS)
-HTTP_ATOM(MESSAGE_ID)
-HTTP_ATOM(PRAGMA)
-HTTP_ATOM(PROXY_AUTHENTICATE)
-HTTP_ATOM(PROXY_AUTHORIZATION)
-HTTP_ATOM(PROXY_CONNECTION)
-HTTP_ATOM(RANGE)
-HTTP_ATOM(REFERER)
-HTTP_ATOM(REFRESH)
-HTTP_ATOM(RETRY_AFTER)
-HTTP_ATOM(SERVER)
-HTTP_ATOM(SET_COOKIE)
-HTTP_ATOM(TITLE)
-HTTP_ATOM(TRANSFER_ENCODING)
-HTTP_ATOM(UPGRADE)
-HTTP_ATOM(USER_AGENT)
-HTTP_ATOM(VARY)
-HTTP_ATOM(VIA)
-HTTP_ATOM(WARNING)
-HTTP_ATOM(WWW_AUTHENTICATE)
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 3376051..3908d74 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -97,7 +97,7 @@
enable_user_alternate_protocol_ports(false),
quic_crypto_client_stream_factory(NULL),
proxy_delegate(NULL) {
- quic_supported_versions.push_back(QUIC_VERSION_23);
+ quic_supported_versions.push_back(QUIC_VERSION_24);
}
HttpNetworkSession::Params::~Params() {}
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 8f33e20..69a3aa5 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -571,7 +571,8 @@
}
bool HttpNetworkTransaction::UsingHttpProxyWithoutTunnel() const {
- return (proxy_info_.is_http() || proxy_info_.is_https()) &&
+ return (proxy_info_.is_http() || proxy_info_.is_https() ||
+ proxy_info_.is_quic()) &&
!(request_->url.SchemeIs("https") || request_->url.SchemeIsWSOrWSS());
}
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 1c70393..c3eab76 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -8508,8 +8508,9 @@
HostPortPair http_host_port_pair("www.google.com", 80);
HttpServerProperties& http_server_properties =
*session->http_server_properties();
- EXPECT_FALSE(
- http_server_properties.HasAlternateProtocol(http_host_port_pair));
+ AlternateProtocolInfo alternate =
+ http_server_properties.GetAlternateProtocol(http_host_port_pair);
+ EXPECT_EQ(alternate.protocol, UNINITIALIZED_ALTERNATE_PROTOCOL);
EXPECT_EQ(OK, callback.WaitForResult());
@@ -8524,12 +8525,10 @@
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
- ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
- const AlternateProtocolInfo alternate =
- http_server_properties.GetAlternateProtocol(http_host_port_pair);
- AlternateProtocolInfo expected_alternate(
- 443, AlternateProtocolFromNextProto(GetParam()), 1);
- EXPECT_TRUE(expected_alternate.Equals(alternate));
+ alternate = http_server_properties.GetAlternateProtocol(http_host_port_pair);
+ EXPECT_EQ(443, alternate.port);
+ EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()), alternate.protocol);
+ EXPECT_EQ(1.0, alternate.probability);
}
TEST_P(HttpNetworkTransactionTest,
@@ -8583,11 +8582,10 @@
ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
EXPECT_EQ("hello world", response_data);
- ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
- HostPortPair::FromURL(request.url)));
const AlternateProtocolInfo alternate =
http_server_properties->GetAlternateProtocol(
HostPortPair::FromURL(request.url));
+ EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL, alternate.protocol);
EXPECT_TRUE(alternate.is_broken);
}
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index 9c8a531..b97c957 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -128,6 +128,10 @@
}
void HttpProxyConnectJob::OnIOComplete(int result) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "455884 HttpProxyConnectJob::OnIOComplete"));
int rv = DoLoop(result);
if (rv != ERR_IO_PENDING) {
NotifyProxyDelegateOfCompletion(rv);
diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h
index 840a359..dcb4cdc 100644
--- a/net/http/http_server_properties.h
+++ b/net/http/http_server_properties.h
@@ -13,6 +13,7 @@
#include "base/time/time.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
+#include "net/base/net_util.h"
#include "net/quic/quic_bandwidth.h"
#include "net/socket/next_proto.h"
#include "net/spdy/spdy_framer.h" // TODO(willchan): Reconsider this.
@@ -147,7 +148,6 @@
typedef base::MRUCache<
HostPortPair, AlternateProtocolInfo> AlternateProtocolMap;
typedef base::MRUCache<HostPortPair, SettingsMap> SpdySettingsMap;
-typedef std::map<HostPortPair, SupportsQuic> SupportsQuicMap;
typedef base::MRUCache<HostPortPair, ServerNetworkStats> ServerNetworkStatsMap;
extern const char kAlternateProtocolHeader[];
@@ -190,11 +190,9 @@
virtual void MaybeForceHTTP11(const HostPortPair& server,
SSLConfig* ssl_config) = 0;
- // Returns true if |server| has an Alternate-Protocol header.
- virtual bool HasAlternateProtocol(const HostPortPair& server) = 0;
-
- // Returns the Alternate-Protocol and port for |server|.
- // HasAlternateProtocol(server) must be true.
+ // Returns the AlternateProtocol for |server| if it has probability equal to
+ // or exceeding threshold, or else the forced AlternateProtocol if there is
+ // one, or else one with UNINITIALIZED_ALTERNATE_PROTOCOL.
virtual AlternateProtocolInfo GetAlternateProtocol(
const HostPortPair& server) = 0;
@@ -249,15 +247,10 @@
// Returns all persistent SPDY settings.
virtual const SpdySettingsMap& spdy_settings_map() const = 0;
- // TODO(rtenneti): Make SupportsQuic a global (instead of per host_port_pair).
- virtual SupportsQuic GetSupportsQuic(
- const HostPortPair& host_port_pair) const = 0;
+ virtual bool GetSupportsQuic(IPAddressNumber* last_address) const = 0;
- virtual void SetSupportsQuic(const HostPortPair& host_port_pair,
- bool used_quic,
- const std::string& address) = 0;
-
- virtual const SupportsQuicMap& supports_quic_map() const = 0;
+ virtual void SetSupportsQuic(bool used_quic,
+ const IPAddressNumber& last_address) = 0;
virtual void SetServerNetworkStats(const HostPortPair& host_port_pair,
ServerNetworkStats stats) = 0;
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc
index a53e73f..9f17afc 100644
--- a/net/http/http_server_properties_impl.cc
+++ b/net/http/http_server_properties_impl.cc
@@ -102,12 +102,9 @@
}
void HttpServerPropertiesImpl::InitializeSupportsQuic(
- SupportsQuicMap* supports_quic_map) {
- for (SupportsQuicMap::reverse_iterator it = supports_quic_map->rbegin();
- it != supports_quic_map->rend();
- ++it) {
- supports_quic_map_.insert(std::make_pair(it->first, it->second));
- }
+ IPAddressNumber* last_address) {
+ if (last_address)
+ last_quic_address_ = *last_address;
}
void HttpServerPropertiesImpl::InitializeServerNetworkStats(
@@ -164,7 +161,7 @@
alternate_protocol_map_.Clear();
canonical_host_to_origin_map_.clear();
spdy_settings_map_.Clear();
- supports_quic_map_.clear();
+ last_quic_address_.clear();
server_network_stats_map_.Clear();
}
@@ -179,10 +176,7 @@
if (spdy_host_port != spdy_servers_map_.end() && spdy_host_port->second)
return true;
- if (!HasAlternateProtocol(host_port_pair))
- return false;
-
- AlternateProtocolInfo info = GetAlternateProtocol(host_port_pair);
+ const AlternateProtocolInfo info = GetAlternateProtocol(host_port_pair);
return info.protocol == QUIC;
}
@@ -228,16 +222,6 @@
}
}
-bool HttpServerPropertiesImpl::HasAlternateProtocol(
- const HostPortPair& server) {
- if (g_forced_alternate_protocol)
- return true;
- AlternateProtocolMap::const_iterator it =
- GetAlternateProtocolIterator(server);
- return it != alternate_protocol_map_.end() &&
- it->second.probability >= alternate_protocol_probability_threshold_;
-}
-
std::string HttpServerPropertiesImpl::GetCanonicalSuffix(
const std::string& host) {
// If this host ends with a canonical suffix, then return the canonical
@@ -251,19 +235,19 @@
return std::string();
}
-AlternateProtocolInfo
-HttpServerPropertiesImpl::GetAlternateProtocol(
+AlternateProtocolInfo HttpServerPropertiesImpl::GetAlternateProtocol(
const HostPortPair& server) {
- DCHECK(HasAlternateProtocol(server));
-
AlternateProtocolMap::const_iterator it =
GetAlternateProtocolIterator(server);
- if (it != alternate_protocol_map_.end())
+ if (it != alternate_protocol_map_.end() &&
+ it->second.probability >= alternate_protocol_probability_threshold_)
return it->second;
- // We must be forcing an alternate.
- DCHECK(g_forced_alternate_protocol);
- return *g_forced_alternate_protocol;
+ if (g_forced_alternate_protocol)
+ return *g_forced_alternate_protocol;
+
+ AlternateProtocolInfo uninitialized_alternate_protocol;
+ return uninitialized_alternate_protocol;
}
void HttpServerPropertiesImpl::SetAlternateProtocol(
@@ -322,24 +306,26 @@
void HttpServerPropertiesImpl::SetBrokenAlternateProtocol(
const HostPortPair& server) {
AlternateProtocolMap::iterator it = alternate_protocol_map_.Get(server);
+ const AlternateProtocolInfo alternate = GetAlternateProtocol(server);
if (it == alternate_protocol_map_.end()) {
- if (!HasAlternateProtocol(server)) {
+ if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) {
LOG(DFATAL) << "Trying to mark unknown alternate protocol broken.";
return;
}
// This server's alternate protocol information is coming from a canonical
// server. Add an entry in the map for this server explicitly so that
// it can be marked as broken.
- it = alternate_protocol_map_.Put(server, GetAlternateProtocol(server));
+ it = alternate_protocol_map_.Put(server, alternate);
}
it->second.is_broken = true;
- int count = ++broken_alternate_protocol_map_[server];
+ const BrokenAlternateProtocolEntry entry(server, alternate.port,
+ alternate.protocol);
+ int count = ++broken_alternate_protocol_map_[entry];
base::TimeDelta delay =
base::TimeDelta::FromSeconds(kBrokenAlternateProtocolDelaySecs);
- BrokenAlternateProtocolEntry entry;
- entry.server = server;
- entry.when = base::TimeTicks::Now() + delay * (1 << (count - 1));
- broken_alternate_protocol_list_.push_back(entry);
+ base::TimeTicks when = base::TimeTicks::Now() + delay * (1 << (count - 1));
+ broken_alternate_protocol_list_.push_back(
+ BrokenAlternateProtocolEntryWithTime(entry, when));
// Do not leave this host as canonical so that we don't infer the other
// hosts are also broken without testing them first.
@@ -354,12 +340,22 @@
bool HttpServerPropertiesImpl::WasAlternateProtocolRecentlyBroken(
const HostPortPair& server) {
- return ContainsKey(broken_alternate_protocol_map_, server);
+ const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server);
+ if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
+ return false;
+ const BrokenAlternateProtocolEntry entry(server, alternate_protocol.port,
+ alternate_protocol.protocol);
+ return ContainsKey(broken_alternate_protocol_map_, entry);
}
void HttpServerPropertiesImpl::ConfirmAlternateProtocol(
const HostPortPair& server) {
- broken_alternate_protocol_map_.erase(server);
+ const AlternateProtocolInfo alternate_protocol = GetAlternateProtocol(server);
+ if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
+ return;
+ const BrokenAlternateProtocolEntry entry(server, alternate_protocol.port,
+ alternate_protocol.protocol);
+ broken_alternate_protocol_map_.erase(entry);
}
void HttpServerPropertiesImpl::ClearAlternateProtocol(
@@ -423,26 +419,22 @@
return spdy_settings_map_;
}
-SupportsQuic HttpServerPropertiesImpl::GetSupportsQuic(
- const HostPortPair& host_port_pair) const {
- SupportsQuicMap::const_iterator it = supports_quic_map_.find(host_port_pair);
- if (it == supports_quic_map_.end()) {
- CR_DEFINE_STATIC_LOCAL(SupportsQuic, kEmptySupportsQuic, ());
- return kEmptySupportsQuic;
+bool HttpServerPropertiesImpl::GetSupportsQuic(
+ IPAddressNumber* last_address) const {
+ if (last_quic_address_.empty())
+ return false;
+
+ *last_address = last_quic_address_;
+ return true;
+}
+
+void HttpServerPropertiesImpl::SetSupportsQuic(bool used_quic,
+ const IPAddressNumber& address) {
+ if (!used_quic) {
+ last_quic_address_.clear();
+ } else {
+ last_quic_address_ = address;
}
- return it->second;
-}
-
-void HttpServerPropertiesImpl::SetSupportsQuic(
- const HostPortPair& host_port_pair,
- bool used_quic,
- const std::string& address) {
- SupportsQuic supports_quic(used_quic, address);
- supports_quic_map_.insert(std::make_pair(host_port_pair, supports_quic));
-}
-
-const SupportsQuicMap& HttpServerPropertiesImpl::supports_quic_map() const {
- return supports_quic_map_;
}
void HttpServerPropertiesImpl::SetServerNetworkStats(
@@ -513,12 +505,14 @@
void HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings() {
base::TimeTicks now = base::TimeTicks::Now();
while (!broken_alternate_protocol_list_.empty()) {
- BrokenAlternateProtocolEntry entry =
+ BrokenAlternateProtocolEntryWithTime entry_with_time =
broken_alternate_protocol_list_.front();
- if (now < entry.when) {
+ if (now < entry_with_time.when) {
break;
}
+ const BrokenAlternateProtocolEntry& entry =
+ entry_with_time.broken_alternate_protocol_entry;
ClearAlternateProtocol(entry.server);
broken_alternate_protocol_list_.pop_front();
}
diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h
index 8d251a2..5c84226 100644
--- a/net/http/http_server_properties_impl.h
+++ b/net/http/http_server_properties_impl.h
@@ -5,6 +5,7 @@
#ifndef NET_HTTP_HTTP_SERVER_PROPERTIES_IMPL_H_
#define NET_HTTP_HTTP_SERVER_PROPERTIES_IMPL_H_
+#include <deque>
#include <map>
#include <set>
#include <string>
@@ -43,7 +44,7 @@
void InitializeSpdySettingsServers(SpdySettingsMap* spdy_settings_map);
- void InitializeSupportsQuic(SupportsQuicMap* supports_quic_map);
+ void InitializeSupportsQuic(IPAddressNumber* last_address);
void InitializeServerNetworkStats(
ServerNetworkStatsMap* server_network_stats_map);
@@ -79,7 +80,6 @@
void SetHTTP11Required(const HostPortPair& server) override;
void MaybeForceHTTP11(const HostPortPair& server,
SSLConfig* ssl_config) override;
- bool HasAlternateProtocol(const HostPortPair& server) override;
AlternateProtocolInfo GetAlternateProtocol(
const HostPortPair& server) override;
void SetAlternateProtocol(const HostPortPair& server,
@@ -101,12 +101,8 @@
void ClearSpdySettings(const HostPortPair& host_port_pair) override;
void ClearAllSpdySettings() override;
const SpdySettingsMap& spdy_settings_map() const override;
- SupportsQuic GetSupportsQuic(
- const HostPortPair& host_port_pair) const override;
- void SetSupportsQuic(const HostPortPair& host_port_pair,
- bool used_quic,
- const std::string& address) override;
- const SupportsQuicMap& supports_quic_map() const override;
+ bool GetSupportsQuic(IPAddressNumber* last_address) const override;
+ void SetSupportsQuic(bool used_quic, const IPAddressNumber& address) override;
void SetServerNetworkStats(const HostPortPair& host_port_pair,
ServerNetworkStats stats) override;
const ServerNetworkStats* GetServerNetworkStats(
@@ -120,16 +116,48 @@
typedef std::map<HostPortPair, HostPortPair> CanonicalHostMap;
typedef std::vector<std::string> CanonicalSufficList;
typedef std::set<HostPortPair> Http11ServerHostPortSet;
- // List of broken host:ports and the times when they can be expired.
+
+ // Server, port, and AlternateProtocol: an entity that can be broken. (Once
+ // we use AlternativeService, the same AltSvc can be broken for one server but
+ // not for another depending on what certificate it can offer.)
struct BrokenAlternateProtocolEntry {
+ BrokenAlternateProtocolEntry(const BrokenAlternateProtocolEntry&) = default;
+ BrokenAlternateProtocolEntry(const HostPortPair& server,
+ uint16 port,
+ AlternateProtocol protocol)
+ : server(server), port(port), protocol(protocol) {}
+
+ bool operator<(const BrokenAlternateProtocolEntry& other) const {
+ if (!server.Equals(other.server))
+ return server < other.server;
+ if (port != other.port)
+ return port < other.port;
+ return protocol < other.protocol;
+ }
+
HostPortPair server;
+ uint16 port;
+ AlternateProtocol protocol;
+ };
+ // BrokenAlternateProtocolEntry with expiration time.
+ struct BrokenAlternateProtocolEntryWithTime {
+ BrokenAlternateProtocolEntryWithTime(
+ const BrokenAlternateProtocolEntry& broken_alternate_protocol_entry,
+ base::TimeTicks when)
+ : broken_alternate_protocol_entry(broken_alternate_protocol_entry),
+ when(when) {}
+
+ BrokenAlternateProtocolEntry broken_alternate_protocol_entry;
base::TimeTicks when;
};
- typedef std::list<BrokenAlternateProtocolEntry>
+ // Deque of BrokenAlternateProtocolEntryWithTime items, ordered by expiration
+ // time.
+ typedef std::deque<BrokenAlternateProtocolEntryWithTime>
BrokenAlternateProtocolList;
- // Map from host:port to the number of times alternate protocol has
- // been marked broken.
- typedef std::map<HostPortPair, int> BrokenAlternateProtocolMap;
+ // Map from (server, alternate protocol and port) to the number of
+ // times that alternate protocol has been marked broken for that server.
+ typedef std::map<BrokenAlternateProtocolEntry, int>
+ BrokenAlternateProtocolMap;
// Return the iterator for |server|, or for its canonical host, or end.
AlternateProtocolMap::const_iterator GetAlternateProtocolIterator(
@@ -149,8 +177,8 @@
BrokenAlternateProtocolList broken_alternate_protocol_list_;
BrokenAlternateProtocolMap broken_alternate_protocol_map_;
+ IPAddressNumber last_quic_address_;
SpdySettingsMap spdy_settings_map_;
- SupportsQuicMap supports_quic_map_;
ServerNetworkStatsMap server_network_stats_map_;
// Contains a map of servers which could share the same alternate protocol.
// Map from a Canonical host/port (host is some postfix of host names) to an
diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc
index be5e6b9..d6c2c1c 100644
--- a/net/http/http_server_properties_impl_unittest.cc
+++ b/net/http/http_server_properties_impl_unittest.cc
@@ -27,6 +27,11 @@
class HttpServerPropertiesImplTest : public testing::Test {
protected:
+ bool HasAlternateProtocol(const HostPortPair& server) {
+ const AlternateProtocolInfo alternate = impl_.GetAlternateProtocol(server);
+ return alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL;
+ }
+
HttpServerPropertiesImpl impl_;
};
@@ -219,23 +224,23 @@
TEST_F(AlternateProtocolServerPropertiesTest, Basic) {
HostPortPair test_host_port_pair("foo", 80);
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, 1.0);
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
const AlternateProtocolInfo alternate =
impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_EQ(443, alternate.port);
EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
impl_.Clear();
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
}
TEST_F(AlternateProtocolServerPropertiesTest, DefaultProbabilityExcluded) {
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, .99);
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
}
TEST_F(AlternateProtocolServerPropertiesTest, Probability) {
@@ -244,7 +249,7 @@
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, .5);
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
const AlternateProtocolInfo alternate =
impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_EQ(443, alternate.port);
@@ -258,7 +263,7 @@
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, .5);
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
}
TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
@@ -284,8 +289,8 @@
EXPECT_EQ(1234, it->second.port);
EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair1));
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair2));
+ ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair1));
+ ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair2));
alternate = impl_.GetAlternateProtocol(test_host_port_pair1);
EXPECT_TRUE(alternate.is_broken);
alternate = impl_.GetAlternateProtocol(test_host_port_pair2);
@@ -293,26 +298,6 @@
EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
}
-TEST_F(AlternateProtocolServerPropertiesTest, MRUOfHasAlternateProtocol) {
- HostPortPair test_host_port_pair1("foo1", 80);
- impl_.SetAlternateProtocol(test_host_port_pair1, 443, NPN_SPDY_3, 1.0);
- HostPortPair test_host_port_pair2("foo2", 80);
- impl_.SetAlternateProtocol(test_host_port_pair2, 1234, NPN_SPDY_3, 1.0);
-
- const AlternateProtocolMap& map = impl_.alternate_protocol_map();
- AlternateProtocolMap::const_iterator it = map.begin();
- EXPECT_TRUE(it->first.Equals(test_host_port_pair2));
- EXPECT_EQ(1234, it->second.port);
- EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
-
- // HasAlternateProtocol should reorder the AlternateProtocol map.
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair1));
- it = map.begin();
- EXPECT_TRUE(it->first.Equals(test_host_port_pair1));
- EXPECT_EQ(443, it->second.port);
- EXPECT_EQ(NPN_SPDY_3, it->second.protocol);
-}
-
TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternateProtocol) {
HostPortPair test_host_port_pair1("foo1", 80);
impl_.SetAlternateProtocol(test_host_port_pair1, 443, NPN_SPDY_3, 1.0);
@@ -340,7 +325,7 @@
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, 1.0);
impl_.SetBrokenAlternateProtocol(test_host_port_pair);
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
AlternateProtocolInfo alternate =
impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_TRUE(alternate.is_broken);
@@ -354,12 +339,12 @@
HostPortPair test_host_port_pair("foo", 80);
impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, 1.0);
impl_.SetBrokenAlternateProtocol(test_host_port_pair);
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
AlternateProtocolInfo alternate =
impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_TRUE(alternate.is_broken);
impl_.ClearAlternateProtocol(test_host_port_pair);
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
}
TEST_F(AlternateProtocolServerPropertiesTest, Forced) {
@@ -370,7 +355,7 @@
// Verify the forced protocol.
HostPortPair test_host_port_pair("foo", 80);
- EXPECT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_TRUE(HasAlternateProtocol(test_host_port_pair));
AlternateProtocolInfo alternate =
impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_EQ(default_protocol.port, alternate.port);
@@ -378,7 +363,7 @@
// Verify the real protocol overrides the forced protocol.
impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3, 1.0);
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
alternate = impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_EQ(443, alternate.port);
EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
@@ -389,22 +374,22 @@
// Verify the forced protocol is off.
HostPortPair test_host_port_pair2("bar", 80);
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair2));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair2));
}
TEST_F(AlternateProtocolServerPropertiesTest, Canonical) {
HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
- EXPECT_FALSE(impl_.HasAlternateProtocol(canonical_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(canonical_port_pair));
AlternateProtocolInfo canonical_protocol(1234, QUIC, 1);
impl_.SetAlternateProtocol(canonical_port_pair, canonical_protocol.port,
canonical_protocol.protocol, 1.0);
// Verify the forced protocol.
- ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ ASSERT_TRUE(HasAlternateProtocol(test_host_port_pair));
AlternateProtocolInfo alternate =
impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_EQ(canonical_protocol.port, alternate.port);
@@ -427,8 +412,8 @@
impl_.SetAlternateProtocol(canonical_port_pair, canonical_protocol.port,
canonical_protocol.protocol,
canonical_protocol.probability);
- EXPECT_FALSE(impl_.HasAlternateProtocol(canonical_port_pair));
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(canonical_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
}
TEST_F(AlternateProtocolServerPropertiesTest, CanonicalAboveThreshold) {
@@ -441,8 +426,8 @@
impl_.SetAlternateProtocol(canonical_port_pair, canonical_protocol.port,
canonical_protocol.protocol,
canonical_protocol.probability);
- EXPECT_TRUE(impl_.HasAlternateProtocol(canonical_port_pair));
- EXPECT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_TRUE(HasAlternateProtocol(canonical_port_pair));
+ EXPECT_TRUE(HasAlternateProtocol(test_host_port_pair));
}
TEST_F(AlternateProtocolServerPropertiesTest, ClearCanonical) {
@@ -456,7 +441,7 @@
canonical_protocol.probability);
impl_.ClearAlternateProtocol(canonical_port_pair);
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
}
TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken) {
@@ -470,7 +455,7 @@
canonical_protocol.probability);
impl_.SetBrokenAlternateProtocol(canonical_port_pair);
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
}
TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken2) {
@@ -500,7 +485,7 @@
canonical_protocol.probability);
impl_.Clear();
- EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+ EXPECT_FALSE(HasAlternateProtocol(test_host_port_pair));
}
typedef HttpServerPropertiesImplTest SpdySettingsServerPropertiesTest;
@@ -695,37 +680,37 @@
TEST_F(SupportsQuicServerPropertiesTest, Initialize) {
HostPortPair quic_server_google("www.google.com", 443);
- // Check by initializing empty SupportsQuic.
- SupportsQuicMap supports_quic_map;
- impl_.InitializeSupportsQuic(&supports_quic_map);
- SupportsQuic supports_quic = impl_.GetSupportsQuic(quic_server_google);
- EXPECT_FALSE(supports_quic.used_quic);
- EXPECT_EQ("", supports_quic.address);
+ // Check by initializing empty address.
+ IPAddressNumber initial_address;
+ impl_.InitializeSupportsQuic(&initial_address);
- // Check by initializing with www.google.com:443.
- SupportsQuic supports_quic1(true, "foo");
- supports_quic_map.insert(std::make_pair(quic_server_google, supports_quic1));
- impl_.InitializeSupportsQuic(&supports_quic_map);
+ IPAddressNumber address;
+ EXPECT_FALSE(impl_.GetSupportsQuic(&address));
+ EXPECT_TRUE(address.empty());
- SupportsQuic supports_quic2 = impl_.GetSupportsQuic(quic_server_google);
- EXPECT_TRUE(supports_quic2.used_quic);
- EXPECT_EQ("foo", supports_quic2.address);
+ // Check by initializing with a valid address.
+ CHECK(ParseIPLiteralToNumber("127.0.0.1", &initial_address));
+ impl_.InitializeSupportsQuic(&initial_address);
+
+ EXPECT_TRUE(impl_.GetSupportsQuic(&address));
+ EXPECT_EQ(initial_address, address);
}
TEST_F(SupportsQuicServerPropertiesTest, SetSupportsQuic) {
- HostPortPair test_host_port_pair("foo", 80);
- SupportsQuic supports_quic = impl_.GetSupportsQuic(test_host_port_pair);
- EXPECT_FALSE(supports_quic.used_quic);
- EXPECT_EQ("", supports_quic.address);
- impl_.SetSupportsQuic(test_host_port_pair, true, "foo");
- SupportsQuic supports_quic1 = impl_.GetSupportsQuic(test_host_port_pair);
- EXPECT_TRUE(supports_quic1.used_quic);
- EXPECT_EQ("foo", supports_quic1.address);
+ IPAddressNumber address;
+ EXPECT_FALSE(impl_.GetSupportsQuic(&address));
+ EXPECT_TRUE(address.empty());
+
+ IPAddressNumber actual_address;
+ CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+ impl_.SetSupportsQuic(true, actual_address);
+
+ EXPECT_TRUE(impl_.GetSupportsQuic(&address));
+ EXPECT_EQ(actual_address, address);
impl_.Clear();
- SupportsQuic supports_quic2 = impl_.GetSupportsQuic(test_host_port_pair);
- EXPECT_FALSE(supports_quic2.used_quic);
- EXPECT_EQ("", supports_quic2.address);
+
+ EXPECT_FALSE(impl_.GetSupportsQuic(&address));
}
typedef HttpServerPropertiesImplTest ServerNetworkStatsServerPropertiesTest;
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index c02518d..d6bfb38 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -50,6 +50,20 @@
// Persist 200 ServerNetworkStats.
const int kMaxServerNetworkStatsHostsToPersist = 200;
+const char kVersionKey[] = "version";
+const char kServersKey[] = "servers";
+const char kSupportsSpdyKey[] = "supports_spdy";
+const char kSettingsKey[] = "settings";
+const char kSupportsQuicKey[] = "supports_quic";
+const char kUsedQuicKey[] = "used_quic";
+const char kAddressKey[] = "address";
+const char kAlternateProtocolKey[] = "alternate_protocol";
+const char kPortKey[] = "port";
+const char kProtocolKey[] = "protocol_str";
+const char kProbabilityKey[] = "probability";
+const char kNetworkStatsKey[] = "network_stats";
+const char kSrttKey[] = "srtt";
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -113,7 +127,7 @@
version_number = kVersionNumber;
DCHECK_LE(version_number, kVersionNumber);
if (version_number <= kVersionNumber)
- http_server_properties_dict->SetInteger("version", version_number);
+ http_server_properties_dict->SetInteger(kVersionKey, version_number);
}
// This is required for conformance with the HttpServerProperties interface.
@@ -166,12 +180,6 @@
http_server_properties_impl_->MaybeForceHTTP11(server, ssl_config);
}
-bool HttpServerPropertiesManager::HasAlternateProtocol(
- const HostPortPair& server) {
- DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
- return http_server_properties_impl_->HasAlternateProtocol(server);
-}
-
AlternateProtocolInfo HttpServerPropertiesManager::GetAlternateProtocol(
const HostPortPair& server) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
@@ -268,28 +276,20 @@
return http_server_properties_impl_->spdy_settings_map();
}
-SupportsQuic HttpServerPropertiesManager::GetSupportsQuic(
- const HostPortPair& host_port_pair) const {
+bool HttpServerPropertiesManager::GetSupportsQuic(
+ IPAddressNumber* last_address) const {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
- return http_server_properties_impl_->GetSupportsQuic(host_port_pair);
+ return http_server_properties_impl_->GetSupportsQuic(last_address);
}
void HttpServerPropertiesManager::SetSupportsQuic(
- const HostPortPair& host_port_pair,
bool used_quic,
- const std::string& address) {
+ const IPAddressNumber& address) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
- http_server_properties_impl_->SetSupportsQuic(
- host_port_pair, used_quic, address);
+ http_server_properties_impl_->SetSupportsQuic(used_quic, address);
ScheduleUpdatePrefsOnNetworkThread();
}
-const SupportsQuicMap& HttpServerPropertiesManager::supports_quic_map()
- const {
- DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
- return http_server_properties_impl_->supports_quic_map();
-}
-
void HttpServerPropertiesManager::SetServerNetworkStats(
const HostPortPair& host_port_pair,
ServerNetworkStats stats) {
@@ -343,7 +343,7 @@
*pref_service_->GetDictionary(path_);
int version = kMissingVersion;
- if (!http_server_properties_dict.GetIntegerWithoutPathExpansion("version",
+ if (!http_server_properties_dict.GetIntegerWithoutPathExpansion(kVersionKey,
&version)) {
DVLOG(1) << "Missing version. Clearing all properties.";
return;
@@ -353,18 +353,20 @@
// http_server_properties_dict["servers"][server].
const base::DictionaryValue* servers_dict = NULL;
if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
- "servers", &servers_dict)) {
+ kServersKey, &servers_dict)) {
DVLOG(1) << "Malformed http_server_properties for servers.";
return;
}
+ IPAddressNumber* addr = new IPAddressNumber;
+ ReadSupportsQuic(http_server_properties_dict, addr);
+
// String is host/port pair of spdy server.
scoped_ptr<StringVector> spdy_servers(new StringVector);
scoped_ptr<SpdySettingsMap> spdy_settings_map(
new SpdySettingsMap(kMaxSpdySettingsHostsToPersist));
scoped_ptr<AlternateProtocolMap> alternate_protocol_map(
new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist));
- scoped_ptr<SupportsQuicMap> supports_quic_map(new SupportsQuicMap());
scoped_ptr<ServerNetworkStatsMap> server_network_stats_map(
new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist));
@@ -388,123 +390,17 @@
// Get if server supports Spdy.
bool supports_spdy = false;
- if ((server_pref_dict->GetBoolean("supports_spdy", &supports_spdy)) &&
+ if ((server_pref_dict->GetBoolean(kSupportsSpdyKey, &supports_spdy)) &&
supports_spdy) {
spdy_servers->push_back(server_str);
}
- // Get SpdySettings.
- DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
- const base::DictionaryValue* spdy_settings_dict = NULL;
- if (server_pref_dict->GetDictionaryWithoutPathExpansion(
- "settings", &spdy_settings_dict)) {
- SettingsMap settings_map;
- for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
- !dict_it.IsAtEnd();
- dict_it.Advance()) {
- const std::string& id_str = dict_it.key();
- int id = 0;
- if (!base::StringToInt(id_str, &id)) {
- DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str;
- NOTREACHED();
- continue;
- }
- int value = 0;
- if (!dict_it.value().GetAsInteger(&value)) {
- DVLOG(1) << "Malformed value in SpdySettings for server: "
- << server_str;
- NOTREACHED();
- continue;
- }
- SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value);
- settings_map[static_cast<SpdySettingsIds>(id)] = flags_and_value;
- }
- spdy_settings_map->Put(server, settings_map);
- }
-
- // Get alternate_protocol server.
- DCHECK(alternate_protocol_map->Peek(server) ==
- alternate_protocol_map->end());
- const base::DictionaryValue* port_alternate_protocol_dict = NULL;
- if (server_pref_dict->GetDictionaryWithoutPathExpansion(
- "alternate_protocol", &port_alternate_protocol_dict)) {
- int port = 0;
- if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion(
- "port", &port) ||
- !IsPortValid(port)) {
- DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
- detected_corrupted_prefs = true;
- continue;
- }
- std::string protocol_str;
- if (!port_alternate_protocol_dict->GetStringWithoutPathExpansion(
- "protocol_str", &protocol_str)) {
- DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
- detected_corrupted_prefs = true;
- continue;
- }
- AlternateProtocol protocol = AlternateProtocolFromString(protocol_str);
- if (!IsAlternateProtocolValid(protocol)) {
- DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
- detected_corrupted_prefs = true;
- continue;
- }
-
- double probability = 1;
- if (port_alternate_protocol_dict->HasKey("probability") &&
- !port_alternate_protocol_dict->GetDoubleWithoutPathExpansion(
- "probability", &probability)) {
- DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
- detected_corrupted_prefs = true;
- continue;
- }
-
- AlternateProtocolInfo port_alternate_protocol(static_cast<uint16>(port),
- protocol, probability);
- alternate_protocol_map->Put(server, port_alternate_protocol);
- }
-
- // Get SupportsQuic.
- DCHECK(supports_quic_map->find(server) == supports_quic_map->end());
- const base::DictionaryValue* supports_quic_dict = NULL;
- if (server_pref_dict->GetDictionaryWithoutPathExpansion(
- "supports_quic", &supports_quic_dict)) {
- bool used_quic = 0;
- if (!supports_quic_dict->GetBooleanWithoutPathExpansion(
- "used_quic", &used_quic)) {
- DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
- detected_corrupted_prefs = true;
- continue;
- }
- std::string address;
- if (!supports_quic_dict->GetStringWithoutPathExpansion(
- "address", &address)) {
- DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
- detected_corrupted_prefs = true;
- continue;
- }
- SupportsQuic supports_quic(used_quic, address);
- supports_quic_map->insert(std::make_pair(server, supports_quic));
- }
-
- // Get ServerNetworkStats.
- DCHECK(server_network_stats_map->Peek(server) ==
- server_network_stats_map->end());
- const base::DictionaryValue* server_network_stats_dict = NULL;
- if (server_pref_dict->GetDictionaryWithoutPathExpansion(
- "network_stats", &server_network_stats_dict)) {
- int srtt;
- if (!server_network_stats_dict->GetIntegerWithoutPathExpansion("srtt",
- &srtt)) {
- DVLOG(1) << "Malformed ServerNetworkStats for server: " << server_str;
- detected_corrupted_prefs = true;
- continue;
- }
- ServerNetworkStats server_network_stats;
- server_network_stats.srtt = base::TimeDelta::FromInternalValue(srtt);
- // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
- // bandwidth_estimate.
- server_network_stats_map->Put(server, server_network_stats);
+ AddToSpdySettingsMap(server, *server_pref_dict, spdy_settings_map.get());
+ if (!AddToAlternateProtocolMap(server, *server_pref_dict,
+ alternate_protocol_map.get()) ||
+ !AddToNetworkStatsMap(server, *server_pref_dict,
+ server_network_stats_map.get())) {
+ detected_corrupted_prefs = true;
}
}
@@ -514,17 +410,159 @@
&HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
base::Unretained(this), base::Owned(spdy_servers.release()),
base::Owned(spdy_settings_map.release()),
- base::Owned(alternate_protocol_map.release()),
- base::Owned(supports_quic_map.release()),
+ base::Owned(alternate_protocol_map.release()), base::Owned(addr),
base::Owned(server_network_stats_map.release()),
detected_corrupted_prefs));
}
+void HttpServerPropertiesManager::AddToSpdySettingsMap(
+ const HostPortPair& server,
+ const base::DictionaryValue& server_pref_dict,
+ SpdySettingsMap* spdy_settings_map) {
+ // Get SpdySettings.
+ DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
+ const base::DictionaryValue* spdy_settings_dict = NULL;
+ if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
+ kSettingsKey, &spdy_settings_dict)) {
+ return;
+ }
+ SettingsMap settings_map;
+ for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
+ !dict_it.IsAtEnd(); dict_it.Advance()) {
+ const std::string& id_str = dict_it.key();
+ int id = 0;
+ if (!base::StringToInt(id_str, &id)) {
+ DVLOG(1) << "Malformed id in SpdySettings for server: "
+ << server.ToString();
+ NOTREACHED();
+ continue;
+ }
+ int value = 0;
+ if (!dict_it.value().GetAsInteger(&value)) {
+ DVLOG(1) << "Malformed value in SpdySettings for server: "
+ << server.ToString();
+ NOTREACHED();
+ continue;
+ }
+ SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value);
+ settings_map[static_cast<SpdySettingsIds>(id)] = flags_and_value;
+ }
+ spdy_settings_map->Put(server, settings_map);
+}
+
+AlternateProtocolInfo HttpServerPropertiesManager::ParseAlternateProtocolDict(
+ const base::DictionaryValue& alternate_protocol_dict,
+ const std::string& server_str) {
+ AlternateProtocolInfo alternate_protocol;
+ int port = 0;
+ if (!alternate_protocol_dict.GetInteger(kPortKey, &port) ||
+ !IsPortValid(port)) {
+ DVLOG(1) << "Malformed AltSvc port for server: " << server_str;
+ return alternate_protocol;
+ }
+ alternate_protocol.port = static_cast<uint16>(port);
+
+ double probability = 1.0;
+ if (alternate_protocol_dict.HasKey(kProbabilityKey) &&
+ !alternate_protocol_dict.GetDoubleWithoutPathExpansion(kProbabilityKey,
+ &probability)) {
+ DVLOG(1) << "Malformed AltSvc probability for server: " << server_str;
+ return alternate_protocol;
+ }
+ alternate_protocol.probability = probability;
+
+ std::string protocol_str;
+ if (!alternate_protocol_dict.GetStringWithoutPathExpansion(kProtocolKey,
+ &protocol_str)) {
+ DVLOG(1) << "Malformed AltSvc protocol string for server: " << server_str;
+ return alternate_protocol;
+ }
+ AlternateProtocol protocol = AlternateProtocolFromString(protocol_str);
+ if (!IsAlternateProtocolValid(protocol)) {
+ DVLOG(1) << "Invalid AltSvc protocol string for server: " << server_str;
+ return alternate_protocol;
+ }
+ alternate_protocol.protocol = protocol;
+
+ return alternate_protocol;
+}
+
+bool HttpServerPropertiesManager::AddToAlternateProtocolMap(
+ const HostPortPair& server,
+ const base::DictionaryValue& server_pref_dict,
+ AlternateProtocolMap* alternate_protocol_map) {
+ // Get alternate_protocol server.
+ DCHECK(alternate_protocol_map->Peek(server) == alternate_protocol_map->end());
+ const base::DictionaryValue* alternate_protocol_dict = NULL;
+ if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
+ kAlternateProtocolKey, &alternate_protocol_dict)) {
+ return true;
+ }
+ AlternateProtocolInfo alternate_protocol =
+ ParseAlternateProtocolDict(*alternate_protocol_dict, server.ToString());
+ if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
+ return false;
+ alternate_protocol_map->Put(server, alternate_protocol);
+ return true;
+}
+
+bool HttpServerPropertiesManager::ReadSupportsQuic(
+ const base::DictionaryValue& http_server_properties_dict,
+ IPAddressNumber* last_quic_address) {
+ const base::DictionaryValue* supports_quic_dict = NULL;
+ if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
+ kSupportsQuicKey, &supports_quic_dict)) {
+ return true;
+ }
+ bool used_quic = false;
+ if (!supports_quic_dict->GetBooleanWithoutPathExpansion(kUsedQuicKey,
+ &used_quic)) {
+ DVLOG(1) << "Malformed SupportsQuic";
+ return false;
+ }
+ if (!used_quic)
+ return false;
+
+ std::string address;
+ if (!supports_quic_dict->GetStringWithoutPathExpansion(kAddressKey,
+ &address) ||
+ !ParseIPLiteralToNumber(address, last_quic_address)) {
+ DVLOG(1) << "Malformed SupportsQuic";
+ return false;
+ }
+ return true;
+}
+
+bool HttpServerPropertiesManager::AddToNetworkStatsMap(
+ const HostPortPair& server,
+ const base::DictionaryValue& server_pref_dict,
+ ServerNetworkStatsMap* network_stats_map) {
+ DCHECK(network_stats_map->Peek(server) == network_stats_map->end());
+ const base::DictionaryValue* server_network_stats_dict = NULL;
+ if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
+ kNetworkStatsKey, &server_network_stats_dict)) {
+ return true;
+ }
+ int srtt;
+ if (!server_network_stats_dict->GetIntegerWithoutPathExpansion(kSrttKey,
+ &srtt)) {
+ DVLOG(1) << "Malformed ServerNetworkStats for server: "
+ << server.ToString();
+ return false;
+ }
+ ServerNetworkStats server_network_stats;
+ server_network_stats.srtt = base::TimeDelta::FromInternalValue(srtt);
+ // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
+ // bandwidth_estimate.
+ network_stats_map->Put(server, server_network_stats);
+ return true;
+}
+
void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
StringVector* spdy_servers,
SpdySettingsMap* spdy_settings_map,
AlternateProtocolMap* alternate_protocol_map,
- SupportsQuicMap* supports_quic_map,
+ IPAddressNumber* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
bool detected_corrupted_prefs) {
// Preferences have the master data because admins might have pushed new
@@ -546,7 +584,7 @@
http_server_properties_impl_->InitializeAlternateProtocolServers(
alternate_protocol_map);
- http_server_properties_impl_->InitializeSupportsQuic(supports_quic_map);
+ http_server_properties_impl_->InitializeSupportsQuic(last_quic_address);
http_server_properties_impl_->InitializeServerNetworkStats(
server_network_stats_map);
@@ -623,14 +661,6 @@
++count;
}
- SupportsQuicMap* supports_quic_map = new SupportsQuicMap();
- const SupportsQuicMap& main_supports_quic_map =
- http_server_properties_impl_->supports_quic_map();
- for (SupportsQuicMap::const_iterator it = main_supports_quic_map.begin();
- it != main_supports_quic_map.end(); ++it) {
- supports_quic_map->insert(std::make_pair(it->first, it->second));
- }
-
ServerNetworkStatsMap* server_network_stats_map =
new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist);
const ServerNetworkStatsMap& main_server_network_stats_map =
@@ -641,13 +671,15 @@
server_network_stats_map->Put(it->first, it->second);
}
+ IPAddressNumber* last_quic_addr = new IPAddressNumber;
+ http_server_properties_impl_->GetSupportsQuic(last_quic_addr);
// Update the preferences on the pref thread.
pref_task_runner_->PostTask(
FROM_HERE,
base::Bind(
&HttpServerPropertiesManager::UpdatePrefsOnPrefThread, pref_weak_ptr_,
base::Owned(spdy_server_list), base::Owned(spdy_settings_map),
- base::Owned(alternate_protocol_map), base::Owned(supports_quic_map),
+ base::Owned(alternate_protocol_map), base::Owned(last_quic_addr),
base::Owned(server_network_stats_map), completion));
}
@@ -682,7 +714,7 @@
base::ListValue* spdy_server_list,
SpdySettingsMap* spdy_settings_map,
AlternateProtocolMap* alternate_protocol_map,
- SupportsQuicMap* supports_quic_map,
+ IPAddressNumber* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
const base::Closure& completion) {
typedef std::map<HostPortPair, ServerPref> ServerPrefMap;
@@ -697,14 +729,7 @@
++list_it) {
if ((*list_it)->GetAsString(&s)) {
HostPortPair server = HostPortPair::FromString(s);
-
- ServerPrefMap::iterator it = server_pref_map.find(server);
- if (it == server_pref_map.end()) {
- ServerPref server_pref(true, NULL, NULL, NULL, NULL);
- server_pref_map[server] = server_pref;
- } else {
- it->second.supports_spdy = true;
- }
+ server_pref_map[server].supports_spdy = true;
}
}
@@ -712,14 +737,7 @@
for (SpdySettingsMap::iterator map_it = spdy_settings_map->begin();
map_it != spdy_settings_map->end(); ++map_it) {
const HostPortPair& server = map_it->first;
-
- ServerPrefMap::iterator it = server_pref_map.find(server);
- if (it == server_pref_map.end()) {
- ServerPref server_pref(false, &map_it->second, NULL, NULL, NULL);
- server_pref_map[server] = server_pref;
- } else {
- it->second.settings_map = &map_it->second;
- }
+ server_pref_map[server].settings_map = &map_it->second;
}
// Add AlternateProtocol servers to server_pref_map.
@@ -731,28 +749,7 @@
if (!IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
continue;
}
-
- ServerPrefMap::iterator it = server_pref_map.find(server);
- if (it == server_pref_map.end()) {
- ServerPref server_pref(false, NULL, &map_it->second, NULL, NULL);
- server_pref_map[server] = server_pref;
- } else {
- it->second.alternate_protocol = &map_it->second;
- }
- }
-
- // Add SupportsQuic servers to server_pref_map.
- for (SupportsQuicMap::const_iterator map_it = supports_quic_map->begin();
- map_it != supports_quic_map->end(); ++map_it) {
- const HostPortPair& server = map_it->first;
-
- ServerPrefMap::iterator it = server_pref_map.find(server);
- if (it == server_pref_map.end()) {
- ServerPref server_pref(false, NULL, NULL, &map_it->second, NULL);
- server_pref_map[server] = server_pref;
- } else {
- it->second.supports_quic = &map_it->second;
- }
+ server_pref_map[server].alternate_protocol = &map_it->second;
}
// Add ServerNetworkStats servers to server_pref_map.
@@ -760,14 +757,7 @@
server_network_stats_map->begin();
map_it != server_network_stats_map->end(); ++map_it) {
const HostPortPair& server = map_it->first;
-
- ServerPrefMap::iterator it = server_pref_map.find(server);
- if (it == server_pref_map.end()) {
- ServerPref server_pref(false, NULL, NULL, NULL, &map_it->second);
- server_pref_map[server] = server_pref;
- } else {
- it->second.server_network_stats = &map_it->second;
- }
+ server_pref_map[server].server_network_stats = &map_it->second;
}
// Persist properties to the |path_|.
@@ -783,69 +773,22 @@
// Save supports_spdy.
if (server_pref.supports_spdy)
- server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy);
-
- // Save SPDY settings.
- if (server_pref.settings_map) {
- base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
- for (SettingsMap::const_iterator it = server_pref.settings_map->begin();
- it != server_pref.settings_map->end(); ++it) {
- SpdySettingsIds id = it->first;
- uint32 value = it->second.second;
- std::string key = base::StringPrintf("%u", id);
- spdy_settings_dict->SetInteger(key, value);
- }
- server_pref_dict->SetWithoutPathExpansion("settings", spdy_settings_dict);
- }
-
- // Save alternate_protocol.
- const AlternateProtocolInfo* port_alternate_protocol =
- server_pref.alternate_protocol;
- if (port_alternate_protocol && !port_alternate_protocol->is_broken) {
- base::DictionaryValue* port_alternate_protocol_dict =
- new base::DictionaryValue;
- port_alternate_protocol_dict->SetInteger("port",
- port_alternate_protocol->port);
- const char* protocol_str =
- AlternateProtocolToString(port_alternate_protocol->protocol);
- port_alternate_protocol_dict->SetString("protocol_str", protocol_str);
- port_alternate_protocol_dict->SetDouble(
- "probability", port_alternate_protocol->probability);
- server_pref_dict->SetWithoutPathExpansion(
- "alternate_protocol", port_alternate_protocol_dict);
- }
-
- // Save supports_quic.
- if (server_pref.supports_quic) {
- base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
- const SupportsQuic* supports_quic = server_pref.supports_quic;
- supports_quic_dict->SetBoolean("used_quic", supports_quic->used_quic);
- supports_quic_dict->SetString("address", supports_quic->address);
- server_pref_dict->SetWithoutPathExpansion(
- "supports_quic", supports_quic_dict);
- }
-
- // Save ServerNetworkStats.
- if (server_pref.server_network_stats) {
- base::DictionaryValue* server_network_stats_dict =
- new base::DictionaryValue;
- const ServerNetworkStats* server_network_stats =
- server_pref.server_network_stats;
- // Becasue JSON doesn't support int64, persist int64 as a string.
- server_network_stats_dict->SetInteger(
- "srtt",
- static_cast<int>(server_network_stats->srtt.ToInternalValue()));
- // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
- // bandwidth_estimate.
- server_pref_dict->SetWithoutPathExpansion("network_stats",
- server_network_stats_dict);
- }
+ server_pref_dict->SetBoolean(kSupportsSpdyKey, server_pref.supports_spdy);
+ SaveSpdySettingsToServerPrefs(server_pref.settings_map, server_pref_dict);
+ SaveAlternateProtocolToServerPrefs(server_pref.alternate_protocol,
+ server_pref_dict);
+ SaveNetworkStatsToServerPrefs(server_pref.server_network_stats,
+ server_pref_dict);
servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
}
- http_server_properties_dict.SetWithoutPathExpansion("servers", servers_dict);
+ http_server_properties_dict.SetWithoutPathExpansion(kServersKey,
+ servers_dict);
SetVersion(&http_server_properties_dict, kVersionNumber);
+
+ SaveSupportsQuicToPrefs(last_quic_address, &http_server_properties_dict);
+
setting_prefs_ = true;
pref_service_->Set(path_, http_server_properties_dict);
setting_prefs_ = false;
@@ -858,6 +801,72 @@
completion.Run();
}
+void HttpServerPropertiesManager::SaveSpdySettingsToServerPrefs(
+ const SettingsMap* settings_map,
+ base::DictionaryValue* server_pref_dict) {
+ if (!settings_map) {
+ return;
+ }
+ base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
+ for (SettingsMap::const_iterator it = settings_map->begin();
+ it != settings_map->end(); ++it) {
+ SpdySettingsIds id = it->first;
+ uint32 value = it->second.second;
+ std::string key = base::StringPrintf("%u", id);
+ spdy_settings_dict->SetInteger(key, value);
+ }
+ server_pref_dict->SetWithoutPathExpansion(kSettingsKey, spdy_settings_dict);
+}
+
+void HttpServerPropertiesManager::SaveAlternateProtocolToServerPrefs(
+ const AlternateProtocolInfo* port_alternate_protocol,
+ base::DictionaryValue* server_pref_dict) {
+ if (!port_alternate_protocol || port_alternate_protocol->is_broken)
+ return;
+
+ base::DictionaryValue* port_alternate_protocol_dict =
+ new base::DictionaryValue;
+ port_alternate_protocol_dict->SetInteger(kPortKey,
+ port_alternate_protocol->port);
+ const char* protocol_str =
+ AlternateProtocolToString(port_alternate_protocol->protocol);
+ port_alternate_protocol_dict->SetString(kProtocolKey, protocol_str);
+ port_alternate_protocol_dict->SetDouble(kProbabilityKey,
+ port_alternate_protocol->probability);
+ server_pref_dict->SetWithoutPathExpansion(kAlternateProtocolKey,
+ port_alternate_protocol_dict);
+}
+
+void HttpServerPropertiesManager::SaveSupportsQuicToPrefs(
+ const IPAddressNumber* last_quic_address,
+ base::DictionaryValue* http_server_properties_dict) {
+ if (!last_quic_address || last_quic_address->empty())
+ return;
+
+ base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
+ supports_quic_dict->SetBoolean(kUsedQuicKey, true);
+ supports_quic_dict->SetString(kAddressKey,
+ IPAddressToString(*last_quic_address));
+ http_server_properties_dict->SetWithoutPathExpansion(kSupportsQuicKey,
+ supports_quic_dict);
+}
+
+void HttpServerPropertiesManager::SaveNetworkStatsToServerPrefs(
+ const ServerNetworkStats* server_network_stats,
+ base::DictionaryValue* server_pref_dict) {
+ if (!server_network_stats)
+ return;
+
+ base::DictionaryValue* server_network_stats_dict = new base::DictionaryValue;
+ // Becasue JSON doesn't support int64, persist int64 as a string.
+ server_network_stats_dict->SetInteger(
+ kSrttKey, static_cast<int>(server_network_stats->srtt.ToInternalValue()));
+ // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
+ // bandwidth_estimate.
+ server_pref_dict->SetWithoutPathExpansion(kNetworkStatsKey,
+ server_network_stats_dict);
+}
+
void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
if (!setting_prefs_)
diff --git a/net/http/http_server_properties_manager.h b/net/http/http_server_properties_manager.h
index 00e5a13..b71671a 100644
--- a/net/http/http_server_properties_manager.h
+++ b/net/http/http_server_properties_manager.h
@@ -86,7 +86,6 @@
void SetHTTP11Required(const HostPortPair& server) override;
void MaybeForceHTTP11(const HostPortPair& server,
SSLConfig* ssl_config) override;
- bool HasAlternateProtocol(const HostPortPair& server) override;
AlternateProtocolInfo GetAlternateProtocol(
const HostPortPair& server) override;
void SetAlternateProtocol(const HostPortPair& server,
@@ -108,12 +107,9 @@
void ClearSpdySettings(const HostPortPair& host_port_pair) override;
void ClearAllSpdySettings() override;
const SpdySettingsMap& spdy_settings_map() const override;
- SupportsQuic GetSupportsQuic(
- const HostPortPair& host_port_pair) const override;
- void SetSupportsQuic(const HostPortPair& host_port_pair,
- bool used_quic,
- const std::string& address) override;
- const SupportsQuicMap& supports_quic_map() const override;
+ bool GetSupportsQuic(IPAddressNumber* last_address) const override;
+ void SetSupportsQuic(bool used_quic,
+ const IPAddressNumber& last_address) override;
void SetServerNetworkStats(const HostPortPair& host_port_pair,
ServerNetworkStats stats) override;
const ServerNetworkStats* GetServerNetworkStats(
@@ -145,7 +141,7 @@
std::vector<std::string>* spdy_servers,
SpdySettingsMap* spdy_settings_map,
AlternateProtocolMap* alternate_protocol_map,
- SupportsQuicMap* supports_quic_map,
+ IPAddressNumber* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
bool detected_corrupted_prefs);
@@ -174,13 +170,41 @@
void UpdatePrefsOnPrefThread(base::ListValue* spdy_server_list,
SpdySettingsMap* spdy_settings_map,
AlternateProtocolMap* alternate_protocol_map,
- SupportsQuicMap* supports_quic_map,
+ IPAddressNumber* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
const base::Closure& completion);
private:
void OnHttpServerPropertiesChanged();
+ bool ReadSupportsQuic(const base::DictionaryValue& server_dict,
+ IPAddressNumber* last_quic_address);
+ void AddToSpdySettingsMap(const HostPortPair& server,
+ const base::DictionaryValue& server_dict,
+ SpdySettingsMap* spdy_settings_map);
+ AlternateProtocolInfo ParseAlternateProtocolDict(
+ const base::DictionaryValue& alternate_protocol_dict,
+ const std::string& server_str);
+ bool AddToAlternateProtocolMap(const HostPortPair& server,
+ const base::DictionaryValue& server_dict,
+ AlternateProtocolMap* alternate_protocol_map);
+ bool AddToNetworkStatsMap(const HostPortPair& server,
+ const base::DictionaryValue& server_dict,
+ ServerNetworkStatsMap* network_stats_map);
+
+ void SaveSpdySettingsToServerPrefs(const SettingsMap* spdy_settings_map,
+ base::DictionaryValue* server_pref_dict);
+ void SaveAlternateProtocolToServerPrefs(
+ const AlternateProtocolInfo* port_alternate_protocol,
+ base::DictionaryValue* server_pref_dict);
+ void SaveNetworkStatsToServerPrefs(
+ const ServerNetworkStats* server_network_stats,
+ base::DictionaryValue* server_pref_dict);
+
+ void SaveSupportsQuicToPrefs(
+ const IPAddressNumber* last_quic_address,
+ base::DictionaryValue* http_server_properties_dict);
+
// -----------
// Pref thread
// -----------
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index d021fc5..f2e3649 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -5,6 +5,7 @@
#include "net/http/http_server_properties_manager.h"
#include "base/basictypes.h"
+#include "base/json/json_writer.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/testing_pref_service.h"
@@ -74,14 +75,14 @@
void(std::vector<std::string>* spdy_servers,
SpdySettingsMap* spdy_settings_map,
AlternateProtocolMap* alternate_protocol_map,
- SupportsQuicMap* supports_quic_map,
+ IPAddressNumber* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
bool detected_corrupted_prefs));
MOCK_METHOD5(UpdatePrefsOnPref,
void(base::ListValue* spdy_server_list,
SpdySettingsMap* spdy_settings_map,
AlternateProtocolMap* alternate_protocol_map,
- SupportsQuicMap* supports_quic_map,
+ IPAddressNumber* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map));
private:
@@ -134,6 +135,12 @@
UpdatePrefsFromCacheOnNetworkThreadConcrete));
}
+ bool HasAlternateProtocol(const HostPortPair& server) {
+ const AlternateProtocolInfo alternate =
+ http_server_props_manager_->GetAlternateProtocol(server);
+ return alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL;
+ }
+
//base::RunLoop loop_;
TestingPrefServiceSimple pref_service_;
scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_;
@@ -163,12 +170,6 @@
server_pref_dict->SetWithoutPathExpansion("alternate_protocol",
alternate_protocol);
- // Set up SupportsQuic for www.google.com:80.
- base::DictionaryValue* supports_quic = new base::DictionaryValue;
- supports_quic->SetBoolean("used_quic", true);
- supports_quic->SetString("address", "foo");
- server_pref_dict->SetWithoutPathExpansion("supports_quic", supports_quic);
-
// Set up ServerNetworkStats for www.google.com:80.
base::DictionaryValue* stats = new base::DictionaryValue;
stats->SetInteger("srtt", 10);
@@ -192,12 +193,6 @@
server_pref_dict1->SetWithoutPathExpansion("alternate_protocol",
alternate_protocol1);
- // Set up SupportsQuic for mail.google.com:80
- base::DictionaryValue* supports_quic1 = new base::DictionaryValue;
- supports_quic1->SetBoolean("used_quic", false);
- supports_quic1->SetString("address", "bar");
- server_pref_dict1->SetWithoutPathExpansion("supports_quic", supports_quic1);
-
// Set up ServerNetworkStats for mail.google.com:80.
base::DictionaryValue* stats1 = new base::DictionaryValue;
stats1->SetInteger("srtt", 20);
@@ -210,6 +205,11 @@
new base::DictionaryValue;
HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict);
+ base::DictionaryValue* supports_quic = new base::DictionaryValue;
+ supports_quic->SetBoolean("used_quic", true);
+ supports_quic->SetString("address", "127.0.0.1");
+ http_server_properties_dict->SetWithoutPathExpansion("supports_quic",
+ supports_quic);
// Set the same value for kHttpServerProperties multiple times.
pref_service_.SetManagedPref(kTestHttpServerProperties,
@@ -230,8 +230,6 @@
HostPortPair::FromString("foo.google.com:1337")));
// Verify AlternateProtocol.
- ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(google_server));
- ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(mail_server));
AlternateProtocolInfo port_alternate_protocol =
http_server_props_manager_->GetAlternateProtocol(google_server);
EXPECT_EQ(443, port_alternate_protocol.port);
@@ -242,13 +240,9 @@
EXPECT_EQ(NPN_SPDY_3_1, port_alternate_protocol.protocol);
// Verify SupportsQuic.
- SupportsQuic supports_quic2 =
- http_server_props_manager_->GetSupportsQuic(google_server);
- EXPECT_TRUE(supports_quic2.used_quic);
- EXPECT_EQ("foo", supports_quic2.address);
- supports_quic2 = http_server_props_manager_->GetSupportsQuic(mail_server);
- EXPECT_FALSE(supports_quic2.used_quic);
- EXPECT_EQ("bar", supports_quic2.address);
+ IPAddressNumber last_address;
+ EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&last_address));
+ EXPECT_EQ("127.0.0.1", IPAddressToString(last_address));
// Verify ServerNetworkStats.
const ServerNetworkStats* stats2 =
@@ -276,12 +270,6 @@
server_pref_dict->SetWithoutPathExpansion("alternate_protocol",
alternate_protocol);
- // Set up SupportsQuic for www.google.com:65536.
- base::DictionaryValue* supports_quic = new base::DictionaryValue;
- supports_quic->SetBoolean("used_quic", true);
- supports_quic->SetString("address", "foo");
- server_pref_dict->SetWithoutPathExpansion("supports_quic", supports_quic);
-
// Set up ServerNetworkStats for www.google.com:65536.
base::DictionaryValue* stats = new base::DictionaryValue;
stats->SetInteger("srtt", 10);
@@ -307,11 +295,8 @@
// Verify that nothing is set.
EXPECT_FALSE(http_server_props_manager_->SupportsRequestPriority(
HostPortPair::FromString("www.google.com:65536")));
- EXPECT_FALSE(http_server_props_manager_->HasAlternateProtocol(
- HostPortPair::FromString("www.google.com:65536")));
- SupportsQuic supports_quic2 = http_server_props_manager_->GetSupportsQuic(
- HostPortPair::FromString("www.google.com:65536"));
- EXPECT_FALSE(supports_quic2.used_quic);
+ EXPECT_FALSE(
+ HasAlternateProtocol(HostPortPair::FromString("www.google.com:65536")));
const ServerNetworkStats* stats1 =
http_server_props_manager_->GetServerNetworkStats(
HostPortPair::FromString("www.google.com:65536"));
@@ -352,8 +337,8 @@
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
// Verify AlternateProtocol is not set.
- EXPECT_FALSE(http_server_props_manager_->HasAlternateProtocol(
- HostPortPair::FromString("www.google.com:80")));
+ EXPECT_FALSE(
+ HasAlternateProtocol(HostPortPair::FromString("www.google.com:80")));
}
TEST_F(HttpServerPropertiesManagerTest, SupportsSpdy) {
@@ -477,12 +462,11 @@
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
}
-TEST_F(HttpServerPropertiesManagerTest, HasAlternateProtocol) {
+TEST_F(HttpServerPropertiesManagerTest, GetAlternateProtocol) {
ExpectPrefsUpdate();
HostPortPair spdy_server_mail("mail.google.com", 80);
- EXPECT_FALSE(
- http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
+ EXPECT_FALSE(HasAlternateProtocol(spdy_server_mail));
http_server_props_manager_->SetAlternateProtocol(spdy_server_mail, 443,
NPN_SPDY_3, 1.0);
@@ -490,32 +474,29 @@
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
- ASSERT_TRUE(
- http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
- AlternateProtocolInfo port_alternate_protocol =
+ const AlternateProtocolInfo alternate_protocol =
http_server_props_manager_->GetAlternateProtocol(spdy_server_mail);
- EXPECT_EQ(443, port_alternate_protocol.port);
- EXPECT_EQ(NPN_SPDY_3, port_alternate_protocol.protocol);
+ EXPECT_EQ(443, alternate_protocol.port);
+ EXPECT_EQ(NPN_SPDY_3, alternate_protocol.protocol);
+ EXPECT_EQ(1.0, alternate_protocol.probability);
}
TEST_F(HttpServerPropertiesManagerTest, SupportsQuic) {
ExpectPrefsUpdate();
- HostPortPair quic_server_mail("mail.google.com", 80);
- SupportsQuic supports_quic =
- http_server_props_manager_->GetSupportsQuic(quic_server_mail);
- EXPECT_FALSE(supports_quic.used_quic);
- EXPECT_EQ("", supports_quic.address);
- http_server_props_manager_->SetSupportsQuic(quic_server_mail, true, "foo");
+ IPAddressNumber address;
+ EXPECT_FALSE(http_server_props_manager_->GetSupportsQuic(&address));
+
+ IPAddressNumber actual_address;
+ CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+ http_server_props_manager_->SetSupportsQuic(true, actual_address);
// Run the task.
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
- SupportsQuic supports_quic1 =
- http_server_props_manager_->GetSupportsQuic(quic_server_mail);
- EXPECT_TRUE(supports_quic1.used_quic);
- EXPECT_EQ("foo", supports_quic1.address);
+ EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
+ EXPECT_EQ(actual_address, address);
}
TEST_F(HttpServerPropertiesManagerTest, ServerNetworkStats) {
@@ -545,7 +526,9 @@
http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
http_server_props_manager_->SetAlternateProtocol(spdy_server_mail, 443,
NPN_SPDY_3, 1.0);
- http_server_props_manager_->SetSupportsQuic(spdy_server_mail, true, "foo");
+ IPAddressNumber actual_address;
+ CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+ http_server_props_manager_->SetSupportsQuic(true, actual_address);
ServerNetworkStats stats;
stats.srtt = base::TimeDelta::FromMicroseconds(10);
http_server_props_manager_->SetServerNetworkStats(spdy_server_mail, stats);
@@ -561,12 +544,10 @@
EXPECT_TRUE(
http_server_props_manager_->SupportsRequestPriority(spdy_server_mail));
- EXPECT_TRUE(
- http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
- SupportsQuic supports_quic =
- http_server_props_manager_->GetSupportsQuic(spdy_server_mail);
- EXPECT_TRUE(supports_quic.used_quic);
- EXPECT_EQ("foo", supports_quic.address);
+ EXPECT_TRUE(HasAlternateProtocol(spdy_server_mail));
+ IPAddressNumber address;
+ EXPECT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
+ EXPECT_EQ(actual_address, address);
const ServerNetworkStats* stats1 =
http_server_props_manager_->GetServerNetworkStats(spdy_server_mail);
EXPECT_EQ(10, stats1->srtt.ToInternalValue());
@@ -591,12 +572,8 @@
EXPECT_FALSE(
http_server_props_manager_->SupportsRequestPriority(spdy_server_mail));
- EXPECT_FALSE(
- http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
- SupportsQuic supports_quic1 =
- http_server_props_manager_->GetSupportsQuic(spdy_server_mail);
- EXPECT_FALSE(supports_quic1.used_quic);
- EXPECT_EQ("", supports_quic1.address);
+ EXPECT_FALSE(HasAlternateProtocol(spdy_server_mail));
+ EXPECT_FALSE(http_server_props_manager_->GetSupportsQuic(&address));
const ServerNetworkStats* stats2 =
http_server_props_manager_->GetServerNetworkStats(spdy_server_mail);
EXPECT_EQ(NULL, stats2);
@@ -629,11 +606,6 @@
// Set the preference for mail.google.com server.
base::DictionaryValue* server_pref_dict1 = new base::DictionaryValue;
- // Set up SupportsQuic for mail.google.com:80
- base::DictionaryValue* supports_quic = new base::DictionaryValue;
- supports_quic->SetBoolean("used_quic", true);
- supports_quic->SetString("address", "bar");
- server_pref_dict1->SetWithoutPathExpansion("supports_quic", supports_quic);
// Set the server preference for mail.google.com:80.
servers_dict->SetWithoutPathExpansion("mail.google.com:80",
@@ -644,6 +616,13 @@
HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict);
+ // Set up SupportsQuic for 127.0.0.1
+ base::DictionaryValue* supports_quic = new base::DictionaryValue;
+ supports_quic->SetBoolean("used_quic", true);
+ supports_quic->SetString("address", "127.0.0.1");
+ http_server_properties_dict->SetWithoutPathExpansion("supports_quic",
+ supports_quic);
+
// Set up the pref.
pref_service_.SetManagedPref(kTestHttpServerProperties,
http_server_properties_dict);
@@ -654,8 +633,6 @@
// Verify AlternateProtocol.
for (int i = 0; i < 200; ++i) {
std::string server = StringPrintf("www.google.com:%d", i);
- ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
- HostPortPair::FromString(server)));
AlternateProtocolInfo port_alternate_protocol =
http_server_props_manager_->GetAlternateProtocol(
HostPortPair::FromString(server));
@@ -664,10 +641,67 @@
}
// Verify SupportsQuic.
- SupportsQuic supports_quic1 = http_server_props_manager_->GetSupportsQuic(
- HostPortPair::FromString("mail.google.com:80"));
- EXPECT_TRUE(supports_quic1.used_quic);
- EXPECT_EQ("bar", supports_quic1.address);
+ IPAddressNumber address;
+ ASSERT_TRUE(http_server_props_manager_->GetSupportsQuic(&address));
+ EXPECT_EQ("127.0.0.1", IPAddressToString(address));
+}
+
+TEST_F(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
+ const HostPortPair server_www("www.google.com", 80);
+ const HostPortPair server_mail("mail.google.com", 80);
+
+ // Set alternate protocol.
+ http_server_props_manager_->SetAlternateProtocol(server_www, 443, NPN_SPDY_3,
+ 1.0);
+ http_server_props_manager_->SetAlternateProtocol(server_mail, 444,
+ NPN_SPDY_3_1, 0.2);
+
+ // Set ServerNetworkStats.
+ ServerNetworkStats stats;
+ stats.srtt = base::TimeDelta::FromInternalValue(42);
+ http_server_props_manager_->SetServerNetworkStats(server_mail, stats);
+
+ // Set SupportsQuic.
+ IPAddressNumber actual_address;
+ CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address));
+ http_server_props_manager_->SetSupportsQuic(true, actual_address);
+
+ // Update cache.
+ ExpectPrefsUpdate();
+ ExpectCacheUpdate();
+ http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
+ base::RunLoop().RunUntilIdle();
+
+ // Verify preferences.
+ const char expected_json[] = "{"
+ "\"servers\":{"
+ "\"mail.google.com:80\":{"
+ "\"alternate_protocol\":{"
+ "\"port\":444,\"probability\":0.2,\"protocol_str\":\"npn-spdy/3.1\""
+ "},"
+ "\"network_stats\":{"
+ "\"srtt\":42"
+ "}"
+ "},"
+ "\"www.google.com:80\":{"
+ "\"alternate_protocol\":{"
+ "\"port\":443,\"probability\":1.0,\"protocol_str\":\"npn-spdy/3\""
+ "}"
+ "}"
+ "},"
+ "\"supports_quic\":{"
+ "\"address\":\"127.0.0.1\",\"used_quic\":true"
+ "},"
+ "\"version\":3"
+ "}";
+
+ const base::Value* http_server_properties =
+ pref_service_.GetUserPref(kTestHttpServerProperties);
+ ASSERT_NE(nullptr, http_server_properties);
+ std::string preferences_json;
+ EXPECT_TRUE(
+ base::JSONWriter::Write(http_server_properties, &preferences_json));
+ EXPECT_EQ(expected_json, preferences_json);
}
TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) {
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index f84b80c..754372b 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -86,14 +86,6 @@
if (mapping_rules)
mapping_rules->RewriteHost(&host_port);
- if (http_server_properties->HasAlternateProtocol(host_port)) {
- const AlternateProtocolInfo existing_alternate =
- http_server_properties->GetAlternateProtocol(host_port);
- // If we think the alternate protocol is broken, don't change it.
- if (existing_alternate.is_broken)
- return;
- }
-
http_server_properties->SetAlternateProtocol(
host_port, static_cast<uint16>(port), protocol, probability);
}
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index 9e932ee..235122d 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -24,11 +24,10 @@
GURL UpgradeUrlToHttps(const GURL& original_url, int port) {
GURL::Replacements replacements;
- // new_sheme and new_port need to be in scope here because GURL::Replacements
- // references the memory contained by them directly.
- const std::string new_scheme = "https";
+ // new_port needs to be in scope here because GURL::Replacements references
+ // the memory contained by it directly.
const std::string new_port = base::IntToString(port);
- replacements.SetSchemeStr(new_scheme);
+ replacements.SetSchemeStr("https");
replacements.SetPortStr(new_port);
return original_url.ReplaceComponents(replacements);
}
@@ -175,8 +174,7 @@
AlternateProtocolInfo HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
const GURL& original_url,
GURL* alternate_url) {
- const AlternateProtocolInfo kNoAlternateProtocol =
- AlternateProtocolInfo(0, UNINITIALIZED_ALTERNATE_PROTOCOL, 0);
+ const AlternateProtocolInfo kNoAlternateProtocol;
if (!session_->params().use_alternate_protocols)
return kNoAlternateProtocol;
@@ -185,19 +183,17 @@
return kNoAlternateProtocol;
HostPortPair origin = HostPortPair::FromURL(original_url);
-
HttpServerProperties& http_server_properties =
*session_->http_server_properties();
- if (!http_server_properties.HasAlternateProtocol(origin))
- return kNoAlternateProtocol;
-
- AlternateProtocolInfo alternate =
+ const AlternateProtocolInfo alternate =
http_server_properties.GetAlternateProtocol(origin);
+
+ if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
+ return kNoAlternateProtocol;
if (alternate.is_broken) {
HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_BROKEN);
return kNoAlternateProtocol;
}
-
if (!IsAlternateProtocolValid(alternate.protocol)) {
NOTREACHED();
return kNoAlternateProtocol;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 45a0970..8729dfb 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -436,6 +437,10 @@
}
void HttpStreamFactoryImpl::Job::OnIOComplete(int result) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "455884 HttpStreamFactoryImpl::Job::OnIOComplete"));
RunLoop(result);
}
diff --git a/net/interfaces/BUILD.gn b/net/interfaces/BUILD.gn
new file mode 100644
index 0000000..03a0778
--- /dev/null
+++ b/net/interfaces/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni")
+
+mojom("interfaces") {
+ sources = [
+ "host_resolver_service.mojom",
+ "proxy_resolver_service.mojom",
+ ]
+}
diff --git a/net/interfaces/host_resolver_service.mojom b/net/interfaces/host_resolver_service.mojom
new file mode 100644
index 0000000..c8acc38
--- /dev/null
+++ b/net/interfaces/host_resolver_service.mojom
@@ -0,0 +1,55 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// WARNING! Do NOT use this mojom. It is intended as a temporary interface to
+// implement out-of-process proxy resolution. If you wish to use a Mojo DNS
+// service, contact amistry@/sammc@ and net-dev to discuss a permanent Mojo DNS
+// interface.
+
+// Put Mojo definitions into their own namespace to avoid collisions with C++
+// definitions.
+// TODO(amistry): Resolve the conflict between these two sets of definitions.
+module net.interfaces;
+
+// Mirror of net::AddressFamily.
+enum AddressFamily {
+ UNSPECIFIED,
+ IPV4,
+ IPV6,
+};
+
+// Mirror of net::HostResolver::RequestInfo.
+struct HostResolverRequestInfo {
+ string host;
+ uint16 port;
+ AddressFamily address_family;
+ bool is_my_ip_address;
+};
+
+// Mirror of net::IPEndPoint.
+struct IPEndPoint {
+ // IP address as a numeric value from most to least significant byte.
+ // Will be of length 4 for IPv4 addresses and 16 for IPv6.
+ array<uint8> address;
+ uint16 port;
+};
+
+// Mirror of net::AddressList.
+struct AddressList {
+ array<IPEndPoint> addresses;
+};
+
+interface HostResolverService {
+ // Use a HostResolverRequestClient instead of returning a result so we can
+ // cancel in-flight requests by destroying the client. IPC requests in Mojo
+ // cannot be cancelled directly.
+ // TODO(amistry): Add BoundNetLog.
+ Resolve(HostResolverRequestInfo request_info,
+ HostResolverRequestClient client);
+};
+
+interface HostResolverRequestClient {
+ // |error| is a value in net::Error.
+ ReportResult(int32 error, AddressList? result);
+};
diff --git a/net/interfaces/proxy_resolver_service.mojom b/net/interfaces/proxy_resolver_service.mojom
new file mode 100644
index 0000000..2cb7a0b
--- /dev/null
+++ b/net/interfaces/proxy_resolver_service.mojom
@@ -0,0 +1,48 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Put Mojo definitions into their own namespace to avoid collisions with C++
+// definitions.
+// TODO(amistry): Resolve the conflict between these two sets of definitions.
+module net.interfaces;
+
+import "host_resolver_service.mojom";
+
+// Mirror of net::ProxyServer::Scheme.
+enum ProxyScheme {
+ INVALID,
+ DIRECT,
+ HTTP,
+ SOCKS4,
+ SOCKS5,
+ HTTPS,
+ QUIC,
+};
+
+// Mirror of net::ProxyServer.
+struct ProxyServer {
+ ProxyScheme scheme;
+ string host;
+ uint16 port;
+};
+
+interface ProxyResolverService {
+ SetPacScript(string data) => (int32 result);
+
+ // Use a ProxyResolverRequestClient instead of returning a result so we can
+ // receive load state updates and cancel in-flight requests by destroying the
+ // client.
+ // TODO(amistry): Add BoundNetLog.
+ GetProxyForUrl(string url, ProxyResolverRequestClient client);
+};
+
+interface ProxyResolverRequestClient {
+ ReportResult(int32 error, array<ProxyServer>? proxy_servers);
+};
+
+interface ProxyResolverFactory {
+ // TODO(amistry): Add NetLog and ProxyResolverErrorObserver.
+ CreateResolver(ProxyResolverService& resolver,
+ HostResolverService host_resolver);
+};
diff --git a/net/net.gyp b/net/net.gyp
index 834a4c6..cd381e0 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -837,6 +837,7 @@
'cookies/cookie_monster_perftest.cc',
'disk_cache/blockfile/disk_cache_perftest.cc',
'proxy/proxy_resolver_perftest.cc',
+ 'udp/udp_socket_perftest.cc',
'websockets/websocket_frame_perftest.cc',
],
'conditions': [
@@ -1203,6 +1204,22 @@
},
],
}],
+ ['use_v8_in_net == 1 and OS != "android"', {
+ 'targets': [
+ {
+ # GN version: //net/interfaces
+ 'target_name': 'net_interfaces',
+ 'type': 'static_library',
+ 'sources': [
+ 'interfaces/host_resolver_service.mojom',
+ 'interfaces/proxy_resolver_service.mojom',
+ ],
+ 'includes': [
+ '../third_party/mojo/mojom_bindings_generator.gypi',
+ ],
+ },
+ ],
+ }],
['OS != "ios" and OS != "android"', {
'targets': [
# iOS doesn't have the concept of simple executables, these targets
diff --git a/net/net.gypi b/net/net.gypi
index 5b5a5f9..e3f0ee1 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -607,7 +607,6 @@
'http/disk_cache_based_quic_server_info.h',
'http/failing_http_transaction_factory.cc',
'http/failing_http_transaction_factory.h',
- 'http/http_atom_list.h',
'http/http_auth.cc',
'http/http_auth.h',
'http/http_auth_cache.cc',
diff --git a/net/net_unittests.isolate b/net/net_unittests.isolate
index e062a7d..877c21e 100644
--- a/net/net_unittests.isolate
+++ b/net/net_unittests.isolate
@@ -19,6 +19,8 @@
'--test-launcher-bot-mode',
'--asan=<(asan)',
'--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
],
'files': [
'../testing/test_env.py',
@@ -32,6 +34,13 @@
'read_only': 1,
},
}],
+ ['OS=="mac" and asan==1', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/net_unittests.dSYM/',
+ ],
+ },
+ }],
['OS=="win" and (fastbuild==0 or fastbuild==1)', {
'variables': {
'files': [
diff --git a/net/proxy/polling_proxy_config_service.cc b/net/proxy/polling_proxy_config_service.cc
index 611ea59..7c086db 100644
--- a/net/proxy/polling_proxy_config_service.cc
+++ b/net/proxy/polling_proxy_config_service.cc
@@ -9,6 +9,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/observer_list.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/synchronization/lock.h"
#include "base/threading/worker_pool.h"
#include "net/proxy/proxy_config.h"
@@ -113,6 +114,11 @@
// Called after the worker thread has finished retrieving a configuration.
void GetConfigCompleted(const ProxyConfig& config) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455942 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "455942 PollingProxyConfigService::Core::GetConfigCompleted"));
DCHECK(poll_task_outstanding_);
poll_task_outstanding_ = false;
diff --git a/net/proxy/proxy_config_service_android.cc b/net/proxy/proxy_config_service_android.cc
index 80e3b92..503388a 100644
--- a/net/proxy/proxy_config_service_android.cc
+++ b/net/proxy/proxy_config_service_android.cc
@@ -302,12 +302,12 @@
explicit JNIDelegateImpl(Delegate* delegate) : delegate_(delegate) {}
// ProxyConfigServiceAndroid::JNIDelegate overrides.
- virtual void ProxySettingsChangedTo(JNIEnv* env,
- jobject jself,
- jstring jhost,
- jint jport,
- jstring jpac_url,
- jobjectArray jexclusion_list) override {
+ void ProxySettingsChangedTo(JNIEnv* env,
+ jobject jself,
+ jstring jhost,
+ jint jport,
+ jstring jpac_url,
+ jobjectArray jexclusion_list) override {
std::string host = ConvertJavaStringToUTF8(env, jhost);
std::string pac_url;
if (jpac_url)
@@ -318,7 +318,7 @@
delegate_->ProxySettingsChangedTo(host, jport, pac_url, exclusion_list);
}
- virtual void ProxySettingsChanged(JNIEnv* env, jobject self) override {
+ void ProxySettingsChanged(JNIEnv* env, jobject self) override {
delegate_->ProxySettingsChanged();
}
diff --git a/net/proxy/proxy_config_service_android.h b/net/proxy/proxy_config_service_android.h
index cb15bc5..64e6b49 100644
--- a/net/proxy/proxy_config_service_android.h
+++ b/net/proxy/proxy_config_service_android.h
@@ -59,7 +59,7 @@
const scoped_refptr<base::SequencedTaskRunner>& network_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& jni_task_runner);
- virtual ~ProxyConfigServiceAndroid();
+ ~ProxyConfigServiceAndroid() override;
// Register JNI bindings.
static bool Register(JNIEnv* env);
@@ -71,9 +71,9 @@
// ProxyConfigService:
// Called only on the network thread.
- virtual void AddObserver(Observer* observer) override;
- virtual void RemoveObserver(Observer* observer) override;
- virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) override;
+ void AddObserver(Observer* observer) override;
+ void RemoveObserver(Observer* observer) override;
+ ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) override;
private:
friend class ProxyConfigServiceAndroidTestBase;
diff --git a/net/proxy/proxy_config_service_android_unittest.cc b/net/proxy/proxy_config_service_android_unittest.cc
index 41f2387..2e4f7bb 100644
--- a/net/proxy/proxy_config_service_android_unittest.cc
+++ b/net/proxy/proxy_config_service_android_unittest.cc
@@ -23,7 +23,7 @@
TestObserver() : availability_(ProxyConfigService::CONFIG_UNSET) {}
// ProxyConfigService::Observer:
- virtual void OnProxyConfigChanged(
+ void OnProxyConfigChanged(
const ProxyConfig& config,
ProxyConfigService::ConfigAvailability availability) override {
config_ = config;
@@ -59,17 +59,15 @@
base::Bind(&ProxyConfigServiceAndroidTestBase::GetProperty,
base::Unretained(this))) {}
- virtual ~ProxyConfigServiceAndroidTestBase() {}
+ ~ProxyConfigServiceAndroidTestBase() override {}
// testing::Test:
- virtual void SetUp() override {
+ void SetUp() override {
message_loop_->RunUntilIdle();
service_.AddObserver(&observer_);
}
- virtual void TearDown() override {
- service_.RemoveObserver(&observer_);
- }
+ void TearDown() override { service_.RemoveObserver(&observer_); }
void ClearConfiguration() {
configuration_.clear();
diff --git a/net/proxy/proxy_config_service_win.cc b/net/proxy/proxy_config_service_win.cc
index 6547659..df9014e 100644
--- a/net/proxy/proxy_config_service_win.cc
+++ b/net/proxy/proxy_config_service_win.cc
@@ -116,7 +116,7 @@
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "ProxyConfigServiceWin_OnObjectSignaled"));
+ "418183 ProxyConfigServiceWin::OnObjectSignaled"));
// Figure out which registry key signalled this change.
RegKeyList::iterator it =
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
index a62732d..bd7d825 100644
--- a/net/proxy/proxy_service.cc
+++ b/net/proxy/proxy_service.cc
@@ -13,6 +13,7 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
@@ -1479,6 +1480,10 @@
void ProxyService::OnProxyConfigChanged(
const ProxyConfig& config,
ProxyConfigService::ConfigAvailability availability) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455942 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "455942 ProxyService::OnProxyConfigChanged"));
// Retrieve the current proxy configuration from the ProxyConfigService.
// If a configuration is not available yet, we will get called back later
// by our ProxyConfigService::Observer once it changes.
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 5219d1e..3c85ca4 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -102,6 +102,21 @@
scoped_ptr<SocketDataProvider> socket_data_;
};
+class ProxyHeadersHandler {
+ public:
+ ProxyHeadersHandler() : was_called_(false) {}
+
+ bool was_called() { return was_called_; }
+
+ void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
+ HttpRequestHeaders* request_headers) {
+ was_called_ = true;
+ }
+
+ private:
+ bool was_called_;
+};
+
class QuicNetworkTransactionTest
: public PlatformTest,
public ::testing::WithParamInterface<QuicVersion> {
@@ -269,11 +284,11 @@
}
void SendRequestAndExpectQuicResponse(const std::string& expected) {
- scoped_ptr<HttpNetworkTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
- RunTransaction(trans.get());
- CheckWasQuicResponse(trans);
- CheckResponseData(trans.get(), expected);
+ SendRequestAndExpectQuicResponseMaybeFromProxy(expected, false);
+ }
+
+ void SendRequestAndExpectQuicResponseFromProxy(const std::string& expected) {
+ SendRequestAndExpectQuicResponseMaybeFromProxy(expected, true);
}
void AddQuicAlternateProtocolMapping(
@@ -284,17 +299,14 @@
}
void ExpectBrokenAlternateProtocolMapping() {
- ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
- HostPortPair::FromURL(request_.url)));
const AlternateProtocolInfo alternate =
session_->http_server_properties()->GetAlternateProtocol(
HostPortPair::FromURL(request_.url));
+ EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL, alternate.protocol);
EXPECT_TRUE(alternate.is_broken);
}
void ExpectQuicAlternateProtocolMapping() {
- ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
- HostPortPair::FromURL(request_.url)));
const AlternateProtocolInfo alternate =
session_->http_server_properties()->GetAlternateProtocol(
HostPortPair::FromURL(request_.url));
@@ -324,6 +336,22 @@
HttpRequestInfo request_;
CapturingBoundNetLog net_log_;
StaticSocketDataProvider hanging_data_;
+
+ private:
+ void SendRequestAndExpectQuicResponseMaybeFromProxy(
+ const std::string& expected,
+ bool used_proxy) {
+ scoped_ptr<HttpNetworkTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
+ ProxyHeadersHandler proxy_headers_handler;
+ trans->SetBeforeProxyHeadersSentCallback(
+ base::Bind(&ProxyHeadersHandler::OnBeforeProxyHeadersSent,
+ base::Unretained(&proxy_headers_handler)));
+ RunTransaction(trans.get());
+ CheckWasQuicResponse(trans);
+ CheckResponseData(trans.get(), expected);
+ EXPECT_EQ(used_proxy, proxy_headers_handler.was_called());
+ }
};
INSTANTIATE_TEST_CASE_P(Version, QuicNetworkTransactionTest,
@@ -414,7 +442,7 @@
CreateSession();
- SendRequestAndExpectQuicResponse("hello!");
+ SendRequestAndExpectQuicResponseFromProxy("hello!");
}
TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index f957c18..3e0f4e3 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -63,9 +63,6 @@
// Set the maximum number of undecryptable packets the connection will store.
const int32 kMaxUndecryptablePackets = 100;
-const char kDummyHostname[] = "quic.global.props";
-const uint16 kDummyPort = 0;
-
void HistogramCreateSessionFailure(enum CreateSessionFailure error) {
UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error,
CREATION_ERROR_MAX);
@@ -619,11 +616,8 @@
void QuicStreamFactory::set_require_confirmation(bool require_confirmation) {
require_confirmation_ = require_confirmation;
if (http_server_properties_ && (!(local_address_ == IPEndPoint()))) {
- // TODO(rtenneti): Delete host_port_pair and persist data in globals.
- HostPortPair host_port_pair(kDummyHostname, kDummyPort);
- http_server_properties_->SetSupportsQuic(
- host_port_pair, !require_confirmation,
- local_address_.ToStringWithoutPort());
+ http_server_properties_->SetSupportsQuic(!require_confirmation,
+ local_address_.address());
}
}
@@ -1002,11 +996,9 @@
socket->GetLocalAddress(&local_address_);
if (check_persisted_supports_quic_ && http_server_properties_) {
check_persisted_supports_quic_ = false;
- // TODO(rtenneti): Delete host_port_pair and persist data in globals.
- HostPortPair host_port_pair(kDummyHostname, kDummyPort);
- SupportsQuic supports_quic(true, local_address_.ToStringWithoutPort());
- if (http_server_properties_->GetSupportsQuic(
- host_port_pair).Equals(supports_quic)) {
+ IPAddressNumber last_address;
+ if (http_server_properties_->GetSupportsQuic(&last_address) &&
+ last_address == local_address_.address()) {
require_confirmation_ = false;
}
}
@@ -1249,7 +1241,9 @@
const HostPortPair& server = server_id.host_port_pair();
// Don't try to change the alternate-protocol state, if the
// alternate-protocol state is unknown.
- if (!http_server_properties_->HasAlternateProtocol(server))
+ const AlternateProtocolInfo alternate =
+ http_server_properties_->GetAlternateProtocol(server);
+ if (alternate.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
return;
// TODO(rch): In the special case where the session has received no
@@ -1258,8 +1252,6 @@
// session connected until the handshake has been confirmed.
HistogramBrokenAlternateProtocolLocation(
BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY);
- AlternateProtocolInfo alternate =
- http_server_properties_->GetAlternateProtocol(server);
DCHECK_EQ(QUIC, alternate.protocol);
// Since the session was active, there's no longer an
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 4092365..4052828 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -1126,6 +1126,10 @@
void ClientSocketPoolBaseHelper::InvokeUserCallback(
ClientSocketHandle* handle) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "455884 ClientSocketPoolBaseHelper::InvokeUserCallback"));
PendingCallbackMap::iterator it = pending_callback_map_.find(handle);
// Exit if the request has already been cancelled.
diff --git a/net/socket/socks_client_socket_pool.cc b/net/socket/socks_client_socket_pool.cc
index e11b7a4..e431227 100644
--- a/net/socket/socks_client_socket_pool.cc
+++ b/net/socket/socks_client_socket_pool.cc
@@ -76,6 +76,9 @@
}
void SOCKSConnectJob::OnIOComplete(int result) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("455884 SOCKSConnectJob::OnIOComplete"));
int rv = DoLoop(result);
if (rv != ERR_IO_PENDING)
NotifyDelegateOfCompletion(rv); // Deletes |this|
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 483c5e7..011474f 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -2288,7 +2288,7 @@
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile1(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "SSLClientSocketNSS::Core::DoReadCallback"));
+ "418183 SSLClientSocketNSS::Core::DoReadCallback"));
PostOrRunCallback(
FROM_HERE,
base::Bind(base::ResetAndReturn(&user_read_callback_), rv));
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 7734d64..bfc37e6 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -247,6 +247,9 @@
}
void SSLConnectJob::OnIOComplete(int result) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455884 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("455884 SSLConnectJob::OnIOComplete"));
int rv = DoLoop(result);
if (rv != ERR_IO_PENDING)
NotifyDelegateOfCompletion(rv); // Deletes |this|.
diff --git a/net/socket/stream_listen_socket.cc b/net/socket/stream_listen_socket.cc
index abb5fbc..619070d 100644
--- a/net/socket/stream_listen_socket.cc
+++ b/net/socket/stream_listen_socket.cc
@@ -249,7 +249,8 @@
void StreamListenSocket::OnObjectSignaled(HANDLE object) {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("StreamListenSocket_OnObjectSignaled"));
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 StreamListenSocket::OnObjectSignaled"));
WSANETWORKEVENTS ev;
if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) {
diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc
index 8eda581..8e719f0 100644
--- a/net/socket/tcp_client_socket.cc
+++ b/net/socket/tcp_client_socket.cc
@@ -327,7 +327,7 @@
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "TCPClientSocket::DidCompleteReadWrite"));
+ "418183 TCPClientSocket::DidCompleteReadWrite"));
callback.Run(result);
}
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc
index 0031c63..538c8d7 100644
--- a/net/socket/tcp_socket_win.cc
+++ b/net/socket/tcp_socket_win.cc
@@ -250,7 +250,7 @@
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "TCPSocketWin_Core_ReadDelegate_OnObjectSignaled"));
+ "418183 TCPSocketWin::Core::ReadDelegate::OnObjectSignaled"));
DCHECK_EQ(object, core_->read_overlapped_.hEvent);
if (core_->socket_) {
@@ -268,7 +268,7 @@
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "TCPSocketWin_Core_WriteDelegate_OnObjectSignaled"));
+ "418183 TCPSocketWin::Core::WriteDelegate::OnObjectSignaled"));
DCHECK_EQ(object, core_->write_overlapped_.hEvent);
if (core_->socket_)
@@ -774,7 +774,8 @@
void TCPSocketWin::OnObjectSignaled(HANDLE object) {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("TCPSocketWin_OnObjectSignaled"));
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418383 TCPSocketWin::OnObjectSignaled"));
WSANETWORKEVENTS ev;
if (WSAEnumNetworkEvents(socket_, accept_event_, &ev) == SOCKET_ERROR) {
@@ -963,6 +964,10 @@
DCHECK(!read_callback_.is_null());
int result;
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is fixed.
+ tracked_objects::ScopedTracker tracking_profile1(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 TCPSocketWin::DidCompleteConnect1"));
WSANETWORKEVENTS events;
int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
&events);
@@ -972,6 +977,11 @@
os_error = WSAGetLastError();
result = MapSystemError(os_error);
} else if (events.lNetworkEvents & FD_CONNECT) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile2(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 TCPSocketWin::DidCompleteConnect2"));
os_error = events.iErrorCode[FD_CONNECT_BIT];
result = MapConnectError(os_error);
} else {
@@ -979,10 +989,18 @@
result = ERR_UNEXPECTED;
}
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is fixed.
+ tracked_objects::ScopedTracker tracking_profile3(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 TCPSocketWin::DidCompleteConnect3"));
connect_os_error_ = os_error;
DoConnectComplete(result);
waiting_connect_ = false;
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is fixed.
+ tracked_objects::ScopedTracker tracking_profile4(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 TCPSocketWin::DidCompleteConnect4"));
DCHECK_NE(result, ERR_IO_PENDING);
base::ResetAndReturn(&read_callback_).Run(result);
}
@@ -1030,6 +1048,9 @@
DCHECK(waiting_read_);
DCHECK(!read_callback_.is_null());
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is fixed.
+ tracked_objects::ScopedTracker tracking_profile1(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("418183 TCPSocketWin::DidSignalRead1"));
int os_error = 0;
WSANETWORKEVENTS network_events;
int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
@@ -1038,6 +1059,11 @@
os_error = WSAGetLastError();
rv = MapSystemError(os_error);
} else if (network_events.lNetworkEvents) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile2(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 TCPSocketWin::DidSignalRead2"));
DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0);
// If network_events.lNetworkEvents is FD_CLOSE and
// network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful
@@ -1058,6 +1084,11 @@
if (rv == ERR_IO_PENDING)
return;
} else {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/418183 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile3(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "418183 TCPSocketWin::DidSignalRead3"));
// This may happen because Read() may succeed synchronously and
// consume all the received data without resetting the event object.
core_->WatchForRead();
@@ -1068,10 +1099,10 @@
core_->read_iobuffer_ = NULL;
core_->read_buffer_length_ = 0;
- DCHECK_NE(rv, ERR_IO_PENDING);
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("TCPSocketWin::DidSignalRead"));
+ tracked_objects::ScopedTracker tracking_profile4(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("418183 TCPSocketWin::DidSignalRead4"));
+ DCHECK_NE(rv, ERR_IO_PENDING);
base::ResetAndReturn(&read_callback_).Run(rv);
}
diff --git a/net/test/spawned_test_server/remote_test_server.h b/net/test/spawned_test_server/remote_test_server.h
index de12e4e..a8b8bb2 100644
--- a/net/test/spawned_test_server/remote_test_server.h
+++ b/net/test/spawned_test_server/remote_test_server.h
@@ -29,7 +29,7 @@
const SSLOptions& ssl_options,
const base::FilePath& document_root);
- virtual ~RemoteTestServer();
+ ~RemoteTestServer() override;
// Starts the Python test server on the host, instead of on the device, and
// blocks until the server is ready.
diff --git a/net/test/spawned_test_server/spawner_communicator.cc b/net/test/spawned_test_server/spawner_communicator.cc
index 53484ea..bb1b445 100644
--- a/net/test/spawned_test_server/spawner_communicator.cc
+++ b/net/test/spawned_test_server/spawner_communicator.cc
@@ -47,7 +47,7 @@
data_received_->clear();
}
- virtual ~SpawnerRequestData() {}
+ ~SpawnerRequestData() override {}
bool DoesRequestIdMatch(int request_id) const {
return request_id_ == request_id;
diff --git a/net/test/spawned_test_server/spawner_communicator.h b/net/test/spawned_test_server/spawner_communicator.h
index 549ad91..ba8bfca 100644
--- a/net/test/spawned_test_server/spawner_communicator.h
+++ b/net/test/spawned_test_server/spawner_communicator.h
@@ -61,7 +61,7 @@
class SpawnerCommunicator : public net::URLRequest::Delegate {
public:
explicit SpawnerCommunicator(uint16 port);
- virtual ~SpawnerCommunicator();
+ ~SpawnerCommunicator() override;
// Starts an instance of the Python test server on the host/ machine.
// If successfully started, returns true, setting |*port| to the port
@@ -100,8 +100,8 @@
std::string* data_received);
// URLRequest::Delegate methods. Called on the IO thread.
- virtual void OnResponseStarted(URLRequest* request) override;
- virtual void OnReadCompleted(URLRequest* request, int num_bytes) override;
+ void OnResponseStarted(URLRequest* request) override;
+ void OnReadCompleted(URLRequest* request, int num_bytes) override;
// Reads Result from the response. Called on the IO thread.
void ReadResult(URLRequest* request);
diff --git a/net/test/url_request/url_request_mock_http_job.cc b/net/test/url_request/url_request_mock_http_job.cc
index 9e63c25..e0905f2 100644
--- a/net/test/url_request/url_request_mock_http_job.cc
+++ b/net/test/url_request/url_request_mock_http_job.cc
@@ -122,16 +122,6 @@
}
// static
-void URLRequestMockHTTPJob::AddHostnameToFileHandler(
- const std::string& hostname,
- const base::FilePath& file,
- const scoped_refptr<base::SequencedWorkerPool>& worker_pool) {
- net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
- filter->AddHostnameInterceptor(
- "http", hostname, CreateInterceptorForSingleFile(file, worker_pool));
-}
-
-// static
GURL URLRequestMockHTTPJob::GetMockUrl(const base::FilePath& path) {
return GetMockUrlForScheme(path, "http");
}
diff --git a/net/test/url_request/url_request_mock_http_job.h b/net/test/url_request/url_request_mock_http_job.h
index 6e454f4..61d5069 100644
--- a/net/test/url_request/url_request_mock_http_job.h
+++ b/net/test/url_request/url_request_mock_http_job.h
@@ -54,13 +54,6 @@
const base::FilePath& base_path,
const scoped_refptr<base::SequencedWorkerPool>& worker_pool);
- // Respond to all HTTP requests of |hostname| with contents of the file
- // located at |file_path|.
- static void AddHostnameToFileHandler(
- const std::string& hostname,
- const base::FilePath& file,
- const scoped_refptr<base::SequencedWorkerPool>& worker_pool);
-
// Given the path to a file relative to the path passed to AddUrlHandler(),
// construct a mock URL.
static GURL GetMockUrl(const base::FilePath& path);
diff --git a/net/tools/net_watcher/net_watcher.cc b/net/tools/net_watcher/net_watcher.cc
index b6cf393..fb5c8e4 100644
--- a/net/tools/net_watcher/net_watcher.cc
+++ b/net/tools/net_watcher/net_watcher.cc
@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/values.h"
#include "build/build_config.h"
#include "net/base/network_change_notifier.h"
@@ -114,6 +115,11 @@
void OnProxyConfigChanged(
const net::ProxyConfig& config,
net::ProxyConfigService::ConfigAvailability availability) override {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455942 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "455942 NetWatcher::OnProxyConfigChanged"));
LOG(INFO) << "OnProxyConfigChanged("
<< ProxyConfigToString(config) << ", "
<< ConfigAvailabilityToString(availability) << ")";
diff --git a/net/udp/udp_client_socket.cc b/net/udp/udp_client_socket.cc
index 9cdaace..8ea024d 100644
--- a/net/udp/udp_client_socket.cc
+++ b/net/udp/udp_client_socket.cc
@@ -62,4 +62,10 @@
return socket_.NetLog();
}
+#if defined(OS_WIN)
+void UDPClientSocket::UseNonBlockingIO() {
+ socket_.UseNonBlockingIO();
+}
+#endif
+
} // namespace net
diff --git a/net/udp/udp_client_socket.h b/net/udp/udp_client_socket.h
index 427db7e..7b4e1a6 100644
--- a/net/udp/udp_client_socket.h
+++ b/net/udp/udp_client_socket.h
@@ -38,6 +38,12 @@
int SetSendBufferSize(int32 size) override;
const BoundNetLog& NetLog() const override;
+#if defined(OS_WIN)
+ // Switch to use non-blocking IO. Must be called right after construction and
+ // before other calls.
+ void UseNonBlockingIO();
+#endif
+
private:
UDPSocket socket_;
DISALLOW_COPY_AND_ASSIGN(UDPClientSocket);
diff --git a/net/udp/udp_server_socket.cc b/net/udp/udp_server_socket.cc
index 4653f71..9fc92df 100644
--- a/net/udp/udp_server_socket.cc
+++ b/net/udp/udp_server_socket.cc
@@ -120,4 +120,10 @@
socket_.DetachFromThread();
}
+#if defined(OS_WIN)
+void UDPServerSocket::UseNonBlockingIO() {
+ socket_.UseNonBlockingIO();
+}
+#endif
+
} // namespace net
diff --git a/net/udp/udp_server_socket.h b/net/udp/udp_server_socket.h
index 0799105..dabb8f0 100644
--- a/net/udp/udp_server_socket.h
+++ b/net/udp/udp_server_socket.h
@@ -47,6 +47,12 @@
int SetDiffServCodePoint(DiffServCodePoint dscp) override;
void DetachFromThread() override;
+#if defined(OS_WIN)
+ // Switch to use non-blocking IO. Must be called right after construction and
+ // before other calls.
+ void UseNonBlockingIO();
+#endif
+
private:
UDPSocket socket_;
bool allow_address_reuse_;
diff --git a/net/udp/udp_socket_perftest.cc b/net/udp/udp_socket_perftest.cc
new file mode 100644
index 0000000..86f0729
--- /dev/null
+++ b/net/udp/udp_socket_perftest.cc
@@ -0,0 +1,141 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/test/perf_time_logger.h"
+#include "net/base/io_buffer.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log_unittest.h"
+#include "net/base/net_util.h"
+#include "net/base/test_completion_callback.h"
+#include "net/test/net_test_suite.h"
+#include "net/udp/udp_client_socket.h"
+#include "net/udp/udp_server_socket.h"
+#include "net/udp/udp_socket.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class UDPSocketPerfTest : public PlatformTest {
+ public:
+ UDPSocketPerfTest()
+ : buffer_(new net::IOBufferWithSize(kPacketSize)), weak_factory_(this) {}
+
+ void DoneWritePacketsToSocket(net::UDPClientSocket* socket,
+ int num_of_packets,
+ base::Closure done_callback,
+ int error) {
+ WritePacketsToSocket(socket, num_of_packets, done_callback);
+ }
+
+ // Send |num_of_packets| to |socket|. Invoke |done_callback| when done.
+ void WritePacketsToSocket(net::UDPClientSocket* socket,
+ int num_of_packets,
+ base::Closure done_callback);
+
+ // Use non-blocking IO if |use_nonblocking_io| is true. This variable only
+ // has effect on Windows.
+ void WriteBenchmark(bool use_nonblocking_io);
+
+ protected:
+ static const int kPacketSize = 1024;
+ scoped_refptr<net::IOBufferWithSize> buffer_;
+ base::WeakPtrFactory<UDPSocketPerfTest> weak_factory_;
+};
+
+// Creates and address from an ip/port and returns it in |address|.
+void CreateUDPAddress(std::string ip_str,
+ uint16 port,
+ net::IPEndPoint* address) {
+ net::IPAddressNumber ip_number;
+ bool rv = net::ParseIPLiteralToNumber(ip_str, &ip_number);
+ if (!rv)
+ return;
+ *address = net::IPEndPoint(ip_number, port);
+}
+
+void UDPSocketPerfTest::WritePacketsToSocket(net::UDPClientSocket* socket,
+ int num_of_packets,
+ base::Closure done_callback) {
+ scoped_refptr<net::IOBufferWithSize> io_buffer(
+ new net::IOBufferWithSize(kPacketSize));
+ memset(io_buffer->data(), 'G', kPacketSize);
+
+ while (num_of_packets) {
+ int rv =
+ socket->Write(io_buffer.get(), io_buffer->size(),
+ base::Bind(&UDPSocketPerfTest::DoneWritePacketsToSocket,
+ weak_factory_.GetWeakPtr(), socket,
+ num_of_packets - 1, done_callback));
+ if (rv == net::ERR_IO_PENDING)
+ break;
+ --num_of_packets;
+ }
+ if (!num_of_packets) {
+ done_callback.Run();
+ return;
+ }
+}
+
+void UDPSocketPerfTest::WriteBenchmark(bool use_nonblocking_io) {
+ base::MessageLoopForIO message_loop;
+ const uint16 kPort = 9999;
+
+ // Setup the server to listen.
+ net::IPEndPoint bind_address;
+ CreateUDPAddress("127.0.0.1", kPort, &bind_address);
+ net::CapturingNetLog server_log;
+ scoped_ptr<net::UDPServerSocket> server(
+ new net::UDPServerSocket(&server_log, net::NetLog::Source()));
+#if defined(OS_WIN)
+ if (use_nonblocking_io)
+ server->UseNonBlockingIO();
+#endif
+ int rv = server->Listen(bind_address);
+ ASSERT_EQ(net::OK, rv);
+
+ // Setup the client.
+ net::IPEndPoint server_address;
+ CreateUDPAddress("127.0.0.1", kPort, &server_address);
+ net::CapturingNetLog client_log;
+ scoped_ptr<net::UDPClientSocket> client(new net::UDPClientSocket(
+ net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(), &client_log,
+ net::NetLog::Source()));
+#if defined(OS_WIN)
+ if (use_nonblocking_io)
+ client->UseNonBlockingIO();
+#endif
+ rv = client->Connect(server_address);
+ EXPECT_EQ(net::OK, rv);
+
+ base::RunLoop run_loop;
+ base::TimeTicks start_ticks = base::TimeTicks::Now();
+ int packets = 100000;
+ client->SetSendBufferSize(1024);
+ WritePacketsToSocket(client.get(), packets, run_loop.QuitClosure());
+ run_loop.Run();
+
+ double elapsed = (base::TimeTicks::Now() - start_ticks).InSecondsF();
+ LOG(INFO) << "Write speed: " << packets / 1024 / elapsed << " MB/s";
+}
+
+TEST_F(UDPSocketPerfTest, Write) {
+ base::PerfTimeLogger timer("UDP_socket_write");
+ WriteBenchmark(false);
+}
+
+#if defined(OS_WIN)
+TEST_F(UDPSocketPerfTest, WriteNonBlocking) {
+ base::PerfTimeLogger timer("UDP_socket_write_nonblocking");
+ WriteBenchmark(true);
+}
+#endif
+
+} // namespace
diff --git a/net/udp/udp_socket_unittest.cc b/net/udp/udp_socket_unittest.cc
index 221be01..4f902a3 100644
--- a/net/udp/udp_socket_unittest.cc
+++ b/net/udp/udp_socket_unittest.cc
@@ -9,7 +9,10 @@
#include "base/basictypes.h"
#include "base/bind.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "base/run_loop.h"
#include "base/stl_util.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
@@ -27,9 +30,7 @@
class UDPSocketTest : public PlatformTest {
public:
- UDPSocketTest()
- : buffer_(new IOBufferWithSize(kMaxRead)) {
- }
+ UDPSocketTest() : buffer_(new IOBufferWithSize(kMaxRead)) {}
// Blocks until data is read from the socket.
std::string RecvFromSocket(UDPServerSocket* socket) {
@@ -112,22 +113,36 @@
return bytes_sent;
}
+ void WriteSocketIgnoreResult(UDPClientSocket* socket, std::string msg) {
+ WriteSocket(socket, msg);
+ }
+
+ // Creates an address from ip address and port and writes it to |*address|.
+ void CreateUDPAddress(std::string ip_str, uint16 port, IPEndPoint* address) {
+ IPAddressNumber ip_number;
+ bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
+ if (!rv)
+ return;
+ *address = IPEndPoint(ip_number, port);
+ }
+
+ // Run unit test for a connection test.
+ // |use_nonblocking_io| is used to switch between overlapped and non-blocking
+ // IO on Windows. It has no effect in other ports.
+ void ConnectTest(bool use_nonblocking_io);
+
protected:
static const int kMaxRead = 1024;
scoped_refptr<IOBufferWithSize> buffer_;
IPEndPoint recv_from_address_;
};
-// Creates and address from an ip/port and returns it in |address|.
-void CreateUDPAddress(std::string ip_str, uint16 port, IPEndPoint* address) {
- IPAddressNumber ip_number;
- bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
- if (!rv)
- return;
- *address = IPEndPoint(ip_number, port);
+void ReadCompleteCallback(int* result_out, base::Closure callback, int result) {
+ *result_out = result;
+ callback.Run();
}
-TEST_F(UDPSocketTest, Connect) {
+void UDPSocketTest::ConnectTest(bool use_nonblocking_io) {
const uint16 kPort = 9999;
std::string simple_message("hello world!");
@@ -137,6 +152,10 @@
CapturingNetLog server_log;
scoped_ptr<UDPServerSocket> server(
new UDPServerSocket(&server_log, NetLog::Source()));
+#if defined(OS_WIN)
+ if (use_nonblocking_io)
+ server->UseNonBlockingIO();
+#endif
server->AllowAddressReuse();
int rv = server->Listen(bind_address);
ASSERT_EQ(OK, rv);
@@ -146,10 +165,13 @@
CreateUDPAddress("127.0.0.1", kPort, &server_address);
CapturingNetLog client_log;
scoped_ptr<UDPClientSocket> client(
- new UDPClientSocket(DatagramSocket::DEFAULT_BIND,
- RandIntCallback(),
- &client_log,
- NetLog::Source()));
+ new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
+ &client_log, NetLog::Source()));
+#if defined(OS_WIN)
+ if (use_nonblocking_io)
+ client->UseNonBlockingIO();
+#endif
+
rv = client->Connect(server_address);
EXPECT_EQ(OK, rv);
@@ -169,6 +191,23 @@
str = ReadSocket(client.get());
DCHECK(simple_message == str);
+ // Test asynchronous read. Server waits for message.
+ base::RunLoop run_loop;
+ int read_result = 0;
+ rv = server->RecvFrom(
+ buffer_.get(), kMaxRead, &recv_from_address_,
+ base::Bind(&ReadCompleteCallback, &read_result, run_loop.QuitClosure()));
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Client sends to the server.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&UDPSocketTest::WriteSocketIgnoreResult,
+ base::Unretained(this), client.get(), simple_message));
+ run_loop.Run();
+ EXPECT_EQ(simple_message.length(), static_cast<size_t>(read_result));
+ EXPECT_EQ(simple_message, std::string(buffer_->data(), read_result));
+
// Delete sockets so they log their final events.
server.reset();
client.reset();
@@ -176,34 +215,48 @@
// Check the server's log.
CapturingNetLog::CapturedEntryList server_entries;
server_log.GetEntries(&server_entries);
- EXPECT_EQ(4u, server_entries.size());
- EXPECT_TRUE(LogContainsBeginEvent(
- server_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
+ EXPECT_EQ(5u, server_entries.size());
+ EXPECT_TRUE(
+ LogContainsBeginEvent(server_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
EXPECT_TRUE(LogContainsEvent(
server_entries, 1, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE));
+ EXPECT_TRUE(LogContainsEvent(server_entries, 2, NetLog::TYPE_UDP_BYTES_SENT,
+ NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEvent(
- server_entries, 2, NetLog::TYPE_UDP_BYTES_SENT, NetLog::PHASE_NONE));
- EXPECT_TRUE(LogContainsEndEvent(
- server_entries, 3, NetLog::TYPE_SOCKET_ALIVE));
+ server_entries, 3, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE));
+ EXPECT_TRUE(
+ LogContainsEndEvent(server_entries, 4, NetLog::TYPE_SOCKET_ALIVE));
// Check the client's log.
CapturingNetLog::CapturedEntryList client_entries;
client_log.GetEntries(&client_entries);
- EXPECT_EQ(6u, client_entries.size());
- EXPECT_TRUE(LogContainsBeginEvent(
- client_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
- EXPECT_TRUE(LogContainsBeginEvent(
- client_entries, 1, NetLog::TYPE_UDP_CONNECT));
- EXPECT_TRUE(LogContainsEndEvent(
- client_entries, 2, NetLog::TYPE_UDP_CONNECT));
- EXPECT_TRUE(LogContainsEvent(
- client_entries, 3, NetLog::TYPE_UDP_BYTES_SENT, NetLog::PHASE_NONE));
+ EXPECT_EQ(7u, client_entries.size());
+ EXPECT_TRUE(
+ LogContainsBeginEvent(client_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
+ EXPECT_TRUE(
+ LogContainsBeginEvent(client_entries, 1, NetLog::TYPE_UDP_CONNECT));
+ EXPECT_TRUE(LogContainsEndEvent(client_entries, 2, NetLog::TYPE_UDP_CONNECT));
+ EXPECT_TRUE(LogContainsEvent(client_entries, 3, NetLog::TYPE_UDP_BYTES_SENT,
+ NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEvent(
client_entries, 4, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE));
- EXPECT_TRUE(LogContainsEndEvent(
- client_entries, 5, NetLog::TYPE_SOCKET_ALIVE));
+ EXPECT_TRUE(LogContainsEvent(client_entries, 5, NetLog::TYPE_UDP_BYTES_SENT,
+ NetLog::PHASE_NONE));
+ EXPECT_TRUE(
+ LogContainsEndEvent(client_entries, 6, NetLog::TYPE_SOCKET_ALIVE));
}
+TEST_F(UDPSocketTest, Connect) {
+ // The variable |use_nonblocking_io| has no effect in non-Windows ports.
+ ConnectTest(false);
+}
+
+#if defined(OS_WIN)
+TEST_F(UDPSocketTest, ConnectNonBlocking) {
+ ConnectTest(true);
+}
+#endif
+
#if defined(OS_MACOSX)
// UDPSocketPrivate_Broadcast is disabled for OSX because it requires
// root permissions on OSX 10.7+.
diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc
index 3c121b2..90ce661 100644
--- a/net/udp/udp_socket_win.cc
+++ b/net/udp/udp_socket_win.cc
@@ -149,7 +149,7 @@
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "UDPSocketWin_Core_ReadDelegate_OnObjectSignaled"));
+ "418183 UDPSocketWin::Core::ReadDelegate::OnObjectSignaled"));
DCHECK_EQ(object, core_->read_overlapped_.hEvent);
if (core_->socket_)
@@ -162,7 +162,7 @@
// TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "UDPSocketWin_Core_WriteDelegate_OnObjectSignaled"));
+ "418183 UDPSocketWin::Core::WriteDelegate::OnObjectSignaled"));
DCHECK_EQ(object, core_->write_overlapped_.hEvent);
if (core_->socket_)
@@ -261,6 +261,9 @@
multicast_time_to_live_(1),
bind_type_(bind_type),
rand_int_cb_(rand_int_cb),
+ use_non_blocking_io_(false),
+ read_iobuffer_len_(0),
+ write_iobuffer_len_(0),
recv_from_address_(NULL),
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)),
qos_handle_(NULL),
@@ -285,7 +288,12 @@
socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
if (socket_ == INVALID_SOCKET)
return MapSystemError(WSAGetLastError());
- core_ = new Core(this);
+ if (!use_non_blocking_io_) {
+ core_ = new Core(this);
+ } else {
+ read_write_event_.Set(WSACreateEvent());
+ WSAEventSelect(socket_, read_write_event_.Get(), FD_READ | FD_WRITE);
+ }
return OK;
}
@@ -312,8 +320,13 @@
addr_family_ = 0;
is_connected_ = false;
- core_->Detach();
- core_ = NULL;
+ read_write_watcher_.StopWatching();
+ read_write_event_.Close();
+
+ if (core_) {
+ core_->Detach();
+ core_ = NULL;
+ }
}
int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
@@ -377,7 +390,8 @@
DCHECK(!callback.is_null()); // Synchronous operation not supported.
DCHECK_GT(buf_len, 0);
- int nread = InternalRecvFrom(buf, buf_len, address);
+ int nread = core_ ? InternalRecvFromOverlapped(buf, buf_len, address)
+ : InternalRecvFromNonBlocking(buf, buf_len, address);
if (nread != ERR_IO_PENDING)
return nread;
@@ -410,7 +424,8 @@
DCHECK_GT(buf_len, 0);
DCHECK(!send_to_address_.get());
- int nwrite = InternalSendTo(buf, buf_len, address);
+ int nwrite = core_ ? InternalSendToOverlapped(buf, buf_len, address)
+ : InternalSendToNonBlocking(buf, buf_len, address);
if (nwrite != ERR_IO_PENDING)
return nwrite;
@@ -573,38 +588,24 @@
WSAResetEvent(core_->read_overlapped_.hEvent);
int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
// Convert address.
- if (recv_from_address_ && result >= 0) {
- if (!ReceiveAddressToIPEndpoint(recv_from_address_))
+ IPEndPoint address;
+ IPEndPoint* address_to_log = NULL;
+ if (result >= 0) {
+ if (address.FromSockAddr(core_->recv_addr_storage_.addr,
+ core_->recv_addr_storage_.addr_len)) {
+ if (recv_from_address_)
+ *recv_from_address_ = address;
+ address_to_log = &address;
+ } else {
result = ERR_ADDRESS_INVALID;
+ }
}
- LogRead(result, core_->read_iobuffer_->data());
+ LogRead(result, core_->read_iobuffer_->data(), address_to_log);
core_->read_iobuffer_ = NULL;
recv_from_address_ = NULL;
DoReadCallback(result);
}
-void UDPSocketWin::LogRead(int result, const char* bytes) const {
- if (result < 0) {
- net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
- return;
- }
-
- if (net_log_.IsLogging()) {
- // Get address for logging, if |address| is NULL.
- IPEndPoint address;
- bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
- net_log_.AddEvent(
- NetLog::TYPE_UDP_BYTES_RECEIVED,
- CreateNetLogUDPDataTranferCallback(
- result, bytes,
- is_address_valid ? &address : NULL));
- }
-
- base::StatsCounter read_bytes("udp.read_bytes");
- read_bytes.Add(result);
- NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
-}
-
void UDPSocketWin::DidCompleteWrite() {
DWORD num_bytes, flags;
BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
@@ -618,6 +619,91 @@
DoWriteCallback(result);
}
+void UDPSocketWin::OnObjectSignaled(HANDLE object) {
+ DCHECK(object == read_write_event_.Get());
+ WSANETWORKEVENTS network_events;
+ int os_error = 0;
+ int rv =
+ WSAEnumNetworkEvents(socket_, read_write_event_.Get(), &network_events);
+ if (rv == SOCKET_ERROR) {
+ os_error = WSAGetLastError();
+ rv = MapSystemError(os_error);
+ if (read_iobuffer_) {
+ read_iobuffer_ = NULL;
+ read_iobuffer_len_ = 0;
+ recv_from_address_ = NULL;
+ DoReadCallback(rv);
+ }
+ if (write_iobuffer_) {
+ write_iobuffer_ = NULL;
+ write_iobuffer_len_ = 0;
+ send_to_address_.reset();
+ DoWriteCallback(rv);
+ }
+ return;
+ }
+ if ((network_events.lNetworkEvents & FD_READ) && read_iobuffer_) {
+ OnReadSignaled();
+ }
+ if ((network_events.lNetworkEvents & FD_WRITE) && write_iobuffer_) {
+ OnWriteSignaled();
+ }
+
+ // There's still pending read / write. Watch for further events.
+ if (read_iobuffer_ || write_iobuffer_) {
+ WatchForReadWrite();
+ }
+}
+
+void UDPSocketWin::OnReadSignaled() {
+ int rv = InternalRecvFromNonBlocking(read_iobuffer_.get(), read_iobuffer_len_,
+ recv_from_address_);
+ if (rv == ERR_IO_PENDING)
+ return;
+ read_iobuffer_ = NULL;
+ read_iobuffer_len_ = 0;
+ recv_from_address_ = NULL;
+ DoReadCallback(rv);
+}
+
+void UDPSocketWin::OnWriteSignaled() {
+ int rv = InternalSendToNonBlocking(write_iobuffer_.get(), write_iobuffer_len_,
+ send_to_address_.get());
+ if (rv == ERR_IO_PENDING)
+ return;
+ write_iobuffer_ = NULL;
+ write_iobuffer_len_ = 0;
+ send_to_address_.reset();
+ DoWriteCallback(rv);
+}
+
+void UDPSocketWin::WatchForReadWrite() {
+ if (read_write_watcher_.IsWatching())
+ return;
+ bool watched =
+ read_write_watcher_.StartWatching(read_write_event_.Get(), this);
+ DCHECK(watched);
+}
+
+void UDPSocketWin::LogRead(int result,
+ const char* bytes,
+ const IPEndPoint* address) const {
+ if (result < 0) {
+ net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
+ return;
+ }
+
+ if (net_log_.IsLogging()) {
+ net_log_.AddEvent(
+ NetLog::TYPE_UDP_BYTES_RECEIVED,
+ CreateNetLogUDPDataTranferCallback(result, bytes, address));
+ }
+
+ base::StatsCounter read_bytes("udp.read_bytes");
+ read_bytes.Add(result);
+ NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
+}
+
void UDPSocketWin::LogWrite(int result,
const char* bytes,
const IPEndPoint* address) const {
@@ -637,8 +723,9 @@
NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result);
}
-int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
- IPEndPoint* address) {
+int UDPSocketWin::InternalRecvFromOverlapped(IOBuffer* buf,
+ int buf_len,
+ IPEndPoint* address) {
DCHECK(!core_->read_iobuffer_.get());
SockaddrStorage& storage = core_->recv_addr_storage_;
storage.addr_len = sizeof(storage.addr_storage);
@@ -657,18 +744,26 @@
if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
int result = num;
// Convert address.
- if (address && result >= 0) {
- if (!ReceiveAddressToIPEndpoint(address))
+ IPEndPoint address_storage;
+ IPEndPoint* address_to_log = NULL;
+ if (result >= 0) {
+ if (address_storage.FromSockAddr(core_->recv_addr_storage_.addr,
+ core_->recv_addr_storage_.addr_len)) {
+ if (address)
+ *address = address_storage;
+ address_to_log = &address_storage;
+ } else {
result = ERR_ADDRESS_INVALID;
+ }
}
- LogRead(result, buf->data());
+ LogRead(result, buf->data(), address_to_log);
return result;
}
} else {
int os_error = WSAGetLastError();
if (os_error != WSA_IO_PENDING) {
int result = MapSystemError(os_error);
- LogRead(result, NULL);
+ LogRead(result, NULL, NULL);
return result;
}
}
@@ -677,8 +772,9 @@
return ERR_IO_PENDING;
}
-int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
- const IPEndPoint* address) {
+int UDPSocketWin::InternalSendToOverlapped(IOBuffer* buf,
+ int buf_len,
+ const IPEndPoint* address) {
DCHECK(!core_->write_iobuffer_.get());
SockaddrStorage storage;
struct sockaddr* addr = storage.addr;
@@ -723,6 +819,78 @@
return ERR_IO_PENDING;
}
+int UDPSocketWin::InternalRecvFromNonBlocking(IOBuffer* buf,
+ int buf_len,
+ IPEndPoint* address) {
+ DCHECK(!read_iobuffer_ || read_iobuffer_.get() == buf);
+ SockaddrStorage storage;
+ storage.addr_len = sizeof(storage.addr_storage);
+
+ CHECK_NE(INVALID_SOCKET, socket_);
+ int rv = recvfrom(socket_, buf->data(), buf_len, 0, storage.addr,
+ &storage.addr_len);
+ if (rv == SOCKET_ERROR) {
+ int os_error = WSAGetLastError();
+ if (os_error == WSAEWOULDBLOCK) {
+ read_iobuffer_ = buf;
+ read_iobuffer_len_ = buf_len;
+ WatchForReadWrite();
+ return ERR_IO_PENDING;
+ }
+ rv = MapSystemError(os_error);
+ LogRead(rv, NULL, NULL);
+ return rv;
+ }
+ IPEndPoint address_storage;
+ IPEndPoint* address_to_log = NULL;
+ if (rv >= 0) {
+ if (address_storage.FromSockAddr(storage.addr, storage.addr_len)) {
+ if (address)
+ *address = address_storage;
+ address_to_log = &address_storage;
+ } else {
+ rv = ERR_ADDRESS_INVALID;
+ }
+ }
+ LogRead(rv, buf->data(), address_to_log);
+ return rv;
+}
+
+int UDPSocketWin::InternalSendToNonBlocking(IOBuffer* buf,
+ int buf_len,
+ const IPEndPoint* address) {
+ DCHECK(!write_iobuffer_ || write_iobuffer_.get() == buf);
+ SockaddrStorage storage;
+ struct sockaddr* addr = storage.addr;
+ // Convert address.
+ if (address) {
+ if (!address->ToSockAddr(addr, &storage.addr_len)) {
+ int result = ERR_ADDRESS_INVALID;
+ LogWrite(result, NULL, NULL);
+ return result;
+ }
+ } else {
+ addr = NULL;
+ storage.addr_len = 0;
+ }
+
+ int rv = sendto(socket_, buf->data(), buf_len, 0, addr, storage.addr_len);
+ if (rv == SOCKET_ERROR) {
+ int os_error = WSAGetLastError();
+ if (os_error == WSAEWOULDBLOCK) {
+ write_iobuffer_ = buf;
+ write_iobuffer_len_ = buf_len;
+ WatchForReadWrite();
+ return ERR_IO_PENDING;
+ }
+ rv = MapSystemError(os_error);
+ LogWrite(rv, NULL, NULL);
+ return rv;
+ }
+ LogWrite(rv, buf->data(), address);
+ return rv;
+}
+
int UDPSocketWin::SetMulticastOptions() {
if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
DWORD loop = 0;
@@ -807,11 +975,6 @@
return DoBind(IPEndPoint(address, 0));
}
-bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
- SockaddrStorage& storage = core_->recv_addr_storage_;
- return address->FromSockAddr(storage.addr, storage.addr_len);
-}
-
int UDPSocketWin::JoinGroup(
const IPAddressNumber& group_address) const {
DCHECK(CalledOnValidThread());
@@ -1016,4 +1179,9 @@
base::NonThreadSafe::DetachFromThread();
}
+void UDPSocketWin::UseNonBlockingIO() {
+ DCHECK(!core_);
+ use_non_blocking_io_ = true;
+}
+
} // namespace net
diff --git a/net/udp/udp_socket_win.h b/net/udp/udp_socket_win.h
index 6f0ec2c..d994eec 100644
--- a/net/udp/udp_socket_win.h
+++ b/net/udp/udp_socket_win.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "base/win/object_watcher.h"
+#include "base/win/scoped_handle.h"
#include "net/base/address_family.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
@@ -23,7 +24,9 @@
namespace net {
-class NET_EXPORT UDPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe) {
+class NET_EXPORT UDPSocketWin
+ : NON_EXPORTED_BASE(public base::NonThreadSafe),
+ NON_EXPORTED_BASE(public base::win::ObjectWatcher::Delegate) {
public:
UDPSocketWin(DatagramSocket::BindType bind_type,
const RandIntCallback& rand_int_cb,
@@ -174,6 +177,10 @@
// Resets the thread to be used for thread-safety checks.
void DetachFromThread();
+ // This class by default uses overlapped IO. Call this method before Open()
+ // to switch to non-blocking IO.
+ void UseNonBlockingIO();
+
private:
enum SocketOptions {
SOCKET_OPTION_MULTICAST_LOOP = 1 << 0
@@ -183,13 +190,20 @@
void DoReadCallback(int rv);
void DoWriteCallback(int rv);
+
void DidCompleteRead();
void DidCompleteWrite();
+ // base::ObjectWatcher::Delegate implementation.
+ virtual void OnObjectSignaled(HANDLE object);
+ void OnReadSignaled();
+ void OnWriteSignaled();
+
+ void WatchForReadWrite();
+
// Handles stats and logging. |result| is the number of bytes transferred, on
- // success, or the net error code on failure. LogRead retrieves the address
- // from |recv_addr_storage_|, while LogWrite takes it as an optional argument.
- void LogRead(int result, const char* bytes) const;
+ // success, or the net error code on failure.
+ void LogRead(int result, const char* bytes, const IPEndPoint* address) const;
void LogWrite(int result, const char* bytes, const IPEndPoint* address) const;
// Same as SendTo(), except that address is passed by pointer
@@ -201,8 +215,22 @@
const CompletionCallback& callback);
int InternalConnect(const IPEndPoint& address);
- int InternalRecvFrom(IOBuffer* buf, int buf_len, IPEndPoint* address);
- int InternalSendTo(IOBuffer* buf, int buf_len, const IPEndPoint* address);
+
+ // Version for using overlapped IO.
+ int InternalRecvFromOverlapped(IOBuffer* buf,
+ int buf_len,
+ IPEndPoint* address);
+ int InternalSendToOverlapped(IOBuffer* buf,
+ int buf_len,
+ const IPEndPoint* address);
+
+ // Version for using non-blocking IO.
+ int InternalRecvFromNonBlocking(IOBuffer* buf,
+ int buf_len,
+ IPEndPoint* address);
+ int InternalSendToNonBlocking(IOBuffer* buf,
+ int buf_len,
+ const IPEndPoint* address);
// Applies |socket_options_| to |socket_|. Should be called before
// Bind().
@@ -211,10 +239,6 @@
// Binds to a random port on |address|.
int RandomBind(const IPAddressNumber& address);
- // Attempts to convert the data in |recv_addr_storage_| and |recv_addr_len_|
- // to an IPEndPoint and writes it to |address|. Returns true on success.
- bool ReceiveAddressToIPEndpoint(IPEndPoint* address) const;
-
SOCKET socket_;
int addr_family_;
bool is_connected_;
@@ -247,6 +271,22 @@
// they are not destroyed while the OS still references them.
scoped_refptr<Core> core_;
+ // True if non-blocking IO is used.
+ bool use_non_blocking_io_;
+
+ // Watches |read_write_event_|.
+ base::win::ObjectWatcher read_write_watcher_;
+
+ // Events for read and write.
+ base::win::ScopedHandle read_write_event_;
+
+ // The buffers used in Read() and Write().
+ scoped_refptr<IOBuffer> read_iobuffer_;
+ scoped_refptr<IOBuffer> write_iobuffer_;
+
+ int read_iobuffer_len_;
+ int write_iobuffer_len_;
+
IPEndPoint* recv_from_address_;
// Cached copy of the current address we're sending to, if any. Used for
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 132a67d..d7203a4 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -227,12 +227,6 @@
return upload_data_stream_.get() != NULL;
}
-void URLRequest::SetExtraRequestHeaderById(int id, const string& value,
- bool overwrite) {
- DCHECK(!is_pending_ || is_redirecting_);
- NOTREACHED() << "implement me!";
-}
-
void URLRequest::SetExtraRequestHeaderByName(const string& name,
const string& value,
bool overwrite) {
@@ -273,6 +267,10 @@
}
LoadStateWithParam URLRequest::GetLoadState() const {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455952 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("455952 URLRequest::GetLoadState"));
// The !blocked_by_.empty() check allows |this| to report it's blocked on a
// delegate before it has been started.
if (calling_delegate_ || !blocked_by_.empty()) {
@@ -378,11 +376,6 @@
return job_->GetUploadProgress();
}
-void URLRequest::GetResponseHeaderById(int id, string* value) {
- DCHECK(job_.get());
- NOTREACHED() << "implement me!";
-}
-
void URLRequest::GetResponseHeaderByName(const string& name, string* value) {
DCHECK(value);
if (response_info_.headers.get()) {
@@ -392,15 +385,6 @@
}
}
-void URLRequest::GetAllResponseHeaders(string* headers) {
- DCHECK(headers);
- if (response_info_.headers.get()) {
- response_info_.headers->GetNormalizedHeaders(headers);
- } else {
- headers->clear();
- }
-}
-
HostPortPair URLRequest::GetSocketAddress() const {
DCHECK(job_.get());
return job_->GetSocketAddress();
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index af972bd..20aab60 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -82,14 +82,6 @@
NetworkDelegate* network_delegate,
const std::string& scheme);
- // HTTP request/response header IDs (via some preprocessor fun) for use with
- // SetRequestHeaderById and GetResponseHeaderById.
- enum {
-#define HTTP_ATOM(x) HTTP_ ## x,
-#include "net/http/http_atom_list.h"
-#undef HTTP_ATOM
- };
-
// Referrer policies (see set_referrer_policy): During server redirects, the
// referrer header might be cleared, if the protocol changes from HTTPS to
// HTTP. This is the default behavior of URLRequest, corresponding to
@@ -334,11 +326,9 @@
// Returns true if the request has a non-empty message body to upload.
bool has_upload() const;
- // Set an extra request header by ID or name, or remove one by name. These
- // methods may only be called before Start() is called, or before a new
- // redirect in the request chain.
- void SetExtraRequestHeaderById(int header_id, const std::string& value,
- bool overwrite);
+ // Set or remove a extra request header. These methods may only be called
+ // before Start() is called, or between receiving a redirect and trying to
+ // follow it.
void SetExtraRequestHeaderByName(const std::string& name,
const std::string& value, bool overwrite);
void RemoveRequestHeaderByName(const std::string& name);
@@ -401,19 +391,13 @@
// chunked, size is set to zero, but position will not be.
UploadProgress GetUploadProgress() const;
- // Get response header(s) by ID or name. These methods may only be called
+ // Get response header(s) by name. This method may only be called
// once the delegate's OnResponseStarted method has been called. Headers
// that appear more than once in the response are coalesced, with values
// separated by commas (per RFC 2616). This will not work with cookies since
// comma can be used in cookie values.
- // TODO(darin): add API to enumerate response headers.
- void GetResponseHeaderById(int header_id, std::string* value);
void GetResponseHeaderByName(const std::string& name, std::string* value);
- // Get all response headers, \n-delimited and \n\0-terminated. This includes
- // the response status line. Restrictions on GetResponseHeaders apply.
- void GetAllResponseHeaders(std::string* headers);
-
// The time when |this| was constructed.
base::TimeTicks creation_time() const { return creation_time_; }
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc
index d774714..d1050e3 100644
--- a/net/url_request/url_request_ftp_job.cc
+++ b/net/url_request/url_request_ftp_job.cc
@@ -285,6 +285,11 @@
}
LoadState URLRequestFtpJob::GetLoadState() const {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455952 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "455952 URLRequestFtpJob::GetLoadState"));
if (proxy_info_.is_direct()) {
return ftp_transaction_ ?
ftp_transaction_->GetLoadState() : LOAD_STATE_IDLE;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 68858c1..4247d83 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -10,6 +10,7 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/debug/alias.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/file_version_info.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
@@ -289,6 +290,12 @@
}
void URLRequestHttpJob::Kill() {
+ if (awaiting_callback_) {
+ // TODO(battre) crbug.com/289715
+ // Simulate a crash to see who kills the job while it is waiting for a
+ // callback. This should not happen, see URLRequest::OrphanJob().
+ base::debug::DumpWithoutCrashing();
+ }
if (!transaction_.get())
return;
@@ -1020,6 +1027,11 @@
}
LoadState URLRequestHttpJob::GetLoadState() const {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/455952 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "455952 URLRequestHttpJob::GetLoadState"));
return transaction_.get() ?
transaction_->GetLoadState() : LOAD_STATE_IDLE;
}
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 2be8a74..3fae14f 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -503,7 +503,8 @@
void URLRequestJob::NotifyReadComplete(int bytes_read) {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("URLRequestJob::NotifyReadComplete"));
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "423948 URLRequestJob::NotifyReadComplete"));
if (!request_ || !request_->has_delegate())
return; // The request was destroyed, so there is no more work to do.
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index c3bc166..5937464 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -5989,10 +5989,8 @@
TestDelegate d;
GURL::Replacements replacements;
- std::string username("user2");
- std::string password("secret");
- replacements.SetUsernameStr(username);
- replacements.SetPasswordStr(password);
+ replacements.SetUsernameStr("user2");
+ replacements.SetPasswordStr("secret");
GURL url_with_identity = url_requiring_auth.ReplaceComponents(replacements);
scoped_ptr<URLRequest> r(context.CreateRequest(
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
index 4aa2f1c..1a3df04 100644
--- a/net/websockets/websocket_end_to_end_test.cc
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -338,9 +338,8 @@
// The test server doesn't have an unauthenticated proxy mode. WebSockets
// cannot provide auth information that isn't already cached, so it's
// necessary to preflight an HTTP request to authenticate against the proxy.
- std::string scheme("http");
GURL::Replacements replacements;
- replacements.SetSchemeStr(scheme);
+ replacements.SetSchemeStr("http");
// It doesn't matter what the URL is, as long as it is an HTTP navigation.
GURL http_page =
ws_server.GetURL("connect_check.html").ReplaceComponents(replacements);
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index 96df5fd..64940f1 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -94,20 +94,23 @@
}
if (compile_suid_client) {
- sources += [ "suid/client/setuid_sandbox_client_unittest.cc" ]
+ sources += [
+ "suid/client/setuid_sandbox_client_unittest.cc",
+ "suid/client/setuid_sandbox_host_unittest.cc",
+ ]
}
if (use_seccomp_bpf) {
sources += [
"bpf_dsl/bpf_dsl_more_unittest.cc",
"bpf_dsl/bpf_dsl_unittest.cc",
+ "bpf_dsl/codegen_unittest.cc",
"bpf_dsl/cons_unittest.cc",
+ "bpf_dsl/syscall_set_unittest.cc",
"seccomp-bpf-helpers/baseline_policy_unittest.cc",
"seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc",
"seccomp-bpf/bpf_tests_unittest.cc",
- "seccomp-bpf/codegen_unittest.cc",
"seccomp-bpf/errorcode_unittest.cc",
"seccomp-bpf/sandbox_bpf_unittest.cc",
- "seccomp-bpf/syscall_iterator_unittest.cc",
"seccomp-bpf/syscall_unittest.cc",
]
}
@@ -146,6 +149,8 @@
"bpf_dsl/bpf_dsl.h",
"bpf_dsl/bpf_dsl_forward.h",
"bpf_dsl/bpf_dsl_impl.h",
+ "bpf_dsl/codegen.cc",
+ "bpf_dsl/codegen.h",
"bpf_dsl/cons.h",
"bpf_dsl/dump_bpf.cc",
"bpf_dsl/dump_bpf.h",
@@ -153,9 +158,9 @@
"bpf_dsl/policy.h",
"bpf_dsl/policy_compiler.cc",
"bpf_dsl/policy_compiler.h",
+ "bpf_dsl/syscall_set.cc",
+ "bpf_dsl/syscall_set.h",
"bpf_dsl/trap_registry.h",
- "seccomp-bpf/codegen.cc",
- "seccomp-bpf/codegen.h",
"seccomp-bpf/die.cc",
"seccomp-bpf/die.h",
"seccomp-bpf/errorcode.cc",
@@ -165,8 +170,6 @@
"seccomp-bpf/sandbox_bpf.h",
"seccomp-bpf/syscall.cc",
"seccomp-bpf/syscall.h",
- "seccomp-bpf/syscall_iterator.cc",
- "seccomp-bpf/syscall_iterator.h",
"seccomp-bpf/trap.cc",
"seccomp-bpf/trap.h",
"seccomp-bpf/verifier.cc",
@@ -306,6 +309,8 @@
"suid/common/suid_unsafe_environment_variables.h",
"suid/client/setuid_sandbox_client.cc",
"suid/client/setuid_sandbox_client.h",
+ "suid/client/setuid_sandbox_host.cc",
+ "suid/client/setuid_sandbox_host.h",
]
defines = [ "SANDBOX_IMPLEMENTATION" ]
diff --git a/sandbox/linux/seccomp-bpf/codegen.cc b/sandbox/linux/bpf_dsl/codegen.cc
similarity index 98%
rename from sandbox/linux/seccomp-bpf/codegen.cc
rename to sandbox/linux/bpf_dsl/codegen.cc
index 055aa71..793d95d 100644
--- a/sandbox/linux/seccomp-bpf/codegen.cc
+++ b/sandbox/linux/bpf_dsl/codegen.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 "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
#include <linux/filter.h>
diff --git a/sandbox/linux/seccomp-bpf/codegen.h b/sandbox/linux/bpf_dsl/codegen.h
similarity index 96%
rename from sandbox/linux/seccomp-bpf/codegen.h
rename to sandbox/linux/bpf_dsl/codegen.h
index ef04a5d..c2e1f93 100644
--- a/sandbox/linux/seccomp-bpf/codegen.h
+++ b/sandbox/linux/bpf_dsl/codegen.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
-#define SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
+#ifndef SANDBOX_LINUX_BPF_DSL_CODEGEN_H__
+#define SANDBOX_LINUX_BPF_DSL_CODEGEN_H__
#include <stddef.h>
#include <stdint.h>
@@ -120,4 +120,4 @@
} // namespace sandbox
-#endif // SANDBOX_LINUX_SECCOMP_BPF_CODEGEN_H__
+#endif // SANDBOX_LINUX_BPF_DSL_CODEGEN_H__
diff --git a/sandbox/linux/seccomp-bpf/codegen_unittest.cc b/sandbox/linux/bpf_dsl/codegen_unittest.cc
similarity index 99%
rename from sandbox/linux/seccomp-bpf/codegen_unittest.cc
rename to sandbox/linux/bpf_dsl/codegen_unittest.cc
index 8d4bf5d..3abfc85 100644
--- a/sandbox/linux/seccomp-bpf/codegen_unittest.cc
+++ b/sandbox/linux/bpf_dsl/codegen_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 "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
#include <linux/filter.h>
diff --git a/sandbox/linux/bpf_dsl/dump_bpf.cc b/sandbox/linux/bpf_dsl/dump_bpf.cc
index ddbcd0e..5cf53ff 100644
--- a/sandbox/linux/bpf_dsl/dump_bpf.cc
+++ b/sandbox/linux/bpf_dsl/dump_bpf.cc
@@ -6,8 +6,8 @@
#include <stdio.h>
+#include "sandbox/linux/bpf_dsl/codegen.h"
#include "sandbox/linux/bpf_dsl/trap_registry.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
namespace sandbox {
diff --git a/sandbox/linux/bpf_dsl/dump_bpf.h b/sandbox/linux/bpf_dsl/dump_bpf.h
index ce260f8..cd12be7 100644
--- a/sandbox/linux/bpf_dsl/dump_bpf.h
+++ b/sandbox/linux/bpf_dsl/dump_bpf.h
@@ -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 "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc
index f91f70c..2b72f3b 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -14,13 +14,13 @@
#include "base/macros.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
#include "sandbox/linux/bpf_dsl/policy.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
#include "sandbox/linux/seccomp-bpf/die.h"
#include "sandbox/linux/seccomp-bpf/errorcode.h"
#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
-#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
namespace sandbox {
namespace bpf_dsl {
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.h b/sandbox/linux/bpf_dsl/policy_compiler.h
index 8737c42..faf6be5 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.h
+++ b/sandbox/linux/bpf_dsl/policy_compiler.h
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
#include "sandbox/linux/seccomp-bpf/errorcode.h"
#include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator.cc b/sandbox/linux/bpf_dsl/syscall_set.cc
similarity index 97%
rename from sandbox/linux/seccomp-bpf/syscall_iterator.cc
rename to sandbox/linux/bpf_dsl/syscall_set.cc
index 195a8b0..22d6046 100644
--- a/sandbox/linux/seccomp-bpf/syscall_iterator.cc
+++ b/sandbox/linux/bpf_dsl/syscall_set.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 "sandbox/linux/seccomp-bpf/syscall_iterator.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
#include "base/logging.h"
#include "base/macros.h"
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator.h b/sandbox/linux/bpf_dsl/syscall_set.h
similarity index 92%
rename from sandbox/linux/seccomp-bpf/syscall_iterator.h
rename to sandbox/linux/bpf_dsl/syscall_set.h
index 5080fcc..b9f076d 100644
--- a/sandbox/linux/seccomp-bpf/syscall_iterator.h
+++ b/sandbox/linux/bpf_dsl/syscall_set.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_ITERATOR_H__
-#define SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_ITERATOR_H__
+#ifndef SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__
+#define SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__
#include <stdint.h>
@@ -14,8 +14,6 @@
namespace sandbox {
-// TODO(mdempsky): Rename this header to syscall_set.h.
-
// Iterates over the entire system call range from 0..0xFFFFFFFFu. This
// iterator is aware of how system calls look like and will skip quickly
// over ranges that can't contain system calls. It iterates more slowly
@@ -102,4 +100,4 @@
} // namespace sandbox
-#endif // SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_ITERATOR_H__
+#endif // SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc b/sandbox/linux/bpf_dsl/syscall_set_unittest.cc
similarity index 87%
rename from sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc
rename to sandbox/linux/bpf_dsl/syscall_set_unittest.cc
index 3bc1eaa..5730dc4 100644
--- a/sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc
+++ b/sandbox/linux/bpf_dsl/syscall_set_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 "sandbox/linux/seccomp-bpf/syscall_iterator.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
#include <stdint.h>
@@ -18,7 +18,7 @@
SyscallSet::InvalidOnly(),
};
-SANDBOX_TEST(SyscallIterator, Monotonous) {
+SANDBOX_TEST(SyscallSet, Monotonous) {
for (const SyscallSet& set : kSyscallSets) {
uint32_t prev = 0;
bool have_prev = false;
@@ -54,7 +54,7 @@
SANDBOX_ASSERT(prev == max);
}
-SANDBOX_TEST(SyscallIterator, ValidSyscallRanges) {
+SANDBOX_TEST(SyscallSet, ValidSyscallRanges) {
AssertRange(MIN_SYSCALL, MAX_PUBLIC_SYSCALL);
#if defined(__arm__)
AssertRange(MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL);
@@ -62,7 +62,7 @@
#endif
}
-SANDBOX_TEST(SyscallIterator, InvalidSyscalls) {
+SANDBOX_TEST(SyscallSet, InvalidSyscalls) {
static const uint32_t kExpected[] = {
#if defined(__mips__)
0,
@@ -93,19 +93,19 @@
}
}
-SANDBOX_TEST(SyscallIterator, ValidOnlyIsOnlyValid) {
+SANDBOX_TEST(SyscallSet, ValidOnlyIsOnlyValid) {
for (uint32_t sysnum : SyscallSet::ValidOnly()) {
SANDBOX_ASSERT(SyscallSet::IsValid(sysnum));
}
}
-SANDBOX_TEST(SyscallIterator, InvalidOnlyIsOnlyInvalid) {
+SANDBOX_TEST(SyscallSet, InvalidOnlyIsOnlyInvalid) {
for (uint32_t sysnum : SyscallSet::InvalidOnly()) {
SANDBOX_ASSERT(!SyscallSet::IsValid(sysnum));
}
}
-SANDBOX_TEST(SyscallIterator, AllIsValidOnlyPlusInvalidOnly) {
+SANDBOX_TEST(SyscallSet, AllIsValidOnlyPlusInvalidOnly) {
std::vector<uint32_t> merged;
const SyscallSet valid_only = SyscallSet::ValidOnly();
const SyscallSet invalid_only = SyscallSet::InvalidOnly();
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 15bd71c..c03b024 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -122,6 +122,8 @@
'bpf_dsl/bpf_dsl.h',
'bpf_dsl/bpf_dsl_forward.h',
'bpf_dsl/bpf_dsl_impl.h',
+ 'bpf_dsl/codegen.cc',
+ 'bpf_dsl/codegen.h',
'bpf_dsl/cons.h',
'bpf_dsl/dump_bpf.cc',
'bpf_dsl/dump_bpf.h',
@@ -129,9 +131,9 @@
'bpf_dsl/policy.h',
'bpf_dsl/policy_compiler.cc',
'bpf_dsl/policy_compiler.h',
+ 'bpf_dsl/syscall_set.cc',
+ 'bpf_dsl/syscall_set.h',
'bpf_dsl/trap_registry.h',
- 'seccomp-bpf/codegen.cc',
- 'seccomp-bpf/codegen.h',
'seccomp-bpf/die.cc',
'seccomp-bpf/die.h',
'seccomp-bpf/errorcode.cc',
@@ -141,8 +143,6 @@
'seccomp-bpf/sandbox_bpf.h',
'seccomp-bpf/syscall.cc',
'seccomp-bpf/syscall.h',
- 'seccomp-bpf/syscall_iterator.cc',
- 'seccomp-bpf/syscall_iterator.h',
'seccomp-bpf/trap.cc',
'seccomp-bpf/trap.h',
'seccomp-bpf/verifier.cc',
@@ -315,6 +315,8 @@
'suid/common/suid_unsafe_environment_variables.h',
'suid/client/setuid_sandbox_client.cc',
'suid/client/setuid_sandbox_client.h',
+ 'suid/client/setuid_sandbox_host.cc',
+ 'suid/client/setuid_sandbox_host.h',
],
'defines': [
'SANDBOX_IMPLEMENTATION',
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index 61517cc..eef29db 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -34,20 +34,21 @@
[ 'compile_suid_client==1', {
'sources': [
'suid/client/setuid_sandbox_client_unittest.cc',
+ 'suid/client/setuid_sandbox_host_unittest.cc',
],
}],
[ 'use_seccomp_bpf==1', {
'sources': [
'bpf_dsl/bpf_dsl_more_unittest.cc',
'bpf_dsl/bpf_dsl_unittest.cc',
+ 'bpf_dsl/codegen_unittest.cc',
'bpf_dsl/cons_unittest.cc',
+ 'bpf_dsl/syscall_set_unittest.cc',
'seccomp-bpf-helpers/baseline_policy_unittest.cc',
'seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc',
'seccomp-bpf/bpf_tests_unittest.cc',
- 'seccomp-bpf/codegen_unittest.cc',
'seccomp-bpf/errorcode_unittest.cc',
'seccomp-bpf/sandbox_bpf_unittest.cc',
- 'seccomp-bpf/syscall_iterator_unittest.cc',
'seccomp-bpf/syscall_unittest.cc',
],
}],
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index 555f672..d51fa78 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -23,15 +23,15 @@
#include "base/memory/scoped_ptr.h"
#include "base/posix/eintr_wrapper.h"
#include "base/third_party/valgrind/valgrind.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
#include "sandbox/linux/bpf_dsl/dump_bpf.h"
#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/bpf_dsl/policy_compiler.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
#include "sandbox/linux/seccomp-bpf/die.h"
#include "sandbox/linux/seccomp-bpf/errorcode.h"
#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
-#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
#include "sandbox/linux/seccomp-bpf/trap.h"
#include "sandbox/linux/seccomp-bpf/verifier.h"
#include "sandbox/linux/services/linux_syscalls.h"
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
index 1a9c1f8..e46889b 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.h
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
@@ -10,7 +10,7 @@
#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "sandbox/linux/seccomp-bpf/codegen.h"
+#include "sandbox/linux/bpf_dsl/codegen.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/seccomp-bpf/verifier.cc
index 548df25..68fca88 100644
--- a/sandbox/linux/seccomp-bpf/verifier.cc
+++ b/sandbox/linux/seccomp-bpf/verifier.cc
@@ -12,10 +12,10 @@
#include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/bpf_dsl/policy_compiler.h"
+#include "sandbox/linux/bpf_dsl/syscall_set.h"
#include "sandbox/linux/seccomp-bpf/errorcode.h"
#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
namespace sandbox {
diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc
index 1209fdf..40a2bc4 100644
--- a/sandbox/linux/services/credentials_unittest.cc
+++ b/sandbox/linux/services/credentials_unittest.cc
@@ -123,11 +123,11 @@
}
// Test the WorkingDirectoryIsRoot() helper.
-TEST(Credentials, CanDetectRoot) {
- ASSERT_EQ(0, chdir("/proc/"));
- ASSERT_FALSE(WorkingDirectoryIsRoot());
- ASSERT_EQ(0, chdir("/"));
- ASSERT_TRUE(WorkingDirectoryIsRoot());
+SANDBOX_TEST(Credentials, CanDetectRoot) {
+ PCHECK(0 == chdir("/proc/"));
+ CHECK(!WorkingDirectoryIsRoot());
+ PCHECK(0 == chdir("/"));
+ CHECK(WorkingDirectoryIsRoot());
}
// Disabled on ASAN because of crbug.com/451603.
diff --git a/sandbox/linux/services/namespace_sandbox_unittest.cc b/sandbox/linux/services/namespace_sandbox_unittest.cc
index ace1f92..91e1db9 100644
--- a/sandbox/linux/services/namespace_sandbox_unittest.cc
+++ b/sandbox/linux/services/namespace_sandbox_unittest.cc
@@ -90,7 +90,8 @@
return 0;
}
-TEST_F(NamespaceSandboxTest, ChrootAndDropCapabilities) {
+// Temporarily disabled on ASAN due to crbug.com/451603.
+TEST_F(NamespaceSandboxTest, DISABLE_ON_ASAN(ChrootAndDropCapabilities)) {
TestProc("ChrootMe");
}
diff --git a/sandbox/linux/services/unix_domain_socket_unittest.cc b/sandbox/linux/services/unix_domain_socket_unittest.cc
index 4d57c0d..dafa91d 100644
--- a/sandbox/linux/services/unix_domain_socket_unittest.cc
+++ b/sandbox/linux/services/unix_domain_socket_unittest.cc
@@ -17,7 +17,7 @@
#include "base/memory/scoped_vector.h"
#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket_linux.h"
-#include "base/process/process_handle.h"
+#include "base/process/process.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/tests/unit_tests.h"
@@ -57,10 +57,9 @@
// base::GetParentProcessId() is defined as taking a ProcessHandle instead of
// a ProcessId, even though it's a POSIX-only function and IDs and Handles
// are both simply pid_t on POSIX... :/
- base::ProcessHandle handle;
- CHECK(base::OpenProcessHandle(pid, &handle));
- base::ProcessId ret = base::GetParentProcessId(pid);
- base::CloseProcessHandle(handle);
+ base::Process process = base::Process::Open(pid);
+ CHECK(process.IsValid());
+ base::ProcessId ret = base::GetParentProcessId(process.Handle());
return ret;
}
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.cc b/sandbox/linux/suid/client/setuid_sandbox_client.cc
index f0b5cef..12ef7f9 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.cc
@@ -5,95 +5,24 @@
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
#include <fcntl.h>
-#include <stdlib.h>
-#include <sys/socket.h>
#include <sys/stat.h>
-#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
-#include "base/command_line.h"
+#include <string>
+
#include "base/environment.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/path_service.h"
#include "base/posix/eintr_wrapper.h"
-#include "base/process/launch.h"
-#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
-#include "sandbox/linux/services/init_process_reaper.h"
#include "sandbox/linux/suid/common/sandbox.h"
-#include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h"
namespace {
bool IsFileSystemAccessDenied() {
- base::ScopedFD self_exe(HANDLE_EINTR(open(base::kProcSelfExe, O_RDONLY)));
- return !self_exe.is_valid();
-}
-
-// Set an environment variable that reflects the API version we expect from the
-// setuid sandbox. Old versions of the sandbox will ignore this.
-void SetSandboxAPIEnvironmentVariable(base::Environment* env) {
- env->SetVar(sandbox::kSandboxEnvironmentApiRequest,
- base::IntToString(sandbox::kSUIDSandboxApiNumber));
-}
-
-// Unset environment variables that are expected to be set by the setuid
-// sandbox. This is to allow nesting of one instance of the SUID sandbox
-// inside another.
-void UnsetExpectedEnvironmentVariables(base::EnvironmentMap* env_map) {
- DCHECK(env_map);
- const base::NativeEnvironmentString environment_vars[] = {
- sandbox::kSandboxDescriptorEnvironmentVarName,
- sandbox::kSandboxHelperPidEnvironmentVarName,
- sandbox::kSandboxEnvironmentApiProvides,
- sandbox::kSandboxPIDNSEnvironmentVarName,
- sandbox::kSandboxNETNSEnvironmentVarName,
- };
-
- for (size_t i = 0; i < arraysize(environment_vars); ++i) {
- // Setting values in EnvironmentMap to an empty-string will make
- // sure that they get unset from the environment via AlterEnvironment().
- (*env_map)[environment_vars[i]] = base::NativeEnvironmentString();
- }
-}
-
-// Wrapper around a shared C function.
-// Returns the "saved" environment variable name corresponding to |envvar|
-// in a new string or NULL.
-std::string* CreateSavedVariableName(const char* env_var) {
- char* const saved_env_var = SandboxSavedEnvironmentVariable(env_var);
- if (!saved_env_var)
- return NULL;
- std::string* saved_env_var_copy = new std::string(saved_env_var);
- // SandboxSavedEnvironmentVariable is the C function that we wrap and uses
- // malloc() to allocate memory.
- free(saved_env_var);
- return saved_env_var_copy;
-}
-
-// The ELF loader will clear many environment variables so we save them to
-// different names here so that the SUID sandbox can resolve them for the
-// renderer.
-void SaveSUIDUnsafeEnvironmentVariables(base::Environment* env) {
- for (unsigned i = 0; kSUIDUnsafeEnvironmentVariables[i]; ++i) {
- const char* env_var = kSUIDUnsafeEnvironmentVariables[i];
- // Get the saved environment variable corresponding to envvar.
- scoped_ptr<std::string> saved_env_var(CreateSavedVariableName(env_var));
- if (saved_env_var == NULL)
- continue;
-
- std::string value;
- if (env->GetVar(env_var, &value))
- env->SetVar(saved_env_var->c_str(), value);
- else
- env->UnSetVar(saved_env_var->c_str());
- }
+ base::ScopedFD root_dir(HANDLE_EINTR(open("/", O_RDONLY)));
+ return !root_dir.is_valid();
}
int GetHelperApi(base::Environment* env) {
@@ -128,30 +57,21 @@
return EnvToInt(env, sandbox::kSandboxDescriptorEnvironmentVarName);
}
-const char* GetDevelSandboxPath() {
- return getenv("CHROME_DEVEL_SANDBOX");
-}
-
} // namespace
namespace sandbox {
SetuidSandboxClient* SetuidSandboxClient::Create() {
base::Environment* environment(base::Environment::Create());
- SetuidSandboxClient* sandbox_client(new SetuidSandboxClient);
-
CHECK(environment);
- sandbox_client->env_ = environment;
- return sandbox_client;
+ return new SetuidSandboxClient(environment);
}
-SetuidSandboxClient::SetuidSandboxClient()
- : env_(NULL),
- sandboxed_(false) {
+SetuidSandboxClient::SetuidSandboxClient(base::Environment* env)
+ : env_(env), sandboxed_(false) {
}
SetuidSandboxClient::~SetuidSandboxClient() {
- delete env_;
}
void SetuidSandboxClient::CloseDummyFile() {
@@ -170,7 +90,7 @@
}
bool SetuidSandboxClient::ChrootMe() {
- int ipc_fd = GetIPCDescriptor(env_);
+ int ipc_fd = GetIPCDescriptor(env_.get());
if (ipc_fd < 0) {
LOG(ERROR) << "Failed to obtain the sandbox IPC descriptor";
@@ -183,7 +103,7 @@
}
// We need to reap the chroot helper process in any event.
- pid_t helper_pid = GetHelperPID(env_);
+ pid_t helper_pid = GetHelperPID(env_.get());
// If helper_pid is -1 we wait for any child.
if (HANDLE_EINTR(waitpid(helper_pid, NULL, 0)) < 0) {
PLOG(ERROR) << "Failed to wait for setuid helper to die";
@@ -208,17 +128,12 @@
return true;
}
-bool SetuidSandboxClient::CreateInitProcessReaper(
- base::Closure* post_fork_parent_callback) {
- return sandbox::CreateInitProcessReaper(post_fork_parent_callback);
-}
-
bool SetuidSandboxClient::IsSuidSandboxUpToDate() const {
- return GetHelperApi(env_) == kSUIDSandboxApiNumber;
+ return GetHelperApi(env_.get()) == kSUIDSandboxApiNumber;
}
bool SetuidSandboxClient::IsSuidSandboxChild() const {
- return GetIPCDescriptor(env_) >= 0;
+ return GetIPCDescriptor(env_.get()) >= 0;
}
bool SetuidSandboxClient::IsInNewPIDNamespace() const {
@@ -233,87 +148,4 @@
return sandboxed_;
}
-// Check if CHROME_DEVEL_SANDBOX is set but empty. This currently disables
-// the setuid sandbox. TODO(jln): fix this (crbug.com/245376).
-bool SetuidSandboxClient::IsDisabledViaEnvironment() {
- const char* devel_sandbox_path = GetDevelSandboxPath();
- if (devel_sandbox_path && '\0' == *devel_sandbox_path) {
- return true;
- }
- return false;
-}
-
-base::FilePath SetuidSandboxClient::GetSandboxBinaryPath() {
- base::FilePath sandbox_binary;
- base::FilePath exe_dir;
- if (PathService::Get(base::DIR_EXE, &exe_dir)) {
- base::FilePath sandbox_candidate = exe_dir.AppendASCII("chrome-sandbox");
- if (base::PathExists(sandbox_candidate))
- sandbox_binary = sandbox_candidate;
- }
-
- // In user-managed builds, including development builds, an environment
- // variable is required to enable the sandbox. See
- // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
- struct stat st;
- if (sandbox_binary.empty() && stat(base::kProcSelfExe, &st) == 0 &&
- st.st_uid == getuid()) {
- const char* devel_sandbox_path = GetDevelSandboxPath();
- if (devel_sandbox_path) {
- sandbox_binary = base::FilePath(devel_sandbox_path);
- }
- }
-
- return sandbox_binary;
-}
-
-void SetuidSandboxClient::PrependWrapper(base::CommandLine* cmd_line) {
- std::string sandbox_binary(GetSandboxBinaryPath().value());
- struct stat st;
- if (sandbox_binary.empty() || stat(sandbox_binary.c_str(), &st) != 0) {
- LOG(FATAL) << "The SUID sandbox helper binary is missing: "
- << sandbox_binary << " Aborting now. See "
- "https://code.google.com/p/chromium/wiki/"
- "LinuxSUIDSandboxDevelopment.";
- }
-
- if (access(sandbox_binary.c_str(), X_OK) != 0 || (st.st_uid != 0) ||
- ((st.st_mode & S_ISUID) == 0) || ((st.st_mode & S_IXOTH)) == 0) {
- LOG(FATAL) << "The SUID sandbox helper binary was found, but is not "
- "configured correctly. Rather than run without sandboxing "
- "I'm aborting now. You need to make sure that "
- << sandbox_binary << " is owned by root and has mode 4755.";
- }
-
- cmd_line->PrependWrapper(sandbox_binary);
-}
-
-void SetuidSandboxClient::SetupLaunchOptions(
- base::LaunchOptions* options,
- base::FileHandleMappingVector* fds_to_remap,
- base::ScopedFD* dummy_fd) {
- DCHECK(options);
- DCHECK(fds_to_remap);
-
- // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
- options->allow_new_privs = true;
- UnsetExpectedEnvironmentVariables(&options->environ);
-
- // Set dummy_fd to the reading end of a closed pipe.
- int pipe_fds[2];
- PCHECK(0 == pipe(pipe_fds));
- PCHECK(0 == IGNORE_EINTR(close(pipe_fds[1])));
- dummy_fd->reset(pipe_fds[0]);
-
- // We no longer need a dummy socket for discovering the child's PID,
- // but the sandbox is still hard-coded to expect a file descriptor at
- // kZygoteIdFd. Fixing this requires a sandbox API change. :(
- fds_to_remap->push_back(std::make_pair(dummy_fd->get(), kZygoteIdFd));
-}
-
-void SetuidSandboxClient::SetupLaunchEnvironment() {
- SaveSUIDUnsafeEnvironmentVariables(env_);
- SetSandboxAPIEnvironmentVariable(env_);
-}
-
} // namespace sandbox
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.h b/sandbox/linux/suid/client/setuid_sandbox_client.h
index e6a3e4c..026894f 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client.h
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.h
@@ -5,28 +5,20 @@
#ifndef SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
#define SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_file.h"
-#include "base/process/launch.h"
+#include "base/environment.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
-// Helper class to use the setuid sandbox. This class is to be used both
-// before launching the setuid helper and after being executed through the
-// setuid helper.
+// Helper class to use the setuid sandbox. This class is to be used
+// after being executed through the setuid helper.
// This class is difficult to use. It has been created by refactoring very old
// code scathered through the Chromium code base.
//
// A typical use for "A" launching a sandboxed process "B" would be:
-// 1. A calls SetupLaunchEnvironment()
-// 2. A sets up a CommandLine and then amends it with
-// PrependWrapper() (or manually, by relying on GetSandboxBinaryPath()).
-// 3. A uses SetupLaunchOptions() to arrange for a dummy descriptor for the
-// setuid sandbox ABI.
-// 4. A launches B with base::LaunchProcess, using the amended CommandLine.
+// (Steps 1 through 4 are described in setuid_sandbox_host.h.)
// 5. B uses CloseDummyFile() to close the dummy file descriptor.
// 6. B performs various initializations that require access to the file
// system.
@@ -37,13 +29,13 @@
// cannot receive any signal from any other process, excluding SIGKILL.
// If B dies, all the processes in the namespace will die.
// B can fork() and the parent can assume the role of init(1), by using
-// CreateInitProcessReaper().
+// sandbox::CreateInitProcessReaper().
// 8. B requests being chroot-ed through ChrootMe() and
// requests other sandboxing status via the status functions.
class SANDBOX_EXPORT SetuidSandboxClient {
public:
// All instantation should go through this factory method.
- static class SetuidSandboxClient* Create();
+ static SetuidSandboxClient* Create();
~SetuidSandboxClient();
// Close the dummy file descriptor leftover from the sandbox ABI.
@@ -52,11 +44,6 @@
// to an empty directory.
// Will only work if we have been launched through the setuid helper.
bool ChrootMe();
- // When a new PID namespace is created, the process with pid == 1 should
- // assume the role of init.
- // See sandbox/linux/services/init_process_reaper.h for more information
- // on this API.
- bool CreateInitProcessReaper(base::Closure* post_fork_parent_callback);
// Did we get launched through an up to date setuid binary ?
bool IsSuidSandboxUpToDate() const;
@@ -69,33 +56,11 @@
// Are we done and fully sandboxed ?
bool IsSandboxed() const;
- // The setuid sandbox may still be disabled via the environment.
- // This is tracked in crbug.com/245376.
- bool IsDisabledViaEnvironment();
- // Get the sandbox binary path. This method knows about the
- // CHROME_DEVEL_SANDBOX environment variable used for user-managed builds. If
- // the sandbox binary cannot be found, it will return an empty FilePath.
- base::FilePath GetSandboxBinaryPath();
- // Modify |cmd_line| to launch via the setuid sandbox. Crash if the setuid
- // sandbox binary cannot be found. |cmd_line| must not be NULL.
- void PrependWrapper(base::CommandLine* cmd_line);
- // Set-up the launch options for launching via the setuid sandbox. Caller is
- // responsible for keeping |dummy_fd| alive until LaunchProcess() completes.
- // |options| and |fds_to_remap| must not be NULL.
- // (Keeping |dummy_fd| alive is an unfortunate historical artifact of the
- // chrome-sandbox ABI.)
- void SetupLaunchOptions(base::LaunchOptions* options,
- base::FileHandleMappingVector* fds_to_remap,
- base::ScopedFD* dummy_fd);
- // Set-up the environment. This should be done prior to launching the setuid
- // helper.
- void SetupLaunchEnvironment();
-
private:
- SetuidSandboxClient();
+ explicit SetuidSandboxClient(base::Environment* env);
// Holds the environment. Will never be NULL.
- base::Environment* env_;
+ scoped_ptr<base::Environment> env_;
bool sandboxed_;
DISALLOW_COPY_AND_ASSIGN(SetuidSandboxClient);
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc b/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc
index d4f7dfe..2acd8fb 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_client_unittest.cc
@@ -2,63 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
+
#include "base/environment.h"
-#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
#include "sandbox/linux/suid/common/sandbox.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sandbox {
-TEST(SetuidSandboxClient, SetupLaunchEnvironment) {
- const char kTestValue[] = "This is a test";
- scoped_ptr<base::Environment> env(base::Environment::Create());
- EXPECT_TRUE(env != NULL);
-
- std::string saved_ld_preload;
- bool environment_had_ld_preload;
- // First, back-up the real LD_PRELOAD if any.
- environment_had_ld_preload = env->GetVar("LD_PRELOAD", &saved_ld_preload);
- // Setup environment variables to save or not save.
- EXPECT_TRUE(env->SetVar("LD_PRELOAD", kTestValue));
- EXPECT_TRUE(env->UnSetVar("LD_ORIGIN_PATH"));
-
- scoped_ptr<SetuidSandboxClient>
- sandbox_client(SetuidSandboxClient::Create());
- EXPECT_TRUE(sandbox_client != NULL);
-
- // Make sure the environment is clean.
- EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiRequest));
- EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiProvides));
-
- sandbox_client->SetupLaunchEnvironment();
-
- // Check if the requested API environment was set.
- std::string api_request;
- EXPECT_TRUE(env->GetVar(kSandboxEnvironmentApiRequest, &api_request));
- int api_request_num;
- EXPECT_TRUE(base::StringToInt(api_request, &api_request_num));
- EXPECT_EQ(api_request_num, kSUIDSandboxApiNumber);
-
- // Now check if LD_PRELOAD was saved to SANDBOX_LD_PRELOAD.
- std::string sandbox_ld_preload;
- EXPECT_TRUE(env->GetVar("SANDBOX_LD_PRELOAD", &sandbox_ld_preload));
- EXPECT_EQ(sandbox_ld_preload, kTestValue);
-
- // Check that LD_ORIGIN_PATH was not saved.
- EXPECT_FALSE(env->HasVar("SANDBOX_LD_ORIGIN_PATH"));
-
- // We should not forget to restore LD_PRELOAD at the end, or this environment
- // variable will affect the next running tests!
- if (environment_had_ld_preload) {
- EXPECT_TRUE(env->SetVar("LD_PRELOAD", saved_ld_preload));
- } else {
- EXPECT_TRUE(env->UnSetVar("LD_PRELOAD"));
- }
-}
-
TEST(SetuidSandboxClient, SandboxedClientAPI) {
scoped_ptr<base::Environment> env(base::Environment::Create());
EXPECT_TRUE(env != NULL);
@@ -89,13 +42,5 @@
EXPECT_FALSE(sandbox_client->IsSandboxed());
}
-// This test doesn't accomplish much, but will make sure that analysis tools
-// will run this codepath.
-TEST(SetuidSandboxClient, GetSandboxBinaryPath) {
- scoped_ptr<SetuidSandboxClient> setuid_sandbox_client(
- SetuidSandboxClient::Create());
- ignore_result(setuid_sandbox_client->GetSandboxBinaryPath());
-}
-
} // namespace sandbox
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host.cc b/sandbox/linux/suid/client/setuid_sandbox_host.cc
new file mode 100644
index 0000000..71171eb
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_host.cc
@@ -0,0 +1,195 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <string>
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/process/launch.h"
+#include "base/process/process_metrics.h"
+#include "base/strings/string_number_conversions.h"
+#include "sandbox/linux/suid/common/sandbox.h"
+#include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h"
+
+namespace {
+
+// Set an environment variable that reflects the API version we expect from the
+// setuid sandbox. Old versions of the sandbox will ignore this.
+void SetSandboxAPIEnvironmentVariable(base::Environment* env) {
+ env->SetVar(sandbox::kSandboxEnvironmentApiRequest,
+ base::IntToString(sandbox::kSUIDSandboxApiNumber));
+}
+
+// Unset environment variables that are expected to be set by the setuid
+// sandbox. This is to allow nesting of one instance of the SUID sandbox
+// inside another.
+void UnsetExpectedEnvironmentVariables(base::EnvironmentMap* env_map) {
+ DCHECK(env_map);
+ const base::NativeEnvironmentString environment_vars[] = {
+ sandbox::kSandboxDescriptorEnvironmentVarName,
+ sandbox::kSandboxHelperPidEnvironmentVarName,
+ sandbox::kSandboxEnvironmentApiProvides,
+ sandbox::kSandboxPIDNSEnvironmentVarName,
+ sandbox::kSandboxNETNSEnvironmentVarName,
+ };
+
+ for (size_t i = 0; i < arraysize(environment_vars); ++i) {
+ // Setting values in EnvironmentMap to an empty-string will make
+ // sure that they get unset from the environment via AlterEnvironment().
+ (*env_map)[environment_vars[i]] = base::NativeEnvironmentString();
+ }
+}
+
+// Wrapper around a shared C function.
+// Returns the "saved" environment variable name corresponding to |envvar|
+// in a new string or NULL.
+std::string* CreateSavedVariableName(const char* env_var) {
+ char* const saved_env_var = SandboxSavedEnvironmentVariable(env_var);
+ if (!saved_env_var)
+ return NULL;
+ std::string* saved_env_var_copy = new std::string(saved_env_var);
+ // SandboxSavedEnvironmentVariable is the C function that we wrap and uses
+ // malloc() to allocate memory.
+ free(saved_env_var);
+ return saved_env_var_copy;
+}
+
+// The ELF loader will clear many environment variables so we save them to
+// different names here so that the SUID sandbox can resolve them for the
+// renderer.
+void SaveSUIDUnsafeEnvironmentVariables(base::Environment* env) {
+ for (unsigned i = 0; kSUIDUnsafeEnvironmentVariables[i]; ++i) {
+ const char* env_var = kSUIDUnsafeEnvironmentVariables[i];
+ // Get the saved environment variable corresponding to envvar.
+ scoped_ptr<std::string> saved_env_var(CreateSavedVariableName(env_var));
+ if (saved_env_var == NULL)
+ continue;
+
+ std::string value;
+ if (env->GetVar(env_var, &value))
+ env->SetVar(saved_env_var->c_str(), value);
+ else
+ env->UnSetVar(saved_env_var->c_str());
+ }
+}
+
+const char* GetDevelSandboxPath() {
+ return getenv("CHROME_DEVEL_SANDBOX");
+}
+
+} // namespace
+
+namespace sandbox {
+
+SetuidSandboxHost* SetuidSandboxHost::Create() {
+ base::Environment* environment(base::Environment::Create());
+ CHECK(environment);
+ return new SetuidSandboxHost(environment);
+}
+
+SetuidSandboxHost::SetuidSandboxHost(base::Environment* env) : env_(env) {
+}
+
+SetuidSandboxHost::~SetuidSandboxHost() {
+}
+
+// Check if CHROME_DEVEL_SANDBOX is set but empty. This currently disables
+// the setuid sandbox. TODO(jln): fix this (crbug.com/245376).
+bool SetuidSandboxHost::IsDisabledViaEnvironment() {
+ const char* devel_sandbox_path = GetDevelSandboxPath();
+ if (devel_sandbox_path && '\0' == *devel_sandbox_path) {
+ return true;
+ }
+ return false;
+}
+
+base::FilePath SetuidSandboxHost::GetSandboxBinaryPath() {
+ base::FilePath sandbox_binary;
+ base::FilePath exe_dir;
+ if (PathService::Get(base::DIR_EXE, &exe_dir)) {
+ base::FilePath sandbox_candidate = exe_dir.AppendASCII("chrome-sandbox");
+ if (base::PathExists(sandbox_candidate))
+ sandbox_binary = sandbox_candidate;
+ }
+
+ // In user-managed builds, including development builds, an environment
+ // variable is required to enable the sandbox. See
+ // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
+ struct stat st;
+ if (sandbox_binary.empty() && stat(base::kProcSelfExe, &st) == 0 &&
+ st.st_uid == getuid()) {
+ const char* devel_sandbox_path = GetDevelSandboxPath();
+ if (devel_sandbox_path) {
+ sandbox_binary = base::FilePath(devel_sandbox_path);
+ }
+ }
+
+ return sandbox_binary;
+}
+
+void SetuidSandboxHost::PrependWrapper(base::CommandLine* cmd_line) {
+ std::string sandbox_binary(GetSandboxBinaryPath().value());
+ struct stat st;
+ if (sandbox_binary.empty() || stat(sandbox_binary.c_str(), &st) != 0) {
+ LOG(FATAL) << "The SUID sandbox helper binary is missing: "
+ << sandbox_binary << " Aborting now. See "
+ "https://code.google.com/p/chromium/wiki/"
+ "LinuxSUIDSandboxDevelopment.";
+ }
+
+ if (access(sandbox_binary.c_str(), X_OK) != 0 || (st.st_uid != 0) ||
+ ((st.st_mode & S_ISUID) == 0) || ((st.st_mode & S_IXOTH)) == 0) {
+ LOG(FATAL) << "The SUID sandbox helper binary was found, but is not "
+ "configured correctly. Rather than run without sandboxing "
+ "I'm aborting now. You need to make sure that "
+ << sandbox_binary << " is owned by root and has mode 4755.";
+ }
+
+ cmd_line->PrependWrapper(sandbox_binary);
+}
+
+void SetuidSandboxHost::SetupLaunchOptions(
+ base::LaunchOptions* options,
+ base::FileHandleMappingVector* fds_to_remap,
+ base::ScopedFD* dummy_fd) {
+ DCHECK(options);
+ DCHECK(fds_to_remap);
+
+ // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
+ options->allow_new_privs = true;
+ UnsetExpectedEnvironmentVariables(&options->environ);
+
+ // Set dummy_fd to the reading end of a closed pipe.
+ int pipe_fds[2];
+ PCHECK(0 == pipe(pipe_fds));
+ PCHECK(0 == IGNORE_EINTR(close(pipe_fds[1])));
+ dummy_fd->reset(pipe_fds[0]);
+
+ // We no longer need a dummy socket for discovering the child's PID,
+ // but the sandbox is still hard-coded to expect a file descriptor at
+ // kZygoteIdFd. Fixing this requires a sandbox API change. :(
+ fds_to_remap->push_back(std::make_pair(dummy_fd->get(), kZygoteIdFd));
+}
+
+void SetuidSandboxHost::SetupLaunchEnvironment() {
+ SaveSUIDUnsafeEnvironmentVariables(env_.get());
+ SetSandboxAPIEnvironmentVariable(env_.get());
+}
+
+} // namespace sandbox
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host.h b/sandbox/linux/suid/client/setuid_sandbox_host.h
new file mode 100644
index 0000000..6788892
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_host.h
@@ -0,0 +1,70 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SUID_SETUID_SANDBOX_HOST_H_
+#define SANDBOX_LINUX_SUID_SETUID_SANDBOX_HOST_H_
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/process/launch.h"
+#include "sandbox/sandbox_export.h"
+
+namespace sandbox {
+
+// Helper class to use the setuid sandbox. This class is to be used
+// before launching the setuid helper.
+// This class is difficult to use. It has been created by refactoring very old
+// code scathered through the Chromium code base.
+//
+// A typical use for "A" launching a sandboxed process "B" would be:
+// 1. A calls SetupLaunchEnvironment()
+// 2. A sets up a base::CommandLine and then amends it with
+// PrependWrapper() (or manually, by relying on GetSandboxBinaryPath()).
+// 3. A uses SetupLaunchOptions() to arrange for a dummy descriptor for the
+// setuid sandbox ABI.
+// 4. A launches B with base::LaunchProcess, using the amended
+// base::CommandLine.
+// (The remaining steps are described within setuid_sandbox_client.h.)
+class SANDBOX_EXPORT SetuidSandboxHost {
+ public:
+ // All instantation should go through this factory method.
+ static SetuidSandboxHost* Create();
+ ~SetuidSandboxHost();
+
+ // The setuid sandbox may still be disabled via the environment.
+ // This is tracked in crbug.com/245376.
+ bool IsDisabledViaEnvironment();
+ // Get the sandbox binary path. This method knows about the
+ // CHROME_DEVEL_SANDBOX environment variable used for user-managed builds. If
+ // the sandbox binary cannot be found, it will return an empty FilePath.
+ base::FilePath GetSandboxBinaryPath();
+ // Modify |cmd_line| to launch via the setuid sandbox. Crash if the setuid
+ // sandbox binary cannot be found. |cmd_line| must not be NULL.
+ void PrependWrapper(base::CommandLine* cmd_line);
+ // Set-up the launch options for launching via the setuid sandbox. Caller is
+ // responsible for keeping |dummy_fd| alive until LaunchProcess() completes.
+ // |options| and |fds_to_remap| must not be NULL.
+ // (Keeping |dummy_fd| alive is an unfortunate historical artifact of the
+ // chrome-sandbox ABI.)
+ void SetupLaunchOptions(base::LaunchOptions* options,
+ base::FileHandleMappingVector* fds_to_remap,
+ base::ScopedFD* dummy_fd);
+ // Set-up the environment. This should be done prior to launching the setuid
+ // helper.
+ void SetupLaunchEnvironment();
+
+ private:
+ explicit SetuidSandboxHost(base::Environment* env);
+
+ // Holds the environment. Will never be NULL.
+ scoped_ptr<base::Environment> env_;
+
+ DISALLOW_COPY_AND_ASSIGN(SetuidSandboxHost);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_SUID_SETUID_SANDBOX_HOST_H_
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc b/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc
new file mode 100644
index 0000000..8415abb
--- /dev/null
+++ b/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
+
+#include <string>
+
+#include "base/environment.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "sandbox/linux/suid/common/sandbox.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+
+TEST(SetuidSandboxHost, SetupLaunchEnvironment) {
+ const char kTestValue[] = "This is a test";
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ EXPECT_TRUE(env != NULL);
+
+ std::string saved_ld_preload;
+ bool environment_had_ld_preload;
+ // First, back-up the real LD_PRELOAD if any.
+ environment_had_ld_preload = env->GetVar("LD_PRELOAD", &saved_ld_preload);
+ // Setup environment variables to save or not save.
+ EXPECT_TRUE(env->SetVar("LD_PRELOAD", kTestValue));
+ EXPECT_TRUE(env->UnSetVar("LD_ORIGIN_PATH"));
+
+ scoped_ptr<SetuidSandboxHost> sandbox_host(SetuidSandboxHost::Create());
+ EXPECT_TRUE(sandbox_host != NULL);
+
+ // Make sure the environment is clean.
+ EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiRequest));
+ EXPECT_TRUE(env->UnSetVar(kSandboxEnvironmentApiProvides));
+
+ sandbox_host->SetupLaunchEnvironment();
+
+ // Check if the requested API environment was set.
+ std::string api_request;
+ EXPECT_TRUE(env->GetVar(kSandboxEnvironmentApiRequest, &api_request));
+ int api_request_num;
+ EXPECT_TRUE(base::StringToInt(api_request, &api_request_num));
+ EXPECT_EQ(api_request_num, kSUIDSandboxApiNumber);
+
+ // Now check if LD_PRELOAD was saved to SANDBOX_LD_PRELOAD.
+ std::string sandbox_ld_preload;
+ EXPECT_TRUE(env->GetVar("SANDBOX_LD_PRELOAD", &sandbox_ld_preload));
+ EXPECT_EQ(sandbox_ld_preload, kTestValue);
+
+ // Check that LD_ORIGIN_PATH was not saved.
+ EXPECT_FALSE(env->HasVar("SANDBOX_LD_ORIGIN_PATH"));
+
+ // We should not forget to restore LD_PRELOAD at the end, or this environment
+ // variable will affect the next running tests!
+ if (environment_had_ld_preload) {
+ EXPECT_TRUE(env->SetVar("LD_PRELOAD", saved_ld_preload));
+ } else {
+ EXPECT_TRUE(env->UnSetVar("LD_PRELOAD"));
+ }
+}
+
+// This test doesn't accomplish much, but will make sure that analysis tools
+// will run this codepath.
+TEST(SetuidSandboxHost, GetSandboxBinaryPath) {
+ scoped_ptr<SetuidSandboxHost> setuid_sandbox_host(
+ SetuidSandboxHost::Create());
+ ignore_result(setuid_sandbox_host->GetSandboxBinaryPath());
+}
+
+} // namespace sandbox
diff --git a/services/surfaces/surfaces_impl.cc b/services/surfaces/surfaces_impl.cc
index 083b6a4..1119985 100644
--- a/services/surfaces/surfaces_impl.cc
+++ b/services/surfaces/surfaces_impl.cc
@@ -4,7 +4,7 @@
#include "services/surfaces/surfaces_impl.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
#include "cc/output/compositor_frame.h"
#include "cc/resources/returned_resource.h"
#include "cc/surfaces/display.h"
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index a7d2296..fb7da07 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -319,9 +319,6 @@
"ext/skia_utils_mac.h",
"ext/skia_utils_win.cc",
"ext/skia_utils_win.h",
- "ext/vector_canvas.h",
- "ext/vector_platform_device_emf_win.cc",
- "ext/vector_platform_device_emf_win.h",
]
# The skia gypi values are relative to the skia_dir, so we need to rebase.
@@ -633,13 +630,8 @@
"ext/refptr_unittest.cc",
"ext/skia_utils_ios_unittest.mm",
"ext/skia_utils_mac_unittest.mm",
- "ext/vector_canvas_unittest.cc",
]
- if (!is_win) {
- sources -= [ "ext/vector_canvas_unittest.cc" ]
- }
-
if (!is_win && !is_mac) {
sources -= [ "ext/platform_canvas_unittest.cc" ]
}
diff --git a/skia/ext/vector_canvas.h b/skia/ext/vector_canvas.h
deleted file mode 100644
index 673becc..0000000
--- a/skia/ext/vector_canvas.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011 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 SKIA_EXT_VECTOR_CANVAS_H_
-#define SKIA_EXT_VECTOR_CANVAS_H_
-
-#include "base/compiler_specific.h"
-#include "skia/ext/platform_canvas.h"
-
-// This was a specialization of PlatformCanvas, but all necessary functionality
-// has been subsumed by just SkCanvas and a specialized device (PDF or EMF).
-// Future evolution goal is to replace this notion (canvas+device) with
-// an updated version of SkDocument, which will have explicit APIs for margins.
-// At that point, this class (and header) will be removed entirely.
-
-namespace skia {
- typedef PlatformCanvas VectorCanvas;
-} // namespace skia
-
-#endif // SKIA_EXT_VECTOR_CANVAS_H_
-
diff --git a/skia/ext/vector_canvas_unittest.cc b/skia/ext/vector_canvas_unittest.cc
deleted file mode 100644
index d3ad9a0..0000000
--- a/skia/ext/vector_canvas_unittest.cc
+++ /dev/null
@@ -1,970 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "build/build_config.h"
-
-#if !defined(OS_WIN)
-#include <unistd.h>
-#endif
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "skia/ext/vector_canvas.h"
-#include "skia/ext/vector_platform_device_emf_win.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/effects/SkDashPathEffect.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace skia {
-
-namespace {
-
-const char kGenerateSwitch[] = "vector-canvas-generate";
-
-// Lightweight HDC management.
-class Context {
- public:
- Context() : context_(CreateCompatibleDC(NULL)) {
- EXPECT_TRUE(context_);
- }
- ~Context() {
- DeleteDC(context_);
- }
-
- HDC context() const { return context_; }
-
- private:
- HDC context_;
-
- DISALLOW_COPY_AND_ASSIGN(Context);
-};
-
-// Lightweight HBITMAP management.
-class Bitmap {
- public:
- Bitmap(const Context& context, int x, int y) {
- BITMAPINFOHEADER hdr;
- hdr.biSize = sizeof(BITMAPINFOHEADER);
- hdr.biWidth = x;
- hdr.biHeight = -y; // Minus means top-down bitmap.
- hdr.biPlanes = 1;
- hdr.biBitCount = 32;
- hdr.biCompression = BI_RGB; // No compression.
- hdr.biSizeImage = 0;
- hdr.biXPelsPerMeter = 1;
- hdr.biYPelsPerMeter = 1;
- hdr.biClrUsed = 0;
- hdr.biClrImportant = 0;
- bitmap_ = CreateDIBSection(context.context(),
- reinterpret_cast<BITMAPINFO*>(&hdr), 0,
- &data_, NULL, 0);
- EXPECT_TRUE(bitmap_);
- EXPECT_TRUE(SelectObject(context.context(), bitmap_));
- }
- ~Bitmap() {
- EXPECT_TRUE(DeleteObject(bitmap_));
- }
-
- private:
- HBITMAP bitmap_;
-
- void* data_;
-
- DISALLOW_COPY_AND_ASSIGN(Bitmap);
-};
-
-// Lightweight raw-bitmap management. The image, once initialized, is immuable.
-// It is mainly used for comparison.
-class Image {
- public:
- // Creates the image from the given filename on disk.
- explicit Image(const base::FilePath& filename) : ignore_alpha_(true) {
- std::string compressed;
- base::ReadFileToString(filename, &compressed);
- EXPECT_TRUE(compressed.size());
-
- SkBitmap bitmap;
- EXPECT_TRUE(gfx::PNGCodec::Decode(
- reinterpret_cast<const unsigned char*>(compressed.data()),
- compressed.size(), &bitmap));
- SetSkBitmap(bitmap);
- }
-
- // Loads the image from a canvas.
- Image(skia::PlatformCanvas& canvas) : ignore_alpha_(true) {
- // Use a different way to access the bitmap. The normal way would be to
- // query the SkBitmap.
- skia::ScopedPlatformPaint scoped_platform_paint(&canvas);
- HDC context = scoped_platform_paint.GetPlatformSurface();
- HGDIOBJ bitmap = GetCurrentObject(context, OBJ_BITMAP);
- EXPECT_TRUE(bitmap != NULL);
- // Initialize the clip region to the entire bitmap.
- BITMAP bitmap_data;
- EXPECT_EQ(GetObject(bitmap, sizeof(BITMAP), &bitmap_data), sizeof(BITMAP));
- width_ = bitmap_data.bmWidth;
- height_ = bitmap_data.bmHeight;
- row_length_ = bitmap_data.bmWidthBytes;
- size_t size = row_length_ * height_;
- data_.resize(size);
- memcpy(&*data_.begin(), bitmap_data.bmBits, size);
- }
-
- // Loads the image from a canvas.
- Image(const SkBitmap& bitmap) : ignore_alpha_(true) {
- SetSkBitmap(bitmap);
- }
-
- int width() const { return width_; }
- int height() const { return height_; }
- int row_length() const { return row_length_; }
-
- // Save the image to a png file. Used to create the initial test files.
- void SaveToFile(const base::FilePath& filename) {
- std::vector<unsigned char> compressed;
- ASSERT_TRUE(gfx::PNGCodec::Encode(&*data_.begin(),
- gfx::PNGCodec::FORMAT_BGRA,
- gfx::Size(width_, height_),
- row_length_,
- true,
- std::vector<gfx::PNGCodec::Comment>(),
- &compressed));
- ASSERT_TRUE(compressed.size());
- FILE* f = base::OpenFile(filename, "wb");
- ASSERT_TRUE(f);
- ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
- compressed.size());
- base::CloseFile(f);
- }
-
- // Returns the percentage of the image that is different from the other,
- // between 0 and 100.
- double PercentageDifferent(const Image& rhs) const {
- if (width_ != rhs.width_ ||
- height_ != rhs.height_ ||
- row_length_ != rhs.row_length_ ||
- width_ == 0 ||
- height_ == 0) {
- return 100.; // When of different size or empty, they are 100% different.
- }
- // Compute pixels different in the overlap
- int pixels_different = 0;
- for (int y = 0; y < height_; ++y) {
- for (int x = 0; x < width_; ++x) {
- uint32_t lhs_pixel = pixel_at(x, y);
- uint32_t rhs_pixel = rhs.pixel_at(x, y);
- if (lhs_pixel != rhs_pixel)
- ++pixels_different;
- }
- }
-
- // Like the WebKit ImageDiff tool, we define percentage different in terms
- // of the size of the 'actual' bitmap.
- double total_pixels = static_cast<double>(width_) *
- static_cast<double>(height_);
- return static_cast<double>(pixels_different) / total_pixels * 100.;
- }
-
- // Returns the 0x0RGB or 0xARGB value of the pixel at the given location,
- // depending on ignore_alpha_.
- uint32 pixel_at(int x, int y) const {
- EXPECT_TRUE(x >= 0 && x < width_);
- EXPECT_TRUE(y >= 0 && y < height_);
- const uint32* data = reinterpret_cast<const uint32*>(&*data_.begin());
- const uint32* data_row = data + y * row_length_ / sizeof(uint32);
- if (ignore_alpha_)
- return data_row[x] & 0xFFFFFF; // Strip out A.
- else
- return data_row[x];
- }
-
- protected:
- void SetSkBitmap(const SkBitmap& bitmap) {
- SkAutoLockPixels lock(bitmap);
- width_ = bitmap.width();
- height_ = bitmap.height();
- row_length_ = static_cast<int>(bitmap.rowBytes());
- size_t size = row_length_ * height_;
- data_.resize(size);
- memcpy(&*data_.begin(), bitmap.getAddr(0, 0), size);
- }
-
- private:
- // Pixel dimensions of the image.
- int width_;
- int height_;
-
- // Length of a line in bytes.
- int row_length_;
-
- // Actual bitmap data in arrays of RGBAs (so when loaded as uint32, it's
- // 0xABGR).
- std::vector<unsigned char> data_;
-
- // Flag to signal if the comparison functions should ignore the alpha channel.
- const bool ignore_alpha_;
-
- DISALLOW_COPY_AND_ASSIGN(Image);
-};
-
-// Base for tests. Capability to process an image.
-class ImageTest : public testing::Test {
- public:
- // In what state is the test running.
- enum ProcessAction {
- GENERATE,
- COMPARE,
- NOOP,
- };
-
- ImageTest(ProcessAction default_action)
- : action_(default_action) {
- }
-
- protected:
- virtual void SetUp() {
- const testing::TestInfo& test_info =
- *testing::UnitTest::GetInstance()->current_test_info();
- PathService::Get(base::DIR_SOURCE_ROOT, &test_dir_);
- test_dir_ = test_dir_.AppendASCII("skia").
- AppendASCII("ext").
- AppendASCII("data").
- AppendASCII(test_info.test_case_name()).
- AppendASCII(test_info.name());
-
- // Hack for a quick lowercase. We assume all the tests names are ASCII.
- base::FilePath::StringType tmp(test_dir_.value());
- for (size_t i = 0; i < tmp.size(); ++i)
- tmp[i] = base::ToLowerASCII(tmp[i]);
- test_dir_ = base::FilePath(tmp);
-
- if (action_ == GENERATE) {
- // Make sure the directory exist.
- base::CreateDirectory(test_dir_);
- }
- }
-
- // Returns the fully qualified path of a data file.
- base::FilePath test_file(const base::FilePath::StringType& filename) const {
- // Hack for a quick lowercase. We assume all the test data file names are
- // ASCII.
-#if defined(OS_WIN)
- std::string tmp = base::UTF16ToASCII(filename);
-#else
- std::string tmp(filename);
-#endif
- for (size_t i = 0; i < tmp.size(); ++i)
- tmp[i] = base::ToLowerASCII(tmp[i]);
-
- return test_dir_.AppendASCII(tmp);
- }
-
- // Compares or saves the bitmap currently loaded in the context, depending on
- // kGenerating value. Returns 0 on success or any positive value between ]0,
- // 100] on failure. The return value is the percentage of difference between
- // the image in the file and the image in the canvas.
- double ProcessCanvas(skia::PlatformCanvas& canvas,
- base::FilePath::StringType filename) const {
- filename = filename + FILE_PATH_LITERAL(".png");
- switch (action_) {
- case GENERATE:
- SaveImage(canvas, filename);
- return 0.;
- case COMPARE:
- return CompareImage(canvas, filename);
- case NOOP:
- return 0;
- default:
- // Invalid state, returns that the image is 100 different.
- return 100.;
- }
- }
-
- // Compares the bitmap currently loaded in the context with the file. Returns
- // the percentage of pixel difference between both images, between 0 and 100.
- double CompareImage(skia::PlatformCanvas& canvas,
- const base::FilePath::StringType& filename) const {
- Image image1(canvas);
- Image image2(test_file(filename));
- double diff = image1.PercentageDifferent(image2);
- return diff;
- }
-
- // Saves the bitmap currently loaded in the context into the file.
- void SaveImage(skia::PlatformCanvas& canvas,
- const base::FilePath::StringType& filename) const {
- Image(canvas).SaveToFile(test_file(filename));
- }
-
- ProcessAction action_;
-
- // Path to directory used to contain the test data.
- base::FilePath test_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageTest);
-};
-
-// Premultiply the Alpha channel on the R, B and G channels.
-void Premultiply(SkBitmap bitmap) {
- SkAutoLockPixels lock(bitmap);
- for (int x = 0; x < bitmap.width(); ++x) {
- for (int y = 0; y < bitmap.height(); ++y) {
- uint32_t* pixel_addr = bitmap.getAddr32(x, y);
- uint32_t color = *pixel_addr;
- BYTE alpha = SkColorGetA(color);
- if (!alpha) {
- *pixel_addr = 0;
- } else {
- BYTE alpha_offset = alpha / 2;
- *pixel_addr = SkColorSetARGB(
- SkColorGetA(color),
- (SkColorGetR(color) * 255 + alpha_offset) / alpha,
- (SkColorGetG(color) * 255 + alpha_offset) / alpha,
- (SkColorGetB(color) * 255 + alpha_offset) / alpha);
- }
- }
- }
-}
-
-void LoadPngFileToSkBitmap(const base::FilePath& filename,
- SkBitmap* bitmap,
- bool is_opaque) {
- std::string compressed;
- base::ReadFileToString(base::MakeAbsoluteFilePath(filename), &compressed);
- ASSERT_TRUE(compressed.size());
-
- ASSERT_TRUE(gfx::PNGCodec::Decode(
- reinterpret_cast<const unsigned char*>(compressed.data()),
- compressed.size(), bitmap));
-
- EXPECT_EQ(is_opaque, bitmap->isOpaque());
- Premultiply(*bitmap);
-}
-
-} // namespace
-
-// Streams an image.
-inline std::ostream& operator<<(std::ostream& out, const Image& image) {
- return out << "Image(" << image.width() << ", "
- << image.height() << ", " << image.row_length() << ")";
-}
-
-// Runs simultaneously the same drawing commands on VectorCanvas and
-// PlatformCanvas and compare the results.
-class VectorCanvasTest : public ImageTest {
- public:
- typedef ImageTest parent;
-
- VectorCanvasTest() : parent(CurrentMode()), compare_canvas_(true) {
- }
-
- protected:
- virtual void SetUp() {
- parent::SetUp();
- Init(100);
- number_ = 0;
- }
-
- virtual void TearDown() {
- delete pcanvas_;
- pcanvas_ = NULL;
-
- delete vcanvas_;
- vcanvas_ = NULL;
-
- delete bitmap_;
- bitmap_ = NULL;
-
- delete context_;
- context_ = NULL;
-
- parent::TearDown();
- }
-
- void Init(int size) {
- size_ = size;
- context_ = new Context();
- bitmap_ = new Bitmap(*context_, size_, size_);
- vcanvas_ = new VectorCanvas(
- VectorPlatformDeviceEmf::CreateDevice(
- size_, size_, true, context_->context()));
- pcanvas_ = CreatePlatformCanvas(size_, size_, false);
-
- // Clear white.
- vcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
- pcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
- }
-
- // Compares both canvas and returns the pixel difference in percentage between
- // both images. 0 on success and ]0, 100] on failure.
- double ProcessImage(const base::FilePath::StringType& filename) {
- std::wstring number(base::StringPrintf(L"%02d_", number_++));
- double diff1 = parent::ProcessCanvas(*vcanvas_, number + L"vc_" + filename);
- double diff2 = parent::ProcessCanvas(*pcanvas_, number + L"pc_" + filename);
- if (!compare_canvas_)
- return std::max(diff1, diff2);
-
- Image image1(*vcanvas_);
- Image image2(*pcanvas_);
- double diff = image1.PercentageDifferent(image2);
- return std::max(std::max(diff1, diff2), diff);
- }
-
- // Returns COMPARE, which is the default. If kGenerateSwitch command
- // line argument is used to start this process, GENERATE is returned instead.
- static ProcessAction CurrentMode() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(kGenerateSwitch)
- ? GENERATE
- : COMPARE;
- }
-
- // Length in x and y of the square canvas.
- int size_;
-
- // Current image number in the current test. Used to number of test files.
- int number_;
-
- // A temporary HDC to draw into.
- Context* context_;
-
- // Bitmap created inside context_.
- Bitmap* bitmap_;
-
- // Vector based canvas.
- VectorCanvas* vcanvas_;
-
- // Pixel based canvas.
- PlatformCanvas* pcanvas_;
-
- // When true (default), vcanvas_ and pcanvas_ contents are compared and
- // verified to be identical.
- bool compare_canvas_;
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Actual tests
-
-#if !defined(USE_AURA) // http://crbug.com/154358
-
-TEST_F(VectorCanvasTest, BasicDrawing) {
- EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.)
- << L"clean";
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clean")));
-
- // Clear white.
- {
- vcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
- pcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawARGB")));
-
- // Diagonal line top-left to bottom-right.
- {
- SkPaint paint;
- // Default color is black.
- vcanvas_->drawLine(10, 10, 90, 90, paint);
- pcanvas_->drawLine(10, 10, 90, 90, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_black")));
-
- // Rect.
- {
- SkPaint paint;
- paint.setColor(SK_ColorGREEN);
- vcanvas_->drawRectCoords(25, 25, 75, 75, paint);
- pcanvas_->drawRectCoords(25, 25, 75, 75, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_green")));
-
- // A single-point rect doesn't leave any mark.
- {
- SkPaint paint;
- paint.setColor(SK_ColorBLUE);
- vcanvas_->drawRectCoords(5, 5, 5, 5, paint);
- pcanvas_->drawRectCoords(5, 5, 5, 5, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
-
- // Rect.
- {
- SkPaint paint;
- paint.setColor(SK_ColorBLUE);
- vcanvas_->drawRectCoords(75, 50, 80, 55, paint);
- pcanvas_->drawRectCoords(75, 50, 80, 55, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
-
- // Empty again
- {
- vcanvas_->drawPaint(SkPaint());
- pcanvas_->drawPaint(SkPaint());
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPaint_black")));
-
- // Horizontal line left to right.
- {
- SkPaint paint;
- paint.setColor(SK_ColorRED);
- vcanvas_->drawLine(10, 20, 90, 20, paint);
- pcanvas_->drawLine(10, 20, 90, 20, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_left_to_right")));
-
- // Vertical line downward.
- {
- SkPaint paint;
- paint.setColor(SK_ColorRED);
- vcanvas_->drawLine(30, 10, 30, 90, paint);
- pcanvas_->drawLine(30, 10, 30, 90, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_red")));
-}
-
-TEST_F(VectorCanvasTest, Circles) {
- // There is NO WAY to make them agree. At least verify that the output doesn't
- // change across versions. This test is disabled. See bug 1060231.
- compare_canvas_ = false;
-
- // Stroked Circle.
- {
- SkPaint paint;
- SkPath path;
- path.addCircle(50, 75, 10);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorMAGENTA);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke")));
-
- // Filled Circle.
- {
- SkPaint paint;
- SkPath path;
- path.addCircle(50, 25, 10);
- paint.setStyle(SkPaint::kFill_Style);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_fill")));
-
- // Stroked Circle over.
- {
- SkPaint paint;
- SkPath path;
- path.addCircle(50, 25, 10);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorBLUE);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_over_strike")));
-
- // Stroke and Fill Circle.
- {
- SkPaint paint;
- SkPath path;
- path.addCircle(12, 50, 10);
- paint.setStyle(SkPaint::kStrokeAndFill_Style);
- paint.setColor(SK_ColorRED);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke_and_fill")));
-
- // Line + Quad + Cubic.
- {
- SkPaint paint;
- SkPath path;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorGREEN);
- path.moveTo(1, 1);
- path.lineTo(60, 40);
- path.lineTo(80, 80);
- path.quadTo(20, 50, 10, 90);
- path.quadTo(50, 20, 90, 10);
- path.cubicTo(20, 40, 50, 50, 10, 10);
- path.cubicTo(30, 20, 50, 50, 90, 10);
- path.addRect(90, 90, 95, 96);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("mixed_stroke")));
-}
-
-TEST_F(VectorCanvasTest, LineOrientation) {
- // There is NO WAY to make them agree. At least verify that the output doesn't
- // change across versions. This test is disabled. See bug 1060231.
- compare_canvas_ = false;
-
- // Horizontal lines.
- {
- SkPaint paint;
- paint.setColor(SK_ColorRED);
- // Left to right.
- vcanvas_->drawLine(10, 20, 90, 20, paint);
- pcanvas_->drawLine(10, 20, 90, 20, paint);
- // Right to left.
- vcanvas_->drawLine(90, 30, 10, 30, paint);
- pcanvas_->drawLine(90, 30, 10, 30, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal")));
-
- // Vertical lines.
- {
- SkPaint paint;
- paint.setColor(SK_ColorRED);
- // Top down.
- vcanvas_->drawLine(20, 10, 20, 90, paint);
- pcanvas_->drawLine(20, 10, 20, 90, paint);
- // Bottom up.
- vcanvas_->drawLine(30, 90, 30, 10, paint);
- pcanvas_->drawLine(30, 90, 30, 10, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical")));
-
- // Try again with a 180 degres rotation.
- vcanvas_->rotate(180);
- pcanvas_->rotate(180);
-
- // Horizontal lines (rotated).
- {
- SkPaint paint;
- paint.setColor(SK_ColorRED);
- vcanvas_->drawLine(-10, -25, -90, -25, paint);
- pcanvas_->drawLine(-10, -25, -90, -25, paint);
- vcanvas_->drawLine(-90, -35, -10, -35, paint);
- pcanvas_->drawLine(-90, -35, -10, -35, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal_180")));
-
- // Vertical lines (rotated).
- {
- SkPaint paint;
- paint.setColor(SK_ColorRED);
- vcanvas_->drawLine(-25, -10, -25, -90, paint);
- pcanvas_->drawLine(-25, -10, -25, -90, paint);
- vcanvas_->drawLine(-35, -90, -35, -10, paint);
- pcanvas_->drawLine(-35, -90, -35, -10, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical_180")));
-}
-
-TEST_F(VectorCanvasTest, PathOrientation) {
- // There is NO WAY to make them agree. At least verify that the output doesn't
- // change across versions. This test is disabled. See bug 1060231.
- compare_canvas_ = false;
-
- // Horizontal lines.
- {
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorRED);
- SkPath path;
- SkPoint start;
- start.set(10, 20);
- SkPoint end;
- end.set(90, 20);
- path.moveTo(start);
- path.lineTo(end);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_ltr")));
-
- // Horizontal lines.
- {
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorRED);
- SkPath path;
- SkPoint start;
- start.set(90, 30);
- SkPoint end;
- end.set(10, 30);
- path.moveTo(start);
- path.lineTo(end);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_rtl")));
-}
-
-TEST_F(VectorCanvasTest, DiagonalLines) {
- SkPaint paint;
- paint.setColor(SK_ColorRED);
-
- vcanvas_->drawLine(10, 10, 90, 90, paint);
- pcanvas_->drawLine(10, 10, 90, 90, paint);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("nw-se")));
-
- // Starting here, there is NO WAY to make them agree. At least verify that the
- // output doesn't change across versions. This test is disabled. See bug
- // 1060231.
- compare_canvas_ = false;
-
- vcanvas_->drawLine(10, 95, 90, 15, paint);
- pcanvas_->drawLine(10, 95, 90, 15, paint);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("sw-ne")));
-
- vcanvas_->drawLine(90, 10, 10, 90, paint);
- pcanvas_->drawLine(90, 10, 10, 90, paint);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("ne-sw")));
-
- vcanvas_->drawLine(95, 90, 15, 10, paint);
- pcanvas_->drawLine(95, 90, 15, 10, paint);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("se-nw")));
-}
-
-#if defined(OS_WIN)
-#define MAYBE_PathEffects DISABLED_PathEffects
-#else
-#define MAYBE_PathEffects PathEffects
-#endif
-TEST_F(VectorCanvasTest, MAYBE_PathEffects) {
- {
- SkPaint paint;
- SkScalar intervals[] = { 1, 1 };
- skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
- new SkDashPathEffect(intervals, arraysize(intervals), 0));
- paint.setPathEffect(effect.get());
- paint.setColor(SK_ColorMAGENTA);
- paint.setStyle(SkPaint::kStroke_Style);
-
- vcanvas_->drawLine(10, 10, 90, 10, paint);
- pcanvas_->drawLine(10, 10, 90, 10, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_line")));
-
-
- // Starting here, there is NO WAY to make them agree. At least verify that the
- // output doesn't change across versions. This test is disabled. See bug
- // 1060231.
- compare_canvas_ = false;
-
- {
- SkPaint paint;
- SkScalar intervals[] = { 3, 5 };
- skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
- new SkDashPathEffect(intervals, arraysize(intervals), 0));
- paint.setPathEffect(effect.get());
- paint.setColor(SK_ColorMAGENTA);
- paint.setStyle(SkPaint::kStroke_Style);
-
- SkPath path;
- path.moveTo(10, 15);
- path.lineTo(90, 15);
- path.lineTo(90, 90);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_path")));
-
- {
- SkPaint paint;
- SkScalar intervals[] = { 2, 1 };
- skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
- new SkDashPathEffect(intervals, arraysize(intervals), 0));
- paint.setPathEffect(effect.get());
- paint.setColor(SK_ColorMAGENTA);
- paint.setStyle(SkPaint::kStroke_Style);
-
- vcanvas_->drawRectCoords(20, 20, 30, 30, paint);
- pcanvas_->drawRectCoords(20, 20, 30, 30, paint);
- }
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_rect")));
-
- // This thing looks like it has been drawn by a 3 years old kid. I haven't
- // filed a bug on this since I guess nobody is expecting this to look nice.
- {
- SkPaint paint;
- SkScalar intervals[] = { 1, 1 };
- skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
- new SkDashPathEffect(intervals, arraysize(intervals), 0));
- paint.setPathEffect(effect.get());
- paint.setColor(SK_ColorMAGENTA);
- paint.setStyle(SkPaint::kStroke_Style);
-
- SkPath path;
- path.addCircle(50, 75, 10);
- vcanvas_->drawPath(path, paint);
- pcanvas_->drawPath(path, paint);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle")));
- }
-}
-
-TEST_F(VectorCanvasTest, Bitmaps) {
- {
- SkBitmap bitmap;
- LoadPngFileToSkBitmap(test_file(L"bitmap_opaque.png"), &bitmap, true);
- vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
- pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("opaque")));
- }
-
- {
- SkBitmap bitmap;
- LoadPngFileToSkBitmap(test_file(L"bitmap_alpha.png"), &bitmap, false);
- vcanvas_->drawBitmap(bitmap, 5, 15, NULL);
- pcanvas_->drawBitmap(bitmap, 5, 15, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("alpha")));
- }
-}
-
-TEST_F(VectorCanvasTest, ClippingRect) {
- SkBitmap bitmap;
- LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
- true);
- SkRect rect;
- rect.fLeft = 2;
- rect.fTop = 2;
- rect.fRight = 30.5f;
- rect.fBottom = 30.5f;
- vcanvas_->clipRect(rect);
- pcanvas_->clipRect(rect);
-
- vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
- pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rect")));
-}
-
-TEST_F(VectorCanvasTest, ClippingPath) {
- SkBitmap bitmap;
- LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
- true);
- SkPath path;
- path.addCircle(20, 20, 10);
- vcanvas_->clipPath(path);
- pcanvas_->clipPath(path);
-
- vcanvas_->drawBitmap(bitmap, 14, 3, NULL);
- pcanvas_->drawBitmap(bitmap, 14, 3, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("path")));
-}
-
-TEST_F(VectorCanvasTest, ClippingCombined) {
- SkBitmap bitmap;
- LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
- true);
-
- SkRect rect;
- rect.fLeft = 2;
- rect.fTop = 2;
- rect.fRight = 30.5f;
- rect.fBottom = 30.5f;
- vcanvas_->clipRect(rect);
- pcanvas_->clipRect(rect);
- SkPath path;
- path.addCircle(20, 20, 10);
- vcanvas_->clipPath(path, SkRegion::kUnion_Op);
- pcanvas_->clipPath(path, SkRegion::kUnion_Op);
-
- vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
- pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("combined")));
-}
-
-TEST_F(VectorCanvasTest, ClippingIntersect) {
- SkBitmap bitmap;
- LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
- true);
-
- SkRect rect;
- rect.fLeft = 2;
- rect.fTop = 2;
- rect.fRight = 30.5f;
- rect.fBottom = 30.5f;
- vcanvas_->clipRect(rect);
- pcanvas_->clipRect(rect);
- SkPath path;
- path.addCircle(23, 23, 15);
- vcanvas_->clipPath(path);
- pcanvas_->clipPath(path);
-
- vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
- pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("intersect")));
-}
-
-TEST_F(VectorCanvasTest, ClippingClean) {
- SkBitmap bitmap;
- LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
- true);
- {
- SkAutoCanvasRestore acrv(vcanvas_, true);
- SkAutoCanvasRestore acrp(pcanvas_, true);
- SkRect rect;
- rect.fLeft = 2;
- rect.fTop = 2;
- rect.fRight = 30.5f;
- rect.fBottom = 30.5f;
- vcanvas_->clipRect(rect);
- pcanvas_->clipRect(rect);
-
- vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
- pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clipped")));
- }
- {
- // Verify that the clipping region has been fixed back.
- vcanvas_->drawBitmap(bitmap, 55, 3, NULL);
- pcanvas_->drawBitmap(bitmap, 55, 3, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("unclipped")));
- }
-}
-
-// See http://crbug.com/26938
-TEST_F(VectorCanvasTest, DISABLED_Matrix) {
- SkBitmap bitmap;
- LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
- true);
- {
- vcanvas_->translate(15, 3);
- pcanvas_->translate(15, 3);
- vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
- pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate1")));
- }
- {
- vcanvas_->translate(-30, -23);
- pcanvas_->translate(-30, -23);
- vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
- pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate2")));
- }
- vcanvas_->resetMatrix();
- pcanvas_->resetMatrix();
-
- // For scaling and rotation, they use a different algorithm (nearest
- // neighborhood vs smoothing). At least verify that the output doesn't change
- // across versions.
- compare_canvas_ = false;
-
- {
- vcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
- pcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
- vcanvas_->drawBitmap(bitmap, 1, 1, NULL);
- pcanvas_->drawBitmap(bitmap, 1, 1, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("scale")));
- }
- vcanvas_->resetMatrix();
- pcanvas_->resetMatrix();
-
- {
- vcanvas_->rotate(67);
- pcanvas_->rotate(67);
- vcanvas_->drawBitmap(bitmap, 20, -50, NULL);
- pcanvas_->drawBitmap(bitmap, 20, -50, NULL);
- EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rotate")));
- }
-}
-
-#endif // !defined(USE_AURA)
-
-} // namespace skia
diff --git a/skia/ext/vector_platform_device_emf_win.cc b/skia/ext/vector_platform_device_emf_win.cc
deleted file mode 100644
index 90e4a20..0000000
--- a/skia/ext/vector_platform_device_emf_win.cc
+++ /dev/null
@@ -1,982 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/vector_platform_device_emf_win.h"
-
-#include <windows.h>
-
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "skia/ext/bitmap_platform_device.h"
-#include "skia/ext/skia_utils_win.h"
-#include "third_party/skia/include/core/SkPathEffect.h"
-#include "third_party/skia/include/core/SkTemplates.h"
-#include "third_party/skia/include/core/SkUtils.h"
-#include "third_party/skia/include/ports/SkTypeface_win.h"
-
-namespace skia {
-
-#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
- do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
-
-// static
-SkBaseDevice* VectorPlatformDeviceEmf::CreateDevice(
- int width, int height, bool is_opaque, HANDLE shared_section) {
- if (!is_opaque) {
- // TODO(maruel): http://crbug.com/18382 When restoring a semi-transparent
- // layer, i.e. merging it, we need to rasterize it because GDI doesn't
- // support transparency except for AlphaBlend(). Right now, a
- // BitmapPlatformDevice is created when VectorCanvas think a saveLayers()
- // call is being done. The way to save a layer would be to create an
- // EMF-based VectorDevice and have this device registers the drawing. When
- // playing back the device into a bitmap, do it at the printer's dpi instead
- // of the layout's dpi (which is much lower).
- return BitmapPlatformDevice::Create(width, height, is_opaque,
- shared_section);
- }
-
- // TODO(maruel): http://crbug.com/18383 Look if it would be worth to
- // increase the resolution by ~10x (any worthy factor) to increase the
- // rendering precision (think about printing) while using a relatively
- // low dpi. This happens because we receive float as input but the GDI
- // functions works with integers. The idea is to premultiply the matrix
- // with this factor and multiply each SkScalar that are passed to
- // SkScalarRound(value) as SkScalarRound(value * 10). Safari is already
- // doing the same for text rendering.
- SkASSERT(shared_section);
- SkBaseDevice* device = VectorPlatformDeviceEmf::create(
- reinterpret_cast<HDC>(shared_section), width, height);
- return device;
-}
-
-static void FillBitmapInfoHeader(int width, int height, BITMAPINFOHEADER* hdr) {
- hdr->biSize = sizeof(BITMAPINFOHEADER);
- hdr->biWidth = width;
- hdr->biHeight = -height; // Minus means top-down bitmap.
- hdr->biPlanes = 1;
- hdr->biBitCount = 32;
- hdr->biCompression = BI_RGB; // no compression
- hdr->biSizeImage = 0;
- hdr->biXPelsPerMeter = 1;
- hdr->biYPelsPerMeter = 1;
- hdr->biClrUsed = 0;
- hdr->biClrImportant = 0;
-}
-
-SkBaseDevice* VectorPlatformDeviceEmf::create(HDC dc, int width, int height) {
- InitializeDC(dc);
-
- // Link the SkBitmap to the current selected bitmap in the device context.
- SkBitmap bitmap;
- HGDIOBJ selected_bitmap = GetCurrentObject(dc, OBJ_BITMAP);
- bool succeeded = false;
- if (selected_bitmap != NULL) {
- BITMAP bitmap_data = {0};
- if (GetObject(selected_bitmap, sizeof(BITMAP), &bitmap_data) ==
- sizeof(BITMAP)) {
- // The context has a bitmap attached. Attach our SkBitmap to it.
- // Warning: If the bitmap gets unselected from the HDC,
- // VectorPlatformDeviceEmf has no way to detect this, so the HBITMAP
- // could be released while SkBitmap still has a reference to it. Be
- // cautious.
- if (width == bitmap_data.bmWidth && height == bitmap_data.bmHeight) {
- SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
- succeeded = bitmap.installPixels(info, bitmap_data.bmBits,
- bitmap_data.bmWidthBytes);
- }
- }
- }
-
- if (!succeeded)
- bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
-
- return new VectorPlatformDeviceEmf(dc, bitmap);
-}
-
-VectorPlatformDeviceEmf::VectorPlatformDeviceEmf(HDC dc, const SkBitmap& bitmap)
- : SkBitmapDevice(bitmap),
- hdc_(dc),
- previous_brush_(NULL),
- previous_pen_(NULL) {
- transform_.reset();
- SetPlatformDevice(this, this);
-}
-
-VectorPlatformDeviceEmf::~VectorPlatformDeviceEmf() {
- SkASSERT(previous_brush_ == NULL);
- SkASSERT(previous_pen_ == NULL);
-}
-
-HDC VectorPlatformDeviceEmf::BeginPlatformPaint() {
- return hdc_;
-}
-
-void VectorPlatformDeviceEmf::drawPaint(const SkDraw& draw,
- const SkPaint& paint) {
- // TODO(maruel): Bypass the current transformation matrix.
- SkRect rect;
- rect.fLeft = 0;
- rect.fTop = 0;
- rect.fRight = SkIntToScalar(width() + 1);
- rect.fBottom = SkIntToScalar(height() + 1);
- drawRect(draw, rect, paint);
-}
-
-void VectorPlatformDeviceEmf::drawPoints(const SkDraw& draw,
- SkCanvas::PointMode mode,
- size_t count,
- const SkPoint pts[],
- const SkPaint& paint) {
- if (!count)
- return;
-
- if (mode == SkCanvas::kPoints_PointMode) {
- SkASSERT(false);
- return;
- }
-
- SkPaint tmp_paint(paint);
- tmp_paint.setStyle(SkPaint::kStroke_Style);
-
- // Draw a path instead.
- SkPath path;
- switch (mode) {
- case SkCanvas::kLines_PointMode:
- if (count % 2) {
- SkASSERT(false);
- return;
- }
- for (size_t i = 0; i < count / 2; ++i) {
- path.moveTo(pts[2 * i]);
- path.lineTo(pts[2 * i + 1]);
- }
- break;
- case SkCanvas::kPolygon_PointMode:
- path.moveTo(pts[0]);
- for (size_t i = 1; i < count; ++i) {
- path.lineTo(pts[i]);
- }
- break;
- default:
- SkASSERT(false);
- return;
- }
- // Draw the calculated path.
- drawPath(draw, path, tmp_paint);
-}
-
-void VectorPlatformDeviceEmf::drawRect(const SkDraw& draw,
- const SkRect& rect,
- const SkPaint& paint) {
- CHECK_FOR_NODRAW_ANNOTATION(paint);
- if (paint.getPathEffect()) {
- // Draw a path instead.
- SkPath path_orginal;
- path_orginal.addRect(rect);
-
- // Apply the path effect to the rect.
- SkPath path_modified;
- paint.getFillPath(path_orginal, &path_modified);
-
- // Removes the path effect from the temporary SkPaint object.
- SkPaint paint_no_effet(paint);
- paint_no_effet.setPathEffect(NULL);
-
- // Draw the calculated path.
- drawPath(draw, path_modified, paint_no_effet);
- return;
- }
-
- if (!ApplyPaint(paint)) {
- return;
- }
- HDC dc = BeginPlatformPaint();
- if (!Rectangle(dc, SkScalarRoundToInt(rect.fLeft),
- SkScalarRoundToInt(rect.fTop),
- SkScalarRoundToInt(rect.fRight),
- SkScalarRoundToInt(rect.fBottom))) {
- SkASSERT(false);
- }
- EndPlatformPaint();
- Cleanup();
-}
-
-void VectorPlatformDeviceEmf::drawRRect(const SkDraw& draw, const SkRRect& rr,
- const SkPaint& paint) {
- SkPath path;
- path.addRRect(rr);
- this->drawPath(draw, path, paint, NULL, true);
-}
-
-void VectorPlatformDeviceEmf::drawPath(const SkDraw& draw,
- const SkPath& path,
- const SkPaint& paint,
- const SkMatrix* prePathMatrix,
- bool pathIsMutable) {
- CHECK_FOR_NODRAW_ANNOTATION(paint);
- if (paint.getPathEffect()) {
- // Apply the path effect forehand.
- SkPath path_modified;
- paint.getFillPath(path, &path_modified);
-
- // Removes the path effect from the temporary SkPaint object.
- SkPaint paint_no_effet(paint);
- paint_no_effet.setPathEffect(NULL);
-
- // Draw the calculated path.
- drawPath(draw, path_modified, paint_no_effet);
- return;
- }
-
- if (!ApplyPaint(paint)) {
- return;
- }
- HDC dc = BeginPlatformPaint();
- if (PlatformDevice::LoadPathToDC(dc, path)) {
- switch (paint.getStyle()) {
- case SkPaint::kFill_Style: {
- BOOL res = StrokeAndFillPath(dc);
- SkASSERT(res != 0);
- break;
- }
- case SkPaint::kStroke_Style: {
- BOOL res = StrokePath(dc);
- SkASSERT(res != 0);
- break;
- }
- case SkPaint::kStrokeAndFill_Style: {
- BOOL res = StrokeAndFillPath(dc);
- SkASSERT(res != 0);
- break;
- }
- default:
- SkASSERT(false);
- break;
- }
- }
- EndPlatformPaint();
- Cleanup();
-}
-
-void VectorPlatformDeviceEmf::drawBitmapRect(const SkDraw& draw,
- const SkBitmap& bitmap,
- const SkRect* src,
- const SkRect& dst,
- const SkPaint& paint,
- SkCanvas::DrawBitmapRectFlags flags) {
- SkMatrix matrix;
- SkRect bitmapBounds, tmpSrc, tmpDst;
- SkBitmap tmpBitmap;
-
- bitmapBounds.isetWH(bitmap.width(), bitmap.height());
-
- // Compute matrix from the two rectangles
- if (src) {
- tmpSrc = *src;
- } else {
- tmpSrc = bitmapBounds;
- }
- matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
-
- const SkBitmap* bitmapPtr = &bitmap;
-
- // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
- // needed (if the src was clipped). No check needed if src==null.
- if (src) {
- if (!bitmapBounds.contains(*src)) {
- if (!tmpSrc.intersect(bitmapBounds)) {
- return; // nothing to draw
- }
- // recompute dst, based on the smaller tmpSrc
- matrix.mapRect(&tmpDst, tmpSrc);
- }
-
- // since we may need to clamp to the borders of the src rect within
- // the bitmap, we extract a subset.
- // TODO: make sure this is handled in drawrect and remove it from here.
- SkIRect srcIR;
- tmpSrc.roundOut(&srcIR);
- if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
- return;
- }
- bitmapPtr = &tmpBitmap;
-
- // Since we did an extract, we need to adjust the matrix accordingly
- SkScalar dx = 0, dy = 0;
- if (srcIR.fLeft > 0) {
- dx = SkIntToScalar(srcIR.fLeft);
- }
- if (srcIR.fTop > 0) {
- dy = SkIntToScalar(srcIR.fTop);
- }
- if (dx || dy) {
- matrix.preTranslate(dx, dy);
- }
- }
- this->drawBitmap(draw, *bitmapPtr, matrix, paint);
-}
-
-void VectorPlatformDeviceEmf::drawBitmap(const SkDraw& draw,
- const SkBitmap& bitmap,
- const SkMatrix& matrix,
- const SkPaint& paint) {
- // Load the temporary matrix. This is what will translate, rotate and resize
- // the bitmap.
- SkMatrix actual_transform(transform_);
- actual_transform.preConcat(matrix);
- LoadTransformToDC(hdc_, actual_transform);
-
- InternalDrawBitmap(bitmap, 0, 0, paint);
-
- // Restore the original matrix.
- LoadTransformToDC(hdc_, transform_);
-}
-
-void VectorPlatformDeviceEmf::drawSprite(const SkDraw& draw,
- const SkBitmap& bitmap,
- int x, int y,
- const SkPaint& paint) {
- SkMatrix identity;
- identity.reset();
- LoadTransformToDC(hdc_, identity);
-
- InternalDrawBitmap(bitmap, x, y, paint);
-
- // Restore the original matrix.
- LoadTransformToDC(hdc_, transform_);
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-static bool gdiCanHandleText(const SkPaint& paint) {
- return !paint.getShader() &&
- !paint.getPathEffect() &&
- (SkPaint::kFill_Style == paint.getStyle()) &&
- (255 == paint.getAlpha());
-}
-
-class SkGDIFontSetup {
- public:
- SkGDIFontSetup() :
- fHDC(NULL),
- fNewFont(NULL),
- fSavedFont(NULL),
- fSavedTextColor(0),
- fUseGDI(false) {
- SkDEBUGCODE(fUseGDIHasBeenCalled = false;)
- }
- ~SkGDIFontSetup();
-
- // can only be called once
- bool useGDI(HDC hdc, const SkPaint&);
-
- private:
- HDC fHDC;
- HFONT fNewFont;
- HFONT fSavedFont;
- COLORREF fSavedTextColor;
- bool fUseGDI;
- SkDEBUGCODE(bool fUseGDIHasBeenCalled;)
-};
-
-bool SkGDIFontSetup::useGDI(HDC hdc, const SkPaint& paint) {
- SkASSERT(!fUseGDIHasBeenCalled);
- SkDEBUGCODE(fUseGDIHasBeenCalled = true;)
-
- fUseGDI = gdiCanHandleText(paint);
- if (fUseGDI) {
- fSavedTextColor = GetTextColor(hdc);
- SetTextColor(hdc, skia::SkColorToCOLORREF(paint.getColor()));
-
- LOGFONT lf = {0};
- SkLOGFONTFromTypeface(paint.getTypeface(), &lf);
- lf.lfHeight = -SkScalarRoundToInt(paint.getTextSize());
- fNewFont = CreateFontIndirect(&lf);
- fSavedFont = (HFONT)::SelectObject(hdc, fNewFont);
- fHDC = hdc;
- }
- return fUseGDI;
-}
-
-SkGDIFontSetup::~SkGDIFontSetup() {
- if (fUseGDI) {
- ::SelectObject(fHDC, fSavedFont);
- ::DeleteObject(fNewFont);
- SetTextColor(fHDC, fSavedTextColor);
- }
-}
-
-static SkScalar getAscent(const SkPaint& paint) {
- SkPaint::FontMetrics fm;
- paint.getFontMetrics(&fm);
- return fm.fAscent;
-}
-
-// return the options int for ExtTextOut. Only valid if the paint's text
-// encoding is not UTF8 (in which case ExtTextOut can't be used).
-static UINT getTextOutOptions(const SkPaint& paint) {
- if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
- return ETO_GLYPH_INDEX;
- } else {
- SkASSERT(SkPaint::kUTF16_TextEncoding == paint.getTextEncoding());
- return 0;
- }
-}
-
-static SkiaEnsureTypefaceCharactersAccessible
- g_skia_ensure_typeface_characters_accessible = NULL;
-
-SK_API void SetSkiaEnsureTypefaceCharactersAccessible(
- SkiaEnsureTypefaceCharactersAccessible func) {
- // This function is supposed to be called once in process life time.
- SkASSERT(g_skia_ensure_typeface_characters_accessible == NULL);
- g_skia_ensure_typeface_characters_accessible = func;
-}
-
-void EnsureTypefaceCharactersAccessible(
- const SkTypeface& typeface, const wchar_t* text, unsigned int text_length) {
- LOGFONT lf = {0};
- SkLOGFONTFromTypeface(&typeface, &lf);
- g_skia_ensure_typeface_characters_accessible(lf, text, text_length);
-}
-
-bool EnsureExtTextOut(HDC hdc, int x, int y, UINT options, const RECT * lprect,
- LPCWSTR text, unsigned int characters, const int * lpDx,
- SkTypeface* const typeface) {
- bool success = ExtTextOut(hdc, x, y, options, lprect, text, characters, lpDx);
- if (!success) {
- if (typeface) {
- EnsureTypefaceCharactersAccessible(*typeface,
- text,
- characters);
- success = ExtTextOut(hdc, x, y, options, lprect, text, characters, lpDx);
- if (!success) {
- LOGFONT lf = {0};
- SkLOGFONTFromTypeface(typeface, &lf);
- VLOG(1) << "SkFontHost::EnsureTypefaceCharactersAccessible FAILED for "
- << " FaceName = " << lf.lfFaceName
- << " and characters: " << base::string16(text, characters);
- }
- } else {
- VLOG(1) << "ExtTextOut FAILED for default FaceName "
- << " and characters: " << base::string16(text, characters);
- }
- }
- return success;
-}
-
-void VectorPlatformDeviceEmf::drawText(const SkDraw& draw,
- const void* text,
- size_t byteLength,
- SkScalar x,
- SkScalar y,
- const SkPaint& paint) {
- SkGDIFontSetup setup;
- bool useDrawPath = true;
-
- if (SkPaint::kUTF8_TextEncoding != paint.getTextEncoding()
- && setup.useGDI(hdc_, paint)) {
- UINT options = getTextOutOptions(paint);
- UINT count = byteLength >> 1;
- useDrawPath = !EnsureExtTextOut(hdc_, SkScalarRoundToInt(x),
- SkScalarRoundToInt(y + getAscent(paint)), options, 0,
- reinterpret_cast<const wchar_t*>(text), count, NULL,
- paint.getTypeface());
- }
-
- if (useDrawPath) {
- SkPath path;
- paint.getTextPath(text, byteLength, x, y, &path);
- drawPath(draw, path, paint);
- }
-}
-
-static size_t size_utf8(const char* text) {
- return SkUTF8_CountUTF8Bytes(text);
-}
-
-static size_t size_utf16(const char* text) {
- uint16_t c = *reinterpret_cast<const uint16_t*>(text);
- return SkUTF16_IsHighSurrogate(c) ? 4 : 2;
-}
-
-static size_t size_glyphid(const char* text) {
- return 2;
-}
-
-void VectorPlatformDeviceEmf::drawPosText(const SkDraw& draw,
- const void* text,
- size_t len,
- const SkScalar pos[],
- int scalarsPerPos,
- const SkPoint& offset,
- const SkPaint& paint) {
- SkGDIFontSetup setup;
- bool useDrawText = true;
-
- if (scalarsPerPos == 2 && len >= 2 &&
- SkPaint::kUTF8_TextEncoding != paint.getTextEncoding() &&
- setup.useGDI(hdc_, paint)) {
- int startX = SkScalarRoundToInt(pos[0] + offset.x());
- int startY = SkScalarRoundToInt(pos[1] + offset.y() + getAscent(paint));
- const int count = len >> 1;
- SkAutoSTMalloc<64, INT> storage(count);
- INT* advances = storage.get();
- for (int i = 0; i < count - 1; ++i) {
- advances[i] = SkScalarRoundToInt(pos[2] - pos[0]);
- pos += 2;
- }
- advances[count - 1] = 0;
- useDrawText = !EnsureExtTextOut(hdc_, startX, startY,
- getTextOutOptions(paint), 0, reinterpret_cast<const wchar_t*>(text),
- count, advances, paint.getTypeface());
- }
-
- if (useDrawText) {
- size_t (*bytesPerCodePoint)(const char*);
- switch (paint.getTextEncoding()) {
- case SkPaint::kUTF8_TextEncoding:
- bytesPerCodePoint = size_utf8;
- break;
- case SkPaint::kUTF16_TextEncoding:
- bytesPerCodePoint = size_utf16;
- break;
- default:
- SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
- bytesPerCodePoint = size_glyphid;
- break;
- }
-
- const char* curr = reinterpret_cast<const char*>(text);
- const char* stop = curr + len;
- while (curr < stop) {
- SkScalar x = offset.x() + pos[0];
- SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[1] : 0);
-
- size_t bytes = bytesPerCodePoint(curr);
- drawText(draw, curr, bytes, x, y, paint);
- curr += bytes;
- pos += scalarsPerPos;
- }
- }
-}
-
-void VectorPlatformDeviceEmf::drawTextOnPath(const SkDraw& draw,
- const void* text,
- size_t len,
- const SkPath& path,
- const SkMatrix* matrix,
- const SkPaint& paint) {
- // This function isn't used in the code. Verify this assumption.
- SkASSERT(false);
-}
-
-void VectorPlatformDeviceEmf::drawVertices(const SkDraw& draw,
- SkCanvas::VertexMode vmode,
- int vertexCount,
- const SkPoint vertices[],
- const SkPoint texs[],
- const SkColor colors[],
- SkXfermode* xmode,
- const uint16_t indices[],
- int indexCount,
- const SkPaint& paint) {
- // This function isn't used in the code. Verify this assumption.
- SkASSERT(false);
-}
-
-void VectorPlatformDeviceEmf::drawDevice(const SkDraw& draw,
- SkBaseDevice* device,
- int x,
- int y,
- const SkPaint& paint) {
- // TODO(maruel): http://b/1183870 Playback the EMF buffer at printer's dpi if
- // it is a vectorial device.
- drawSprite(draw, device->accessBitmap(false), x, y, paint);
-}
-
-bool VectorPlatformDeviceEmf::ApplyPaint(const SkPaint& paint) {
- // Note: The goal here is to transfert the SkPaint's state to the HDC's state.
- // This function does not execute the SkPaint drawing commands. These should
- // be executed in drawPaint().
-
- SkPaint::Style style = paint.getStyle();
- if (!paint.getAlpha())
- style = (SkPaint::Style) SkPaint::kStyleCount;
-
- switch (style) {
- case SkPaint::kFill_Style:
- if (!CreateBrush(true, paint) ||
- !CreatePen(false, paint))
- return false;
- break;
- case SkPaint::kStroke_Style:
- if (!CreateBrush(false, paint) ||
- !CreatePen(true, paint))
- return false;
- break;
- case SkPaint::kStrokeAndFill_Style:
- if (!CreateBrush(true, paint) ||
- !CreatePen(true, paint))
- return false;
- break;
- default:
- if (!CreateBrush(false, paint) ||
- !CreatePen(false, paint))
- return false;
- break;
- }
-
- /*
- getFlags();
- isAntiAlias();
- isDither()
- isLinearText()
- isSubpixelText()
- isUnderlineText()
- isStrikeThruText()
- isFakeBoldText()
- isDevKernText()
- isFilterBitmap()
-
- // Skia's text is not used. This should be fixed.
- getTextAlign()
- getTextScaleX()
- getTextSkewX()
- getTextEncoding()
- getFontMetrics()
- getFontSpacing()
- */
-
- // BUG 1094907: Implement shaders. Shaders currently in use:
- // SkShader::CreateBitmapShader
- // SkGradientShader::CreateRadial
- // SkGradientShader::CreateLinear
- // SkASSERT(!paint.getShader());
-
- // http://b/1106647 Implement loopers and mask filter. Looper currently in
- // use:
- // SkBlurDrawLooper is used for shadows.
- // SkASSERT(!paint.getLooper());
- // SkASSERT(!paint.getMaskFilter());
-
- // http://b/1165900 Implement xfermode.
- // SkASSERT(!paint.getXfermode());
-
- // The path effect should be processed before arriving here.
- SkASSERT(!paint.getPathEffect());
-
- // This isn't used in the code. Verify this assumption.
- SkASSERT(!paint.getRasterizer());
- // Reuse code to load Win32 Fonts.
- return true;
-}
-
-void VectorPlatformDeviceEmf::setMatrixClip(const SkMatrix& transform,
- const SkRegion& region,
- const SkClipStack&) {
- transform_ = transform;
- LoadTransformToDC(hdc_, transform_);
- clip_region_ = region;
- if (!clip_region_.isEmpty())
- LoadClipRegion();
-}
-
-void VectorPlatformDeviceEmf::LoadClipRegion() {
- SkMatrix t;
- t.reset();
- LoadClippingRegionToDC(hdc_, clip_region_, t);
-}
-
-SkBaseDevice* VectorPlatformDeviceEmf::onCreateCompatibleDevice(
- const CreateInfo& info) {
- SkASSERT(info.fInfo.colorType() == kN32_SkColorType);
- return VectorPlatformDeviceEmf::CreateDevice(
- info.fInfo.width(), info.fInfo.height(), info.fInfo.isOpaque(), NULL);
-}
-
-bool VectorPlatformDeviceEmf::CreateBrush(bool use_brush, COLORREF color) {
- SkASSERT(previous_brush_ == NULL);
- // We can't use SetDCBrushColor() or DC_BRUSH when drawing to a EMF buffer.
- // SetDCBrushColor() calls are not recorded at all and DC_BRUSH will use
- // WHITE_BRUSH instead.
-
- if (!use_brush) {
- // Set the transparency.
- if (0 == SetBkMode(hdc_, TRANSPARENT)) {
- SkASSERT(false);
- return false;
- }
-
- // Select the NULL brush.
- previous_brush_ = SelectObject(GetStockObject(NULL_BRUSH));
- return previous_brush_ != NULL;
- }
-
- // Set the opacity.
- if (0 == SetBkMode(hdc_, OPAQUE)) {
- SkASSERT(false);
- return false;
- }
-
- // Create and select the brush.
- previous_brush_ = SelectObject(CreateSolidBrush(color));
- return previous_brush_ != NULL;
-}
-
-bool VectorPlatformDeviceEmf::CreatePen(bool use_pen,
- COLORREF color,
- int stroke_width,
- float stroke_miter,
- DWORD pen_style) {
- SkASSERT(previous_pen_ == NULL);
- // We can't use SetDCPenColor() or DC_PEN when drawing to a EMF buffer.
- // SetDCPenColor() calls are not recorded at all and DC_PEN will use BLACK_PEN
- // instead.
-
- // No pen case
- if (!use_pen) {
- previous_pen_ = SelectObject(GetStockObject(NULL_PEN));
- return previous_pen_ != NULL;
- }
-
- // Use the stock pen if the stroke width is 0.
- if (stroke_width == 0) {
- // Create a pen with the right color.
- previous_pen_ = SelectObject(::CreatePen(PS_SOLID, 0, color));
- return previous_pen_ != NULL;
- }
-
- // Load a custom pen.
- LOGBRUSH brush = {0};
- brush.lbStyle = BS_SOLID;
- brush.lbColor = color;
- brush.lbHatch = 0;
- HPEN pen = ExtCreatePen(pen_style, stroke_width, &brush, 0, NULL);
- SkASSERT(pen != NULL);
- previous_pen_ = SelectObject(pen);
- if (previous_pen_ == NULL)
- return false;
-
- if (!SetMiterLimit(hdc_, stroke_miter, NULL)) {
- SkASSERT(false);
- return false;
- }
- return true;
-}
-
-void VectorPlatformDeviceEmf::Cleanup() {
- if (previous_brush_) {
- HGDIOBJ result = SelectObject(previous_brush_);
- previous_brush_ = NULL;
- if (result) {
- BOOL res = DeleteObject(result);
- SkASSERT(res != 0);
- }
- }
- if (previous_pen_) {
- HGDIOBJ result = SelectObject(previous_pen_);
- previous_pen_ = NULL;
- if (result) {
- BOOL res = DeleteObject(result);
- SkASSERT(res != 0);
- }
- }
- // Remove any loaded path from the context.
- AbortPath(hdc_);
-}
-
-HGDIOBJ VectorPlatformDeviceEmf::SelectObject(HGDIOBJ object) {
- HGDIOBJ result = ::SelectObject(hdc_, object);
- SkASSERT(result != HGDI_ERROR);
- if (result == HGDI_ERROR)
- return NULL;
- return result;
-}
-
-bool VectorPlatformDeviceEmf::CreateBrush(bool use_brush,
- const SkPaint& paint) {
- // Make sure that for transparent color, no brush is used.
- if (paint.getAlpha() == 0) {
- use_brush = false;
- }
-
- return CreateBrush(use_brush, SkColorToCOLORREF(paint.getColor()));
-}
-
-bool VectorPlatformDeviceEmf::CreatePen(bool use_pen, const SkPaint& paint) {
- // Make sure that for transparent color, no pen is used.
- if (paint.getAlpha() == 0) {
- use_pen = false;
- }
-
- DWORD pen_style = PS_GEOMETRIC | PS_SOLID;
- switch (paint.getStrokeJoin()) {
- case SkPaint::kMiter_Join:
- // Connects path segments with a sharp join.
- pen_style |= PS_JOIN_MITER;
- break;
- case SkPaint::kRound_Join:
- // Connects path segments with a round join.
- pen_style |= PS_JOIN_ROUND;
- break;
- case SkPaint::kBevel_Join:
- // Connects path segments with a flat bevel join.
- pen_style |= PS_JOIN_BEVEL;
- break;
- default:
- SkASSERT(false);
- break;
- }
- switch (paint.getStrokeCap()) {
- case SkPaint::kButt_Cap:
- // Begin/end contours with no extension.
- pen_style |= PS_ENDCAP_FLAT;
- break;
- case SkPaint::kRound_Cap:
- // Begin/end contours with a semi-circle extension.
- pen_style |= PS_ENDCAP_ROUND;
- break;
- case SkPaint::kSquare_Cap:
- // Begin/end contours with a half square extension.
- pen_style |= PS_ENDCAP_SQUARE;
- break;
- default:
- SkASSERT(false);
- break;
- }
-
- return CreatePen(use_pen,
- SkColorToCOLORREF(paint.getColor()),
- SkScalarRoundToInt(paint.getStrokeWidth()),
- paint.getStrokeMiter(),
- pen_style);
-}
-
-void VectorPlatformDeviceEmf::InternalDrawBitmap(const SkBitmap& bitmap,
- int x, int y,
- const SkPaint& paint) {
- unsigned char alpha = paint.getAlpha();
- if (alpha == 0)
- return;
-
- bool is_translucent;
- if (alpha != 255) {
- // ApplyPaint expect an opaque color.
- SkPaint tmp_paint(paint);
- tmp_paint.setAlpha(255);
- if (!ApplyPaint(tmp_paint))
- return;
- is_translucent = true;
- } else {
- if (!ApplyPaint(paint))
- return;
- is_translucent = false;
- }
- int src_size_x = bitmap.width();
- int src_size_y = bitmap.height();
- if (!src_size_x || !src_size_y)
- return;
-
- // Create a BMP v4 header that we can serialize. We use the shared "V3"
- // fillter to fill the stardard items, then add in the "V4" stuff we want.
- BITMAPV4HEADER bitmap_header = {0};
- FillBitmapInfoHeader(src_size_x, src_size_y,
- reinterpret_cast<BITMAPINFOHEADER*>(&bitmap_header));
- bitmap_header.bV4Size = sizeof(BITMAPV4HEADER);
- bitmap_header.bV4RedMask = 0x00ff0000;
- bitmap_header.bV4GreenMask = 0x0000ff00;
- bitmap_header.bV4BlueMask = 0x000000ff;
- bitmap_header.bV4AlphaMask = 0xff000000;
-
- SkAutoLockPixels lock(bitmap);
- SkASSERT(bitmap.colorType() == kN32_SkColorType);
- const uint32_t* pixels = static_cast<const uint32_t*>(bitmap.getPixels());
- if (pixels == NULL) {
- SkASSERT(false);
- return;
- }
-
- if (!is_translucent) {
- int row_length = bitmap.rowBytesAsPixels();
- // There is no quick way to determine if an image is opaque.
- for (int y2 = 0; y2 < src_size_y; ++y2) {
- for (int x2 = 0; x2 < src_size_x; ++x2) {
- if (SkColorGetA(pixels[(y2 * row_length) + x2]) != 255) {
- is_translucent = true;
- y2 = src_size_y;
- break;
- }
- }
- }
- }
-
- HDC dc = BeginPlatformPaint();
- BITMAPINFOHEADER hdr = {0};
- FillBitmapInfoHeader(src_size_x, src_size_y, &hdr);
- if (is_translucent) {
- // The image must be loaded as a bitmap inside a device context.
- HDC bitmap_dc = ::CreateCompatibleDC(dc);
- void* bits = NULL;
- HBITMAP hbitmap = ::CreateDIBSection(
- bitmap_dc, reinterpret_cast<const BITMAPINFO*>(&hdr),
- DIB_RGB_COLORS, &bits, NULL, 0);
-
- // static cast to a char so we can do byte ptr arithmatic to
- // get the offset.
- unsigned char* dest_buffer = static_cast<unsigned char *>(bits);
-
- // We will copy row by row to avoid having to worry about
- // the row strides being different.
- const int dest_row_size = hdr.biBitCount / 8 * hdr.biWidth;
- for (int row = 0; row < bitmap.height(); ++row) {
- int dest_offset = row * dest_row_size;
- // pixels_offset in terms of pixel count.
- int src_offset = row * bitmap.rowBytesAsPixels();
- memcpy(dest_buffer + dest_offset, pixels + src_offset, dest_row_size);
- }
- SkASSERT(hbitmap);
- HGDIOBJ old_bitmap = ::SelectObject(bitmap_dc, hbitmap);
-
- // After some analysis of IE7's behavior, this is the thing to do. I was
- // sure IE7 was doing so kind of bitmasking due to the way translucent image
- // where renderered but after some windbg tracing, it is being done by the
- // printer driver after all (mostly HP printers). IE7 always use AlphaBlend
- // for bitmasked images. The trick seems to switch the stretching mode in
- // what the driver expects.
- DWORD previous_mode = GetStretchBltMode(dc);
- BOOL result = SetStretchBltMode(dc, COLORONCOLOR);
- SkASSERT(result);
- // Note that this function expect premultiplied colors (!)
- BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
- result = GdiAlphaBlend(dc,
- x, y, // Destination origin.
- src_size_x, src_size_y, // Destination size.
- bitmap_dc,
- 0, 0, // Source origin.
- src_size_x, src_size_y, // Source size.
- blend_function);
- SkASSERT(result);
- result = SetStretchBltMode(dc, previous_mode);
- SkASSERT(result);
-
- ::SelectObject(bitmap_dc, static_cast<HBITMAP>(old_bitmap));
- DeleteObject(hbitmap);
- DeleteDC(bitmap_dc);
- } else {
- int nCopied = StretchDIBits(dc,
- x, y, // Destination origin.
- src_size_x, src_size_y,
- 0, 0, // Source origin.
- src_size_x, src_size_y, // Source size.
- pixels,
- reinterpret_cast<const BITMAPINFO*>(&hdr),
- DIB_RGB_COLORS,
- SRCCOPY);
- }
- EndPlatformPaint();
- Cleanup();
-}
-
-} // namespace skia
diff --git a/skia/ext/vector_platform_device_emf_win.h b/skia/ext/vector_platform_device_emf_win.h
deleted file mode 100644
index 81b92af..0000000
--- a/skia/ext/vector_platform_device_emf_win.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2011 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 SKIA_EXT_VECTOR_PLATFORM_DEVICE_EMF_WIN_H_
-#define SKIA_EXT_VECTOR_PLATFORM_DEVICE_EMF_WIN_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "skia/ext/platform_device.h"
-#include "third_party/skia/include/core/SkMatrix.h"
-#include "third_party/skia/include/core/SkRegion.h"
-
-namespace skia {
-
-// A device is basically a wrapper around SkBitmap that provides a surface for
-// SkCanvas to draw into. This specific device is not not backed by a surface
-// and is thus unreadable. This is because the backend is completely vectorial.
-// This device is a simple wrapper over a Windows device context (HDC) handle.
-// TODO(robertphillips): Once Skia's SkBaseDevice is refactored to remove
-// the bitmap-specific entry points, this class should derive from it.
-class VectorPlatformDeviceEmf : public SkBitmapDevice, public PlatformDevice {
- public:
- SK_API static SkBaseDevice* CreateDevice(int width, int height, bool isOpaque,
- HANDLE shared_section);
-
- // Factory function. The DC is kept as the output context.
- static SkBaseDevice* create(HDC dc, int width, int height);
-
- VectorPlatformDeviceEmf(HDC dc, const SkBitmap& bitmap);
- virtual ~VectorPlatformDeviceEmf();
-
- // PlatformDevice methods
- virtual PlatformSurface BeginPlatformPaint() override;
-
- // SkBaseDevice methods.
- virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) override;
- virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
- size_t count, const SkPoint[],
- const SkPaint& paint) override;
- virtual void drawRect(const SkDraw& draw, const SkRect& r,
- const SkPaint& paint) override;
- virtual void drawRRect(const SkDraw&, const SkRRect& rr,
- const SkPaint& paint) override;
- virtual void drawPath(const SkDraw& draw, const SkPath& path,
- const SkPaint& paint,
- const SkMatrix* prePathMatrix = NULL,
- bool pathIsMutable = false) override;
- virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
- const SkRect* src, const SkRect& dst,
- const SkPaint& paint,
- SkCanvas::DrawBitmapRectFlags flags) override;
- virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
- const SkMatrix& matrix,
- const SkPaint& paint) override;
- virtual void drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
- int x, int y, const SkPaint& paint) override;
- virtual void drawText(const SkDraw& draw, const void* text, size_t len,
- SkScalar x, SkScalar y, const SkPaint& paint) override;
- virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
- const SkScalar pos[], int scalarsPerPos,
- const SkPoint& offset, const SkPaint& paint) override;
- virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) override;
- virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode,
- int vertexCount,
- const SkPoint verts[], const SkPoint texs[],
- const SkColor colors[], SkXfermode* xmode,
- const uint16_t indices[], int indexCount,
- const SkPaint& paint) override;
- virtual void drawDevice(const SkDraw& draw, SkBaseDevice*, int x, int y,
- const SkPaint&) override;
-
- virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region,
- const SkClipStack&) override;
-
- void LoadClipRegion();
-
- protected:
- virtual SkBaseDevice* onCreateCompatibleDevice(const CreateInfo& info) override;
-
- private:
- // Applies the SkPaint's painting properties in the current GDI context, if
- // possible. If GDI can't support all paint's properties, returns false. It
- // doesn't execute the "commands" in SkPaint.
- bool ApplyPaint(const SkPaint& paint);
-
- // Selects a new object in the device context. It can be a pen, a brush, a
- // clipping region, a bitmap or a font. Returns the old selected object.
- HGDIOBJ SelectObject(HGDIOBJ object);
-
- // Creates a brush according to SkPaint's properties.
- bool CreateBrush(bool use_brush, const SkPaint& paint);
-
- // Creates a pen according to SkPaint's properties.
- bool CreatePen(bool use_pen, const SkPaint& paint);
-
- // Restores back the previous objects (pen, brush, etc) after a paint command.
- void Cleanup();
-
- // Creates a brush according to SkPaint's properties.
- bool CreateBrush(bool use_brush, COLORREF color);
-
- // Creates a pen according to SkPaint's properties.
- bool CreatePen(bool use_pen, COLORREF color, int stroke_width,
- float stroke_miter, DWORD pen_style);
-
- // Draws a bitmap in the the device, using the currently loaded matrix.
- void InternalDrawBitmap(const SkBitmap& bitmap, int x, int y,
- const SkPaint& paint);
-
- // The Windows Device Context handle. It is the backend used with GDI drawing.
- // This backend is write-only and vectorial.
- HDC hdc_;
-
- // Translation assigned to the DC: we need to keep track of this separately
- // so it can be updated even if the DC isn't created yet.
- SkMatrix transform_;
-
- // The current clipping
- SkRegion clip_region_;
-
- // Previously selected brush before the current drawing.
- HGDIOBJ previous_brush_;
-
- // Previously selected pen before the current drawing.
- HGDIOBJ previous_pen_;
-
- DISALLOW_COPY_AND_ASSIGN(VectorPlatformDeviceEmf);
-};
-
-typedef void (*SkiaEnsureTypefaceCharactersAccessible)
- (const LOGFONT& font, const wchar_t* text, unsigned int text_length);
-
-SK_API void SetSkiaEnsureTypefaceCharactersAccessible(
- SkiaEnsureTypefaceCharactersAccessible func);
-
-} // namespace skia
-
-#endif // SKIA_EXT_VECTOR_PLATFORM_DEVICE_EMF_WIN_H_
diff --git a/skia/skia_chrome.gypi b/skia/skia_chrome.gypi
index 6a24635..d689a92 100644
--- a/skia/skia_chrome.gypi
+++ b/skia/skia_chrome.gypi
@@ -77,9 +77,6 @@
'ext/skia_utils_mac.h',
'ext/skia_utils_win.cc',
'ext/skia_utils_win.h',
- 'ext/vector_canvas.h',
- 'ext/vector_platform_device_emf_win.cc',
- 'ext/vector_platform_device_emf_win.h',
],
'conditions': [
[ 'OS == "android" and '
diff --git a/skia/skia_tests.gyp b/skia/skia_tests.gyp
index fcc7347..698493d 100644
--- a/skia/skia_tests.gyp
+++ b/skia/skia_tests.gyp
@@ -29,14 +29,8 @@
'ext/refptr_unittest.cc',
'ext/skia_utils_ios_unittest.mm',
'ext/skia_utils_mac_unittest.mm',
- 'ext/vector_canvas_unittest.cc',
],
'conditions': [
- ['OS != "win"', {
- 'sources!': [
- 'ext/vector_canvas_unittest.cc',
- ],
- }],
['OS != "win" and OS != "mac"', {
'sources!': [
'ext/platform_canvas_unittest.cc',
diff --git a/sky/compositor/layer.cc b/sky/compositor/layer.cc
index 006206d..5c05fdf 100644
--- a/sky/compositor/layer.cc
+++ b/sky/compositor/layer.cc
@@ -4,7 +4,7 @@
#include "sky/compositor/layer.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
#include "sky/compositor/layer_host.h"
#include "sky/compositor/picture_serializer.h"
#include "sky/compositor/rasterizer.h"
diff --git a/sky/compositor/layer_host.cc b/sky/compositor/layer_host.cc
index 697ed26..bf46618 100644
--- a/sky/compositor/layer_host.cc
+++ b/sky/compositor/layer_host.cc
@@ -4,8 +4,8 @@
#include "sky/compositor/layer_host.h"
-#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop.h"
+#include "base/trace_event/trace_event.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/gpu/gl_context.h"
#include "mojo/services/surfaces/public/cpp/surfaces_utils.h"
diff --git a/sky/compositor/rasterizer_ganesh.cc b/sky/compositor/rasterizer_ganesh.cc
index d91749e..46ac59b 100644
--- a/sky/compositor/rasterizer_ganesh.cc
+++ b/sky/compositor/rasterizer_ganesh.cc
@@ -4,7 +4,7 @@
#include "sky/compositor/rasterizer_ganesh.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
#include "mojo/skia/ganesh_surface.h"
#include "sky/compositor/layer_host.h"
#include "third_party/skia/include/core/SkCanvas.h"
diff --git a/sky/engine/platform/SharedTimer.cpp b/sky/engine/platform/SharedTimer.cpp
index 90312a1..8debac0 100644
--- a/sky/engine/platform/SharedTimer.cpp
+++ b/sky/engine/platform/SharedTimer.cpp
@@ -5,6 +5,7 @@
#include "sky/engine/config.h"
#include "sky/engine/platform/SharedTimer.h"
+#include <cmath>
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "sky/engine/wtf/CurrentTime.h"
diff --git a/sky/engine/platform/TraceEvent.h b/sky/engine/platform/TraceEvent.h
index bd0c344..d0d23a5 100644
--- a/sky/engine/platform/TraceEvent.h
+++ b/sky/engine/platform/TraceEvent.h
@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
diff --git a/sky/engine/platform/network/ResourceResponse.cpp b/sky/engine/platform/network/ResourceResponse.cpp
index 200e583..2614e1d 100644
--- a/sky/engine/platform/network/ResourceResponse.cpp
+++ b/sky/engine/platform/network/ResourceResponse.cpp
@@ -27,6 +27,7 @@
#include "sky/engine/config.h"
#include "sky/engine/platform/network/ResourceResponse.h"
+#include <cmath>
#include "sky/engine/wtf/CurrentTime.h"
#include "sky/engine/wtf/StdLibExtras.h"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 01d893f..b5fc002 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -743,6 +743,9 @@
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
+ "sbox_unittests",
+ "sbox_integration_tests",
+ "sbox_validation_tests",
"ipc_tests",
"sync_unit_tests",
"skia_unittests",
@@ -791,6 +794,9 @@
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
+ "sbox_unittests",
+ "sbox_integration_tests",
+ "sbox_validation_tests",
"ipc_tests",
"sync_unit_tests",
"skia_unittests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index c9059e7..55e5481 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -101,6 +101,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
@@ -245,6 +246,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
@@ -389,6 +391,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
@@ -534,6 +537,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json
index 7244be8..3d5b728 100644
--- a/testing/buildbot/chromium.memory.fyi.json
+++ b/testing/buildbot/chromium.memory.fyi.json
@@ -4,7 +4,12 @@
"accessibility_unittests",
"app_list_unittests",
"aura_unittests",
- "base_unittests",
+ {
+ "test": "base_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"cacheinvalidation_unittests",
"cast_unittests",
"cc_unittests",
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 452fc51..c462aaf 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -92,6 +92,7 @@
"can_use_on_swarming_builders": true
}
},
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
@@ -233,6 +234,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
@@ -382,6 +384,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
@@ -535,6 +538,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
@@ -681,6 +685,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json
index c5e51b6..c2d7e72 100644
--- a/testing/buildbot/chromium_trybot.json
+++ b/testing/buildbot/chromium_trybot.json
@@ -174,10 +174,7 @@
"mojo_public_system_unittests",
"mojo_public_utility_unittests",
"mojo_system_unittests",
- {
- "test": "nacl_loader_unittests",
- "platforms": ["linux"]
- },
+ "nacl_loader_unittests",
{
"test": "net_unittests",
"swarming": {
diff --git a/testing/gtest.gyp b/testing/gtest.gyp
index c4510f6..d61772e 100644
--- a/testing/gtest.gyp
+++ b/testing/gtest.gyp
@@ -39,6 +39,7 @@
'sources': [
'gtest_mac.h',
'gtest_mac.mm',
+ 'platform_test_mac.mm',
],
'link_settings': {
'libraries': [
@@ -46,11 +47,6 @@
],
},
}],
- ['OS == "mac"', {
- 'sources': [
- 'platform_test_mac.mm',
- ],
- }],
['OS == "ios"', {
'dependencies' : [
'<(DEPTH)/testing/iossim/iossim.gyp:iossim#host',
@@ -85,7 +81,6 @@
'sources': [
'coverage_util_ios.cc',
'coverage_util_ios.h',
- 'platform_test_ios.mm',
],
}],
['OS=="ios" and asan==1', {
diff --git a/testing/legion/__init__.py b/testing/legion/__init__.py
new file mode 100644
index 0000000..50b23df
--- /dev/null
+++ b/testing/legion/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/testing/legion/client_controller.py b/testing/legion/client_controller.py
new file mode 100755
index 0000000..dd80c29
--- /dev/null
+++ b/testing/legion/client_controller.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The main client_controller code.
+
+This code is the main entry point for the client machines and handles
+registering with the host server and running the local RPC server.
+"""
+
+import argparse
+import logging
+import socket
+import sys
+import time
+
+#pylint: disable=relative-import
+import client_rpc_server
+import common_lib
+
+
+def main():
+ print ' '.join(sys.argv)
+ common_lib.InitLogging()
+ logging.info('Client controller starting')
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--otp',
+ help='One time token used to authenticate with the host')
+ parser.add_argument('--host',
+ help='The ip address of the host')
+ parser.add_argument('--idle-timeout', type=int,
+ default=common_lib.DEFAULT_TIMEOUT_SECS,
+ help='The idle timeout for the rpc server in seconds')
+ args, _ = parser.parse_known_args()
+
+ logging.info(
+ 'Registering with discovery server at %s using OTP %s', args.host,
+ args.otp)
+ server = common_lib.ConnectToServer(args.host).RegisterClient(
+ args.otp, common_lib.MY_IP)
+
+ server = client_rpc_server.RPCServer(args.host, args.idle_timeout)
+
+ server.serve_forever()
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/testing/legion/client_lib.py b/testing/legion/client_lib.py
new file mode 100644
index 0000000..4d6a633
--- /dev/null
+++ b/testing/legion/client_lib.py
@@ -0,0 +1,214 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Defines the client library."""
+
+import argparse
+import datetime
+import logging
+import os
+import socket
+import subprocess
+import sys
+import tempfile
+import threading
+import xmlrpclib
+
+#pylint: disable=relative-import
+import common_lib
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+SWARMING_DIR = os.path.join(THIS_DIR, '..', '..', 'tools/swarming_client')
+ISOLATE_PY = os.path.join(SWARMING_DIR, 'isolate.py')
+SWARMING_PY = os.path.join(SWARMING_DIR, 'swarming.py')
+
+
+class Error(Exception):
+ pass
+
+
+class ConnectionTimeoutError(Error):
+ pass
+
+
+class ClientController(object):
+ """Creates, configures, and controls a client machine."""
+
+ _client_count = 0
+ _controllers = []
+
+ def __init__(self, isolate_file, config_vars, dimensions, priority=100,
+ idle_timeout_secs=common_lib.DEFAULT_TIMEOUT_SECS,
+ connection_timeout_secs=common_lib.DEFAULT_TIMEOUT_SECS,
+ verbosity='ERROR', name=None):
+ assert isinstance(config_vars, dict)
+ assert isinstance(dimensions, dict)
+ type(self)._controllers.append(self)
+ type(self)._client_count += 1
+ self.verbosity = verbosity
+ self._name = name or 'Client%d' % type(self)._client_count
+ self._priority = priority
+ self._isolate_file = isolate_file
+ self._isolated_file = isolate_file + 'd'
+ self._idle_timeout_secs = idle_timeout_secs
+ self._config_vars = config_vars
+ self._dimensions = dimensions
+ self._connect_event = threading.Event()
+ self._connected = False
+ self._ip_address = None
+ self._otp = self._CreateOTP()
+ self._rpc = None
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--isolate-server')
+ parser.add_argument('--swarming-server')
+ parser.add_argument('--client-connection-timeout-secs',
+ default=common_lib.DEFAULT_TIMEOUT_SECS)
+ args, _ = parser.parse_known_args()
+
+ self._isolate_server = args.isolate_server
+ self._swarming_server = args.swarming_server
+ self._connection_timeout_secs = (connection_timeout_secs or
+ args.client_connection_timeout_secs)
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def otp(self):
+ return self._otp
+
+ @property
+ def connected(self):
+ return self._connected
+
+ @property
+ def connect_event(self):
+ return self._connect_event
+
+ @property
+ def rpc(self):
+ return self._rpc
+
+ @property
+ def verbosity(self):
+ return self._verbosity
+
+ @verbosity.setter
+ def verbosity(self, level):
+ """Sets the verbosity level as a string.
+
+ Either a string ('INFO', 'DEBUG', etc) or a logging level (logging.INFO,
+ logging.DEBUG, etc) is allowed.
+ """
+ assert isinstance(level, (str, int))
+ if isinstance(level, int):
+ level = logging.getLevelName(level)
+ self._verbosity = level #pylint: disable=attribute-defined-outside-init
+
+ @classmethod
+ def ReleaseAllControllers(cls):
+ for controller in cls._controllers:
+ controller.Release()
+
+ def _CreateOTP(self):
+ """Creates the OTP."""
+ host_name = socket.gethostname()
+ test_name = os.path.basename(sys.argv[0])
+ creation_time = datetime.datetime.utcnow()
+ otp = 'client:%s-host:%s-test:%s-creation:%s' % (
+ self._name, host_name, test_name, creation_time)
+ return otp
+
+ def Create(self):
+ """Creates the client machine."""
+ logging.info('Creating %s', self.name)
+ self._connect_event.clear()
+ self._ExecuteIsolate()
+ self._ExecuteSwarming()
+
+ def WaitForConnection(self):
+ """Waits for the client machine to connect.
+
+ Raises:
+ ConnectionTimeoutError if the client doesn't connect in time.
+ """
+ logging.info('Waiting for %s to connect with a timeout of %d seconds',
+ self._name, self._connection_timeout_secs)
+ self._connect_event.wait(self._connection_timeout_secs)
+ if not self._connect_event.is_set():
+ raise ConnectionTimeoutError('%s failed to connect' % self.name)
+
+ def Release(self):
+ """Quits the client's RPC server so it can release the machine."""
+ if self._rpc is not None and self._connected:
+ logging.info('Releasing %s', self._name)
+ try:
+ self._rpc.Quit()
+ except (socket.error, xmlrpclib.Fault):
+ logging.error('Unable to connect to %s to call Quit', self.name)
+ self._rpc = None
+ self._connected = False
+
+ def _ExecuteIsolate(self):
+ """Executes isolate.py."""
+ cmd = [
+ 'python',
+ ISOLATE_PY,
+ 'archive',
+ '--isolate', self._isolate_file,
+ '--isolated', self._isolated_file,
+ ]
+
+ if self._isolate_server:
+ cmd.extend(['--isolate-server', self._isolate_server])
+ for key, value in self._config_vars.iteritems():
+ cmd.extend(['--config-var', key, value])
+
+ self._ExecuteProcess(cmd)
+
+ def _ExecuteSwarming(self):
+ """Executes swarming.py."""
+ cmd = [
+ 'python',
+ SWARMING_PY,
+ 'trigger',
+ self._isolated_file,
+ '--priority', str(self._priority),
+ ]
+
+ if self._isolate_server:
+ cmd.extend(['--isolate-server', self._isolate_server])
+ if self._swarming_server:
+ cmd.extend(['--swarming', self._swarming_server])
+ for key, value in self._dimensions.iteritems():
+ cmd.extend(['--dimension', key, value])
+
+ cmd.extend([
+ '--',
+ '--host', common_lib.MY_IP,
+ '--otp', self._otp,
+ '--verbosity', self._verbosity,
+ '--idle-timeout', str(self._idle_timeout_secs),
+ ])
+
+ self._ExecuteProcess(cmd)
+
+ def _ExecuteProcess(self, cmd):
+ """Executes a process, waits for it to complete, and checks for success."""
+ logging.debug('Running %s', ' '.join(cmd))
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ _, stderr = p.communicate()
+ if p.returncode != 0:
+ stderr.seek(0)
+ raise Error(stderr)
+
+ def OnConnect(self, ip_address):
+ """Receives client ip address on connection."""
+ self._ip_address = ip_address
+ self._connected = True
+ self._rpc = common_lib.ConnectToServer(self._ip_address)
+ logging.info('%s connected from %s', self._name, ip_address)
+ self._connect_event.set()
diff --git a/testing/legion/client_rpc_methods.py b/testing/legion/client_rpc_methods.py
new file mode 100644
index 0000000..24a552e
--- /dev/null
+++ b/testing/legion/client_rpc_methods.py
@@ -0,0 +1,42 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Defines the client RPC methods."""
+
+import logging
+import subprocess
+import threading
+
+
+class RPCMethods(object):
+ """Class exposing RPC methods."""
+
+ def __init__(self, server):
+ self.server = server
+
+ def Echo(self, message):
+ """Simple RPC method to print and return a message."""
+ logging.info('Echoing %s', message)
+ return 'echo %s' % str(message)
+
+ def Subprocess(self, cmd):
+ """Run the commands in a subprocess.
+
+ Returns:
+ (returncode, stdout, stderr).
+ """
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ return (p.returncode, stdout, stderr)
+
+ def Quit(self):
+ """Call server.shutdown in another thread.
+
+ This is needed because server.shutdown waits for the server to actually
+ quit. However the server cannot shutdown until it completes handling this
+ call. Calling this in the same thread results in a deadlock.
+ """
+ t = threading.Thread(target=self.server.shutdown)
+ t.start()
diff --git a/testing/legion/client_rpc_server.py b/testing/legion/client_rpc_server.py
new file mode 100644
index 0000000..7a5f565
--- /dev/null
+++ b/testing/legion/client_rpc_server.py
@@ -0,0 +1,128 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The client RPC server code.
+
+This server is an XML-RPC server which serves code from
+client_rpc_methods.RPCMethods.
+
+This server will run until shutdown is called on the server object. This can
+be achieved in 2 ways:
+
+- Calling the Quit RPC method defined in RPCMethods
+- Not receiving any calls within the idle_timeout_secs time.
+"""
+
+import logging
+import threading
+import time
+import xmlrpclib
+import SimpleXMLRPCServer
+import SocketServer
+
+#pylint: disable=relative-import
+import client_rpc_methods
+import common_lib
+
+
+class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
+ """Restricts access to only specified IP address.
+
+ This call assumes the server is RPCServer.
+ """
+
+ def do_POST(self):
+ """Verifies the client is authorized to perform RPCs."""
+ if self.client_address[0] != self.server.authorized_address:
+ logging.error('Received unauthorized RPC request from %s',
+ self.client_address[0])
+ self.send_response(403)
+ response = 'Forbidden'
+ self.send_header('Content-type', 'text/plain')
+ self.send_header('Content-length', str(len(response)))
+ self.end_headers()
+ self.wfile.write(response)
+ else:
+ return SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self)
+
+
+class RPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer,
+ SocketServer.ThreadingMixIn):
+ """Restricts all endpoints to only specified IP addresses."""
+
+ def __init__(self, authorized_address,
+ idle_timeout_secs=common_lib.DEFAULT_TIMEOUT_SECS):
+ SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(
+ self, (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT),
+ allow_none=True, logRequests=False,
+ requestHandler=RequestHandler)
+
+ self.authorized_address = authorized_address
+ self.idle_timeout_secs = idle_timeout_secs
+ self.register_instance(client_rpc_methods.RPCMethods(self))
+
+ self._shutdown_requested_event = threading.Event()
+ self._rpc_received_event = threading.Event()
+ self._idle_thread = threading.Thread(target=self._CheckForIdleQuit)
+
+ def shutdown(self):
+ """Shutdown the server.
+
+ This overloaded method sets the _shutdown_requested_event to allow the
+ idle timeout thread to quit.
+ """
+ self._shutdown_requested_event.set()
+ SimpleXMLRPCServer.SimpleXMLRPCServer.shutdown(self)
+ logging.info('Server shutdown complete')
+
+ def serve_forever(self, poll_interval=0.5):
+ """Serve forever.
+
+ This overloaded method starts the idle timeout thread before calling
+ serve_forever. This ensures the idle timer thread doesn't get started
+ without the server running.
+
+ Args:
+ poll_interval: The interval to poll for shutdown.
+ """
+ logging.info('RPC server starting')
+ self._idle_thread.start()
+ SimpleXMLRPCServer.SimpleXMLRPCServer.serve_forever(self, poll_interval)
+
+ def _dispatch(self, method, params):
+ """Dispatch the call to the correct method with the provided params.
+
+ This overloaded method adds logging to help trace connection and
+ call problems.
+
+ Args:
+ method: The method name to call.
+ params: A tuple of parameters to pass.
+
+ Returns:
+ The result of the parent class' _dispatch method.
+ """
+ logging.debug('Calling %s%s', method, params)
+ self._rpc_received_event.set()
+ return SimpleXMLRPCServer.SimpleXMLRPCServer._dispatch(self, method, params)
+
+ def _CheckForIdleQuit(self):
+ """Check for, and exit, if the server is idle for too long.
+
+ This method must be run in a separate thread to avoid a deadlock when
+ calling server.shutdown.
+ """
+ timeout = time.time() + self.idle_timeout_secs
+ while time.time() < timeout:
+ if self._shutdown_requested_event.is_set():
+ # An external source called shutdown()
+ return
+ elif self._rpc_received_event.is_set():
+ logging.debug('Resetting the idle timeout')
+ timeout = time.time() + self.idle_timeout_secs
+ self._rpc_received_event.clear()
+ time.sleep(1)
+ # We timed out, kill the server
+ logging.warning('Shutting down the server due to the idle timeout')
+ self.shutdown()
diff --git a/testing/legion/common_lib.py b/testing/legion/common_lib.py
new file mode 100644
index 0000000..b66481e
--- /dev/null
+++ b/testing/legion/common_lib.py
@@ -0,0 +1,40 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Common library methods used by both host and client controllers."""
+
+import argparse
+import logging
+import socket
+import xmlrpclib
+
+LOGGING_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'WARN', 'ERROR']
+MY_IP = socket.gethostbyname(socket.gethostname())
+SERVER_ADDRESS = ''
+SERVER_PORT = 31710
+DEFAULT_TIMEOUT_SECS = 20 * 60 # 30 minutes
+
+
+def InitLogging():
+ """Initialize the logging module.
+
+ Raises:
+ argparse.ArgumentError if the --verbosity arg is incorrect.
+ """
+ parser = argparse.ArgumentParser()
+ logging_action = parser.add_argument('--verbosity', default='ERROR')
+ args, _ = parser.parse_known_args()
+ if args.verbosity not in LOGGING_LEVELS:
+ raise argparse.ArgumentError(
+ logging_action, 'Only levels %s supported' % str(LOGGING_LEVELS))
+ logging.basicConfig(
+ format='%(asctime)s %(filename)s:%(lineno)s %(levelname)s] %(message)s',
+ datefmt='%H:%M:%S', level=args.verbosity)
+
+
+def ConnectToServer(server):
+ """Connect to an RPC server."""
+ addr = 'http://%s:%d' % (server, SERVER_PORT)
+ logging.debug('Connecting to RPC server at %s', addr)
+ return xmlrpclib.Server(addr)
diff --git a/testing/legion/discovery_server.py b/testing/legion/discovery_server.py
new file mode 100644
index 0000000..94786ce
--- /dev/null
+++ b/testing/legion/discovery_server.py
@@ -0,0 +1,55 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The discovery server used to register clients.
+
+The discovery server is started by the host controller and allows the clients
+to register themselves when they start. Authentication of the client controllers
+is based on an OTP passed to the client controller binary on startup.
+"""
+
+import logging
+import threading
+import xmlrpclib
+import SimpleXMLRPCServer
+
+#pylint: disable=relative-import
+import common_lib
+
+
+class DiscoveryServer(object):
+ """Discovery server run on the host."""
+
+ def __init__(self):
+ self._expected_clients = {}
+ self._rpc_server = None
+ self._thread = None
+
+ def _RegisterClientRPC(self, otp, ip):
+ """The RPC used by a client to register with the discovery server."""
+ assert otp in self._expected_clients
+ cb = self._expected_clients.pop(otp)
+ cb(ip)
+
+ def RegisterClientCallback(self, otp, callback):
+ """Registers a callback associated with an OTP."""
+ assert callable(callback)
+ self._expected_clients[otp] = callback
+
+ def Start(self):
+ """Starts the discovery server."""
+ logging.debug('Starting discovery server')
+ self._rpc_server = SimpleXMLRPCServer.SimpleXMLRPCServer(
+ (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT),
+ allow_none=True, logRequests=False)
+ self._rpc_server.register_function(
+ self._RegisterClientRPC, 'RegisterClient')
+ self._thread = threading.Thread(target=self._rpc_server.serve_forever)
+ self._thread.start()
+
+ def Shutdown(self):
+ """Shuts the discovery server down."""
+ if self._thread and self._thread.is_alive():
+ logging.debug('Shutting down discovery server')
+ self._rpc_server.shutdown()
diff --git a/testing/legion/examples/hello_world/client_test.isolate b/testing/legion/examples/hello_world/client_test.isolate
new file mode 100644
index 0000000..7135ef2
--- /dev/null
+++ b/testing/legion/examples/hello_world/client_test.isolate
@@ -0,0 +1,23 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../../legion.isolate'
+ ],
+ 'conditions': [
+ ['multi_machine == 1', {
+ 'variables': {
+ 'command': [
+ 'python',
+ '../../client_controller.py',
+ ],
+ 'files': [
+ 'client_test.py',
+ 'client_test.isolate'
+ ],
+ },
+ }],
+ ],
+}
diff --git a/testing/legion/examples/hello_world/client_test.py b/testing/legion/examples/hello_world/client_test.py
new file mode 100755
index 0000000..0333f7b
--- /dev/null
+++ b/testing/legion/examples/hello_world/client_test.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A simple client test module.
+
+This module is invoked by the host by calling the client controller's
+Subprocess RPC method. The name is passed in as a required argument on the
+command line.
+"""
+
+import argparse
+import os
+import sys
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('name')
+ args = parser.parse_args()
+ print 'Hello world from', args.name
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/testing/legion/examples/hello_world/host_test.isolate b/testing/legion/examples/hello_world/host_test.isolate
new file mode 100644
index 0000000..da4ee4e
--- /dev/null
+++ b/testing/legion/examples/hello_world/host_test.isolate
@@ -0,0 +1,22 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../../legion.isolate',
+ 'client_test.isolate'
+ ],
+ 'conditions': [
+ ['multi_machine == 1', {
+ 'variables': {
+ 'command': [
+ 'host_test.py',
+ ],
+ 'files': [
+ 'host_test.py',
+ ],
+ },
+ }],
+ ]
+}
diff --git a/testing/legion/examples/hello_world/host_test.py b/testing/legion/examples/hello_world/host_test.py
new file mode 100755
index 0000000..77eca06
--- /dev/null
+++ b/testing/legion/examples/hello_world/host_test.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A simple host test module.
+
+This module runs on the host machine and is responsible for creating 2
+client machines, waiting for them, and running RPC calls on them.
+"""
+
+# Map the legion directory so we can import the host controller.
+import sys
+sys.path.append('../../')
+
+import logging
+import time
+
+import host_controller
+
+
+class ExampleController(host_controller.HostController):
+ """A simple example controller for a test."""
+
+ def __init__(self):
+ super(ExampleController, self).__init__()
+ self.client1 = None
+ self.client2 = None
+
+ def CreateClient(self):
+ """Create a client object and set the proper values."""
+ client = self.NewClient(
+ isolate_file='client_test.isolate',
+ config_vars={'multi_machine': '1'},
+ dimensions={'os': 'Linux', 'pool': 'legion'}, priority=200,
+ idle_timeout_secs=90, connection_timeout_secs=90,
+ verbosity=logging.INFO)
+ client.Create()
+ return client
+
+ def SetUp(self):
+ """Create the client machines and wait until they connect.
+
+ In this call the actual creation of the client machines is done in parallel
+ by the system. The WaitForConnect calls are performed in series but will
+ return as soon as the clients connect.
+ """
+ self.client1 = self.CreateClient()
+ self.client2 = self.CreateClient()
+ self.client1.WaitForConnection()
+ self.client2.WaitForConnection()
+
+ def Task(self):
+ """Main method to run the task code."""
+ self.CallEcho(self.client1)
+ self.CallEcho(self.client2)
+ self.CallClientTest(self.client1)
+ self.CallClientTest(self.client2)
+
+ def CallEcho(self, client):
+ """Call rpc.Echo on a client."""
+ logging.info('Calling Echo on %s', client.name)
+ logging.info(self.client1.rpc.Echo(client.name))
+
+ def CallClientTest(self, client):
+ """Call client_test.py name on a client."""
+ logging.info('Calling Subprocess to run "./client_test.py %s"', client.name)
+ retcode, stdout, stderr = client.rpc.Subprocess(
+ ['./client_test.py', client.name])
+ logging.info('retcode: %s, stdout: %s, stderr: %s', retcode, stdout, stderr)
+
+
+if __name__ == '__main__':
+ ExampleController().RunController()
diff --git a/testing/legion/host_controller.py b/testing/legion/host_controller.py
new file mode 100644
index 0000000..dadcba4
--- /dev/null
+++ b/testing/legion/host_controller.py
@@ -0,0 +1,70 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Defines the host controller base library.
+
+This module is the basis on which host controllers are built and executed.
+"""
+
+import logging
+import sys
+
+#pylint: disable=relative-import
+import client_lib
+import common_lib
+import discovery_server
+
+
+class HostController(object):
+ """The base host controller class."""
+
+ def __init__(self):
+ self._discovery_server = discovery_server.DiscoveryServer()
+
+ def SetUp(self):
+ """Setup method used by the subclass."""
+ pass
+
+ def Task(self):
+ """Main task method used by the subclass."""
+ pass
+
+ def TearDown(self):
+ """Teardown method used by the subclass."""
+ pass
+
+ def NewClient(self, *args, **kwargs):
+ controller = client_lib.ClientController(*args, **kwargs)
+ self._discovery_server.RegisterClientCallback(
+ controller.otp, controller.OnConnect)
+ return controller
+
+ def RunController(self):
+ """Main entry point for the controller."""
+ print ' '.join(sys.argv)
+ common_lib.InitLogging()
+ self._discovery_server.Start()
+
+ error = None
+ tb = None
+ try:
+ self.SetUp()
+ self.Task()
+ except Exception as e:
+ # Defer raising exceptions until after TearDown and _TearDown are called.
+ error = e
+ tb = sys.exc_info()[-1]
+ try:
+ self.TearDown()
+ except Exception as e:
+ # Defer raising exceptions until after _TearDown is called.
+ # Note that an error raised here will obscure any errors raised
+ # previously.
+ error = e
+ tb = sys.exc_info()[-1]
+
+ self._discovery_server.Shutdown()
+ client_lib.ClientController.ReleaseAllControllers()
+ if error:
+ raise error, None, tb #pylint: disable=raising-bad-type
diff --git a/testing/legion/legion.isolate b/testing/legion/legion.isolate
new file mode 100644
index 0000000..463764d
--- /dev/null
+++ b/testing/legion/legion.isolate
@@ -0,0 +1,20 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'files': [
+ '__init__.py',
+ 'client_controller.py',
+ 'client_lib.py',
+ 'client_rpc_methods.py',
+ 'client_rpc_server.py',
+ 'common_lib.py',
+ 'discovery_server.py',
+ 'host_controller.py',
+ 'legion.isolate',
+ '../../tools/swarming_client/',
+ ],
+ },
+}
diff --git a/testing/platform_test_ios.mm b/testing/platform_test_ios.mm
deleted file mode 100644
index 5162c1d..0000000
--- a/testing/platform_test_ios.mm
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "platform_test.h"
-
-#import <Foundation/Foundation.h>
-
-#include "coverage_util_ios.h"
-
-PlatformTest::PlatformTest()
- : pool_([[NSAutoreleasePool alloc] init]) {
-}
-
-PlatformTest::~PlatformTest() {
- [pool_ release];
- coverage_util::FlushCoverageDataIfNecessary();
-}
diff --git a/testing/test_env.py b/testing/test_env.py
index 0743f34..66a3721 100755
--- a/testing/test_env.py
+++ b/testing/test_env.py
@@ -35,7 +35,10 @@
def trim_cmd(cmd):
"""Removes internal flags from cmd since they're just used to communicate from
the host machine to this script running on the swarm slaves."""
- internal_flags = frozenset(['--asan=0', '--asan=1', '--lsan=0', '--lsan=1'])
+ sanitizers = ['asan', 'lsan', 'msan', 'tsan']
+ internal_flags = frozenset('--%s=%d' % (name, value)
+ for name in sanitizers
+ for value in [0, 1])
return [i for i in cmd if i not in internal_flags]
@@ -49,12 +52,12 @@
return out
-def get_asan_env(cmd, lsan):
- """Returns the envirnoment flags needed for ASan and LSan."""
+def get_sanitizer_env(cmd, asan, lsan, msan, tsan):
+ """Returns the envirnoment flags needed for sanitizer tools."""
extra_env = {}
- # Instruct GTK to use malloc while running ASan or LSan tests.
+ # Instruct GTK to use malloc while running sanitizer-instrumented tests.
extra_env['G_SLICE'] = 'always-malloc'
extra_env['NSS_DISABLE_ARENA_FREE_LIST'] = '1'
@@ -65,25 +68,12 @@
symbolizer_path = os.path.abspath(os.path.join(ROOT_DIR, 'third_party',
'llvm-build', 'Release+Asserts', 'bin', 'llvm-symbolizer'))
- asan_options = []
- if lsan:
- asan_options.append('detect_leaks=1')
- if sys.platform == 'linux2':
- # Use the debug version of libstdc++ under LSan. If we don't, there will
- # be a lot of incomplete stack traces in the reports.
- extra_env['LD_LIBRARY_PATH'] = '/usr/lib/x86_64-linux-gnu/debug:'
-
+ if lsan or tsan:
# LSan is not sandbox-compatible, so we can use online symbolization. In
# fact, it needs symbolization to be able to apply suppressions.
symbolization_options = ['symbolize=1',
'external_symbolizer_path=%s' % symbolizer_path]
-
- suppressions_file = os.path.join(ROOT_DIR, 'tools', 'lsan',
- 'suppressions.txt')
- lsan_options = ['suppressions=%s' % suppressions_file,
- 'print_suppressions=1']
- extra_env['LSAN_OPTIONS'] = ' '.join(lsan_options)
- else:
+ elif asan or msan:
# ASan uses a script for offline symbolization.
# Important note: when running ASan with leak detection enabled, we must use
# the LSan symbolization options above.
@@ -91,26 +81,57 @@
# Set the path to llvm-symbolizer to be used by asan_symbolize.py
extra_env['LLVM_SYMBOLIZER_PATH'] = symbolizer_path
- asan_options.extend(symbolization_options)
+ if asan:
+ asan_options = symbolization_options[:]
+ if lsan:
+ asan_options.append('detect_leaks=1')
- extra_env['ASAN_OPTIONS'] = ' '.join(asan_options)
+ extra_env['ASAN_OPTIONS'] = ' '.join(asan_options)
- if sys.platform == 'darwin':
- isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0]))
- # This is needed because the test binary has @executable_path embedded in it
- # it that the OS tries to resolve to the cache directory and not the mapped
- # directory.
- extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir)
+ if sys.platform == 'darwin':
+ isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0]))
+ # This is needed because the test binary has @executable_path embedded in
+ # it that the OS tries to resolve to the cache directory and not the
+ # mapped directory.
+ extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir)
+
+ if lsan:
+ if asan or msan:
+ lsan_options = []
+ else:
+ lsan_options = symbolization_options[:]
+ if sys.platform == 'linux2':
+ # Use the debug version of libstdc++ under LSan. If we don't, there will
+ # be a lot of incomplete stack traces in the reports.
+ extra_env['LD_LIBRARY_PATH'] = '/usr/lib/x86_64-linux-gnu/debug:'
+
+ suppressions_file = os.path.join(ROOT_DIR, 'tools', 'lsan',
+ 'suppressions.txt')
+ lsan_options += ['suppressions=%s' % suppressions_file,
+ 'print_suppressions=1']
+ extra_env['LSAN_OPTIONS'] = ' '.join(lsan_options)
+
+ if msan:
+ msan_options = symbolization_options[:]
+ if lsan:
+ msan_options.append('detect_leaks=1')
+ extra_env['MSAN_OPTIONS'] = ' '.join(msan_options)
+
+ if tsan:
+ tsan_options = symbolization_options[:]
+ extra_env['TSAN_OPTIONS'] = ' '.join(tsan_options)
return extra_env
-def get_sanitizer_symbolize_command(json_path=None):
+def get_sanitizer_symbolize_command(json_path=None, executable_path=None):
"""Construct the command to invoke offline symbolization script."""
script_path = '../tools/valgrind/asan/asan_symbolize.py'
cmd = [sys.executable, script_path]
if json_path is not None:
cmd.append('--test-summary-json-file=%s' % json_path)
+ if executable_path is not None:
+ cmd.append('--executable-path=%s' % executable_path)
return cmd
@@ -130,7 +151,8 @@
return
try:
- symbolize_command = get_sanitizer_symbolize_command(json_path=json_path)
+ symbolize_command = get_sanitizer_symbolize_command(
+ json_path=json_path, executable_path=cmd[0])
p = subprocess.Popen(symbolize_command, stderr=subprocess.PIPE, env=env)
(_, stderr) = p.communicate()
except OSError as e:
@@ -159,14 +181,15 @@
# Copy logic from tools/build/scripts/slave/runtest.py.
asan = '--asan=1' in cmd
lsan = '--lsan=1' in cmd
- use_symbolization_script = asan and not lsan
+ msan = '--msan=1' in cmd
+ tsan = '--tsan=1' in cmd
+ use_symbolization_script = (asan or msan) and not lsan
- if asan:
- extra_env.update(get_asan_env(cmd, lsan))
- # ASan is not yet sandbox-friendly on Windows (http://crbug.com/382867).
- if sys.platform == 'win32':
- cmd.append('--no-sandbox')
- if lsan:
+ if asan or lsan or msan or tsan:
+ extra_env.update(get_sanitizer_env(cmd, asan, lsan, msan, tsan))
+
+ if lsan or tsan:
+ # LSan and TSan are not sandbox-friendly.
cmd.append('--no-sandbox')
cmd = trim_cmd(cmd)
@@ -187,8 +210,9 @@
# Need to pipe to the symbolizer script.
p1 = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE,
stderr=sys.stdout)
- p2 = subprocess.Popen(get_sanitizer_symbolize_command(),
- env=env, stdin=p1.stdout)
+ p2 = subprocess.Popen(
+ get_sanitizer_symbolize_command(executable_path=cmd[0]),
+ env=env, stdin=p1.stdout)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
p1.wait()
p2.wait()
diff --git a/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1 b/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
index e15eeb1..94c02d2 100644
--- a/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
+++ b/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
@@ -1 +1 @@
-fd80d8d02666517d0781d3039499b4131e5d3e4e
\ No newline at end of file
+e73c227c9cfacfc5fecaa22ee3555b90925f96c2
\ No newline at end of file
diff --git a/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1 b/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
index e2d07aa..b415234 100644
--- a/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
+++ b/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
@@ -1 +1 @@
-905e9e6eb9b0e11f0587177cfbaf9f7822736f34
\ No newline at end of file
+05497e34b29c01dd82df76d2fbdf017d4a2c4214
\ No newline at end of file
diff --git a/third_party/binutils/README.chromium b/third_party/binutils/README.chromium
index 5daa8d7..d20934b 100644
--- a/third_party/binutils/README.chromium
+++ b/third_party/binutils/README.chromium
@@ -19,5 +19,11 @@
* ehframe-race.patch for http://crbug.com/161942 from upstream change
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=635aa30e3ae9735e362cfd1cda2be9f7b65b32a2
+ * unlock-thin.patch for http://crbug.com/453195 from upstream change
+ https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=2cfbf2fece582c29df348104b28677c38a8301f4
+
+ * plugin-dso-fix.patch for http://crbug.com/453195 from upstream change
+ https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=3c537f7fdb11f02f7082749f3f21dfdd2c2025e8
+
* (build-all.sh|build-one.sh|upload.sh) scripts for building the binutils
binaries and uploading them to Google storage.
diff --git a/third_party/binutils/build-all.sh b/third_party/binutils/build-all.sh
index fc00db1..a39984c 100755
--- a/third_party/binutils/build-all.sh
+++ b/third_party/binutils/build-all.sh
@@ -44,6 +44,8 @@
(
cd binutils-$VERSION
patch -p1 < ../ehframe-race.patch
+ patch -p1 < ../unlock-thin.patch
+ patch -p1 < ../plugin-dso-fix.patch
)
fi
@@ -106,6 +108,10 @@
# Copy them out of the chroot
cp -a "$BUILDDIR/output/$ARCHNAME" "$OUTPUTDIR"
+ # Copy plugin header out of the chroot
+ mkdir "$OUTPUTDIR/$ARCHNAME/include"
+ cp "$BUILDDIR/binutils-$VERSION/include/plugin-api.h" "$OUTPUTDIR/$ARCHNAME/include/"
+
# Clean up chroot
sudo rm -rf "$BUILDDIR"
done
diff --git a/third_party/binutils/plugin-dso-fix.patch b/third_party/binutils/plugin-dso-fix.patch
new file mode 100644
index 0000000..5589756
--- /dev/null
+++ b/third_party/binutils/plugin-dso-fix.patch
@@ -0,0 +1,97 @@
+commit 3c537f7fdb11f02f7082749f3f21dfdd2c2025e8
+Author: Peter Collingbourne <pcc@google.com>
+Date: Wed Feb 4 09:47:28 2015 -0800
+
+ Resolve forwarding symbols in plugins.
+
+ 2015-02-04 Peter Collingbourne <pcc@google.com>
+
+ * plugin.cc (Pluginobj::get_symbol_resolution_info): Resolve
+ forwarding symbols when computing symbol resolution info for plugins.
+
+diff --git a/gold/plugin.cc b/gold/plugin.cc
+index bde8c78..68da8e3 100644
+--- a/gold/plugin.cc
++++ b/gold/plugin.cc
+@@ -914,7 +914,8 @@ is_visible_from_outside(Symbol* lsym)
+ // Get symbol resolution info.
+
+ ld_plugin_status
+-Pluginobj::get_symbol_resolution_info(int nsyms,
++Pluginobj::get_symbol_resolution_info(Symbol_table* symtab,
++ int nsyms,
+ ld_plugin_symbol* syms,
+ int version) const
+ {
+@@ -943,6 +944,8 @@ Pluginobj::get_symbol_resolution_info(int nsyms,
+ {
+ ld_plugin_symbol* isym = &syms[i];
+ Symbol* lsym = this->symbols_[i];
++ if (lsym->is_forwarder())
++ lsym = symtab->resolve_forwards(lsym);
+ ld_plugin_symbol_resolution res = LDPR_UNKNOWN;
+
+ if (lsym->is_undefined())
+@@ -1511,14 +1514,16 @@ static enum ld_plugin_status
+ get_symbols(const void* handle, int nsyms, ld_plugin_symbol* syms)
+ {
+ gold_assert(parameters->options().has_plugins());
+- Object* obj = parameters->options().plugins()->object(
++ Plugin_manager* plugins = parameters->options().plugins();
++ Object* obj = plugins->object(
+ static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
+ if (obj == NULL)
+ return LDPS_ERR;
+ Pluginobj* plugin_obj = obj->pluginobj();
+ if (plugin_obj == NULL)
+ return LDPS_ERR;
+- return plugin_obj->get_symbol_resolution_info(nsyms, syms, 1);
++ Symbol_table* symtab = plugins->symtab();
++ return plugin_obj->get_symbol_resolution_info(symtab, nsyms, syms, 1);
+ }
+
+ // Version 2 of the above. The only difference is that this version
+@@ -1528,14 +1533,16 @@ static enum ld_plugin_status
+ get_symbols_v2(const void* handle, int nsyms, ld_plugin_symbol* syms)
+ {
+ gold_assert(parameters->options().has_plugins());
+- Object* obj = parameters->options().plugins()->object(
++ Plugin_manager* plugins = parameters->options().plugins();
++ Object* obj = plugins->object(
+ static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)));
+ if (obj == NULL)
+ return LDPS_ERR;
+ Pluginobj* plugin_obj = obj->pluginobj();
+ if (plugin_obj == NULL)
+ return LDPS_ERR;
+- return plugin_obj->get_symbol_resolution_info(nsyms, syms, 2);
++ Symbol_table* symtab = plugins->symtab();
++ return plugin_obj->get_symbol_resolution_info(symtab, nsyms, syms, 2);
+ }
+
+ // Add a new (real) input file generated by a plugin.
+diff --git a/gold/plugin.h b/gold/plugin.h
+index ef78b84..f926879 100644
+--- a/gold/plugin.h
++++ b/gold/plugin.h
+@@ -282,6 +282,10 @@ class Plugin_manager
+ input_objects() const
+ { return this->input_objects_; }
+
++ Symbol_table*
++ symtab()
++ { return this->symtab_; }
++
+ Layout*
+ layout()
+ { return this->layout_; }
+@@ -396,7 +400,8 @@ class Pluginobj : public Object
+
+ // Fill in the symbol resolution status for the given plugin symbols.
+ ld_plugin_status
+- get_symbol_resolution_info(int nsyms,
++ get_symbol_resolution_info(Symbol_table* symtab,
++ int nsyms,
+ ld_plugin_symbol* syms,
+ int version) const;
+
diff --git a/third_party/binutils/unlock-thin.patch b/third_party/binutils/unlock-thin.patch
new file mode 100644
index 0000000..6a4b6a7
--- /dev/null
+++ b/third_party/binutils/unlock-thin.patch
@@ -0,0 +1,129 @@
+commit 2cfbf2fece582c29df348104b28677c38a8301f4
+Author: Cary Coutant <ccoutant@google.com>
+Date: Tue Feb 3 19:54:57 2015 -0800
+
+ Fix a file descriptor leak in gold.
+
+ When an LTO linker plugin claims an external member of a thin archive, gold
+ does not properly unlock the file and make its file descriptor available for
+ reuse. This patch fixes the problem by modifying Archive::include_member to
+ unlock the object file via an RAII class instance, ensuring that it will be
+ unlocked no matter what path is taken through the function.
+
+ gold/
+ PR gold/15660
+ * archive.cc (Thin_archive_object_unlocker): New class.
+ (Archive::include_member): Unlock external members of thin archives.
+ * testsuite/Makefile.am (plugin_test_1): Rename .syms files.
+ (plugin_test_2): Likewise.
+ (plugin_test_3): Likewise.
+ (plugin_test_4): Likewise.
+ (plugin_test_5): Likewise.
+ (plugin_test_6): Likewise.
+ (plugin_test_7): Likewise.
+ (plugin_test_8): Likewise.
+ (plugin_test_9): Likewise.
+ (plugin_test_10): Likewise.
+ (plugin_test_11): New test case.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/plugin_test.c (claim_file_hook): Check for parallel .syms
+ file to decide whether to claim file.
+ (all_symbols_read_hook): Likewise.
+ * testsuite/plugin_test_1.sh: Adjust expected output.
+ * testsuite/plugin_test_2.sh: Likewise.
+ * testsuite/plugin_test_3.sh: Likewise.
+ * testsuite/plugin_test_6.sh: Likewise.
+ * testsuite/plugin_test_tls.sh: Likewise.
+ * testsuite/plugin_test_11.sh: New testcase.
+
+diff --git a/gold/archive.cc b/gold/archive.cc
+index 69107f5..6d25980 100644
+--- a/gold/archive.cc
++++ b/gold/archive.cc
+@@ -930,6 +930,32 @@ Archive::count_members()
+ return ret;
+ }
+
++// RAII class to ensure we unlock the object if it's a member of a
++// thin archive. We can't use Task_lock_obj in Archive::include_member
++// because the object file is already locked when it's opened by
++// get_elf_object_for_member.
++
++class Thin_archive_object_unlocker
++{
++ public:
++ Thin_archive_object_unlocker(const Task *task, Object* obj)
++ : task_(task), obj_(obj)
++ { }
++
++ ~Thin_archive_object_unlocker()
++ {
++ if (this->obj_->offset() == 0)
++ this->obj_->unlock(this->task_);
++ }
++
++ private:
++ Thin_archive_object_unlocker(const Thin_archive_object_unlocker&);
++ Thin_archive_object_unlocker& operator=(const Thin_archive_object_unlocker&);
++
++ const Task* task_;
++ Object* obj_;
++};
++
+ // Include an archive member in the link. OFF is the file offset of
+ // the member header. WHY is the reason we are including this member.
+ // Return true if we added the member or if we had an error, return
+@@ -978,6 +1004,10 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
+ return unconfigured ? false : true;
+ }
+
++ // If the object is an external member of a thin archive,
++ // unlock it when we're done here.
++ Thin_archive_object_unlocker unlocker(this->task_, obj);
++
+ if (mapfile != NULL)
+ mapfile->report_include_archive_member(obj->name(), sym, why);
+
+@@ -991,31 +1021,21 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
+
+ if (!input_objects->add_object(obj))
+ {
+- // If this is an external member of a thin archive, unlock the
+- // file.
+- if (obj->offset() == 0)
+- obj->unlock(this->task_);
+ delete obj;
++ return true;
+ }
+- else
+- {
+- {
+- if (layout->incremental_inputs() != NULL)
+- layout->incremental_inputs()->report_object(obj, 0, this, NULL);
+- Read_symbols_data sd;
+- obj->read_symbols(&sd);
+- obj->layout(symtab, layout, &sd);
+- obj->add_symbols(symtab, &sd, layout);
+- }
+-
+- // If this is an external member of a thin archive, unlock the file
+- // for the next task.
+- if (obj->offset() == 0)
+- obj->unlock(this->task_);
+
+- this->included_member_ = true;
+- }
++ if (layout->incremental_inputs() != NULL)
++ layout->incremental_inputs()->report_object(obj, 0, this, NULL);
++
++ {
++ Read_symbols_data sd;
++ obj->read_symbols(&sd);
++ obj->layout(symtab, layout, &sd);
++ obj->add_symbols(symtab, &sd, layout);
++ }
+
++ this->included_member_ = true;
+ return true;
+ }
+
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi
index 2691ef8..0750678 100644
--- a/third_party/boringssl/boringssl.gypi
+++ b/third_party/boringssl/boringssl.gypi
@@ -331,6 +331,7 @@
'linux-arm/crypto/sha/sha256-armv4.S',
'linux-arm/crypto/sha/sha512-armv4.S',
'src/crypto/chacha/chacha_vec_arm.S',
+ 'src/crypto/cpu-arm-asm.S',
'src/crypto/poly1305/poly1305_arm_asm.S',
],
'boringssl_linux_x86_sources': [
diff --git a/third_party/boringssl/update_gypi_and_asm.py b/third_party/boringssl/update_gypi_and_asm.py
index 476e42f..db11e64 100644
--- a/third_party/boringssl/update_gypi_and_asm.py
+++ b/third_party/boringssl/update_gypi_and_asm.py
@@ -29,6 +29,7 @@
('linux', 'arm'): [
'src/crypto/poly1305/poly1305_arm_asm.S',
'src/crypto/chacha/chacha_vec_arm.S',
+ 'src/crypto/cpu-arm-asm.S',
],
}
diff --git a/third_party/libevent/README.chromium b/third_party/libevent/README.chromium
index be4fee3..a3e5c6e 100644
--- a/third_party/libevent/README.chromium
+++ b/third_party/libevent/README.chromium
@@ -23,3 +23,4 @@
nacl_nonsfi/event-config.h are derived from linux/ counterparts.
nacl_nonsfi/random.c is also added to provide the random() function,
which is missing in the newlib-based PNaCl toolchain.
+8) Apply https://github.com/libevent/libevent/commit/ea6b1df
diff --git a/third_party/libevent/evdns.c b/third_party/libevent/evdns.c
index da6ea19..6fa971c 100644
--- a/third_party/libevent/evdns.c
+++ b/third_party/libevent/evdns.c
@@ -55,7 +55,9 @@
#endif
/* #define _POSIX_C_SOURCE 200507 */
+#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
+#endif
#ifdef DNS_USE_CPU_CLOCK_FOR_ID
#ifdef DNS_USE_OPENSSL_FOR_ID
diff --git a/third_party/libxml/libxml.gyp b/third_party/libxml/libxml.gyp
index dcc75b9..1decbe9 100644
--- a/third_party/libxml/libxml.gyp
+++ b/third_party/libxml/libxml.gyp
@@ -237,6 +237,7 @@
'libraries': [
# We need dl for dlopen() and friends.
'-ldl',
+ '-lm',
],
},
}],
diff --git a/third_party/mesa/mesa.gyp b/third_party/mesa/mesa.gyp
index bf2afcd..220bc17 100644
--- a/third_party/mesa/mesa.gyp
+++ b/third_party/mesa/mesa.gyp
@@ -46,13 +46,7 @@
"_GLAPI_NO_EXPORTS",
],
'conditions': [
- ['OS=="android"', {
- 'defines': [
- '__GLIBC__',
- '_GNU_SOURCE',
- ],
- }],
- ['OS=="linux"', {
+ ['OS == "linux" or OS == "android"', {
'defines': [
'_GNU_SOURCE',
],
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn
index 973672b..1367d8a 100644
--- a/third_party/protobuf/BUILD.gn
+++ b/third_party/protobuf/BUILD.gn
@@ -30,10 +30,13 @@
}
}
-# This condif should be applied to targets using generated code from the proto
+# This config should be applied to targets using generated code from the proto
# compiler. It sets up the include directories properly.
config("using_proto") {
- include_dirs = [ "$root_gen_dir/protoc_out" ]
+ include_dirs = [
+ "src",
+ "$root_gen_dir/protoc_out",
+ ]
}
protobuf_lite_sources = [
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium
index 8e51806..c6bb5c2 100644
--- a/third_party/protobuf/README.chromium
+++ b/third_party/protobuf/README.chromium
@@ -38,3 +38,5 @@
GetEmptyString() and GoogleOnceInit() have been uninlined, for a large savings
in binary size.
+
+A BUILD.gn file has been added for building with GN.
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium
index fdf3394..8fb3768 100644
--- a/third_party/qcms/README.chromium
+++ b/third_party/qcms/README.chromium
@@ -51,5 +51,7 @@
- https://code.google.com/p/chromium/issues/detail?id=401971
- Minor variable name change: description -> description_offset
- https://code.google.com/p/chromium/issues/detail?id=401971
+ - Avoid divisions creating sample points in the float cube LUT builder
+ - https://code.google.com/p/chromium/issues/detail?id=443863
To regenerate google.patch:
git diff b8456f38 src > google.patch
diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c
index 08db142..9fd8238 100644
--- a/third_party/qcms/src/transform.c
+++ b/third_party/qcms/src/transform.c
@@ -1118,28 +1118,31 @@
float* src = NULL;
float* dest = NULL;
float* lut = NULL;
+ float inverse;
src = malloc(lutSize*sizeof(float));
dest = malloc(lutSize*sizeof(float));
if (src && dest) {
- /* Prepare a list of points we want to sample */
+ /* Prepare a list of points we want to sample: x, y, z order */
l = 0;
+ inverse = 1 / (float)(samples-1);
for (x = 0; x < samples; x++) {
for (y = 0; y < samples; y++) {
for (z = 0; z < samples; z++) {
- src[l++] = x / (float)(samples-1);
- src[l++] = y / (float)(samples-1);
- src[l++] = z / (float)(samples-1);
+ src[l++] = x * inverse; // r
+ src[l++] = y * inverse; // g
+ src[l++] = z * inverse; // b
}
}
}
lut = qcms_chain_transform(in, out, src, dest, lutSize);
+
if (lut) {
- transform->r_clut = &lut[0];
- transform->g_clut = &lut[1];
- transform->b_clut = &lut[2];
+ transform->r_clut = &lut[0]; // r
+ transform->g_clut = &lut[1]; // g
+ transform->b_clut = &lut[2]; // b
transform->grid_size = samples;
if (in_type == QCMS_DATA_RGBA_8) {
transform->transform_fn = qcms_transform_data_tetra_clut_rgba;
@@ -1149,8 +1152,8 @@
}
}
-
- //XXX: qcms_modular_transform_data may return either the src or dest buffer. If so it must not be free-ed
+ // XXX: qcms_modular_transform_data may return the lut in either the src or the
+ // dest buffer. If so, it must not be free-ed.
if (src && lut != src) {
free(src);
}
diff --git a/third_party/re2/patches/re2-libcxx.patch b/third_party/re2/patches/re2-libcxx.patch
index fc4dd1c..3ef6eb5 100644
--- a/third_party/re2/patches/re2-libcxx.patch
+++ b/third_party/re2/patches/re2-libcxx.patch
@@ -12,3 +12,12 @@
#include <tr1/unordered_set>
using std::tr1::unordered_set;
+@@ -54,7 +55,7 @@ using std::tr1::unordered_set;
+ #else
+
+ #include <unordered_set>
+-#if defined(WIN32) || defined(OS_ANDROID)
++#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION))
+ using std::tr1::unordered_set;
+ #else
+ using std::unordered_set;
diff --git a/third_party/re2/util/util.h b/third_party/re2/util/util.h
index 8350445..4f0fdb8 100644
--- a/third_party/re2/util/util.h
+++ b/third_party/re2/util/util.h
@@ -55,7 +55,7 @@
#else
#include <unordered_set>
-#if defined(WIN32) || defined(OS_ANDROID)
+#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION))
using std::tr1::unordered_set;
#else
using std::unordered_set;
diff --git a/tools/android/forwarder2/device_forwarder_main.cc b/tools/android/forwarder2/device_forwarder_main.cc
index c215efa..8b5df26 100644
--- a/tools/android/forwarder2/device_forwarder_main.cc
+++ b/tools/android/forwarder2/device_forwarder_main.cc
@@ -48,7 +48,7 @@
public:
ServerDelegate() : initialized_(false) {}
- virtual ~ServerDelegate() {
+ ~ServerDelegate() override {
if (!controller_thread_.get())
return;
// The DeviceController instance, if any, is constructed on the controller
@@ -68,7 +68,7 @@
}
// Daemon::ServerDelegate:
- virtual void Init() override {
+ void Init() override {
DCHECK(!g_notifier);
g_notifier = new forwarder2::PipeNotifier();
signal(SIGTERM, KillHandler);
@@ -77,7 +77,7 @@
controller_thread_->Start();
}
- virtual void OnClientConnected(scoped_ptr<Socket> client_socket) override {
+ void OnClientConnected(scoped_ptr<Socket> client_socket) override {
if (initialized_) {
client_socket->WriteString("OK");
return;
@@ -119,7 +119,7 @@
bool has_failed() const { return has_failed_; }
// Daemon::ClientDelegate:
- virtual void OnDaemonReady(Socket* daemon_socket) override {
+ void OnDaemonReady(Socket* daemon_socket) override {
char buf[kBufSize];
const int bytes_read = daemon_socket->Read(
buf, sizeof(buf) - 1 /* leave space for null terminator */);
diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc
index a94a97b..f5d8e2f 100644
--- a/tools/android/forwarder2/host_forwarder_main.cc
+++ b/tools/android/forwarder2/host_forwarder_main.cc
@@ -314,7 +314,7 @@
}
// Daemon::ServerDelegate:
- virtual void Init() override {
+ void Init() override {
LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
DCHECK(!g_notifier);
g_notifier = new PipeNotifier();
@@ -322,7 +322,7 @@
signal(SIGINT, KillHandler);
}
- virtual void OnClientConnected(scoped_ptr<Socket> client_socket) override {
+ void OnClientConnected(scoped_ptr<Socket> client_socket) override {
char buf[kBufSize];
const int bytes_read = client_socket->Read(buf, sizeof(buf));
if (bytes_read <= 0) {
@@ -366,7 +366,7 @@
bool has_failed() const { return has_failed_; }
// Daemon::ClientDelegate:
- virtual void OnDaemonReady(Socket* daemon_socket) override {
+ void OnDaemonReady(Socket* daemon_socket) override {
// Send the forward command to the daemon.
CHECK_EQ(static_cast<long>(command_pickle_.size()),
daemon_socket->WriteNumBytes(command_pickle_.data(),
diff --git a/tools/android/heap_profiler/heap_profiler_unittest.cc b/tools/android/heap_profiler/heap_profiler_unittest.cc
index d69af5f..1771a88 100644
--- a/tools/android/heap_profiler/heap_profiler_unittest.cc
+++ b/tools/android/heap_profiler/heap_profiler_unittest.cc
@@ -14,9 +14,9 @@
class HeapProfilerTest : public testing::Test {
public:
- virtual void SetUp() override { heap_profiler_init(&stats_); }
+ void SetUp() override { heap_profiler_init(&stats_); }
- virtual void TearDown() override {
+ void TearDown() override {
CheckAllocVsStacktaceConsistency();
heap_profiler_cleanup();
}
diff --git a/tools/android/run_pie/run_pie.gyp b/tools/android/run_pie/run_pie.gyp
index b713dc4..75850f4 100644
--- a/tools/android/run_pie/run_pie.gyp
+++ b/tools/android/run_pie/run_pie.gyp
@@ -18,10 +18,10 @@
'ldflags!': [
'-pie',
],
- # Don't inherit unneeded dependencies on stlport.so, so the binary remains
+ # Don't inherit unneeded dependencies on libc++, so the binary remains
# self-contained also in component=shared_library builds.
'libraries!': [
- '-l<(android_stlport_library)',
+ '-l<(android_libcpp_library)',
],
},
{
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index 7b964cc..a2b7b19 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -904,7 +904,7 @@
--platform=android-14 \
--install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
--system=linux-x86_64 \
- --stl=stlport \
+ --stl=libcxx \
--toolchain=arm-linux-androideabi-4.9
# Android NDK r9d copies a broken unwind.h into the toolchain, see
diff --git a/tools/git/move_source_file.py b/tools/git/move_source_file.py
index 117b3eb..b5496fd 100755
--- a/tools/git/move_source_file.py
+++ b/tools/git/move_source_file.py
@@ -119,6 +119,48 @@
r'\1%s\2' % PathMinusFirstComponent(to_path),
['*.gyp*'])
+ # Update references in BUILD.gn files.
+ #
+ # Unlike .gyp(i) files, BUILD.gn files can be placed in any directories,
+ # and paths in a BUILD.gn file are relative to the directory where the
+ # BUILD.gn file is placed.
+ #
+ # For instance, "chrome/browser/chromeos/device_uma.h" is listed as
+ # "browser/chromeos/device_uma.h" in "chrome/chrome_browser_chromeos.gypi",
+ # but it's listed as "device_uma.h" in "chrome/browser/chromeos/BUILD.gn".
+ #
+ # To handle this, the code here will visit directories from the top level
+ # src directory to the directory of |from_path| and try to update BUILD.gn
+ # in each directory.
+ #
+ # The code only handles files moved/renamed within the same BUILD.gn
+ # file. If files are moved beyond the same BUILD.gn file, the affected
+ # BUILD.gn files should be fixed manually.
+ def SplitByFirstComponent(path):
+ """'foo/bar/baz' -> ('foo', 'bar/baz')
+ 'bar' -> ('bar', '')
+ '' -> ('', '')
+ """
+ parts = re.split(r"[/\\]", path, 1)
+ if len(parts) == 2:
+ return (parts[0], parts[1])
+ else:
+ return (parts[0], '')
+
+ visiting_directory = ''
+ from_rest = from_path
+ to_rest = to_path
+ while True:
+ mffr.MultiFileFindReplace(
+ r'([\'"])%s([\'"])' % from_rest,
+ r'\1%s\2' % to_rest,
+ [os.path.join(visiting_directory, 'BUILD.gn')])
+ from_first, from_rest = SplitByFirstComponent(from_rest)
+ to_first, to_rest = SplitByFirstComponent(to_rest)
+ visiting_directory = os.path.join(visiting_directory, from_first)
+ if not from_rest or not to_rest:
+ break
+
def MakeIncludeGuardName(path_from_root):
"""Returns an include guard name given a path from root."""
diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py
index cd61dae..9280d7a 100755
--- a/tools/valgrind/asan/asan_symbolize.py
+++ b/tools/valgrind/asan/asan_symbolize.py
@@ -10,6 +10,8 @@
import base64
import json
import os
+import re
+import subprocess
import sys
class LineBuffered(object):
@@ -48,6 +50,73 @@
os.environ['LLVM_SYMBOLIZER_PATH'] = os.path.abspath(symbolizer_path)
+def is_hash_name(name):
+ match = re.match('[0-9a-f]+$', name)
+ return bool(match)
+
+
+def split_path(path):
+ ret = []
+ while True:
+ head, tail = os.path.split(path)
+ if head == path:
+ return [head] + ret
+ ret, path = [tail] + ret, head
+
+
+def chrome_product_dir_path(exe_path):
+ if exe_path is None:
+ return None
+ path_parts = split_path(exe_path)
+ # Make sure the product dir path isn't empty if |exe_path| consists of
+ # a single component.
+ if len(path_parts) == 1:
+ path_parts = ['.'] + path_parts
+ for index, part in enumerate(path_parts):
+ if part.endswith('.app'):
+ return os.path.join(*path_parts[:index])
+ # If the executable isn't an .app bundle, it's a commandline binary that
+ # resides right in the product dir.
+ return os.path.join(*path_parts[:-1])
+
+
+inode_path_cache = {}
+
+
+def find_inode_at_path(inode, path):
+ if inode in inode_path_cache:
+ return inode_path_cache[inode]
+ cmd = ['find', path, '-inum', str(inode)]
+ find_line = subprocess.check_output(cmd).rstrip()
+ lines = find_line.split('\n')
+ ret = None
+ if lines:
+ # `find` may give us several paths (e.g. 'Chromium Framework' in the
+ # product dir and 'Chromium Framework' inside 'Chromium.app',
+ # chrome_dsym_hints() will produce correct .dSYM path for any of them.
+ ret = lines[0]
+ inode_path_cache[inode] = ret
+ return ret
+
+
+# Create a binary name filter that works around https://crbug.com/444835.
+# When running tests on OSX swarming servers, ASan sometimes prints paths to
+# files in cache (ending with SHA1 filenames) instead of paths to hardlinks to
+# those files in the product dir.
+# For a given |binary_path| chrome_osx_binary_name_filter() returns one of the
+# hardlinks to the same inode in |product_dir_path|.
+def make_chrome_osx_binary_name_filter(product_dir_path=''):
+ def chrome_osx_binary_name_filter(binary_path):
+ basename = os.path.basename(binary_path)
+ if is_hash_name(basename) and product_dir_path:
+ inode = os.stat(binary_path).st_ino
+ new_binary_path = find_inode_at_path(inode, product_dir_path)
+ if new_binary_path:
+ return new_binary_path
+ return binary_path
+ return chrome_osx_binary_name_filter
+
+
# Construct a path to the .dSYM bundle for the given binary.
# There are three possible cases for binary location in Chromium:
# 1. The binary is a standalone executable or dynamic library in the product
@@ -63,7 +132,7 @@
# path. Only one of these bundles may be a framework and frameworks cannot
# contain other bundles.
def chrome_dsym_hints(binary):
- path_parts = binary.split(os.path.sep)
+ path_parts = split_path(binary)
app_positions = []
framework_positions = []
for index, part in enumerate(path_parts):
@@ -89,7 +158,7 @@
# In case 2 this is the same as |outermost_bundle|.
innermost_bundle = bundle_positions[-1]
dsym_path = product_dir + [path_parts[innermost_bundle]]
- result = '%s.dSYM' % os.path.sep.join(dsym_path)
+ result = '%s.dSYM' % os.path.join(*dsym_path)
return [result]
@@ -169,13 +238,22 @@
parser.add_argument('strip_path_prefix', nargs='*',
help='When printing source file names, the longest prefix ending in one '
'of these substrings will be stripped. E.g.: "Release/../../".')
+ parser.add_argument('--executable-path',
+ help='Path to program executable. Used on OSX swarming bots to locate '
+ 'dSYM bundles for associated frameworks and bundles.')
args = parser.parse_args()
disable_buffering()
set_symbolizer_path()
asan_symbolize.demangle = True
asan_symbolize.fix_filename_patterns = args.strip_path_prefix
- loop = asan_symbolize.SymbolizationLoop(dsym_hint_producer=chrome_dsym_hints)
+ binary_name_filter = None
+ if os.uname()[0] == 'Darwin':
+ binary_name_filter = make_chrome_osx_binary_name_filter(
+ chrome_product_dir_path(args.executable_path))
+ loop = asan_symbolize.SymbolizationLoop(
+ binary_name_filter=binary_name_filter,
+ dsym_hint_producer=chrome_dsym_hints)
if args.test_summary_json_file:
symbolize_snippets_in_json(args.test_summary_json_file, loop)
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index 51ebeda..554beb3 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -567,7 +567,8 @@
"--no-retry-failures", # retrying takes too much time
# http://crbug.com/176908: Don't launch a browser when done.
"--no-show-results",
- "--nocheck-sys-deps"]
+ "--nocheck-sys-deps",
+ "--additional-drt-flag=--no-sandbox"]
# Pass build mode to run-webkit-tests. We aren't passed it directly,
# so parse it out of build_dir. run-webkit-tests can only handle
# the two values "Release" and "Debug".
diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt
index 876d6f7..1a9b9ee 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -461,11 +461,12 @@
name=http://crbug.com/371348
system call NtCreateSection
KERNELBASE.dll!CreateFileMappingW
-base.dll!base::SharedMemory::Create
-base.dll!base::SharedMemory::CreateAnonymous
-content.dll!content::ChildThread::AllocateSharedMemory
-content.dll!content::ChildSharedBitmapManager::AllocateSharedBitmap
-cc.dll!cc::ResourceProvider::CreateBitmap
+*!base::SharedMemory::Create
+*!base::SharedMemory::CreateAnonymous
+*!content::ChildThreadImpl::AllocateSharedMemory
+...
+*!content::ChildSharedBitmapManager::AllocateSharedBitmap
+*!cc::ResourceProvider::CreateBitmap
HANDLE LEAK
name=http://crbug.com/371357
@@ -711,3 +712,62 @@
KERNELBASE.dll!OpenProcess
base.dll!base::Process::OpenWithExtraPriviles
content.dll!content::BrowserMessageFilter::Internal::OnChannelConnected
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/455060
+*!content::FrameAccessibility::GetParent
+*!content::RenderFrameHostImpl::AccessibilityGetParentFrame
+*!content::BrowserAccessibilityManager::GetDelegateFromRootManager
+*!content::BrowserAccessibilityManager::OnWindowBlurred
+...
+*!content::RenderWidgetHostViewAura::Destroy
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/455066
+system call NtReadFile parameter #4
+KERNELBASE.dll!ReadFile
+KERNEL32.dll!ReadFile
+*!net::FileStream::Context::ReadAsync
+*!base::internal::RunnableAdapter<>::Run
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/455994
+drmemorylib.dll!replace_operator_delete
+*!IPC::Listener::`vector deleting destructor'
+*!content::RenderFrameImpl::~RenderFrameImpl
+*!content::RenderFrameImpl::`vector deleting destructor'
+*!content::RenderViewImpl::~RenderViewImpl
+*!content::RenderViewImpl::`vector deleting destructor'
+*!scoped_refptr<>::Release
+*!base::internal::BindState<>::`scalar deleting destructor'
+*!scoped_refptr<>::Release
+*!base::internal::CallbackBase::~CallbackBase
+*!base::MessagePumpDefault::Run
+*!base::MessageLoop::RunHandler
+*!base::MessageLoop::Run
+*!content::RendererMain
+*!content::RunNamedProcessTypeMain
+*!content::ContentMainRunnerImpl::Run
+*!content::ContentMain
+*!content::LaunchTests
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/456131
+...
+*!content::NavigateToURL
+*!content::BrowserSideNavigationBrowserTest_BrowserInitiatedNavigations_Test::RunTestOnMainThread
+*!content::ContentBrowserTest::RunTestOnMainThreadLoop
+*!content::BrowserTestBase::ProxyRunTestOnMainThreadLoop
+*!content::ShellBrowserMainParts::PreMainMessageLoopRun
+*!content::BrowserMainLoop::PreMainMessageLoopRun
+*!base::internal::Invoker<>::Run
+*!content::StartupTaskRunner::RunAllTasksNow
+*!content::BrowserMainLoop::CreateStartupTasks
+*!content::BrowserMainRunnerImpl::Initialize
+*!ShellBrowserMain
+*!content::ShellMainDelegate::RunProcess
+*!content::RunNamedProcessTypeMain
+*!content::ContentMainRunnerImpl::Run
+*!content::ContentMain
+*!content::BrowserTestBase::SetUp
+*!content::ContentBrowserTest::SetUp
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index 2036d21..d823d49 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1890,10 +1890,11 @@
*!testing::internal::HandleExceptionsInMethodIfSupported<>
UNINITIALIZED READ
-name=bug_446256
-*!`anonymous namespace'::GraphicsContextTest_trackDisplayListRecording_Test::TestBody
-*!testing::internal::HandleExceptionsInMethodIfSupported<>
-
-UNINITIALIZED READ
name=bug_399842
skia.dll!S32A_Opaque_BlitRow32_SSE4
+
+UNINITIALIZED READ
+name=bug_455417
+*!std::char_traits<>::compare
+...
+*!*::*URLRequest*::TestBody
diff --git a/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 0000000..f1382da
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,2 @@
+# crbug.com/455536
+ChromeWatcherCommandLineTest.BasicTest
diff --git a/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt b/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
index 5a8f1bc..a43a673 100644
--- a/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
+++ b/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
@@ -32,6 +32,3 @@
# http://crbug.com/403533
ExtensionPathUtilTest.BasicPrettifyPathTest
-
-# http://crbug.com/452071
-SupervisedUserServiceExtensionTest.InstallContentPacks
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 579b481..10849ae 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -3401,10 +3401,10 @@
bug_431213
Memcheck:Leak
fun:_Znw*
- fun:_ZN3gin22CreateFunctionTemplateIFSsPN4mojo2js13HandleWrapperEEEEN2v85LocalINS6_16FunctionTemplateEEEPNS6_7IsolateEN4base8CallbackIT_EEi
- fun:_ZN3gin12_GLOBAL__N_114CallbackTraitsIMN4mojo2js13HandleWrapperEFSsvEvE14CreateTemplateEPN2v87IsolateES6_
- fun:_ZN3gin21ObjectTemplateBuilder9SetMethodIMN4mojo2js13HandleWrapperEFSsvEEERS0_RKN4base16BasicStringPieceISsEERKT_
- fun:_ZN4mojo2js13HandleWrapper24GetObjectTemplateBuilderEPN2v87IsolateE
+ fun:_ZN3gin22CreateFunctionTemplateIF*LocalINS6_16FunctionTemplateEEEPNS6_7IsolateEN4base8CallbackIT_EEi
+ fun:_ZN3gin12_GLOBAL__N_114CallbackTraitsIMN*CreateTemplateEPN2v87IsolateES6_
+ fun:_ZN3gin21ObjectTemplateBuilder9SetMethodIMN*0_RKN4base16BasicStringPieceISsEERKT_
+ fun:_ZN*24GetObjectTemplateBuilderEPN2v87IsolateE
}
{
bug_436110
@@ -3596,3 +3596,23 @@
fun:_ZN4base12SimpleThread10ThreadMainEv
fun:_ZN4base12_GLOBAL__N_110ThreadFuncEPv
}
+{
+ bug_455732
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4mojo7BindingINS_15ServiceProviderEE4BindENS_16ScopedHandleBaseINS_17MessagePipeHandleEEEPK15MojoAsyncWaiter
+ fun:_ZN4mojo7BindingINS_15ServiceProviderEE4BindENS_16InterfaceRequestIS1_EEPK15MojoAsyncWaiter
+ fun:_ZN7content19ServiceRegistryImpl4BindEN4mojo16InterfaceRequestINS1_15ServiceProviderEEE
+ fun:_ZN7content12_GLOBAL__N_120ApplicationSetupImpl24ExchangeServiceProvidersEN4mojo16InterfaceRequestINS2_15ServiceProviderEEENS2_12InterfacePtrIS4_EE
+ fun:_ZN7content20ApplicationSetupStub6AcceptEPN4mojo7MessageE
+ fun:_ZN4mojo8internal6Router21HandleIncomingMessageEPNS_7MessageE
+ fun:_ZN4mojo8internal6Router26HandleIncomingMessageThunk6AcceptEPNS_7MessageE
+ fun:_ZN7content32ApplicationSetupRequestValidator6AcceptEPN4mojo7MessageE
+ fun:_ZN4mojo8internal22MessageHeaderValidator6AcceptEPNS_7MessageE
+ fun:_ZN4mojo22ReadAndDispatchMessageENS_17MessagePipeHandleEPNS_15MessageReceiverEPb
+ fun:_ZN4mojo8internal9Connector17ReadSingleMessageEPi
+ fun:_ZN4mojo8internal9Connector24ReadAllAvailableMessagesEv
+ fun:_ZN4mojo8internal9Connector13OnHandleReadyEi
+ fun:_ZN4mojo8internal9Connector17CallOnHandleReadyEPvi
+ fun:_ZN4mojo8internal12_GLOBAL__N_113OnHandleReadyEPNS_6common13HandleWatcherEPFvPviES5_i
+}
diff --git a/ui/events/gesture_detection/gesture_provider.cc b/ui/events/gesture_detection/gesture_provider.cc
index 116b744..a7a43ee 100644
--- a/ui/events/gesture_detection/gesture_provider.cc
+++ b/ui/events/gesture_detection/gesture_provider.cc
@@ -7,7 +7,7 @@
#include <cmath>
#include "base/auto_reset.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
#include "ui/events/event_constants.h"
#include "ui/events/gesture_detection/gesture_event_data.h"
#include "ui/events/gesture_detection/gesture_listeners.h"
diff --git a/ui/events/gesture_detection/motion_event_buffer.cc b/ui/events/gesture_detection/motion_event_buffer.cc
index 89690d6..2b3d2c3 100644
--- a/ui/events/gesture_detection/motion_event_buffer.cc
+++ b/ui/events/gesture_detection/motion_event_buffer.cc
@@ -4,7 +4,7 @@
#include "ui/events/gesture_detection/motion_event_buffer.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/events/gesture_detection/motion_event_generic.h"
diff --git a/ui/events/latency_info.cc b/ui/events/latency_info.cc
index 248acb9..145b77a 100644
--- a/ui/events/latency_info.cc
+++ b/ui/events/latency_info.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/debug/trace_event.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/stringprintf.h"
+#include "base/trace_event/trace_event.h"
#include "ui/events/latency_info.h"
#include <algorithm>
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index 5943bb6..52daf1c 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -817,18 +817,6 @@
{ 'return_type': 'void',
'names': ['glReleaseShaderCompiler'],
'arguments': 'void', },
-# Multisampling API is different in different GL versions, some require an
-# explicit resolve step for renderbuffers and/or FBO texture attachments and
-# some do not. Multiple alternatives might be present in a single
-# implementation, which require different use of the API and may have
-# different performance (explicit resolve performing worse, for example).
-# So even though the function signature is the same across versions, we split
-# their definitions so that the function to use can be chosen correctly at a
-# higher level.
-# TODO(oetuaho@nvidia.com): Some of these might still be possible to combine.
-# This could also fix weirdness in the mock bindings that's caused by the same
-# function name appearing multiple times.
-# This is the ES3 function, which requires explicit resolve:
{ 'return_type': 'void',
'names': ['glRenderbufferStorageEXT', 'glRenderbufferStorage'],
'arguments':
@@ -838,18 +826,11 @@
'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
'GLsizei width, GLsizei height', },
{ 'return_type': 'void',
- 'names': ['glRenderbufferStorageMultisampleANGLE',
- 'glRenderbufferStorageMultisample'],
+ 'names': ['glRenderbufferStorageMultisampleANGLE'],
'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
'GLsizei width, GLsizei height', },
-# In desktop GL, EXT and core versions both have an explicit resolve step,
-# though desktop core GL implicitly resolves when drawing to a window.
-# TODO(oetuaho@nvidia.com): Right now this function also doubles as ES2 EXT
-# function, which has implicit resolve, and for which the fallback is wrong.
-# Fix this.
{ 'return_type': 'void',
- 'names': ['glRenderbufferStorageMultisampleEXT',
- 'glRenderbufferStorageMultisample'],
+ 'names': ['glRenderbufferStorageMultisampleEXT'],
'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
'GLsizei width, GLsizei height', },
{ 'return_type': 'void',
@@ -1379,7 +1360,7 @@
'arguments': 'EGLint engine', },
{ 'return_type': 'EGLint',
'versions': [{ 'name': 'eglWaitSyncKHR',
- 'extensions': ['EGL_KHR_fence_sync', 'EGL_KHR_wait_sync'] }],
+ 'extensions': ['EGL_KHR_wait_sync'] }],
'arguments': 'EGLDisplay dpy, EGLSyncKHR sync, EGLint flags' },
]
diff --git a/ui/gl/gl_bindings_autogen_egl.cc b/ui/gl/gl_bindings_autogen_egl.cc
index e0de7f2..003b545 100644
--- a/ui/gl/gl_bindings_autogen_egl.cc
+++ b/ui/gl/gl_bindings_autogen_egl.cc
@@ -209,7 +209,7 @@
}
debug_fn.eglWaitSyncKHRFn = 0;
- if (ext.b_EGL_KHR_fence_sync || ext.b_EGL_KHR_wait_sync) {
+ if (ext.b_EGL_KHR_wait_sync) {
fn.eglWaitSyncKHRFn = reinterpret_cast<eglWaitSyncKHRProc>(
GetGLProcAddress("eglWaitSyncKHR"));
DCHECK(fn.eglWaitSyncKHRFn);
diff --git a/ui/gl/gl_bindings_autogen_gl.cc b/ui/gl/gl_bindings_autogen_gl.cc
index 642190c..11383b1 100644
--- a/ui/gl/gl_bindings_autogen_gl.cc
+++ b/ui/gl/gl_bindings_autogen_gl.cc
@@ -1692,12 +1692,7 @@
}
debug_fn.glRenderbufferStorageMultisampleANGLEFn = 0;
- if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 0u)) {
- fn.glRenderbufferStorageMultisampleANGLEFn =
- reinterpret_cast<glRenderbufferStorageMultisampleANGLEProc>(
- GetGLProcAddress("glRenderbufferStorageMultisample"));
- DCHECK(fn.glRenderbufferStorageMultisampleANGLEFn);
- } else if (ext.b_GL_ANGLE_framebuffer_multisample) {
+ if (ext.b_GL_ANGLE_framebuffer_multisample) {
fn.glRenderbufferStorageMultisampleANGLEFn =
reinterpret_cast<glRenderbufferStorageMultisampleANGLEProc>(
GetGLProcAddress("glRenderbufferStorageMultisampleANGLE"));
@@ -1705,13 +1700,8 @@
}
debug_fn.glRenderbufferStorageMultisampleEXTFn = 0;
- if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 0u)) {
- fn.glRenderbufferStorageMultisampleEXTFn =
- reinterpret_cast<glRenderbufferStorageMultisampleEXTProc>(
- GetGLProcAddress("glRenderbufferStorageMultisample"));
- DCHECK(fn.glRenderbufferStorageMultisampleEXTFn);
- } else if (ext.b_GL_EXT_multisampled_render_to_texture ||
- ext.b_GL_EXT_framebuffer_multisample) {
+ if (ext.b_GL_EXT_multisampled_render_to_texture ||
+ ext.b_GL_EXT_framebuffer_multisample) {
fn.glRenderbufferStorageMultisampleEXTFn =
reinterpret_cast<glRenderbufferStorageMultisampleEXTProc>(
GetGLProcAddress("glRenderbufferStorageMultisampleEXT"));
diff --git a/ui/gl/gl_bindings_autogen_mock.cc b/ui/gl/gl_bindings_autogen_mock.cc
index 185d809..8e84aa3 100644
--- a/ui/gl/gl_bindings_autogen_mock.cc
+++ b/ui/gl/gl_bindings_autogen_mock.cc
@@ -1829,8 +1829,8 @@
GLsizei width,
GLsizei height) {
MakeFunctionUnique("glRenderbufferStorageMultisample");
- interface_->RenderbufferStorageMultisampleEXT(target, samples, internalformat,
- width, height);
+ interface_->RenderbufferStorageMultisample(target, samples, internalformat,
+ width, height);
}
void GL_BINDING_CALL
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index 4cfcf73..f89f1d2 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -38,20 +38,6 @@
canceled_ = true;
}
-GLContext::FlushEvent::FlushEvent() {
-}
-
-GLContext::FlushEvent::~FlushEvent() {
-}
-
-void GLContext::FlushEvent::Signal() {
- flag_.Set();
-}
-
-bool GLContext::FlushEvent::IsSignaled() {
- return flag_.IsSet();
-}
-
GLContext::GLContext(GLShareGroup* share_group) :
share_group_(share_group),
swap_interval_(1),
@@ -69,13 +55,6 @@
}
}
-scoped_refptr<GLContext::FlushEvent> GLContext::SignalFlush() {
- DCHECK(IsCurrent(NULL));
- scoped_refptr<FlushEvent> flush_event = new FlushEvent();
- flush_events_.push_back(flush_event);
- return flush_event;
-}
-
bool GLContext::GetTotalGpuMemory(size_t* bytes) {
DCHECK(bytes);
*bytes = 0;
@@ -230,12 +209,6 @@
SetGLToRealGLApi();
}
-void GLContext::OnFlush() {
- for (size_t n = 0; n < flush_events_.size(); n++)
- flush_events_[n]->Signal();
- flush_events_.clear();
-}
-
GLContextReal::GLContextReal(GLShareGroup* share_group)
: GLContext(share_group) {}
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h
index 62cabcd..5eac838 100644
--- a/ui/gl/gl_context.h
+++ b/ui/gl/gl_context.h
@@ -34,25 +34,6 @@
virtual bool Initialize(
GLSurface* compatible_surface, GpuPreference gpu_preference) = 0;
- class FlushEvent : public base::RefCountedThreadSafe<FlushEvent> {
- public:
- bool IsSignaled();
-
- private:
- friend class base::RefCountedThreadSafe<FlushEvent>;
- friend class GLContext;
- FlushEvent();
- virtual ~FlushEvent();
- void Signal();
-
- base::CancellationFlag flag_;
- };
-
- // Needs to be called with this context current. It will return a FlushEvent
- // that is initially unsignaled, but will transition to signaled after the
- // next glFlush() or glFinish() occurs in this context.
- scoped_refptr<FlushEvent> SignalFlush();
-
// Destroys the GL context.
virtual void Destroy() = 0;
@@ -143,9 +124,6 @@
// Returns the GL renderer string. The context must be current.
virtual std::string GetGLRenderer();
- // Called when glFlush()/glFinish() is called with this context current.
- void OnFlush();
-
protected:
virtual ~GLContext();
@@ -186,8 +164,6 @@
scoped_ptr<GLStateRestorer> state_restorer_;
scoped_ptr<GLVersionInfo> version_info_;
- std::vector<scoped_refptr<FlushEvent> > flush_events_;
-
int swap_interval_;
bool force_swap_interval_zero_;
diff --git a/ui/gl/gl_context_android.cc b/ui/gl/gl_context_android.cc
index 76b9238..9d3c86c 100644
--- a/ui/gl/gl_context_android.cc
+++ b/ui/gl/gl_context_android.cc
@@ -26,18 +26,18 @@
GLNonOwnedContext(GLShareGroup* share_group);
// Implement GLContext.
- virtual bool Initialize(GLSurface* compatible_surface,
- GpuPreference gpu_preference) override;
- virtual void Destroy() override {}
- virtual bool MakeCurrent(GLSurface* surface) override;
- virtual void ReleaseCurrent(GLSurface* surface) override {}
- virtual bool IsCurrent(GLSurface* surface) override { return true; }
- virtual void* GetHandle() override { return NULL; }
- virtual void OnSetSwapInterval(int interval) override {}
- virtual std::string GetExtensions() override;
+ bool Initialize(GLSurface* compatible_surface,
+ GpuPreference gpu_preference) override;
+ void Destroy() override {}
+ bool MakeCurrent(GLSurface* surface) override;
+ void ReleaseCurrent(GLSurface* surface) override {}
+ bool IsCurrent(GLSurface* surface) override { return true; }
+ void* GetHandle() override { return NULL; }
+ void OnSetSwapInterval(int interval) override {}
+ std::string GetExtensions() override;
protected:
- virtual ~GLNonOwnedContext() {}
+ ~GLNonOwnedContext() override {}
private:
DISALLOW_COPY_AND_ASSIGN(GLNonOwnedContext);
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index c254411..0fb3a74 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -19,35 +19,6 @@
namespace gfx {
-namespace {
-
-// static
-GLFence* CreateFence(bool flush) {
- DCHECK(GLContext::GetCurrent())
- << "Trying to create fence with no context";
-
- scoped_ptr<GLFence> fence;
- // Prefer ARB_sync which supports server-side wait.
- if (g_driver_gl.ext.b_GL_ARB_sync ||
- GetGLVersionInfo()->is_es3) {
- fence.reset(new GLFenceARB(flush));
-#if defined(OS_MACOSX)
- } else if (g_driver_gl.ext.b_GL_APPLE_fence) {
- fence.reset(new GLFenceAPPLE(flush));
-#else
- } else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) {
- fence.reset(new GLFenceEGL(flush));
-#endif
- } else if (g_driver_gl.ext.b_GL_NV_fence) {
- fence.reset(new GLFenceNV(flush));
- }
-
- DCHECK_EQ(!!fence.get(), GLFence::IsSupported());
- return fence.release();
-}
-
-} // namespace
-
GLFence::GLFence() {
}
@@ -66,11 +37,27 @@
}
GLFence* GLFence::Create() {
- return CreateFence(true);
-}
+ DCHECK(GLContext::GetCurrent())
+ << "Trying to create fence with no context";
-GLFence* GLFence::CreateWithoutFlush() {
- return CreateFence(false);
+ scoped_ptr<GLFence> fence;
+ // Prefer ARB_sync which supports server-side wait.
+ if (g_driver_gl.ext.b_GL_ARB_sync ||
+ GetGLVersionInfo()->is_es3) {
+ fence.reset(new GLFenceARB);
+#if defined(OS_MACOSX)
+ } else if (g_driver_gl.ext.b_GL_APPLE_fence) {
+ fence.reset(new GLFenceAPPLE);
+#else
+ } else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) {
+ fence.reset(new GLFenceEGL);
+#endif
+ } else if (g_driver_gl.ext.b_GL_NV_fence) {
+ fence.reset(new GLFenceNV);
+ }
+
+ DCHECK_EQ(!!fence.get(), GLFence::IsSupported());
+ return fence.release();
}
} // namespace gfx
diff --git a/ui/gl/gl_fence.h b/ui/gl/gl_fence.h
index 5af253d..76511f4 100644
--- a/ui/gl/gl_fence.h
+++ b/ui/gl/gl_fence.h
@@ -18,12 +18,6 @@
static bool IsSupported();
static GLFence* Create();
- // Creates a fence that is not guaranteed to signal until the current context
- // is flushed. It is illegal to call Client/ServerWait() on a fence without
- // having explicitly called glFlush() or glFinish() in the originating
- // context.
- static GLFence* CreateWithoutFlush();
-
virtual bool HasCompleted() = 0;
virtual void ClientWait() = 0;
diff --git a/ui/gl/gl_fence_apple.cc b/ui/gl/gl_fence_apple.cc
index 9df0cad..3b5f697 100644
--- a/ui/gl/gl_fence_apple.cc
+++ b/ui/gl/gl_fence_apple.cc
@@ -5,19 +5,14 @@
#include "ui/gl/gl_fence_apple.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
namespace gfx {
-GLFenceAPPLE::GLFenceAPPLE(bool flush) {
+GLFenceAPPLE::GLFenceAPPLE() {
glGenFencesAPPLE(1, &fence_);
glSetFenceAPPLE(fence_);
DCHECK(glIsFenceAPPLE(fence_));
- if (flush) {
- glFlush();
- } else {
- flush_event_ = GLContext::GetCurrent()->SignalFlush();
- }
+ glFlush();
}
bool GLFenceAPPLE::HasCompleted() {
@@ -27,11 +22,7 @@
void GLFenceAPPLE::ClientWait() {
DCHECK(glIsFenceAPPLE(fence_));
- if (!flush_event_.get() || flush_event_->IsSignaled()) {
- glFinishFenceAPPLE(fence_);
- } else {
- LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
- }
+ glFinishFenceAPPLE(fence_);
}
void GLFenceAPPLE::ServerWait() {
diff --git a/ui/gl/gl_fence_apple.h b/ui/gl/gl_fence_apple.h
index 6c8633d..5458e0d 100644
--- a/ui/gl/gl_fence_apple.h
+++ b/ui/gl/gl_fence_apple.h
@@ -7,14 +7,13 @@
#include "base/macros.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
namespace gfx {
class GL_EXPORT GLFenceAPPLE : public GLFence {
public:
- GLFenceAPPLE(bool flush);
+ GLFenceAPPLE();
~GLFenceAPPLE() override;
// GLFence implementation:
@@ -24,7 +23,6 @@
private:
GLuint fence_;
- scoped_refptr<GLContext::FlushEvent> flush_event_;
DISALLOW_COPY_AND_ASSIGN(GLFenceAPPLE);
};
diff --git a/ui/gl/gl_fence_arb.cc b/ui/gl/gl_fence_arb.cc
index 05bda6b..5c6b337 100644
--- a/ui/gl/gl_fence_arb.cc
+++ b/ui/gl/gl_fence_arb.cc
@@ -6,7 +6,6 @@
#include "base/strings/stringprintf.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
namespace gfx {
@@ -24,14 +23,10 @@
} // namespace
-GLFenceARB::GLFenceARB(bool flush) {
+GLFenceARB::GLFenceARB() {
sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
DCHECK_EQ(GL_TRUE, glIsSync(sync_));
- if (flush) {
- glFlush();
- } else {
- flush_event_ = GLContext::GetCurrent()->SignalFlush();
- }
+ glFlush();
}
bool GLFenceARB::HasCompleted() {
@@ -52,25 +47,17 @@
void GLFenceARB::ClientWait() {
DCHECK_EQ(GL_TRUE, glIsSync(sync_));
- if (!flush_event_.get() || flush_event_->IsSignaled()) {
- GLenum result =
- glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
- DCHECK_NE(static_cast<GLenum>(GL_TIMEOUT_EXPIRED), result);
- if (result == GL_WAIT_FAILED) {
- LOG(FATAL) << "Failed to wait for GLFence. error code:" << GetGLErrors();
- }
- } else {
- LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ GLenum result =
+ glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+ DCHECK_NE(static_cast<GLenum>(GL_TIMEOUT_EXPIRED), result);
+ if (result == GL_WAIT_FAILED) {
+ LOG(FATAL) << "Failed to wait for GLFence. error code:" << GetGLErrors();
}
}
void GLFenceARB::ServerWait() {
DCHECK_EQ(GL_TRUE, glIsSync(sync_));
- if (!flush_event_.get() || flush_event_->IsSignaled()) {
- glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
- } else {
- LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
- }
+ glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
}
GLFenceARB::~GLFenceARB() {
diff --git a/ui/gl/gl_fence_arb.h b/ui/gl/gl_fence_arb.h
index ef43948..3975efe 100644
--- a/ui/gl/gl_fence_arb.h
+++ b/ui/gl/gl_fence_arb.h
@@ -7,14 +7,13 @@
#include "base/macros.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
namespace gfx {
class GL_EXPORT GLFenceARB : public GLFence {
public:
- GLFenceARB(bool flush);
+ GLFenceARB();
~GLFenceARB() override;
// GLFence implementation:
@@ -24,7 +23,6 @@
private:
GLsync sync_;
- scoped_refptr<GLContext::FlushEvent> flush_event_;
DISALLOW_COPY_AND_ASSIGN(GLFenceARB);
};
diff --git a/ui/gl/gl_fence_egl.cc b/ui/gl/gl_fence_egl.cc
index c96d6d8..74f0a01 100644
--- a/ui/gl/gl_fence_egl.cc
+++ b/ui/gl/gl_fence_egl.cc
@@ -6,19 +6,25 @@
#include "ui/gl/egl_util.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
namespace gfx {
-GLFenceEGL::GLFenceEGL(bool flush) {
+namespace {
+
+bool g_ignore_egl_sync_failures = false;
+
+} // namespace
+
+// static
+void GLFenceEGL::SetIgnoreFailures() {
+ g_ignore_egl_sync_failures = true;
+}
+
+GLFenceEGL::GLFenceEGL() {
display_ = eglGetCurrentDisplay();
sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
DCHECK(sync_ != EGL_NO_SYNC_KHR);
- if (flush) {
- glFlush();
- } else {
- flush_event_ = GLContext::GetCurrent()->SignalFlush();
- }
+ glFlush();
}
bool GLFenceEGL::HasCompleted() {
@@ -35,17 +41,15 @@
}
void GLFenceEGL::ClientWait() {
- if (!flush_event_.get() || flush_event_->IsSignaled()) {
- EGLint flags = 0;
- EGLTimeKHR time = EGL_FOREVER_KHR;
- EGLint result = eglClientWaitSyncKHR(display_, sync_, flags, time);
- DCHECK_NE(EGL_TIMEOUT_EXPIRED_KHR, result);
- if (result == EGL_FALSE) {
- LOG(FATAL) << "Failed to wait for EGLSync. error:"
- << ui::GetLastEGLErrorString();
- }
- } else {
- LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ EGLint flags = 0;
+ EGLTimeKHR time = EGL_FOREVER_KHR;
+ EGLint result = eglClientWaitSyncKHR(display_, sync_, flags, time);
+ DCHECK_IMPLIES(!g_ignore_egl_sync_failures,
+ EGL_TIMEOUT_EXPIRED_KHR == result);
+ if (result == EGL_FALSE) {
+ LOG(ERROR) << "Failed to wait for EGLSync. error:"
+ << ui::GetLastEGLErrorString();
+ CHECK(g_ignore_egl_sync_failures);
}
}
@@ -54,14 +58,11 @@
ClientWait();
return;
}
- if (!flush_event_.get() || flush_event_->IsSignaled()) {
- EGLint flags = 0;
- if (eglWaitSyncKHR(display_, sync_, flags) == EGL_FALSE) {
- LOG(FATAL) << "Failed to wait for EGLSync. error:"
- << ui::GetLastEGLErrorString();
- }
- } else {
- LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ EGLint flags = 0;
+ if (eglWaitSyncKHR(display_, sync_, flags) == EGL_FALSE) {
+ LOG(ERROR) << "Failed to wait for EGLSync. error:"
+ << ui::GetLastEGLErrorString();
+ CHECK(g_ignore_egl_sync_failures);
}
}
diff --git a/ui/gl/gl_fence_egl.h b/ui/gl/gl_fence_egl.h
index 75a0444..5b6006c 100644
--- a/ui/gl/gl_fence_egl.h
+++ b/ui/gl/gl_fence_egl.h
@@ -7,14 +7,15 @@
#include "base/macros.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
namespace gfx {
class GL_EXPORT GLFenceEGL : public GLFence {
public:
- GLFenceEGL(bool flush);
+ static void SetIgnoreFailures();
+
+ GLFenceEGL();
~GLFenceEGL() override;
// GLFence implementation:
@@ -25,7 +26,6 @@
private:
EGLSyncKHR sync_;
EGLDisplay display_;
- scoped_refptr<GLContext::FlushEvent> flush_event_;
DISALLOW_COPY_AND_ASSIGN(GLFenceEGL);
};
diff --git a/ui/gl/gl_fence_nv.cc b/ui/gl/gl_fence_nv.cc
index 46dadd5..0e23b28 100644
--- a/ui/gl/gl_fence_nv.cc
+++ b/ui/gl/gl_fence_nv.cc
@@ -5,11 +5,10 @@
#include "ui/gl/gl_fence_nv.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
namespace gfx {
-GLFenceNV::GLFenceNV(bool flush) {
+GLFenceNV::GLFenceNV() {
// What if either of these GL calls fails? TestFenceNV will return true.
// See spec:
// http://www.opengl.org/registry/specs/NV/fence.txt
@@ -23,11 +22,7 @@
glGenFencesNV(1, &fence_);
glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
DCHECK(glIsFenceNV(fence_));
- if (flush) {
- glFlush();
- } else {
- flush_event_ = GLContext::GetCurrent()->SignalFlush();
- }
+ glFlush();
}
bool GLFenceNV::HasCompleted() {
@@ -37,11 +32,7 @@
void GLFenceNV::ClientWait() {
DCHECK(glIsFenceNV(fence_));
- if (!flush_event_.get() || flush_event_->IsSignaled()) {
- glFinishFenceNV(fence_);
- } else {
- LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
- }
+ glFinishFenceNV(fence_);
}
void GLFenceNV::ServerWait() {
diff --git a/ui/gl/gl_fence_nv.h b/ui/gl/gl_fence_nv.h
index 0bac11c..b1dc88f 100644
--- a/ui/gl/gl_fence_nv.h
+++ b/ui/gl/gl_fence_nv.h
@@ -7,14 +7,13 @@
#include "base/macros.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
namespace gfx {
class GL_EXPORT GLFenceNV : public GLFence {
public:
- GLFenceNV(bool flush);
+ GLFenceNV();
~GLFenceNV() override;
// GLFence implementation:
@@ -24,7 +23,6 @@
private:
GLuint fence_;
- scoped_refptr<GLContext::FlushEvent> flush_event_;
DISALLOW_COPY_AND_ASSIGN(GLFenceNV);
};
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index fada5e3..81a1b72 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -395,11 +395,6 @@
driver_ = driver;
}
-void GLApiBase::SignalFlush() {
- DCHECK(GLContext::GetCurrent());
- GLContext::GetCurrent()->OnFlush();
-}
-
RealGLApi::RealGLApi() {
}
@@ -412,12 +407,10 @@
void RealGLApi::glFlushFn() {
GLApiBase::glFlushFn();
- GLApiBase::SignalFlush();
}
void RealGLApi::glFinishFn() {
GLApiBase::glFinishFn();
- GLApiBase::SignalFlush();
}
TraceGLApi::~TraceGLApi() {
@@ -525,12 +518,10 @@
void VirtualGLApi::glFlushFn() {
GLApiBase::glFlushFn();
- GLApiBase::SignalFlush();
}
void VirtualGLApi::glFinishFn() {
GLApiBase::glFinishFn();
- GLApiBase::SignalFlush();
}
ScopedSetGLToRealGLApi::ScopedSetGLToRealGLApi()
diff --git a/ui/gl/gl_gl_api_implementation.h b/ui/gl/gl_gl_api_implementation.h
index 1b23097..d408600 100644
--- a/ui/gl/gl_gl_api_implementation.h
+++ b/ui/gl/gl_gl_api_implementation.h
@@ -44,7 +44,6 @@
GLApiBase();
~GLApiBase() override;
void InitializeBase(DriverGL* driver);
- void SignalFlush();
DriverGL* driver_;
};
diff --git a/ui/gl/gl_image_surface_texture.h b/ui/gl/gl_image_surface_texture.h
index eaf4363..d2ff5b7 100644
--- a/ui/gl/gl_image_surface_texture.h
+++ b/ui/gl/gl_image_surface_texture.h
@@ -19,23 +19,23 @@
bool Initialize(SurfaceTexture* surface_texture);
// Overridden from GLImage:
- virtual void Destroy(bool have_context) override;
- virtual gfx::Size GetSize() override;
- virtual bool BindTexImage(unsigned target) override;
- virtual void ReleaseTexImage(unsigned target) override {}
- virtual bool CopyTexImage(unsigned target) override;
- virtual void WillUseTexImage() override {}
- virtual void DidUseTexImage() override {}
- virtual void WillModifyTexImage() override {}
- virtual void DidModifyTexImage() override {}
- virtual bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
- int z_order,
- OverlayTransform transform,
- const Rect& bounds_rect,
- const RectF& crop_rect) override;
+ void Destroy(bool have_context) override;
+ gfx::Size GetSize() override;
+ bool BindTexImage(unsigned target) override;
+ void ReleaseTexImage(unsigned target) override {}
+ bool CopyTexImage(unsigned target) override;
+ void WillUseTexImage() override {}
+ void DidUseTexImage() override {}
+ void WillModifyTexImage() override {}
+ void DidModifyTexImage() override {}
+ bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+ int z_order,
+ OverlayTransform transform,
+ const Rect& bounds_rect,
+ const RectF& crop_rect) override;
protected:
- virtual ~GLImageSurfaceTexture();
+ ~GLImageSurfaceTexture() override;
private:
scoped_refptr<SurfaceTexture> surface_texture_;
diff --git a/url/gurl.h b/url/gurl.h
index ef1e529..566fc5e 100644
--- a/url/gurl.h
+++ b/url/gurl.h
@@ -18,8 +18,8 @@
class URL_EXPORT GURL {
public:
- typedef url::StdStringReplacements<std::string> Replacements;
- typedef url::StdStringReplacements<base::string16> ReplacementsW;
+ typedef url::StringPieceReplacements<std::string> Replacements;
+ typedef url::StringPieceReplacements<base::string16> ReplacementsW;
// Creates an empty, invalid URL.
GURL();
diff --git a/url/url_canon_stdstring.h b/url/url_canon_stdstring.h
index c3d8ba1..662cac7 100644
--- a/url/url_canon_stdstring.h
+++ b/url/url_canon_stdstring.h
@@ -12,6 +12,7 @@
#include <string>
#include "base/compiler_specific.h"
+#include "base/strings/string_piece.h"
#include "url/url_canon.h"
#include "url/url_export.h"
@@ -48,35 +49,35 @@
};
// An extension of the Replacements class that allows the setters to use
-// standard strings.
+// StringPieces (implicitly allowing strings or char*s).
//
-// The strings passed as arguments are not copied and must remain valid until
-// this class goes out of scope.
+// The contents of the StringPieces are not copied and must remain valid until
+// the StringPieceReplacements object goes out of scope.
template<typename STR>
-class StdStringReplacements : public Replacements<typename STR::value_type> {
+class StringPieceReplacements : public Replacements<typename STR::value_type> {
public:
- void SetSchemeStr(const STR& s) {
+ void SetSchemeStr(const base::BasicStringPiece<STR>& s) {
this->SetScheme(s.data(), Component(0, static_cast<int>(s.length())));
}
- void SetUsernameStr(const STR& s) {
+ void SetUsernameStr(const base::BasicStringPiece<STR>& s) {
this->SetUsername(s.data(), Component(0, static_cast<int>(s.length())));
}
- void SetPasswordStr(const STR& s) {
+ void SetPasswordStr(const base::BasicStringPiece<STR>& s) {
this->SetPassword(s.data(), Component(0, static_cast<int>(s.length())));
}
- void SetHostStr(const STR& s) {
+ void SetHostStr(const base::BasicStringPiece<STR>& s) {
this->SetHost(s.data(), Component(0, static_cast<int>(s.length())));
}
- void SetPortStr(const STR& s) {
+ void SetPortStr(const base::BasicStringPiece<STR>& s) {
this->SetPort(s.data(), Component(0, static_cast<int>(s.length())));
}
- void SetPathStr(const STR& s) {
+ void SetPathStr(const base::BasicStringPiece<STR>& s) {
this->SetPath(s.data(), Component(0, static_cast<int>(s.length())));
}
- void SetQueryStr(const STR& s) {
+ void SetQueryStr(const base::BasicStringPiece<STR>& s) {
this->SetQuery(s.data(), Component(0, static_cast<int>(s.length())));
}
- void SetRefStr(const STR& s) {
+ void SetRefStr(const base::BasicStringPiece<STR>& s) {
this->SetRef(s.data(), Component(0, static_cast<int>(s.length())));
}
};